示例#1
0
/**
 * metaWeblog.newMediaObject image upload
 * wp.uploadFile
 *
 * Supplied image is encoded into the struct as bits
 *
 * @see http://www.xmlrpc.com/metaWeblogApi#metaweblognewmediaobject
 * @see http://codex.wordpress.org/XML-RPC_wp#wp.uploadFile
 *
 * @param xmlrpcmsg XML-RPC Message
 *					0 blogid (string): Unique identifier of the blog the post will be added to.
 *						Currently ignored in b2evo, in favor of the category.
 *					1 username (string): Login for a Blogger user who has permission to edit the given
 *						post (either the user who originally created it or an admin of the blog).
 *					2 password (string): Password for said username.
 *					3 struct (struct)
 * 							- name : filename
 * 							- type : mimetype
 * 							- bits : base64 encoded file
 * @return xmlrpcresp XML-RPC Response
 */
function _wp_mw_newmediaobject($m)
{
    global $Settings, $Plugins, $force_upload_forbiddenext;
    // CHECK LOGIN:
    /**
     * @var User
     */
    if (!($current_User =& xmlrpcs_login($m, 1, 2))) {
        // Login failed, return (last) error:
        return xmlrpcs_resperror();
    }
    // GET BLOG:
    /**
     * @var Blog
     */
    if (!($Blog =& xmlrpcs_get_Blog($m, 0))) {
        // Login failed, return (last) error:
        return xmlrpcs_resperror();
    }
    // CHECK PERMISSION:
    if (!$current_User->check_perm('files', 'add', false, $Blog->ID)) {
        // Permission denied
        return xmlrpcs_resperror(3);
        // User error 3
    }
    logIO('Permission granted.');
    if (!$Settings->get('upload_enabled')) {
        return xmlrpcs_resperror(2, 'Object upload not allowed');
    }
    $xcontent = $m->getParam(3);
    // Get the main data - and decode it properly for the image - sorry, binary object
    logIO('Decoding content...');
    $contentstruct = xmlrpc_decode_recurse($xcontent);
    $data = $contentstruct['bits'];
    $file_mimetype = isset($contentstruct['type']) ? $contentstruct['type'] : '(none)';
    logIO('Received MIME type: ' . $file_mimetype);
    $overwrite = false;
    if (isset($contentstruct['overwrite'])) {
        $overwrite = (bool) $contentstruct['overwrite'];
    }
    logIO('Overwrite if exists: ' . ($overwrite ? 'yes' : 'no'));
    load_funcs('files/model/_file.funcs.php');
    $filesize = evo_bytes($data);
    if (($maxfilesize = $Settings->get('upload_maxkb') * 1024) && $filesize > $maxfilesize) {
        return xmlrpcs_resperror(4, sprintf(T_('The file is too large: %s but the maximum allowed is %s.'), bytesreadable($filesize, false), bytesreadable($maxfilesize, false)));
    }
    logIO('File size is OK: ' . bytesreadable($filesize, false));
    $FileRootCache =& get_FileRootCache();
    $fm_FileRoot =& $FileRootCache->get_by_type_and_ID('collection', $Blog->ID, true);
    if (!$fm_FileRoot) {
        // fileRoot not found:
        return xmlrpcs_resperror(14, 'File root not found');
    }
    $rf_filepath = $contentstruct['name'];
    logIO('Received filepath: ' . $rf_filepath);
    // Split into path + name:
    $filepath_parts = explode('/', $rf_filepath);
    $filename = array_pop($filepath_parts);
    logIO('Original file name: ' . $filename);
    // Validate and sanitize filename
    if ($error_filename = process_filename($filename, true)) {
        return xmlrpcs_resperror(5, $error_filename);
    }
    logIO('Sanitized file name: ' . $filename);
    // Check valid path parts:
    $rds_subpath = '';
    foreach ($filepath_parts as $filepath_part) {
        if (empty($filepath_part) || $filepath_part == '.') {
            // self ref not useful
            continue;
        }
        if ($error = validate_dirname($filepath_part)) {
            // invalid relative path:
            logIO($error);
            return xmlrpcs_resperror(6, $error);
        }
        $rds_subpath .= $filepath_part . '/';
    }
    logIO('Subpath: ' . $rds_subpath);
    // Create temporary file and insert contents into it.
    $tmpfile_name = tempnam(sys_get_temp_dir(), 'fmupload');
    if ($tmpfile_name) {
        if (save_to_file($data, $tmpfile_name, 'wb')) {
            $image_info = @getimagesize($tmpfile_name);
        } else {
            return xmlrpcs_resperror(13, 'Error while writing to temp file.');
        }
    }
    if (!empty($image_info)) {
        // This is an image file, let's check mimetype and correct extension
        if ($image_info['mime'] != $file_mimetype) {
            // Invalid file type
            $FiletypeCache =& get_FiletypeCache();
            // Get correct file type based on mime type
            $correct_Filetype = $FiletypeCache->get_by_mimetype($image_info['mime'], false, false);
            $file_mimetype = $image_info['mime'];
            // Check if file type is known by us, and if it is allowed for upload.
            // If we don't know this file type or if it isn't allowed we don't change the extension! The current extension is allowed for sure.
            if ($correct_Filetype && $correct_Filetype->is_allowed()) {
                // A FileType with the given mime type exists in database and it is an allowed file type for current User
                // The "correct" extension is a plausible one, proceed...
                $correct_extension = array_shift($correct_Filetype->get_extensions());
                $path_info = pathinfo($filename);
                $current_extension = $path_info['extension'];
                // change file extension to the correct extension, but only if the correct extension is not restricted, this is an extra security check!
                if (strtolower($current_extension) != strtolower($correct_extension) && !in_array($correct_extension, $force_upload_forbiddenext)) {
                    // change the file extension to the correct extension
                    $old_filename = $filename;
                    $filename = $path_info['filename'] . '.' . $correct_extension;
                }
            }
        }
    }
    // Get File object for requested target location:
    $FileCache =& get_FileCache();
    $newFile =& $FileCache->get_by_root_and_path($fm_FileRoot->type, $fm_FileRoot->in_type_ID, trailing_slash($rds_subpath) . $filename, true);
    if ($newFile->exists()) {
        if ($overwrite && $newFile->unlink()) {
            // OK, file deleted
            // Delete thumb caches from old location:
            logIO('Old file deleted');
            $newFile->rm_cache();
        } else {
            return xmlrpcs_resperror(8, sprintf(T_('The file «%s» already exists.'), $filename));
        }
    }
    // Trigger plugin event
    if ($Plugins->trigger_event_first_false('AfterFileUpload', array('File' => &$newFile, 'name' => &$filename, 'type' => &$file_mimetype, 'tmp_name' => &$tmpfile_name, 'size' => &$filesize))) {
        // Plugin returned 'false'.
        // Abort upload for this file:
        @unlink($tmpfile_name);
        return xmlrpcs_resperror(16, 'File upload aborted by a plugin.');
    }
    if (!mkdir_r($newFile->get_dir())) {
        // Dir didn't already exist and could not be created
        return xmlrpcs_resperror(9, 'Error creating sub directories: ' . $newFile->get_rdfs_rel_path());
    }
    if (!@rename($tmpfile_name, $newFile->get_full_path())) {
        return xmlrpcs_resperror(13, 'Error while writing to file.');
    }
    // chmod the file
    $newFile->chmod();
    // Initializes file properties (type, size, perms...)
    $newFile->load_properties();
    // Load meta data AND MAKE SURE IT IS CREATED IN DB:
    $newFile->meta == 'unknown';
    $newFile->load_meta(true);
    // Resize and rotate
    logIO('Running file post-processing (resize and rotate)...');
    prepare_uploaded_files(array($newFile));
    logIO('Done');
    $url = $newFile->get_url();
    logIO('URL of new file: ' . $url);
    $struct = new xmlrpcval(array('file' => new xmlrpcval($filename, 'string'), 'url' => new xmlrpcval($url, 'string'), 'type' => new xmlrpcval($file_mimetype, 'string')), 'struct');
    logIO('OK.');
    return new xmlrpcresp($struct);
}
示例#2
0
     $message['text'] = '<span class="result_error"> ' . $error_filename . '</span>';
     out_echo($message, $specialchars);
     exit;
 }
 list($newFile, $oldFile_thumb) = check_file_exists($fm_FileRoot, $path, $newName);
 $newName = $newFile->get('name');
 // If everything is ok, save the file somewhere
 if (save_to_file($file->get_content(), $newFile->get_full_path(), 'wb')) {
     // Change to default chmod settings
     $newFile->chmod(NULL);
     // Refreshes file properties (type, size, perms...)
     $newFile->load_properties();
     // save file into the db
     $newFile->dbsave();
     // Prepare the uploaded file to the final format ( E.g. Resize and Rotate images )
     prepare_uploaded_files(array($newFile));
     $message = '';
     if (!empty($oldFile_thumb)) {
         $image_info = getimagesize($newFile->get_full_path());
         if ($image_info) {
             $newFile_thumb = $newFile->get_preview_thumb('fulltype');
         } else {
             $newFile_thumb = $newFile->get_size_formatted();
         }
         $message = '<br />';
         $message .= sprintf(T_('%s was renamed to %s. Would you like to replace %s with the new version instead?'), '&laquo;' . $oldName . '&raquo;', '&laquo;' . $newName . '&raquo;', '&laquo;' . $oldName . '&raquo;');
         $message .= '<div class="invalid" title="' . T_('File name changed.') . '">';
         $message .= '<input type="radio" name="Renamed_' . $newFile->ID . '" value="Yes" id="Yes_' . $newFile->ID . '"/>';
         $message .= '<label for="Yes_' . $newFile->ID . '">';
         $message .= sprintf(T_("Replace the old version %s with the new version %s and keep old version as %s."), $oldFile_thumb, $newFile_thumb, $newName) . '</label><br />';
         $message .= '<input type="radio" name="Renamed_' . $newFile->ID . '" value="No" id="No_' . $newFile->ID . '" checked="checked"/>';
示例#3
0
/**
 * Process file uploads (this can process multiple file uploads at once)
 *
 * @param string FileRoot id string
 * @param string the upload dir relative path in the FileRoot
 * @param boolean Shall we create path dirs if they do not exist?
 * @param boolean Shall we check files add permission for current_User?
 * @param boolean upload quick mode
 * @param boolean show warnings if filename is not valid
 * @param integer minimum size for pictures in pixels (width and height)
 * @return mixed NULL if upload was impossible to complete for some reason (wrong fileroot ID, insufficient user permission, etc.)
 * 				       array, which contains uploadedFiles, failedFiles, renamedFiles and renamedMessages
 */
function process_upload($root_ID, $path, $create_path_dirs = false, $check_perms = true, $upload_quickmode = true, $warn_invalid_filenames = true, $min_size = 0)
{
    global $Settings, $Plugins, $Messages, $current_User, $force_upload_forbiddenext;
    if (empty($_FILES)) {
        // We have NO uploaded files to process...
        return NULL;
    }
    /**
     * Remember failed files (and the error messages)
     * @var array
     */
    $failedFiles = array();
    /**
     * Remember uploaded files
     * @var array
     */
    $uploadedFiles = array();
    /**
     * Remember renamed files
     * @var array
     */
    $renamedFiles = array();
    /**
     * Remember renamed Messages
     * @var array
     */
    $renamedMessages = array();
    $FileRootCache =& get_FileRootCache();
    $fm_FileRoot =& $FileRootCache->get_by_ID($root_ID, true);
    if (!$fm_FileRoot) {
        // fileRoot not found:
        return NULL;
    }
    if ($check_perms && (!isset($current_User) || $current_User->check_perm('files', 'add', false, $fm_FileRoot))) {
        // Permission check required but current User has no permission to upload:
        return NULL;
    }
    // Let's get into requested list dir...
    $non_canonical_list_path = $fm_FileRoot->ads_path . $path;
    // Dereference any /../ just to make sure, and CHECK if directory exists:
    $ads_list_path = get_canonical_path($non_canonical_list_path);
    // check if the upload dir exists
    if (!is_dir($ads_list_path)) {
        if ($create_path_dirs) {
            // Create path
            mkdir_r($ads_list_path);
        } else {
            // This case should not happen! If it happens then there is a bug in the code where this function was called!
            return NULL;
        }
    }
    // Get param arrays for all uploaded files:
    $uploadfile_title = param('uploadfile_title', 'array/string', array());
    $uploadfile_alt = param('uploadfile_alt', 'array/string', array());
    $uploadfile_desc = param('uploadfile_desc', 'array/string', array());
    $uploadfile_name = param('uploadfile_name', 'array/string', array());
    // LOOP THROUGH ALL UPLOADED FILES AND PROCCESS EACH ONE:
    foreach ($_FILES['uploadfile']['name'] as $lKey => $lName) {
        if (empty($lName)) {
            // No file name:
            if ($upload_quickmode || !empty($uploadfile_title[$lKey]) || !empty($uploadfile_alt[$lKey]) || !empty($uploadfile_desc[$lKey]) || !empty($uploadfile_name[$lKey])) {
                // User specified params but NO file! Warn the user:
                $failedFiles[$lKey] = T_('Please select a local file to upload.');
            }
            // Abort upload for this file:
            continue;
        }
        if ($Settings->get('upload_maxkb') && $_FILES['uploadfile']['size'][$lKey] > $Settings->get('upload_maxkb') * 1024) {
            // File is larger than allowed in settings:
            $failedFiles[$lKey] = sprintf(T_('The file is too large: %s but the maximum allowed is %s.'), bytesreadable($_FILES['uploadfile']['size'][$lKey]), bytesreadable($Settings->get('upload_maxkb') * 1024));
            // Abort upload for this file:
            continue;
        }
        if (!empty($min_size)) {
            // Check pictures for small sizes
            $image_sizes = imgsize($_FILES['uploadfile']['tmp_name'][$lKey], 'widthheight');
            if ($image_sizes[0] < $min_size || $image_sizes[1] < $min_size) {
                // Abort upload for this file:
                $failedFiles[$lKey] = sprintf(T_('Your profile picture must have a minimum size of %dx%d pixels.'), $min_size, $min_size);
                continue;
            }
        }
        if ($_FILES['uploadfile']['error'][$lKey]) {
            // PHP itself has detected an error!:
            switch ($_FILES['uploadfile']['error'][$lKey]) {
                case UPLOAD_ERR_FORM_SIZE:
                    // The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the html form.
                    // This can easily be edited by the user/hacker, so we do not use it.. file size gets checked for real just above.
                    break;
                case UPLOAD_ERR_INI_SIZE:
                    // File is larger than allowed in php.ini:
                    $failedFiles[$lKey] = 'The file exceeds the upload_max_filesize directive in php.ini.';
                    // Configuration error, no translation
                    // Abort upload for this file:
                    continue;
                case UPLOAD_ERR_PARTIAL:
                    $failedFiles[$lKey] = T_('The file was only partially uploaded.');
                    // Abort upload for this file:
                    continue;
                case UPLOAD_ERR_NO_FILE:
                    // Is probably the same as empty($lName) before.
                    $failedFiles[$lKey] = T_('No file was uploaded.');
                    // Abort upload for this file:
                    continue;
                case 6:
                    // numerical value of UPLOAD_ERR_NO_TMP_DIR
                    # (min_php: 4.3.10, 5.0.3) case UPLOAD_ERR_NO_TMP_DIR:
                    // Missing a temporary folder.
                    $failedFiles[$lKey] = 'Temporary upload dir is missing! (upload_tmp_dir in php.ini)';
                    // Configuration error, no translation
                    // Abort upload for this file:
                    continue;
                default:
                    $failedFiles[$lKey] = T_('An unknown error has occurred!') . ' Error code #' . $_FILES['uploadfile']['error'][$lKey];
                    // Abort upload for this file:
                    continue;
            }
        }
        if (!isset($_FILES['uploadfile']['_evo_fetched_url'][$lKey]) && !is_uploaded_file($_FILES['uploadfile']['tmp_name'][$lKey])) {
            // Ensure that a malicious user hasn't tried to trick the script into working on files upon which it should not be working.
            $failedFiles[$lKey] = T_('The file does not seem to be a valid upload! It may exceed the upload_max_filesize directive in php.ini.');
            // Abort upload for this file:
            continue;
        }
        // Use new name on server if specified:
        $newName = !empty($uploadfile_name[$lKey]) ? $uploadfile_name[$lKey] : $lName;
        // validate file name
        if ($error_filename = process_filename($newName, !$warn_invalid_filenames)) {
            // Not a valid file name or not an allowed extension:
            $failedFiles[$lKey] = $error_filename;
            // Abort upload for this file:
            continue;
        }
        // Check if the uploaded file type is an image, and if is an image then try to fix the file extension based on mime type
        // If the mime type is a known mime type and user has right to upload files with this kind of file type,
        // this part of code will check if the file extension is the same as admin defined for this file type, and will fix it if it isn't the same
        // Note: it will also change the jpeg extensions to jpg.
        $uploadfile_path = $_FILES['uploadfile']['tmp_name'][$lKey];
        // this image_info variable will be used again to get file thumb
        $image_info = getimagesize($uploadfile_path);
        if ($image_info) {
            // This is an image, validate mimetype vs. extension:
            $image_mimetype = $image_info['mime'];
            $FiletypeCache =& get_FiletypeCache();
            // Get correct file type based on mime type
            $correct_Filetype = $FiletypeCache->get_by_mimetype($image_mimetype, false, false);
            // Check if file type is known by us, and if it is allowed for upload.
            // If we don't know this file type or if it isn't allowed we don't change the extension! The current extension is allowed for sure.
            if ($correct_Filetype && $correct_Filetype->is_allowed()) {
                // A FileType with the given mime type exists in database and it is an allowed file type for current User
                // The "correct" extension is a plausible one, proceed...
                $correct_extension = array_shift($correct_Filetype->get_extensions());
                $path_info = pathinfo($newName);
                $current_extension = $path_info['extension'];
                // change file extension to the correct extension, but only if the correct extension is not restricted, this is an extra security check!
                if (strtolower($current_extension) != strtolower($correct_extension) && !in_array($correct_extension, $force_upload_forbiddenext)) {
                    // change the file extension to the correct extension
                    $old_name = $newName;
                    $newName = $path_info['filename'] . '.' . $correct_extension;
                    $Messages->add(sprintf(T_('The extension of the file &laquo;%s&raquo; has been corrected. The new filename is &laquo;%s&raquo;.'), $old_name, $newName), 'warning');
                }
            }
        }
        // Get File object for requested target location:
        $oldName = strtolower($newName);
        list($newFile, $oldFile_thumb) = check_file_exists($fm_FileRoot, $path, $newName, $image_info);
        $newName = $newFile->get('name');
        // Trigger plugin event
        if ($Plugins->trigger_event_first_false('AfterFileUpload', array('File' => &$newFile, 'name' => &$_FILES['uploadfile']['name'][$lKey], 'type' => &$_FILES['uploadfile']['type'][$lKey], 'tmp_name' => &$_FILES['uploadfile']['tmp_name'][$lKey], 'size' => &$_FILES['uploadfile']['size'][$lKey]))) {
            // Plugin returned 'false'.
            // Abort upload for this file:
            continue;
        }
        // Attempt to move the uploaded file to the requested target location:
        if (isset($_FILES['uploadfile']['_evo_fetched_url'][$lKey])) {
            // fetched remotely
            if (!rename($_FILES['uploadfile']['tmp_name'][$lKey], $newFile->get_full_path())) {
                $failedFiles[$lKey] = T_('An unknown error occurred when moving the uploaded file on the server.');
                // Abort upload for this file:
                continue;
            }
        } elseif (!move_uploaded_file($_FILES['uploadfile']['tmp_name'][$lKey], $newFile->get_full_path())) {
            $failedFiles[$lKey] = T_('An unknown error occurred when moving the uploaded file on the server.');
            // Abort upload for this file:
            continue;
        }
        // change to default chmod settings
        if ($newFile->chmod(NULL) === false) {
            // add a note, this is no error!
            $Messages->add(sprintf(T_('Could not change permissions of &laquo;%s&raquo; to default chmod setting.'), $newFile->dget('name')), 'note');
        }
        // Refreshes file properties (type, size, perms...)
        $newFile->load_properties();
        if (!empty($oldFile_thumb)) {
            // The file name was changed!
            if ($image_info) {
                $newFile_thumb = $newFile->get_preview_thumb('fulltype');
            } else {
                $newFile_thumb = $newFile->get_size_formatted();
            }
            //$newFile_size = bytesreadable ($_FILES['uploadfile']['size'][$lKey]);
            $renamedMessages[$lKey]['message'] = sprintf(T_('"%s was renamed to %s. Would you like to replace %s with the new version instead?'), '&laquo;' . $oldName . '&raquo;', '&laquo;' . $newName . '&raquo;', '&laquo;' . $oldName . '&raquo;');
            $renamedMessages[$lKey]['oldThumb'] = $oldFile_thumb;
            $renamedMessages[$lKey]['newThumb'] = $newFile_thumb;
            $renamedFiles[$lKey]['oldName'] = $oldName;
            $renamedFiles[$lKey]['newName'] = $newName;
        }
        // Store extra info about the file into File Object:
        if (isset($uploadfile_title[$lKey])) {
            // If a title text has been passed... (does not happen in quick upload mode)
            $newFile->set('title', trim(strip_tags($uploadfile_title[$lKey])));
        }
        if (isset($uploadfile_alt[$lKey])) {
            // If an alt text has been passed... (does not happen in quick upload mode)
            $newFile->set('alt', trim(strip_tags($uploadfile_alt[$lKey])));
        }
        if (isset($uploadfile_desc[$lKey])) {
            // If a desc text has been passed... (does not happen in quick upload mode)
            $newFile->set('desc', trim(strip_tags($uploadfile_desc[$lKey])));
        }
        // Store File object into DB:
        $newFile->dbsave();
        $uploadedFiles[] = $newFile;
    }
    prepare_uploaded_files($uploadedFiles);
    return array('uploadedFiles' => $uploadedFiles, 'failedFiles' => $failedFiles, 'renamedFiles' => $renamedFiles, 'renamedMessages' => $renamedMessages);
}