Sync downloadalbum in branch '3.1'
This commit is contained in:
parent
55babdfc85
commit
8aa45472a8
@ -22,30 +22,55 @@ class downloadalbum_Controller extends Controller {
|
|||||||
/**
|
/**
|
||||||
* Generate a ZIP on-the-fly.
|
* Generate a ZIP on-the-fly.
|
||||||
*/
|
*/
|
||||||
public function zip($id) {
|
public function zip($container_type, $id) {
|
||||||
$album = $this->init($id);
|
switch($container_type) {
|
||||||
$files = $this->getFilesList($album);
|
case "album":
|
||||||
|
$container = ORM::factory("item", $id);
|
||||||
|
if (!$container->is_album()) {
|
||||||
|
throw new Kohana_Exception('container is not an album: '.$container->relative_path());
|
||||||
|
}
|
||||||
|
|
||||||
|
$zipname = (empty($container->name))
|
||||||
|
? 'Gallery.zip' // @todo purified_version_of($container->title).'.zip'
|
||||||
|
: $container->name.'.zip';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "tag":
|
||||||
|
// @todo: if the module is not installed, it crash
|
||||||
|
$container = ORM::factory("tag", $id);
|
||||||
|
if (is_null($container->name)) {
|
||||||
|
throw new Kohana_Exception('container is not a tag: '.$id);
|
||||||
|
}
|
||||||
|
|
||||||
|
$zipname = $container->name.'.zip';
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new Kohana_Exception('unhandled container type: '.$container_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
$files = $this->getFilesList($container);
|
||||||
|
|
||||||
// Calculate ZIP size (look behind for details)
|
// Calculate ZIP size (look behind for details)
|
||||||
$zipsize = 22;
|
$zipsize = 22;
|
||||||
foreach($files as $f) {
|
foreach($files as $f_name => $f_path) {
|
||||||
$zipsize += 76 + 2*strlen($f) + filesize($f);
|
$zipsize += 76 + 2*strlen($f_name) + filesize($f_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send headers
|
// Send headers
|
||||||
$this->prepareOutput();
|
$this->prepareOutput();
|
||||||
$this->sendHeaders($album->name.'.zip', $zipsize);
|
$this->sendHeaders($zipname, $zipsize);
|
||||||
|
|
||||||
// Generate and send ZIP file
|
// Generate and send ZIP file
|
||||||
// http://www.pkware.com/documents/casestudies/APPNOTE.TXT (v6.3.2)
|
// http://www.pkware.com/documents/casestudies/APPNOTE.TXT (v6.3.2)
|
||||||
$lfh_offset = 0;
|
$lfh_offset = 0;
|
||||||
$cds = '';
|
$cds = '';
|
||||||
$cds_offset = 0;
|
$cds_offset = 0;
|
||||||
foreach($files as $f) {
|
foreach($files as $f_name => $f_path) {
|
||||||
$f_namelen = strlen($f);
|
$f_namelen = strlen($f_name);
|
||||||
$f_size = filesize($f);
|
$f_size = filesize($f_path);
|
||||||
$f_mtime = $this->unix2dostime(filemtime($f));
|
$f_mtime = $this->unix2dostime(filemtime($f_path));
|
||||||
$f_crc32 = $this->fixBug45028(hexdec(hash_file('crc32b', $f, false)));
|
$f_crc32 = $this->fixBug45028(hexdec(hash_file('crc32b', $f_path, false)));
|
||||||
|
|
||||||
// Local file header
|
// Local file header
|
||||||
echo pack('VvvvVVVVvva' . $f_namelen,
|
echo pack('VvvvVVVVvva' . $f_namelen,
|
||||||
@ -60,12 +85,12 @@ class downloadalbum_Controller extends Controller {
|
|||||||
$f_namelen, // file name length (2 bytes)
|
$f_namelen, // file name length (2 bytes)
|
||||||
0, // extra field length (2 bytes)
|
0, // extra field length (2 bytes)
|
||||||
|
|
||||||
$f // file name (variable size)
|
$f_name // file name (variable size)
|
||||||
// extra field (variable size) => n/a
|
// extra field (variable size) => n/a
|
||||||
);
|
);
|
||||||
|
|
||||||
// File data
|
// File data
|
||||||
readfile($f);
|
readfile($f_path);
|
||||||
|
|
||||||
// Data descriptor (n/a)
|
// Data descriptor (n/a)
|
||||||
|
|
||||||
@ -88,7 +113,7 @@ class downloadalbum_Controller extends Controller {
|
|||||||
0x81b40000, // external file attributes (4 bytes) => chmod 664
|
0x81b40000, // external file attributes (4 bytes) => chmod 664
|
||||||
$lfh_offset, // relative offset of local header (4 bytes)
|
$lfh_offset, // relative offset of local header (4 bytes)
|
||||||
|
|
||||||
$f // file name (variable size)
|
$f_name // file name (variable size)
|
||||||
// extra field (variable size) => n/a
|
// extra field (variable size) => n/a
|
||||||
// file comment (variable size) => n/a
|
// file comment (variable size) => n/a
|
||||||
);
|
);
|
||||||
@ -128,59 +153,58 @@ class downloadalbum_Controller extends Controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Init
|
|
||||||
*/
|
|
||||||
private function init($id) {
|
|
||||||
$item = ORM::factory("item", $id);
|
|
||||||
|
|
||||||
// Only send an album
|
|
||||||
if (!$item->is_album()) {
|
|
||||||
// @todo: throw an exception?
|
|
||||||
Kohana::log('error', 'item is not an album: '.$item->relative_path());
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Must have view_full to download the originals files
|
|
||||||
access::required("view_full", $item);
|
|
||||||
|
|
||||||
return $item;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the files that must be included in the archive.
|
* Return the files that must be included in the archive.
|
||||||
*/
|
*/
|
||||||
private function getFilesList($album) {
|
private function getFilesList($container) {
|
||||||
$files = array();
|
$files = array();
|
||||||
|
|
||||||
// Go to the parent of album so the ZIP will not contains all the
|
if( $container instanceof Item_Model && $container->is_album() ) {
|
||||||
// server hierarchy
|
$container_realpath = realpath($container->file_path().'/../');
|
||||||
if (!chdir($album->file_path().'/../')) {
|
|
||||||
// @todo: throw an exception?
|
|
||||||
Kohana::log('error', 'unable to chdir('.$item->file_path().'/../)');
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
$cwd = getcwd();
|
|
||||||
|
|
||||||
$items = $album->viewable()
|
$items = $container->viewable()
|
||||||
->descendants(null, null, array(array("type", "<>", "album")));
|
->descendants(null, null, array(array("type", "<>", "album")));
|
||||||
foreach($items as $i) {
|
foreach($items as $i) {
|
||||||
if (!access::can('view_full', $i)) {
|
if (!access::can('view_full', $i)) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$i_realpath = realpath($i->file_path());
|
||||||
|
if (!is_readable($i_realpath)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$i_relative_path = str_replace($container_realpath.DIRECTORY_SEPARATOR, '', $i_realpath);
|
||||||
|
$i_relative_path = str_replace(DIRECTORY_SEPARATOR, '/', $i_relative_path);
|
||||||
|
$files[$i_relative_path] = $i_realpath;
|
||||||
}
|
}
|
||||||
|
|
||||||
$relative_path = str_replace($cwd.'/', '', realpath($i->file_path()));
|
} else if( $container instanceof Tag_Model ) {
|
||||||
if (!is_readable($relative_path)) {
|
$items = $container->items();
|
||||||
continue;
|
foreach($items as $i) {
|
||||||
}
|
if (!access::can('view_full', $i)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
$files[] = $relative_path;
|
if( $i->is_album() ) {
|
||||||
|
foreach($this->getFilesList($i) as $f_name => $f_path) {
|
||||||
|
$files[$container->name.'/'.$f_name] = $f_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
$i_realpath = realpath($i->file_path());
|
||||||
|
if (!is_readable($i_realpath)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$i_relative_path = $container->name.'/'.$i->name;
|
||||||
|
$files[$i_relative_path] = $i_realpath;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count($files) === 0) {
|
if (count($files) === 0) {
|
||||||
// @todo: throw an exception?
|
throw new Kohana_Exception('no zippable files in ['.$container->name.']');
|
||||||
Kohana::log('error', 'no zippable files in ['.$album->relative_path().']');
|
|
||||||
exit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $files;
|
return $files;
|
||||||
@ -264,9 +288,13 @@ class downloadalbum_Controller extends Controller {
|
|||||||
* See http://bugs.php.net/bug.php?id=45028
|
* See http://bugs.php.net/bug.php?id=45028
|
||||||
*/
|
*/
|
||||||
private function fixBug45028($hash) {
|
private function fixBug45028($hash) {
|
||||||
return (version_compare(PHP_VERSION, '5.2.7', '<'))
|
$output = $hash;
|
||||||
? (($hash & 0x000000ff) << 24) + (($hash & 0x0000ff00) << 8)
|
|
||||||
+ (($hash & 0x00ff0000) >> 8) + (($hash & 0xff000000) >> 24)
|
if( version_compare(PHP_VERSION, '5.2.7', '<') ) {
|
||||||
: $hash;
|
$str = str_pad(dechex($hash), 8, '0', STR_PAD_LEFT);
|
||||||
|
$output = hexdec($str{6}.$str{7}.$str{4}.$str{5}.$str{2}.$str{3}.$str{0}.$str{1});
|
||||||
|
}
|
||||||
|
|
||||||
|
return $output;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,14 +19,22 @@
|
|||||||
*/
|
*/
|
||||||
class downloadalbum_event_Core {
|
class downloadalbum_event_Core {
|
||||||
static function album_menu($menu, $theme) {
|
static function album_menu($menu, $theme) {
|
||||||
if (access::can("view_full", $theme->item)) {
|
$downloadLink = url::site("downloadalbum/zip/album/{$theme->item->id}");
|
||||||
$downloadLink = url::site("downloadalbum/zip/{$theme->item->id}");
|
$menu
|
||||||
$menu
|
->append(Menu::factory("link")
|
||||||
->append(Menu::factory("link")
|
->id("downloadalbum")
|
||||||
->id("downloadalbum")
|
->label(t("Download Album"))
|
||||||
->label(t("Download Album"))
|
->url($downloadLink)
|
||||||
->url($downloadLink)
|
->css_id("g-download-album-link"));
|
||||||
->css_id("g-download-album-link"));
|
}
|
||||||
}
|
|
||||||
|
static function tag_menu($menu, $theme) {
|
||||||
|
$downloadLink = url::site("downloadalbum/zip/tag/{$theme->tag()->id}");
|
||||||
|
$menu
|
||||||
|
->append(Menu::factory("link")
|
||||||
|
->id("downloadalbum")
|
||||||
|
->label(t("Download Album"))
|
||||||
|
->url($downloadLink)
|
||||||
|
->css_id("g-download-album-link"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,8 +19,6 @@
|
|||||||
*/
|
*/
|
||||||
class downloadalbum_theme {
|
class downloadalbum_theme {
|
||||||
static function head($theme) {
|
static function head($theme) {
|
||||||
if ($theme->item && access::can("view_full", $theme->item)) {
|
$theme->css("downloadalbum_menu.css");
|
||||||
$theme->css("downloadalbum_menu.css");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
name = "DownloadAlbum"
|
name = "DownloadAlbum"
|
||||||
description = "Displays a link to download a ZIP archive of the current album."
|
description = "Displays a link to download a ZIP archive of the current album."
|
||||||
version = 1
|
version = 2
|
||||||
|
Reference in New Issue
Block a user