diff options
Diffstat (limited to 'Zotlabs/Module/Attach.php')
-rw-r--r-- | Zotlabs/Module/Attach.php | 195 |
1 files changed, 161 insertions, 34 deletions
diff --git a/Zotlabs/Module/Attach.php b/Zotlabs/Module/Attach.php index 490d5edd0..5f5779b51 100644 --- a/Zotlabs/Module/Attach.php +++ b/Zotlabs/Module/Attach.php @@ -1,61 +1,188 @@ <?php + namespace Zotlabs\Module; +use ZipArchive; +use Zotlabs\Web\Controller; +use Zotlabs\Lib\Verify; + require_once('include/security.php'); require_once('include/attach.php'); +class Attach extends Controller { -class Attach extends \Zotlabs\Web\Controller { + function post() { - function init() { - - if(argc() < 2) { - notice( t('Item not available.') . EOL); + $attach_ids = ((x($_REQUEST, 'attach_ids')) ? $_REQUEST['attach_ids'] : []); + $attach_path = ((x($_REQUEST, 'attach_path')) ? $_REQUEST['attach_path'] : ''); + $channel_id = ((x($_REQUEST, 'channel_id')) ? intval($_REQUEST['channel_id']) : 0); + $channel = channelx_by_n($channel_id); + + if (!$channel) { + notice(t('Channel not found.') . EOL); return; } - - $r = attach_by_hash(argv(1),get_observer_hash(),((argc() > 2) ? intval(argv(2)) : 0)); - - if(! $r['success']) { - notice( $r['message'] . EOL); + + $strip_str = '/cloud/' . $channel['channel_address'] . '/'; + $count = strlen($strip_str); + $attach_path = substr($attach_path, $count); + + if ($attach_ids) { + + $zip_dir = 'store/[data]/' . $channel['channel_address'] . '/tmp'; + if (!is_dir($zip_dir)) + mkdir($zip_dir, STORAGE_DEFAULT_PERMISSIONS, true); + + $token = random_string(32); + + $zip_file = 'download_' . $token . '.zip'; + $zip_path = $zip_dir . '/' . $zip_file; + + $zip = new ZipArchive(); + + if ($zip->open($zip_path, ZipArchive::CREATE) === true) { + + $zip_filename = self::zip_archive_handler($zip, $attach_ids, $attach_path); + + $zip->close(); + + $meta = [ + 'zip_filename' => $zip_filename, + 'zip_path' => $zip_path + ]; + + Verify::create('zip_token', 0, $token, json_encode($meta)); + + json_return_and_die([ + 'success' => true, + 'token' => $token + ]); + + } + } + } + + function get() { + + if (argc() < 2) { + notice(t('Item not available.') . EOL); return; } - + + $token = ((x($_REQUEST, 'token')) ? $_REQUEST['token'] : ''); + + if (argv(1) === 'download') { + $meta = Verify::get_meta('zip_token', 0, $token); + + if (!$meta) + killme(); + + $meta = json_decode($meta, true); + + header('Content-Type: application/zip'); + header('Content-Disposition: attachment; filename="' . $meta['zip_filename'] . '"'); + header('Content-Length: ' . filesize($meta['zip_path'])); + + $istream = fopen($meta['zip_path'], 'rb'); + $ostream = fopen('php://output', 'wb'); + if ($istream && $ostream) { + pipe_streams($istream, $ostream); + fclose($istream); + fclose($ostream); + } + + unlink($meta['zip_path']); + killme(); + } + + $r = attach_by_hash(argv(1), get_observer_hash(), ((argc() > 2) ? intval(argv(2)) : 0)); + + if (!$r['success']) { + notice($r['message'] . EOL); + return; + } + $c = q("select channel_address from channel where channel_id = %d limit 1", intval($r['data']['uid']) ); - - if(! $c) + + if (!$c) return; - - - $unsafe_types = array('text/html','text/css','application/javascript'); - - if(in_array($r['data']['filetype'],$unsafe_types) && (! channel_codeallowed($r['data']['uid']))) { - header('Content-type: text/plain'); + + $unsafe_types = array('text/html', 'text/css', 'application/javascript'); + + if (in_array($r['data']['filetype'], $unsafe_types) && (!channel_codeallowed($r['data']['uid']))) { + header('Content-Type: text/plain'); } else { - header('Content-type: ' . $r['data']['filetype']); - } - - header('Content-disposition: attachment; filename="' . $r['data']['filename'] . '"'); - if(intval($r['data']['os_storage'])) { - $fname = dbunescbin($r['data']['content']); - if(strpos($fname,'store') !== false) - $istream = fopen($fname,'rb'); + header('Content-Type: ' . $r['data']['filetype']); + } + + header('Content-Disposition: attachment; filename="' . $r['data']['filename'] . '"'); + if (intval($r['data']['os_storage'])) { + $fname = $r['data']['content']; + if (strpos($fname, 'store') !== false) + $istream = fopen($fname, 'rb'); else - $istream = fopen('store/' . $c[0]['channel_address'] . '/' . $fname,'rb'); - $ostream = fopen('php://output','wb'); - if($istream && $ostream) { - pipe_streams($istream,$ostream); + $istream = fopen('store/' . $c[0]['channel_address'] . '/' . $fname, 'rb'); + $ostream = fopen('php://output', 'wb'); + if ($istream && $ostream) { + pipe_streams($istream, $ostream); fclose($istream); fclose($ostream); } } else - echo dbunescbin($r['data']['content']); + echo $r['data']['content']; killme(); - + } - + + public function zip_archive_handler($zip, $attach_ids, $attach_path, $pass = 1) { + + $observer_hash = get_observer_hash(); + $single = ((count($attach_ids) == 1) ? true : false); + $download_name = 'download.zip'; + + foreach ($attach_ids as $attach_id) { + + $r = attach_by_id($attach_id, $observer_hash); + + if (!$r['success']) { + continue; + } + + if ($r['data']['is_dir'] && $single && $pass === 1) + $download_name = $r['data']['filename'] . '.zip'; + + $zip_path = $r['data']['display_path']; + + if ($attach_path) { + $strip_str = $attach_path . '/'; + $count = strlen($strip_str); + $zip_path = substr($r['data']['display_path'], $count); + } + + if ($r['data']['is_dir']) { + $zip->addEmptyDir($zip_path); + + $d = q("SELECT id FROM attach WHERE folder = '%s'", + dbesc($r['data']['hash']) + ); + + $attach_ids = ids_to_array($d); + self::zip_archive_handler($zip, $attach_ids, $attach_path, $pass++); + } + else { + $file_path = $r['data']['content']; + $zip->addFile($file_path, $zip_path); + // compressing can be ressource intensive - just store the data + $zip->setCompressionName($zip_path, ZipArchive::CM_STORE); + } + + } + + return $download_name; + } + } |