diff options
Diffstat (limited to 'modules')
45 files changed, 478 insertions, 187 deletions
diff --git a/modules/comment/helpers/comment_theme.php b/modules/comment/helpers/comment_theme.php index 89b2f57c..b807e2cf 100644 --- a/modules/comment/helpers/comment_theme.php +++ b/modules/comment/helpers/comment_theme.php @@ -19,7 +19,7 @@ */ class comment_theme_Core { static function head($theme) { - $theme->script("modules/comment/js/comment.js"); + $theme->script("comment.js"); return ""; } diff --git a/modules/comment/views/admin_block_recent_comments.html.php b/modules/comment/views/admin_block_recent_comments.html.php index 4ff24f86..516a8181 100644 --- a/modules/comment/views/admin_block_recent_comments.html.php +++ b/modules/comment/views/admin_block_recent_comments.html.php @@ -2,7 +2,7 @@ <ul> <? foreach ($comments as $i => $comment): ?> <li class="<?= ($i % 2 == 0) ? "gEvenRow" : "gOddRow" ?>"> - <img src="<?= $comment->author()->avatar_url(32, $theme->theme_url("images/avatar.jpg", true)) ?>" + <img src="<?= $comment->author()->avatar_url(32, $theme->url("images/avatar.jpg", true)) ?>" class="gAvatar" alt="<?= p::clean($comment->author_name()) ?>" width="32" diff --git a/modules/comment/views/admin_comments.html.php b/modules/comment/views/admin_comments.html.php index ad0ae8f3..9fe7164b 100644 --- a/modules/comment/views/admin_comments.html.php +++ b/modules/comment/views/admin_comments.html.php @@ -106,7 +106,7 @@ <tr id="gComment-<?= $comment->id ?>" class="<?= ($i % 2 == 0) ? "gEvenRow" : "gOddRow" ?>"> <td> <a href="#"> - <img src="<?= $comment->author()->avatar_url(40, $theme->theme_url("images/avatar.jpg", true)) ?>" + <img src="<?= $comment->author()->avatar_url(40, $theme->url("images/avatar.jpg", true)) ?>" class="gAvatar" alt="<?= p::clean($comment->author_name()) ?>" width="40" diff --git a/modules/comment/views/comment.html.php b/modules/comment/views/comment.html.php index ab72a0c8..3d17411c 100644 --- a/modules/comment/views/comment.html.php +++ b/modules/comment/views/comment.html.php @@ -2,7 +2,7 @@ <li id="gComment-<?= $comment->id; ?>"> <p class="gAuthor"> <a href="#"> - <img src="<?= $comment->author()->avatar_url(40, $theme->theme_url("images/avatar.jpg", true)) ?>" + <img src="<?= $comment->author()->avatar_url(40, $theme->url("images/avatar.jpg", true)) ?>" class="gAvatar" alt="<?= p::clean($comment->author_name()) ?>" width="40" diff --git a/modules/comment/views/comments.html.php b/modules/comment/views/comments.html.php index fa25a4e0..f7251389 100644 --- a/modules/comment/views/comments.html.php +++ b/modules/comment/views/comments.html.php @@ -10,7 +10,7 @@ <li id="gComment-<?= $comment->id ?>"> <p class="gAuthor"> <a href="#"> - <img src="<?= $comment->author()->avatar_url(40, $theme->theme_url("images/avatar.jpg", true)) ?>" + <img src="<?= $comment->author()->avatar_url(40, $theme->url("images/avatar.jpg", true)) ?>" class="gAvatar" alt="<?= p::clean($comment->author_name()) ?>" width="40" diff --git a/modules/digibug/config/digibug.php b/modules/digibug/config/digibug.php new file mode 100644 index 00000000..6cd165d1 --- /dev/null +++ b/modules/digibug/config/digibug.php @@ -0,0 +1,29 @@ +<?php defined("SYSPATH") or die("No direct script access."); +/** + * Gallery - a web based photo album viewer and editor + * Copyright (C) 2000-2009 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. + */ +/** + * PHP Mail Configuration parameters + * from => email address that appears as the from address + * line-length => word wrap length (PHP documentations suggest no larger tha 70 characters + * reply-to => what goes into the reply to header + */ +$config["ranges"] = array( + "Digibug1" => array("low" => "65.249.152.0", "high" => "65.249.159.255"), + "Digibug2" => array("low" => "208.122.55.0", "high" => "208.122.55.255") +); diff --git a/modules/digibug/controllers/digibug.php b/modules/digibug/controllers/digibug.php index d881db9b..e0f4b6bf 100644 --- a/modules/digibug/controllers/digibug.php +++ b/modules/digibug/controllers/digibug.php @@ -21,7 +21,7 @@ class Digibug_Controller extends Controller { public function print_photo($id) { access::verify_csrf(); $item = ORM::factory("item", $id); - access::required("view_full", $item); + access::required("view", $item); if (access::group_can(group::everybody(), "view_full", $item)) { $full_url = $item->file_url(true); @@ -56,6 +56,30 @@ class Digibug_Controller extends Controller { } public function print_proxy($type, $id) { + // If its a request for the full size then make sure we are coming from an + // authorized address + if ($type == "full") { + $remote_addr = ip2long($this->input->server("REMOTE_ADDR")); + if ($remote_addr === false) { + Kohana::show_404(); + } + $config = Kohana::config("digibug"); + + $authorized = false; + foreach ($config["ranges"] as $ip_range) { + $low = ip2long($ip_range["low"]); + $high = ip2long($ip_range["high"]); + $authorized = $low !== false && $high !== false && + $low <= $remote_addr && $remote_addr <= $high; + if ($authorized) { + break; + } + } + if (!$authorized) { + Kohana::show_404(); + } + } + $proxy = ORM::factory("digibug_proxy", array("uuid" => $id)); if (!$proxy->loaded || !$proxy->item->loaded) { Kohana::show_404(); @@ -69,16 +93,18 @@ class Digibug_Controller extends Controller { // We don't need to save the session for this request Session::abort_save(); - // Dump out the image - header("Content-Type: $proxy->item->mime_type"); - Kohana::close_buffers(false); - $fd = fopen($file, "rb"); - fpassthru($fd); - fclose($fd); + if (!TEST_MODE) { + // Dump out the image + header("Content-Type: $proxy->item->mime_type"); + Kohana::close_buffers(false); + $fd = fopen($file, "rb"); + fpassthru($fd); + fclose($fd); - // If the request was for the image and not the thumb, then delete the proxy. - if ($type == "full") { - $proxy->delete(); + // If the request was for the image and not the thumb, then delete the proxy. + if ($type == "full") { + $proxy->delete(); + } } $this->_clean_expired(); @@ -89,8 +115,8 @@ class Digibug_Controller extends Controller { } private function _clean_expired() { - Database::instance()>query( - "DELETE FROM {digibug_proxy} " . + Database::instance()->query( + "DELETE FROM {digibug_proxies} " . "WHERE request_date <= (CURDATE() - INTERVAL 10 DAY) " . "LIMIT 20"); } diff --git a/modules/digibug/helpers/digibug_menu.php b/modules/digibug/helpers/digibug_menu.php index c95cada2..3f70fa24 100644 --- a/modules/digibug/helpers/digibug_menu.php +++ b/modules/digibug/helpers/digibug_menu.php @@ -37,7 +37,7 @@ class digibug_menu { } static function thumb($menu, $theme, $item) { - if ($item->type == "photo" && access::can("view_full", $item)) { + if ($item->type == "photo") { $menu->get("options_menu") ->append( Menu::factory("link") diff --git a/modules/digibug/helpers/digibug_theme.php b/modules/digibug/helpers/digibug_theme.php index f94d07c6..ceda55b5 100644 --- a/modules/digibug/helpers/digibug_theme.php +++ b/modules/digibug/helpers/digibug_theme.php @@ -19,6 +19,6 @@ */ class digibug_theme_Core { static function head($theme) { - $theme->script("modules/digibug/js/digibug.js"); + $theme->script("digibug.js"); } } diff --git a/modules/digibug/tests/Digibug_Controller_Test.php b/modules/digibug/tests/Digibug_Controller_Test.php new file mode 100644 index 00000000..859ff637 --- /dev/null +++ b/modules/digibug/tests/Digibug_Controller_Test.php @@ -0,0 +1,78 @@ +<?php defined("SYSPATH") or die("No direct script access."); +/** + * Gallery - a web based photo album viewer and editor + * Copyright (C) 2000-2009 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 Digibug_Controller_Test extends Unit_Test_Case { + private $_proxy; + private $_item; + private $_server; + + public function teardown() { + $_SERVER = $this->_server; + + if ($this->_proxy) { + $this->_proxy->delete(); + } + } + + public function setup() { + $this->_server = $_SERVER; + + $root = ORM::factory("item", 1); + $this->_album = album::create($root, rand(), "test album"); + access::deny(group::everybody(), "view_full", $this->_album); + access::deny(group::registered_users(), "view_full", $this->_album); + + $rand = rand(); + $this->_item = photo::create($this->_album, MODPATH . "gallery/tests/test.jpg", "$rand.jpg", + $rand, $rand); + $this->_proxy = ORM::factory("digibug_proxy"); + $this->_proxy->uuid = md5(rand()); + $this->_proxy->item_id = $this->_item->id; + $this->_proxy->save(); + } + + public function digibug_request_thumb_test() { + $controller = new Digibug_Controller(); + $controller->print_proxy("thumb", $this->_proxy->uuid); + } + + public function digibug_request_full_malicious_ip_test() { + $_SERVER["REMOTE_ADDR"] = "123.123.123.123"; + try { + $controller = new Digibug_Controller(); + $controller->print_proxy("full", $this->_proxy->uuid); + $this->assert_true(false, "Should have failed with an 404 exception"); + } catch (Kohana_404_Exception $e) { + // expected behavior + } + } + + public function digibug_request_full_authorized_ip_test() { + $config = Kohana::config("digibug"); + $this->assert_true(!empty($config), "The Digibug config is empty"); + + $ranges = array_values($config["ranges"]); + $low = ip2long($ranges[0]["low"]); + $high = ip2long($ranges[0]["high"]); + + $_SERVER["REMOTE_ADDR"] = long2ip(rand($low, $high)); + $controller = new Digibug_Controller(); + $controller->print_proxy("full", $this->_proxy->uuid); + } +} diff --git a/modules/gallery/controllers/albums.php b/modules/gallery/controllers/albums.php index 56b74cb1..4fefd3a1 100644 --- a/modules/gallery/controllers/albums.php +++ b/modules/gallery/controllers/albums.php @@ -166,7 +166,8 @@ class Albums_Controller extends Items_Controller { access::required("view", $album); access::required("edit", $album); - $form = album::get_edit_form($album); + $view = album::get_edit_form($album); + $form = $view->form; if ($valid = $form->validate()) { // Make sure that there's not a conflict if ($album->id != 1 && @@ -202,7 +203,7 @@ class Albums_Controller extends Items_Controller { } else { print json_encode( array("result" => "error", - "form" => $form->__toString())); + "form" => $view->__toString())); } } diff --git a/modules/gallery/controllers/movies.php b/modules/gallery/controllers/movies.php index c8227d74..1391c4b4 100644 --- a/modules/gallery/controllers/movies.php +++ b/modules/gallery/controllers/movies.php @@ -70,7 +70,8 @@ class Movies_Controller extends Items_Controller { access::required("view", $photo); access::required("edit", $photo); - $form = photo::get_edit_form($photo); + $view = photo::get_edit_form($photo); + $form = $view->form; if ($valid = $form->validate()) { // Make sure that there's not a conflict if (Database::instance() @@ -101,7 +102,7 @@ class Movies_Controller extends Items_Controller { } else { print json_encode( array("result" => "error", - "form" => $form->__toString())); + "form" => $view->__toString())); } } diff --git a/modules/gallery/controllers/photos.php b/modules/gallery/controllers/photos.php index 8ee24da8..9d9b25a1 100644 --- a/modules/gallery/controllers/photos.php +++ b/modules/gallery/controllers/photos.php @@ -61,7 +61,8 @@ class Photos_Controller extends Items_Controller { access::required("view", $photo); access::required("edit", $photo); - $form = photo::get_edit_form($photo); + $view = photo::get_edit_form($photo); + $form = $view->form; if ($valid = $form->validate()) { if ($form->edit_item->filename->value != $photo->name) { // Make sure that there's not a conflict @@ -94,7 +95,7 @@ class Photos_Controller extends Items_Controller { } else { print json_encode( array("result" => "error", - "form" => $form->__toString())); + "form" => $view->__toString())); } } diff --git a/modules/gallery/helpers/access.php b/modules/gallery/helpers/access.php index 224b51e0..c84527f4 100644 --- a/modules/gallery/helpers/access.php +++ b/modules/gallery/helpers/access.php @@ -66,9 +66,10 @@ * the Access_Intent_Model */ class access_Core { - const DENY = 0; - const ALLOW = 1; - const UNKNOWN = 2; + const DENY = false; + const ALLOW = true; + const INHERIT = null; // access_intent + const UNKNOWN = null; // cache (access_cache, items) /** * Does the active user have this permission on this item? @@ -100,8 +101,8 @@ class access_Core { $resource = $perm_name == "view" ? $item : model_cache::get("access_cache", $item->id, "item_id"); - foreach (user::group_ids() as $id) { - if ($resource->__get("{$perm_name}_$id") === self::ALLOW) { + foreach ($user->groups as $group) { + if ($resource->__get("{$perm_name}_{$group->id}") === self::ALLOW) { return true; } } @@ -141,7 +142,7 @@ class access_Core { * @param Group_Model $group * @param string $perm_name * @param Item_Model $item - * @return integer access::ALLOW, access::DENY or null for no intent + * @return boolean access::ALLOW, access::DENY or access::INHERIT (null) for no intent */ static function group_intent($group, $perm_name, $item) { $intent = model_cache::get("access_intent", $item->id, "item_id"); @@ -169,7 +170,7 @@ class access_Core { ->where("`right` >= $item->right") ->where("items.id <> $item->id") ->join("access_intents", "items.id", "access_intents.item_id") - ->where("access_intents.view_$group->id", 0) + ->where("access_intents.view_$group->id", self::DENY) ->orderby("level", "DESC") ->limit(1) ->find(); @@ -253,7 +254,7 @@ class access_Core { if ($item->id == 1) { throw new Exception("@todo CANT_RESET_ROOT_PERMISSION"); } - self::_set($group, $perm_name, $item, null); + self::_set($group, $perm_name, $item, self::INHERIT); } /** @@ -455,9 +456,10 @@ class access_Core { $db = Database::instance(); $field = "{$perm_name}_{$group->id}"; $cache_table = $perm_name == "view" ? "items" : "access_caches"; - $db->query("ALTER TABLE {{$cache_table}} ADD `$field` SMALLINT NOT NULL DEFAULT 0"); - $db->query("ALTER TABLE {access_intents} ADD `$field` BOOLEAN DEFAULT NULL"); - $db->update("access_intents", array($field => 0), array("item_id" => 1)); + $not_null = $cache_table == "items" ? "" : "NOT NULL"; + $db->query("ALTER TABLE {{$cache_table}} ADD `$field` BINARY $not_null DEFAULT FALSE"); + $db->query("ALTER TABLE {access_intents} ADD `$field` BINARY DEFAULT NULL"); + $db->update("access_intents", array($field => self::DENY), array("item_id" => 1)); model_cache::clear(); ORM::factory("access_intent")->clear_cache(); } @@ -513,7 +515,7 @@ class access_Core { ->where("left >=", $item->left) ->where("right <=", $item->right) ->where("type", "album") - ->where("access_intents.$field IS NOT", null) + ->where("access_intents.$field IS NOT", self::INHERIT) ->orderby("level", "DESC") ->find_all(); foreach ($query as $row) { @@ -557,12 +559,12 @@ class access_Core { // // @todo To optimize this, we wouldn't need to propagate from the parent, we could just // propagate from here with the parent's intent. - if ($access->$field === null) { + if ($access->$field === self::INHERIT) { $tmp_item = ORM::factory("item") ->join("access_intents", "items.id", "access_intents.item_id") ->where("left <", $item->left) ->where("right >", $item->right) - ->where("$field IS NOT", null) + ->where("$field IS NOT", self::UNKNOWN) ->orderby("left", "DESC") ->limit(1) ->find(); @@ -578,12 +580,13 @@ class access_Core { ->join("items", "items.id", "access_intents.item_id") ->where("left >=", $item->left) ->where("right <=", $item->right) - ->where("$field IS NOT", null) + ->where("$field IS NOT", self::INHERIT) ->orderby("level", "ASC") ->find_all(); foreach ($query as $row) { + $value = ($row->$field === self::ALLOW) ? "TRUE" : "FALSE"; $db->query( - "UPDATE {access_caches} SET `$field` = {$row->$field} " . + "UPDATE {access_caches} SET `$field` = $value " . "WHERE `item_id` IN " . " (SELECT `id` FROM {items} " . " WHERE `left` >= $row->left " . diff --git a/modules/gallery/helpers/album.php b/modules/gallery/helpers/album.php index 5f10bd02..0263e0e1 100644 --- a/modules/gallery/helpers/album.php +++ b/modules/gallery/helpers/album.php @@ -94,9 +94,11 @@ class album_Core { } static function get_edit_form($parent) { - $form = new Forge("albums/{$parent->id}", "", "post", array("id" => "gEditAlbumForm")); - $form->hidden("_method")->value("put"); - $group = $form->group("edit_item")->label(t("Edit Album")); + $view = new View("item_edit.html"); + $view->script = array(); + $view->form = new Forge("albums/{$parent->id}", "", "post", array("id" => "gEditAlbumForm")); + $view->form->hidden("_method")->value("put"); + $group = $view->form->group("edit_item")->label(t("Edit Album")); $group->input("title")->label(t("Title"))->value($parent->title); $group->textarea("description")->label(t("Description"))->value($parent->description); @@ -127,11 +129,11 @@ class album_Core { "DESC" => t("Descending"))) ->selected($parent->sort_order); - module::event("item_edit_form", $parent, $form); + module::event("item_edit_form", $parent, $view); $group->hidden("type")->value("album"); $group->submit("")->value(t("Modify")); - $form->add_rules_from(ORM::factory("item")); - return $form; + $view->form->add_rules_from(ORM::factory("item")); + return $view; } } diff --git a/modules/gallery/helpers/gallery.php b/modules/gallery/helpers/gallery.php index a32ac484..2fa7ad1c 100644 --- a/modules/gallery/helpers/gallery.php +++ b/modules/gallery/helpers/gallery.php @@ -18,7 +18,7 @@ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ class gallery_Core { - const VERSION = "3.0 beta 2"; + const VERSION = "3.0 git (pre-beta3)"; /** * If Gallery is in maintenance mode, then force all non-admins to get routed to a "This site is diff --git a/modules/gallery/helpers/gallery_installer.php b/modules/gallery/helpers/gallery_installer.php index 28c1990f..db13307f 100644 --- a/modules/gallery/helpers/gallery_installer.php +++ b/modules/gallery/helpers/gallery_installer.php @@ -305,6 +305,24 @@ class gallery_installer { module::clear_var("gallery", "version"); module::set_version("gallery", $version = 7); } + + if ($version == 7) { + $groups = ORM::factory("group")->find_all(); + $permissions = ORM::factory("permission")->find_all(); + foreach($groups as $group) { + foreach($permissions as $permission) { + // Update access intents + $db->query("ALTER TABLE {access_intents} MODIFY COLUMN {$permission->name}_{$group->id} BINARY(1) DEFAULT NULL"); + // Update access cache + if ($permission->name === "view") { + $db->query("ALTER TABLE {items} MODIFY COLUMN {$permission->name}_{$group->id} BINARY(1) DEFAULT FALSE"); + } else { + $db->query("ALTER TABLE {access_caches} MODIFY COLUMN {$permission->name}_{$group->id} BINARY(1) NOT NULL DEFAULT FALSE"); + } + } + } + module::set_version("gallery", $version = 8); + } } static function uninstall() { diff --git a/modules/gallery/helpers/gallery_quick.php b/modules/gallery/helpers/gallery_quick.php index d0ffc584..8a92890b 100644 --- a/modules/gallery/helpers/gallery_quick.php +++ b/modules/gallery/helpers/gallery_quick.php @@ -108,12 +108,20 @@ class gallery_quick_Core { "href" => url::site("move/browse/$item->id")); } - if (access::can("edit", $item->parent())) { - $disabledState = - $item->type == "album" && empty($item->album_cover_item_id) ? " ui-state-disabled" : ""; + $parent = $item->parent(); + if (access::can("edit", $parent)) { + // We can't make this item the highlight if it's an album with no album cover, or if it's + // already the album cover. + if (($item->type == "album" && empty($item->album_cover_item_id)) || + ($item->type == "album" && $parent->album_cover_item_id == $item->album_cover_item_id) || + $parent->album_cover_item_id == $item->id) { + $disabledState = " ui-state-disabled"; + } else { + $disabledState = " "; + } $elements["right"][] = (object)array( "title" => $cover_title, - "class" => "gButtonLink{$disabledState}", + "class" => "gButtonLink$disabledState", "icon" => "ui-icon-star", "href" => url::site("quick/make_album_cover/$item->id?csrf=$csrf&page_type=$page_type")); diff --git a/modules/gallery/helpers/gallery_theme.php b/modules/gallery/helpers/gallery_theme.php index f245ea31..998eb289 100644 --- a/modules/gallery/helpers/gallery_theme.php +++ b/modules/gallery/helpers/gallery_theme.php @@ -22,12 +22,12 @@ class gallery_theme_Core { $session = Session::instance(); $buf = ""; if ($session->get("debug")) { - $theme->css("modules/gallery/css/debug.css"); + $theme->css("debug.css"); } if (($theme->page_type == "album" || $theme->page_type == "photo") && access::can("edit", $theme->item())) { - $theme->css("modules/gallery/css/quick.css"); - $theme->script("modules/gallery/js/quick.js"); + $theme->css("quick.css"); + $theme->script("quick.js"); } if (module::is_active("rss")) { @@ -43,9 +43,9 @@ class gallery_theme_Core { } if ($session->get("l10n_mode", false)) { - $theme->css("modules/gallery/css/l10n_client.css"); - $theme->script("lib/jquery.cookie.js"); - $theme->script("modules/gallery/js/l10n_client.js"); + $theme->css("l10n_client.css"); + $theme->script("jquery.cookie.js"); + $theme->script("l10n_client.js"); } return $buf; @@ -80,13 +80,13 @@ class gallery_theme_Core { static function admin_head($theme) { $session = Session::instance(); if ($session->get("debug")) { - $theme->css("modules/gallery/css/debug.css"); + $theme->css("debug.css"); } if ($session->get("l10n_mode", false)) { - $theme->css("modules/gallery/css/l10n_client.css"); - $theme->script("lib/jquery.cookie.js"); - $theme->script("modules/gallery/js/l10n_client.js"); + $theme->css("l10n_client.css"); + $theme->script("jquery.cookie.js"); + $theme->script("l10n_client.js"); } } diff --git a/modules/gallery/helpers/photo.php b/modules/gallery/helpers/photo.php index 5cf37de1..299195e9 100644 --- a/modules/gallery/helpers/photo.php +++ b/modules/gallery/helpers/photo.php @@ -135,9 +135,11 @@ class photo_Core { } static function get_edit_form($photo) { - $form = new Forge("photos/$photo->id", "", "post", array("id" => "gEditPhotoForm")); - $form->hidden("_method")->value("put"); - $group = $form->group("edit_item")->label(t("Edit Photo")); + $view = new View("item_edit.html"); + $view->script = array(); + $view->form = new Forge("photos/$photo->id", "", "post", array("id" => "gEditPhotoForm")); + $view->form->hidden("_method")->value("put"); + $group = $view->form->group("edit_item")->label(t("Edit Photo")); $group->input("title")->label(t("Title"))->value($photo->title); $group->textarea("description")->label(t("Description"))->value($photo->description); $group->input("filename")->label(t("Filename"))->value($photo->name) @@ -147,11 +149,11 @@ class photo_Core { ->callback("item::validate_no_trailing_period") ->error_messages("no_trailing_period", t("The photo name can't end in \".\"")); - module::event("item_edit_form", $photo, $form); + module::event("item_edit_form", $photo, $view); $group->submit("")->value(t("Modify")); - $form->add_rules_from(ORM::factory("item")); - return $form; + $view->form->add_rules_from(ORM::factory("item")); + return $view; } /** diff --git a/modules/gallery/libraries/Gallery_View.php b/modules/gallery/libraries/Gallery_View.php index 31231ca6..219cc883 100644 --- a/modules/gallery/libraries/Gallery_View.php +++ b/modules/gallery/libraries/Gallery_View.php @@ -27,24 +27,20 @@ class Gallery_View_Core extends View { * @param $file the relative path to a script from the gallery3 directory */ public function script($file) { - $this->scripts[$file] = 1; - } - - /** - * Add a script to the combined scripts list. - * @param $file the relative path to a script from the base of the active theme - * @param - */ - public function theme_script($file) { - $file = "themes/{$this->theme_name}/$file"; - $this->scripts[$file] = 1; + $base_file = str_replace(".js", "", $file); + if (($path = Kohana::find_file("js", $base_file, false, "js")) || + file_exists($path = DOCROOT . "lib/$file")) { + $this->scripts[$path] = 1; + } else { + Kohana::log("error", "Can't find script file: $file"); + } } /** * Provide a url to a resource within the current theme. This allows us to refer to theme * resources without naming the theme itself which makes themes easier to copy. */ - public function theme_url($path, $absolute_url=false) { + public function url($path, $absolute_url=false) { $arg = "themes/{$this->theme_name}/$path"; return $absolute_url ? url::abs_file($arg) : url::file($arg); } @@ -53,27 +49,23 @@ class Gallery_View_Core extends View { * Add a css file to the combined css list. * @param $file the relative path to a script from the gallery3 directory */ - public function css($file, $theme_relative=false) { - $this->css[$file] = 1; - } - - /** - * Add a css file to the combined css list. - * @param $file the relative path to a script from the base of the active theme - * @param - */ - public function theme_css($file) { - $file = "themes/{$this->theme_name}/$file"; - $this->css[$file] = 1; + public function css($file) { + $base_file = str_replace(".css", "", $file); + if (($path = Kohana::find_file("css", $base_file, false, "css")) || + file_exists($path = DOCROOT . "lib/$file")) { + $this->css[$path] = 1; + } else { + Kohana::log("error", "Can't find css file: $file"); + } } /** * Combine a series of files into a single one and cache it in the database. */ - protected function combine_files($files, $type) { + protected function combine_files($paths, $type) { $links = array(); - if (empty($files)) { + if (empty($paths)) { return; } @@ -81,16 +73,10 @@ class Gallery_View_Core extends View { // entries. $key = array(url::abs_file("")); - foreach (array_keys($files) as $file) { - $path = DOCROOT . $file; - if (file_exists($path)) { - $stats = stat($path); - $links[$file] = $path; - // 7 == size, 9 == mtime, see http://php.net/stat - $key[] = "$file $stats[7] $stats[9]"; - } else { - Kohana::log("error", "missing file ($type): $file"); - } + foreach (array_keys($paths) as $path) { + $stats = stat($path); + // 7 == size, 9 == mtime, see http://php.net/stat + $key[] = "$path $stats[7] $stats[9]"; } $key = md5(join(" ", $key)); @@ -99,11 +85,13 @@ class Gallery_View_Core extends View { if (empty($contents)) { $contents = ""; - foreach ($links as $file => $link) { + $docroot_len = strlen(DOCROOT); + foreach (array_keys($paths) as $path) { + $relative = substr($path, $docroot_len); if ($type == "css") { - $contents .= "/* $file */\n" . $this->process_css($link) . "\n"; + $contents .= "/* $relative */\n" . $this->process_css($path) . "\n"; } else { - $contents .= "/* $file */\n" . file_get_contents($link) . "\n"; + $contents .= "/* $relative */\n" . file_get_contents($path) . "\n"; } } diff --git a/modules/gallery/module.info b/modules/gallery/module.info index cefcaa08..ba367878 100644 --- a/modules/gallery/module.info +++ b/modules/gallery/module.info @@ -1,3 +1,3 @@ name = "Gallery 3" description = "Gallery core application" -version = 7 +version = 8 diff --git a/modules/gallery/tests/Access_Helper_Test.php b/modules/gallery/tests/Access_Helper_Test.php index 1352b493..59cec453 100644 --- a/modules/gallery/tests/Access_Helper_Test.php +++ b/modules/gallery/tests/Access_Helper_Test.php @@ -64,6 +64,43 @@ class Access_Helper_Test extends Unit_Test_Case { $this->assert_false(array_key_exists("access_test_{$group->id}", $fields)); } + public function user_can_access_test() { + $access_test = group::create("access_test"); + + $root = ORM::factory("item", 1); + access::allow($access_test, "view", $root); + + $item = album::create($root, rand(), "test album"); + + access::deny(group::everybody(), "view", $item); + access::deny(group::registered_users(), "view", $item); + + $user = user::create("access_test", "Access Test", ""); + foreach ($user->groups as $group) { + $user->remove($group); + } + $user->add($access_test); + $user->save(); + + $this->assert_true(access::user_can($user, "view", $item), "Should be able to view"); + } + + public function user_can_no_access_test() { + $root = ORM::factory("item", 1); + $item = album::create($root, rand(), "test album"); + + access::deny(group::everybody(), "view", $item); + access::deny(group::registered_users(), "view", $item); + + $user = user::create("access_test", "Access Test", ""); + foreach ($user->groups as $group) { + $user->remove($group); + } + $user->save(); + + $this->assert_false(access::user_can($user, "view", $item), "Should be unable to view"); + } + public function adding_and_removing_items_adds_ands_removes_rows_test() { $root = ORM::factory("item", 1); $item = album::create($root, rand(), "test album"); diff --git a/modules/gallery/tests/xss_data.txt b/modules/gallery/tests/xss_data.txt index ce2fa2a5..2940a8df 100644 --- a/modules/gallery/tests/xss_data.txt +++ b/modules/gallery/tests/xss_data.txt @@ -2,7 +2,7 @@ modules/akismet/views/admin_akismet.html.php 14 DIRTY $form modules/akismet/views/admin_akismet_stats.html.php 9 DIRTY $api_key modules/akismet/views/admin_akismet_stats.html.php 9 DIRTY $blog_url modules/comment/views/admin_block_recent_comments.html.php 4 DIRTY $i -modules/comment/views/admin_block_recent_comments.html.php 5 DIRTY $comment->author()->avatar_url(32, $theme->theme_url("images/avatar.jpg", true)) +modules/comment/views/admin_block_recent_comments.html.php 5 DIRTY $comment->author()->avatar_url(32, $theme->url("images/avatar.jpg", true)) modules/comment/views/admin_block_recent_comments.html.php 7 $comment->author_name() modules/comment/views/admin_block_recent_comments.html.php 10 DIRTY $comment->created modules/comment/views/admin_block_recent_comments.html.php 12 $comment->author_name() @@ -15,7 +15,7 @@ modules/comment/views/admin_comments.html.php 72 DIRTY $counts-> modules/comment/views/admin_comments.html.php 75 DIRTY $csrf modules/comment/views/admin_comments.html.php 106 DIRTY $comment->id modules/comment/views/admin_comments.html.php 106 DIRTY $i -modules/comment/views/admin_comments.html.php 109 DIRTY $comment->author()->avatar_url(40, $theme->theme_url("images/avatar.jpg", true)) +modules/comment/views/admin_comments.html.php 109 DIRTY $comment->author()->avatar_url(40, $theme->url("images/avatar.jpg", true)) modules/comment/views/admin_comments.html.php 111 $comment->author_name() modules/comment/views/admin_comments.html.php 115 $comment->author_email() modules/comment/views/admin_comments.html.php 116 $comment->author_email() @@ -35,7 +35,7 @@ modules/comment/views/admin_comments.html.php 175 DIRTY $comment- modules/comment/views/admin_comments.html.php 183 DIRTY $comment->id modules/comment/views/admin_comments.html.php 196 DIRTY $pager modules/comment/views/comment.html.php 2 DIRTY $comment->id -modules/comment/views/comment.html.php 5 DIRTY $comment->author()->avatar_url(40, $theme->theme_url("images/avatar.jpg", true)) +modules/comment/views/comment.html.php 5 DIRTY $comment->author()->avatar_url(40, $theme->url("images/avatar.jpg", true)) modules/comment/views/comment.html.php 7 $comment->author_name() modules/comment/views/comment.html.php 12 DIRTY $comment->created modules/comment/views/comment.html.php 13 $comment->author_name() @@ -58,7 +58,7 @@ modules/comment/views/comment.mrss.php 34 DIRTY $child->t modules/comment/views/comment.mrss.php 35 DIRTY $child->thumb_height modules/comment/views/comment.mrss.php 35 DIRTY $child->thumb_width modules/comment/views/comments.html.php 10 DIRTY $comment->id -modules/comment/views/comments.html.php 13 DIRTY $comment->author()->avatar_url(40, $theme->theme_url("images/avatar.jpg", true)) +modules/comment/views/comments.html.php 13 DIRTY $comment->author()->avatar_url(40, $theme->url("images/avatar.jpg", true)) modules/comment/views/comments.html.php 15 $comment->author_name() modules/comment/views/comments.html.php 20 DIRTY $comment->created modules/comment/views/comments.html.php 21 $comment->author_name() @@ -108,7 +108,7 @@ modules/gallery/views/admin_block_photo_stream.html.php 6 DIRTY $photo->w modules/gallery/views/admin_block_photo_stream.html.php 6 DIRTY $photo->height modules/gallery/views/admin_block_photo_stream.html.php 7 DIRTY $photo->thumb_url() modules/gallery/views/admin_block_photo_stream.html.php 7 $photo->title -modules/gallery/views/admin_block_platform.html.php 16 DIRTY $load_average +modules/gallery/views/admin_block_platform.html.php 19 DIRTY $load_average modules/gallery/views/admin_block_stats.html.php 7 DIRTY $album_count modules/gallery/views/admin_block_stats.html.php 10 DIRTY $photo_count modules/gallery/views/admin_dashboard.html.php 5 DIRTY $csrf @@ -207,6 +207,8 @@ modules/gallery/views/admin_themes_preview.html.php 4 DIRTY $info->na modules/gallery/views/admin_themes_preview.html.php 7 DIRTY $url modules/gallery/views/after_install.html.php 11 $user->name modules/gallery/views/after_install.html.php 15 DIRTY $user->id +modules/gallery/views/item_edit.html.php 4 DIRTY $script +modules/gallery/views/item_edit.html.php 8 DIRTY $form modules/gallery/views/kohana_error_page.php 102 DIRTY $message modules/gallery/views/kohana_error_page.php 104 DIRTY $file modules/gallery/views/kohana_error_page.php 104 DIRTY $line @@ -303,8 +305,8 @@ modules/info/views/info_block.html.php 10 $item->de modules/info/views/info_block.html.php 16 $item->name modules/info/views/info_block.html.php 22 DIRTY $item->captured modules/info/views/info_block.html.php 29 DIRTY $item->owner->url -modules/info/views/info_block.html.php 29 $item->owner->full_name -modules/info/views/info_block.html.php 31 $item->owner->name +modules/info/views/info_block.html.php 29 $item->owner->display_name() +modules/info/views/info_block.html.php 31 $item->owner->display_name() modules/notification/views/comment_published.html.php 4 $subject modules/notification/views/comment_published.html.php 7 $subject modules/notification/views/comment_published.html.php 11 $comment->text @@ -442,8 +444,8 @@ modules/tag/views/admin_tags.html.php 50 DIRTY $tag->id modules/tag/views/admin_tags.html.php 50 $tag->name modules/tag/views/admin_tags.html.php 51 DIRTY $tag->count modules/tag/views/admin_tags.html.php 52 DIRTY $tag->id -modules/tag/views/tag_block.html.php 3 DIRTY $cloud -modules/tag/views/tag_block.html.php 5 DIRTY $form +modules/tag/views/tag_block.html.php 13 DIRTY $cloud +modules/tag/views/tag_block.html.php 15 DIRTY $form modules/tag/views/tag_cloud.html.php 4 DIRTY $tag->count modules/tag/views/tag_cloud.html.php 4 DIRTY $max_count modules/tag/views/tag_cloud.html.php 5 DIRTY $tag->count @@ -454,7 +456,7 @@ modules/user/views/admin_users.html.php 36 DIRTY $csrf modules/user/views/admin_users.html.php 67 DIRTY $user->id modules/user/views/admin_users.html.php 67 DIRTY $user->admin modules/user/views/admin_users.html.php 68 DIRTY $user->id -modules/user/views/admin_users.html.php 69 DIRTY $user->avatar_url(20, $theme->theme_url("images/avatar.jpg", true)) +modules/user/views/admin_users.html.php 69 DIRTY $user->avatar_url(20, $theme->url("images/avatar.jpg", true)) modules/user/views/admin_users.html.php 71 $user->name modules/user/views/admin_users.html.php 74 $user->name modules/user/views/admin_users.html.php 77 $user->full_name @@ -475,9 +477,7 @@ modules/user/views/admin_users_group.html.php 22 DIRTY $group->i modules/user/views/admin_users_group.html.php 25 $user->name modules/user/views/admin_users_group.html.php 25 $group->name modules/user/views/login.html.php 12 DIRTY $user->id -modules/user/views/login.html.php 15 $user->full_name -modules/user/views/login.html.php 15 $user->name -modules/user/views/login.html.php 15 $user->full_name +modules/user/views/login.html.php 15 $user->display_name() modules/user/views/login.html.php 18 DIRTY $csrf modules/user/views/login_ajax.html.php 37 DIRTY $form modules/user/views/reset_password.html.php 9 $user->full_name @@ -488,20 +488,20 @@ modules/watermark/views/admin_watermarks.html.php 19 DIRTY $width modules/watermark/views/admin_watermarks.html.php 19 DIRTY $height modules/watermark/views/admin_watermarks.html.php 19 DIRTY $url modules/watermark/views/admin_watermarks.html.php 21 DIRTY $position -themes/admin_default/views/admin.html.php 10 DIRTY $theme->css("lib/yui/reset-fonts-grids.css") -themes/admin_default/views/admin.html.php 11 DIRTY $theme->css("lib/themeroller/ui.base.css") -themes/admin_default/views/admin.html.php 12 DIRTY $theme->css("lib/superfish/css/superfish.css") -themes/admin_default/views/admin.html.php 13 DIRTY $theme->css("themes/default/css/screen.css") -themes/admin_default/views/admin.html.php 14 DIRTY $theme->theme_css("css/screen.css") -themes/admin_default/views/admin.html.php 16 DIRTY $theme->theme_url("css/fix-ie.css") -themes/admin_default/views/admin.html.php 20 DIRTY $theme->script("lib/jquery.js") -themes/admin_default/views/admin.html.php 21 DIRTY $theme->script("lib/jquery.form.js") -themes/admin_default/views/admin.html.php 22 DIRTY $theme->script("lib/jquery-ui.js") -themes/admin_default/views/admin.html.php 23 DIRTY $theme->script("lib/gallery.common.js") -themes/admin_default/views/admin.html.php 28 DIRTY $theme->script("lib/gallery.dialog.js") -themes/admin_default/views/admin.html.php 29 DIRTY $theme->script("lib/superfish/js/superfish.js") -themes/admin_default/views/admin.html.php 30 DIRTY $theme->theme_script("js/jquery.dropshadow.js") -themes/admin_default/views/admin.html.php 31 DIRTY $theme->theme_script("js/ui.init.js") +themes/admin_default/views/admin.html.php 10 DIRTY $theme->css("yui/reset-fonts-grids.css") +themes/admin_default/views/admin.html.php 11 DIRTY $theme->css("themeroller/ui.base.css") +themes/admin_default/views/admin.html.php 12 DIRTY $theme->css("superfish/css/superfish.css") +themes/admin_default/views/admin.html.php 13 DIRTY $theme->css("screen.css") +themes/admin_default/views/admin.html.php 14 DIRTY $theme->css("admin_screen.css") +themes/admin_default/views/admin.html.php 16 DIRTY $theme->url("fix-ie.css") +themes/admin_default/views/admin.html.php 20 DIRTY $theme->script("jquery.js") +themes/admin_default/views/admin.html.php 21 DIRTY $theme->script("jquery.form.js") +themes/admin_default/views/admin.html.php 22 DIRTY $theme->script("jquery-ui.js") +themes/admin_default/views/admin.html.php 23 DIRTY $theme->script("gallery.common.js") +themes/admin_default/views/admin.html.php 28 DIRTY $theme->script("gallery.dialog.js") +themes/admin_default/views/admin.html.php 29 DIRTY $theme->script("superfish/js/superfish.js") +themes/admin_default/views/admin.html.php 30 DIRTY $theme->script("jquery.dropshadow.js") +themes/admin_default/views/admin.html.php 31 DIRTY $theme->script("ui.init.js") themes/admin_default/views/admin.html.php 33 DIRTY $theme->admin_head() themes/admin_default/views/admin.html.php 36 DIRTY $theme->body_attributes() themes/admin_default/views/admin.html.php 37 DIRTY $theme->admin_page_top() @@ -569,7 +569,7 @@ themes/default/views/footer.html.php 4 DIRTY $footer_t themes/default/views/footer.html.php 9 DIRTY $theme->credits() themes/default/views/header.html.php 2 DIRTY $theme->header_top() themes/default/views/header.html.php 4 DIRTY $header_text -themes/default/views/header.html.php 7 DIRTY $theme->theme_url("images/logo.png") +themes/default/views/header.html.php 7 DIRTY $theme->url("images/logo.png") themes/default/views/header.html.php 12 DIRTY $theme->site_menu() themes/default/views/header.html.php 15 DIRTY $theme->header_bottom() themes/default/views/header.html.php 21 DIRTY $parent->id @@ -590,27 +590,27 @@ themes/default/views/page.html.php 13 $theme->i themes/default/views/page.html.php 15 $theme->item()->title themes/default/views/page.html.php 17 $theme->item()->title themes/default/views/page.html.php 20 $theme->tag()->name -themes/default/views/page.html.php 26 DIRTY $theme->theme_url("images/favicon.ico") -themes/default/views/page.html.php 27 DIRTY $theme->css("lib/yui/reset-fonts-grids.css") -themes/default/views/page.html.php 28 DIRTY $theme->css("lib/superfish/css/superfish.css") -themes/default/views/page.html.php 29 DIRTY $theme->css("lib/themeroller/ui.base.css") -themes/default/views/page.html.php 30 DIRTY $theme->theme_css("css/screen.css") -themes/default/views/page.html.php 32 DIRTY $theme->theme_url("css/fix-ie.css") +themes/default/views/page.html.php 26 DIRTY $theme->url("images/favicon.ico") +themes/default/views/page.html.php 27 DIRTY $theme->css("yui/reset-fonts-grids.css") +themes/default/views/page.html.php 28 DIRTY $theme->css("superfish/css/superfish.css") +themes/default/views/page.html.php 29 DIRTY $theme->css("themeroller/ui.base.css") +themes/default/views/page.html.php 30 DIRTY $theme->css("screen.css") +themes/default/views/page.html.php 32 DIRTY $theme->url("css/fix-ie.css") themes/default/views/page.html.php 41 DIRTY $new_width themes/default/views/page.html.php 42 DIRTY $new_height themes/default/views/page.html.php 43 DIRTY $thumb_proportion -themes/default/views/page.html.php 48 DIRTY $theme->script("lib/jquery.js") -themes/default/views/page.html.php 49 DIRTY $theme->script("lib/jquery.form.js") -themes/default/views/page.html.php 50 DIRTY $theme->script("lib/jquery-ui.js") -themes/default/views/page.html.php 51 DIRTY $theme->script("lib/gallery.common.js") -themes/default/views/page.html.php 56 DIRTY $theme->script("lib/gallery.dialog.js") -themes/default/views/page.html.php 57 DIRTY $theme->script("lib/gallery.form.js") -themes/default/views/page.html.php 58 DIRTY $theme->script("lib/superfish/js/superfish.js") -themes/default/views/page.html.php 59 DIRTY $theme->script("lib/jquery.localscroll.js") -themes/default/views/page.html.php 60 DIRTY $theme->theme_script("js/ui.init.js") -themes/default/views/page.html.php 64 DIRTY $theme->script("lib/jquery.scrollTo.js") -themes/default/views/page.html.php 65 DIRTY $theme->script("lib/gallery.show_full_size.js") -themes/default/views/page.html.php 67 DIRTY $theme->script("lib/flowplayer.js") +themes/default/views/page.html.php 48 DIRTY $theme->script("jquery.js") +themes/default/views/page.html.php 49 DIRTY $theme->script("jquery.form.js") +themes/default/views/page.html.php 50 DIRTY $theme->script("jquery-ui.js") +themes/default/views/page.html.php 51 DIRTY $theme->script("gallery.common.js") +themes/default/views/page.html.php 56 DIRTY $theme->script("gallery.dialog.js") +themes/default/views/page.html.php 57 DIRTY $theme->script("gallery.form.js") +themes/default/views/page.html.php 58 DIRTY $theme->script("superfish/js/superfish.js") +themes/default/views/page.html.php 59 DIRTY $theme->script("jquery.localscroll.js") +themes/default/views/page.html.php 60 DIRTY $theme->script("ui.init.js") +themes/default/views/page.html.php 64 DIRTY $theme->script("jquery.scrollTo.js") +themes/default/views/page.html.php 65 DIRTY $theme->script("gallery.show_full_size.js") +themes/default/views/page.html.php 67 DIRTY $theme->script("flowplayer.js") themes/default/views/page.html.php 70 DIRTY $theme->head() themes/default/views/page.html.php 73 DIRTY $theme->body_attributes() themes/default/views/page.html.php 74 DIRTY $theme->page_top() diff --git a/modules/gallery/views/admin_maintenance_task.html.php b/modules/gallery/views/admin_maintenance_task.html.php index 5c2c03a1..c81fe571 100644 --- a/modules/gallery/views/admin_maintenance_task.html.php +++ b/modules/gallery/views/admin_maintenance_task.html.php @@ -1,11 +1,32 @@ <?php defined("SYSPATH") or die("No direct script access.") ?> <script type="text/javascript"> + var target_value; + var animation = null; + var delta = 1; + animate_progress_bar = function() { + var current_value = Number($(".gProgressBar div").css("width").replace("%", "")); + if (current_value != target_value) { + var new_value = Math.min(current_value + delta, target_value); + if (target_value - current_value > delta) { + delta += .075; + } + $(".gProgressBar").progressbar("value", new_value); + animation = setTimeout(function() { animate_progress_bar(target_value); }, 100); + } else { + animation = null; + delta = 1; + } + } + update = function() { $.ajax({ url: "<?= url::site("admin/maintenance/run/$task->id?csrf=$csrf") ?>", dataType: "json", success: function(data) { - $(".gProgressBar").progressbar("value", data.task.percent_complete); + target_value = data.task.percent_complete; + if (!animation) { + animate_progress_bar(); + } $("#gStatus").html("" + data.task.status); if (data.task.done) { $("#gPauseButton").hide(); diff --git a/modules/gallery/views/item_edit.html.php b/modules/gallery/views/item_edit.html.php new file mode 100644 index 00000000..9aa2fb64 --- /dev/null +++ b/modules/gallery/views/item_edit.html.php @@ -0,0 +1,9 @@ +<?php defined("SYSPATH") or die("No direct script access.") ?> +<? if (!empty($script)): ?> +<script> + <?= implode("\n", $script) ?> +</script> +<? endif ?> +<div id="gEditFormContainer"> + <?= $form ?> +</div>
\ No newline at end of file diff --git a/modules/gallery/views/permissions_form.html.php b/modules/gallery/views/permissions_form.html.php index 0f60070a..ee5e3a24 100644 --- a/modules/gallery/views/permissions_form.html.php +++ b/modules/gallery/views/permissions_form.html.php @@ -26,7 +26,7 @@ </a> </td> <? else: ?> - <? if ($intent === null): ?> + <? if ($intent === access::INHERIT): ?> <? if ($allowed): ?> <td class="gAllowed"> <a href="javascript:set('allow',<?= $group->id ?>,<?= $permission->id ?>,<?= $item->id ?>)" diff --git a/modules/notification/helpers/notification.php b/modules/notification/helpers/notification.php index e246af2c..d91a37e8 100644 --- a/modules/notification/helpers/notification.php +++ b/modules/notification/helpers/notification.php @@ -67,6 +67,8 @@ class notification { } static function get_subscribers($item) { + // @todo don't access the user table directly + // @todo only return distinct email addresses $users = ORM::factory("user") ->join("subscriptions", "users.id", "subscriptions.user_id") ->join("items", "subscriptions.item_id", "items.id") @@ -77,9 +79,11 @@ class notification { $subscribers = array(); foreach ($users as $user) { - $subscribers[] = $user->email; + if (access::user_can($user, "view", $item)) { + $subscribers[$user->email] = 1; + } } - return $subscribers; + return array_keys($subscribers); } static function send_item_updated($item) { @@ -103,8 +107,8 @@ class notification { array("title" => $item->title, "parent_title" => $parent->title)) : ($item->is_photo() ? t("Photo %title added to %parent_title", - array("title" => $item->title, "parent_title" => $parent->title)) - : t("Movie %title added to %parent_title", + array("title" => $item->title, "parent_title" => $parent->title)) : + t("Movie %title added to %parent_title", array("title" => $item->title, "parent_title" => $parent->title))); self::_notify_subscribers($item, $v->render(), $v->subject); diff --git a/modules/notification/helpers/notification_menu.php b/modules/notification/helpers/notification_menu.php index 87478b8a..73d1dd03 100644 --- a/modules/notification/helpers/notification_menu.php +++ b/modules/notification/helpers/notification_menu.php @@ -22,10 +22,10 @@ class notification_menu_Core { if (!user::active()->guest) { $item = $theme->item(); - if ($item && $item->is_album()) { + if ($item && $item->is_album() && access::can("view", $item)) { $watching = notification::is_watching($item); - $watching ? $label = t("Remove notifications") : $label = t("Enable notifications"); + $label = $watching ? t("Remove notifications") : t("Enable notifications"); $menu->get("options_menu") ->append(Menu::factory("link") diff --git a/modules/organize/helpers/organize_theme.php b/modules/organize/helpers/organize_theme.php index 02f1f589..e4feba2b 100644 --- a/modules/organize/helpers/organize_theme.php +++ b/modules/organize/helpers/organize_theme.php @@ -20,8 +20,8 @@ class organize_theme { static function head($theme) { // @tdo remove the addition css and organize.js (just here to test) - $theme->script("modules/organize/js/organize_init.js"); - $theme->script("modules/organize/js/organize.js"); - $theme->css("modules/organize/css/organize.css"); + $theme->script("organize_init.js"); + $theme->script("organize.js"); + $theme->css("organize.css"); } } diff --git a/modules/search/helpers/search.php b/modules/search/helpers/search.php index 6317020f..b08cf89d 100644 --- a/modules/search/helpers/search.php +++ b/modules/search/helpers/search.php @@ -24,7 +24,7 @@ class search_Core { if (!user::active()->admin) { foreach (user::group_ids() as $id) { - $fields[] = "`view_$id` = " . access::ALLOW; + $fields[] = "`view_$id` = TRUE"; // access::ALLOW } $access_sql = "AND (" . join(" AND ", $fields) . ")"; } else { diff --git a/modules/server_add/helpers/server_add_theme.php b/modules/server_add/helpers/server_add_theme.php index 02f99690..2ba2e167 100644 --- a/modules/server_add/helpers/server_add_theme.php +++ b/modules/server_add/helpers/server_add_theme.php @@ -20,20 +20,20 @@ class server_add_theme_Core { static function head($theme) { if (user::active()->admin) { - $theme->script("modules/server_add/js/server_add.js"); + $theme->script("server_add.js"); } } static function admin_head($theme) { $head = array(); if (strpos(Router::$current_uri, "admin/server_add") !== false) { - $theme->css("lib/jquery.autocomplete.css"); + $theme->css("jquery.autocomplete.css"); $base = url::site("__ARGS__"); $csrf = access::csrf_token(); $head[] = "<script> var base_url = \"$base\"; var csrf = \"$csrf\";</script>"; - $theme->script("lib/jquery.autocomplete.js"); - $theme->script("modules/server_add/js/admin.js"); + $theme->script("jquery.autocomplete.js"); + $theme->script("admin.js"); } return implode("\n", $head); diff --git a/modules/server_add/views/server_add_tree_dialog.html.php b/modules/server_add/views/server_add_tree_dialog.html.php index a4eda3b9..21952849 100644 --- a/modules/server_add/views/server_add_tree_dialog.html.php +++ b/modules/server_add/views/server_add_tree_dialog.html.php @@ -1,7 +1,7 @@ <?php defined("SYSPATH") or die("No direct script access.") ?> <script type="text/javascript"> var GET_CHILDREN_URL = "<?= url::site("server_add/children?path=__PATH__") ?>"; - var START_URL = "<?= url::site("server_add/start?item_id={$item->id}&csrf=$csrf") ?>"; + var START_URL = "<?= url::site("server_add/start?item_id={$item->id}&csrf=$csrf") ?>"; </script> <div id="gServerAdd"> diff --git a/modules/tag/controllers/tags.php b/modules/tag/controllers/tags.php index 85f6d16e..a600ea1a 100644 --- a/modules/tag/controllers/tags.php +++ b/modules/tag/controllers/tags.php @@ -53,10 +53,10 @@ class Tags_Controller extends REST_Controller { $form = tag::get_add_form($item); if ($form->validate()) { - foreach (split("[\,\ \;]", $form->add_tag->inputs["name"]->value) as $tag_name) { + foreach (split("[\,\;]", $form->add_tag->inputs["name"]->value) as $tag_name) { $tag_name = trim($tag_name); if ($tag_name) { - $tag = tag::add($item, $tag_name); + $tag = tag::add($item, str_replace(" ", ".", $tag_name)); } } @@ -78,4 +78,21 @@ class Tags_Controller extends REST_Controller { return tag::get_add_form($item); } + + public function autocomplete() { + $tags = array(); + $tag_parts = preg_split("#[,\s;]+# ", $this->input->get("q")); + $limit = $this->input->get("limit"); + $tag_part = end($tag_parts); + $tag_list = ORM::factory("tag") + ->like("name", "{$tag_part}%", false) + ->orderby("name", "ASC") + ->limit($limit) + ->find_all(); + foreach ($tag_list as $tag) { + $tags[] = $tag->name; + } + + print implode("\n", $tags); + } } diff --git a/modules/tag/helpers/tag.php b/modules/tag/helpers/tag.php index 5efa6a19..be5461a4 100644 --- a/modules/tag/helpers/tag.php +++ b/modules/tag/helpers/tag.php @@ -104,7 +104,7 @@ class tag_Core { ($item->is_photo() ? t("Add tag to photo") : t("Add tag to movie")); $group = $form->group("add_tag")->label("Add Tag"); - $group->input("name")->label($label)->rules("required|length[1,64]"); + $group->input("name")->label($label)->rules("required"); $group->hidden("item_id")->value($item->id); $group->submit("")->value(t("Add Tag")); return $form; diff --git a/modules/tag/helpers/tag_event.php b/modules/tag/helpers/tag_event.php index d13d1340..58034900 100644 --- a/modules/tag/helpers/tag_event.php +++ b/modules/tag/helpers/tag_event.php @@ -64,9 +64,15 @@ class tag_event_Core { tag::compact(); } - static function item_edit_form($item, $form) { + static function item_edit_form($item, $view) { + $url = url::site("tags/autocomplete"); + $view->script[] = "$('#gEditFormContainer form').ready(function() { + $('#gEditFormContainer form input[id=tags]').autocomplete( + '$url', {max: 30, formatResult: formatTagAutoCompleteResult} + ); + });"; $tag_value = implode("; ", tag::item_tags($item)); - $form->edit_item->input("tags")->label(t("Tags (separate by , or ;)")) + $view->form->edit_item->input("tags")->label(t("Tags (separate by , or ;)")) ->value($tag_value); } @@ -74,7 +80,7 @@ class tag_event_Core { tag::clear_all($item); foreach (preg_split("/[,;]/", $form->edit_item->tags->value) as $tag_name) { if ($tag_name) { - tag::add($item, $tag_name); + tag::add($item, str_replace(" ", ".", $tag_name)); } } tag::compact(); diff --git a/modules/tag/helpers/tag_theme.php b/modules/tag/helpers/tag_theme.php index fe30354f..1bce9bd8 100644 --- a/modules/tag/helpers/tag_theme.php +++ b/modules/tag/helpers/tag_theme.php @@ -19,11 +19,13 @@ */ class tag_theme_Core { static function head($theme) { - $theme->script("modules/tag/js/tag.js"); + $theme->css("jquery.autocomplete.css"); + $theme->script("jquery.autocomplete.js"); + $theme->script("tag.js"); } static function admin_head($theme) { - $theme->script("modules/tag/js/tag.js"); + $theme->script("tag.js"); } static function sidebar_blocks($theme) { diff --git a/modules/tag/js/tag.js b/modules/tag/js/tag.js index a1eaeecd..bbf44166 100644 --- a/modules/tag/js/tag.js +++ b/modules/tag/js/tag.js @@ -7,7 +7,7 @@ function ajaxify_tag_form() { dataType: "json", success: function(data) { if (data.result == "success") { - $.get($("#gTagCloud").attr("src"), function(data, textStatus) { + $.get($("#gTagCloud").attr("title"), function(data, textStatus) { $("#gTagCloud").html(data); }); } @@ -66,3 +66,18 @@ function editInPlace(element) { }; ajaxify_editInPlaceForm(); } + +function formatTagAutoCompleteResult(row) { + var text = $(".ac_loading").val(); + if (/[\s,;]/.test(text)) { + for (var i= text.length - 1; i >= 0; i--) { + var chr = text.charAt(i); + if (chr == " " || chr == "," || chr == ";") { + break; + } + } + return text.substr(0, i + 1) + row[0]; + } else { + return row[0]; + } +} diff --git a/modules/tag/models/tag.php b/modules/tag/models/tag.php index 7a85dbab..e910a8ee 100644 --- a/modules/tag/models/tag.php +++ b/modules/tag/models/tag.php @@ -44,10 +44,14 @@ class Tag_Model extends ORM { * @return integer */ public function items_count($type=null) { - return ORM::factory("item") + $model = ORM::factory("item") ->viewable() ->join("items_tags", "items.id", "items_tags.item_id") - ->where("items_tags.tag_id", $this->id) - ->count_all(); + ->where("items_tags.tag_id", $this->id); + + if ($type) { + $model->where("items.type", $type); + } + return $model->count_all(); } }
\ No newline at end of file diff --git a/modules/tag/views/tag_block.html.php b/modules/tag/views/tag_block.html.php index 9c8f3de5..233eb361 100644 --- a/modules/tag/views/tag_block.html.php +++ b/modules/tag/views/tag_block.html.php @@ -1,5 +1,15 @@ <?php defined("SYSPATH") or die("No direct script access.") ?> -<div id="gTagCloud" src="<?= url::site("tags") ?>"> +<script> + $("#gAddTagForm").ready(function() { + var url = $("#gTagCloud").attr("title") + "/autocomplete"; + $("#gAddTagForm input:text").autocomplete( + url, { + max: 30, + formatResult: formatTagAutoCompleteResult} + ); + }); +</script> +<div id="gTagCloud" title="<?= url::site("tags") ?>"> <?= $cloud ?> </div> <?= $form ?>
\ No newline at end of file diff --git a/modules/user/controllers/admin_users.php b/modules/user/controllers/admin_users.php index b5dc6cb5..0a0086ff 100644 --- a/modules/user/controllers/admin_users.php +++ b/modules/user/controllers/admin_users.php @@ -48,8 +48,10 @@ class Admin_Users_Controller extends Controller { $desired_locale = $form->add_user->locale->value; $user->locale = $desired_locale == "none" ? null : $desired_locale; } - $user->save(); + + module::event("user_add_form_admin_completed", $user, $form); + message::success(t("Created user %user_name", array("user_name" => p::clean($user->name)))); print json_encode(array("result" => "success")); } else { diff --git a/modules/user/controllers/users.php b/modules/user/controllers/users.php index 46f799c5..0bf2e81d 100644 --- a/modules/user/controllers/users.php +++ b/modules/user/controllers/users.php @@ -39,6 +39,7 @@ class Users_Controller extends REST_Controller { $user->locale = $desired_locale == "none" ? null : $desired_locale; } $user->save(); + module::event("user_edit_form_completed", $user, $form); message::success(t("User information updated.")); print json_encode( diff --git a/modules/user/helpers/user.php b/modules/user/helpers/user.php index 53e9052c..a153ab69 100644 --- a/modules/user/helpers/user.php +++ b/modules/user/helpers/user.php @@ -36,6 +36,8 @@ class user_Core { $group->input("url")->label(t("URL"))->id("gUrl")->value($user->url); $group->submit("")->value(t("Save")); $form->add_rules_from($user); + + module::event("user_edit_form", $user); return $form; } @@ -56,6 +58,8 @@ class user_Core { $group->submit("")->value(t("Modify User")); $form->add_rules_from($user); $form->edit_user->password->rules("-required"); + + module::event("user_edit_form_admin", $user); return $form; } @@ -75,6 +79,8 @@ class user_Core { $group->submit("")->value(t("Add User")); $user = ORM::factory("user"); $form->add_rules_from($user); + + module::event("user_add_form_admin", $user); return $form; } diff --git a/modules/user/helpers/user_theme.php b/modules/user/helpers/user_theme.php index ad9d4c63..c5351f8e 100644 --- a/modules/user/helpers/user_theme.php +++ b/modules/user/helpers/user_theme.php @@ -26,7 +26,7 @@ class user_theme_Core { static function admin_head($theme) { if (strpos(Router::$current_uri, "admin/users") !== false) { - $theme->script("lib/gallery.panel.js"); + $theme->script("gallery.panel.js"); } } } diff --git a/modules/user/views/admin_users.html.php b/modules/user/views/admin_users.html.php index b469f82d..542b8b8b 100644 --- a/modules/user/views/admin_users.html.php +++ b/modules/user/views/admin_users.html.php @@ -66,7 +66,7 @@ <? foreach ($users as $i => $user): ?> <tr id="gUser-<?= $user->id ?>" class="<?= text::alternate("gOddRow", "gEvenRow") ?> user <?= $user->admin ? "admin" : "" ?>"> <td id="user-<?= $user->id ?>" class="core-info gDraggable"> - <img src="<?= $user->avatar_url(20, $theme->theme_url("images/avatar.jpg", true)) ?>" + <img src="<?= $user->avatar_url(20, $theme->url("images/avatar.jpg", true)) ?>" title="<?= t("Drag user onto group below to add as a new member") ?>" alt="<?= p::clean($user->name) ?>" width="20" |