Esempio n. 1
0
/**
 * Finds a pingback server URI based on the given URL.
 *
 * Checks the HTML for the rel="pingback" link and x-pingback headers. It does
 * a check for the x-pingback headers first and returns that, if available. The
 * check for the rel="pingback" has more overhead than just the header.
 *
 * @since 0.0.1
 *
 * @param string $url URL to ping.
 * @param int $deprecated Not Used.
 * @return false|string False on failure, string containing URI on success.
 */
function discover_pingback_server_uri($url, $deprecated = '')
{
    if (!empty($deprecated)) {
        _deprecated_argument(__FUNCTION__, '2.7');
    }
    $pingback_str_dquote = 'rel="pingback"';
    $pingback_str_squote = 'rel=\'pingback\'';
    /** @todo Should use Filter Extension or custom preg_match instead. */
    $parsed_url = parse_url($url);
    if (!isset($parsed_url['host'])) {
        // Not an URL. This should never happen.
        return false;
    }
    //Do not search for a pingback server on our own uploads
    $uploads_dir = hq_upload_dir();
    if (0 === strpos($url, $uploads_dir['baseurl'])) {
        return false;
    }
    $response = hq_safe_remote_head($url, array('timeout' => 2, 'httpversion' => '1.0'));
    if (is_hq_error($response)) {
        return false;
    }
    if (hq_remote_retrieve_header($response, 'x-pingback')) {
        return hq_remote_retrieve_header($response, 'x-pingback');
    }
    // Not an (x)html, sgml, or xml page, no use going further.
    if (preg_match('#(image|audio|video|model)/#is', hq_remote_retrieve_header($response, 'content-type'))) {
        return false;
    }
    // Now do a GET since we're going to look in the html headers (and we're sure it's not a binary file)
    $response = hq_safe_remote_get($url, array('timeout' => 2, 'httpversion' => '1.0'));
    if (is_hq_error($response)) {
        return false;
    }
    $contents = hq_remote_retrieve_body($response);
    $pingback_link_offset_dquote = strpos($contents, $pingback_str_dquote);
    $pingback_link_offset_squote = strpos($contents, $pingback_str_squote);
    if ($pingback_link_offset_dquote || $pingback_link_offset_squote) {
        $quote = $pingback_link_offset_dquote ? '"' : '\'';
        $pingback_link_offset = $quote == '"' ? $pingback_link_offset_dquote : $pingback_link_offset_squote;
        $pingback_href_pos = @strpos($contents, 'href=', $pingback_link_offset);
        $pingback_href_start = $pingback_href_pos + 6;
        $pingback_href_end = @strpos($contents, $quote, $pingback_href_start);
        $pingback_server_url_len = $pingback_href_end - $pingback_href_start;
        $pingback_server_url = substr($contents, $pingback_href_start, $pingback_server_url_len);
        // We may find rel="pingback" but an incomplete pingback URL
        if ($pingback_server_url_len > 0) {
            // We got it!
            return $pingback_server_url;
        }
    }
    return false;
}
Esempio n. 2
0
/**
 * Create a file in the upload folder with given content.
 *
 * If there is an error, then the key 'error' will exist with the error message.
 * If success, then the key 'file' will have the unique file path, the 'url' key
 * will have the link to the new file. and the 'error' key will be set to false.
 *
 * This function will not move an uploaded file to the upload folder. It will
 * create a new file with the content in $bits parameter. If you move the upload
 * file, read the content of the uploaded file, and then you can give the
 * filename and content to this function, which will add it to the upload
 * folder.
 *
 * The permissions will be set on the new file automatically by this function.
 *
 * @since 0.0.1
 *
 * @param string       $name       Filename.
 * @param null|string  $deprecated Never used. Set to null.
 * @param mixed        $bits       File content
 * @param string       $time       Optional. Time formatted in 'yyyy/mm'. Default null.
 * @return array
 */
