diff --git a/administrator/components/com_media/controllers/file.json.php b/administrator/components/com_media/controllers/file.json.php
index 9a5bb546942b3..4ee056f13f180 100644
--- a/administrator/components/com_media/controllers/file.json.php
+++ b/administrator/components/com_media/controllers/file.json.php
@@ -34,8 +34,9 @@ public function upload()
if (!JSession::checkToken('request'))
{
$response = array(
- 'status' => '0',
- 'error' => JText::_('JINVALID_TOKEN')
+ 'status' => '0',
+ 'message' => JText::_('JINVALID_TOKEN'),
+ 'error' => JText::_('JINVALID_TOKEN')
);
echo json_encode($response);
@@ -59,8 +60,9 @@ public function upload()
|| $_SERVER['CONTENT_LENGTH'] > $mediaHelper->toBytes(ini_get('memory_limit')))
{
$response = array(
- 'status' => '0',
- 'error' => JText::_('COM_MEDIA_ERROR_WARNFILETOOLARGE')
+ 'status' => '0',
+ 'message' => JText::_('COM_MEDIA_ERROR_WARNFILETOOLARGE'),
+ 'error' => JText::_('COM_MEDIA_ERROR_WARNFILETOOLARGE')
);
echo json_encode($response);
@@ -70,39 +72,41 @@ public function upload()
// Set FTP credentials, if given
JClientHelper::setCredentialsFromRequest('ftp');
- // Make the filename safe
- $file['name'] = JFile::makeSafe($file['name']);
-
- if (!isset($file['name']))
+ if (isset($file['name']))
{
- $response = array(
- 'status' => '0',
- 'error' => JText::_('COM_MEDIA_ERROR_BAD_REQUEST')
- );
+ // Make the filename safe
+ $file['name'] = JFile::makeSafe($file['name']);
- echo json_encode($response);
+ // We need a URL safe name
+ $fileparts = pathinfo(COM_MEDIA_BASE . '/' . $folder . '/' . $file['name']);
- return;
- }
+ // Transform filename to punycode
+ $fileparts['filename'] = JStringPunycode::toPunycode($fileparts['filename']);
+ $tempExt = (!empty($fileparts['extension'])) ? strtolower($fileparts['extension']) : '';
- // The request is valid
- $err = null;
+ // Transform filename to punycode, then neglect otherthan non-alphanumeric characters & underscores. Also transform extension to lowercase
+ $safeFileName = preg_replace(array("/[\\s]/", "/[^a-zA-Z0-9_]/"), array("_", ""), $fileparts['filename']) . '.' . $tempExt;
- $filepath = JPath::clean(COM_MEDIA_BASE . '/' . $folder . '/' . strtolower($file['name']));
+ // Create filepath with safe-filename
+ $files['final'] = $fileparts['dirname'] . DIRECTORY_SEPARATOR . $safeFileName;
+ $file['name'] = $safeFileName;
- if (!MediaHelper::canUpload($file, $err))
- {
- JLog::add('Invalid: ' . $filepath . ': ' . $err, JLog::INFO, 'upload');
+ $filepath = JPath::clean($files['final']);
- $response = array(
- 'status' => '0',
- 'error' => JText::_($err)
- );
+ if (!$mediaHelper->canUpload($file, 'com_media'))
+ {
+ JLog::add('Invalid: ' . $filepath, JLog::INFO, 'upload');
- echo json_encode($response);
+ $response = array(
+ 'status' => '0',
+ 'message' => JText::_('COM_MEDIA_ERROR_UNABLE_TO_UPLOAD_FILE'),
+ 'error' => JText::_('COM_MEDIA_ERROR_UNABLE_TO_UPLOAD_FILE')
+ );
- return;
- }
+ echo json_encode($response);
+
+ return;
+ }
// Trigger the onContentBeforeSave event.
JPluginHelper::importPlugin('content');
@@ -111,77 +115,100 @@ public function upload()
$object_file->filepath = $filepath;
$result = $dispatcher->trigger('onContentBeforeSave', array('com_media.file', &$object_file, true));
- if (in_array(false, $result, true))
- {
- // There are some errors in the plugins
- JLog::add('Errors before save: ' . $object_file->filepath . ' : ' . implode(', ', $object_file->getErrors()), JLog::INFO, 'upload');
-
- $response = array(
- 'status' => '0',
- 'error' => JText::plural('COM_MEDIA_ERROR_BEFORE_SAVE', count($errors = $object_file->getErrors()), implode('
', $errors))
- );
-
- echo json_encode($response);
-
- return;
+ if (in_array(false, $result, true))
+ {
+ // There are some errors in the plugins
+ JLog::add('Errors before save: ' . $object_file->filepath . ' : ' . implode(', ', $object_file->getErrors()), JLog::INFO, 'upload');
+
+ $response = array(
+ 'status' => '0',
+ 'message' => JText::plural('COM_MEDIA_ERROR_BEFORE_SAVE', count($errors = $object_file->getErrors()), implode('
', $errors)),
+ 'error' => JText::plural('COM_MEDIA_ERROR_BEFORE_SAVE', count($errors = $object_file->getErrors()), implode('
', $errors))
+ );
+
+ echo json_encode($response);
+
+ return;
+ }
+
+ if (JFile::exists($object_file->filepath))
+ {
+ // File exists
+ JLog::add('File exists: ' . $object_file->filepath . ' by user_id ' . $user->id, JLog::INFO, 'upload');
+
+ $response = array(
+ 'status' => '0',
+ 'message' => JText::_('COM_MEDIA_ERROR_FILE_EXISTS'),
+ 'error' => JText::_('COM_MEDIA_ERROR_FILE_EXISTS'),
+ 'location' => str_replace(JPATH_ROOT, '', $filepath)
+ );
+
+ echo json_encode($response);
+
+ return;
+ }
+ elseif (!$user->authorise('core.create', 'com_media'))
+ {
+ // File does not exist and user is not authorised to create
+ JLog::add('Create not permitted: ' . $object_file->filepath . ' by user_id ' . $user->id, JLog::INFO, 'upload');
+
+ $response = array(
+ 'status' => '0',
+ 'error' => JText::_('COM_MEDIA_ERROR_CREATE_NOT_PERMITTED'),
+ 'message' => JText::_('COM_MEDIA_ERROR_CREATE_NOT_PERMITTED')
+ );
+
+ echo json_encode($response);
+
+ return;
+ }
+
+ if (!JFile::upload($object_file->tmp_name, $object_file->filepath))
+ {
+ // Error in upload
+ JLog::add('Error on upload: ' . $object_file->filepath, JLog::INFO, 'upload');
+
+ $response = array(
+ 'status' => '0',
+ 'message' => JText::_('COM_MEDIA_ERROR_UNABLE_TO_UPLOAD_FILE'),
+ 'error' => JText::_('COM_MEDIA_ERROR_UNABLE_TO_UPLOAD_FILE')
+ );
+
+ echo json_encode($response);
+
+ return;
+ }
+ else
+ {
+ // Trigger the onContentAfterSave event.
+ $dispatcher->trigger('onContentAfterSave', array('com_media.file', &$object_file, true));
+ JLog::add($folder, JLog::INFO, 'upload');
+
+ $returnUrl = str_replace(JPATH_ROOT, '', $object_file->filepath);
+
+ $response = array(
+ 'status' => '1',
+ 'message' => JText::sprintf('COM_MEDIA_UPLOAD_COMPLETE', $returnUrl),
+ 'error' => JText::sprintf('COM_MEDIA_UPLOAD_COMPLETE', $returnUrl),
+ 'location' => str_replace('\\', '/', $returnUrl)
+ );
+
+ echo json_encode($response);
+
+ return;
+ }
}
-
- if (JFile::exists($object_file->filepath))
+ else
{
- // File exists
- JLog::add('File exists: ' . $object_file->filepath . ' by user_id ' . $user->id, JLog::INFO, 'upload');
-
$response = array(
- 'status' => '0',
- 'error' => JText::_('COM_MEDIA_ERROR_FILE_EXISTS')
+ 'status' => '0',
+ 'error' => JText::_('COM_MEDIA_ERROR_BAD_REQUEST'),
+ 'message' => JText::_('COM_MEDIA_ERROR_BAD_REQUEST')
);
echo json_encode($response);
return;
}
-
- if (!$user->authorise('core.create', 'com_media'))
- {
- // File does not exist and user is not authorised to create
- JLog::add('Create not permitted: ' . $object_file->filepath . ' by user_id ' . $user->id, JLog::INFO, 'upload');
-
- $response = array(
- 'status' => '0',
- 'error' => JText::_('COM_MEDIA_ERROR_CREATE_NOT_PERMITTED')
- );
-
- echo json_encode($response);
-
- return;
- }
-
- if (!JFile::upload($object_file->tmp_name, $object_file->filepath))
- {
- // Error in upload
- JLog::add('Error on upload: ' . $object_file->filepath, JLog::INFO, 'upload');
-
- $response = array(
- 'status' => '0',
- 'error' => JText::_('COM_MEDIA_ERROR_UNABLE_TO_UPLOAD_FILE')
- );
-
- echo json_encode($response);
-
- return;
- }
-
- // Trigger the onContentAfterSave event.
- $dispatcher->trigger('onContentAfterSave', array('com_media.file', &$object_file, true));
- JLog::add($folder, JLog::INFO, 'upload');
-
- $response = array(
- 'status' => '1',
- 'error' => JText::sprintf('COM_MEDIA_UPLOAD_COMPLETE', substr($object_file->filepath, strlen(COM_MEDIA_BASE)))
- );
-
- echo json_encode($response);
-
- return;
}
}
diff --git a/administrator/language/en-GB/en-GB.plg_editors_tinymce.ini b/administrator/language/en-GB/en-GB.plg_editors_tinymce.ini
index c1361ace6bf41..33a967877ecc9 100644
--- a/administrator/language/en-GB/en-GB.plg_editors_tinymce.ini
+++ b/administrator/language/en-GB/en-GB.plg_editors_tinymce.ini
@@ -7,6 +7,7 @@ PLG_EDITORS_TINYMCE="Editor - TinyMCE"
PLG_TINY_BUTTON_TOGGLE_EDITOR="Toggle editor"
PLG_TINY_ERR_CUSTOMCSSFILENOTPRESENT="The file name %s was entered in the TinyMCE Custom CSS field. This file could not be found in the default template folder. No styles are available."
PLG_TINY_ERR_EDITORCSSFILENOTPRESENT="Could not find the file 'editor.css' in the template or templates/system folder. No styles are available."
+PLG_TINY_ERR_UNSUPPORTEDBROWSER="Drag and drop image upload is not available for your your browser. Please consider using a fully HTML5 compatible browser"
PLG_TINY_FIELD_ADVIMAGE_DESC="Turn on/off a more advanced image dialog."
PLG_TINY_FIELD_ADVIMAGE_LABEL="Advanced Image"
PLG_TINY_FIELD_ADVLIST_DESC="Turn on/off to enable to set number formats and bullet types in ordered and unordered lists."
@@ -27,10 +28,14 @@ PLG_TINY_FIELD_CUSTOMBUTTON_DESC="Add custom button(s)."
PLG_TINY_FIELD_CUSTOMBUTTON_LABEL="Custom Button"
PLG_TINY_FIELD_CUSTOMPLUGIN_DESC="Add custom plugin(s)."
PLG_TINY_FIELD_CUSTOMPLUGIN_LABEL="Custom Plugin"
+PLG_TINY_FIELD_CUSTOM_PATH_DESC="Provide a directory for the images to be uploaded. If nothing provided images will be uploaded at /images."
+PLG_TINY_FIELD_CUSTOM_PATH_LABEL="Images directory"
PLG_TINY_FIELD_DATE_DESC="Show or hide the Insert Date button. Only works in Extended mode."
PLG_TINY_FIELD_DATE_LABEL="Insert Date"
PLG_TINY_FIELD_DIRECTION_DESC="Choose default text direction."
PLG_TINY_FIELD_DIRECTION_LABEL="Text Direction"
+PLG_TINY_FIELD_DRAG_DROP_DESC="Enable drag and drop for uploading images"
+PLG_TINY_FIELD_DRAG_DROP_LABEL="Images drag&drop"
PLG_TINY_FIELD_ELEMENTS_DESC="Allows the addition of specific valid elements to the existing rule set."
PLG_TINY_FIELD_ELEMENTS_LABEL="Extended Valid Elements"
PLG_TINY_FIELD_ENCODING_DESC="Controls how HTML entities are encoded. Recommended setting is 'raw'. 'named' = used named entity encoding (for example, '<'). 'numeric' = use numeric HTML encoding (for example, '%03c'). raw = Do not encode HTML entities. Note that searching content may not work properly if setting is not 'raw'."
diff --git a/media/editors/tinymce/plugins/jdragdrop/plugin.js b/media/editors/tinymce/plugins/jdragdrop/plugin.js
new file mode 100644
index 0000000000000..1fa68610bf63a
--- /dev/null
+++ b/media/editors/tinymce/plugins/jdragdrop/plugin.js
@@ -0,0 +1,121 @@
+tinymce.PluginManager.add('jdragdrop', function(editor) {
+
+ // Reset the drop area border
+ tinyMCE.DOM.bind(document, 'dragleave', function(e) {
+ e.stopPropagation();
+ e.preventDefault();
+ tinyMCE.activeEditor.contentAreaContainer.style.borderWidth='';
+
+ return false;
+ });
+
+ // The upload logic
+ function UploadFile(file) {
+ var fd = new FormData();
+ fd.append('Filedata', file);
+ fd.append('folder', mediaUploadPath);
+
+ var xhr = new XMLHttpRequest();
+
+ xhr.upload.onprogress = function(e) {
+ var percentComplete = (e.loaded / e.total) * 100;
+ jQuery('.bar').width(percentComplete + '%');
+ };
+
+ removeProgessBar = function(){
+ setTimeout(function(){
+ jQuery('#jloader').remove();
+ editor.contentAreaContainer.style.borderWidth = '';
+ }, 200);
+ };
+
+ xhr.onload = function() {
+ var resp = JSON.parse(xhr.responseText);
+
+ if (xhr.status == 200) {
+ if (resp.status == '0') {
+ removeProgessBar();
+
+ tinyMCE.activeEditor.windowManager.alert(resp.message + ': ' + setCustomDir + resp.location);
+
+ }
+
+ if (resp.status == '1') {
+ removeProgessBar();
+
+ // Create the image tag
+ var newNode = tinyMCE.activeEditor.getDoc().createElement ('img');
+ newNode.src= setCustomDir + resp.location;
+ tinyMCE.activeEditor.execCommand('mceInsertContent', false, newNode.outerHTML);
+ }
+ } else {
+ removeProgessBar();
+ }
+ };
+
+ xhr.onerror = function() {
+ removeProgessBar();
+ };
+
+ xhr.open("POST", uploadUri, true);
+ xhr.send(fd);
+
+ }
+
+ // Listers for drag and drop
+ if (typeof FormData != 'undefined'){
+
+ // Fix for Chrome
+ editor.on('dragenter', function(e) {
+ e.stopPropagation();
+
+ return false;
+ });
+
+
+ // Notify user when file is over the drop area
+ editor.on('dragover', function(e) {
+ e.preventDefault();
+ tinyMCE.activeEditor.contentAreaContainer.style.borderStyle = 'dashed';
+ tinyMCE.activeEditor.contentAreaContainer.style.borderWidth = '5px';
+
+ return false;
+ });
+
+ // Logic for the dropped file
+ editor.on('drop', function(e) {
+
+ // We override only for files
+ if (e.dataTransfer && e.dataTransfer.files && e.dataTransfer.files.length > 0) {
+ for (var i = 0, f; f = e.dataTransfer.files[i]; i++) {
+
+ // Only images allowed
+ if (f.name.toLowerCase().match(/\.(jpg|jpeg|png|gif)$/)) {
+
+ // Display a spining Joomla! logo
+ jQuery('.mce-toolbar-grp').append(
+ '