summaryrefslogtreecommitdiff
path: root/modules/gallery/helpers
diff options
context:
space:
mode:
Diffstat (limited to 'modules/gallery/helpers')
-rw-r--r--modules/gallery/helpers/data_rest.php93
-rw-r--r--modules/gallery/helpers/gallery.php4
-rw-r--r--modules/gallery/helpers/gallery_event.php14
-rw-r--r--modules/gallery/helpers/gallery_installer.php31
-rw-r--r--modules/gallery/helpers/gallery_task.php56
-rw-r--r--modules/gallery/helpers/identity.php7
-rw-r--r--modules/gallery/helpers/item_rest.php6
-rw-r--r--modules/gallery/helpers/items_rest.php2
-rw-r--r--modules/gallery/helpers/json.php4
-rw-r--r--modules/gallery/helpers/module.php20
-rw-r--r--modules/gallery/helpers/movie.php44
-rw-r--r--modules/gallery/helpers/photo.php12
-rw-r--r--modules/gallery/helpers/theme.php2
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);