Esempio n. 1
0
                if (!$tmpfile_name) {
                    $failedFiles[$k] = 'Failed to find temporary directory.';
                    // no trans: very unlikely
                    continue;
                }
                if (!save_to_file($file_contents, $tmpfile_name, 'w')) {
                    unlink($tmpfile_name);
                    $failedFiles[$k] = sprintf('Could not write to temporary file (%s).', $tmpfile_name);
                    continue;
                }
                // Fake/inject info into PHP's array of uploaded files.
                // fp> TODO! This is a nasty dirty hack. That kind of stuff always breaks somewhere down the line. Needs cleanup.
                // This allows us to treat it (nearly) the same way as regular uploads, apart from
                // is_uploaded_file(), which we skip and move_uploaded_file() (where we use rename()).
                $_FILES['uploadfile']['name'][$k] = rawurldecode(basename($parsed_url['path']));
                $_FILES['uploadfile']['size'][$k] = evo_bytes($file_contents);
                $_FILES['uploadfile']['error'][$k] = 0;
                $_FILES['uploadfile']['tmp_name'][$k] = $tmpfile_name;
                $_FILES['uploadfile']['_evo_fetched_url'][$k] = $url;
                // skip is_uploaded_file and keep info
                unset($file_contents);
            } else {
                $failedFiles[$k] = sprintf('Could not retrieve file. Error: %s (status %s). Used method: %s.', $info['error'], isset($info['status']) ? $info['status'] : '-', isset($info['used_method']) ? $info['used_method'] : '-');
            }
        }
    }
}
// Process renaming/replacing of old versions:
if (!empty($renamedFiles)) {
    foreach ($renamedFiles as $rKey => $rData) {
        $replace_old = param('Renamed_' . $rKey, 'string', null);
Esempio n. 2
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);
}
Esempio n. 3
0
/**
 * Fetch remote page
 *
 * Attempt to retrieve a remote page using a HTTP GET request, first with
 * cURL, then fsockopen, then fopen.
 *
 * cURL gets skipped, if $max_size_kb is requested, since there appears to be no
 * method to control this.
 * {@internal (CURLOPT_READFUNCTION maybe? But it has not been called for me.. seems
 *            to affect sending, not fetching?!)}}
 *
 * @todo dh> Should we try remaining methods, if the previous one(s) failed?
 * @todo Tblue> Also allow HTTP POST.
 *
 * @param string URL
 * @param array Info (by reference)
 *        'error': holds error message, if any
 *        'status': HTTP status (e.g. 200 or 404)
 *        'used_method': Used method ("curl", "fopen", "fsockopen" or null if no method
 *                       is available)
 * @param integer Timeout (default: 15 seconds)
 * @param integer Maximum size in kB
 * @return string|false The remote page as a string; false in case of error
 */
