Index: branches/5.3.x/core/kernel/db/db_event_handler.php =================================================================== diff -u -N -r15999 -r16002 --- branches/5.3.x/core/kernel/db/db_event_handler.php (.../db_event_handler.php) (revision 15999) +++ branches/5.3.x/core/kernel/db/db_event_handler.php (.../db_event_handler.php) (revision 16002) @@ -1,6 +1,6 @@ status = kEvent::erSTOP; -// define('DBG_SKIP_REPORTING', 0); - $default_msg = "Flash requires that we output something or it won't fire the uploadSuccess event"; - if ( !$this->Application->HttpQuery->Post ) { - // Variables {field, id, flashsid} are always submitted through POST! - // When file size is larger, then "upload_max_filesize" (in php.ini), - // then these variables also are not submitted -> handle such case. - header('HTTP/1.0 413 File size exceeds allowed limit'); - echo $default_msg; - return; - } + /** @var kUploadHelper $upload_helper */ + $upload_helper = $this->Application->recallObject('kUploadHelper'); - if ( !$this->_checkFlashUploaderPermission($event) ) { - // 403 Forbidden - header('HTTP/1.0 403 You don\'t have permissions to upload'); - echo $default_msg; - return; - } + try { + $filename = $upload_helper->handle($event); - $value = $this->Application->GetVar('Filedata'); - - if ( !$value || ($value['error'] != UPLOAD_ERR_OK) ) { - // 413 Request Entity Too Large (file uploads disabled OR uploaded file was - // to large for web server to accept, see "upload_max_filesize" in php.ini) - header('HTTP/1.0 413 File size exceeds allowed limit'); - echo $default_msg; - return; + $response = array( + 'jsonrpc' => '2.0', + 'status' => 'success', + 'result' => $filename, + ); } - - if ( !$this->Application->isAdmin ) { - $value = array_map('htmlspecialchars_decode', $value); + catch ( kUploaderException $e ) { + $response = array( + 'jsonrpc' => '2.0', + 'status' => 'error', + 'error' => array('code' => $e->getCode(), 'message' => $e->getMessage()), + ); } - $tmp_path = WRITEABLE . '/tmp/'; - $filename = $value['name'] . '.tmp'; - $id = $this->Application->GetVar('id'); - - if ( $id ) { - $filename = $id . '_' . $filename; - } - - if ( !is_writable($tmp_path) ) { - // 500 Internal Server Error - // check both temp and live upload directory - header('HTTP/1.0 500 Write permissions not set on the server'); - echo $default_msg; - return; - } - - $file_helper = $this->Application->recallObject('FileHelper'); - /* @var $file_helper FileHelper */ - - $filename = $file_helper->ensureUniqueFilename($tmp_path, $filename); - $storage_format = $this->_getStorageFormat($this->Application->GetVar('field'), $event); - - if ( $storage_format ) { - $image_helper = $this->Application->recallObject('ImageHelper'); - /* @var $image_helper ImageHelper */ - - move_uploaded_file($value['tmp_name'], $value['tmp_name'] . '.jpg'); // add extension, so ResizeImage can work - $url = $image_helper->ResizeImage($value['tmp_name'] . '.jpg', $storage_format); - $tmp_name = preg_replace('/^' . preg_quote($this->Application->BaseURL(), '/') . '/', '/', $url); - rename($tmp_name, $tmp_path . $filename); - } - else { - move_uploaded_file($value['tmp_name'], $tmp_path . $filename); - } - - echo preg_replace('/^' . preg_quote($id, '/') . '_/', '', $filename); - - $this->deleteTempFiles($tmp_path); - - if ( file_exists($tmp_path . 'resized/') ) { - $this->deleteTempFiles($tmp_path . 'resized/'); - } + echo json_encode($response); } /** - * Gets storage format for a given field - * - * @param string $field_name - * @param kEvent $event - * @return bool - * @access protected - */ - protected function _getStorageFormat($field_name, kEvent $event) - { - $config = $event->getUnitConfig(); - $field_options = $config->getFieldByName($field_name); - - if ( !$field_options ) { - $field_options = $config->getVirtualFieldByName($field_name); - } - - return isset($field_options['storage_format']) ? $field_options['storage_format'] : false; - } - - /** - * Delete temporary files, that won't be used for sure - * - * @param string $path - * @return void - * @access protected - */ - protected function deleteTempFiles($path) - { - $files = glob($path . '*.*'); - $max_file_date = strtotime('-1 day'); - - foreach ($files as $file) { - if (filemtime($file) < $max_file_date) { - unlink($file); - } - } - } - - /** - * Checks, that flash uploader is allowed to perform upload - * - * @param kEvent $event - * @return bool - */ - protected function _checkFlashUploaderPermission(kEvent $event) - { - // Flash uploader does NOT send correct cookies, so we need to make our own check - $cookie_name = 'adm_' . $this->Application->ConfigValue('SessionCookieName'); - $this->Application->HttpQuery->Cookie['cookies_on'] = 1; - $this->Application->HttpQuery->Cookie[$cookie_name] = $this->Application->GetVar('flashsid'); - - // this prevents session from auto-expiring when KeepSessionOnBrowserClose & FireFox is used - $this->Application->HttpQuery->Cookie[$cookie_name . '_live'] = $this->Application->GetVar('flashsid'); - - $admin_ses = $this->Application->recallObject('Session.admin'); - /* @var $admin_ses Session */ - - if ( $admin_ses->RecallVar('user_id') == USER_ROOT ) { - return true; - } - - // copy some data from given session to current session - $backup_user_id = $this->Application->RecallVar('user_id'); - $this->Application->StoreVar('user_id', $admin_ses->RecallVar('user_id')); - - $backup_user_groups = $this->Application->RecallVar('UserGroups'); - $this->Application->StoreVar('UserGroups', $admin_ses->RecallVar('UserGroups')); - - // check permissions using event, that have "add|edit" rule - $check_event = new kEvent($event->getPrefixSpecial() . ':OnProcessSelected'); - $check_event->setEventParam('top_prefix', $this->Application->GetTopmostPrefix($event->Prefix, true)); - $allowed_to_upload = $this->CheckPermission($check_event); - - // restore changed data, so nothing gets saved to database - $this->Application->StoreVar('user_id', $backup_user_id); - $this->Application->StoreVar('UserGroups', $backup_user_groups); - - return $allowed_to_upload; - } - - /** * Remembers, that file should be deleted on item's save from temp table * * @param kEvent $event @@ -3300,28 +3166,30 @@ protected function OnDeleteFile(kEvent $event) { $event->status = kEvent::erSTOP; - $filename = $this->_getSafeFilename(); + $field_id = $this->Application->GetVar('field_id'); - if ( !$filename ) { + if ( !preg_match_all('/\[([^\[\]]*)\]/', $field_id, $regs) ) { return; } - $object = $event->getObject(Array ('skip_autoload' => true)); - /* @var $object kDBItem */ + $field = $regs[1][1]; + $record_id = $regs[1][0]; - $field_id = $this->Application->GetVar('field_id'); + /** @var kUploadHelper $upload_helper */ + $upload_helper = $this->Application->recallObject('kUploadHelper'); + $object = $upload_helper->prepareUploadedFile($event, $field); - if ( !preg_match_all('/\[([^\[\]]*)\]/', $field_id, $regs) ) { + if ( !$object->GetDBField($field) ) { return; } - $field = $regs[1][1]; - $record_id = $regs[1][0]; $pending_actions = $object->getPendingActions($record_id); - $upload_dir = $object->GetFieldOption($field, 'upload_dir'); $pending_actions[] = Array ( - 'action' => 'delete', 'id' => $record_id, 'field' => $field, 'file' => FULL_PATH . $upload_dir . $filename + 'action' => 'delete', + 'id' => $record_id, + 'field' => $field, + 'file' => $object->GetField($field, 'full_path'), ); $object->setPendingActions($pending_actions, $record_id); @@ -3337,41 +3205,26 @@ protected function OnViewFile(kEvent $event) { $event->status = kEvent::erSTOP; - $filename = $this->_getSafeFilename(); - - if ( !$filename ) { - return; - } - - $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); + /** @var kUploadHelper $upload_helper */ + $upload_helper = $this->Application->recallObject('kUploadHelper'); + $object = $upload_helper->prepareUploadedFile($event, $field); - $object->SetDBField($field, $this->Application->GetVar('id') . '_' . $filename); + if ( !$object->GetDBField($field) ) { + return; } - else { - $object->SetDBField($field, $filename); - } // get url to uploaded file if ( $this->Application->GetVar('thumb') ) { - $url = $object->GetField($field, $options['thumb_format']); + $url = $object->GetField($field, $object->GetFieldOption($field, 'thumb_format')); } else { $url = $object->GetField($field, 'raw_url'); } + /** @var FileHelper $file_helper */ $file_helper = $this->Application->recallObject('FileHelper'); - /* @var $file_helper FileHelper */ - $path = $file_helper->urlToPath($url); if ( !file_exists($path) ) { @@ -3380,34 +3233,12 @@ header('Content-Length: ' . filesize($path)); $this->Application->setContentType(kUtil::mimeContentType($path), false); - header('Content-Disposition: inline; filename="' . kUtil::removeTempExtension($filename) . '"'); + header('Content-Disposition: inline; filename="' . kUtil::removeTempExtension($object->GetDBField($field)) . '"'); readfile($path); } /** - * Returns safe version of filename specified in url - * - * @return bool|string - * @access protected - */ - protected function _getSafeFilename() - { - $filename = $this->Application->GetVar('file'); - - if ( !$this->Application->isAdmin ) { - $filename = htmlspecialchars_decode($filename); - } - - 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; - } - - return $filename; - } - - /** * Validates MInput control fields * * @param kEvent $event