From 0fe44fe3809041edb64b69496bcee070578483d5 Mon Sep 17 00:00:00 2001 From: Bharat Mediratta Date: Fri, 6 Aug 2010 10:40:41 -0700 Subject: Use module::install and module::activate for the gallery module as well; I've verified that it generates the same installer files. --- modules/gallery/controllers/packager.php | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'modules/gallery/controllers') diff --git a/modules/gallery/controllers/packager.php b/modules/gallery/controllers/packager.php index 835cb903..f463d0de 100644 --- a/modules/gallery/controllers/packager.php +++ b/modules/gallery/controllers/packager.php @@ -59,11 +59,7 @@ class Packager_Controller extends Controller { // numbers, keeping our install.sql file more stable. srand(0); - gallery_installer::install(true); - - module::load_modules(); - - foreach (array("user", "comment", "organize", "info", "rest", + foreach (array("gallery", "user", "comment", "organize", "info", "rest", "rss", "search", "slideshow", "tag") as $module_name) { module::install($module_name); module::activate($module_name); -- cgit v1.2.3 From c6ca77377f2c55316923c62e80b34802a45979c2 Mon Sep 17 00:00:00 2001 From: Bharat Mediratta Date: Sat, 7 Aug 2010 18:02:39 -0700 Subject: Whitespace fix. --- modules/gallery/controllers/uploader.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'modules/gallery/controllers') diff --git a/modules/gallery/controllers/uploader.php b/modules/gallery/controllers/uploader.php index 87520032..85d344d6 100644 --- a/modules/gallery/controllers/uploader.php +++ b/modules/gallery/controllers/uploader.php @@ -50,7 +50,8 @@ class Uploader_Controller extends Controller { // Uploadify adds its own field to the form, so validate that separately. $file_validation = new Validation($_FILES); $file_validation->add_rules( - "Filedata", "upload::valid", "upload::required", "upload::type[gif,jpg,jpeg,png,flv,mp4,m4v]"); + "Filedata", "upload::valid", "upload::required", + "upload::type[gif,jpg,jpeg,png,flv,mp4,m4v]"); if ($form->validate() && $file_validation->validate()) { $temp_filename = upload::save("Filedata"); -- cgit v1.2.3 From dfb095a26267f8b68b40add03dfe407966c49b92 Mon Sep 17 00:00:00 2001 From: Bharat Mediratta Date: Sat, 7 Aug 2010 22:18:28 -0700 Subject: Add the ability to replace the source data file in Item_Model::save(). Refactor the rotate code in Quick_Controller to replace the data file, and then have gallery_event::item_updated_data_file() pick up after the change is saved, rebuild the image and handle album covers. This is much more portable than before and it will allow any mechanism (eg: REST) to replace the source image. --- modules/gallery/controllers/quick.php | 22 ++------- modules/gallery/helpers/gallery_event.php | 14 ++++++ modules/gallery/helpers/movie.php | 44 +++++++++++------- modules/gallery/helpers/photo.php | 12 +++++ modules/gallery/models/item.php | 74 ++++++++++++++++++++----------- modules/gallery/tests/Item_Model_Test.php | 31 +++++++++++++ 6 files changed, 137 insertions(+), 60 deletions(-) (limited to 'modules/gallery/controllers') diff --git a/modules/gallery/controllers/quick.php b/modules/gallery/controllers/quick.php index fee601d9..c34209da 100644 --- a/modules/gallery/controllers/quick.php +++ b/modules/gallery/controllers/quick.php @@ -36,25 +36,11 @@ class Quick_Controller extends Controller { } if ($degrees) { - gallery_graphics::rotate($item->file_path(), $item->file_path(), - array("degrees" => $degrees)); - - list($item->width, $item->height) = getimagesize($item->file_path()); - $item->resize_dirty= 1; - $item->thumb_dirty= 1; + $tmpfile = tempnam(TMPPATH, "rotate"); + gallery_graphics::rotate($item->file_path(), $tmpfile, array("degrees" => $degrees)); + $item->set_data_file($tmpfile); $item->save(); - - graphics::generate($item); - - // @todo: this is an inadequate way to regenerate album cover thumbnails after rotation. - foreach (ORM::factory("item") - ->where("album_cover_item_id", "=", $item->id) - ->find_all() as $target) { - copy($item->thumb_path(), $target->thumb_path()); - $target->thumb_width = $item->thumb_width; - $target->thumb_height = $item->thumb_height; - $target->save(); - } + unlink($tmpfile); } if (Input::instance()->get("page_type") == "collection") { diff --git a/modules/gallery/helpers/gallery_event.php b/modules/gallery/helpers/gallery_event.php index e3fa5e08..e048118b 100644 --- a/modules/gallery/helpers/gallery_event.php +++ b/modules/gallery/helpers/gallery_event.php @@ -124,6 +124,20 @@ class gallery_event_Core { } } + static function item_updated_data_file($item) { + graphics::generate($item); + + // Update any places where this is the album cover + foreach (ORM::factory("item") + ->where("album_cover_item_id", "=", $item->id) + ->find_all() as $target) { + copy($item->thumb_path(), $target->thumb_path()); + $target->thumb_width = $item->thumb_width; + $target->thumb_height = $item->thumb_height; + $target->save(); + } + } + static function batch_complete() { // Set the album covers for any items that where we probably deleted the album cover during // this batch. The item may have been deleted, so don't count on it being around. Choose the diff --git a/modules/gallery/helpers/movie.php b/modules/gallery/helpers/movie.php index bbb5b66c..4ff29a7b 100644 --- a/modules/gallery/helpers/movie.php +++ b/modules/gallery/helpers/movie.php @@ -57,23 +57,6 @@ class movie_Core { return $form; } - - static function getmoviesize($filename) { - $ffmpeg = self::find_ffmpeg(); - if (empty($ffmpeg)) { - throw new Exception("@todo MISSING_FFMPEG"); - } - - $cmd = escapeshellcmd($ffmpeg) . " -i " . escapeshellarg($filename) . " 2>&1"; - $result = `$cmd`; - if (preg_match("/Stream.*?Video:.*?(\d+)x(\d+)/", $result, $regs)) { - list ($width, $height) = array($regs[1], $regs[2]); - } else { - list ($width, $height) = array(0, 0); - } - return array($width, $height); - } - static function extract_frame($input_file, $output_file) { $ffmpeg = self::find_ffmpeg(); if (empty($ffmpeg)) { @@ -114,4 +97,31 @@ class movie_Core { } return $ffmpeg_path; } + + + /** + * Return the width, height, mime_type and extension of the given movie file. + */ + static function get_file_metadata($file_path) { + $ffmpeg = self::find_ffmpeg(); + if (empty($ffmpeg)) { + throw new Exception("@todo MISSING_FFMPEG"); + } + + $cmd = escapeshellcmd($ffmpeg) . " -i " . escapeshellarg($file_path) . " 2>&1"; + $result = `$cmd`; + if (preg_match("/Stream.*?Video:.*?(\d+)x(\d+)/", $result, $regs)) { + list ($width, $height) = array($regs[1], $regs[2]); + } else { + list ($width, $height) = array(0, 0); + } + + $pi = pathinfo($file_path); + $extension = isset($pi["extension"]) ? $pi["extension"] : "flv"; // No extension? Assume FLV. + $mime_type = in_array(strtolower($extension), array("mp4", "m4v")) ? + "video/mp4" : "video/x-flv"; + + return array($width, $height, $mime_type, $extension); + } + } diff --git a/modules/gallery/helpers/photo.php b/modules/gallery/helpers/photo.php index 73cd60c0..a38b4fb2 100644 --- a/modules/gallery/helpers/photo.php +++ b/modules/gallery/helpers/photo.php @@ -77,4 +77,16 @@ class photo_Core { } return sprintf($format, $new_width, $new_height); } + + /** + * Return the width, height, mime_type and extension of the given image file. + */ + static function get_file_metadata($file_path) { + $image_info = getimagesize($file_path); + $width = $image_info[0]; + $height = $image_info[1]; + $mime_type = $image_info["mime"]; + $extension = image_type_to_extension($image_info[2], false); + return array($width, $height, $mime_type, $extension); + } } diff --git a/modules/gallery/models/item.php b/modules/gallery/models/item.php index c00b7972..5257bbb9 100644 --- a/modules/gallery/models/item.php +++ b/modules/gallery/models/item.php @@ -316,7 +316,7 @@ class Item_Model extends ORM_MPTT { unset($significant_changes["relative_url_cache"]); unset($significant_changes["relative_path_cache"]); - if (!empty($this->changed) && $significant_changes) { + if ((!empty($this->changed) && $significant_changes) || isset($this->data_file)) { $this->updated = time(); if (!$this->loaded()) { // Create a new item. @@ -341,30 +341,19 @@ class Item_Model extends ORM_MPTT { } // Get the width, height and mime type from our data file for photos and movies. - if ($this->is_movie() || $this->is_photo()) { - $pi = pathinfo($this->data_file); - + if ($this->is_photo() || $this->is_movie()) { if ($this->is_photo()) { - $image_info = getimagesize($this->data_file); - $this->width = $image_info[0]; - $this->height = $image_info[1]; - $this->mime_type = $image_info["mime"]; - - // Force an extension onto the name if necessary - if (empty($pi["extension"])) { - $pi["extension"] = image_type_to_extension($image_info[2], false); - $this->name .= "." . $pi["extension"]; - } - } else { - list ($this->width, $this->height) = movie::getmoviesize($this->data_file); - - // No extension? Assume FLV. - if (empty($pi["extension"])) { - $pi["extension"] = "flv"; - $this->name .= "." . $pi["extension"]; - } + list ($this->width, $this->height, $this->mime_type, $extension) = + photo::get_file_metadata($this->data_file); + } else if ($this->is_movie()) { + list ($this->width, $this->height, $this->mime_type, $extension) = + movie::get_file_metadata($this->data_file); + } - $this->mime_type = in_array(strtolower($pi["extension"]), array("mp4", "m4v")) ? "video/mp4" : "video/x-flv"; + // Force an extension onto the name if necessary + $pi = pathinfo($this->data_file); + if (empty($pi["extension"])) { + $this->name = "{$this->name}.$extension"; } } @@ -479,7 +468,30 @@ class Item_Model extends ORM_MPTT { ->execute(); } + // Replace the data file, if requested. + // @todo: we don't handle the case where you swap in a file of a different mime type + // should we prevent that in validation? or in set_data_file() + if ($this->data_file && ($this->is_photo() || $this->is_movie())) { + copy($this->data_file, $this->file_path()); + + // Get the width, height and mime type from our data file for photos and movies. + if ($this->is_photo()) { + list ($this->width, $this->height) = photo::get_file_metadata($this->file_path()); + } else if ($this->is_movie()) { + list ($this->width, $this->height) = movie::get_file_metadata($this->file_path()); + } + $this->thumb_dirty = 1; + $this->resize_dirty = 1; + } + module::event("item_updated", $original, $this); + + if ($this->data_file) { + // Null out the data file variable here, otherwise this event will trigger another + // save() which will think that we're doing another file move. + $this->data_file = null; + module::event("item_updated_data_file", $this); + } } } else if (!empty($this->changed)) { // Insignificant changes only. Don't fire events or do any special checking to try to keep @@ -765,8 +777,9 @@ class Item_Model extends ORM_MPTT { $this->rules["slug"] = array(); } - // Movies and photos must have data files - if (($this->is_photo() || $this->is_movie()) && !$this->loaded()) { + // Movies and photos must have data files. Verify the data file on new items, or if it has + // been replaced. + if (($this->is_photo() || $this->is_movie()) && $this->data_file) { $this->rules["name"]["callbacks"][] = array($this, "valid_data_file"); } } @@ -842,6 +855,17 @@ class Item_Model extends ORM_MPTT { } else if (filesize($this->data_file) == 0) { $v->add_error("name", "empty_data_file"); } + + if ($this->loaded()) { + if ($this->is_photo()) { + list ($a, $b, $mime_type) = photo::get_file_metadata($this->data_file); + } else if ($this->is_movie()) { + list ($a, $b, $mime_type) = movie::get_file_metadata($this->data_file); + } + if ($mime_type != $this->mime_type) { + $v->add_error("name", "cant_change_mime_type"); + } + } } /** diff --git a/modules/gallery/tests/Item_Model_Test.php b/modules/gallery/tests/Item_Model_Test.php index 907cfe24..bd123098 100644 --- a/modules/gallery/tests/Item_Model_Test.php +++ b/modules/gallery/tests/Item_Model_Test.php @@ -384,4 +384,35 @@ class Item_Model_Test extends Gallery_Unit_Test_Case { $this->assert_same($photo->id, $album->album_cover_item_id); } + + public function replace_data_file_test() { + // Random photo is modules/gallery/tests/test.jpg which is 1024x768 and 6232 bytes. + $photo = test::random_photo(); + $this->assert_equal(1024, $photo->width); + $this->assert_equal(768, $photo->height); + $this->assert_equal(6232, filesize($photo->file_path())); + + // Random photo is gallery/images/imagemagick.jpg is 114x118 and 20337 bytes + $photo->set_data_file(MODPATH . "gallery/images/imagemagick.jpg"); + $photo->save(); + + $this->assert_equal(114, $photo->width); + $this->assert_equal(118, $photo->height); + $this->assert_equal(20337, filesize($photo->file_path())); + } + + public function replacement_data_file_must_be_same_mime_type_test() { + // Random photo is modules/gallery/tests/test.jpg + $photo = test::random_photo(); + $photo->set_data_file(MODPATH . "gallery/images/graphicsmagick.png"); + + try { + $photo->save(); + } catch (ORM_Validation_Exception $e) { + $this->assert_same(array("name" => "cant_change_mime_type"), $e->validation->errors()); + return; // pass + } + $this->assert_true(false, "Shouldn't get here"); + + } } -- cgit v1.2.3 From 1ad1f9517f91875875f2e062bda7d834827c3430 Mon Sep 17 00:00:00 2001 From: Tim Almdal Date: Sun, 8 Aug 2010 17:29:22 -0700 Subject: Fix for ticket #1279. In admin themes sanitize the theme name before checking that theme.info exists. --- modules/gallery/controllers/admin_themes.php | 7 ++++--- modules/gallery/helpers/theme.php | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'modules/gallery/controllers') diff --git a/modules/gallery/controllers/admin_themes.php b/modules/gallery/controllers/admin_themes.php index e59eadaf..a88e1e89 100644 --- a/modules/gallery/controllers/admin_themes.php +++ b/modules/gallery/controllers/admin_themes.php @@ -31,10 +31,11 @@ class Admin_Themes_Controller extends Admin_Controller { private function _get_themes() { $themes = array(); foreach (scandir(THEMEPATH) as $theme_name) { + if ($theme_name[0] == ".") { + continue; + } + $theme_name = preg_replace("/[^a-zA-Z0-9\._-]/", "", $theme_name); if (file_exists(THEMEPATH . "$theme_name/theme.info")) { - if ($theme_name[0] == ".") { - continue; - } $themes[$theme_name] = theme::get_info($theme_name); } diff --git a/modules/gallery/helpers/theme.php b/modules/gallery/helpers/theme.php index 3589a5b7..9df3eaf2 100644 --- a/modules/gallery/helpers/theme.php +++ b/modules/gallery/helpers/theme.php @@ -111,7 +111,7 @@ class theme_Core { } static function get_info($theme_name) { - $theme_name = preg_replace("/[^\w]/", "", $theme_name); + $theme_name = preg_replace("/[^a-zA-Z0-9\._-]/", "", $theme_name); $file = THEMEPATH . "$theme_name/theme.info"; $theme_info = new ArrayObject(parse_ini_file($file), ArrayObject::ARRAY_AS_PROPS); $theme_info->description = t($theme_info->description); -- cgit v1.2.3 From 0ff81c7ded9e61a16a2f900edfbe98d48847bf59 Mon Sep 17 00:00:00 2001 From: Bharat Mediratta Date: Mon, 9 Aug 2010 15:18:25 -0700 Subject: The root album's edit form doesn't have a name field, so don't count on it being there in update(). Fixes ticket #1281. --- modules/gallery/controllers/albums.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'modules/gallery/controllers') diff --git a/modules/gallery/controllers/albums.php b/modules/gallery/controllers/albums.php index f3f5dee3..fb7d5c59 100644 --- a/modules/gallery/controllers/albums.php +++ b/modules/gallery/controllers/albums.php @@ -132,7 +132,9 @@ class Albums_Controller extends Items_Controller { $album->description = $form->edit_item->description->value; $album->sort_column = $form->edit_item->sort_order->column->value; $album->sort_order = $form->edit_item->sort_order->direction->value; - $album->name = $form->edit_item->inputs["name"]->value; + if (array_key_exists("name", $form->edit_item->inputs)) { + $album->name = $form->edit_item->inputs["name"]->value; + } $album->slug = $form->edit_item->slug->value; $album->validate(); } catch (ORM_Validation_Exception $e) { -- cgit v1.2.3 From f0d8aef0ead373f310c59c665f8973264815e784 Mon Sep 17 00:00:00 2001 From: Bharat Mediratta Date: Mon, 9 Aug 2010 22:51:14 -0700 Subject: "Content-type" --> "Content-Type". --- modules/gallery/controllers/file_proxy.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'modules/gallery/controllers') diff --git a/modules/gallery/controllers/file_proxy.php b/modules/gallery/controllers/file_proxy.php index 15b4279f..d4e0d4c7 100644 --- a/modules/gallery/controllers/file_proxy.php +++ b/modules/gallery/controllers/file_proxy.php @@ -127,7 +127,7 @@ class File_Proxy_Controller extends Controller { // Dump out the image. If the item is a movie, then its thumbnail will be a JPG. if ($item->is_movie() && $type != "albums") { - header("Content-type: image/jpeg"); + header("Content-Type: image/jpeg"); } else { header("Content-Type: $item->mime_type"); } -- cgit v1.2.3 From 524554c65b363adfd264c66dafe0671ba5115a1f Mon Sep 17 00:00:00 2001 From: Bharat Mediratta Date: Wed, 11 Aug 2010 21:02:57 -0700 Subject: Send back the content length of files. This fixes streaming movies. Fixes ticket #974. --- modules/gallery/controllers/file_proxy.php | 2 ++ 1 file changed, 2 insertions(+) (limited to 'modules/gallery/controllers') diff --git a/modules/gallery/controllers/file_proxy.php b/modules/gallery/controllers/file_proxy.php index d4e0d4c7..b17310c4 100644 --- a/modules/gallery/controllers/file_proxy.php +++ b/modules/gallery/controllers/file_proxy.php @@ -116,6 +116,8 @@ class File_Proxy_Controller extends Controller { throw new Kohana_404_Exception(); } + header("Content-Length: " . filesize($file)); + header("Pragma:"); // Check that the content hasn't expired or it wasn't changed since cached expires::check(2592000, $item->updated); -- cgit v1.2.3 From ff1d8aea2f2805f85ce3cc7e4079d04fb9f1bac4 Mon Sep 17 00:00:00 2001 From: Bharat Mediratta Date: Sun, 15 Aug 2010 01:59:54 -0700 Subject: We use UTF-8 everywhere. Fixes ticket #1285. --- modules/gallery/controllers/user_profile.php | 2 +- modules/gallery/tests/Sendmail_Test.php | 4 ++-- modules/gallery/views/error_admin.html.php | 2 +- modules/gallery/views/error_user.html.php | 2 +- modules/notification/helpers/notification.php | 6 +++--- modules/rest/helpers/rest.php | 2 +- modules/user/controllers/password.php | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) (limited to 'modules/gallery/controllers') diff --git a/modules/gallery/controllers/user_profile.php b/modules/gallery/controllers/user_profile.php index 726d3e51..e992655b 100644 --- a/modules/gallery/controllers/user_profile.php +++ b/modules/gallery/controllers/user_profile.php @@ -56,7 +56,7 @@ class User_Profile_Controller extends Controller { ->to($user->email) ->subject(html::clean($form->message->subject->value)) ->header("Mime-Version", "1.0") - ->header("Content-type", "text/html; charset=iso-8859-1") + ->header("Content-type", "text/html; charset=UTF-8") ->reply_to($form->message->reply_to->value) ->message(html::purify($form->message->message->value)) ->send(); diff --git a/modules/gallery/tests/Sendmail_Test.php b/modules/gallery/tests/Sendmail_Test.php index b20543d1..b9406047 100644 --- a/modules/gallery/tests/Sendmail_Test.php +++ b/modules/gallery/tests/Sendmail_Test.php @@ -65,14 +65,14 @@ class Sendmail_Test extends Gallery_Unit_Test_Case { "From: from@gallery3.com\n" . "Reply-To: public@gallery3.com\n" . "MIME-Version: 1.0\n" . - "Content-type: text/html; charset=iso-8859-1\r\n" . + "Content-Type: text/html; charset=UTF-8\r\n" . "Subject: Test Email Unit test\r\n\r\n" . "

This is an html msg

"; $result = Sendmail_For_Test::factory() ->to("receiver@someemail.com") ->subject("Test Email Unit test") ->header("MIME-Version", "1.0") - ->header("Content-type", "text/html; charset=iso-8859-1") + ->header("Content-Type", "text/html; charset=UTF-8") ->message("

This is an html msg

") ->send() ->send_text; diff --git a/modules/gallery/views/error_admin.html.php b/modules/gallery/views/error_admin.html.php index f5004eae..af78c59c 100644 --- a/modules/gallery/views/error_admin.html.php +++ b/modules/gallery/views/error_admin.html.php @@ -120,7 +120,7 @@ font-size: 1.1em; } - + <?= t("Something went wrong!") ?>