diff --git a/modules/downloadalbum/controllers/downloadalbum.php b/modules/downloadalbum/controllers/downloadalbum.php new file mode 100644 index 00000000..83f4ab0c --- /dev/null +++ b/modules/downloadalbum/controllers/downloadalbum.php @@ -0,0 +1,258 @@ +init($id); + $files = $this->getFilesList($album); + + // Calculate ZIP size (look behind for details) + $zipsize = 22; + foreach($files as $f) { + $zipsize += 76 + 2*strlen($f) + filesize($f); + } + + // Send headers + $this->prepareOutput(); + $this->sendHeaders($album->name.'.zip', $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) { + $f_namelen = strlen($f); + $f_size = filesize($f); + $f_mtime = $this->unix2dostime(filemtime($f)); + $f_crc32 = hexdec(hash_file('crc32b', $f, 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 // file name (variable size) + // extra field (variable size) => n/a + ); + + // File data + readfile($f); + + // 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 // 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) + ); + } + + + /** + * 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. + */ + private function getFilesList($album) { + $files = array(); + + // Go to the parent of album so the ZIP will not contains all the + // server hierarchy + if (!chdir($album->file_path().'/../')) { + // @todo: throw an exception? + Kohana::log('error', 'unable to chdir('.$item->file_path().'/../)'); + exit; + } + $cwd = getcwd(); + + $items = $album->viewable() + ->descendants(null, null, array(array("type", "<>", "album"))); + foreach($items as $i) { + if (!access::can('view_full', $i)) { + continue; + } + + $relative_path = str_replace($cwd.'/', '', realpath($i->file_path())); + if (!is_readable($relative_path)) { + continue; + } + + $files[] = $relative_path; + } + + if (count($files) === 0) { + // @todo: throw an exception? + Kohana::log('error', 'no zippable files in ['.$album->relative_path().']'); + exit; + } + + return $files; + } + + + /** + * See system/helpers/download.php + */ + private function prepareOutput() { + // Close output buffers + Kohana::close_buffers(FALSE); + // Clear any output + Event::add('system.display', create_function('', 'Kohana::$output = "";')); + } + + /** + * See system/helpers/download.php + */ + private function sendHeaders($filename, $filesize = null) { + if (!is_null($filesize)) { + header('Content-Length: '.$filesize); + } + + // Retrieve MIME type by extension + $mime = Kohana::config('mimes.'.strtolower(substr(strrchr($filename, '.'), 1))); + $mime = empty($mime) ? 'application/octet-stream' : $mime[0]; + header("Content-Type: $mime"); + header('Content-Transfer-Encoding: binary'); + + // Send headers necessary to invoke a "Save As" dialog + header('Content-Disposition: attachment; filename="'.$filename.'"'); + + // Prevent caching + header('Expires: Thu, 01 Jan 1970 00:00:00 GMT'); + + if (request::user_agent('browser') === 'Internet Explorer' + AND request::user_agent('version') <= '6.0') + { + // HTTP 1.0 + header('Pragma:'); + + // HTTP 1.1 with IE extensions + header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); + } + else + { + // HTTP 1.0 + header('Pragma: no-cache'); + + // HTTP 1.1 + header('Cache-Control: no-cache, max-age=0'); + } + } + + /** + * @return integer DOS date and time + * @param integer _timestamp Unix timestamp + * @desc returns DOS date and time of the timestamp + */ + private function unix2dostime($timestamp) + { + $timebit = getdate($timestamp); + + if ($timebit['year'] < 1980) { + return (1 << 21 | 1 << 16); + } + + $timebit['year'] -= 1980; + + return ($timebit['year'] << 25 | $timebit['mon'] << 21 | + $timebit['mday'] << 16 | $timebit['hours'] << 11 | + $timebit['minutes'] << 5 | $timebit['seconds'] >> 1); + } +} diff --git a/modules/downloadalbum/css/downloadalbum_menu.css b/modules/downloadalbum/css/downloadalbum_menu.css new file mode 100644 index 00000000..e3c4c67e --- /dev/null +++ b/modules/downloadalbum/css/downloadalbum_menu.css @@ -0,0 +1,3 @@ +#g-view-menu #g-download-album-link { + background-image: url('../images/ico-view-downloadalbum.png'); +} diff --git a/modules/downloadalbum/helpers/downloadalbum_event.php b/modules/downloadalbum/helpers/downloadalbum_event.php new file mode 100644 index 00000000..e2fe4420 --- /dev/null +++ b/modules/downloadalbum/helpers/downloadalbum_event.php @@ -0,0 +1,32 @@ +item)) { + $downloadLink = url::site("downloadalbum/zip/{$theme->item->id}"); + $menu + ->append(Menu::factory("link") + ->id("downloadalbum") + ->label(t("Download Album")) + ->url($downloadLink) + ->css_id("g-download-album-link")); + } + } +} diff --git a/modules/downloadalbum/helpers/downloadalbum_theme.php b/modules/downloadalbum/helpers/downloadalbum_theme.php new file mode 100644 index 00000000..2fd23552 --- /dev/null +++ b/modules/downloadalbum/helpers/downloadalbum_theme.php @@ -0,0 +1,26 @@ +item && access::can("view_full", $theme->item)) { + $theme->css("downloadalbum_menu.css"); + } + } +} diff --git a/modules/downloadalbum/images/ico-view-downloadalbum.png b/modules/downloadalbum/images/ico-view-downloadalbum.png new file mode 100644 index 00000000..ce7804d2 Binary files /dev/null and b/modules/downloadalbum/images/ico-view-downloadalbum.png differ diff --git a/modules/downloadalbum/module.info b/modules/downloadalbum/module.info new file mode 100644 index 00000000..177ad4a8 --- /dev/null +++ b/modules/downloadalbum/module.info @@ -0,0 +1,3 @@ +name = "DownloadAlbum" +description = "Displays a link to download a ZIP archive of the current album." +version = 1 diff --git a/modules/moduleupdates/controllers/admin_moduleupdates.php b/modules/moduleupdates/controllers/admin_moduleupdates.php index fc9d1905..ba812515 100644 --- a/modules/moduleupdates/controllers/admin_moduleupdates.php +++ b/modules/moduleupdates/controllers/admin_moduleupdates.php @@ -47,16 +47,24 @@ class Admin_Moduleupdates_Controller extends Admin_Controller { foreach (module::available() as $this_module_name => $module_info) { + $remote_version = ''; + $remote_server = ''; + list ($remote_version, $remote_server) = $this->get_remote_module_version($this_module_name); $font_color = "black"; if ($remote_version == "DNE") { $font_color = "blue"; - } else if ($remote_version < $module_info->code_version) { + } else if ($module_info->version != '' and $module_info->code_version < $module_info->version) { + $font_color = "pink"; + } else if ($module_info->version != '' and $module_info->code_version > $module_info->version) { + $font_color = "orange"; + } else if ($remote_version < $module_info->code_version or ($module_info->version != '' and $remote_version < $module_info->version)) { $font_color = "green"; - } else if ($remote_version > $module_info->code_version) { + } else if ($remote_version > $module_info->code_version or ($module_info->version != '' and $remote_version > $module_info->version)) { $font_color = "red"; } + $all_modules->$this_module_name = array ("name" => $module_info->name, "locked" => $module_info->locked, "code_version" => $module_info->code_version, "active" => $module_info->active, "version" => $module_info->version,"description" => $module_info->description, @@ -91,7 +99,9 @@ class Admin_Moduleupdates_Controller extends Admin_Controller { try { $file = fopen ("http://github.com/gallery/gallery3/raw/master/modules/".$module_name."/module.info", "r"); - $server = '(G3)'; + if ($file != null) { + $server = '(G3)'; + } } catch (Exception $e) { //echo 'Message: ' .$e->getMessage() . '
'; @@ -100,7 +110,9 @@ class Admin_Moduleupdates_Controller extends Admin_Controller { if ($file == null) { try { $file = fopen ("http://github.com/gallery/gallery3-contrib/raw/master/modules/".$module_name."/module.info", "r"); - $server = '(G3CC)'; + if ($file != null) { + $server = '(G3CC)'; + } } catch (Exception $e) { //echo 'Message: ' .$e->getMessage() . '
'; diff --git a/modules/moduleupdates/views/admin_moduleupdates.html.php b/modules/moduleupdates/views/admin_moduleupdates.html.php index e4e3f038..8a7c6494 100644 --- a/modules/moduleupdates/views/admin_moduleupdates.html.php +++ b/modules/moduleupdates/views/admin_moduleupdates.html.php @@ -1,11 +1,13 @@
-