function fetch_remote_page($url, &$info, $timeout = NULL, $max_size_kb = NULL)
{
    global $outgoing_proxy_hostname, $outgoing_proxy_port, $outgoing_proxy_username, $outgoing_proxy_password;
    $info = array('error' => '', 'status' => NULL, 'mimetype' => NULL, 'used_method' => NULL);
    if (!isset($timeout)) {
        $timeout = 15;
    }
    if (extension_loaded('curl') && !$max_size_kb) {
        // CURL:
        $info['used_method'] = 'curl';
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
        curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
        // Set proxy:
        if (!empty($outgoing_proxy_hostname)) {
            curl_setopt($ch, CURLOPT_PROXY, $outgoing_proxy_hostname);
            curl_setopt($ch, CURLOPT_PROXYPORT, $outgoing_proxy_port);
            curl_setopt($ch, CURLOPT_PROXYUSERPWD, $outgoing_proxy_username . ':' . $outgoing_proxy_password);
        }
        @curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        // made silent due to possible errors with safe_mode/open_basedir(?)
        curl_setopt($ch, CURLOPT_MAXREDIRS, 3);
        $r = curl_exec($ch);
        $info['mimetype'] = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
        $info['status'] = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $info['error'] = curl_error($ch);
        if ($errno = curl_errno($ch)) {
            $info['error'] .= ' (#' . $errno . ')';
        }
        curl_close($ch);
        return $r;
    }
    if (function_exists('fsockopen')) {
        // FSOCKOPEN:
        $info['used_method'] = 'fsockopen';
        if (($url_parsed = @parse_url($url)) === false || !isset($url_parsed['host'])) {
            $info['error'] = NT_('Could not parse URL');
            return false;
        }
        $host = $url_parsed['host'];
        $port = empty($url_parsed['port']) ? 80 : $url_parsed['port'];
        $path = empty($url_parsed['path']) ? '/' : $url_parsed['path'];
        if (!empty($url_parsed['query'])) {
            $path .= '?' . $url_parsed['query'];
        }
        $out = 'GET ' . $path . ' HTTP/1.1' . "\r\n";
        $out .= 'Host: ' . $host;
        if (!empty($url_parsed['port'])) {
            // we don't want to add :80 if not specified. remote end may not resolve it. (e-g b2evo multiblog does not)
            $out .= ':' . $port;
        }
        $out .= "\r\n" . 'Connection: Close' . "\r\n\r\n";
        $fp = @fsockopen($host, $port, $errno, $errstr, $timeout);
        if (!$fp) {
            $info['error'] = $errstr . ' (#' . $errno . ')';
            return false;
        }
        // Send request:
        fwrite($fp, $out);
        // Set timeout for data:
        if (function_exists('stream_set_timeout')) {
            stream_set_timeout($fp, $timeout);
            // PHP 4.3.0
        } else {
            socket_set_timeout($fp, $timeout);
            // PHP 4
        }
        // Read response:
        $r = '';
        // First line:
        $s = fgets($fp);
        if (!preg_match('~^HTTP/\\d+\\.\\d+ (\\d+)~', $s, $match)) {
            $info['error'] = NT_('Invalid response.');
            fclose($fp);
            return false;
        }
        while (!feof($fp)) {
            $r .= fgets($fp);
            if ($max_size_kb && evo_bytes($r) >= $max_size_kb * 1024) {
                $info['error'] = NT_(sprintf('Maximum size of %d kB reached.', $max_size_kb));
                return false;
            }
        }
        fclose($fp);
        if (($pos = strpos($r, "\r\n\r\n")) === false) {
            $info['error'] = NT_('Could not locate end of headers');
            return false;
        }
        // Remember headers to extract info at the end
        $headers = explode("\r\n", substr($r, 0, $pos));
        $info['status'] = $match[1];
        $r = substr($r, $pos + 4);
    } elseif (ini_get('allow_url_fopen')) {
        // URL FOPEN:
        $info['used_method'] = 'fopen';
        $fp = @fopen($url, 'r');
        if (!$fp) {
            if (isset($http_response_header) && ($code = _http_wrapper_last_status($http_response_header)) !== false) {
                // fopen() returned false because it got a bad HTTP code:
                $info['error'] = NT_('Invalid response');
                $info['status'] = $code;
                return '';
            }
            $info['error'] = NT_('fopen() failed');
            return false;
        } else {
            if (!isset($http_response_header) || ($code = _http_wrapper_last_status($http_response_header)) === false) {
                $info['error'] = NT_('Invalid response');
                return false;
            } else {
                // Used to get info at the end
                $headers = $http_response_header;
                // Retrieve contents
                $r = '';
                while (!feof($fp)) {
                    $r .= fgets($fp);
                    if ($max_size_kb && evo_bytes($r) >= $max_size_kb * 1024) {
                        $info['error'] = NT_(sprintf('Maximum size of %d kB reached.', $max_size_kb));
                        return false;
                    }
                }
                $info['status'] = $code;
            }
        }
        fclose($fp);
    }
    // Extract mimetype info from the headers (for fsockopen/fopen)
    if (isset($r)) {
        foreach ($headers as $header) {
            $header = strtolower($header);
            if (substr($header, 0, 13) == 'content-type:') {
                $info['mimetype'] = trim(substr($header, 13));
                break;
                // only looking for mimetype
            }
        }
        return $r;
    }
    // All failed:
    $info['error'] = NT_('No method available to access URL!');
    return false;
}