Create New Item
×
Item Type
File
Folder
Item Name
×
Search file in folder and subfolders...
File Manager
/
wp-content
/
plugins
/
woocommerce
/
includes
Advanced Search
Upload
New Item
Settings
Back
Back Up
Advanced Editor
Save
<?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();