<?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;
}
}
}