static function SendFile($file_path, $args = array()) { global $wpdb; $defaults = array('bandwidth' => 0, 'etag' => null, 'force_download' => WPFB_Core::$settings->force_download, 'cache_max_age' => 0, 'md5_hash' => null, 'filename' => null); extract(wp_parse_args($args, $defaults), EXTR_SKIP); @ini_set('max_execution_time', '0'); @set_time_limit(0); @error_reporting(0); while (@ob_end_clean()) { } $no_cache = WPFB_Core::$settings->http_nocache && $cache_max_age != 0; @ini_set("zlib.output_compression", "Off"); // remove some headers if (function_exists('header_remove')) { header_remove(); } else { header("Expires: "); header("X-Pingback: "); } if (!@file_exists($file_path) || !is_file($file_path)) { header('HTTP/1.x 404 Not Found'); wp_die('File ' . basename($file_path) . ' not found!'); } wpfb_loadclass('FileUtils'); $size = WPFB_FileUtils::GetFileSize($file_path); $time = filemtime($file_path); $file_type = WPFB_Download::GetFileType($file_path); if (empty($etag)) { $etag = md5("{$size}|{$time}|{$file_type}"); } else { $etag = trim($etag, '"'); } // set basic headers if ($no_cache) { header("Cache-Control: no-cache, must-revalidate, max-age=0"); header("Pragma: no-cache"); header("Expires: Wed, 11 Jan 1984 05:00:00 GMT"); } elseif ($cache_max_age > 0) { header("Cache-Control: must-revalidate, max-age={$cache_max_age}"); } elseif ($cache_max_age == -1) { header("Cache-Control: public"); } //header("Connection: close"); //header("Keep-Alive: timeout=5, max=100"); //header("Connection: Keep-Alive"); header("Content-Type: " . $file_type . (strpos($file_type, 'text/') !== false ? '; charset=' : '')); // charset fix header("Last-Modified: " . gmdate("D, d M Y H:i:s", $no_cache ? time() : $time) . " GMT"); if (!empty($md5_hash) && $md5_hash[0] != '#') { // check if fake md5 $pmd5 = @pack('H32', $md5_hash); if (!empty($pmd5)) { header("Content-MD5: " . @base64_encode($pmd5)); } } if (!$no_cache) { header("ETag: \"{$etag}\""); $if_mod_since = !empty($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? $_SERVER['HTTP_IF_MODIFIED_SINCE'] : false; $if_none_match = !empty($_SERVER['HTTP_IF_NONE_MATCH']) ? $etag == trim($_SERVER['HTTP_IF_NONE_MATCH'], '"') : false; if ($if_mod_since || $if_none_match) { $not_modified = true; if ($not_modified && $if_mod_since) { $not_modified = @strtotime($if_mod_since) >= $time; } if ($not_modified && $if_none_match) { $not_modified = $if_none_match == $etag; } if ($not_modified) { header("Content-Length: " . $size); header("HTTP/1.x 304 Not Modified"); exit; } } } if (!($fh = @fopen($file_path, 'rb'))) { wp_die(__('Could not read file!', 'wp-filebase')); } list($begin, $end) = self::ParseRangeHeader($size); if ($begin > 0 || $end < $size - 1) { header('HTTP/1.0 206 Partial Content'); header("Content-Range: bytes {$begin}-{$end}/{$size}"); } else { header('HTTP/1.0 200 OK'); } $length = $end - $begin + 1; WPFB_Download::AddTraffic($length); if (self::ShouldSendRangeHeader($file_path, $file_type)) { header("Accept-Ranges: bytes"); } $request_file_name = basename(urldecode(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH))); $filename_set = !empty($filename); if (!$filename_set) { $filename = basename($file_path); } // content headers if ($force_download) { header("Content-Disposition: attachment; filename=\"{$filename}\""); header("Content-Description: File Transfer"); } elseif ($filename != $request_file_name) { header("Content-Disposition: inline; filename=\"{$filename}\""); } header("Content-Length: " . $length); // clean up things that are not needed for download @session_write_close(); // disable blocking of multiple downloads at the same time // close db connection if (method_exists($wpdb, 'close')) { $wpdb->close(); } elseif (function_exists('mysql_close')) { if (!empty($wpdb->dbh) && is_resource($wpdb->dbh)) { @mysql_close($wpdb->dbh); } else { @mysql_close(); } } @ob_flush(); @flush(); // ready to send the file! if ($begin > 0) { fseek($fh, $begin, 0); } if (WPFB_Core::$settings->use_fpassthru) { fpassthru($fh); } else { $bandwidth = empty($bandwidth) ? 0 : (double) $bandwidth; if ($bandwidth <= 0) { $bandwidth = 1024 * 1024; } $buffer_size = (int) (1024 * min($bandwidth, 64)); // convert kib/s => bytes/ms $bandwidth *= 1024 / 1000; $cur = $begin; while (!@feof($fh) && $cur <= $end && @connection_status() == 0) { $nbytes = min($buffer_size, $end - $cur + 1); $ts = microtime(true); print @fread($fh, $nbytes); @ob_flush(); @flush(); $dt = (microtime(true) - $ts) * 1000; // dt = time delta in ms $st = $nbytes / $bandwidth - $dt; if ($st > 0) { usleep($st * 1000); } $cur += $nbytes; } } @fclose($fh); return true; }
static function GetRemoteFileInfo($url, $follow_redirects = 5) { wpfb_loadclass('Download'); if (parse_url($url, PHP_URL_SCHEME) === 'file' && is_readable($url)) { return array('name' => basename($url), 'size' => filesize($url), 'type' => WPFB_Download::GetFileType($url), 'time' => filemtime($url)); } $info = array(); $path = parse_url($url, PHP_URL_PATH); require_once ABSPATH . WPINC . "/http.php"; $response = wp_remote_head($url, array_merge(array('timeout' => 10))); if (is_wp_error($response)) { return $response; } $headers = wp_remote_retrieve_headers($response); if (empty($headers)) { return new WP_Error('get_remote_file_info', 'Headers not set!'); } if ($response['response']['code'] >= 300 && $response['response']['code'] <= 399) { if (empty($headers['location'])) { return new WP_Error('get_remote_file_info', "HTTP {$response['code']} but no location header!"); } if ($follow_redirects > 0) { return self::GetRemoteFileInfo($headers['location'], $follow_redirects - 1); } $info['location'] = $headers['location']; } $info['size'] = isset($headers['content-length']) ? $headers['content-length'] : -1; $info['type'] = isset($headers['content-type']) ? strtolower($headers['content-type']) : null; if (($p = strpos($info['type'], ';')) > 0) { $info['type'] = substr($info['type'], 0, $p); } $info['time'] = isset($headers['last-modified']) ? @strtotime($headers['last-modified']) : 0; $info['etag'] = isset($headers['etag']) ? trim($headers['etag'], '"') : ''; $info['_response'] = $response; // check for filename header if (!empty($headers['content-disposition'])) { $matches = array(); if (preg_match('/filename="?([^"]+)"?/', $headers['content-disposition'], $matches) == 1) { $info['name'] = $matches[1]; } } if (empty($info['name'])) { $info['name'] = basename($path); } // compare extension type with http header content-type, if they are different deterime proper extension from http content-type $exType = WPFB_Download::GetFileType($info['name']); if ($exType != $info['type'] && ($e = WPFB_Download::FileType2Ext($info['type'])) != null) { $info['name'] .= '.' . $e; } return $info; }
static function GetRemoteFileInfo($url) { wpfb_loadclass('Download'); if (parse_url($url, PHP_URL_SCHEME) === 'file' && is_readable($url)) { return array('name' => basename($url), 'size' => filesize($url), 'type' => WPFB_Download::GetFileType($url), 'time' => filemtime($url)); } $info = array(); $path = parse_url($url, PHP_URL_PATH); $headers = self::HttpGetHeaders($url); if (empty($headers)) { return null; } $info['size'] = isset($headers['content-length']) ? $headers['content-length'] : -1; $info['type'] = isset($headers['content-type']) ? strtolower($headers['content-type']) : null; $info['time'] = isset($headers['last-modified']) ? @strtotime($headers['last-modified']) : 0; // check for filename header if (!empty($headers['content-disposition'])) { $matches = array(); if (preg_match('/filename="(.+)"/', $headers['content-disposition'], $matches) == 1) { $info['name'] = $matches[1]; } } if (empty($info['name'])) { $info['name'] = basename($path); } // compare extension type with http header content-type, if they are different deterime proper extension from http content-type $exType = WPFB_Download::GetFileType($info['name']); if ($exType != $info['type'] && ($e = WPFB_Download::FileType2Ext($info['type'])) != null) { $info['name'] .= '.' . $e; } return $info; }
static function GetRemoteFileInfo($url) { wpfb_loadclass('Download'); if (parse_url($url, PHP_URL_SCHEME) === 'file' && is_readable($url)) { return array('name' => basename($url), 'size' => filesize($url), 'type' => WPFB_Download::GetFileType($url), 'time' => filemtime($url)); } $info = array(); $path = parse_url($url, PHP_URL_PATH); require_once ABSPATH . WPINC . "/http.php"; $response = wp_remote_head($url, array('timeout' => 10)); if (is_wp_error($response)) { return $response; } $headers = wp_remote_retrieve_headers($response); if (empty($headers)) { return new WP_Error('get_remote_file_info', 'Headers not set!'); } $info['size'] = isset($headers['content-length']) ? $headers['content-length'] : -1; $info['type'] = isset($headers['content-type']) ? strtolower($headers['content-type']) : null; $info['time'] = isset($headers['last-modified']) ? @strtotime($headers['last-modified']) : 0; // check for filename header if (!empty($headers['content-disposition'])) { $matches = array(); if (preg_match('/filename="(.+)"/', $headers['content-disposition'], $matches) == 1) { $info['name'] = $matches[1]; } } if (empty($info['name'])) { $info['name'] = basename($path); } // compare extension type with http header content-type, if they are different deterime proper extension from http content-type $exType = WPFB_Download::GetFileType($info['name']); if ($exType != $info['type'] && ($e = WPFB_Download::FileType2Ext($info['type'])) != null) { $info['name'] .= '.' . $e; } return $info; }