<?php /** * Manage file downloading * * @category PHP * @package VenoFileManager * @author Nicola Franchini <info@veno.it> * @license Exclusively sold on CodeCanyon * @link http://filemanager.veno.it/ */ if (!class_exists('Downloader', false)) { /** * Downloader class * * @category PHP * @package VenoFileManager * @author Nicola Franchini <info@veno.it> * @license Exclusively sold on CodeCanyon * @link http://filemanager.veno.it/ */ class Downloader { /** * Checks if file is under user folder * * @param string $checkPath path to check * * @return true/false */ public function subDir($checkPath) { global $gateKeeper; if ($gateKeeper->getUserInfo('dir') == null) { return true; } else { $userdirs = json_decode($gateKeeper->getUserInfo('dir'), true); foreach ($userdirs as $value) { $pos = strpos($checkPath, $value); if ($pos !== false) { return true; } } } return false; } /** * The safe way * * @param string $checkfile file to check * @param string $path relative path to call the functionf from /ajax/ * * @return true/false */ public function checkFile($checkfile, $path = '') { global $setUp; $fileclean = ltrim(base64_decode($checkfile), './'); $file = $path.'../'.ltrim(urldecode($fileclean), './'); $filepathinfo = Utils::mbPathinfo($fileclean); $filename = $filepathinfo['basename']; $safedir = $filepathinfo['dirname']; $safedir = str_replace(array('/', '.'), '', $safedir); $realfile = realpath($file); $realsetup = realpath($path.'.'.$setUp->getConfig('starting_dir')); $avoidDir = array('vfm-admin', 'etc'); // $avoidFile = array('index.php', 'vfm-thumb.php', '.htaccess', '.htpasswd'); $avoidFile = $setUp->getConfig('hidden_files'); if (strpos($realfile, $realsetup) !== false && !in_array($safedir, $avoidDir) && !in_array($filename, $avoidFile) && file_exists($file) ) { return true; } return false; } /** * Check download lifetime * * @param string $time time to check * @param integer $lifedays days total * * @return true/false */ public function checkTime($time, $lifedays = false) { global $setUp; $lifedays = $lifedays ? (int)$lifedays : (int)$setUp->getConfig('lifetime'); $lifetime = 86400 * $lifedays; if (time() <= $time + $lifetime) { return true; } return false; } /** * Get file info before processing download * * @param string $getfile file to download * @param string $playmp3 check audio * * @return $headers array */ public function getHeaders($getfile, $playmp3 = false) { $headers = array(); $audiofiles = array('mp3','wav', 'flac', 'aac'); $trackfile = './'.urldecode(base64_decode($getfile)); $file = '.'.$trackfile; $filepathinfo = Utils::mbPathinfo($file); $filename = $filepathinfo['basename']; $dirname = $filepathinfo['dirname'].'/'; $ext = $filepathinfo['extension']; $file_size = Utils::getFileSize($file); // $disposition = 'inline'; $disposition = 'attachment'; $content_type = 'application/force-download'; if (strtolower($ext) == 'pdf') { $content_type = 'application/pdf'; $disposition = 'inline'; } if (strtolower($ext) == 'zip') { $content_type = 'application/zip'; } if (in_array(strtolower($ext), $audiofiles) && $playmp3 == 'play') { $content_type = 'audio/'.strtolower($ext); $disposition = 'inline'; } $headers['file'] = $file; $headers['filename'] = $filename; $headers['file_size'] = $file_size; $headers['content_type'] = $content_type; $headers['disposition'] = $disposition; $headers['trackfile'] = $trackfile; $headers['dirname'] = $dirname; return $headers; } /** * Download files * * @param string $file path to download * @param string $filename file name * @param string $file_size file size * @param string $content_type header content type * @param string $disposition header disposition * @param bool $android android device * * @return file served */ public function download( $file, $filename, $file_size, $content_type, $disposition = 'inline', $android = false ) { // Gzip enabled may set the wrong file size. if (function_exists('apache_setenv')) { @apache_setenv('no-gzip', 1); } if (ini_get('zlib.output_compression')) { @ini_set('zlib.output_compression', 'Off'); } @set_time_limit(0); session_write_close(); header("Content-Length: ".$file_size); if ($android) { header("Content-Type: application/octet-stream"); header("Content-Disposition: attachment; filename=\"".$filename."\""); } else { header("Content-Type: $content_type"); header("Content-Disposition: $disposition; filename=\"".$filename."\""); // header("Content-Transfer-Encoding: binary"); header("Expires: -1"); } if (ob_get_level()) { ob_end_clean(); } $handle = fopen($file, 'rb'); if ($handle !== false && $file_size > 0) { @flock($handle, LOCK_SH); $start = 0; $end = $file_size - 1; $chunk = 8 * 1024; $requested = (float)$end - (float)$start + 1; $error = false; while (!$error) { if ($chunk >= $requested) { $chunk = (integer)$requested; } while (!feof($handle) && (connection_status() === 0)) { if (!$buffer = @fread($handle, $chunk)) { $error = true; break 2; } print($buffer); flush(); } @flock($handle, LOCK_UN); @fclose($handle); break; } if ($error) { // 500 - Internal server error exit; } } /* Deprecated method, connection error with very large files */ // readfile($file); return true; } } }