Download Multiple Items/Image as Zip Module of sorts

adamlavelle

Joined: 2012-12-05
Posts: 1
Posted: Fri, 2012-12-07 00:18

So I've spent the last couple days re-acquainting myself with Gallery (haven't worked on it since version 1 so its been many years).

I thought it would be nice to allow download of favorites tagged in favourites module .... Concept being its easy to mark the items as favorites and then be able to download them as a zip. Merging some functions from Gallery3:Modules:downloadalbum and Gallery3:Modules:favourites

So I'm testing with

http://localhost/gallery3/index.php/downloadfavs/index/8/9

8 & 9 being the images

and I've tried a variety of options, but it doesn't seem to pass the items correctly. I've looked at a bunch of other modules but am probably lost. Any suggestions are appreciated.

Attached and inline


<?php defined("SYSPATH") or die("No direct script access.");/**
 * Gallery - a web based photo album viewer and editor
 * Copyright (C) 2000-2012 Bharat Mediratta
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
 */
class DownloadFavs_Controller extends Controller {

  /**
   * pulled from downloadalbum_Controller
   * ie http://localhost/gallery3/index.php/downloadalbum/zip/album/6
   * or for tag http://localhost/gallery3/index.php/downloadalbum/zip/tag/2
   * Generate a ZIP on-the-fly.
   */

  public function index() {
    
    // This is the array of arguments passed to the page
    $array = func_get_args();
   
    foreach($array as $i=>$item){
      // need to create something with the items here ?
    }
    
   $files = $this->getFilesList($array);

    // Calculate ZIP size (look behind for details)
    $zipsize = 22;
    foreach($files as $f_name => $f_path) {
      $zipsize += 76 + 2*strlen($f_name) + filesize($f_path);
    }

    // Send headers
    $this->prepareOutput();
    $this->sendHeaders($zipname, $zipsize);

    // Generate and send ZIP file
    // http://www.pkware.com/documents/casestudies/APPNOTE.TXT (v6.3.2)
    $lfh_offset = 0;
    $cds = '';
    $cds_offset = 0;
    foreach($files as $f_name => $f_path) {
      $f_namelen = strlen($f_name);
      $f_size = filesize($f_path);
      $f_mtime = $this->unix2dostime(filemtime($f_path));
      $f_crc32 = $this->fixBug45028(hexdec(hash_file('crc32b', $f_path, false)));

      // Local file header
      echo pack('VvvvVVVVvva' . $f_namelen,
          0x04034b50,         // local file header signature (4 bytes)
          0x0a,               // version needed to extract (2 bytes) => 1.0
          0x0800,             // general purpose bit flag (2 bytes) => UTF-8
          0x00,               // compression method (2 bytes) => store
          $f_mtime,           // last mod file time and date (4 bytes)
          $f_crc32,           // crc-32 (4 bytes)
          $f_size,            // compressed size (4 bytes)
          $f_size,            // uncompressed size (4 bytes)
          $f_namelen,         // file name length (2 bytes)
          0,                  // extra field length (2 bytes)

          $f_name             // file name (variable size)
                              // extra field (variable size) => n/a
      );

      // File data
      readfile($f_path);

      // Data descriptor (n/a)

      // Central directory structure: File header
      $cds .= pack('VvvvvVVVVvvvvvVVa' . $f_namelen,
          0x02014b50,         // central file header signature (4 bytes)
          0x031e,             // version made by (2 bytes) => v3 / Unix
          0x0a,               // version needed to extract (2 bytes) => 1.0
          0x0800,             // general purpose bit flag (2 bytes) => UTF-8
          0x00,               // compression method (2 bytes) => store
          $f_mtime,           // last mod file time and date (4 bytes)
          $f_crc32,           // crc-32 (4 bytes)
          $f_size,            // compressed size (4 bytes)
          $f_size,            // uncompressed size (4 bytes)
          $f_namelen,         // file name length (2 bytes)
          0,                  // extra field length (2 bytes)
          0,                  // file comment length (2 bytes)
          0,                  // disk number start (2 bytes)
          0,                  // internal file attributes (2 bytes)
          0x81b40000,         // external file attributes (4 bytes) => chmod 664
          $lfh_offset,        // relative offset of local header (4 bytes)

          $f_name             // file name (variable size)
                              // extra field (variable size) => n/a
                              // file comment (variable size) => n/a
      );

      // Update local file header/central directory structure offset
      $cds_offset = $lfh_offset += 30 + $f_namelen + $f_size;
    }

    // Archive decryption header (n/a)
    // Archive extra data record (n/a)

    // Central directory structure: Digital signature (n/a)
    echo $cds; // send Central directory structure

    // Zip64 end of central directory record (n/a)
    // Zip64 end of central directory locator (n/a)

    // End of central directory record
    $numfile = count($files);
    $cds_len = strlen($cds);
    echo pack('VvvvvVVv',
        0x06054b50,             // end of central dir signature (4 bytes)
        0,                      // number of this disk (2 bytes)
        0,                      // number of the disk with the start of
                                // the central directory (2 bytes)
        $numfile,               // total number of entries in the
                                // central directory on this disk (2 bytes)
        $numfile,               // total number of entries in the
                                // central directory (2 bytes)
        $cds_len,               // size of the central directory (4 bytes)
        $cds_offset,            // offset of start of central directory
                                // with respect to the
                                // starting disk number (4 bytes)
        0                       // .ZIP file comment length (2 bytes)
                                // .ZIP file comment (variable size)
    );

    print $this->_get_form();
  }

  private function getFilesList($container) {
    $files = array();

    if( $container instanceof Item_Model && $container->is_album() ) {
      $container_realpath = realpath($container->file_path().'/../');

      $items = $container->viewable()
          ->descendants(null, null, array(array("type", "<>", "album")));
      foreach($items as $i) {
        if (!access::can('view_full', $i)) {
          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;
      }

    } else if( $container instanceof Tag_Model ) {
      $items = $container->items();
      foreach($items as $i) {
        if (!access::can('view_full', $i)) {
          continue;
        }

        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) {
      throw new Kohana_Exception('no zippable files in ['.$container->name.']');
    }

    return $files;
  }



  public function handler() {
    access::verify_csrf();

    $form = $this->_get_form();
    if ($form->validate()) {
      // @todo process the admin form

      message::success(t("DownloadFavs Processing Successfully"));

      json::reply(array("result" => "success"));
    } else {
      json::reply(array("result" => "error", "html" => (string)$form));
    }
  }

  private function _get_form() {
    $form = new Forge("downloadfavs/handler", "", "post",
                      array("id" => "g-DownloadFavs-form"));
    $group = $form->group("group")->label(t("DownloadFavs Handler"));
    $group->input("text")->label(t("Text"))->rules("required");
    $group->submit("submit")->value(t("Submit"));

    return $form;
  }
}


AttachmentSize
downloadfavs.zip16.17 KB