diff options
author | Nathan Kinkade <nkinkade@nkinka.de> | 2010-08-19 23:29:35 +0000 |
---|---|---|
committer | Nathan Kinkade <nkinkade@nkinka.de> | 2010-08-19 23:29:35 +0000 |
commit | 45b6d344b4a5431e7cf11fde5808c63bf7553676 (patch) | |
tree | 33a5bd2ee0124553c4d35f4152e607296479a551 | |
parent | d1475ec40ebda6404baab45b5b2482c651e657f9 (diff) | |
parent | 21a0f832b66eaba902b09e2a88ece52c76e4a0c3 (diff) |
Merge branch 'master' of git://github.com/gallery/gallery3
56 files changed, 727 insertions, 279 deletions
diff --git a/installer/install.sql b/installer/install.sql index 8836f53f..c6314aa7 100644 --- a/installer/install.sql +++ b/installer/install.sql @@ -10,7 +10,8 @@ CREATE TABLE {access_caches} ( `view_full_2` binary(1) NOT NULL DEFAULT '0', `edit_2` binary(1) NOT NULL DEFAULT '0', `add_2` binary(1) NOT NULL DEFAULT '0', - PRIMARY KEY (`id`) + PRIMARY KEY (`id`), + KEY `item_id` (`item_id`) ) AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; INSERT INTO {access_caches} VALUES (1,1,'1','0','0','1','0','0'); @@ -184,7 +185,8 @@ CREATE TABLE {items} ( KEY `parent_id` (`parent_id`), KEY `type` (`type`), KEY `random` (`rand_key`), - KEY `weight` (`weight`) + KEY `weight` (`weight`), + KEY `left_ptr` (`left_ptr`) ) AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; INSERT INTO {items} VALUES (1,NULL,NULL,UNIX_TIMESTAMP(),'',NULL,1,1,NULL,NULL,2,0,NULL,'','',1,NULL,NULL,2,NULL,'weight','ASC',1,NULL,NULL,'Gallery','album',UNIX_TIMESTAMP(),0,1,NULL,'1','1'); @@ -236,20 +238,22 @@ CREATE TABLE {modules} ( `active` tinyint(1) DEFAULT '0', `name` varchar(64) DEFAULT NULL, `version` int(9) DEFAULT NULL, + `weight` int(9) DEFAULT NULL, PRIMARY KEY (`id`), - UNIQUE KEY `name` (`name`) + UNIQUE KEY `name` (`name`), + KEY `weight` (`weight`) ) AUTO_INCREMENT=11 DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; -INSERT INTO {modules} VALUES (1,1,'gallery',31); -INSERT INTO {modules} VALUES (2,1,'user',3); -INSERT INTO {modules} VALUES (3,1,'comment',3); -INSERT INTO {modules} VALUES (4,1,'organize',1); -INSERT INTO {modules} VALUES (5,1,'info',1); -INSERT INTO {modules} VALUES (6,1,'rest',3); -INSERT INTO {modules} VALUES (7,1,'rss',1); -INSERT INTO {modules} VALUES (8,1,'search',1); -INSERT INTO {modules} VALUES (9,1,'slideshow',2); -INSERT INTO {modules} VALUES (10,1,'tag',2); +INSERT INTO {modules} VALUES (1,1,'gallery',34,1); +INSERT INTO {modules} VALUES (2,1,'user',3,2); +INSERT INTO {modules} VALUES (3,1,'comment',3,3); +INSERT INTO {modules} VALUES (4,1,'organize',1,4); +INSERT INTO {modules} VALUES (5,1,'info',1,5); +INSERT INTO {modules} VALUES (6,1,'rest',3,6); +INSERT INTO {modules} VALUES (7,1,'rss',1,7); +INSERT INTO {modules} VALUES (8,1,'search',1,8); +INSERT INTO {modules} VALUES (9,1,'slideshow',2,9); +INSERT INTO {modules} VALUES (10,1,'tag',2,10); DROP TABLE IF EXISTS {outgoing_translations}; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; @@ -391,7 +395,7 @@ CREATE TABLE {vars} ( `value` text, PRIMARY KEY (`id`), UNIQUE KEY `module_name` (`module_name`,`name`) -) AUTO_INCREMENT=42 DEFAULT CHARSET=utf8; +) AUTO_INCREMENT=43 DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; INSERT INTO {vars} VALUES (NULL,'gallery','active_site_theme','wind'); INSERT INTO {vars} VALUES (NULL,'gallery','active_admin_theme','admin_wind'); @@ -408,14 +412,14 @@ INSERT INTO {vars} VALUES (NULL,'gallery','simultaneous_upload_limit','5'); INSERT INTO {vars} VALUES (NULL,'gallery','admin_area_timeout','5400'); INSERT INTO {vars} VALUES (NULL,'gallery','maintenance_mode','0'); INSERT INTO {vars} VALUES (NULL,'gallery','blocks_dashboard_sidebar','a:4:{i:2;a:2:{i:0;s:7:\"gallery\";i:1;s:11:\"block_adder\";}i:3;a:2:{i:0;s:7:\"gallery\";i:1;s:5:\"stats\";}i:4;a:2:{i:0;s:7:\"gallery\";i:1;s:13:\"platform_info\";}i:5;a:2:{i:0;s:7:\"gallery\";i:1;s:12:\"project_news\";}}'); -INSERT INTO {vars} VALUES (NULL,'comment','access_permissions','everybody'); INSERT INTO {vars} VALUES (NULL,'gallery','date_time_format','Y-M-d H:i:s'); INSERT INTO {vars} VALUES (NULL,'gallery','date_format','Y-M-d'); INSERT INTO {vars} VALUES (NULL,'gallery','blocks_dashboard_center','a:3:{i:6;a:2:{i:0;s:7:\"gallery\";i:1;s:7:\"welcome\";}i:7;a:2:{i:0;s:7:\"gallery\";i:1;s:12:\"photo_stream\";}i:8;a:2:{i:0;s:7:\"gallery\";i:1;s:11:\"log_entries\";}}'); INSERT INTO {vars} VALUES (NULL,'gallery','choose_default_tookit','1'); +INSERT INTO {vars} VALUES (NULL,'comment','access_permissions','everybody'); +INSERT INTO {vars} VALUES (NULL,'gallery','blocks_site_sidebar','a:4:{i:9;a:2:{i:0;s:7:\"gallery\";i:1;s:8:\"language\";}i:10;a:2:{i:0;s:4:\"info\";i:1;s:8:\"metadata\";}i:11;a:2:{i:0;s:3:\"rss\";i:1;s:9:\"rss_feeds\";}i:12;a:2:{i:0;s:3:\"tag\";i:1;s:3:\"tag\";}}'); INSERT INTO {vars} VALUES (NULL,'gallery','identity_provider','user'); INSERT INTO {vars} VALUES (NULL,'comment','spam_caught','0'); INSERT INTO {vars} VALUES (NULL,'user','mininum_password_length','5'); INSERT INTO {vars} VALUES (NULL,'rest','allow_guest_access','0'); -INSERT INTO {vars} VALUES (NULL,'gallery','blocks_site_sidebar','a:3:{i:9;a:2:{i:0;s:4:\"info\";i:1;s:8:\"metadata\";}i:10;a:2:{i:0;s:3:\"rss\";i:1;s:9:\"rss_feeds\";}i:11;a:2:{i:0;s:3:\"tag\";i:1;s:3:\"tag\";}}'); INSERT INTO {vars} VALUES (NULL,'slideshow','max_scale','0'); diff --git a/modules/comment/controllers/admin_manage_comments.php b/modules/comment/controllers/admin_manage_comments.php index e451791f..0889dc4e 100644 --- a/modules/comment/controllers/admin_manage_comments.php +++ b/modules/comment/controllers/admin_manage_comments.php @@ -35,9 +35,9 @@ class Admin_Manage_Comments_Controller extends Admin_Controller { public function menu_labels() { $menu = $this->_menu($this->_counts()); json::reply(array((string) $menu->get("unpublished")->label, - (string) $menu->get("published")->label, - (string) $menu->get("spam")->label, - (string) $menu->get("deleted")->label)); + (string) $menu->get("published")->label, + (string) $menu->get("spam")->label, + (string) $menu->get("deleted")->label)); } public function queue($state) { @@ -51,8 +51,10 @@ class Admin_Manage_Comments_Controller extends Admin_Controller { $view->content->state = $state; $view->content->comments = ORM::factory("comment") ->order_by("created", "DESC") + ->order_by("id", "DESC") ->where("state", "=", $state) - ->limit(self::$items_per_page, ($page - 1) * self::$items_per_page) + ->limit(self::$items_per_page) + ->offset(($page - 1) * self::$items_per_page) ->find_all(); $view->content->pager = new Pagination(); $view->content->pager->initialize( diff --git a/modules/comment/controllers/comments.php b/modules/comment/controllers/comments.php index 6ec4132b..ff0e9ce1 100644 --- a/modules/comment/controllers/comments.php +++ b/modules/comment/controllers/comments.php @@ -57,8 +57,8 @@ class Comments_Controller extends Controller { $view->comment = $comment; json::reply(array("result" => "success", - "view" => (string)$view, - "form" => (string)comment::get_add_form($item))); + "view" => (string)$view, + "form" => (string)comment::get_add_form($item))); } else { $form = comment::prefill_add_form($form); json::reply(array("result" => "error", "form" => (string)$form)); diff --git a/modules/comment/views/comments.html.php b/modules/comment/views/comments.html.php index da45f57b..b524f5da 100644 --- a/modules/comment/views/comments.html.php +++ b/modules/comment/views/comments.html.php @@ -36,11 +36,11 @@ </a> <? if ($comment->author()->guest): ?> <?= t('on %date %name said', - array("date" => date("Y-M-d H:i:s", $comment->created), - "name" => html::clean($comment->author_name()))); ?> + array("date" => gallery::date_time($comment->created), + "name" => html::clean($comment->author_name()))); ?> <? else: ?> <?= t('on %date <a href="%url">%name</a> said', - array("date" => date("Y-M-d H:i:s", $comment->created), + array("date" => gallery::date_time($comment->created), "url" => user_profile::url($comment->author_id), "name" => html::clean($comment->author_name()))); ?> <? endif ?> diff --git a/modules/comment/views/user_profile_comments.html.php b/modules/comment/views/user_profile_comments.html.php index a2a641ba..377b2d95 100644 --- a/modules/comment/views/user_profile_comments.html.php +++ b/modules/comment/views/user_profile_comments.html.php @@ -4,8 +4,8 @@ <? foreach ($comments as $comment): ?> <li id="g-comment-<?= $comment->id ?>"> <p class="g-author"> - <?= t('on %date for %title ', - array("date" => date("Y-M-d H:i:s", $comment->created), + <?= t("on %date for %title ", + array("date" => gallery::date_time($comment->created), "title" => $comment->item()->title)); ?> <a href="<?= $comment->item()->url() ?>"> <?= $comment->item()->thumb_img(array(), 50) ?> diff --git a/modules/g2_import/helpers/g2_import.php b/modules/g2_import/helpers/g2_import.php index 4aa9e642..f2e9dad9 100644 --- a/modules/g2_import/helpers/g2_import.php +++ b/modules/g2_import/helpers/g2_import.php @@ -442,6 +442,7 @@ class g2_import_Core { "title" => "title", "viewCount" => "view_count"); $direction_map = array( + 1 => "asc", ORDER_ASCENDING => "asc", ORDER_DESCENDING => "desc"); // Only consider G2's first sort order @@ -587,6 +588,20 @@ class g2_import_Core { $item->description = self::_decode_html_special_chars(self::extract_description($g2_item)); $item->owner_id = self::map($g2_item->getOwnerId()); $item->save(); + + // If the item has a preferred derivative with a rotation, then rotate this image + // accordingly. Should we obey scale rules as well? I vote no because rotation is less + // destructive -- you lose too much data from scaling. + $g2_preferred = g2(GalleryCoreApi::fetchPreferredSource($g2_item)); + if ($g2_preferred && $g2_preferred instanceof GalleryDerivative) { + if (preg_match("/rotate\|(-?\d+)/", $g2_preferred->getDerivativeOperations(), $matches)) { + $tmpfile = tempnam(TMPPATH, "rotate"); + gallery_graphics::rotate($item->file_path(), $tmpfile, array("degrees" => $matches[1])); + $item->set_data_file($tmpfile); + $item->save(); + unlink($tmpfile); + } + } } catch (Exception $e) { $exception_info = (string) new G2_Import_Exception( t("Corrupt image '%path'", array("path" => $g2_path)), @@ -837,11 +852,7 @@ class g2_import_Core { return; } - $text = $g2_comment->getSubject(); - if ($text) { - $text .= " "; - } - $text .= $g2_comment->getComment(); + $text = join("\n", array($g2_comment->getSubject(), $g2_comment->getComment())); $text = html_entity_decode($text); // Just import the fields we know about. Do this outside of the comment API for now so that @@ -858,7 +869,6 @@ class g2_import_Core { $comment->text = self::_transform_bbcode($text); $comment->state = "published"; $comment->server_http_host = $g2_comment->getHost(); - $comment->created = $g2_comment->getDate(); try { $comment->save(); } catch (Exception $e) { @@ -867,6 +877,14 @@ class g2_import_Core { array("id" => $g2_comment_id)), $e); } + + // Backdate the creation date. We can't do this at creation time because + // Comment_Model::save() will override it. + db::update("comments") + ->set("created", $g2_comment->getDate()) + ->set("updated", $g2_comment->getDate()) + ->where("id", "=", $comment->id) + ->execute(); } /** diff --git a/modules/gallery/controllers/admin_themes.php b/modules/gallery/controllers/admin_themes.php index e59eadaf..a88e1e89 100644 --- a/modules/gallery/controllers/admin_themes.php +++ b/modules/gallery/controllers/admin_themes.php @@ -31,10 +31,11 @@ class Admin_Themes_Controller extends Admin_Controller { private function _get_themes() { $themes = array(); foreach (scandir(THEMEPATH) as $theme_name) { + if ($theme_name[0] == ".") { + continue; + } + $theme_name = preg_replace("/[^a-zA-Z0-9\._-]/", "", $theme_name); if (file_exists(THEMEPATH . "$theme_name/theme.info")) { - if ($theme_name[0] == ".") { - continue; - } $themes[$theme_name] = theme::get_info($theme_name); } diff --git a/modules/gallery/controllers/albums.php b/modules/gallery/controllers/albums.php index f3f5dee3..fb7d5c59 100644 --- a/modules/gallery/controllers/albums.php +++ b/modules/gallery/controllers/albums.php @@ -132,7 +132,9 @@ class Albums_Controller extends Items_Controller { $album->description = $form->edit_item->description->value; $album->sort_column = $form->edit_item->sort_order->column->value; $album->sort_order = $form->edit_item->sort_order->direction->value; - $album->name = $form->edit_item->inputs["name"]->value; + if (array_key_exists("name", $form->edit_item->inputs)) { + $album->name = $form->edit_item->inputs["name"]->value; + } $album->slug = $form->edit_item->slug->value; $album->validate(); } catch (ORM_Validation_Exception $e) { diff --git a/modules/gallery/controllers/file_proxy.php b/modules/gallery/controllers/file_proxy.php index 15b4279f..b17310c4 100644 --- a/modules/gallery/controllers/file_proxy.php +++ b/modules/gallery/controllers/file_proxy.php @@ -116,6 +116,8 @@ class File_Proxy_Controller extends Controller { throw new Kohana_404_Exception(); } + header("Content-Length: " . filesize($file)); + header("Pragma:"); // Check that the content hasn't expired or it wasn't changed since cached expires::check(2592000, $item->updated); @@ -127,7 +129,7 @@ class File_Proxy_Controller extends Controller { // Dump out the image. If the item is a movie, then its thumbnail will be a JPG. if ($item->is_movie() && $type != "albums") { - header("Content-type: image/jpeg"); + header("Content-Type: image/jpeg"); } else { header("Content-Type: $item->mime_type"); } diff --git a/modules/gallery/controllers/packager.php b/modules/gallery/controllers/packager.php index 835cb903..f463d0de 100644 --- a/modules/gallery/controllers/packager.php +++ b/modules/gallery/controllers/packager.php @@ -59,11 +59,7 @@ class Packager_Controller extends Controller { // numbers, keeping our install.sql file more stable. srand(0); - gallery_installer::install(true); - - module::load_modules(); - - foreach (array("user", "comment", "organize", "info", "rest", + foreach (array("gallery", "user", "comment", "organize", "info", "rest", "rss", "search", "slideshow", "tag") as $module_name) { module::install($module_name); module::activate($module_name); diff --git a/modules/gallery/controllers/quick.php b/modules/gallery/controllers/quick.php index fee601d9..c34209da 100644 --- a/modules/gallery/controllers/quick.php +++ b/modules/gallery/controllers/quick.php @@ -36,25 +36,11 @@ class Quick_Controller extends Controller { } if ($degrees) { - gallery_graphics::rotate($item->file_path(), $item->file_path(), - array("degrees" => $degrees)); - - list($item->width, $item->height) = getimagesize($item->file_path()); - $item->resize_dirty= 1; - $item->thumb_dirty= 1; + $tmpfile = tempnam(TMPPATH, "rotate"); + gallery_graphics::rotate($item->file_path(), $tmpfile, array("degrees" => $degrees)); + $item->set_data_file($tmpfile); $item->save(); - - graphics::generate($item); - - // @todo: this is an inadequate way to regenerate album cover thumbnails after rotation. - foreach (ORM::factory("item") - ->where("album_cover_item_id", "=", $item->id) - ->find_all() as $target) { - copy($item->thumb_path(), $target->thumb_path()); - $target->thumb_width = $item->thumb_width; - $target->thumb_height = $item->thumb_height; - $target->save(); - } + unlink($tmpfile); } if (Input::instance()->get("page_type") == "collection") { diff --git a/modules/gallery/controllers/uploader.php b/modules/gallery/controllers/uploader.php index 87520032..85d344d6 100644 --- a/modules/gallery/controllers/uploader.php +++ b/modules/gallery/controllers/uploader.php @@ -50,7 +50,8 @@ class Uploader_Controller extends Controller { // Uploadify adds its own field to the form, so validate that separately. $file_validation = new Validation($_FILES); $file_validation->add_rules( - "Filedata", "upload::valid", "upload::required", "upload::type[gif,jpg,jpeg,png,flv,mp4,m4v]"); + "Filedata", "upload::valid", "upload::required", + "upload::type[gif,jpg,jpeg,png,flv,mp4,m4v]"); if ($form->validate() && $file_validation->validate()) { $temp_filename = upload::save("Filedata"); diff --git a/modules/gallery/controllers/user_profile.php b/modules/gallery/controllers/user_profile.php index 726d3e51..e992655b 100644 --- a/modules/gallery/controllers/user_profile.php +++ b/modules/gallery/controllers/user_profile.php @@ -56,7 +56,7 @@ class User_Profile_Controller extends Controller { ->to($user->email) ->subject(html::clean($form->message->subject->value)) ->header("Mime-Version", "1.0") - ->header("Content-type", "text/html; charset=iso-8859-1") + ->header("Content-type", "text/html; charset=UTF-8") ->reply_to($form->message->reply_to->value) ->message(html::purify($form->message->message->value)) ->send(); diff --git a/modules/gallery/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); diff --git a/modules/gallery/images/missing_movie.png b/modules/gallery/images/missing_movie.png Binary files differindex fdc97779..fdc97779 100755..100644 --- a/modules/gallery/images/missing_movie.png +++ b/modules/gallery/images/missing_movie.png diff --git a/modules/gallery/libraries/MY_Kohana_Exception.php b/modules/gallery/libraries/MY_Kohana_Exception.php index 72cb2ac0..82899d7e 100644 --- a/modules/gallery/libraries/MY_Kohana_Exception.php +++ b/modules/gallery/libraries/MY_Kohana_Exception.php @@ -22,11 +22,15 @@ class Kohana_Exception extends Kohana_Exception_Core { * Dump out the full stack trace as part of the text representation of the exception. */ public static function text($e) { - return sprintf( - "%s [ %s ]: %s\n%s [ %s ]\n%s", - get_class($e), $e->getCode(), strip_tags($e->getMessage()), - $e->getFile(), $e->getLine(), - $e->getTraceAsString()); + if ($e instanceof Kohana_404_Exception) { + return "File not found: " . Router::$complete_uri; + } else { + return sprintf( + "%s [ %s ]: %s\n%s [ %s ]\n%s", + get_class($e), $e->getCode(), strip_tags($e->getMessage()), + $e->getFile(), $e->getLine(), + $e->getTraceAsString()); + } } /** @@ -41,16 +45,21 @@ class Kohana_Exception extends Kohana_Exception_Core { * data, such as session ids and passwords / hashes. */ public static function safe_dump($value, $key, $length=128, $max_level=5) { - return parent::dump(self::_sanitize_for_dump($value, $key), $length, $max_level); + return parent::dump(self::_sanitize_for_dump($value, $key, $max_level), $length, $max_level); } /** * Elides sensitive data which shouldn't be echoed to the client, * such as passwords, and other secrets. */ - /* Visible for testing*/ static function _sanitize_for_dump($value, $key=null) { + /* Visible for testing*/ static function _sanitize_for_dump($value, $key=null, $max_level) { // Better elide too much than letting something through. // Note: unanchored match is intended. + if (!$max_level) { + // Too much recursion; give up. We gave it our best shot. + return $value; + } + $sensitive_info_pattern = '/(password|pass|email|hash|private_key|session_id|session|g3sid|csrf|secret)/i'; if (preg_match($sensitive_info_pattern, $key) || @@ -63,7 +72,7 @@ class Kohana_Exception extends Kohana_Exception_Core { } else if ($value instanceof User_Model) { return get_class($value) . ' object for "' . $value->name . '" - details omitted for display'; } - return self::_sanitize_for_dump((array) $value, $key); + return self::_sanitize_for_dump((array) $value, $key, $max_level - 1); } else if (is_array($value)) { $result = array(); foreach ($value as $k => $v) { @@ -78,7 +87,7 @@ class Kohana_Exception extends Kohana_Exception_Core { if (is_object($v)) { $key_for_display .= ' (type: ' . get_class($v) . ')'; } - $result[$key_for_display] = self::_sanitize_for_dump($v, $actual_key); + $result[$key_for_display] = self::_sanitize_for_dump($v, $actual_key, $max_level - 1); } } else { $result = $value; diff --git a/modules/gallery/models/item.php b/modules/gallery/models/item.php index c00b7972..c4591279 100644 --- a/modules/gallery/models/item.php +++ b/modules/gallery/models/item.php @@ -316,7 +316,7 @@ class Item_Model extends ORM_MPTT { unset($significant_changes["relative_url_cache"]); unset($significant_changes["relative_path_cache"]); - if (!empty($this->changed) && $significant_changes) { + if ((!empty($this->changed) && $significant_changes) || isset($this->data_file)) { $this->updated = time(); if (!$this->loaded()) { // Create a new item. @@ -341,30 +341,19 @@ class Item_Model extends ORM_MPTT { } // Get the width, height and mime type from our data file for photos and movies. - if ($this->is_movie() || $this->is_photo()) { - $pi = pathinfo($this->data_file); - + if ($this->is_photo() || $this->is_movie()) { if ($this->is_photo()) { - $image_info = getimagesize($this->data_file); - $this->width = $image_info[0]; - $this->height = $image_info[1]; - $this->mime_type = $image_info["mime"]; - - // Force an extension onto the name if necessary - if (empty($pi["extension"])) { - $pi["extension"] = image_type_to_extension($image_info[2], false); - $this->name .= "." . $pi["extension"]; - } - } else { - list ($this->width, $this->height) = movie::getmoviesize($this->data_file); - - // No extension? Assume FLV. - if (empty($pi["extension"])) { - $pi["extension"] = "flv"; - $this->name .= "." . $pi["extension"]; - } + list ($this->width, $this->height, $this->mime_type, $extension) = + photo::get_file_metadata($this->data_file); + } else if ($this->is_movie()) { + list ($this->width, $this->height, $this->mime_type, $extension) = + movie::get_file_metadata($this->data_file); + } - $this->mime_type = in_array(strtolower($pi["extension"]), array("mp4", "m4v")) ? "video/mp4" : "video/x-flv"; + // Force an extension onto the name if necessary + $pi = pathinfo($this->data_file); + if (empty($pi["extension"])) { + $this->name = "{$this->name}.$extension"; } } @@ -479,7 +468,30 @@ class Item_Model extends ORM_MPTT { ->execute(); } + // Replace the data file, if requested. + // @todo: we don't handle the case where you swap in a file of a different mime type + // should we prevent that in validation? or in set_data_file() + if ($this->data_file && ($this->is_photo() || $this->is_movie())) { + copy($this->data_file, $this->file_path()); + + // Get the width, height and mime type from our data file for photos and movies. + if ($this->is_photo()) { + list ($this->width, $this->height) = photo::get_file_metadata($this->file_path()); + } else if ($this->is_movie()) { + list ($this->width, $this->height) = movie::get_file_metadata($this->file_path()); + } + $this->thumb_dirty = 1; + $this->resize_dirty = 1; + } + module::event("item_updated", $original, $this); + + if ($this->data_file) { + // Null out the data file variable here, otherwise this event will trigger another + // save() which will think that we're doing another file move. + $this->data_file = null; + module::event("item_updated_data_file", $this); + } } } else if (!empty($this->changed)) { // Insignificant changes only. Don't fire events or do any special checking to try to keep @@ -656,9 +668,9 @@ class Item_Model extends ORM_MPTT { public function resize_img($extra_attrs) { $attrs = array_merge($extra_attrs, array("src" => $this->resize_url(), - "alt" => $this->title, - "width" => $this->resize_width, - "height" => $this->resize_height) + "alt" => $this->title, + "width" => $this->resize_width, + "height" => $this->resize_height) ); // html::image forces an absolute url which we don't want return "<img" . html::attributes($attrs) . "/>"; @@ -765,8 +777,9 @@ class Item_Model extends ORM_MPTT { $this->rules["slug"] = array(); } - // Movies and photos must have data files - if (($this->is_photo() || $this->is_movie()) && !$this->loaded()) { + // Movies and photos must have data files. Verify the data file on new items, or if it has + // been replaced. + if (($this->is_photo() || $this->is_movie()) && $this->data_file) { $this->rules["name"]["callbacks"][] = array($this, "valid_data_file"); } } @@ -842,6 +855,17 @@ class Item_Model extends ORM_MPTT { } else if (filesize($this->data_file) == 0) { $v->add_error("name", "empty_data_file"); } + + if ($this->loaded()) { + if ($this->is_photo()) { + list ($a, $b, $mime_type) = photo::get_file_metadata($this->data_file); + } else if ($this->is_movie()) { + list ($a, $b, $mime_type) = movie::get_file_metadata($this->data_file); + } + if ($mime_type != $this->mime_type) { + $v->add_error("name", "cant_change_mime_type"); + } + } } /** @@ -949,14 +973,25 @@ class Item_Model extends ORM_MPTT { } unset($data["album_cover_item_id"]); - if (access::can("view_full", $this) && $this->is_photo()) { - $data["file_url"] = $this->file_url(true); + if (access::can("view_full", $this) && !$this->is_album()) { + $data["file_url"] = rest::url("data", $this, "full"); + } + if (access::user_can(identity::guest(), "view_full", $this)) { + $data["file_url_public"] = $this->file_url(true); + } + + if ($this->is_photo()) { + $data["resize_url"] = rest::url("data", $this, "resize"); + if (access::user_can(identity::guest(), "view", $this)) { + $data["resize_url_public"] = $this->resize_url(true); + } } - if (($tmp = $this->resize_url(true)) && $this->is_photo()) { - $data["resize_url"] = $tmp; + $data["thumb_url"] = rest::url("data", $this, "thumb"); + if (access::user_can(identity::guest(), "view", $this)) { + $data["thumb_url_public"] = $this->thumb_url(true); } - $data["thumb_url"] = $this->thumb_url(true); + $data["can_edit"] = access::can("edit", $this); // Elide some internal-only data that is going to cause confusion in the client. diff --git a/modules/gallery/module.info b/modules/gallery/module.info index 7d28a7c1..084a0945 100644 --- a/modules/gallery/module.info +++ b/modules/gallery/module.info @@ -1,3 +1,3 @@ name = "Gallery 3" description = "Gallery core application" -version = 31 +version = 34 diff --git a/modules/gallery/tests/Item_Model_Test.php b/modules/gallery/tests/Item_Model_Test.php index 907cfe24..bd123098 100644 --- a/modules/gallery/tests/Item_Model_Test.php +++ b/modules/gallery/tests/Item_Model_Test.php @@ -384,4 +384,35 @@ class Item_Model_Test extends Gallery_Unit_Test_Case { $this->assert_same($photo->id, $album->album_cover_item_id); } + + public function replace_data_file_test() { + // Random photo is modules/gallery/tests/test.jpg which is 1024x768 and 6232 bytes. + $photo = test::random_photo(); + $this->assert_equal(1024, $photo->width); + $this->assert_equal(768, $photo->height); + $this->assert_equal(6232, filesize($photo->file_path())); + + // Random photo is gallery/images/imagemagick.jpg is 114x118 and 20337 bytes + $photo->set_data_file(MODPATH . "gallery/images/imagemagick.jpg"); + $photo->save(); + + $this->assert_equal(114, $photo->width); + $this->assert_equal(118, $photo->height); + $this->assert_equal(20337, filesize($photo->file_path())); + } + + public function replacement_data_file_must_be_same_mime_type_test() { + // Random photo is modules/gallery/tests/test.jpg + $photo = test::random_photo(); + $photo->set_data_file(MODPATH . "gallery/images/graphicsmagick.png"); + + try { + $photo->save(); + } catch (ORM_Validation_Exception $e) { + $this->assert_same(array("name" => "cant_change_mime_type"), $e->validation->errors()); + return; // pass + } + $this->assert_true(false, "Shouldn't get here"); + + } } diff --git a/modules/gallery/tests/Kohana_Exception_Test.php b/modules/gallery/tests/Kohana_Exception_Test.php index 48bc5184..df7cf9ff 100644 --- a/modules/gallery/tests/Kohana_Exception_Test.php +++ b/modules/gallery/tests/Kohana_Exception_Test.php @@ -37,22 +37,22 @@ class Kohana_Exception_Test extends Gallery_Unit_Test_Case { public function sanitize_for_dump_match_key_test() { $this->assert_equal("removed for display", - Kohana_Exception::_sanitize_for_dump("original value", "password")); + Kohana_Exception::_sanitize_for_dump("original value", "password", 5)); $this->assert_equal("original value", - Kohana_Exception::_sanitize_for_dump("original value", "meow")); + Kohana_Exception::_sanitize_for_dump("original value", "meow", 5)); } public function sanitize_for_dump_match_key_loosely_test() { $this->assert_equal("removed for display", - Kohana_Exception::_sanitize_for_dump("original value", "this secret key")); + Kohana_Exception::_sanitize_for_dump("original value", "this secret key", 5)); } public function sanitize_for_dump_match_value_test() { // Looks like a hash / secret value. $this->assert_equal("removed for display", - Kohana_Exception::_sanitize_for_dump("p$2a178b841c6391d6368f131", "meow")); + Kohana_Exception::_sanitize_for_dump("p$2a178b841c6391d6368f131", "meow", 5)); $this->assert_equal("original value", - Kohana_Exception::_sanitize_for_dump("original value", "meow")); + Kohana_Exception::_sanitize_for_dump("original value", "meow", 5)); } public function sanitize_for_dump_array_test() { @@ -64,7 +64,7 @@ class Kohana_Exception_Test extends Gallery_Unit_Test_Case { "three" => "removed for display"); $this->assert_equal($expected, - Kohana_Exception::_sanitize_for_dump($var, "ignored")); + Kohana_Exception::_sanitize_for_dump($var, "ignored", 5)); } public function sanitize_for_dump_nested_array_test() { @@ -73,7 +73,7 @@ class Kohana_Exception_Test extends Gallery_Unit_Test_Case { $expected = array("safe" => "original value 1", "safe 2" => array("some hash" => "removed for display")); $this->assert_equal($expected, - Kohana_Exception::_sanitize_for_dump($var, "ignored")); + Kohana_Exception::_sanitize_for_dump($var, "ignored", 5)); } public function sanitize_for_dump_user_test() { @@ -83,7 +83,7 @@ class Kohana_Exception_Test extends Gallery_Unit_Test_Case { $user->email = "value 2"; $user->full_name = "value 3"; $this->assert_equal('User_Model object for "john" - details omitted for display', - Kohana_Exception::_sanitize_for_dump($user, "ignored")); + Kohana_Exception::_sanitize_for_dump($user, "ignored", 5)); } public function sanitize_for_dump_database_test() { @@ -91,7 +91,7 @@ class Kohana_Exception_Test extends Gallery_Unit_Test_Case { array("connection" => array("user" => "john", "name" => "gallery_3"), "cache" => array())); $this->assert_equal("Kohana_Exception_Test_Database object - details omitted for display", - Kohana_Exception::_sanitize_for_dump($db, "ignored")); + Kohana_Exception::_sanitize_for_dump($db, "ignored", 5)); } public function sanitize_for_dump_nested_database_test() { @@ -104,7 +104,7 @@ class Kohana_Exception_Test extends Gallery_Unit_Test_Case { array("some" => "foo", "bar (type: Kohana_Exception_Test_Database)" => "Kohana_Exception_Test_Database object - details omitted for display"), - Kohana_Exception::_sanitize_for_dump($var, "ignored")); + Kohana_Exception::_sanitize_for_dump($var, "ignored", 5)); } public function sanitize_for_dump_object_test() { @@ -117,7 +117,7 @@ class Kohana_Exception_Test extends Gallery_Unit_Test_Case { "private: email_address" => "removed for display", "password" => "removed for display"); $this->assert_equal($expected, - Kohana_Exception::_sanitize_for_dump($obj, "ignored")); + Kohana_Exception::_sanitize_for_dump($obj, "ignored", 5)); } public function sanitize_for_dump_nested_object_test() { @@ -142,7 +142,7 @@ class Kohana_Exception_Test extends Gallery_Unit_Test_Case { "foo" => array("bar (type: User_Model)" => 'User_Model object for "john" - details omitted for display')); $this->assert_equal($expected, - Kohana_Exception::_sanitize_for_dump($obj, "ignored")); + Kohana_Exception::_sanitize_for_dump($obj, "ignored", 5)); } } diff --git a/modules/gallery/tests/Sendmail_Test.php b/modules/gallery/tests/Sendmail_Test.php index b20543d1..b9406047 100644 --- a/modules/gallery/tests/Sendmail_Test.php +++ b/modules/gallery/tests/Sendmail_Test.php @@ -65,14 +65,14 @@ class Sendmail_Test extends Gallery_Unit_Test_Case { "From: from@gallery3.com\n" . "Reply-To: public@gallery3.com\n" . "MIME-Version: 1.0\n" . - "Content-type: text/html; charset=iso-8859-1\r\n" . + "Content-Type: text/html; charset=UTF-8\r\n" . "Subject: Test Email Unit test\r\n\r\n" . "<html><body><p>This is an html msg</p></body></html>"; $result = Sendmail_For_Test::factory() ->to("receiver@someemail.com") ->subject("Test Email Unit test") ->header("MIME-Version", "1.0") - ->header("Content-type", "text/html; charset=iso-8859-1") + ->header("Content-Type", "text/html; charset=UTF-8") ->message("<html><body><p>This is an html msg</p></body></html>") ->send() ->send_text; diff --git a/modules/gallery/tests/controller_auth_data.txt b/modules/gallery/tests/controller_auth_data.txt index 3c9b3afc..8b776fb9 100644 --- a/modules/gallery/tests/controller_auth_data.txt +++ b/modules/gallery/tests/controller_auth_data.txt @@ -14,7 +14,6 @@ modules/gallery/controllers/login.php auth_ajax modules/gallery/controllers/login.php html DIRTY_AUTH modules/gallery/controllers/login.php auth_html DIRTY_AUTH modules/gallery/controllers/logout.php index DIRTY_AUTH -modules/gallery/controllers/maintenance.php index DIRTY_AUTH modules/gallery/controllers/quick.php form_edit DIRTY_CSRF modules/gallery/controllers/upgrader.php index DIRTY_AUTH modules/gallery/controllers/uploader.php start DIRTY_AUTH @@ -26,6 +25,8 @@ modules/gallery/controllers/welcome_message.php index modules/organize/controllers/organize.php dialog DIRTY_CSRF modules/organize/controllers/organize.php add_album_fields DIRTY_AUTH modules/rest/controllers/rest.php index DIRTY_CSRF|DIRTY_AUTH +modules/rest/controllers/rest.php reset_api_key_confirm DIRTY_AUTH +modules/rest/controllers/rest.php reset_api_key DIRTY_AUTH modules/rest/controllers/rest.php __call DIRTY_CSRF|DIRTY_AUTH modules/rss/controllers/rss.php feed DIRTY_CSRF|DIRTY_AUTH modules/search/controllers/search.php index DIRTY_CSRF|DIRTY_AUTH diff --git a/modules/gallery/tests/xss_data.txt b/modules/gallery/tests/xss_data.txt index 02483865..3eae3d07 100644 --- a/modules/gallery/tests/xss_data.txt +++ b/modules/gallery/tests/xss_data.txt @@ -77,23 +77,23 @@ modules/gallery/views/admin_languages.html.php 62 DIRTY form:: modules/gallery/views/admin_languages.html.php 63 DIRTY $display_name modules/gallery/views/admin_languages.html.php 65 DIRTY form::radio("default_locale",$code,($default_locale==$code),((isset($installed_locales[$code]))?'':'disabled="disabled"')) modules/gallery/views/admin_languages.html.php 113 DIRTY $share_translations_form -modules/gallery/views/admin_maintenance.html.php 24 DIRTY_ATTR text::alternate("g-odd","g-even") -modules/gallery/views/admin_maintenance.html.php 24 DIRTY_ATTR log::severity_class($task->severity) -modules/gallery/views/admin_maintenance.html.php 25 DIRTY_ATTR log::severity_class($task->severity) -modules/gallery/views/admin_maintenance.html.php 26 DIRTY $task->name -modules/gallery/views/admin_maintenance.html.php 29 DIRTY $task->description -modules/gallery/views/admin_maintenance.html.php 70 DIRTY_ATTR text::alternate("g-odd","g-even") -modules/gallery/views/admin_maintenance.html.php 70 DIRTY_ATTR $task->state=="stalled"?"g-warning":"" -modules/gallery/views/admin_maintenance.html.php 71 DIRTY_ATTR $task->state=="stalled"?"g-warning":"" -modules/gallery/views/admin_maintenance.html.php 72 DIRTY gallery::date_time($task->updated) -modules/gallery/views/admin_maintenance.html.php 75 DIRTY $task->name -modules/gallery/views/admin_maintenance.html.php 90 DIRTY $task->status -modules/gallery/views/admin_maintenance.html.php 141 DIRTY_ATTR text::alternate("g-odd","g-even") -modules/gallery/views/admin_maintenance.html.php 141 DIRTY_ATTR $task->state=="success"?"g-success":"g-error" -modules/gallery/views/admin_maintenance.html.php 142 DIRTY_ATTR $task->state=="success"?"g-success":"g-error" -modules/gallery/views/admin_maintenance.html.php 143 DIRTY gallery::date_time($task->updated) -modules/gallery/views/admin_maintenance.html.php 146 DIRTY $task->name -modules/gallery/views/admin_maintenance.html.php 158 DIRTY $task->status +modules/gallery/views/admin_maintenance.html.php 40 DIRTY_ATTR text::alternate("g-odd","g-even") +modules/gallery/views/admin_maintenance.html.php 40 DIRTY_ATTR log::severity_class($task->severity) +modules/gallery/views/admin_maintenance.html.php 41 DIRTY_ATTR log::severity_class($task->severity) +modules/gallery/views/admin_maintenance.html.php 42 DIRTY $task->name +modules/gallery/views/admin_maintenance.html.php 45 DIRTY $task->description +modules/gallery/views/admin_maintenance.html.php 86 DIRTY_ATTR text::alternate("g-odd","g-even") +modules/gallery/views/admin_maintenance.html.php 86 DIRTY_ATTR $task->state=="stalled"?"g-warning":"" +modules/gallery/views/admin_maintenance.html.php 87 DIRTY_ATTR $task->state=="stalled"?"g-warning":"" +modules/gallery/views/admin_maintenance.html.php 88 DIRTY gallery::date_time($task->updated) +modules/gallery/views/admin_maintenance.html.php 91 DIRTY $task->name +modules/gallery/views/admin_maintenance.html.php 106 DIRTY $task->status +modules/gallery/views/admin_maintenance.html.php 157 DIRTY_ATTR text::alternate("g-odd","g-even") +modules/gallery/views/admin_maintenance.html.php 157 DIRTY_ATTR $task->state=="success"?"g-success":"g-error" +modules/gallery/views/admin_maintenance.html.php 158 DIRTY_ATTR $task->state=="success"?"g-success":"g-error" +modules/gallery/views/admin_maintenance.html.php 159 DIRTY gallery::date_time($task->updated) +modules/gallery/views/admin_maintenance.html.php 162 DIRTY $task->name +modules/gallery/views/admin_maintenance.html.php 174 DIRTY $task->status modules/gallery/views/admin_maintenance_show_log.html.php 8 DIRTY_JS url::site("admin/maintenance/save_log/$task->id?csrf=$csrf") modules/gallery/views/admin_maintenance_show_log.html.php 13 DIRTY $task->name modules/gallery/views/admin_maintenance_task.html.php 55 DIRTY $task->name @@ -122,50 +122,52 @@ modules/gallery/views/admin_themes.html.php 76 DIRTY $info- modules/gallery/views/admin_themes.html.php 78 DIRTY $info->description modules/gallery/views/admin_themes_preview.html.php 8 DIRTY_ATTR $url modules/gallery/views/error_404.html.php 14 DIRTY $login_form -modules/gallery/views/error_admin.html.php 150 DIRTY $type -modules/gallery/views/error_admin.html.php 150 DIRTY $code -modules/gallery/views/error_admin.html.php 153 DIRTY $message -modules/gallery/views/error_admin.html.php 156 DIRTY_ATTR $error_id -modules/gallery/views/error_admin.html.php 161 DIRTY Kohana_Exception::debug_path($file) -modules/gallery/views/error_admin.html.php 161 DIRTY $line -modules/gallery/views/error_admin.html.php 166 DIRTY_ATTR ($num==$line)?"highlight":"" -modules/gallery/views/error_admin.html.php 166 DIRTY $num -modules/gallery/views/error_admin.html.php 166 DIRTY htmlspecialchars($row,ENT_NOQUOTES,Kohana::CHARSET) -modules/gallery/views/error_admin.html.php 178 DIRTY_ATTR $source_id -modules/gallery/views/error_admin.html.php 178 DIRTY_JS $source_id -modules/gallery/views/error_admin.html.php 178 DIRTY Kohana_Exception::debug_path($step["file"]) -modules/gallery/views/error_admin.html.php 178 DIRTY $step["line"] -modules/gallery/views/error_admin.html.php 180 DIRTY Kohana_Exception::debug_path($step["file"]) -modules/gallery/views/error_admin.html.php 180 DIRTY $step["line"] -modules/gallery/views/error_admin.html.php 187 DIRTY $step["function"] -modules/gallery/views/error_admin.html.php 188 DIRTY_ATTR $args_id -modules/gallery/views/error_admin.html.php 188 DIRTY_JS $args_id -modules/gallery/views/error_admin.html.php 192 DIRTY_ATTR $args_id -modules/gallery/views/error_admin.html.php 197 DIRTY $name -modules/gallery/views/error_admin.html.php 200 DIRTY Kohana_Exception::safe_dump($arg,$name) -modules/gallery/views/error_admin.html.php 208 DIRTY_ATTR $source_id -modules/gallery/views/error_admin.html.php 208 DIRTY_ATTR ($num==$step["line"])?"highlight":"" -modules/gallery/views/error_admin.html.php 208 DIRTY $num -modules/gallery/views/error_admin.html.php 208 DIRTY htmlspecialchars($row,ENT_NOQUOTES,Kohana::CHARSET) -modules/gallery/views/error_admin.html.php 218 DIRTY_ATTR $env_id=$error_id."environment" -modules/gallery/views/error_admin.html.php 218 DIRTY_JS $env_id -modules/gallery/views/error_admin.html.php 220 DIRTY_ATTR $env_id -modules/gallery/views/error_admin.html.php 222 DIRTY_ATTR $env_id=$error_id."environment_included" -modules/gallery/views/error_admin.html.php 222 DIRTY_JS $env_id -modules/gallery/views/error_admin.html.php 222 DIRTY count($included) -modules/gallery/views/error_admin.html.php 223 DIRTY_ATTR $env_id -modules/gallery/views/error_admin.html.php 228 DIRTY Kohana_Exception::debug_path($file) -modules/gallery/views/error_admin.html.php 235 DIRTY_ATTR $env_id=$error_id."environment_loaded" -modules/gallery/views/error_admin.html.php 235 DIRTY_JS $env_id -modules/gallery/views/error_admin.html.php 235 DIRTY count($included) -modules/gallery/views/error_admin.html.php 236 DIRTY_ATTR $env_id -modules/gallery/views/error_admin.html.php 241 DIRTY Kohana_Exception::debug_path($file) -modules/gallery/views/error_admin.html.php 249 DIRTY_ATTR $env_id="$error_id.environment".strtolower($var) -modules/gallery/views/error_admin.html.php 250 DIRTY_JS $env_id -modules/gallery/views/error_admin.html.php 250 DIRTY $var -modules/gallery/views/error_admin.html.php 251 DIRTY_ATTR $env_id -modules/gallery/views/error_admin.html.php 257 DIRTY $key -modules/gallery/views/error_admin.html.php 261 DIRTY Kohana_Exception::safe_dump($value,$key) +modules/gallery/views/error_admin.html.php 178 DIRTY @gallery_block::get("platform_info") +modules/gallery/views/error_admin.html.php 179 DIRTY @gallery_block::get("stats") +modules/gallery/views/error_admin.html.php 184 DIRTY $type +modules/gallery/views/error_admin.html.php 184 DIRTY $code +modules/gallery/views/error_admin.html.php 187 DIRTY $message +modules/gallery/views/error_admin.html.php 190 DIRTY_ATTR $error_id +modules/gallery/views/error_admin.html.php 195 DIRTY Kohana_Exception::debug_path($file) +modules/gallery/views/error_admin.html.php 195 DIRTY $line +modules/gallery/views/error_admin.html.php 200 DIRTY_ATTR ($num==$line)?"highlight":"" +modules/gallery/views/error_admin.html.php 200 DIRTY $num +modules/gallery/views/error_admin.html.php 200 DIRTY htmlspecialchars($row,ENT_NOQUOTES,Kohana::CHARSET) +modules/gallery/views/error_admin.html.php 212 DIRTY_ATTR $source_id +modules/gallery/views/error_admin.html.php 212 DIRTY_JS $source_id +modules/gallery/views/error_admin.html.php 212 DIRTY Kohana_Exception::debug_path($step["file"]) +modules/gallery/views/error_admin.html.php 212 DIRTY $step["line"] +modules/gallery/views/error_admin.html.php 214 DIRTY Kohana_Exception::debug_path($step["file"]) +modules/gallery/views/error_admin.html.php 214 DIRTY $step["line"] +modules/gallery/views/error_admin.html.php 221 DIRTY $step["function"] +modules/gallery/views/error_admin.html.php 222 DIRTY_ATTR $args_id +modules/gallery/views/error_admin.html.php 222 DIRTY_JS $args_id +modules/gallery/views/error_admin.html.php 226 DIRTY_ATTR $args_id +modules/gallery/views/error_admin.html.php 231 DIRTY $name +modules/gallery/views/error_admin.html.php 234 DIRTY Kohana_Exception::safe_dump($arg,$name) +modules/gallery/views/error_admin.html.php 242 DIRTY_ATTR $source_id +modules/gallery/views/error_admin.html.php 242 DIRTY_ATTR ($num==$step["line"])?"highlight":"" +modules/gallery/views/error_admin.html.php 242 DIRTY $num +modules/gallery/views/error_admin.html.php 242 DIRTY htmlspecialchars($row,ENT_NOQUOTES,Kohana::CHARSET) +modules/gallery/views/error_admin.html.php 252 DIRTY_ATTR $env_id=$error_id."environment" +modules/gallery/views/error_admin.html.php 252 DIRTY_JS $env_id +modules/gallery/views/error_admin.html.php 254 DIRTY_ATTR $env_id +modules/gallery/views/error_admin.html.php 256 DIRTY_ATTR $env_id=$error_id."environment_included" +modules/gallery/views/error_admin.html.php 256 DIRTY_JS $env_id +modules/gallery/views/error_admin.html.php 256 DIRTY count($included) +modules/gallery/views/error_admin.html.php 257 DIRTY_ATTR $env_id +modules/gallery/views/error_admin.html.php 262 DIRTY Kohana_Exception::debug_path($file) +modules/gallery/views/error_admin.html.php 269 DIRTY_ATTR $env_id=$error_id."environment_loaded" +modules/gallery/views/error_admin.html.php 269 DIRTY_JS $env_id +modules/gallery/views/error_admin.html.php 269 DIRTY count($included) +modules/gallery/views/error_admin.html.php 270 DIRTY_ATTR $env_id +modules/gallery/views/error_admin.html.php 275 DIRTY Kohana_Exception::debug_path($file) +modules/gallery/views/error_admin.html.php 283 DIRTY_ATTR $env_id="$error_id.environment".strtolower($var) +modules/gallery/views/error_admin.html.php 284 DIRTY_JS $env_id +modules/gallery/views/error_admin.html.php 284 DIRTY $var +modules/gallery/views/error_admin.html.php 285 DIRTY_ATTR $env_id +modules/gallery/views/error_admin.html.php 291 DIRTY $key +modules/gallery/views/error_admin.html.php 295 DIRTY Kohana_Exception::safe_dump($value,$key) modules/gallery/views/form_uploadify.html.php 9 DIRTY_JS url::file("lib/uploadify/uploadify.swf") modules/gallery/views/form_uploadify.html.php 10 DIRTY_JS url::site("uploader/add_photo/{$album->id}") modules/gallery/views/form_uploadify.html.php 14 DIRTY_JS url::file("lib/uploadify/cancel.png") @@ -191,7 +193,6 @@ modules/gallery/views/l10n_client.html.php 62 DIRTY form:: modules/gallery/views/l10n_client.html.php 67 DIRTY form::textarea("l10n-edit-plural-translation-other","",' rows="2"') modules/gallery/views/login_ajax.html.php 6 DIRTY_JS url::site("password/reset") modules/gallery/views/login_ajax.html.php 44 DIRTY $form -modules/gallery/views/maintenance.html.php 46 DIRTY auth::get_login_form("login/auth_html") modules/gallery/views/menu.html.php 4 DIRTY $menu->css_id?"id='$menu->css_id'":"" modules/gallery/views/menu.html.php 4 DIRTY_ATTR $menu->css_class modules/gallery/views/menu.html.php 6 DIRTY $element->render() @@ -268,7 +269,7 @@ modules/gallery/views/user_profile.html.php 34 DIRTY_ATTR $use modules/gallery/views/user_profile.html.php 43 DIRTY $info->view modules/image_block/views/image_block_block.html.php 3 DIRTY_JS $item->url() modules/image_block/views/image_block_block.html.php 4 DIRTY $item->thumb_img(array("class"=>"g-thumbnail")) -modules/info/views/info_block.html.php 22 DIRTY date("M j, Y H:i:s",$item->captured) +modules/info/views/info_block.html.php 22 DIRTY gallery::date_time($item->captured) modules/info/views/info_block.html.php 29 DIRTY_JS $item->owner->url modules/notification/views/comment_published.html.php 28 DIRTY_JS $comment->item()->abs_url() modules/notification/views/comment_published.html.php 29 DIRTY $comment->item()->abs_url() @@ -295,6 +296,7 @@ modules/organize/views/organize_dialog.html.php 136 DIRTY_ATTR requ modules/recaptcha/views/admin_recaptcha.html.php 11 DIRTY $form modules/recaptcha/views/admin_recaptcha.html.php 23 DIRTY_JS $public_key modules/recaptcha/views/form_recaptcha.html.php 7 DIRTY_JS $public_key +modules/rest/views/reset_api_key_confirm.html.php 6 DIRTY $form modules/rss/views/feed.mrss.php 10 DIRTY $feed->uri modules/rss/views/feed.mrss.php 13 DIRTY_JS $feed->uri modules/rss/views/feed.mrss.php 16 DIRTY_JS $feed->previous_page_uri @@ -368,8 +370,8 @@ themes/admin_wind/views/admin.html.php 61 DIRTY $theme themes/admin_wind/views/admin.html.php 68 DIRTY $content themes/admin_wind/views/admin.html.php 74 DIRTY $sidebar themes/admin_wind/views/admin.html.php 79 DIRTY $theme->admin_footer() -themes/admin_wind/views/admin.html.php 81 DIRTY $theme->admin_credits() -themes/admin_wind/views/admin.html.php 85 DIRTY $theme->admin_page_bottom() +themes/admin_wind/views/admin.html.php 82 DIRTY $theme->admin_credits() +themes/admin_wind/views/admin.html.php 87 DIRTY $theme->admin_page_bottom() themes/admin_wind/views/block.html.php 3 DIRTY_ATTR $anchor themes/admin_wind/views/block.html.php 5 DIRTY $id themes/admin_wind/views/block.html.php 5 DIRTY_ATTR $css_id diff --git a/modules/gallery/views/admin_modules.html.php b/modules/gallery/views/admin_modules.html.php index 4d6fe5f0..f4ae965c 100644 --- a/modules/gallery/views/admin_modules.html.php +++ b/modules/gallery/views/admin_modules.html.php @@ -18,7 +18,7 @@ height: 400, width: 500, position: "center", - title: <?= t("Confirm Module Activation")->for_js() ?>, + title: <?= t("Confirm module activation")->for_js() ?>, buttons: { <?= t("Continue")->for_js() ?>: function() { $("form", this).submit(); diff --git a/modules/gallery/views/error_admin.html.php b/modules/gallery/views/error_admin.html.php index 40eb7374..af78c59c 100644 --- a/modules/gallery/views/error_admin.html.php +++ b/modules/gallery/views/error_admin.html.php @@ -20,7 +20,20 @@ margin: 20px auto; } - div#framework_error { + #framework_error { + height: 6em; + } + + #framework_error .crashlogo { + position: relative; + top: .3em; + font-size: 6.0em; + } + + #framework_error .title { + position: relative; + top: -2.5em; + padding: 0px; text-align: center; } @@ -102,8 +115,12 @@ .number { padding-right: 1em; } + + #g-platform h2, #g-stats h2 { + font-size: 1.1em; + } </style> - <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <title><?= t("Something went wrong!") ?></title> <script type="text/javascript"> @@ -133,17 +150,34 @@ <body> <? try { $user = identity::active_user(); } catch (Exception $e) { } ?> <div class="big_box" id="framework_error"> - <h1> - <?= t("Dang... Something went wrong!") ?> - </h1> - <h2> - <?= t("We tried really hard, but it's broken.") ?> - </h2> + <div class="crashlogo"> + :-( + </div> + <div class="title"> + <h1> + <?= t("Dang... Something went wrong!") ?> + </h1> + <h2> + <?= t("We tried really hard, but it's broken.") ?> + </h2> + </div> </div> <div class="big_box" id="error_details"> <h2> <?= t("Hey wait, you're an admin! We can tell you stuff.") ?> </h2> + <p> + There's an error message below and you can find more details + in gallery3/var/logs (look for the file with the most recent + date on it). Stuck? Stop by the <a href="http://gallery.menalto.com/forum/96">Gallery 3 + Forums</a> and ask for help. You can also look at our list + of <a href="http://sourceforge.net/apps/trac/gallery/roadmap">open + tickets</a> to see if the problem you're seeing has been + reported. If you post a request, here's some useful + information to include: + <?= @gallery_block::get("platform_info") ?> + <?= @gallery_block::get("stats") ?> + </p> <div id="kohana_error"> <h3> <span class="type"> diff --git a/modules/gallery/views/error_user.html.php b/modules/gallery/views/error_user.html.php index 74c6a8fb..09ab752a 100644 --- a/modules/gallery/views/error_user.html.php +++ b/modules/gallery/views/error_user.html.php @@ -19,24 +19,42 @@ margin: 20px auto; } - div#framework_error { + #framework_error { + height: 8em; + } + + #framework_error .crashlogo { + position: relative; + top: .3em; + font-size: 6em; + } + + #framework_error .title { + position: relative; + top: -3em; text-align: center; + margin: 0 auto; } </style> - <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <title><?= t("Something went wrong!") ?></title> </head> <body> <div class="big_box" id="framework_error"> - <h1> - <?= t("Dang... Something went wrong!") ?> - </h1> - <h2> - <?= t("We tried really hard, but it's broken.") ?> - </h2> - <p> - <?= t("Talk to your Gallery administrator for help fixing this!") ?> - </p> + <div class="crashlogo"> + :-( + </div> + <div class="title"> + <h1> + <?= t("Dang... Something went wrong!") ?> + </h1> + <h2> + <?= t("We tried really hard, but it's broken.") ?> + </h2> + <p> + <?= t("Talk to your Gallery administrator for help fixing this!") ?> + </p> + </div> </div> </body> </html> diff --git a/modules/gallery_unit_test/views/kohana_unit_test_cli.php b/modules/gallery_unit_test/views/kohana_unit_test_cli.php index a0de0f52..61dae7dd 100644 --- a/modules/gallery_unit_test/views/kohana_unit_test_cli.php +++ b/modules/gallery_unit_test/views/kohana_unit_test_cli.php @@ -71,7 +71,7 @@ foreach ($results as $class => $methods) { } echo "+", str_repeat("=", 87), "+", str_repeat("=", 10), "+\n"; - printf("| %-40.40s %-13.13s %-13.13s %-13.13s %-13.13s |\n", + printf("| %-40.40s %-10.10s %-10.10s %-10.10s %-10.10s %-10.10s |\n", $class, "Score: {$stats[$class]['score']}", "Total: {$stats[$class]['total']}", @@ -81,7 +81,7 @@ foreach ($results as $class => $methods) { echo "+", str_repeat("=", 98), "+\n\n\n"; } -printf(" %-40.40s %-13.13s %-13.13s %-13.13s %-13.13s\n", +printf(" %-40.40s %-10.10s %-10.10s %-10.10s %-10.10s %-10.10s\n", "TOTAL", "Score: " . ($totals["total"] ? 100 * ($totals["passed"] / $totals["total"]) : 0), "Total: {$totals['total']}", diff --git a/modules/info/views/info_block.html.php b/modules/info/views/info_block.html.php index ac177ee7..ebe9bd28 100644 --- a/modules/info/views/info_block.html.php +++ b/modules/info/views/info_block.html.php @@ -19,7 +19,7 @@ <? if ($item->captured): ?> <li> <strong class="caption"><?= t("Captured:") ?></strong> - <?= date("M j, Y H:i:s", $item->captured)?> + <?= gallery::date_time($item->captured)?> </li> <? endif ?> <? if ($item->owner): ?> diff --git a/modules/notification/helpers/notification.php b/modules/notification/helpers/notification.php index 0cf536bc..e4212203 100644 --- a/modules/notification/helpers/notification.php +++ b/modules/notification/helpers/notification.php @@ -185,7 +185,7 @@ class notification { ->to($email) ->subject($pending->subject) ->header("Mime-Version", "1.0") - ->header("Content-type", "text/html; charset=utf-8") + ->header("Content-Type", "text/html; charset=UTF-8") ->message($pending->body) ->send(); $pending->delete(); @@ -199,7 +199,7 @@ class notification { ->to($email) ->subject(t("Multiple events have occurred")) // @todo fix this terrible subject line ->header("Mime-Version", "1.0") - ->header("Content-type", "text/html; charset=utf-8") + ->header("Content-Type", "text/html; charset=UTF-8") ->message($text) ->send(); } @@ -213,7 +213,7 @@ class notification { ->to($subscribers) ->subject($subject) ->header("Mime-Version", "1.0") - ->header("Content-type", "text/html; charset=utf-8") + ->header("Content-Type", "text/html; charset=UTF-8") ->message($text) ->send(); } else { diff --git a/modules/organize/controllers/organize.php b/modules/organize/controllers/organize.php index 3005eb67..7b2ba8ef 100644 --- a/modules/organize/controllers/organize.php +++ b/modules/organize/controllers/organize.php @@ -38,7 +38,7 @@ class Organize_Controller extends Controller { $v = new View("organize_dialog.html"); $v->album = $album; - $v->domain = $input->server("SERVER_NAME"); + $v->domain = $input->server("HTTP_HOST"); $v->access_key = rest::access_key(); $v->file_filter = addslashes($file_filter); $v->sort_order = addslashes(json_encode($sort_order)); diff --git a/modules/organize/lib/Gallery3WebClient.swf b/modules/organize/lib/Gallery3WebClient.swf Binary files differindex 40249a73..b37a74c3 100644 --- a/modules/organize/lib/Gallery3WebClient.swf +++ b/modules/organize/lib/Gallery3WebClient.swf diff --git a/modules/rest/controllers/rest.php b/modules/rest/controllers/rest.php index bf2f0a54..a721ff2b 100644 --- a/modules/rest/controllers/rest.php +++ b/modules/rest/controllers/rest.php @@ -37,6 +37,22 @@ class Rest_Controller extends Controller { rest::reply(rest::access_key()); } + public function reset_api_key_confirm() { + $form = new Forge("rest/reset_api_key", "", "post", array("id" => "g-reset-api-key")); + $group = $form->group("confirm_reset")->label(t("Confirm resetting your REST API key")); + $group->submit("")->value(t("Reset")); + $v = new View("reset_api_key_confirm.html"); + $v->form = $form; + print $v; + } + + public function reset_api_key() { + access::verify_csrf(); + rest::reset_access_key(); + message::success(t("Your REST API key has been reset.")); + json::reply(array("result" => "success")); + } + public function __call($function, $args) { try { $input = Input::instance(); diff --git a/modules/rest/helpers/registry_rest.php b/modules/rest/helpers/registry_rest.php new file mode 100644 index 00000000..e9c8b955 --- /dev/null +++ b/modules/rest/helpers/registry_rest.php @@ -0,0 +1,30 @@ +<?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 registry_rest_Core { + static function get($request) { + $results = array(); + foreach (module::active() as $module) { + foreach (glob(MODPATH . "{$module->name}/helpers/*_rest.php") as $filename) { + $results[] = str_replace("_rest.php", "", basename($filename)); + } + } + return array_unique($results); + } +} diff --git a/modules/rest/helpers/rest.php b/modules/rest/helpers/rest.php index 644779da..d5ed0452 100644 --- a/modules/rest/helpers/rest.php +++ b/modules/rest/helpers/rest.php @@ -24,8 +24,28 @@ class rest_Core { Session::instance()->abort_save(); header("X-Gallery-API-Version: " . rest::API_VERSION); - if (Input::instance()->get("output") == "html") { - header("Content-type: text/html"); + switch (Input::instance()->get("output", "json")) { + case "json": + json::reply($data); + break; + + case "jsonp": + if (!($callback = Input::instance()->get("callback", ""))) { + throw new Rest_Exception( + "Bad Request", 400, array("errors" => array("callback" => "missing"))); + } + + if (preg_match('/^[$A-Za-z_][0-9A-Za-z_]*$/', $callback) == 1) { + header("Content-type: application/javascript; charset=UTF-8"); + print "$callback(" . json_encode($data) . ")"; + } else { + throw new Rest_Exception( + "Bad Request", 400, array("errors" => array("callback" => "invalid"))); + } + break; + + case "html": + header("Content-type: text/html; charset=UTF-8"); if ($data) { $html = preg_replace( "#([\w]+?://[\w]+[^ \'\"\n\r\t<]*)#ise", "'<a href=\"\\1\" >\\1</a>'", @@ -34,8 +54,10 @@ class rest_Core { $html = t("Empty response"); } print "<pre>$html</pre>"; - } else { - json::reply($data); + break; + + default: + throw new Rest_Exception("Bad Request", 400); } } @@ -65,6 +87,16 @@ class rest_Core { identity::set_active_user($user); } + static function reset_access_key() { + $key = ORM::factory("user_access_key") + ->where("user_id", "=", identity::active_user()->id) + ->find(); + if ($key->loaded()) { + $key->delete(); + } + return rest::access_key(); + } + static function access_key() { $key = ORM::factory("user_access_key") ->where("user_id", "=", identity::active_user()->id) diff --git a/modules/rest/helpers/rest_event.php b/modules/rest/helpers/rest_event.php index f23b9a58..d8c69e94 100644 --- a/modules/rest/helpers/rest_event.php +++ b/modules/rest/helpers/rest_event.php @@ -55,13 +55,6 @@ class rest_event { } /** - * Called when user is editing their own form - */ - static function user_edit_form($user, $form) { - self::_get_access_key_form($user, $form); - } - - /** * Get the form fields for user edit */ static function _get_access_key_form($user, $form) { @@ -104,6 +97,6 @@ class rest_event { $key->save(); } $view->rest_key = $key->access_key; - $data->content[] = (object)array("title" => t("REST api"), "view" => $view); + $data->content[] = (object)array("title" => t("REST API"), "view" => $view); } } diff --git a/modules/rest/views/reset_api_key_confirm.html.php b/modules/rest/views/reset_api_key_confirm.html.php new file mode 100644 index 00000000..3aae2a9a --- /dev/null +++ b/modules/rest/views/reset_api_key_confirm.html.php @@ -0,0 +1,7 @@ +<?php defined("SYSPATH") or die("No direct script access.") ?> +<div id="g-rest-reset-api-key" class="ui-helper-clearfix"> + <p> + <?= t("Do you really want to reset your REST API key? Any clients that use this key will need to be updated with the new value.") ?> + </p> + <?= $form ?> +</div> diff --git a/modules/rest/views/user_profile_rest.html.php b/modules/rest/views/user_profile_rest.html.php index e81f3d0b..3e5d3dbf 100644 --- a/modules/rest/views/user_profile_rest.html.php +++ b/modules/rest/views/user_profile_rest.html.php @@ -4,6 +4,9 @@ <li id="g-rest-key"> <p> <?= t("<b>Key</b>: %key", array("key" => $rest_key)) ?> + <a class="g-button ui-state-default ui-corner-all g-dialog-link" href="<?= url::site("rest/reset_api_key_confirm") ?>"> + <?= t("reset") ?> + </a> </p> </li> </ul> diff --git a/modules/search/views/search.html.php b/modules/search/views/search.html.php index 2e139ecf..3436a00c 100644 --- a/modules/search/views/search.html.php +++ b/modules/search/views/search.html.php @@ -8,10 +8,10 @@ <ul> <li> <label for="q"><?= t("Search the gallery") ?></label> - <input name="q" id="q" type="text" value="<?= html::clean_attribute($q) ?>"/> + <input name="q" id="q" type="text" value="<?= html::clean_attribute($q) ?>" class="text" /> </li> <li> - <input type="submit" value="<?= t("Search")->for_html_attr() ?>" /> + <input type="submit" value="<?= t("Search")->for_html_attr() ?>" class="submit" /> </li> </ul> </fieldset> diff --git a/modules/search/views/search_link.html.php b/modules/search/views/search_link.html.php index 481d0c82..dd3a76a4 100644 --- a/modules/search/views/search_link.html.php +++ b/modules/search/views/search_link.html.php @@ -3,10 +3,10 @@ <ul> <li> <label for="g-search"><?= t("Search the gallery") ?></label> - <input type="text" name="q" id="g-search"/> + <input type="text" name="q" id="g-search" class="text" /> </li> <li> - <input type="submit" value="<?= t("Go")->for_html_attr() ?>" /> + <input type="submit" value="<?= t("Go")->for_html_attr() ?>" class="submit" /> </li> </ul> </form> diff --git a/modules/server_add/helpers/server_add_event.php b/modules/server_add/helpers/server_add_event.php index 631af02f..fd4ade71 100644 --- a/modules/server_add/helpers/server_add_event.php +++ b/modules/server_add/helpers/server_add_event.php @@ -22,7 +22,7 @@ class server_add_event_Core { $menu->get("settings_menu") ->append(Menu::factory("link") ->id("server_add") - ->label(t("Server Add")) + ->label(t("Server add")) ->url(url::site("admin/server_add"))); } @@ -35,7 +35,7 @@ class server_add_event_Core { $menu->get("add_menu") ->append(Menu::factory("dialog") ->id("server_add") - ->label(t("Server Add")) + ->label(t("Server add")) ->url(url::site("server_add/browse/$item->id"))); } } diff --git a/modules/user/controllers/password.php b/modules/user/controllers/password.php index 575720a8..2e5eac5f 100644 --- a/modules/user/controllers/password.php +++ b/modules/user/controllers/password.php @@ -61,7 +61,7 @@ class Password_Controller extends Controller { ->to($user->email) ->subject(t("Password Reset Request")) ->header("Mime-Version", "1.0") - ->header("Content-type", "text/html; charset=iso-8859-1") + ->header("Content-type", "text/html; charset=UTF-8") ->message($message->render()) ->send(); diff --git a/modules/user/controllers/users.php b/modules/user/controllers/users.php index 5e6239d8..6bb4967f 100644 --- a/modules/user/controllers/users.php +++ b/modules/user/controllers/users.php @@ -41,7 +41,7 @@ class Users_Controller extends Controller { // Translate ORM validation errors into form error messages foreach ($e->validation->errors() as $key => $error) { $form->edit_user->inputs[$key]->add_error($error, 1); - } + } $valid = false; } @@ -55,7 +55,7 @@ class Users_Controller extends Controller { module::event("user_edit_form_completed", $user, $form); message::success(t("User information updated")); json::reply(array("result" => "success", - "resource" => url::site("users/{$user->id}"))); + "resource" => url::site("users/{$user->id}"))); } else { json::reply(array("result" => "error", "html" => (string)$form)); } @@ -87,7 +87,7 @@ class Users_Controller extends Controller { module::event("user_auth", $user); module::event("user_password_change", $user); json::reply(array("result" => "success", - "resource" => url::site("users/{$user->id}"))); + "resource" => url::site("users/{$user->id}"))); } else { log::warning("user", t("Failed password change for %name", array("name" => $user->name))); $name = $user->name; @@ -121,7 +121,7 @@ class Users_Controller extends Controller { message::success(t("Email address changed")); module::event("user_auth", $user); json::reply(array("result" => "success", - "resource" => url::site("users/{$user->id}"))); + "resource" => url::site("users/{$user->id}"))); } else { log::warning("user", t("Failed email change for %name", array("name" => $user->name))); $name = $user->name; diff --git a/themes/admin_wind/views/admin.html.php b/themes/admin_wind/views/admin.html.php index f9ef18c7..6b0c3fe5 100644 --- a/themes/admin_wind/views/admin.html.php +++ b/themes/admin_wind/views/admin.html.php @@ -77,9 +77,11 @@ </div> <div id="g-footer" class="g-inline ui-helper-clearfix"> <?= $theme->admin_footer() ?> - <div> + <? if (module::get_var("gallery", "show_credits")): ?> + <ul id="g-credits" class="g-inline"> <?= $theme->admin_credits() ?> - </div> + </ul> + <? endif ?> </div> </div> <?= $theme->admin_page_bottom() ?> diff --git a/themes/wind/css/fix-ie.css b/themes/wind/css/fix-ie.css index ac100da4..0633ff07 100644 --- a/themes/wind/css/fix-ie.css +++ b/themes/wind/css/fix-ie.css @@ -1,5 +1,5 @@ /** - * Fix display in IE 6, 7 + * Fix display in IE 6, 7, and 8 */ #g-banner { @@ -26,11 +26,17 @@ input.submit { display: inline !important; } -.g-short-form input[type='submit'] { +.g-short-form input.text, +.g-short-form input.submit { + font-size: 1em; line-height: 1em; padding: .38em .3em; } +#g-search-form input#q { + width: 300px; +} + #g-add-tag-form input.textbox { width: 110px !important; } |