diff options
Diffstat (limited to 'modules/gallery/helpers')
-rw-r--r-- | modules/gallery/helpers/data_rest.php | 93 | ||||
-rw-r--r-- | modules/gallery/helpers/gallery.php | 4 | ||||
-rw-r--r-- | modules/gallery/helpers/gallery_event.php | 14 | ||||
-rw-r--r-- | modules/gallery/helpers/gallery_installer.php | 31 | ||||
-rw-r--r-- | modules/gallery/helpers/gallery_task.php | 56 | ||||
-rw-r--r-- | modules/gallery/helpers/identity.php | 7 | ||||
-rw-r--r-- | modules/gallery/helpers/item_rest.php | 6 | ||||
-rw-r--r-- | modules/gallery/helpers/items_rest.php | 2 | ||||
-rw-r--r-- | modules/gallery/helpers/json.php | 4 | ||||
-rw-r--r-- | modules/gallery/helpers/module.php | 20 | ||||
-rw-r--r-- | modules/gallery/helpers/movie.php | 44 | ||||
-rw-r--r-- | modules/gallery/helpers/photo.php | 12 | ||||
-rw-r--r-- | modules/gallery/helpers/theme.php | 2 |
13 files changed, 256 insertions, 39 deletions
diff --git a/modules/gallery/helpers/data_rest.php b/modules/gallery/helpers/data_rest.php new file mode 100644 index 00000000..98c98894 --- /dev/null +++ b/modules/gallery/helpers/data_rest.php @@ -0,0 +1,93 @@ +<?php defined("SYSPATH") or die("No direct script access."); +/** + * Gallery - a web based photo album viewer and editor + * Copyright (C) 2000-2010 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. + */ + +/** + * This resource returns the raw contents of Item_Model data files. It's analogous to the + * file_proxy controller, but it uses the REST authentication model. + */ +class data_rest_Core { + static function get($request) { + $item = rest::resolve($request->url); + access::required("view", $item); + + $p = $request->params; + if (!isset($p->size) || !in_array($p->size, array("thumb", "resize", "full"))) { + throw new Rest_Exception("Bad Request", 400, array("errors" => array("size" => "invalid"))); + } + + switch ($p->size) { + case "thumb": + $file = $item->thumb_path(); + break; + + case "resize": + $file = $item->resize_path(); + break; + + case "full": + $file = $item->file_path(); + break; + } + + if (!file_exists($file)) { + throw new Kohana_404_Exception(); + } + + // Note: this code is roughly duplicated in data_rest, so if you modify this, please look to + // see if you should make the same change there as well. + // + // We don't have a cache buster in the url, so don't set cache headers here. + // We don't need to save the session for this request + Session::instance()->abort_save(); + + if ($item->is_album() && !$item->album_cover_item_id) { + // No thumbnail. Return nothing. + // @todo: what should we do here? + return; + } + + // Dump out the image. If the item is a movie, then its thumbnail will be a JPG. + if ($item->is_movie() && $p->size == "thumb") { + header("Content-Type: image/jpeg"); + } else if ($item->is_album()) { + header("Content-Type: " . $item->album_cover()->mime_type); + } else { + header("Content-Type: {$item->mime_type}"); + } + Kohana::close_buffers(false); + readfile($file); + + // We must exit here to keep the regular REST framework reply code from adding more bytes on + // at the end or tinkering with headers. + exit; + } + + static function resolve($id) { + $item = ORM::factory("item", $id); + if (!access::can("view", $item)) { + throw new Kohana_404_Exception(); + } + return $item; + } + + static function url($item, $size) { + return url::abs_site("rest/data/{$item->id}?size=$size"); + } +} diff --git a/modules/gallery/helpers/gallery.php b/modules/gallery/helpers/gallery.php index 54d16322..3f83b23d 100644 --- a/modules/gallery/helpers/gallery.php +++ b/modules/gallery/helpers/gallery.php @@ -60,7 +60,7 @@ class gallery_Core { * @return string */ static function date_time($timestamp) { - return date(module::get_var("gallery", "date_time_format", "Y-M-d H:i:s"), $timestamp); + return date(module::get_var("gallery", "date_time_format"), $timestamp); } /** @@ -69,7 +69,7 @@ class gallery_Core { * @return string */ static function date($timestamp) { - return date(module::get_var("gallery", "date_format", "Y-M-d"), $timestamp); + return date(module::get_var("gallery", "date_format"), $timestamp); } /** 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/gallery_installer.php b/modules/gallery/helpers/gallery_installer.php index f5589618..569c5118 100644 --- a/modules/gallery/helpers/gallery_installer.php +++ b/modules/gallery/helpers/gallery_installer.php @@ -23,7 +23,8 @@ class gallery_installer { $db->query("CREATE TABLE {access_caches} ( `id` int(9) NOT NULL auto_increment, `item_id` int(9), - PRIMARY KEY (`id`)) + PRIMARY KEY (`id`), + KEY (`item_id`)) DEFAULT CHARSET=utf8;"); $db->query("CREATE TABLE {access_intents} ( @@ -114,7 +115,8 @@ class gallery_installer { KEY `parent_id` (`parent_id`), KEY `type` (`type`), KEY `random` (`rand_key`), - KEY `weight` (`weight` DESC)) + KEY `weight` (`weight` DESC), + KEY `left_ptr` (`left_ptr`)) DEFAULT CHARSET=utf8;"); $db->query("CREATE TABLE {logs} ( @@ -144,8 +146,10 @@ class gallery_installer { `active` BOOLEAN default 0, `name` varchar(64) default NULL, `version` int(9) default NULL, + `weight` int(9) default NULL, PRIMARY KEY (`id`), - UNIQUE KEY(`name`)) + UNIQUE KEY(`name`), + KEY (`weight`)) DEFAULT CHARSET=utf8;"); $db->query("CREATE TABLE {outgoing_translations} ( @@ -296,7 +300,7 @@ class gallery_installer { module::set_var("gallery", "simultaneous_upload_limit", 5); module::set_var("gallery", "admin_area_timeout", 90 * 60); module::set_var("gallery", "maintenance_mode", 0); - module::set_version("gallery", 31); + module::set_version("gallery", 34); } static function upgrade($version) { @@ -561,6 +565,25 @@ class gallery_installer { module::set_var("gallery", "maintenance_mode", 0); module::set_version("gallery", $version = 31); } + + if ($version == 31) { + $db->query("ALTER TABLE {modules} ADD COLUMN `weight` int(9) DEFAULT NULL"); + $db->query("ALTER TABLE {modules} ADD KEY (`weight`)"); + db::update("modules") + ->set("weight", new Database_Expression("`id`")) + ->execute(); + module::set_version("gallery", $version = 32); + } + + if ($version == 32) { + $db->query("ALTER TABLE {items} ADD KEY (`left_ptr`)"); + module::set_version("gallery", $version = 33); + } + + if ($version == 33) { + $db->query("ALTER TABLE {access_caches} ADD KEY (`item_id`)"); + module::set_version("gallery", $version = 34); + } } static function uninstall() { diff --git a/modules/gallery/helpers/gallery_task.php b/modules/gallery/helpers/gallery_task.php index bf1355b8..6a1fc28a 100644 --- a/modules/gallery/helpers/gallery_task.php +++ b/modules/gallery/helpers/gallery_task.php @@ -26,7 +26,9 @@ class gallery_task_Core { const FIX_STATE_RUN_DUPE_SLUGS = 5; const FIX_STATE_START_DUPE_NAMES = 6; const FIX_STATE_RUN_DUPE_NAMES = 7; - const FIX_STATE_DONE = 8; + const FIX_STATE_START_MISSING_ACCESS_CACHES = 8; + const FIX_STATE_RUN_MISSING_ACCESS_CACHES = 9; + const FIX_STATE_DONE = 10; static function available_tasks() { $dirty_count = graphics::find_dirty_images_query()->count_records(); @@ -323,15 +325,14 @@ class gallery_task_Core { $total = $task->get("total"); if (empty($total)) { // mptt: 2 operations for every item - // album audit (permissions and bogus album covers): 1 operation for every album - // dupe slugs: 1 operation for each unique conflicted slug $total = 2 * db::build()->count_records("items"); + // album audit (permissions and bogus album covers): 1 operation for every album $total += db::build()->where("type", "=", "album")->count_records("items"); - foreach (self::find_dupe_slugs() as $row) { - $total++; - } - foreach (self::find_dupe_names() as $row) { - $total++; + // one operation for each missing slug, name and access cache + foreach (array("find_dupe_slugs", "find_dupe_names", "find_missing_access_caches") as $func) { + foreach (self::$func() as $row) { + $total++; + } } $task->set("total", $total); @@ -542,6 +543,36 @@ class gallery_task_Core { $completed++; if (empty($stack)) { + $state = self::FIX_STATE_START_MISSING_ACCESS_CACHES; + } + break; + + case self::FIX_STATE_START_MISSING_ACCESS_CACHES: + $stack = array(); + foreach (self::find_missing_access_caches() as $row) { + $stack[] = $row->id; + } + if ($stack) { + $task->set("stack", implode(" ", $stack)); + $state = self::FIX_STATE_RUN_MISSING_ACCESS_CACHES; + } else { + $state = self::FIX_STATE_DONE; + } + break; + + case self::FIX_STATE_RUN_MISSING_ACCESS_CACHES: + $stack = explode(" ", $task->get("stack")); + $id = array_pop($stack); + $access_cache = ORM::factory("access_cache"); + $access_cache->item_id = $id; + $access_cache->save(); + $task->set("stack", implode(" ", $stack)); + $completed++; + if (empty($stack)) { + // The new cache rows are there, but they're incorrectly populated so we have to fix + // them. If this turns out to be too slow, we'll have to refactor + // access::recalculate_permissions to allow us to do it in slices. + access::recalculate_permissions(item::root()); $state = self::FIX_STATE_DONE; } break; @@ -587,4 +618,13 @@ class gallery_task_Core { ->group_by("parent_name") ->execute(); } + + static function find_missing_access_caches() { + return db::build() + ->select("items.id") + ->from("items") + ->join("access_caches", "items.id", "access_caches.item_id", "left") + ->where("access_caches.id", "is", null) + ->execute(); + } }
\ No newline at end of file diff --git a/modules/gallery/helpers/identity.php b/modules/gallery/helpers/identity.php index 5f1664ec..5de05948 100644 --- a/modules/gallery/helpers/identity.php +++ b/modules/gallery/helpers/identity.php @@ -66,17 +66,20 @@ class identity_Core { // The installer cannot set a user into the session, so it just sets an id which we should // upconvert into a user. - // @todo set the user name into the session instead of 2 and then use it to get the user object + // @todo set the user name into the session instead of 2 and then use it to get the + // user object if ($user === 2) { auth::login(IdentityProvider::instance()->admin_user()); } - if (!$session->get("group_ids")) { + // Cache the group ids for a day to trade off performance for security updates. + if (!$session->get("group_ids") || $session->get("group_ids_timeout", 0) < time()) { $ids = array(); foreach ($user->groups() as $group) { $ids[] = $group->id; } $session->set("group_ids", $ids); + $session->set("group_ids_timeout", time() + 86400); } } catch (Exception $e) { // Log it, so we at least have so notification that we swallowed the exception. diff --git a/modules/gallery/helpers/item_rest.php b/modules/gallery/helpers/item_rest.php index 6869181d..10f9e16a 100644 --- a/modules/gallery/helpers/item_rest.php +++ b/modules/gallery/helpers/item_rest.php @@ -126,6 +126,12 @@ class item_rest_Core { } } } + + // Replace the data file, if required + if (($item->is_photo() || $item->is_movie()) && isset($request->file)) { + $item->set_data_file($request->file); + } + $item->save(); if (isset($request->params->members) && $item->sort_column == "weight") { diff --git a/modules/gallery/helpers/items_rest.php b/modules/gallery/helpers/items_rest.php index 9cca9a54..f0b68d63 100644 --- a/modules/gallery/helpers/items_rest.php +++ b/modules/gallery/helpers/items_rest.php @@ -80,7 +80,7 @@ class items_rest_Core { "relationships" => rest::relationships("item", $item)); if ($item->type == "album") { $members = array(); - foreach ($item->children() as $child) { + foreach ($item->viewable()->children() as $child) { $members[] = rest::url("item", $child); } $item_rest["members"] = $members; diff --git a/modules/gallery/helpers/json.php b/modules/gallery/helpers/json.php index a39db27a..a88608aa 100644 --- a/modules/gallery/helpers/json.php +++ b/modules/gallery/helpers/json.php @@ -25,9 +25,7 @@ class json_Core { * @param mixed $message string or object to json encode and print */ static function reply($message) { - if (!headers_sent()) { - header("Content-Type: application/json; charset=" . Kohana::CHARSET); - } + header("Content-Type: application/json; charset=" . Kohana::CHARSET); print json_encode($message); } }
\ No newline at end of file diff --git a/modules/gallery/helpers/module.php b/modules/gallery/helpers/module.php index 5134c7b3..ca6651f1 100644 --- a/modules/gallery/helpers/module.php +++ b/modules/gallery/helpers/module.php @@ -166,6 +166,16 @@ class module_Core { } else { module::set_version($module_name, 1); } + + // Set the weight of the new module, which controls the order in which the modules are + // loaded. By default, new modules are installed at the end of the priority list. Since the + // id field is monotonically increasing, the easiest way to guarantee that is to set the weight + // the same as the id. We don't know that until we save it for the first time + $module = ORM::factory("module")->where("name", "=", $module_name)->find(); + if ($module->loaded()) { + $module->weight = $module->id; + $module->save(); + } module::load_modules(); // Now the module is installed but inactive, so don't leave it in the active path @@ -314,7 +324,15 @@ class module_Core { self::$modules = array(); self::$active = array(); $kohana_modules = array(); - foreach (ORM::factory("module")->find_all() as $module) { + + // In version 32 we introduced a weight column so we can specify the module order + // If we try to use that blindly, we'll break earlier versions before they can even + // run the upgrader. + $modules = module::get_version("gallery") < 32 ? + ORM::factory("module")->find_all(): + ORM::factory("module")->order_by("weight")->find_all(); + + foreach ($modules as $module) { self::$modules[$module->name] = $module; if (!$module->active) { continue; 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/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); |