Index: branches/5.2.x/core/kernel/utility/formatters/upload_formatter.php =================================================================== diff -u -N -r15534 -r15729 --- branches/5.2.x/core/kernel/utility/formatters/upload_formatter.php (.../upload_formatter.php) (revision 15534) +++ branches/5.2.x/core/kernel/utility/formatters/upload_formatter.php (.../upload_formatter.php) (revision 15729) @@ -1,6 +1,6 @@ Application->isAdmin ) { + // this allows to revert htmlspecialchars call for each field submitted on front-end + $value = is_array($value) ? array_map('htmlspecialchars_decode', $value) : htmlspecialchars_decode($value); + } + + $options = $object->GetFieldOptions($field_name); + if ( getArrayValue($options, 'upload_dir') ) { $this->DestinationPath = $options['upload_dir']; $this->FullPath = FULL_PATH . $this->DestinationPath; } + + if ( is_array($value) && isset($value['tmp_ids']) ) { + // SWF Uploader + return $this->_processFlashUploader($value, $field_name, $object); + } + + return $this->_processRegularUploader($value, $field_name, $object); } /** - * Processes file uploads from form + * Handles uploaded files, provided by Flash uploader * - * @param mixed $value + * @param Array|string $value * @param string $field_name * @param kDBItem $object - * @return mixed - * @access public + * @return string + * @access protected */ - public function Parse($value, $field_name, &$object) + protected function _processFlashUploader($value, $field_name, $object) { - if ( !$this->Application->isAdmin ) { - // this allows to revert htmlspecialchars call for each field submitted on front-end - $value = is_array($value) ? array_map('htmlspecialchars_decode', $value) : htmlspecialchars_decode($value); + $options = $object->GetFieldOptions($field_name); + $this->sorting = isset($value['order']) ? explode('|', $value['order']) : Array (); + + if ( $value['tmp_deleted'] ) { + $n_upload = Array (); + $deleted = explode('|', $value['tmp_deleted']); + $upload = explode('|', $value['upload']); + + foreach ($upload as $name) { + if ( in_array($name, $deleted) ) { + continue; + } + + $n_upload[] = $name; + } + + $value['upload'] = implode('|', $n_upload); } - $ret = !is_array($value) ? $value : ''; - $options = $object->GetFieldOptions($field_name); + if ( !$value['tmp_ids'] ) { + // no pending files -> return already uploaded files + return $this->_sortFiles($value['upload']); + } - $this->_initUploadFolder($options); + $swf_uploaded_ids = explode('|', $value['tmp_ids']); + $swf_uploaded_names = explode('|', $value['tmp_names']); + $existing = $value['upload'] ? explode('|', $value['upload']) : Array (); - // SWF Uploader: BEGIN - if ( is_array($value) && isset($value['json']) ) { - $files_info = $this->_decodeJSON($value['json'], $options); - $this->Application->StoreVar($object->getFileInfoVariableName($field_name), serialize($files_info)); + $fret = Array (); + $max_files = $this->_getMaxFiles($options); - return getArrayValue($value, 'upload'); + // don't delete uploaded file, when it's name matches delete file name + $files_to_delete = Array (); + $var_name = $object->getPendingActionVariableName(); + $schedule = $this->Application->RecallVar($var_name); + $schedule = $schedule ? unserialize($schedule) : Array (); + + foreach ($schedule as $data) { + if ( $data['action'] == 'delete' ) { + $files_to_delete[] = $data['file']; + } } - // SWF Uploader: END + for ($i = 0; $i < min($max_files, count($swf_uploaded_ids)); $i++) { + $real_name = $this->_getRealFilename($swf_uploaded_names[$i], $options, $object, $files_to_delete); + $file_name = $this->FullPath . $real_name; + + $tmp_file = WRITEABLE . '/tmp/' . $swf_uploaded_ids[$i] . '_' . $swf_uploaded_names[$i]; + rename($tmp_file, $file_name); + + @chmod($file_name, 0666); + $fret[] = getArrayValue($options, 'upload_dir') ? $real_name : $this->DestinationPath . $real_name; + + $this->_renameFileInSorting($swf_uploaded_names[$i], $real_name); + } + + return $this->_sortFiles(array_merge($existing, $fret)); + } + + /** + * Handles regular file upload + * + * @param string|Array $value + * @param string $field_name + * @param kDBItem $object + * @return string + * @access protected + */ + protected function _processRegularUploader($value, $field_name, $object) + { + $ret = !is_array($value) ? $value : ''; + $options = $object->GetFieldOptions($field_name); + if ( getArrayValue($value, 'upload') && getArrayValue($value, 'error') == UPLOAD_ERR_NO_FILE ) { // file was not uploaded this time, but was uploaded before, then use previously uploaded file (from db) return getArrayValue($value, 'upload'); } if ( is_array($value) && count($value) > 1 && $value['size'] ) { if ( is_array($value) && (int)$value['error'] === UPLOAD_ERR_OK ) { - $max_filesize = isset($options['max_size']) ? $options['max_size'] : MAX_UPLOAD_SIZE; + $max_file_size = isset($options['max_size']) ? $options['max_size'] : MAX_UPLOAD_SIZE; - // we can get mime type based on file content and no use one, provided by the client + // we can get mime type based on file content and don't use one, provided by the client // $value['type'] = kUtil::mimeContentType($value['tmp_name']); if ( getArrayValue($options, 'file_types') && !$this->extensionMatch($value['name'], $options['file_types']) ) { @@ -117,7 +196,7 @@ $object->SetError($field_name, 'bad_file_format', 'la_error_InvalidFileFormat', $error_params); } - elseif ( $value['size'] > $max_filesize ) { + elseif ( $value['size'] > $max_file_size ) { $object->SetError($field_name, 'bad_file_size', 'la_error_FileTooLarge'); } elseif ( !is_writable($this->FullPath) ) { @@ -164,8 +243,8 @@ // delete previous file, when new file is uploaded under same field /*$previous_file = isset($value['upload']) ? $value['upload'] : false; - if ($previous_file && file_exists($this->FullPath.$previous_file)) { - unlink($this->FullPath.$previous_file); + if ( $previous_file && file_exists($this->FullPath . $previous_file) ) { + unlink($this->FullPath . $previous_file); }*/ } } @@ -193,7 +272,7 @@ protected function extensionMatch($filename, $file_types) { if ( preg_match_all('/\*\.(.*?)(;|$)/', $file_types, $regs) ) { - $file_extension = mb_strtolower( pathinfo($filename, PATHINFO_EXTENSION) ); + $file_extension = mb_strtolower(pathinfo($filename, PATHINFO_EXTENSION)); $file_extensions = array_map('mb_strtolower', $regs[1]); return in_array($file_extension, $file_extensions); @@ -203,61 +282,25 @@ } /** - * Decodes JSON information about uploaded files + * Resorts uploaded files according to given file order * - * @param string $json - * @param Array $options - * @return Array + * @param Array|string $files + * @return string * @access protected */ - protected function _decodeJSON($json, $options) + protected function _sortFiles($files) { - if ( !$json ) { - return Array (); + if ( !is_array($files) ) { + $files = explode('|', $files); } - $ret = Array (); - $files_info = explode('|', $json); - $max_files = $this->_getMaxFiles($options); + $sorted_files = array_intersect($this->sorting, $files); // removes deleted files from sorting + $new_files = array_diff($files, $sorted_files); // files, that weren't sorted - add to the end - foreach ($files_info as $file_info) { - $file_info = (array)json_decode($file_info); - - if ( $file_info['deleted'] ) { - $ret[$file_info['name']] = $file_info; - } - elseif ( $max_files ) { - $ret[$file_info['name']] = $file_info; - $max_files--; - } - } - - uasort($ret, Array ($this, '_sortFiles')); - - return $ret; + return implode('|', array_merge($sorted_files, $new_files)); } /** - * Resorts uploaded files according to given file order - * - * @param $file_a - * @param $file_b - * @return int - * @access protected - */ - protected function _sortFiles($file_a, $file_b) - { - $file_a_order = isset($file_a['order']) ? (int)$file_a['order'] : 0; - $file_b_order = isset($file_b['order']) ? (int)$file_b['order'] : 0; - - if ( $file_a_order == $file_b_order ) { - return 0; - } - - return ($file_a_order < $file_b_order) ? -1 : 1; - } - - /** * Returns maximal allowed file count per field * * @param Array $options @@ -274,66 +317,6 @@ } /** - * Processes uploaded files - * - * @param kDBItem $object - * @param string $field_name - * @param int $id - * @return Array - */ - public function processFlashUpload($object, $field_name, $id = null) - { - $value = $object->GetDBField($field_name); - $options = $object->GetFieldOptions($field_name); - - $this->_initUploadFolder($options); - $files_info = $this->Application->RecallVar($object->getFileInfoVariableName($field_name, $id)); - - if ( !$files_info ) { - $this->Application->RemoveVar($object->getFileInfoVariableName($field_name, $id)); - - return Array (); - } - - $files_info = unserialize($files_info); - $live_files = $value ? explode('|', $value) : Array (); - - // don't rename file into file, that will be deleted - $files_to_delete = $this->_getFilesToDelete($object); - - foreach ($files_info as $file_name => $file_info) { - if ( $file_info['deleted'] ) { - // user deleted live file - $live_files = array_diff($live_files, Array ($file_name)); - } - elseif ( $file_info['temp'] == 1 ) { - // user uploaded new file to temp folder - - // 1. get unique filename for live folder - $real_name = $this->_getRealFilename($file_name, $options, $object, $files_to_delete); - $file_name = $this->FullPath . $real_name; - - // 2. move file from temp folder to live folder - $tmp_file = WRITEABLE . '/tmp/' . $file_info['id'] . '_' . $file_info['name']; - rename($tmp_file, $file_name); - - // 3. add to resulting file list - @chmod($file_name, 0666); - $live_files[] = getArrayValue($options, 'upload_dir') ? $real_name : $this->DestinationPath . $real_name; - } - } - - $this->Application->RemoveVar($object->getFileInfoVariableName($field_name, $id)); - $object->SetDBField($field_name, implode('|', $live_files)); - - if ( $object->GetOriginalField($field_name, true) != $object->GetField($field_name) ) { - return Array ($field_name); - } - - return Array (); - } - - /** * Returns final filename after applying storage-engine specific naming * * @param string $file_name @@ -352,48 +335,29 @@ } /** - * Returns list of files, that user marked for deletion + * Renames file in sorting list * - * @param kDBItem $object - * @return Array + * @param string $old_name + * @param string $new_name + * @return void * @access protected */ - protected function _getFilesToDelete($object) + protected function _renameFileInSorting($old_name, $new_name) { - $var_name = $object->getPendingActionVariableName(); - $schedule = $this->Application->RecallVar($var_name); + $index = array_search($old_name, $this->sorting); - if ( !$schedule ) { - return Array (); + if ( $index !== false ) { + $this->sorting[$index] = $new_name; } - - $ret = Array (); - $schedule = unserialize($schedule); - - foreach ($schedule as $data) { - if ( $data['action'] == 'delete' ) { - $ret[] = $data['file']; - } - } - - return $ret; } - /** - * Allows to determine single-file format based on multi-file format - * - * @param string $format - * @return string - * @access protected - */ - protected function getSingleFormat($format) + function getSingleFormat($format) { $single_mapping = Array ( 'file_urls' => 'full_url', 'file_paths' => 'full_path', 'file_sizes' => 'file_size', 'files_resized' => 'resize', - 'files_json' => 'file_json', 'img_sizes' => 'img_size', 'wms' => 'wm', ); @@ -417,15 +381,12 @@ } $options = $object->GetFieldOptions($field_name); + if ( !isset($format) ) { $format = isset($options['format']) ? $options['format'] : false; } - if ( $format && preg_match('/(file_urls|file_paths|file_names|file_sizes|img_sizes|files_resized|files_json|wms)(.*)/', $format, $regs) ) { - if ( $format == 'files_json' ) { - $value = $this->_mergeFilesFromSession($value, $field_name, $object); - } - + if ( $format && preg_match('/(file_urls|file_paths|file_names|file_sizes|img_sizes|files_resized|wms)(.*)/', $format, $regs) ) { if ( !$value || $format == 'file_names' ) { // storage format matches display format OR no value return $value; @@ -443,6 +404,7 @@ } $tc_value = $this->TypeCast($value, $options); + if ( ($tc_value === false) || ($tc_value != $value) ) { // for leaving badly formatted date on the form return $value; @@ -453,28 +415,6 @@ } /** - * Merges filenames from session into database filenames list - * - * @param string $value - * @param string $field_name - * @param kDBItem $object - * @return string - */ - protected function _mergeFilesFromSession($value, $field_name, $object) - { - $files_info = $this->Application->RecallVar($object->getFileInfoVariableName($field_name)); - - if ( $files_info ) { - $temp_files = array_keys(unserialize($files_info)); - $live_files = $value ? explode('|', $value) : Array (); - - $value = implode('|', array_merge($live_files, $temp_files)); - } - - return $value; - } - - /** * Return formatted file url,path or size * * @param string $value @@ -538,27 +478,6 @@ $image_info = $image_helper->getImageInfo(FULL_PATH . str_replace('/', DIRECTORY_SEPARATOR, $upload_dir) . $value); return $image_info ? $image_info[3] : ''; break; - - case 'file_json': - // get info about 1 file as JSON-encoded object - $files_info = $this->Application->RecallVar($object->getFileInfoVariableName($field_name)); - $files_info = $files_info ? unserialize($files_info) : Array (); - - if ( isset($files_info[$value]) ) { - // file that was uploaded, but not saved to database - return json_encode($files_info[$value]); - } - - $file_info = Array ( - 'id' => 'uploaded_' . crc32($value), - 'name' => $value, - 'size' => $this->GetFormatted($value, $field_name, $object, 'file_size'), - 'deleted' => 0, - 'temp' => 0, - ); - - return json_encode($file_info); - break; } return sprintf($format, $value); @@ -571,6 +490,7 @@ * @param array $options * @return string * @access protected + * @throws Exception */ protected function getStorageEngineFolder($file_name, $options) { @@ -645,6 +565,7 @@ } } + class kPictureFormatter extends kUploadFormatter { public function __construct() Index: branches/5.2.x/core/admin_templates/js/uploader/upload_manager.js =================================================================== diff -u -N -r15446 -r15729 --- branches/5.2.x/core/admin_templates/js/uploader/upload_manager.js (.../upload_manager.js) (revision 15446) +++ branches/5.2.x/core/admin_templates/js/uploader/upload_manager.js (.../upload_manager.js) (revision 15729) @@ -111,17 +111,18 @@ delete this._Uploaders[id]; } -UploadsManager.DeleteFile = function(uploader_id, file, confirmed) { - if ( !confirmed && !confirm('Are you sure you want to delete "' + file.name + '" file?') ) { +UploadsManager.DeleteFile = function(uploader_id, fname, confirmed) { + if (!confirmed && !confirm('Are you sure you want to delete "' + fname + '" file?')) { return false; } var $uploader = this._Uploaders[uploader_id]; $.get( - $uploader.getUrl(file, 'deleteURL'), + $uploader.deleteURL.replace('#FILE#', encodeURIComponent(fname)).replace('#FIELD#', $uploader.params.field), function ($data) { - $uploader.removeFile({id: file.name}, true); + $uploader.removeFile({id:fname}); + $uploader.deleted.push(fname); $uploader.updateInfo(undefined, true); } ); @@ -210,7 +211,7 @@ this.files.push(file); if (this.files[0].uploaded) { - UploadsManager.DeleteFile(UploadsManager._getUploader(file).id, this.files[0], true); + UploadsManager.DeleteFile(UploadsManager._getUploader(file).id, this.files[0].name, true); } else { this.callFlash('CancelUpload', [this.files[0].id]); Index: branches/5.2.x/core/kernel/db/dbitem.php =================================================================== diff -u -N -r15541 -r15729 --- branches/5.2.x/core/kernel/db/dbitem.php (.../dbitem.php) (revision 15541) +++ branches/5.2.x/core/kernel/db/dbitem.php (.../dbitem.php) (revision 15729) @@ -1,6 +1,6 @@ getUploaderFields(); - - foreach ($uploader_fields as $field) { - $formatter = $this->Application->recallObject($this->GetFieldOption($field, 'formatter')); - /* @var $formatter kUploadFormatter */ - - $changed_fields = array_merge($changed_fields, $formatter->processFlashUpload($this, $field, $id)); - } - - if ( $changed_fields ) { - $this->Update(null, array_unique($changed_fields)); - } - } - - /** - * Removes any info about queued uploaded files - * - * @param int $id - * @return void - * @access public - */ - public function resetUploads($id = NULL) - { - $uploader_fields = $this->getUploaderFields(); - - foreach ($uploader_fields as $field) { - $this->Application->RemoveVar($this->getFileInfoVariableName($field, $id)); - } - } - - /** - * Returns uploader fields - * - * @return Array - * @access public - */ - public function getUploaderFields() - { - $ret = Array (); - - foreach ($this->Fields as $field => $options) { - if ( !isset($options['formatter']) ) { - continue; - } - - $formatter = $this->Application->recallObject($options['formatter']); - /* @var $formatter kUploadFormatter */ - - if ( $formatter instanceof kUploadFormatter ) { - $ret[] = $field; - } - } - - return $ret; - } - - /** * Returns variable name, used to store pending file actions * * @return string @@ -606,25 +540,6 @@ } /** - * Returns variable name, which stores file information for object/field/window combination - * - * @param string $field_name - * @param int $id - * @return string - * @access public - */ - public function getFileInfoVariableName($field_name, $id = NULL) - { - if ( !isset($id) ) { - $id = $this->GetID(); - } - - $window_id = $this->Application->GetTopmostWid($this->Prefix); - - return $this->Prefix . '[' . $id . '][' . $field_name . ']_file_info' . $window_id; - } - - /** * Allows to skip certain fields from getting into sql queries * * @param string $field_name Index: branches/5.2.x/core/admin_templates/js/uploader/uploader.js =================================================================== diff -u -N -r15724 -r15729 --- branches/5.2.x/core/admin_templates/js/uploader/uploader.js (.../uploader.js) (revision 15724) +++ branches/5.2.x/core/admin_templates/js/uploader/uploader.js (.../uploader.js) (revision 15729) @@ -47,8 +47,6 @@ multiple : 0, field: '', thumb_format: '', - json: '', - previewURL: '', fileQueueLimit : 0, buttonImageURL : '', buttonWidth : 1, @@ -83,35 +81,24 @@ } Uploader.prototype._prepareFiles = function() { - var $files_json = [], $raw_file_info, $file_info; + var ids = ''; + var names = ''; - // process uploaded files for (var f = 0; f < this.files.length; f++) { - $raw_file_info = this.files[f]; + if (isset(this.files[f].uploaded) && !isset(this.files[f].temp)) { + continue; + } - $file_info = { - id: $raw_file_info.id, - name: $raw_file_info.name, - size: $raw_file_info.size, - deleted: 0, - temp: $raw_file_info.temp, - order: $raw_file_info.order - }; - - $files_json.push(JSON.stringify($file_info)); + ids += this.files[f].id + '|' + names += this.files[f].name + '|' } - // process deleted files; - for (var $i = 0; $i < this.deleted.length; $i++) { - $file_info = { - name: this.deleted[$i], - deleted: 1 - }; + ids = ids.replace(/\|$/, '', ids); + names = names.replace(/\|$/, '', names); - $files_json.push(JSON.stringify($file_info)); - } - - document.getElementById(this.id+'[json]').value = $files_json.join('|'); + document.getElementById(this.id+'[tmp_ids]').value = ids; + document.getElementById(this.id+'[tmp_names]').value = names; + document.getElementById(this.id+'[tmp_deleted]').value = this.deleted.join('|'); } Uploader.prototype._formatSize = function (bytes) { @@ -192,40 +179,29 @@ } ) - if (this.params.json != '') { - var $json_decoded = this.params.json.split('|'), $file, $preview_url; + if (this.params.urls != '') { + var urls = this.params.urls.split('|'); + var names = this.params.names.split('|'); + var sizes = this.params.sizes.split('|'); - for (var $i = 0; $i < $json_decoded.length; $i++) { - $file = JSON.parse($json_decoded[$i]); + for (var i = 0; i < urls.length; i++) { + var a_file = { + id : 'uploaded_' + crc32(names[i]), + name : names[i], + url : urls[i], + size: sizes[i], + uploaded : 1, + progress: 100 + }; - if ( $file.deleted ) { - this.deleted.push($file.name); - continue; - } - - $file.url = this.getUrl($file, 'previewURL'); - $file.uploaded = 1; - $file.progress = 100; - - this.files.push($file); + this.files.push(a_file); this.files_count++; } this.updateInfo(); } } -Uploader.prototype.getUrl = function($file, $param_name) { - var $url = this.params[$param_name]; - - $url = $url.replace('#TMP#', $file.temp); - $url = $url.replace('#ID#', $file.id); - $url = $url.replace('#FILE#', encodeURIComponent($file.name)); - $url = $url.replace('#FIELD#', this.params.field); - - return $url; -} - Uploader.prototype.enableUploadButton = function() { var $me = this; @@ -369,7 +345,7 @@ $('.delete-file-btn', $ret).click( function ($e) { - $(this).attr('checked', UploadsManager.DeleteFile($me.id, $file) ? '' : 'checked'); + $(this).attr('checked', UploadsManager.DeleteFile($me.id, $file.name) ? '' : 'checked'); } ); @@ -397,15 +373,17 @@ return $ret; } -Uploader.prototype.sortFiles = function($ordered_queue) { - var $file_id, $file_index; +Uploader.prototype.getSortedFiles = function($ordered_queue) { + var $me = this; - for (var $i = 0; $i < $ordered_queue.length; $i++) { - $file_id = $ordered_queue[$i].replace(/_queue_row$/, ''); - $file_index = this.getFileIndex({id: $file_id}); + var $ret = $.map($me.files, function ($elem, $index) { + var $file_id = $ordered_queue[$index].replace(/_queue_row$/, ''), + $file_index = $me.getFileIndex({id: $file_id}); - this.files[$file_index].order = $i; - } + return $me.files[$file_index].name; + }); + + return $ret; } Uploader.prototype.updateQueueFile = function($file_index, $delete_file) { @@ -455,7 +433,7 @@ $('#' + this.files[$file_index].id + '_progress').html($progress_code); } -Uploader.prototype.removeFile = function (file, $mark_deleted) { +Uploader.prototype.removeFile = function (file) { var count = 0; var n_files = new Array(); @@ -478,26 +456,8 @@ this.files = n_files; this.files_count = count; this.updateInfo(undefined, true); - - if ( $mark_deleted !== undefined && $mark_deleted === true ) { - this.markDeleted(file.id); - } } -Uploader.prototype.markDeleted = function ($file_name) { - if ( !in_array($file_name, this.deleted) ) { - this.deleted.push($file_name); - } -} - -Uploader.prototype.unMarkDeleted = function ($file_name) { - var $file_index = array_search($file_name, this.deleted); - - if ( $file_index !== -1 ) { - this.deleted.splice($file_index, 1); - } -} - Uploader.prototype.hasQueue = function() { for (var f = 0; f < this.files.length; f++) { if (isset(this.files[f].uploaded)) { @@ -568,15 +528,12 @@ // file was uploaded OR file upload was cancelled var $file_index = this.getFileIndex(file); - this.unMarkDeleted(file.name); - if ($file_index !== false) { // in case if file upload was cancelled, then no info here this.files[$file_index].uploaded = 1; this.files[$file_index].progress = 100; this.files[$file_index].temp = 1; - this.files[$file_index].url = this.getUrl(this.files[$file_index], 'previewURL'); - this.files[$file_index].order = $file_index; + this.files[$file_index].url = this.params.tmp_url.replace('#ID#', file.id).replace('#FILE#', encodeURIComponent(file.name)).replace('#FIELD#', this.params.field); this.updateInfo($file_index); } Index: branches/5.2.x/core/kernel/db/db_event_handler.php =================================================================== diff -u -N -r15727 -r15729 --- branches/5.2.x/core/kernel/db/db_event_handler.php (.../db_event_handler.php) (revision 15727) +++ branches/5.2.x/core/kernel/db/db_event_handler.php (.../db_event_handler.php) (revision 15729) @@ -1,6 +1,6 @@ Prefix . '_changes_' . $this->Application->GetTopmostWid($this->Prefix); $this->Application->RemoveVar($changes_var_name); - foreach ($ids as $id) { - $object->resetUploads($id); - } - $temp_handler = $this->Application->recallObject($event->getPrefixSpecial() . '_TempHandler', 'kTempTablesHandler', Array ('parent_event' => $event)); /* @var $temp_handler kTempTablesHandler */ @@ -2170,8 +2166,6 @@ $this->Application->SetVar($event->getPrefixSpecial() . '_id', 0); $this->Application->SetVar($event->getPrefixSpecial() . '_PreCreate', 1); - $object->resetUploads(); - $changes_var_name = $this->Prefix . '_changes_' . $this->Application->GetTopmostWid($this->Prefix); $this->Application->RemoveVar($changes_var_name); @@ -2606,19 +2600,6 @@ $object = $event->getObject(); /* @var $object kDBItem */ - if ( $object->getUploaderFields() ) { - // this would prevent SQL error when loading "*-ci" prefix object - if ( $event->Name == 'OnAfterCopyToLive' ) { - $object->SwitchToLive(); - $object->Load($event->getEventParam('id')); - - $object->processUploads($event->getEventParam('temp_id')); - } - else { - $object->processUploads(); - } - } - $var_name = $object->getPendingActionVariableName(); $schedule = $this->Application->RecallVar($var_name); @@ -3263,20 +3244,21 @@ protected function OnDeleteFile(kEvent $event) { $event->status = kEvent::erSTOP; - $filename = $this->_getUploadedFileInfo($event, 'full_path'); + $filename = $this->_getSafeFilename(); - if ( $filename === false ) { + if ( !$filename ) { return; } $object = $event->getObject(Array ('skip_autoload' => true)); /* @var $object kDBItem */ + $upload_dir = $object->GetFieldOption($this->Application->GetVar('field'), 'upload_dir'); + $var_name = $object->getPendingActionVariableName(); $schedule = $this->Application->RecallVar($var_name); $schedule = $schedule ? unserialize($schedule) : Array (); - $schedule[] = Array ('action' => 'delete', 'file' => $filename); - + $schedule[] = Array ('action' => 'delete', 'file' => FULL_PATH . $upload_dir . $filename); $this->Application->StoreVar($var_name, serialize($schedule)); } @@ -3290,21 +3272,37 @@ protected function OnViewFile(kEvent $event) { $event->status = kEvent::erSTOP; + $filename = $this->_getSafeFilename(); - if ( $this->Application->GetVar('thumb') ) { - $object = $event->getObject(Array ('skip_autoload' => true)); - /* @var $object kDBItem */ + if ( !$filename ) { + return; + } - $field = $this->Application->GetVar('field'); - $url = $this->_getUploadedFileInfo($event, $object->GetFieldOption($field, 'thumb_format')); + $object = $event->getObject(Array ('skip_autoload' => true)); + /* @var $object kDBItem */ + + $field = $this->Application->GetVar('field'); + $options = $object->GetFieldOptions($field); + + // set current uploaded file + if ( $this->Application->GetVar('tmp') ) { + $options['upload_dir'] = WRITEBALE_BASE . '/tmp/'; + unset($options['include_path']); + $object->SetFieldOptions($field, $options); + + $object->SetDBField($field, $this->Application->GetVar('id') . '_' . $filename); } else { - $url = $this->_getUploadedFileInfo($event, 'full_url'); + $object->SetDBField($field, $filename); } - if ( $url === false ) { - return; + // get url to uploaded file + if ( $this->Application->GetVar('thumb') ) { + $url = $object->GetField($field, $options['thumb_format']); } + else { + $url = $object->GetField($field, 'full_url'); // don't use "file_urls" format to prevent recursion + } $file_helper = $this->Application->recallObject('FileHelper'); /* @var $file_helper FileHelper */ @@ -3317,51 +3315,31 @@ header('Content-Length: ' . filesize($path)); $this->Application->setContentType(kUtil::mimeContentType($path), false); - header('Content-Disposition: inline; filename="' . basename($path) . '"'); + header('Content-Disposition: inline; filename="' . $filename . '"'); readfile($path); } /** - * Returns information about uploaded file + * Returns safe version of filename specified in url * - * @param kEvent $event - * @param string $format - * @return bool + * @return bool|string * @access protected */ - protected function _getUploadedFileInfo(kEvent $event, $format) + protected function _getSafeFilename() { - $file = $this->Application->GetVar('file'); + $filename = $this->Application->GetVar('file'); if ( !$this->Application->isAdmin ) { - $file = htmlspecialchars_decode($file); + $filename = htmlspecialchars_decode($filename); } - if ( (strpos($file, '../') !== false) || (trim($file) !== $file) ) { + if ( (strpos($filename, '../') !== false) || (trim($filename) !== $filename) ) { // when relative paths or special chars are found template names from url, then it's hacking attempt return false; } - $object = $event->getObject(Array ('skip_autoload' => true)); - /* @var $object kDBItem */ - - $field = $this->Application->GetVar('field'); - $options = $object->GetFieldOptions($field); - - // set current uploaded file - if ( $this->Application->GetVar('tmp') ) { - $options['upload_dir'] = WRITEBALE_BASE . '/tmp/'; - unset($options['include_path']); - $object->SetFieldOptions($field, $options); - - $object->SetDBField($field, $this->Application->GetVar('id') . '_' . $file); - } - else { - $object->SetDBField($field, $file); - } - - return $object->GetField($field, $format); + return $filename; } /** Index: branches/5.2.x/core/admin_templates/incs/form_blocks.tpl =================================================================== diff -u -N -r15723 -r15729 --- branches/5.2.x/core/admin_templates/incs/form_blocks.tpl (.../form_blocks.tpl) (revision 15723) +++ branches/5.2.x/core/admin_templates/incs/form_blocks.tpl (.../form_blocks.tpl) (revision 15729) @@ -350,7 +350,10 @@
- + + + +