diff options
Diffstat (limited to 'modules/gallery/helpers')
-rw-r--r-- | modules/gallery/helpers/MY_url.php | 42 | ||||
-rw-r--r-- | modules/gallery/helpers/access.php | 14 | ||||
-rw-r--r-- | modules/gallery/helpers/block_manager.php | 2 | ||||
-rw-r--r-- | modules/gallery/helpers/gallery_event.php | 7 | ||||
-rw-r--r-- | modules/gallery/helpers/gallery_installer.php | 4 | ||||
-rw-r--r-- | modules/gallery/helpers/item.php | 71 | ||||
-rw-r--r-- | modules/gallery/helpers/items_rest.php | 6 | ||||
-rw-r--r-- | modules/gallery/helpers/random.php | 50 | ||||
-rw-r--r-- | modules/gallery/helpers/tree_rest.php | 92 |
9 files changed, 251 insertions, 37 deletions
diff --git a/modules/gallery/helpers/MY_url.php b/modules/gallery/helpers/MY_url.php index 877c5ada..8ac26602 100644 --- a/modules/gallery/helpers/MY_url.php +++ b/modules/gallery/helpers/MY_url.php @@ -31,7 +31,7 @@ class url extends url_Core { return; } - $item = self::get_item_from_uri(Router::$current_uri); + $item = item::find_by_relative_url(html_entity_decode(Router::$current_uri, ENT_QUOTES)); if ($item && $item->loaded()) { Router::$controller = "{$item->type}s"; Router::$controller_path = MODPATH . "gallery/controllers/{$item->type}s.php"; @@ -41,32 +41,6 @@ class url extends url_Core { } /** - * Locate an item using the URI. We assume that the uri is in the form /a/b/c where each - * component matches up with an item slug. - * @param string $uri the uri fragment - * @return Item_Model - */ - static function get_item_from_uri($uri) { - $current_uri = html_entity_decode($uri, ENT_QUOTES); - // In most cases, we'll have an exact match in the relative_url_cache item field. - // but failing that, walk down the tree until we find it. The fallback code will fix caches - // as it goes, so it'll never be run frequently. - $item = ORM::factory("item")->where("relative_url_cache", "=", $current_uri)->find(); - if (!$item->loaded()) { - $count = count(Router::$segments); - foreach (ORM::factory("item") - ->where("slug", "=", html_entity_decode(Router::$segments[$count - 1], ENT_QUOTES)) - ->where("level", "=", $count + 1) - ->find_all() as $match) { - if ($match->relative_url() == $current_uri) { - $item = $match; - } - } - } - return $item; - } - - /** * Just like url::file() except that it returns an absolute URI */ static function abs_file($path) { @@ -101,4 +75,18 @@ class url extends url_Core { static function current($qs=false, $suffix=false) { return htmlspecialchars(parent::current($qs, $suffix)); } + + /** + * Merge extra an query string onto a given url safely. + * @param string the original url + * @param array the query string data in key=value form + */ + static function merge_querystring($url, $query_params) { + $qs = implode("&", $query_params); + if (strpos($url, "?") === false) { + return $url . "?$qs"; + } else { + return $url . "&$qs"; + } + } } diff --git a/modules/gallery/helpers/access.php b/modules/gallery/helpers/access.php index 0b0dcbc1..4148049a 100644 --- a/modules/gallery/helpers/access.php +++ b/modules/gallery/helpers/access.php @@ -99,8 +99,12 @@ class access_Core { return true; } + // Use the nearest parent album (including the current item) so that we take advantage + // of the cache when checking many items in a single album. + $id = ($item->type == "album") ? $item->id : $item->parent_id; $resource = $perm_name == "view" ? - $item : model_cache::get("access_cache", $item->id, "item_id"); + $item : model_cache::get("access_cache", $id, "item_id"); + foreach ($user->groups() as $group) { if ($resource->__get("{$perm_name}_{$group->id}") === access::ALLOW) { return true; @@ -136,8 +140,12 @@ class access_Core { * @return boolean */ static function group_can($group, $perm_name, $item) { + // Use the nearest parent album (including the current item) so that we take advantage + // of the cache when checking many items in a single album. + $id = ($item->type == "album") ? $item->id : $item->parent_id; $resource = $perm_name == "view" ? - $item : model_cache::get("access_cache", $item->id, "item_id"); + $item : model_cache::get("access_cache", $id, "item_id"); + return $resource->__get("{$perm_name}_{$group->id}") === access::ALLOW; } @@ -426,7 +434,7 @@ class access_Core { $session = Session::instance(); $csrf = $session->get("csrf"); if (empty($csrf)) { - $csrf = md5(rand()); + $csrf = random::hash(); $session->set("csrf", $csrf); } return $csrf; diff --git a/modules/gallery/helpers/block_manager.php b/modules/gallery/helpers/block_manager.php index 2237b702..4bd649c2 100644 --- a/modules/gallery/helpers/block_manager.php +++ b/modules/gallery/helpers/block_manager.php @@ -28,7 +28,7 @@ class block_manager_Core { static function add($location, $module_name, $block_id) { $blocks = block_manager::get_active($location); - $blocks[rand()] = array($module_name, $block_id); + $blocks[random::int()] = array($module_name, $block_id); block_manager::set_active($location, $blocks); } diff --git a/modules/gallery/helpers/gallery_event.php b/modules/gallery/helpers/gallery_event.php index b59bb9b9..5d3ee6ee 100644 --- a/modules/gallery/helpers/gallery_event.php +++ b/modules/gallery/helpers/gallery_event.php @@ -178,6 +178,10 @@ class gallery_event_Core { } Session::instance()->set("active_auth_timestamp", time()); auth::clear_failed_attempts($user); + + if ($user->admin && ini_get("session.use_trans_sid")) { + message::info(t("PHP is configured with <a href=\"url\">session.use_trans_sid</a> enabled which will cause random logouts. Please disable this setting.", array("url" => "http://www.php.net/manual/en/session.configuration.php#ini.session.use-trans-sid"))); + } } static function user_auth_failed($name) { @@ -371,6 +375,9 @@ class gallery_event_Core { ->id("admin_menu") ->label(t("Admin"))); module::event("admin_menu", $admin_menu, $theme); + + $settings_menu = $admin_menu->get("settings_menu"); + sort($settings_menu->elements); } } } diff --git a/modules/gallery/helpers/gallery_installer.php b/modules/gallery/helpers/gallery_installer.php index 3d82bc69..a6b8e6a2 100644 --- a/modules/gallery/helpers/gallery_installer.php +++ b/modules/gallery/helpers/gallery_installer.php @@ -459,7 +459,7 @@ class gallery_installer { $blocks = block_manager::get_active($location); $new_blocks = array(); foreach ($blocks as $block) { - $new_blocks[rand()] = $block; + $new_blocks[random::int()] = $block; } block_manager::set_active($location, $new_blocks); } @@ -507,7 +507,7 @@ class gallery_installer { ->execute() as $row) { $new_slug = item::convert_filename_to_slug($row->slug); if (empty($new_slug)) { - $new_slug = rand(); + $new_slug = random::int(); } db::build() ->update("items") diff --git a/modules/gallery/helpers/item.php b/modules/gallery/helpers/item.php index 052b1c8e..29dd8603 100644 --- a/modules/gallery/helpers/item.php +++ b/modules/gallery/helpers/item.php @@ -210,6 +210,75 @@ class item_Core { } /** + * Find an item by its path. If there's no match, return an empty Item_Model. + * NOTE: the caller is responsible for performing security checks on the resulting item. + * @param string $path + * @return object Item_Model + */ + static function find_by_path($path) { + $path = trim($path, "/"); + + // The root path name is NULL not "", hence this workaround. + if ($path == "") { + return item::root(); + } + + // Check to see if there's an item in the database with a matching relative_path_cache value. + // Since that field is urlencoded, we must urlencoded the components of the path. + foreach (explode("/", $path) as $part) { + $encoded_array[] = rawurlencode($part); + } + $encoded_path = join("/", $encoded_array); + $item = ORM::factory("item") + ->where("relative_path_cache", "=", $encoded_path) + ->find(); + if ($item->loaded()) { + return $item; + } + + // Since the relative_path_cache field is a cache, it can be unavailable. If we don't find + // anything, fall back to checking the path the hard way. + $paths = explode("/", $path); + foreach (ORM::factory("item") + ->where("name", "=", end($paths)) + ->where("level", "=", count($paths) + 1) + ->find_all() as $item) { + if (urldecode($item->relative_path()) == $path) { + return $item; + } + } + + return new Item_Model(); + } + + + /** + * Locate an item using the URL. We assume that the url is in the form /a/b/c where each + * component matches up with an item slug. If there's no match, return an empty Item_Model + * NOTE: the caller is responsible for performing security checks on the resulting item. + * @param string $url the relative url fragment + * @return Item_Model + */ + static function find_by_relative_url($relative_url) { + // In most cases, we'll have an exact match in the relative_url_cache item field. + // but failing that, walk down the tree until we find it. The fallback code will fix caches + // as it goes, so it'll never be run frequently. + $item = ORM::factory("item")->where("relative_url_cache", "=", $relative_url)->find(); + if (!$item->loaded()) { + $segments = explode("/", $relative_url); + foreach (ORM::factory("item") + ->where("slug", "=", end($segments)) + ->where("level", "=", count($segments) + 1) + ->find_all() as $match) { + if ($match->relative_url() == $relative_url) { + $item = $match; + } + } + } + return $item; + } + + /** * Return the root Item_Model * @return Item_Model */ @@ -232,7 +301,7 @@ class item_Core { // distributed so this is going to be more efficient with larger data sets. return ORM::factory("item") ->viewable() - ->where("rand_key", "<", ((float)mt_rand()) / (float)mt_getrandmax()) + ->where("rand_key", "<", random::percent()) ->order_by("rand_key", "DESC"); } }
\ No newline at end of file diff --git a/modules/gallery/helpers/items_rest.php b/modules/gallery/helpers/items_rest.php index 08aa3279..3c09faa8 100644 --- a/modules/gallery/helpers/items_rest.php +++ b/modules/gallery/helpers/items_rest.php @@ -84,9 +84,9 @@ class items_rest_Core { if ($item->type == "album") { $members = array(); foreach ($item->viewable()->children() as $child) { - if (empty($types) || in_array($child->type, $types)) { - $members[] = rest::url("item", $child); - } + if (empty($types) || in_array($child->type, $types)) { + $members[] = rest::url("item", $child); + } } $item_rest["members"] = $members; } diff --git a/modules/gallery/helpers/random.php b/modules/gallery/helpers/random.php new file mode 100644 index 00000000..a26762bd --- /dev/null +++ b/modules/gallery/helpers/random.php @@ -0,0 +1,50 @@ +<?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. + */ +class random_Core { + /** + * Return a random 32 bit hash value. + * @param string extra entropy data + */ + static function hash($entropy="") { + return md5($entropy . uniqid(mt_rand(), true)); + } + + /** + * Return a random hexadecimal string of the given length. + * @param int the desired length of the string + */ + static function string($length) { + return substr(random::hash(), 0, $length); + } + + /** + * Return a random floating point number between 0 and 1 + */ + static function percent() { + return ((float)mt_rand()) / (float)mt_getrandmax(); + } + + /** + * Return a random number between 0 and mt_getrandmax() + */ + static function int() { + return mt_rand(); + } +}
\ No newline at end of file diff --git a/modules/gallery/helpers/tree_rest.php b/modules/gallery/helpers/tree_rest.php new file mode 100644 index 00000000..21928cbe --- /dev/null +++ b/modules/gallery/helpers/tree_rest.php @@ -0,0 +1,92 @@ +<?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. + */ +class tree_rest_Core { + /** + * The tree is rooted in a single item and can have modifiers which adjust what data is shown + * for items inside the given tree, up to the depth that you want. The entity for this resource + * is a series of items. + * + * depth=<number> + * Only traverse this far down into the tree. If there are more albums + * below this depth, provide RESTful urls to other tree resources in + * the members section. Default is infinite. + * + * type=<album|photo|movie> + * Restrict the items displayed to the given type. Default is all types. + * + * fields=<comma separated list of field names> + * In the entity section only return these fields for each item. + * Default is all fields. + */ + static function get($request) { + $item = rest::resolve($request->url); + access::required("view", $item); + + $query_params = array(); + $p = $request->params; + $where = array(); + if (isset($p->type)) { + $where[] = array("type", "=", $p->type); + $query_params[] = "type={$p->type}"; + } + + if (isset($p->depth)) { + $lowest_depth = $item->level + $p->depth; + $where[] = array("level", "<=", $lowest_depth); + $query_params[] = "depth={$p->depth}"; + } + + $fields = array(); + if (isset($p->fields)) { + $fields = explode(",", $p->fields); + $query_params[] = "fields={$p->fields}"; + } + + $entity = array(array("url" => rest::url("item", $item), + "entity" => $item->as_restful_array($fields))); + $members = array(); + foreach ($item->viewable()->descendants(null, null, $where) as $child) { + $entity[] = array("url" => rest::url("item", $child), + "entity" => $child->as_restful_array($fields)); + if (isset($lowest_depth) && $child->level == $lowest_depth) { + $members[] = url::merge_querystring(rest::url("tree", $child), $query_params); + } + } + + $result = array( + "url" => $request->url, + "entity" => $entity, + "members" => $members, + "relationships" => rest::relationships("tree", $item)); + return $result; + } + + 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) { + return url::abs_site("rest/tree/{$item->id}"); + } +} |