function hq_upload_bits($name, $deprecated, $bits, $time = null)
{
    if (!empty($deprecated)) {
        _deprecated_argument(__FUNCTION__, '2.0');
    }
    if (empty($name)) {
        return array('error' => __('Empty filename'));
    }
    $hq_filetype = hq_check_filetype($name);
    if (!$hq_filetype['ext'] && !current_user_can('unfiltered_upload')) {
        return array('error' => __('Invalid file type'));
    }
    $upload = hq_upload_dir($time);
    if ($upload['error'] !== false) {
        return $upload;
    }
    /**
     * Filter whether to treat the upload bits as an error.
     *
     * Passing a non-array to the filter will effectively short-circuit preparing
     * the upload bits, returning that value instead.
     *
     * @since 0.0.1
     *
     * @param mixed $upload_bits_error An array of upload bits data, or a non-array error to return.
     */
    $upload_bits_error = apply_filters('hq_upload_bits', array('name' => $name, 'bits' => $bits, 'time' => $time));
    if (!is_array($upload_bits_error)) {
        $upload['error'] = $upload_bits_error;
        return $upload;
    }
    $filename = hq_unique_filename($upload['path'], $name);
    $new_file = $upload['path'] . "/{$filename}";
    if (!hq_mkdir_p(dirname($new_file))) {
        if (0 === strpos($upload['basedir'], ABSPATH)) {
            $error_path = str_replace(ABSPATH, '', $upload['basedir']) . $upload['subdir'];
        } else {
            $error_path = basename($upload['basedir']) . $upload['subdir'];
        }
        $message = sprintf(__('Unable to create directory %s. Is its parent directory writable by the server?'), $error_path);
        return array('error' => $message);
    }
    $ifp = @fopen($new_file, 'hq');
    if (!$ifp) {
        return array('error' => sprintf(__('Could not write file %s'), $new_file));
    }
    @fwrite($ifp, $bits);
    fclose($ifp);
    clearstatcache();
    // Set correct file permissions
    $stat = @stat(dirname($new_file));
    $perms = $stat['mode'] & 07777;
    $perms = $perms & 0666;
    @chmod($new_file, $perms);
    clearstatcache();
    // Compute the URL
    $url = $upload['url'] . "/{$filename}";
    return array('file' => $new_file, 'url' => $url, 'error' => false);
}
Esempio n. 3
0
/**
 * Outputs the form used by the importers to accept the data to be imported
 *
 * @since 0.0.1
 *
 * @param string $action The action attribute for the form.
 */
function hq_import_upload_form($action)
{
    /**
     * Filter the maximum allowed upload size for import files.
     *
     * @since 0.0.1
     *
     * @see hq_max_upload_size()
     *
     * @param int $max_upload_size Allowed upload size. Default 1 MB.
     */
    $bytes = apply_filters('import_upload_size_limit', hq_max_upload_size());
    $size = size_format($bytes);
    $upload_dir = hq_upload_dir();
    if (!empty($upload_dir['error'])) {
        ?>
<div class="error"><p><?php 
        _e('Before you can upload your import file, you will need to fix the following error:');
        ?>
</p>
		<p><strong><?php 
        echo $upload_dir['error'];
        ?>
</strong></p></div><?php 
    } else {
        ?>
<form enctype="multipart/form-data" id="import-upload-form" method="post" class="hq-upload-form" action="<?php 
        echo esc_url(hq_nonce_url($action, 'import-upload'));
        ?>
">
<p>
<label for="upload"><?php 
        _e('Choose a file from your computer:');
        ?>
</label> (<?php 
        printf(__('Maximum size: %s'), $size);
        ?>
)
<input type="file" id="upload" name="import" size="25" />
<input type="hidden" name="action" value="save" />
<input type="hidden" name="max_file_size" value="<?php 
        echo $bytes;
        ?>
" />
</p>
<?php 
        submit_button(__('Upload file and import'), 'button');
        ?>
</form>
<?php 
    }
}
Esempio n. 4
0
/**
 * Tries to convert an attachment URL into a post ID.
 *
 * @since 0.0.1
 *
 * @global hqdb $hqdb HiveQueen database abstraction object.
 *
 * @param string $url The URL to resolve.
 * @return int The found post ID, or 0 on failure.
 */
function attachment_url_to_postid($url)
{
    global $hqdb;
    $dir = hq_upload_dir();
    $path = $url;
    if (0 === strpos($path, $dir['baseurl'] . '/')) {
        $path = substr($path, strlen($dir['baseurl'] . '/'));
    }
    $sql = $hqdb->prepare("SELECT post_id FROM {$hqdb->postmeta} WHERE meta_key = '_hq_attached_file' AND meta_value = %s", $path);
    $post_id = $hqdb->get_var($sql);
    /**
     * Filter an attachment id found by URL.
     *
     * @since 0.0.1
     *
     * @param int|null $post_id The post_id (if any) found by the function.
     * @param string   $url     The URL being looked up.
     */
    $post_id = apply_filters('attachment_url_to_postid', $post_id, $url);
    return (int) $post_id;
}
Esempio n. 5
0
/**
 * Retrieve the URL for an attachment.
 *
 * @since 0.0.1
 *
 * @global string $pagenow
 *
 * @param int $post_id Optional. Attachment ID. Default 0.
 * @return string|false Attachment URL, otherwise false.
 */