+


") ?> - Red = Out of Date
") ?> - Green = Your version is newer
") ?> + Red = Your version is older than the GitHub
") ?> + Green = Your version is newer than the GitHub
") ?> + Orange = Your file version is newer than the installed version
") ?> + Pink = Your installed version is newer than file version
") ?> Blue = Does Not Exist/No information available
") ?>

@@ -17,14 +19,14 @@ - + "> - + diff --git a/modules/user_homes/helpers/user_homes_event.php b/modules/user_homes/helpers/user_homes_event.php index 7cb0a487..65077809 100644 --- a/modules/user_homes/helpers/user_homes_event.php +++ b/modules/user_homes/helpers/user_homes_event.php @@ -178,13 +178,13 @@ class user_homes_event_Core { } } - static function album_add_form($form){ + static function album_add_form($parent, $form){ $group = $form->group("privacy") ->label(t("album privacy settings")); $group->checkbox("private")->label(t("Private"))->id("uh_private")->onClick("pc()"); $group->input("username")->label(t("Username"))->id("uh_username") - ->callback("user_homes_event::user_already_exists") + ->callback("user_homes_event::valid_name") ->error_messages("in_use", t("There is already a user with that username")) ->error_messages("required", t("You must enter a username"))->callback("user_homes_event::valid_name")->rules("length[1,32]"); $group->password("password")->label(t("Password"))->id("uh_password") diff --git a/themes/sobriety/js/ui.init.js b/themes/sobriety/js/ui.init.js index 2e1e6e89..4393a04a 100644 --- a/themes/sobriety/js/ui.init.js +++ b/themes/sobriety/js/ui.init.js @@ -43,6 +43,9 @@ $(document).ready(function() { }); } + // Remove titles for menu options since we're displaying that text anyway + $(".sf-menu a, .sf-menu li").removeAttr("title"); + // Album and search results views /*if ($("#g-album-grid").length) { // Set equal height for album items and vertically align thumbnails/metadata diff --git a/themes/sobriety/theme.info b/themes/sobriety/theme.info index f2bcb5f3..545a0815 100644 --- a/themes/sobriety/theme.info +++ b/themes/sobriety/theme.info @@ -4,5 +4,5 @@ version = 1 author = "Romain LE DISEZ" site = 1 admin = 0 -;wind commit = 2bbce8dddb0ab0a00aee727e2f639b793988a1d1 -;wind date = Thu Jun 17 09:10:01 2010 -0700 +;wind commit = 3b05db2685d92ca538d7993c960b06ea32f3a8df +;wind date = Wed Jun 23 11:16:56 2010 -0700 diff --git a/themes/sobriety/views/album.html.php b/themes/sobriety/views/album.html.php index eabe07c3..b9072e2b 100644 --- a/themes/sobriety/views/album.html.php +++ b/themes/sobriety/views/album.html.php @@ -29,7 +29,7 @@ admin || access::can("add", $item)): ?> - id") ?> + id") ?>
  • Add some.", array("attrs" => html::mark_clean("href=\"$addurl\" class=\"g-dialog-link\""))) ?>
  • diff --git a/themes/sobriety/views/form_uploadify.html.php b/themes/sobriety/views/form_uploadify.html.php index 6012f40b..62171c04 100644 --- a/themes/sobriety/views/form_uploadify.html.php +++ b/themes/sobriety/views/form_uploadify.html.php @@ -49,7 +49,7 @@ uploader: "", script: "id}") ?>", scriptData: , - fileExt: "*.gif;*.jpg;*.jpeg;*.png;*.flv;*.mp4;*.GIF;*.JPG;*.JPEG;*.PNG;*.FLV;*.MP4", + fileExt: "*.gif;*.jpg;*.jpeg;*.png;*.flv;*.mp4;*.m4v;*.GIF;*.JPG;*.JPEG;*.PNG;*.FLV;*.MP4;*.M4V", fileDesc: for_js() ?>, cancelImg: "", simUploadLimit: , @@ -166,4 +166,4 @@ */ -?> \ No newline at end of file +?> diff --git a/themes/sobriety/views/page.html.php b/themes/sobriety/views/page.html.php index 040ec1c5..cf10b85e 100644 --- a/themes/sobriety/views/page.html.php +++ b/themes/sobriety/views/page.html.php @@ -95,11 +95,13 @@ the immediate parent so that when you go back up a level you're on the right page. --> item()->id}" : null) ?>">title) ?> + "show={$theme->item()->id}" : null) ?>">title), 15) ?> -
  • ">item()->title) ?>
  • +
  • "> + item()->title), 15) ?> +
  • [File/Installed]") ?>
    "; ?> "; ?> "; ?> "; ?> "; ?>