<?php
/**
* Add a file to the personal storage of a user by downloading it from the network
* @package phlyMail Nahariya 4.0+ Default Branch
* @subpackage Files handler
* @copyright 2005-2010 phlyLabs, Berlin (http://phlylabs.de)
* @version 4.0.6 2010-11-08
*/
// Only valid within phlyMail
if (!defined('_IN_PHM_')) die();
// We got to have the upload_tmp_dir set to something useful
if (!ini_get('upload_tmp_dir')) ini_set('upload_tmp_dir', $_PM_['path']['storage'].'/'.$_SESSION['phM_uid'].'/files/.tmp');
$uplIDName = 'DOWNLOAD_IDENTIFIER';
/**
* Frontend requests download progress information
* This requires either APCs implementation or the PECL extension uploadprogress,
* you can easily get the PECL one with "pecl install uploadprogress", APC
* is recommended for caching purposes
*/
if (isset($_REQUEST['uplInf']) && $_REQUEST['uplInf']) {
$uid = $_SESSION['phM_uid'];
session_write_close();
$nfo = basename($_REQUEST['uplInf']);
$info = array('time_start' => 0, 'time_last' => 0, 'speed_average' => 0
,'speed_last' => 0, 'bytes_uploaded' => 0, 'bytes_total' => 0
,'files_uploaded' => 0, 'est_sec' => 0);
if (false !== ($ulinfo = @file_get_contents($_PM_['path']['storage'].'/'.$uid.'/files/.tmp/'.$nfo.'.dnl'))) {
$ulinfo = explode(';', $ulinfo);
if (is_array($ulinfo) && isset($ulinfo[3])) {
$rate = ($ulinfo[0]-$ulinfo[1] != 0) ? $ulinfo[3]/($ulinfo[0]-$ulinfo[1]) : 0;
$info = array('bytes_uploaded' => $ulinfo[3], 'bytes_total' => $ulinfo[2]
,'time_start' => $ulinfo[0], 'time_last' => $ulinfo[1]
,'est_sec' => ($rate != 0 && $ulinfo[3] != 0 && $ulinfo[2] != 0) ? ($ulinfo[2]-$ulinfo[3])/$rate : 0
,'speed_average' => $rate
);
}
}
$info['field'] = $nfo;
sendJS(array('upload_stats' => $info), 1, 1);
}
if (!isset($_PM_files_iamincluded)) {
$tpl = new fxl_cached_template($_PM_['path']['frontend'].'/templates/files.getfromurl.tpl', $_PM_['path']['tplcache'].'files.getfromurl.tpl');
require_once($_PM_['path']['handler'].'/files/fs.php');
$FS = new files_storage($_SESSION['phM_uid']);
require_once($_PM_['path']['lib'].'/phm_mime_handler.php');
$MIME = new phm_mime_handler($_PM_['path']['conf'].'/mime.map.wpop');
}
$defaultFolder = (isset($_SESSION['files_workfolder']) && $_SESSION['files_workfolder']) ? $_SESSION['files_workfolder'] : false;
$destfolder = (isset($_REQUEST['destfolder'])) ? intval($_REQUEST['destfolder']) : $defaultFolder;
if (isset($_REQUEST['destfolder'])) {
$uploadname = basename($_REQUEST[$uplIDName]);
$destinfo = $FS->get_folder_info($_REQUEST['destfolder']);
$destpath = $_PM_['path']['storage'].'/'.$_SESSION['phM_uid'].'/files/'.$destinfo['folder_path'].'/'.$uploadname;
$ulinfo = $_PM_['path']['storage'].'/'.$_SESSION['phM_uid'].'/files/.tmp/'.$uploadname.'.dnl';
$stat = download($_REQUEST['file'], $destpath, $ulinfo, 1073741824); // Replace max size with user's quota limit
switch ($stat['error']) {
case UPLOAD_ERR_INI_SIZE: $error = 'The file was too large.'; break;
case UPLOAD_ERR_PARTIAL: $error = 'The file was only partially downloaded.'; break;
case UPLOAD_ERR_NO_FILE: $error = 'Could not download the file'; break;
case UPLOAD_ERR_CANT_WRITE: $error = 'Failed to write file to disk'; break;
}
list ($type) = $MIME->get_type_from_name($stat['name'], false);
if (!$type) $type = ($stat['type']) ? $stat['type'] : 'application/octet-stream';
$bicon = $MIME->get_icon_from_type($_PM_['path']['frontend'].'/filetypes/64', $type, array('png', 'jpg', 'jpeg', 'gif'));
// Images get a nice thumbnail, additionally we gather some info for the indexer
$ii = (substr($type, 0, 6) == 'image/') ? getimagesize($destpath) : array(0, 0, 0);
// Only try creating the thumbnail with the correct GD support.
// GIF got dropped a while ago, then reappeared again; JPEG or PNG might not be compiled in
if ($ii[2] == 1 && !function_exists('imagecreatefromgif')) $ii[2] = 0;
if ($ii[2] == 2 && !function_exists('imagecreatefromjpeg')) $ii[2] = 0;
if ($ii[2] == 3 && !function_exists('imagecreatefrompng')) $ii[2] = 0;
if ($ii[2] == 15 && !function_exists('imagecreatefromwbmp')) $ii[2] = 0;
if (false !== $ii && $ii[2] > 0 && $ii[2] < 4) {
$has_thumb = '0';
if (function_exists('imagecreatetruecolor')) {
$has_thumb = '1';
$ti = $ii;
if ($ti[0] > 190 || $ti[1] > 190) {
$wf = $ti[0] / 190; // Calculate width factor
$hf = $ti[1] / 190; // Calculate height factor
if ($wf >= $hf) {
if ($wf > 1) {
$ti[0] /= $wf;
$ti[1] /= $wf;
}
} else {
if ($hf > 1) {
$ti[0] /= $hf;
$ti[1] /= $hf;
}
}
$ti[0] = round($ti[0], 0);
$ti[1] = round($ti[1], 0);
}
if ($ii[2] == 1) {
$si = imagecreatefromgif($destpath);
} elseif ($ii[2] == 2) {
$si = imagecreatefromjpeg($destpath);
} elseif ($ii[2] == 3) {
$si = imagecreatefrompng($destpath);
} elseif ($ii[2] == 15) {
$si = imagecreatefromwbmp($destpath);
}
if (!$si) {
$has_thumb = '0';
$ti = array(0 => 0, 1 => 0);
} else {
$tn = imagecreatetruecolor($ti[0], $ti[1]);
imagecopyresampled($tn, $si, 0, 0, 0, 0, $ti[0], $ti[1], $ii[0], $ii[1]);
// Get the thumbnail and populate thumbinfo
ob_start();
if (imagetypes() & IMG_PNG) {
$thmime = 'image/png';
imagepng($tn, null);
} elseif (imagetypes() & IMG_JPG) {
$thmime = 'image/jpeg';
imagejpeg($tn, null, 75);
} elseif (imagetypes() & IMG_GIF) {
$thmime = 'image/gif';
imagegif($tn, null);
}
$thsize = ob_get_length();
$thstream = ob_get_contents();
ob_end_clean();
imagedestroy($tn);
}
}
} else {
$ti = array(0 => 0, 1 => 0);
$has_thumb = '0';
}
$friendlyname = basename(phm_stripslashes($stat['name']));
$exists = $FS->item_exists($friendlyname, $destfolder);
if ($exists) {
$expos = strrpos($friendlyname, '.');
// Yes, we mean "Not found" AND "on position 0"!
if (!$expos) {
$basename = $friendlyname;
$ext = '';
} else {
$basename = substr($friendlyname, 0, $expos);
$ext = substr($friendlyname, $expos);
}
$adder = 1;
while (true) {
$match = $FS->item_exists($basename.' ('.$adder.')'.$ext, $destfolder);
if (!$match) {
$friendlyname = $basename.' ('.$adder.')'.$ext;
break;
}
++$adder;
}
}
$FS->file_item(array
('folder_id' => $destfolder
,'filed' => true
,'filename' => $uploadname
,'friendlyname' => $friendlyname
,'type' => $type
,'size' => $stat['size']
,'img_w' => $ii[0]
,'img_h' => $ii[1]
,'thumb' => serialize(array
('has' => $has_thumb, 'w' => $ti[0], 'h' => $ti[1]
,'mime' => ($has_thumb) ? $thmime : ''
,'size' => ($has_thumb) ? $thsize : 0
,'stream' => ($has_thumb) ? $thstream : ''
))
));
if (isset($_PM_files_iamincluded)) return;
$tpl->assign_block('onupload');
$tpl->assign(array
('name' => $stat['name']
,'big_icon' => $_PM_['path']['frontend'].'/filetypes/64/'.$bicon
,'mimetype' => $stat['type']
,'opener' => (isset($_REQUEST['opener'])) ? $_REQUEST['opener'] : false
));
} else {
if (isset($_PM_files_iamincluded)) return;
$tpl->assign_block('default');
}
if (isset($_PM_files_iamincluded)) return;
$FS->init_folders();
$t_inb = $tpl->get_block('destfolder');
foreach ($FS->read_folders_flat() as $id => $data) {
$lvl_space = ($data['level'] > 0) ? str_repeat(' ', $data['level'] * 2) : '';
$t_inb->assign(array
('id' => (!$data['has_items'])
? '" style="color:darkgray;" disabled="disabled'
: $id.($id == $defaultFolder ? '" selected="selected' : '')
,'name' => $lvl_space . phm_entities($data['foldername'])
));
$tpl->assign('destfolder', $t_inb);
$t_inb->clear();
}
$passthru = give_passthrough(1);
$tpl->assign(array
('action' => htmlspecialchars(PHP_SELF.'?load=getfromurl&handler=files&'.$passthru)
,'opener' => (isset($_REQUEST['opener'])) ? phm_entities($_REQUEST['opener']) : false
,'msg_select' => $WP_msg['EnterURL']
,'msg_upload' => $WP_msg['Upload']
,'about_done' => $WP_msg['UploadDone']
,'msg_filetofolder' => $WP_msg['FldrBrwsSelect']
,'leg_enterurl' => $WP_msg['DownloadFromURL']
,'leg_localfolder' => $WP_msg['LegLocalFolder']
,'UL_ID' => uniqid($_SESSION['phM_uid'], true)
,'UL_ID_NAME' => $uplIDName
,'upload_progress_url_js' => PHP_SELF.'?load=getfromurl&handler=files&'.$passthru.'&uplInf='
));
/**
* The internal function to download a file from a URL, given that allow_url_fopen is allowed
*
* @param string $file_source a HTTP or FTP URI. No other means are supported right now due to
* security reasons (a malicious person could try to "download" local files
* @param string $file_target internal target file
* @param string $uploadinfo Where to put and how to name the donwload info for APC upload progress
* @param string $maxsize maximum file size (not checked for right now)
* @return array
* 'error' int corresponding to the UPLOAD_ERR_xxx constants
* 'size' int size in bytes actually downloaded
* 'name' string file name as deliviered by the server
* 'type' string MIME type as delivered by the server
*/
function download($file_source, $file_target, $uploadinfo, $maxsize = 1073741824)
{
$start = time();
$return = array('error' => UPLOAD_ERR_NO_FILE, 'size' => 0, 'name' => '', 'type' => 'application/octet-stream');
$allowedSchemes = array('http', 'https', 'ftp', 'ftps');
$file_source = str_replace(' ', '%20', html_entity_decode($file_source)); // fix url format
$state = ($uriparts = @parse_url($file_source));
if (!$state) return $return;
if (empty($uriparts)) return $return;
if (!in_array($uriparts['scheme'], $allowedSchemes)) return $return;
if (file_exists($file_target)) chmod($file_target, $GLOBALS['_PM_']['core']['file_umask']);
if (($rh = fopen($file_source, 'rb')) === false) {
$return['error'] = UPLOAD_ERR_NO_FILE;
return $return;
}
if (($wh = fopen($file_target, 'wb')) === false) {
$return['error'] = UPLOAD_ERR_CANT_WRITE;
return $return;
}
$headers = stream_get_meta_data($rh);
foreach ($headers['wrapper_data'] as $head) {
if (strtolower(substr($head, 0, 13)) == 'content-type:') $return['type'] = trim(strtolower(substr($head, 13)));
if (strtolower(substr($head, 0, 15)) == 'content-length:') $return['size'] = trim(strtolower(substr($head, 15)));
if ($return['name'] == '' && preg_match('!name=("?)(.*)\1!i', $head, $found)) $return['name'] = $found[2];
}
// Set a default name
if ($return['name'] == '' && isset($uriparts['path'])) $return['name'] = basename(urldecode($uriparts['path']));
// error handling
if ($return['size'] > 0 && $return['size'] > $maxsize) {
fclose($rh);
fclose($wh);
$return['error'] = UPLOAD_ERR_INI_SIZE;
return $return;
}
while (!feof($rh)) {
// unable to write to file, possibly because the harddrive has filled up
if (fwrite($wh, fread($rh, 16384)) === false) {
fclose($rh);
fclose($wh);
$return['error'] = UPLOAD_ERR_PARTIAL;
return $return;
}
$stat = fstat($wh);
if ($stat['size'] >= $maxsize) {
fclose($rh);
fclose($wh);
$return['error'] = UPLOAD_ERR_PARTIAL;
return $return;
}
clearstatcache();
file_put_contents($uploadinfo.'.dnl', $start.';'.time().';'.$return['size'].';'.$stat['size']);
}
// Finished without errors
fclose($rh);
fclose($wh);
unlink($uploadinfo);
$return['error'] = UPLOAD_ERR_OK;
return $return;
}
?>