function hq_get_attachment_url($post_id = 0)
{
    $post_id = (int) $post_id;
    if (!($post = get_post($post_id))) {
        return false;
    }
    if ('attachment' != $post->post_type) {
        return false;
    }
    $url = '';
    // Get attached file.
    if ($file = get_post_meta($post->ID, '_hq_attached_file', true)) {
        // Get upload directory.
        if (($uploads = hq_upload_dir()) && false === $uploads['error']) {
            // Check that the upload base exists in the file location.
            if (0 === strpos($file, $uploads['basedir'])) {
                // Replace file location with url location.
                $url = str_replace($uploads['basedir'], $uploads['baseurl'], $file);
            } elseif (false !== strpos($file, 'hq-content/uploads')) {
                $url = $uploads['baseurl'] . substr($file, strpos($file, 'hq-content/uploads') + 18);
            } else {
                // It's a newly-uploaded file, therefore $file is relative to the basedir.
                $url = $uploads['baseurl'] . "/{$file}";
            }
        }
    }
    /*
     * If any of the above options failed, Fallback on the GUID as used pre-2.7,
     * not recommended to rely upon this.
     */
    if (empty($url)) {
        $url = get_the_guid($post->ID);
    }
    // On SSL front-end, URLs should be HTTPS.
    if (is_ssl() && !is_admin() && 'hq-login.php' !== $GLOBALS['pagenow']) {
        $url = set_url_scheme($url);
    }
    /**
     * Filter the attachment URL.
     *
     * @since 0.0.1
     *
     * @param string $url     URL for the given attachment.
     * @param int    $post_id Attachment ID.
     */
    $url = apply_filters('hq_get_attachment_url', $url, $post->ID);
    if (empty($url)) {
        return false;
    }
    return $url;
}
Esempio n. 6
0
/**
 * Handle PHP uploads in HiveQueen, sanitizing file names, checking extensions for mime type,
 * and moving the file to the appropriate directory within the uploads directory.
 *
 * @since 0.0.1
 *
 * @see hq_handle_upload_error
 *
 * @param array       $file      Reference to a single element of $_FILES. Call the function once for each uploaded file.
 * @param array|false $overrides An associative array of names => values to override default variables. Default false.
 * @param string      $time      Time formatted in 'yyyy/mm'.
 * @param string      $action    Expected value for $_POST['action'].
 * @return array On success, returns an associative array of file attributes. On failure, returns
 *               $overrides['upload_error_handler'](&$file, $message ) or array( 'error'=>$message ).
*/
function _hq_handle_upload(&$file, $overrides, $time, $action)
{
    // The default error handler.
    if (!function_exists('hq_handle_upload_error')) {
        function hq_handle_upload_error(&$file, $message)
        {
            return array('error' => $message);
        }
    }
    /**
     * Filter the data for a file before it is uploaded to HiveQueen.
     *
     * The dynamic portion of the hook name, `$action`, refers to the post action.
     *
     * @since 0.0.1
     * @since 0.0.1
     *
     * @param array $file An array of data for a single file.
     */
    $file = apply_filters("{$action}_prefilter", $file);
    // You may define your own function and pass the name in $overrides['upload_error_handler']
    $upload_error_handler = 'hq_handle_upload_error';
    if (isset($overrides['upload_error_handler'])) {
        $upload_error_handler = $overrides['upload_error_handler'];
    }
    // You may have had one or more 'hq_handle_upload_prefilter' functions error out the file. Handle that gracefully.
    if (isset($file['error']) && !is_numeric($file['error']) && $file['error']) {
        return $upload_error_handler($file, $file['error']);
    }
    // Install user overrides. Did we mention that this voids your warranty?
    // You may define your own function and pass the name in $overrides['unique_filename_callback']
    $unique_filename_callback = null;
    if (isset($overrides['unique_filename_callback'])) {
        $unique_filename_callback = $overrides['unique_filename_callback'];
    }
    /*
     * This may not have orignially been intended to be overrideable,
     * but historically has been.
     */
    if (isset($overrides['upload_error_strings'])) {
        $upload_error_strings = $overrides['upload_error_strings'];
    } else {
        // Courtesy of php.net, the strings that describe the error indicated in $_FILES[{form field}]['error'].
        $upload_error_strings = array(false, __('The uploaded file exceeds the upload_max_filesize directive in php.ini.'), __('The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.'), __('The uploaded file was only partially uploaded.'), __('No file was uploaded.'), '', __('Missing a temporary folder.'), __('Failed to write file to disk.'), __('File upload stopped by extension.'));
    }
    // All tests are on by default. Most can be turned off by $overrides[{test_name}] = false;
    $test_form = isset($overrides['test_form']) ? $overrides['test_form'] : true;
    $test_size = isset($overrides['test_size']) ? $overrides['test_size'] : true;
    // If you override this, you must provide $ext and $type!!
    $test_type = isset($overrides['test_type']) ? $overrides['test_type'] : true;
    $mimes = isset($overrides['mimes']) ? $overrides['mimes'] : false;
    // A correct form post will pass this test.
    if ($test_form && (!isset($_POST['action']) || $_POST['action'] != $action)) {
        return call_user_func($upload_error_handler, $file, __('Invalid form submission.'));
    }
    // A successful upload will pass this test. It makes no sense to override this one.
    if (isset($file['error']) && $file['error'] > 0) {
        return call_user_func($upload_error_handler, $file, $upload_error_strings[$file['error']]);
    }
    $test_file_size = 'hq_handle_upload' === $action ? $file['size'] : filesize($file['tmp_name']);
    // A non-empty file will pass this test.
    if ($test_size && !($test_file_size > 0)) {
        if (is_multisite()) {
            $error_msg = __('File is empty. Please upload something more substantial.');
        } else {
            $error_msg = __('File is empty. Please upload something more substantial. This error could also be caused by uploads being disabled in your php.ini or by post_max_size being defined as smaller than upload_max_filesize in php.ini.');
        }
        return call_user_func($upload_error_handler, $file, $error_msg);
    }
    // A properly uploaded file will pass this test. There should be no reason to override this one.
    $test_uploaded_file = 'hq_handle_upload' === $action ? @is_uploaded_file($file['tmp_name']) : @is_file($file['tmp_name']);
    if (!$test_uploaded_file) {
        return call_user_func($upload_error_handler, $file, __('Specified file failed upload test.'));
    }
    // A correct MIME type will pass this test. Override $mimes or use the upload_mimes filter.
    if ($test_type) {
        $hq_filetype = hq_check_filetype_and_ext($file['tmp_name'], $file['name'], $mimes);
        $ext = empty($hq_filetype['ext']) ? '' : $hq_filetype['ext'];
        $type = empty($hq_filetype['type']) ? '' : $hq_filetype['type'];
        $proper_filename = empty($hq_filetype['proper_filename']) ? '' : $hq_filetype['proper_filename'];
        // Check to see if hq_check_filetype_and_ext() determined the filename was incorrect
        if ($proper_filename) {
            $file['name'] = $proper_filename;
        }
        if ((!$type || !$ext) && !current_user_can('unfiltered_upload')) {
            return call_user_func($upload_error_handler, $file, __('Sorry, this file type is not permitted for security reasons.'));
        }
        if (!$type) {
            $type = $file['type'];
        }
    } else {
        $type = '';
    }
    /*
     * A writable uploads dir will pass this test. Again, there's no point
     * overriding this one.
     */
    if (!(($uploads = hq_upload_dir($time)) && false === $uploads['error'])) {
        return call_user_func($upload_error_handler, $file, $uploads['error']);
    }
    $filename = hq_unique_filename($uploads['path'], $file['name'], $unique_filename_callback);
    // Move the file to the uploads dir.
    $new_file = $uploads['path'] . "/{$filename}";
    if ('hq_handle_upload' === $action) {
        $move_new_file = @move_uploaded_file($file['tmp_name'], $new_file);
    } else {
        $move_new_file = @rename($file['tmp_name'], $new_file);
    }
    if (false === $move_new_file) {
        if (0 === strpos($uploads['basedir'], ABSPATH)) {
            $error_path = str_replace(ABSPATH, '', $uploads['basedir']) . $uploads['subdir'];
        } else {
            $error_path = basename($uploads['basedir']) . $uploads['subdir'];
        }
        return $upload_error_handler($file, sprintf(__('The uploaded file could not be moved to %s.'), $error_path));
    }
    // Set correct file permissions.
    $stat = stat(dirname($new_file));
    $perms = $stat['mode'] & 0666;
    @chmod($new_file, $perms);
    // Compute the URL.
    $url = $uploads['url'] . "/{$filename}";
    if (is_multisite()) {
        delete_transient('dirsize_cache');
    }
    /**
     * Filter the data array for the uploaded file.
     *
     * @since 0.0.1
     *
     * @param array  $upload {
     *     Array of upload data.
     *
     *     @type string $file Filename of the newly-uploaded file.
     *     @type string $url  URL of the uploaded file.
     *     @type string $type File type.
     * }
     * @param string $context The type of upload action. Values include 'upload' or 'sideload'.
     */
    return apply_filters('hq_handle_upload', array('file' => $new_file, 'url' => $url, 'type' => $type), 'hq_handle_sideload' === $action ? 'sideload' : 'upload');
}