File "class-wc-download-handler.php"

Full path: /home/kosmetik/public_html/wp-content/plugins/woocommerce/includes/class-wc-download-handler.php
File size: 17.13 B
MIME-type: text/x-php
Charset: utf-8

Download   Open   Edit   Advanced Editor   Back

<?php

defined('ABSPATH') || exit;
class WC_Download_Handler
{
    public static function init()
    {
        if (isset($_GET['download_file'], $_GET['order']) && (isset($_GET['email']) || isset($_GET['uid']))) {
            add_action('init', array(__CLASS__, 'download_product'));
        }
        add_action('woocommerce_download_file_redirect', array(__CLASS__, 'download_file_redirect'), 10, 2);
        add_action('woocommerce_download_file_xsendfile', array(__CLASS__, 'download_file_xsendfile'), 10, 2);
        add_action('woocommerce_download_file_force', array(__CLASS__, 'download_file_force'), 10, 2);
    }
    public static function download_product()
    {
        $product_id = absint($_GET['download_file']);
        $product = wc_get_product($product_id);
        $data_store = WC_Data_Store::load('customer-download');
        if (!$product || empty($_GET['key']) || empty($_GET['order'])) {
            self::download_error(__('Invalid download link.', 'woocommerce'));
        }
        if (empty($_GET['email']) && empty($_GET['uid'])) {
            self::download_error(__('Invalid download link.', 'woocommerce'));
        }
        $order_id = wc_get_order_id_by_order_key(wc_clean(wp_unslash($_GET['order'])));
        $order = wc_get_order($order_id);
        if (isset($_GET['email'])) {
            $email_address = wp_unslash($_GET['email']);
        } else {
            $email_address = is_a($order, 'WC_Order') ? $order->get_billing_email() : null;
            $email_hash = function_exists('hash') ? hash('sha256', $email_address) : sha1($email_address);
            if (is_null($email_address) || !hash_equals(wp_unslash($_GET['uid']), $email_hash)) {
                self::download_error(__('Invalid download link.', 'woocommerce'));
            }
        }
        $download_ids = $data_store->get_downloads(array('user_email' => sanitize_email(str_replace(' ', '+', $email_address)), 'order_key' => wc_clean(wp_unslash($_GET['order'])), 'product_id' => $product_id, 'download_id' => wc_clean(preg_replace('/\\s+/', ' ', wp_unslash($_GET['key']))), 'orderby' => 'downloads_remaining', 'order' => 'DESC', 'limit' => 1, 'return' => 'ids'));
        if (empty($download_ids)) {
            self::download_error(__('Invalid download link.', 'woocommerce'));
        }
        $download = new WC_Customer_Download(current($download_ids));
        $file_path = apply_filters('woocommerce_download_product_filepath', $product->get_file_download_path($download->get_download_id()), $email_address, $order, $product, $download);
        $parsed_file_path = self::parse_file_path($file_path);
        $download_range = self::get_download_range(@filesize($parsed_file_path['file_path']));
        self::check_order_is_valid($download);
        if (!$download_range['is_range_request']) {
            self::check_downloads_remaining($download);
        }
        self::check_download_expiry($download);
        self::check_download_login_required($download);
        do_action('woocommerce_download_product', $download->get_user_email(), $download->get_order_key(), $download->get_product_id(), $download->get_user_id(), $download->get_download_id(), $download->get_order_id());
        $download->save();
        $current_user_id = get_current_user_id();
        $ip_address = WC_Geolocation::get_ip_address();
        if (!$download_range['is_range_request']) {
            $download->track_download($current_user_id > 0 ? $current_user_id : null, !empty($ip_address) ? $ip_address : null);
        }
        self::download($file_path, $download->get_product_id());
    }
    private static function check_order_is_valid($download)
    {
        if ($download->get_order_id()) {
            $order = wc_get_order($download->get_order_id());
            if ($order && !$order->is_download_permitted()) {
                self::download_error(__('Invalid order.', 'woocommerce'), '', 403);
            }
        }
    }
    private static function check_downloads_remaining($download)
    {
        if ('' !== $download->get_downloads_remaining() && 0 >= $download->get_downloads_remaining()) {
            self::download_error(__('Sorry, you have reached your download limit for this file', 'woocommerce'), '', 403);
        }
    }
    private static function check_download_expiry($download)
    {
        if (!is_null($download->get_access_expires()) && $download->get_access_expires()->getTimestamp() < strtotime('midnight', time())) {
            self::download_error(__('Sorry, this download has expired', 'woocommerce'), '', 403);
        }
    }
    private static function check_download_login_required($download)
    {
        if ($download->get_user_id() && 'yes' === get_option('woocommerce_downloads_require_login')) {
            if (!is_user_logged_in()) {
                if (wc_get_page_id('myaccount')) {
                    wp_safe_redirect(add_query_arg('wc_error', rawurlencode(__('You must be logged in to download files.', 'woocommerce')), wc_get_page_permalink('myaccount')));
                    exit;
                } else {
                    self::download_error(__('You must be logged in to download files.', 'woocommerce') . ' <a href="' . esc_url(wp_login_url(wc_get_page_permalink('myaccount'))) . '" class="wc-forward">' . __('Login', 'woocommerce') . '</a>', __('Log in to Download Files', 'woocommerce'), 403);
                }
            } elseif (!current_user_can('download_file', $download)) {
                self::download_error(__('This is not your download link.', 'woocommerce'), '', 403);
            }
        }
    }
    public static function count_download($download_data)
    {
        wc_deprecated_function('WC_Download_Handler::count_download', '4.4.0', '');
    }
    public static function download($file_path, $product_id)
    {
        if (!$file_path) {
            self::download_error(__('No file defined', 'woocommerce'));
        }
        $filename = basename($file_path);
        if (strstr($filename, '?')) {
            $filename = current(explode('?', $filename));
        }
        $filename = apply_filters('woocommerce_file_download_filename', $filename, $product_id);
        $file_download_method = apply_filters('woocommerce_file_download_method', get_option('woocommerce_file_download_method', 'force'), $product_id, $file_path);
        add_action('nocache_headers', array(__CLASS__, 'ie_nocache_headers_fix'));
        do_action('woocommerce_download_file_' . $file_download_method, $file_path, $filename);
    }
    public static function download_file_redirect($file_path, $filename = '')
    {
        header('Location: ' . $file_path);
        exit;
    }
    public static function parse_file_path($file_path)
    {
        $wp_uploads = wp_upload_dir();
        $wp_uploads_dir = $wp_uploads['basedir'];
        $wp_uploads_url = $wp_uploads['baseurl'];
        $replacements = array($wp_uploads_url => $wp_uploads_dir, network_site_url('/', 'https') => ABSPATH, str_replace('https:', 'http:', network_site_url('/', 'http')) => ABSPATH, site_url('/', 'https') => ABSPATH, str_replace('https:', 'http:', site_url('/', 'http')) => ABSPATH);
        $file_path = str_replace(array_keys($replacements), array_values($replacements), $file_path);
        $parsed_file_path = wp_parse_url($file_path);
        $remote_file = true;
        if ('//' === substr($file_path, 0, 2)) {
            return array('remote_file' => true, 'file_path' => is_ssl() ? 'https:' . $file_path : 'http:' . $file_path);
        }
        if (file_exists(ABSPATH . $file_path)) {
            $remote_file = false;
            $file_path = ABSPATH . $file_path;
        } elseif ('/wp-content' === substr($file_path, 0, 11)) {
            $remote_file = false;
            $file_path = realpath(WP_CONTENT_DIR . substr($file_path, 11));
        } elseif ((!isset($parsed_file_path['scheme']) || !in_array($parsed_file_path['scheme'], array('http', 'https', 'ftp'), true)) && isset($parsed_file_path['path']) && file_exists($parsed_file_path['path'])) {
            $remote_file = false;
            $file_path = $parsed_file_path['path'];
        }
        return array('remote_file' => $remote_file, 'file_path' => $file_path);
    }
    public static function download_file_xsendfile($file_path, $filename)
    {
        $parsed_file_path = self::parse_file_path($file_path);
        if ($parsed_file_path['remote_file'] && !apply_filters('woocommerce_use_xsendfile_for_remote', false)) {
            do_action('woocommerce_download_file_force', $file_path, $filename);
            return;
        }
        if (function_exists('apache_get_modules') && in_array('mod_xsendfile', apache_get_modules(), true)) {
            self::download_headers($parsed_file_path['file_path'], $filename);
            $filepath = apply_filters('woocommerce_download_file_xsendfile_file_path', $parsed_file_path['file_path'], $file_path, $filename, $parsed_file_path);
            header('X-Sendfile: ' . $filepath);
            exit;
        } elseif (stristr(getenv('SERVER_SOFTWARE'), 'lighttpd')) {
            self::download_headers($parsed_file_path['file_path'], $filename);
            $filepath = apply_filters('woocommerce_download_file_xsendfile_lighttpd_file_path', $parsed_file_path['file_path'], $file_path, $filename, $parsed_file_path);
            header('X-Lighttpd-Sendfile: ' . $filepath);
            exit;
        } elseif (stristr(getenv('SERVER_SOFTWARE'), 'nginx') || stristr(getenv('SERVER_SOFTWARE'), 'cherokee')) {
            self::download_headers($parsed_file_path['file_path'], $filename);
            $xsendfile_path = trim(preg_replace('`^' . str_replace('\\', '/', getcwd()) . '`', '', $parsed_file_path['file_path']), '/');
            $xsendfile_path = apply_filters('woocommerce_download_file_xsendfile_x_accel_redirect_file_path', $xsendfile_path, $file_path, $filename, $parsed_file_path);
            header("X-Accel-Redirect: /{$xsendfile_path}");
            exit;
        }
        wc_get_logger()->warning(sprintf(__('%1$s could not be served using the X-Accel-Redirect/X-Sendfile method. A Force Download will be used instead.', 'woocommerce'), $file_path));
        self::download_file_force($file_path, $filename);
    }
    protected static function get_download_range($file_size)
    {
        $start = 0;
        $download_range = array('start' => $start, 'is_range_valid' => false, 'is_range_request' => false);
        if (!$file_size) {
            return $download_range;
        }
        $end = $file_size - 1;
        $download_range['length'] = $file_size;
        if (isset($_SERVER['HTTP_RANGE'])) {
            $http_range = sanitize_text_field(wp_unslash($_SERVER['HTTP_RANGE']));
            $download_range['is_range_request'] = true;
            $c_start = $start;
            $c_end = $end;
            list(, $range) = explode('=', $http_range, 2);
            if (strpos($range, ',') !== false) {
                return $download_range;
            }
            if ('-' === $range[0]) {
                $c_start = $file_size - substr($range, 1);
            } else {
                $range = explode('-', $range);
                $c_start = isset($range[0]) && is_numeric($range[0]) ? (int) $range[0] : 0;
                $c_end = isset($range[1]) && is_numeric($range[1]) ? (int) $range[1] : $file_size;
            }
            $c_end = $c_end > $end ? $end : $c_end;
            if ($c_start > $c_end || $c_start > $file_size - 1 || $c_end >= $file_size) {
                return $download_range;
            }
            $start = $c_start;
            $end = $c_end;
            $length = $end - $start + 1;
            $download_range['start'] = $start;
            $download_range['length'] = $length;
            $download_range['is_range_valid'] = true;
        }
        return $download_range;
    }
    public static function download_file_force($file_path, $filename)
    {
        $parsed_file_path = self::parse_file_path($file_path);
        $download_range = self::get_download_range(@filesize($parsed_file_path['file_path']));
        self::download_headers($parsed_file_path['file_path'], $filename, $download_range);
        $start = isset($download_range['start']) ? $download_range['start'] : 0;
        $length = isset($download_range['length']) ? $download_range['length'] : 0;
        if (!self::readfile_chunked($parsed_file_path['file_path'], $start, $length)) {
            if ($parsed_file_path['remote_file'] && 'yes' === get_option('woocommerce_downloads_redirect_fallback_allowed')) {
                wc_get_logger()->warning(sprintf(__('%1$s could not be served using the Force Download method. A redirect will be used instead.', 'woocommerce'), $file_path));
                self::download_file_redirect($file_path);
            } else {
                self::download_error(__('File not found', 'woocommerce'));
            }
        }
        exit;
    }
    private static function get_download_content_type($file_path)
    {
        $file_extension = strtolower(substr(strrchr($file_path, '.'), 1));
        $ctype = 'application/force-download';
        foreach (get_allowed_mime_types() as $mime => $type) {
            $mimes = explode('|', $mime);
            if (in_array($file_extension, $mimes, true)) {
                $ctype = $type;
                break;
            }
        }
        return $ctype;
    }
    private static function download_headers($file_path, $filename, $download_range = array())
    {
        self::check_server_config();
        self::clean_buffers();
        wc_nocache_headers();
        header('X-Robots-Tag: noindex, nofollow', true);
        header('Content-Type: ' . self::get_download_content_type($file_path));
        header('Content-Description: File Transfer');
        header('Content-Disposition: attachment; filename="' . $filename . '";');
        header('Content-Transfer-Encoding: binary');
        $file_size = @filesize($file_path);
        if (!$file_size) {
            return;
        }
        if (isset($download_range['is_range_request']) && true === $download_range['is_range_request']) {
            if (false === $download_range['is_range_valid']) {
                header('HTTP/1.1 416 Requested Range Not Satisfiable');
                header('Content-Range: bytes 0-' . ($file_size - 1) . '/' . $file_size);
                exit;
            }
            $start = $download_range['start'];
            $end = $download_range['start'] + $download_range['length'] - 1;
            $length = $download_range['length'];
            header('HTTP/1.1 206 Partial Content');
            header("Accept-Ranges: 0-{$file_size}");
            header("Content-Range: bytes {$start}-{$end}/{$file_size}");
            header("Content-Length: {$length}");
        } else {
            header('Content-Length: ' . $file_size);
        }
    }
    private static function check_server_config()
    {
        wc_set_time_limit(0);
        if (function_exists('apache_setenv')) {
            @apache_setenv('no-gzip', 1);
        }
        @ini_set('zlib.output_compression', 'Off');
        @session_write_close();
    }
    private static function clean_buffers()
    {
        if (ob_get_level()) {
            $levels = ob_get_level();
            for ($i = 0; $i < $levels; $i++) {
                @ob_end_clean();
            }
        } else {
            @ob_end_clean();
        }
    }
    public static function readfile_chunked($file, $start = 0, $length = 0)
    {
        if (!defined('WC_CHUNK_SIZE')) {
            define('WC_CHUNK_SIZE', 1024 * 1024);
        }
        $handle = @fopen($file, 'r');
        if (false === $handle) {
            return false;
        }
        if (!$length) {
            $length = @filesize($file);
        }
        $read_length = (int) WC_CHUNK_SIZE;
        if ($length) {
            $end = $start + $length - 1;
            @fseek($handle, $start);
            $p = @ftell($handle);
            while (!@feof($handle) && $p <= $end) {
                if ($p + $read_length > $end) {
                    $read_length = $end - $p + 1;
                }
                echo @fread($handle, $read_length);
                $p = @ftell($handle);
                if (ob_get_length()) {
                    ob_flush();
                    flush();
                }
            }
        } else {
            while (!@feof($handle)) {
                echo @fread($handle, $read_length);
                if (ob_get_length()) {
                    ob_flush();
                    flush();
                }
            }
        }
        return @fclose($handle);
    }
    public static function ie_nocache_headers_fix($headers)
    {
        if (is_ssl() && !empty($GLOBALS['is_IE'])) {
            $headers['Cache-Control'] = 'private';
            unset($headers['Pragma']);
        }
        return $headers;
    }
    private static function download_error($message, $title = '', $status = 404)
    {
        header('Content-Type: ' . get_option('html_type') . '; charset=' . get_option('blog_charset'));
        header_remove('Content-Description;');
        header_remove('Content-Disposition');
        header_remove('Content-Transfer-Encoding');
        if (!strstr($message, '<a ')) {
            $message .= ' <a href="' . esc_url(wc_get_page_permalink('shop')) . '" class="wc-forward">' . esc_html__('Go to shop', 'woocommerce') . '</a>';
        }
        wp_die($message, $title, array('response' => $status));
    }
}
WC_Download_Handler::init();