diff options
Diffstat (limited to 'modules')
570 files changed, 5164 insertions, 29077 deletions
diff --git a/modules/akismet/controllers/admin_akismet.php b/modules/akismet/controllers/admin_akismet.php index 9ba89bd4..ca3a1473 100644 --- a/modules/akismet/controllers/admin_akismet.php +++ b/modules/akismet/controllers/admin_akismet.php @@ -45,7 +45,8 @@ class Admin_Akismet_Controller extends Admin_Controller { message::success(t("Your Akismet key has been saved.")); } - log::success("akismet", t("Akismet key changed to $new_key")); + log::success("akismet", t("Akismet key changed to %new_key", + array("new_key" => $new_key))); module::set_var("akismet", "api_key", $new_key); akismet::check_config(); url::redirect("admin/akismet"); diff --git a/modules/akismet/helpers/akismet.php b/modules/akismet/helpers/akismet.php index db45a6ab..acd5cb3e 100644 --- a/modules/akismet/helpers/akismet.php +++ b/modules/akismet/helpers/akismet.php @@ -94,7 +94,7 @@ class akismet_Core { if (empty($api_key)) { site_status::warning( t("Akismet is not quite ready! Please provide an <a href=\"%url\">API Key</a>", - array("url" => url::site("admin/akismet"))), + array("url" => html::mark_clean(url::site("admin/akismet")))), "akismet_config"); } else { site_status::clear("akismet_config"); diff --git a/modules/akismet/helpers/akismet_event.php b/modules/akismet/helpers/akismet_event.php index 80fe0127..cec6d95d 100644 --- a/modules/akismet/helpers/akismet_event.php +++ b/modules/akismet/helpers/akismet_event.php @@ -40,15 +40,31 @@ class akismet_event_Core { $comment->save(); } - static function comment_updated($old, $new) { + static function comment_updated($original, $new) { if (!module::get_var("akismet", "api_key")) { return; } - if ($old->state != "spam" && $new->state == "spam") { + if ($original->state != "spam" && $new->state == "spam") { akismet::submit_spam($new); - } else if ($old->state == "spam" && $new->state != "spam") { + } else if ($original->state == "spam" && $new->state != "spam") { akismet::submit_ham($new); } } + + static function admin_menu($menu, $theme) { + $menu->get("settings_menu") + ->append(Menu::factory("link") + ->id("akismet") + ->label(t("Akismet")) + ->url(url::site("admin/akismet"))); + + if (module::get_var("akismet", "api_key")) { + $menu->get("statistics_menu") + ->append(Menu::factory("link") + ->id("akismet") + ->label(t("Akismet")) + ->url(url::site("admin/akismet/stats"))); + } + } } diff --git a/modules/akismet/helpers/akismet_installer.php b/modules/akismet/helpers/akismet_installer.php index 5d8c0e07..b891fc7b 100644 --- a/modules/akismet/helpers/akismet_installer.php +++ b/modules/akismet/helpers/akismet_installer.php @@ -18,10 +18,6 @@ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ class akismet_installer { - static function install() { - module::set_version("akismet", 1); - } - static function activate() { akismet::check_config(); } diff --git a/modules/akismet/views/admin_akismet.html.php b/modules/akismet/views/admin_akismet.html.php index 9963f223..009d8810 100644 --- a/modules/akismet/views/admin_akismet.html.php +++ b/modules/akismet/views/admin_akismet.html.php @@ -2,11 +2,13 @@ <div id="gAdminAkismet"> <h1> <?= t("Akismet Spam Filtering") ?> </h1> <p> - <?= t("Akismet is a free, automated spam filtering service. In order to use it, you need to sign up for a <a href=\"http://wordpress.com/api-keys\">Wordpress.com API Key</a>, which is also free. Your comments will be automatically relayed to <a href=\"http://akismet.com\">Akismet.com</a> where they'll be scanned for spam. Spam messages will be flagged accordingly and hidden from your vistors until you approve or delete them.") ?> + <?= t("Akismet is a free, automated spam filtering service. In order to use it, you need to sign up for a <a href=\"%api_key_url\">Wordpress.com API Key</a>, which is also free. Your comments will be automatically relayed to <a href=\"%akismet_url\">Akismet.com</a> where they'll be scanned for spam. Spam messages will be flagged accordingly and hidden from your vistors until you approve or delete them.", + array("api_key_url" => "http://wordpress.com/api-keys", + "akismet_url" => "http://akismet.com")) ?> </p> <? if ($valid_key): ?> - <div class="gSuccess"> + <div class="gModuleStatus gSuccess"> <?= t("Your API Key is valid. Your comments will be filtered!") ?> </div> <? endif ?> diff --git a/modules/comment/controllers/admin_comments.php b/modules/comment/controllers/admin_comments.php index 3e8d3c46..a164f79f 100644 --- a/modules/comment/controllers/admin_comments.php +++ b/modules/comment/controllers/admin_comments.php @@ -113,10 +113,6 @@ class Admin_Comments_Controller extends Admin_Controller { if ($comment->loaded) { $comment->state = $state; $comment->save(); - module::event("comment_updated", $orig, $comment); - if ($orig->state == "published" || $comment->state == "published") { - module::event("item_related_update", $comment->item()); - } } } diff --git a/modules/comment/controllers/comments.php b/modules/comment/controllers/comments.php index 02c38491..82b12893 100644 --- a/modules/comment/controllers/comments.php +++ b/modules/comment/controllers/comments.php @@ -39,9 +39,9 @@ class Comments_Controller extends REST_Controller { foreach ($comments as $comment) { $data[] = array( "id" => $comment->id, - "author_name" => p::clean($comment->author_name()), + "author_name" => html::clean($comment->author_name()), "created" => $comment->created, - "text" => nl2br(p::purify($comment->text))); + "text" => nl2br(html::purify($comment->text))); } print json_encode($data); break; @@ -126,9 +126,9 @@ class Comments_Controller extends REST_Controller { array("result" => "success", "data" => array( "id" => $comment->id, - "author_name" => p::clean($comment->author_name()), + "author_name" => html::clean($comment->author_name()), "created" => $comment->created, - "text" => nl2br(p::purify($comment->text))))); + "text" => nl2br(html::purify($comment->text))))); } else { $view = new Theme_View("comment.html", "fragment"); $view->comment = $comment; @@ -152,7 +152,6 @@ class Comments_Controller extends REST_Controller { $comment->url = $form->edit_comment->url->value; $comment->text = $form->edit_comment->text->value; $comment->save(); - module::event("comment_updated", $comment); print json_encode( array("result" => "success", diff --git a/modules/comment/helpers/comment.php b/modules/comment/helpers/comment.php index 08cba096..f74a8644 100644 --- a/modules/comment/helpers/comment.php +++ b/modules/comment/helpers/comment.php @@ -35,7 +35,7 @@ class comment_Core { * @return Comment_Model */ static function create($item, $author, $text, $guest_name=null, - $guest_email=ull, $guest_url=null) { + $guest_email=null, $guest_url=null) { $comment = ORM::factory("comment"); $comment->author_id = $author->id; $comment->guest_email = $guest_email; @@ -61,11 +61,6 @@ class comment_Core { $comment->server_remote_port = substr($input->server("REMOTE_PORT"), 0, 16); $comment->save(); - module::event("comment_created", $comment); - if ($comment->state == "published") { - module::event("item_related_update", $comment->item()); - } - return $comment; } diff --git a/modules/comment/helpers/comment_event.php b/modules/comment/helpers/comment_event.php index a3beb27a..0234aea9 100644 --- a/modules/comment/helpers/comment_event.php +++ b/modules/comment/helpers/comment_event.php @@ -18,7 +18,35 @@ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ class comment_event_Core { - static function item_before_delete($item) { + static function item_deleted($item) { Database::instance()->delete("comments", array("item_id" => $item->id)); } + + static function admin_menu($menu, $theme) { + $menu->get("content_menu") + ->append(Menu::factory("link") + ->id("comments") + ->label(t("Comments")) + ->url(url::site("admin/comments"))); + } + + static function photo_menu($menu, $theme) { + $menu + ->append(Menu::factory("link") + ->id("comments") + ->label(t("View comments on this item")) + ->url("#comments") + ->css_id("gCommentsLink")); + } + + static function item_index_data($item, $data) { + foreach (Database::instance() + ->select("text") + ->from("comments") + ->where("item_id", $item->id) + ->get() + ->as_array() as $row) { + $data[] = $row->text; + } + } } diff --git a/modules/comment/helpers/comment_installer.php b/modules/comment/helpers/comment_installer.php index f54913c3..80594c16 100644 --- a/modules/comment/helpers/comment_installer.php +++ b/modules/comment/helpers/comment_installer.php @@ -44,7 +44,7 @@ class comment_installer { `text` text, `updated` int(9) NOT NULL, PRIMARY KEY (`id`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); block_manager::add("dashboard_center", "comment", "recent_comments"); module::set_var("comment", "spam_caught", 0); @@ -52,8 +52,8 @@ class comment_installer { } static function upgrade($version) { + $db = Database::instance(); if ($version == 1) { - $db = Database::instance(); $db->query("ALTER TABLE {comments} CHANGE `state` `state` varchar(15) default 'unpublished'"); module::set_version("comment", 2); } @@ -61,9 +61,16 @@ class comment_installer { static function uninstall() { $db = Database::instance(); - $sql = "SELECT `item_id` FROM {comments}"; - module::event("item_related_update_batch", $sql); + // Notify listeners that we're deleting some data. This is probably going to be very + // inefficient for large uninstalls, and we could make it better by doing things like passing + // a SQL fragment through so that the listeners could use subselects. But by using a single, + // simple event API we lighten the load on module developers. + foreach (ORM::factory("item") + ->join("comments", "items.id", "comments.item_id") + ->find_all() as $item) { + module::event("item_related_update", $item); + } $db->query("DROP TABLE IF EXISTS {comments};"); } } diff --git a/modules/comment/helpers/comment_menu.php b/modules/comment/helpers/comment_menu.php deleted file mode 100644 index 01881921..00000000 --- a/modules/comment/helpers/comment_menu.php +++ /dev/null @@ -1,37 +0,0 @@ -<?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 comment_menu_Core { - static function admin($menu, $theme) { - $menu->get("content_menu") - ->append(Menu::factory("link") - ->id("comments") - ->label(t("Comments")) - ->url(url::site("admin/comments"))); - } - - static function photo($menu, $theme) { - $menu - ->append(Menu::factory("link") - ->id("comments") - ->label(t("View comments on this item")) - ->url("#comments") - ->css_id("gCommentsLink")); - } -} diff --git a/modules/comment/helpers/comment_rss.php b/modules/comment/helpers/comment_rss.php index ab3d2283..4424981d 100644 --- a/modules/comment/helpers/comment_rss.php +++ b/modules/comment/helpers/comment_rss.php @@ -23,7 +23,7 @@ class comment_rss_Core { $feeds["comment/newest"] = t("All new comments"); if ($item) { $feeds["comment/item/$item->id"] = - t("Comments on %title", array("title" => p::purify($item->title))); + t("Comments on %title", array("title" => html::purify($item->title))); } return $feeds; } @@ -34,41 +34,35 @@ class comment_rss_Core { } $comments = ORM::factory("comment") - ->where("state", "published") - ->orderby("created", "DESC"); - $all_comments = ORM::factory("comment") + ->viewable() ->where("state", "published") ->orderby("created", "DESC"); if ($feed_id == "item") { $comments->where("item_id", $id); - $all_comments->where("item_id", $id); } - if (!empty($comments)) { - $feed->view = "comment.mrss"; - $comments = $comments->find_all($limit, $offset); - $feed->children = array(); - foreach ($comments as $comment) { - $item = $comment->item(); - $feed->children[] = new ArrayObject( - array("pub_date" => date("D, d M Y H:i:s T", $comment->created), - "text" => nl2br(p::purify($comment->text)), - "thumb_url" => $item->thumb_url(), - "thumb_height" => $item->thumb_height, - "thumb_width" => $item->thumb_width, - "item_uri" => url::abs_site("{$item->type}s/$item->id"), - "title" => p::purify($item->title), - "author" => p::clean($comment->author_name())), - ArrayObject::ARRAY_AS_PROPS); - } + $feed->view = "comment.mrss"; + $feed->children = array(); + foreach ($comments->find_all($limit, $offset) as $comment) { + $item = $comment->item(); + $feed->children[] = new ArrayObject( + array("pub_date" => date("D, d M Y H:i:s T", $comment->created), + "text" => nl2br(html::purify($comment->text)), + "thumb_url" => $item->thumb_url(), + "thumb_height" => $item->thumb_height, + "thumb_width" => $item->thumb_width, + "item_uri" => url::abs_site("{$item->type}s/$item->id"), + "title" => html::purify($item->title), + "author" => html::clean($comment->author_name())), + ArrayObject::ARRAY_AS_PROPS); + } - $feed->max_pages = ceil($all_comments->find_all()->count() / $limit); - $feed->title = htmlspecialchars(t("Recent Comments")); - $feed->uri = url::abs_site("albums/" . (empty($id) ? "1" : $id)); - $feed->description = t("Recent Comments"); + $feed->max_pages = ceil($comments->count_all() / $limit); + $feed->title = htmlspecialchars(t("Recent Comments")); + $feed->uri = url::abs_site("albums/" . (empty($id) ? "1" : $id)); + $feed->description = t("Recent Comments"); - return $feed; - } + return $feed; } -}
\ No newline at end of file +} diff --git a/modules/comment/helpers/comment_search.php b/modules/comment/helpers/comment_search.php deleted file mode 100644 index 29762eae..00000000 --- a/modules/comment/helpers/comment_search.php +++ /dev/null @@ -1,34 +0,0 @@ -<?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 Comment_Search_Core { - static function item_index_data($item) { - $data = array(); - foreach (Database::instance() - ->select("text") - ->from("comments") - ->where("item_id", $item->id) - ->get() - ->as_array() as $row) { - $data[] = $row->text; - } - return join(" ", $data); - } -} diff --git a/modules/comment/helpers/comment_theme.php b/modules/comment/helpers/comment_theme.php index 89b2f57c..38a00b5c 100644 --- a/modules/comment/helpers/comment_theme.php +++ b/modules/comment/helpers/comment_theme.php @@ -19,14 +19,13 @@ */ class comment_theme_Core { static function head($theme) { - $theme->script("modules/comment/js/comment.js"); + $theme->script("comment.js"); return ""; } static function photo_bottom($theme) { $block = new Block; $block->css_id = "gComments"; - $block->anchor = t("comments"); $block->title = t("Comments"); $view = new View("comments.html"); @@ -37,7 +36,6 @@ class comment_theme_Core { ->find_all(); $block->content = $view; - $block->content .= comment::get_add_form($theme->item())->render("form.html"); return $block; } }
\ No newline at end of file diff --git a/modules/comment/js/comment.js b/modules/comment/js/comment.js index 00fc6027..9fd63c1a 100644 --- a/modules/comment/js/comment.js +++ b/modules/comment/js/comment.js @@ -1,5 +1,13 @@ $("document").ready(function() { - ajaxify_comment_form(); + $("#gAddCommentButton").click(function(event) { + event.preventDefault(); + $.get($(this).attr("href"), + {}, + function(data) { + $("#gCommentDetail").append(data); + ajaxify_comment_form(); + }); + }); }); function ajaxify_comment_form() { diff --git a/modules/comment/models/comment.php b/modules/comment/models/comment.php index 22c465df..de9b0cd6 100644 --- a/modules/comment/models/comment.php +++ b/modules/comment/models/comment.php @@ -31,7 +31,7 @@ class Comment_Model extends ORM { if ($author->guest) { return $this->guest_name; } else { - return $author->full_name; + return $author->display_name(); } } @@ -61,8 +61,33 @@ class Comment_Model extends ORM { $this->updated = time(); if (!$this->loaded && empty($this->created)) { $this->created = $this->updated; + $created = true; } } - return parent::save(); + $visible_change = $this->original()->state == "published" || $this->state == "published"; + parent::save(); + + if (isset($created)) { + module::event("comment_created", $this); + } else { + module::event("comment_updated", $this->original(), $this); + } + + // We only notify on the related items if we're making a visible change. + if ($visible_change) { + module::event("item_related_update", $this->item()); + } + + return $this; + } + + /** + * Add a set of restrictions to any following queries to restrict access only to items + * viewable by the active user. + * @chainable + */ + public function viewable() { + $this->join("items", "items.id", "comments.item_id"); + return item::viewable($this); } } diff --git a/modules/gallery/libraries/HtmlPurifier.php b/modules/comment/tests/Comment_Model_Test.php index daa5896e..f4c68b15 100644 --- a/modules/gallery/libraries/HtmlPurifier.php +++ b/modules/comment/tests/Comment_Model_Test.php @@ -17,22 +17,24 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ -class HtmlPurifier_Core { - private static $_instance; +class Comment_Model_Test extends Unit_Test_Case { - static function instance($config=null) { - require_once(dirname(__file__) . "/HTMLPurifier/HTMLPurifier.auto.php"); - if (self::$_instance == NULL) { - $config = isset($config) ? $config : Kohana::config('purifier'); - $purifier_config = HTMLPurifier_Config::createDefault(); - foreach ($config as $category => $key_value) { - foreach ($key_value as $key => $value) { - $purifier_config->set("$category.$key", $value); - } - } - self::$_instance = new HtmlPurifier($purifier_config); - } + public function cant_view_comments_for_unviewable_items_test() { + $root = ORM::factory("item", 1); + $album = album::create($root, rand(), rand(), rand()); + $comment = comment::create($album, user::guest(), "text", "name", "email", "url"); + user::set_active(user::guest()); - return self::$_instance; + // We can see the comment when permissions are granted on the album + access::allow(group::everybody(), "view", $album); + $this->assert_equal( + 1, + ORM::factory("comment")->viewable()->where("comments.id", $comment->id)->count_all()); + + // We can't see the comment when permissions are denied on the album + access::deny(group::everybody(), "view", $album); + $this->assert_equal( + 0, + ORM::factory("comment")->viewable()->where("comments.id", $comment->id)->count_all()); } } diff --git a/modules/comment/views/admin_block_recent_comments.html.php b/modules/comment/views/admin_block_recent_comments.html.php index 4ff24f86..2afa5bf8 100644 --- a/modules/comment/views/admin_block_recent_comments.html.php +++ b/modules/comment/views/admin_block_recent_comments.html.php @@ -2,15 +2,15 @@ <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()) ?>" + alt="<?= html::clean_attribute($comment->author_name()) ?>" width="32" height="32" /> <?= gallery::date_time($comment->created) ?> <?= t('<a href="#">%author_name</a> said <em>%comment_text</em>', - array("author_name" => p::clean($comment->author_name()), - "comment_text" => text::limit_words(nl2br(p::purify($comment->text)), 50))); ?> + array("author_name" => html::clean($comment->author_name()), + "comment_text" => text::limit_words(nl2br(html::purify($comment->text)), 50))); ?> </li> <? endforeach ?> </ul> diff --git a/modules/comment/views/admin_comments.html.php b/modules/comment/views/admin_comments.html.php index ad0ae8f3..455cd714 100644 --- a/modules/comment/views/admin_comments.html.php +++ b/modules/comment/views/admin_comments.html.php @@ -1,7 +1,7 @@ <?php defined("SYSPATH") or die("No direct script access.") ?> <script type="text/javascript"> var set_state_url = - "<?= url::site("admin/comments/set_state/__ID__/__STATE__?csrf=$csrf") ?>"; + <?= html::js_string(url::site("admin/comments/set_state/__ID__/__STATE__?csrf=$csrf")) ?>; function set_state(state, id) { $.get(set_state_url.replace("__STATE__", state).replace("__ID__", id), {}, @@ -12,7 +12,7 @@ } var delete_url = - "<?= url::site("admin/comments/delete/__ID__?csrf=$csrf") ?>"; + <?= html::js_string(url::site("admin/comments/delete/__ID__?csrf=$csrf")) ?>; function del(id) { $.get(delete_url.replace("__ID__", id), @@ -24,7 +24,7 @@ } function update_menu() { - $.get("<?= url::site("admin/comments/menu_labels") ?>", {}, + $.get(<?= html::js_string(url::site("admin/comments/menu_labels")) ?>, {}, function(data) { for (var i = 0; i < data.length; i++) { $("#gAdminCommentsMenu li:eq(" + i + ") a").html(data[i]); @@ -103,17 +103,17 @@ </th> </tr> <? foreach ($comments as $i => $comment): ?> - <tr id="gComment-<?= $comment->id ?>" class="<?= ($i % 2 == 0) ? "gEvenRow" : "gOddRow" ?>"> + <tr id="gComment-<?= $comment->id ?>" class="<?= ($i % 2 == 0) ? "gOddRow" : "gEvenRow" ?>"> <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()) ?>" + alt="<?= html::clean_attribute($comment->author_name()) ?>" width="40" height="40" /> </a> - <p><a href="mailto:<?= p::clean($comment->author_email()) ?>" - title="<?= p::clean($comment->author_email()) ?>"> <?= p::clean($comment->author_name()) ?> </a></p> + <p><a href="mailto:<?= html::clean_attribute($comment->author_email()) ?>" + title="<?= html::clean_attribute($comment->author_email()) ?>"> <?= html::clean($comment->author_name()) ?> </a></p> </td> <td> <div class="right"> @@ -122,7 +122,7 @@ <a href="<?= $item->url() ?>"> <? if ($item->has_thumb()): ?> <img src="<?= $item->thumb_url() ?>" - alt="<?= p::purify($item->title) ?>" + alt="<?= html::purify($item->title)->for_html_attr() ?>" <?= photo::img_dimensions($item->thumb_width, $item->thumb_height, 75) ?> /> <? else: ?> @@ -132,7 +132,7 @@ </div> </div> <p><?= gallery::date($comment->created) ?></p> - <?= nl2br(p::purify($comment->text)) ?> + <?= nl2br(html::purify($comment->text)) ?> </td> <td> <ul class="gButtonSetVertical"> diff --git a/modules/comment/views/comment.html.php b/modules/comment/views/comment.html.php index ab72a0c8..ce4e197d 100644 --- a/modules/comment/views/comment.html.php +++ b/modules/comment/views/comment.html.php @@ -2,17 +2,17 @@ <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()) ?>" + alt="<?= html::clean_attribute($comment->author_name()) ?>" width="40" height="40" /> </a> <?= t("on %date_time, %author_name said", array("date_time" => gallery::date_time($comment->created), - "author_name" => p::clean($comment->author_name()))) ?> + "author_name" => html::clean($comment->author_name()))) ?> </p> <div> - <?= nl2br(p::purify($comment->text)) ?> + <?= nl2br(html::purify($comment->text)) ?> </div> </li> diff --git a/modules/comment/views/comment.mrss.php b/modules/comment/views/comment.mrss.php index 2b5b13c1..c2a4b538 100644 --- a/modules/comment/views/comment.mrss.php +++ b/modules/comment/views/comment.mrss.php @@ -6,9 +6,9 @@ xmlns:fh="http://purl.org/syndication/history/1.0"> <channel> <generator>Gallery 3</generator> - <title><?= p::clean($feed->title) ?></title> + <title><?= html::clean($feed->title) ?></title> <link><?= $feed->uri ?></link> - <description><?= p::clean($feed->description) ?></description> + <description><?= html::clean($feed->description) ?></description> <language>en-us</language> <atom:link rel="self" href="<?= $feed->uri ?>" type="application/rss+xml" /> <fh:complete/> @@ -22,14 +22,14 @@ <lastBuildDate><?= $pub_date ?></lastBuildDate> <? foreach ($feed->children as $child): ?> <item> - <title><?= p::purify($child->title) ?></title> - <link><?= p::clean($child->item_uri) ?></link> - <author><?= p::clean($child->author) ?></author> + <title><?= html::purify($child->title) ?></title> + <link><?= html::clean($child->item_uri) ?></link> + <author><?= html::clean($child->author) ?></author> <guid isPermaLink="true"><?= $child->item_uri ?></guid> <pubDate><?= $child->pub_date ?></pubDate> <content:encoded> <![CDATA[ - <p><?= nl2br(p::purify($child->text)) ?></p> + <p><?= nl2br(html::purify($child->text)) ?></p> <p> <img alt="" src="<?= $child->thumb_url ?>" height="<?= $child->thumb_height ?>" width="<?= $child->thumb_width ?>" /> diff --git a/modules/comment/views/comments.html.php b/modules/comment/views/comments.html.php index fa25a4e0..7eb34c20 100644 --- a/modules/comment/views/comments.html.php +++ b/modules/comment/views/comments.html.php @@ -1,29 +1,35 @@ <?php defined("SYSPATH") or die("No direct script access.") ?> + <a href="<?= url::site("form/add/comments/{$item->id})") ?>" id="gAddCommentButton" + class="gButtonLink ui-corner-all ui-icon-left ui-state-default right"> + <span class="ui-icon ui-icon-comment"></span> + <?= t("Add a comment") ?> +</a> +<div id="gCommentDetail"> <? if (!$comments->count()): ?> <p id="gNoCommentsYet"> <?= t("No comments yet. Be the first to <a %attrs>comment</a>!", - array("attrs" => "href=\"#add_comment_form\" class=\"showCommentForm\"")) ?> + array("attrs" => html::mark_clean("href=\"#add_comment_form\" class=\"showCommentForm\""))) ?> </p> <? endif ?> -<ul id="gComments"> +<ul> <? foreach ($comments as $comment): ?> <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()) ?>" + alt="<?= html::clean_attribute($comment->author_name()) ?>" width="40" height="40" /> </a> <?= t('on %date <a href="#">%name</a> said', array("date" => date("Y-M-d H:i:s", $comment->created), - "name" => p::clean($comment->author_name()))); ?> + "name" => html::clean($comment->author_name()))); ?> </p> <div> - <?= nl2br(p::purify($comment->text)) ?> + <?= nl2br(html::purify($comment->text)) ?> </div> </li> <? endforeach ?> </ul> -<a name="add_comment_form"></a> +</div> diff --git a/modules/gallery/config/purifier.php b/modules/digibug/config/digibug.php index 30de9dc5..6cd165d1 100644 --- a/modules/gallery/config/purifier.php +++ b/modules/digibug/config/digibug.php @@ -17,11 +17,13 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ - -$config["Cache"] = array( - "SerializerPath" => TMPPATH -); - -$config["Attr"] = array( - "EnableID" => true +/** + * 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..0939704b 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); @@ -50,12 +50,36 @@ class Digibug_Controller extends Controller { "image_width_1" => $item->width, "thumb_height_1" => $item->thumb_height, "thumb_width_1" => $item->thumb_width, - "title_1" => p::purify($item->title)); + "title_1" => html::purify($item->title)); print $v; } 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_event.php index c95cada2..d2830b80 100644 --- a/modules/digibug/helpers/digibug_menu.php +++ b/modules/digibug/helpers/digibug_event.php @@ -17,8 +17,8 @@ * 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_menu { - static function admin($menu, $theme) { +class digibug_event_Core { + static function admin_menu($menu, $theme) { $menu->get("settings_menu") ->append(Menu::factory("link") ->id("digibug_menu") @@ -26,25 +26,25 @@ class digibug_menu { ->url(url::site("admin/digibug"))); } - static function photo($menu, $theme) { + static function photo_menu($menu, $theme) { $item = $theme->item(); - $menu->append( - Menu::factory("link") - ->id("digibug") - ->label(t("Print with Digibug")) - ->url(url::site("digibug/print_photo/$item->id?csrf=$theme->csrf")) - ->css_id("gDigibugLink")); + $menu->append(Menu::factory("link") + ->id("digibug") + ->label(t("Print with Digibug")) + ->url(url::site("digibug/print_photo/$item->id?csrf=$theme->csrf")) + ->css_id("gDigibugLink") + ->css_class("ui-icon-print")); } - static function thumb($menu, $theme, $item) { - if ($item->type == "photo" && access::can("view_full", $item)) { + static function context_menu($menu, $theme, $item) { + if ($item->type == "photo") { $menu->get("options_menu") - ->append( - Menu::factory("link") - ->id("digibug") - ->label(t("Print with Digibug")) - ->url(url::site("digibug/print_photo/$item->id?csrf=$theme->csrf")) - ->css_id("gDigibugLink")); + ->append(Menu::factory("link") + ->id("digibug") + ->label(t("Print with Digibug")) + ->url(url::site("digibug/print_photo/$item->id?csrf=$theme->csrf")) + ->css_id("gDigibugLink") + ->css_class("ui-icon-print")); } } } diff --git a/modules/digibug/helpers/digibug_installer.php b/modules/digibug/helpers/digibug_installer.php index 1cd78b44..7e8145d2 100644 --- a/modules/digibug/helpers/digibug_installer.php +++ b/modules/digibug/helpers/digibug_installer.php @@ -26,7 +26,7 @@ class digibug_installer { `request_date` TIMESTAMP NOT NULL DEFAULT current_timestamp, `item_id` int(9) NOT NULL, PRIMARY KEY (`id`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); module::set_var("digibug", "company_id", "3153"); module::set_var("digibug", "event_id", "8491"); 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/digibug/views/admin_digibug.html.php b/modules/digibug/views/admin_digibug.html.php index 7e4436ff..9a1838f7 100644 --- a/modules/digibug/views/admin_digibug.html.php +++ b/modules/digibug/views/admin_digibug.html.php @@ -16,7 +16,7 @@ <p> <?= t("You don't need an account with Digibug, but if you <a href=\"%signup_url\">register with Digibug</a> and enter your Digibug id in the <a href=\"%advanced_settings_url\">Advanced Settings</a> page you can make money off of your photos!", array("signup_url" => "http://www.digibug.com/signup.php", - "advanced_settings_url" => url::site("admin/advanced_settings"))) ?> + "advanced_settings_url" => html::mark_clean(url::site("admin/advanced_settings")))) ?> </p> </div> </div> diff --git a/modules/exif/helpers/exif.php b/modules/exif/helpers/exif.php index 20ecd0cb..83540622 100644 --- a/modules/exif/helpers/exif.php +++ b/modules/exif/helpers/exif.php @@ -164,7 +164,7 @@ class exif_Core { if ($remaining) { site_status::warning( t('Your Exif index needs to be updated. <a href="%url" class="gDialogLink">Fix this now</a>', - array("url" => url::site("admin/maintenance/start/exif_task::update_index?csrf=__CSRF__"))), + array("url" => html::mark_clean(url::site("admin/maintenance/start/exif_task::update_index?csrf=__CSRF__")))), "exif_index_out_of_date"); } } diff --git a/modules/exif/helpers/exif_event.php b/modules/exif/helpers/exif_event.php index f5677653..826ec959 100644 --- a/modules/exif/helpers/exif_event.php +++ b/modules/exif/helpers/exif_event.php @@ -19,10 +19,12 @@ */ class exif_event_Core { static function item_created($item) { - exif::extract($item); + if (!$item->is_album()) { + exif::extract($item); + } } - static function item_before_delete($item) { + static function item_deleted($item) { Database::instance()->delete("exif_records", array("item_id" => $item->id)); } } diff --git a/modules/exif/helpers/exif_installer.php b/modules/exif/helpers/exif_installer.php index 0233f2bb..66226061 100644 --- a/modules/exif/helpers/exif_installer.php +++ b/modules/exif/helpers/exif_installer.php @@ -28,7 +28,7 @@ class exif_installer { `dirty` BOOLEAN default 1, PRIMARY KEY (`id`), KEY(`item_id`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); module::set_version("exif", 1); } diff --git a/modules/exif/helpers/exif_task.php b/modules/exif/helpers/exif_task.php index f3e77975..7c4c97c4 100644 --- a/modules/exif/helpers/exif_task.php +++ b/modules/exif/helpers/exif_task.php @@ -42,7 +42,6 @@ class exif_task_Core { $completed = $task->get("completed", 0); $start = microtime(true); - $message = array(); foreach (ORM::factory("item") ->join("exif_records", "items.id", "exif_records.item_id", "left") ->where("type", "photo") @@ -51,17 +50,20 @@ class exif_task_Core { ->orwhere("exif_records.dirty", 1) ->close_paren() ->find_all() as $item) { - if (microtime(true) - $start > 1.5) { - break; + // The query above can take a long time, so start the timer after its done + // to give ourselves a little time to actually process rows. + if (!isset($start)) { + $start = microtime(true); } - $completed++; exif::extract($item); - $message[] = t("Updated Exif meta data for '%title'", - array("title" => p::purify($item->title))); + $completed++; + + if (microtime(true) - $start > 1.5) { + break; + } } - $task->log($message); list ($remaining, $total, $percent) = exif::stats(); $task->set("completed", $completed); if ($remaining == 0 || !($remaining + $completed)) { diff --git a/modules/exif/views/exif_dialog.html.php b/modules/exif/views/exif_dialog.html.php index 6494b2b0..11d1e212 100644 --- a/modules/exif/views/exif_dialog.html.php +++ b/modules/exif/views/exif_dialog.html.php @@ -14,14 +14,14 @@ <?= $details[$i]["caption"] ?> </td> <td class="gOdd"> - <?= p::clean($details[$i]["value"]) ?> + <?= html::clean($details[$i]["value"]) ?> </td> <? if (!empty($details[++$i])): ?> <td class="gEven"> <?= $details[$i]["caption"] ?> </td> <td class="gOdd"> - <?= p::clean($details[$i]["value"]) ?> + <?= html::clean($details[$i]["value"]) ?> </td> <? else: ?> <td class="gEven"></td><td class="gOdd"></td> diff --git a/modules/exif/views/exif_sidebar.html.php b/modules/exif/views/exif_sidebar.html.php index ee528613..60c0e1d4 100644 --- a/modules/exif/views/exif_sidebar.html.php +++ b/modules/exif/views/exif_sidebar.html.php @@ -1,5 +1,5 @@ <?php defined("SYSPATH") or die("No direct script access.") ?> -<a id="gExifDataLink" href="<?= url::site("exif/show/{$item->id}") ?>" title="<?= t("Photo Details") ?>" +<a id="gExifDataLink" href="<?= url::site("exif/show/{$item->id}") ?>" title="<?= t("Photo Details")->for_html_attr() ?>" class="gDialogLink gButtonLink ui-icon-left ui-state-default ui-corner-all"> <span class="ui-icon ui-icon-info"></span> <?= t("View more information") ?> diff --git a/modules/forge/libraries/Form_Checkbox.php b/modules/forge/libraries/Form_Checkbox.php index b94fc438..aded4fdf 100644 --- a/modules/forge/libraries/Form_Checkbox.php +++ b/modules/forge/libraries/Form_Checkbox.php @@ -68,7 +68,7 @@ class Form_Checkbox_Core extends Form_Input { $label = ' '.ltrim($label); } - return '<label>'.form::input($data).$label.'</label>'; + return '<label>'.form::input($data).html::clean($label).'</label>'; } protected function load_value() diff --git a/modules/forge/libraries/Form_Checklist.php b/modules/forge/libraries/Form_Checklist.php index 99b455bd..4536d396 100644 --- a/modules/forge/libraries/Form_Checklist.php +++ b/modules/forge/libraries/Form_Checklist.php @@ -67,7 +67,7 @@ class Form_Checklist_Core extends Form_Input { $data['value'] = $val; $data['checked'] = $checked; - $checklist .= '<li><label>'.form::checkbox($data).' '.$title.'</label></li>'.$nl; + $checklist .= '<li><label>'.form::checkbox($data).' '.html::purify($title).'</label></li>'.$nl; } $checklist .= '</ul>'; diff --git a/modules/forge/libraries/Form_Group.php b/modules/forge/libraries/Form_Group.php index 29eff510..e0601321 100644 --- a/modules/forge/libraries/Form_Group.php +++ b/modules/forge/libraries/Form_Group.php @@ -57,7 +57,7 @@ class Form_Group_Core extends Forge { { if ($label = $this->data['label']) { - return $this->data['label']; + return html::purify($this->data['label']); } } else diff --git a/modules/g2_import/helpers/g2_import.php b/modules/g2_import/helpers/g2_import.php index 8b4169dd..7e5c6f75 100644 --- a/modules/g2_import/helpers/g2_import.php +++ b/modules/g2_import/helpers/g2_import.php @@ -376,12 +376,10 @@ class g2_import_Core { } $album->save(); - $message[] = t("Album '%name' imported.", array("name" => $album->name)); - $message[] = self::import_keywords_as_tags($g2_album->getKeywords(), $album); + self::import_keywords_as_tags($g2_album->getKeywords(), $album); self::set_map($g2_album_id, $album->id); // @todo import album highlights - return $message; } /** @@ -401,7 +399,6 @@ class g2_import_Core { } $table = g2(GalleryCoreApi::fetchThumbnailsByItemIds(array($g2_album_id))); - $message = ""; if (isset($table[$g2_album_id])) { // Backtrack the source id to an item $g2_source = $table[$g2_album_id]; @@ -417,10 +414,8 @@ class g2_import_Core { $g2_album->view_count = g2(GalleryCoreApi::fetchItemViewCount($g2_album_id)); $g2_album->save(); graphics::generate($g2_album); - $message = t("Highlight created for album '%name'", array("name" => $g2_album->name)); } } - return $message; } /** @@ -478,7 +473,6 @@ class g2_import_Core { self::_decode_html_special_chars($g2_item->getTitle()), self::_decode_html_special_chars(self::extract_description($g2_item)), self::map($g2_item->getOwnerId())); - $message[].= t("Imported photo: '%title'", array("title" => p::purify($item->title))); } catch (Exception $e) { Kohana::log( "alert", "Corrupt image $g2_path\n" . $e->__toString()); @@ -499,7 +493,6 @@ class g2_import_Core { self::_decode_html_special_chars($g2_item->getTitle()), self::_decode_html_special_chars(self::extract_description($g2_item)), self::map($g2_item->getOwnerId())); - $message[] = t("Imported movie: '%title'", array("title" => p::purify($item->title))); } catch (Exception $e) { Kohana::log("alert", "Corrupt movie $g2_path\n" . $e->__toString()); $message[] = t("Corrupt movie '%path'", array("path" => $g2_path)); @@ -520,14 +513,13 @@ class g2_import_Core { } if (!empty($item)) { - $message[] = self::import_keywords_as_tags($g2_item->getKeywords(), $item); + self::import_keywords_as_tags($g2_item->getKeywords(), $item); } if (isset($item)) { self::set_map($g2_item_id, $item->id); $item->view_count = g2(GalleryCoreApi::fetchItemViewCount($g2_item_id)); $item->save(); - $message[] = t("View count updated: %count", array("count" => $item->view_count)); } if ($corrupt) { @@ -598,7 +590,7 @@ class g2_import_Core { self::map($g2_comment->getId(), $comment->id); return t("Imported comment '%comment' for item with id: %id", array("id" => $comment->item_id, - "comment" => text::limit_words(nl2br(p::purify($comment->text)), 50))); + "comment" => text::limit_words(nl2br(html::purify($comment->text)), 50))); } /** @@ -624,20 +616,14 @@ class g2_import_Core { // Multiword tags have the space changed to dots.s foreach ($tag_names as $tag_name) { $tags .= (strlen($tags) ? ", " : "") . - tag::add($g3_item, preg_replace('/\s+/', '.', $tag_name)); + tag::add($g3_item, $tag_name); } // Tag operations are idempotent so we don't need to map them. Which is good because we don't // have an id for each individual tag mapping anyway so it'd be hard to set up the mapping. - return t("Added '%tags' to '%title'", array("tags" => $tags, - "title" => p::purify($item->title))); } static function import_keywords_as_tags($keywords, $item) { - if (!module::is_active("tag")) { - return t("Gallery 3 tag module is inactive, no keywords will be imported"); - } - // Keywords in G2 are free form. So we don't know what our user used as a separator. Try to // be smart about it. If we see a comma or a semicolon, expect the keywords to be separated // by that delimeter. Otherwise, use space as the delimiter. @@ -656,8 +642,6 @@ class g2_import_Core { $tags .= (strlen($tags) ? ", " : "") . tag::add($item, $keyword); } } - return strlen($tags) ? t("Added '%keywords' to '%title'", - array("keywords" => $tags, "title" => p::purify($item->title))) : ""; } /** diff --git a/modules/g2_import/helpers/g2_import_event.php b/modules/g2_import/helpers/g2_import_event.php index 13f5b1a0..609e1a45 100644 --- a/modules/g2_import/helpers/g2_import_event.php +++ b/modules/g2_import/helpers/g2_import_event.php @@ -18,11 +18,20 @@ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ class g2_import_event_Core { - static function item_before_delete($item) { + static function item_deleted($item) { Database::instance()->delete("g2_maps", array("g3_id" => $item->id)); } static function item_created($item) { g2_import::copy_matching_thumbnails_and_resizes($item); } + + static function admin_menu($menu, $theme) { + $menu + ->get("settings_menu") + ->append(Menu::factory("link") + ->id("g2_import") + ->label(t("Gallery 2 Import")) + ->url(url::site("admin/g2_import"))); + } } diff --git a/modules/g2_import/helpers/g2_import_installer.php b/modules/g2_import/helpers/g2_import_installer.php index 0f87da6c..feacb518 100644 --- a/modules/g2_import/helpers/g2_import_installer.php +++ b/modules/g2_import/helpers/g2_import_installer.php @@ -26,7 +26,7 @@ class g2_import_installer { `g3_id` int(9) NOT NULL, PRIMARY KEY (`id`), KEY (`g2_id`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); module::set_version("g2_import", 1); mkdir(VARPATH . "modules/g2_import"); diff --git a/modules/g2_import/helpers/g2_import_menu.php b/modules/g2_import/helpers/g2_import_menu.php deleted file mode 100644 index 68d75cb4..00000000 --- a/modules/g2_import/helpers/g2_import_menu.php +++ /dev/null @@ -1,29 +0,0 @@ -<?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 g2_import_menu_Core { - static function admin($menu, $theme) { - $menu - ->get("settings_menu") - ->append(Menu::factory("link") - ->id("g2_import") - ->label(t("Gallery 2 Import")) - ->url(url::site("admin/g2_import"))); - } -} diff --git a/modules/g2_import/views/admin_g2_import.html.php b/modules/g2_import/views/admin_g2_import.html.php index da2bb5d1..23ff27a8 100644 --- a/modules/g2_import/views/admin_g2_import.html.php +++ b/modules/g2_import/views/admin_g2_import.html.php @@ -37,9 +37,9 @@ <? if ($g2_sizes["thumb"]["size"] && $thumb_size != $g2_sizes["thumb"]["size"]): ?> <li class="gWarning"> <?= t("Your most common thumbnail size in Gallery 2 is %g2_pixels pixels, but your Gallery 3 thumbnail size is set to %g3_pixels pixels. <a href=\"%url\">Using the same value</a> will speed up your import.", - array("g2_pixels" => $g2_sizes["thumb"]["size"], - "g3_pixels" => $thumb_size, - "url" => url::site("admin/theme_options"))) ?> + array("g2_pixels" => $g2_sizes["thumb"]["size"], + "g3_pixels" => $thumb_size, + "url" => html::mark_clean(url::site("admin/theme_options")))) ?> </li> <? endif ?> @@ -47,8 +47,8 @@ <li class="gWarning"> <?= t("Your most common intermediate size in Gallery 2 is %g2_pixels pixels, but your Gallery 3 thumbnail size is set to %g3_pixels pixels. <a href=\"%url\">Using the same value</a> will speed up your import.", array("g2_pixels" => $g2_sizes["resize"]["size"], - "g3_pixels" => $resize_size, - "url" => url::site("admin/theme_options"))) ?> + "g3_pixels" => $resize_size, + "url" => html::mark_clean(url::site("admin/theme_options")))) ?> </li> <? endif ?> </ul> diff --git a/modules/gallery/controllers/admin_advanced_settings.php b/modules/gallery/controllers/admin_advanced_settings.php index 64007fdb..79bc1183 100644 --- a/modules/gallery/controllers/admin_advanced_settings.php +++ b/modules/gallery/controllers/admin_advanced_settings.php @@ -46,7 +46,7 @@ class Admin_Advanced_Settings_Controller extends Admin_Controller { module::set_var($module_name, $var_name, Input::instance()->post("value")); message::success( t("Saved value for %var (%module_name)", - array("var" => p::clean($var_name), "module_name" => $module_name))); + array("var" => $var_name, "module_name" => $module_name))); print json_encode(array("result" => "success")); } diff --git a/modules/gallery/controllers/admin_graphics.php b/modules/gallery/controllers/admin_graphics.php index 72f8d8e1..c59dd38e 100644 --- a/modules/gallery/controllers/admin_graphics.php +++ b/modules/gallery/controllers/admin_graphics.php @@ -21,41 +21,24 @@ class Admin_Graphics_Controller extends Admin_Controller { public function index() { $view = new Admin_View("admin.html"); $view->content = new View("admin_graphics.html"); - $view->content->available = ""; - - $tk = new ArrayObject(graphics::detect_toolkits(), ArrayObject::ARRAY_AS_PROPS); - $active = module::get_var("gallery", "graphics_toolkit", "none"); - foreach (array("gd", "imagemagick", "graphicsmagick", "none") as $id) { - if ($id == $active) { - $view->content->active = new View("admin_graphics_$id.html"); - $view->content->active->tk = $tk; - $view->content->active->is_active = true; - } else if ($id != "none") { - $v = new View("admin_graphics_$id.html"); - $v->tk = $tk; - $v->is_active = false; - $view->content->available .= $v; - } - } - + $view->content->tk = graphics::detect_toolkits(); + $view->content->active = module::get_var("gallery", "graphics_toolkit", "none"); print $view; } - public function choose($toolkit) { + public function choose($toolkit_id) { access::verify_csrf(); - if ($toolkit != module::get_var("gallery", "graphics_toolkit")) { - module::set_var("gallery", "graphics_toolkit", $toolkit); - - $toolkit_info = graphics::detect_toolkits(); - if ($toolkit == "graphicsmagick" || $toolkit == "imagemagick") { - module::set_var("gallery", "graphics_toolkit_path", $toolkit_info[$toolkit]); - } + if ($toolkit_id != module::get_var("gallery", "graphics_toolkit")) { + $tk = graphics::detect_toolkits(); + module::set_var("gallery", "graphics_toolkit", $toolkit_id); + module::set_var("gallery", "graphics_toolkit_path", $tk->$toolkit_id->dir); site_status::clear("missing_graphics_toolkit"); - message::success(t("Updated Graphics Toolkit")); - log::success("graphics", t("Changed graphics toolkit to: %toolkit", - array("toolkit" => $toolkit))); + + $msg = t("Changed graphics toolkit to: %toolkit", array("toolkit" => $tk->$toolkit_id->name)); + message::success($msg); + log::success("graphics", $msg); } url::redirect("admin/graphics"); diff --git a/modules/gallery/controllers/admin_languages.php b/modules/gallery/controllers/admin_languages.php index d1b805da..d91e5205 100644 --- a/modules/gallery/controllers/admin_languages.php +++ b/modules/gallery/controllers/admin_languages.php @@ -21,7 +21,10 @@ class Admin_Languages_Controller extends Admin_Controller { public function index($share_translations_form=null) { $v = new Admin_View("admin.html"); $v->content = new View("admin_languages.html"); - $v->content->settings_form = $this->_languages_form(); + $v->content->available_locales = locales::available(); + $v->content->installed_locales = locales::installed(); + $v->content->default_locale = module::get_var("gallery", "default_locale"); + if (empty($share_translations_form)) { $share_translations_form = $this->_share_translations_form(); } @@ -32,14 +35,21 @@ class Admin_Languages_Controller extends Admin_Controller { public function save() { access::verify_csrf(); - - $form = $this->_languages_form(); - if ($form->validate()) { - module::set_var("gallery", "default_locale", $form->choose_language->locale->value); - locale::update_installed($form->choose_language->installed_locales->value); - message::success(t("Settings saved")); - } - url::redirect("admin/languages"); + + locales::update_installed($this->input->post("installed_locales")); + + $installed_locales = array_keys(locales::installed()); + $new_default_locale = $this->input->post("default_locale"); + if (!in_array($new_default_locale, $installed_locales)) { + if (!empty($installed_locales)) { + $new_default_locale = $installed_locales[0]; + } else { + $new_default_locale = "en_US"; + } + } + module::set_var("gallery", "default_locale", $new_default_locale); + + print json_encode(array("result" => "success")); } public function share() { @@ -51,7 +61,7 @@ class Admin_Languages_Controller extends Admin_Controller { return $this->index($form); } - if ($form->sharing->share) { + if ($this->input->post("share")) { l10n_client::submit_translations(); message::success(t("Translations submitted")); } else { @@ -88,30 +98,6 @@ class Admin_Languages_Controller extends Admin_Controller { } } - private function _languages_form() { - $all_locales = locale::available(); - $installed_locales = locale::installed(); - $form = new Forge("admin/languages/save", "", "post", array("id" => "gLanguageSettingsForm")); - $group = $form->group("choose_language") - ->label(t("Language settings")); - $group->dropdown("locale") - ->options($installed_locales) - ->selected(module::get_var("gallery", "default_locale")) - ->label(t("Default language")) - ->rules('required'); - - $installation_options = array(); - foreach ($all_locales as $code => $display_name) { - $installation_options[$code] = array($display_name, isset($installed_locales->$code)); - } - $group->checklist("installed_locales") - ->label(t("Installed Languages")) - ->options($installation_options) - ->rules("required"); - $group->submit("save")->value(t("Save settings")); - return $form; - } - private function _outgoing_translations_count() { return ORM::factory("outgoing_translation")->count_all(); } @@ -125,7 +111,7 @@ class Admin_Languages_Controller extends Admin_Controller { $group->input("api_key") ->label(empty($api_key) ? t("This is a unique key that will allow you to send translations to the remote server. To get your API key go to %server-link.", - array("server-link" => html::anchor($server_link))) + array("server-link" => html::mark_clean(html::anchor($server_link)))) : t("API Key")) ->value($api_key) ->error_messages("invalid", t("The API key you provided is invalid.")); diff --git a/modules/gallery/controllers/admin_maintenance.php b/modules/gallery/controllers/admin_maintenance.php index 543961a1..66bcce55 100644 --- a/modules/gallery/controllers/admin_maintenance.php +++ b/modules/gallery/controllers/admin_maintenance.php @@ -34,7 +34,7 @@ class Admin_Maintenance_Controller extends Admin_Controller { "%count tasks are stalled", $stalled_count), t('<a href="%url">view</a>', - array("url" => url::site("admin/maintenance")))); + array("url" => html::mark_clean(url::site("admin/maintenance"))))); } $view = new Admin_View("admin.html"); diff --git a/modules/gallery/controllers/admin_themes.php b/modules/gallery/controllers/admin_themes.php index da001c55..24f91aba 100644 --- a/modules/gallery/controllers/admin_themes.php +++ b/modules/gallery/controllers/admin_themes.php @@ -38,7 +38,7 @@ class Admin_Themes_Controller extends Admin_Controller { $theme_info = new ArrayObject(parse_ini_file($file), ArrayObject::ARRAY_AS_PROPS); $theme_info->description = t($theme_info->description); $theme_info->name = t($theme_info->name); - + $themes[$theme_name] = $theme_info; } return $themes; @@ -54,7 +54,7 @@ class Admin_Themes_Controller extends Admin_Controller { if ($type == "admin") { $view->url = url::site("admin?theme=$theme_name"); } else { - $view->url = url::site("albums/1?theme=$theme_name"); + $view->url = item::root()->url("theme=$theme_name"); } print $view; } diff --git a/modules/gallery/controllers/albums.php b/modules/gallery/controllers/albums.php index d141d157..08a60132 100644 --- a/modules/gallery/controllers/albums.php +++ b/modules/gallery/controllers/albums.php @@ -40,11 +40,13 @@ class Albums_Controller extends Items_Controller { if ($show) { $index = $album->get_position($show); - $page = ceil($index / $page_size); - if ($page == 1) { - url::redirect("albums/$album->id"); - } else { - url::redirect("albums/$album->id?page=$page"); + if ($index) { + $page = ceil($index / $page_size); + if ($page == 1) { + url::redirect($album->abs_url()); + } else { + url::redirect($album->abs_url("page=$page")); + } } } @@ -55,9 +57,9 @@ class Albums_Controller extends Items_Controller { // Make sure that the page references a valid offset if ($page < 1) { - url::redirect("albums/$album->id"); + url::redirect($album->abs_url()); } else if ($page > $max_pages) { - url::redirect("albums/$album->id?page=$max_pages"); + url::redirect($album->abs_url("page=$max_pages")); } $template = new Theme_View("page.html", "album"); @@ -107,22 +109,23 @@ class Albums_Controller extends Items_Controller { $this->input->post("name"), $this->input->post("title", $this->input->post("name")), $this->input->post("description"), - user::active()->id); + user::active()->id, + $this->input->post("slug")); log::success("content", "Created an album", - html::anchor("albums/$new_album->id", "view album")); - message::success( - t("Created album %album_title", array("album_title" => p::clean($new_album->title)))); + html::anchor("albums/$new_album->id", "view album")); + message::success(t("Created album %album_title", + array("album_title" => html::purify($new_album->title)))); print json_encode( array("result" => "success", - "location" => url::site("albums/$new_album->id"), - "resource" => url::site("albums/$new_album->id"))); + "location" => $new_album->url(), + "resource" => $new_album->url())); } else { print json_encode( array( "result" => "error", - "form" => $form->__toString() . html::script("modules/gallery/js/albums_form_add.js"))); + "form" => $form->__toString())); } } @@ -144,13 +147,13 @@ class Albums_Controller extends Items_Controller { user::active()->id); log::success("content", "Added a photo", html::anchor("photos/$photo->id", "view photo")); - message::success( - t("Added photo %photo_title", array("photo_title" => p::clean($photo->title)))); + message::success(t("Added photo %photo_title", + array("photo_title" => html::purify($photo->title)))); print json_encode( array("result" => "success", - "resource" => url::site("photos/$photo->id"), - "location" => url::site("photos/$photo->id"))); + "resource" => $photo->url(), + "location" => $photo->url())); } else { print json_encode( array("result" => "error", @@ -168,43 +171,50 @@ class Albums_Controller extends Items_Controller { $form = album::get_edit_form($album); if ($valid = $form->validate()) { - // Make sure that there's not a conflict if ($album->id != 1 && - Database::instance() - ->from("items") - ->where("parent_id", $album->parent_id) - ->where("id <>", $album->id) - ->where("name", $form->edit_album->dirname->value) - ->count_records()) { - $form->edit_album->dirname->add_error("conflict", 1); - $valid = false; + $form->edit_item->dirname->value != $album->name || + $form->edit_item->slug->value != $album->slug) { + // Make sure that there's not a conflict + if ($row = Database::instance() + ->select(array("name", "slug")) + ->from("items") + ->where("parent_id", $album->parent_id) + ->where("id <>", $album->id) + ->open_paren() + ->where("name", $form->edit_item->dirname->value) + ->orwhere("slug", $form->edit_item->slug->value) + ->close_paren() + ->get() + ->current()) { + if ($row->name == $form->edit_item->dirname->value) { + $form->edit_item->dirname->add_error("name_conflict", 1); + } + if ($row->slug == $form->edit_item->slug->value) { + $form->edit_item->slug->add_error("slug_conflict", 1); + } + $valid = false; + } } } - // @todo - // @todo we need to make sure that filename / dirname components can't contain a / - // @todo - if ($valid) { - $orig = clone $album; - $album->title = $form->edit_album->title->value; - $album->description = $form->edit_album->description->value; - $album->sort_column = $form->edit_album->sort_order->column->value; - $album->sort_order = $form->edit_album->sort_order->direction->value; + $album->title = $form->edit_item->title->value; + $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; if ($album->id != 1) { - $album->rename($form->edit_album->dirname->value); + $album->rename($form->edit_item->dirname->value); } + $album->slug = $form->edit_item->slug->value; $album->save(); - - module::event("item_updated", $orig, $album); + module::event("item_edit_form_completed", $album, $form); log::success("content", "Updated album", "<a href=\"albums/$album->id\">view</a>"); - message::success( - t("Saved album %album_title", array("album_title" => p::clean($album->title)))); + message::success(t("Saved album %album_title", + array("album_title" => html::purify($album->title)))); print json_encode( - array("result" => "success", - "location" => url::site("albums/$album->id"))); + array("result" => "success")); } else { print json_encode( array("result" => "error", @@ -222,8 +232,7 @@ class Albums_Controller extends Items_Controller { switch ($this->input->get("type")) { case "album": - print album::get_add_form($album) . - html::script("modules/gallery/js/albums_form_add.js"); + print album::get_add_form($album); break; case "photo": diff --git a/modules/gallery/controllers/combined.php b/modules/gallery/controllers/combined.php index 925d052d..c1f42bfe 100644 --- a/modules/gallery/controllers/combined.php +++ b/modules/gallery/controllers/combined.php @@ -42,32 +42,34 @@ class Combined_Controller extends Controller { private function _emit($type, $key) { $input = Input::instance(); + // We don't need to save the session for this request + Session::abort_save(); + // Our data is immutable, so if they already have a copy then it needs no updating. if ($input->server("HTTP_IF_MODIFIED_SINCE")) { header('HTTP/1.0 304 Not Modified'); header("Expires: Tue, 19 Jan 2038 00:00:00 GMT"); header("Cache-Control: max-age=2678400"); header('Pragma: public'); - return; + Kohana::close_buffers(false); + return ""; } if (empty($key)) { Kohana::show_404(); } - // We don't need to save the session for this request - Session::abort_save(); - $cache = Cache::instance(); $use_gzip = function_exists("gzencode") && - (strpos($input->server("HTTP_ACCEPT_ENCODING"), "gzip") !== false); + stripos($input->server("HTTP_ACCEPT_ENCODING"), "gzip") !== false && + (int) ini_get("zlib.output_compression") === 0; + if ($use_gzip && $content = $cache->get("{$key}_gz")) { header("Content-Encoding: gzip"); } else { // Fall back to non-gzipped if we have to $content = $cache->get($key); } - if (empty($content)) { Kohana::show_404(); } diff --git a/modules/gallery/controllers/file_proxy.php b/modules/gallery/controllers/file_proxy.php index c5b34033..8cb90c50 100644 --- a/modules/gallery/controllers/file_proxy.php +++ b/modules/gallery/controllers/file_proxy.php @@ -63,21 +63,20 @@ class File_Proxy_Controller extends Controller { // We now have the relative path to the item. Search for it in the path cache $item = ORM::factory("item")->where("relative_path_cache", $path)->find(); if (!$item->loaded) { - // We didn't turn it up. This may mean that the path cache is out of date, so look it up - // the hard way. - // - // Find all items that match the level and name, then iterate over those to find a match. - // In most cases we'll get it in one. Note that for the level calculation, we just count the - // size of $paths. - $paths = explode("/", $path); - $count = count($paths); - foreach (ORM::factory("item") - ->where("name", $paths[$count - 1]) - ->where("level", $count + 1) - ->find_all() as $match) { - if ($match->relative_path() == $path) { - $item = $match; - break; + // We didn't turn it up. It's possible that the relative_path_cache is out of date here. + // There was fallback code, but bharat deleted it in 8f1bca74. If it turns out to be + // necessary, it's easily resurrected. + + // If we're looking for a .jpg then it's it's possible that we're requesting the thumbnail + // for a movie. In that case, the .flv or .mp4 file would have been converted to a .jpg. + // So try some alternate types: + if (preg_match('/.jpg$/', $path)) { + foreach (array("flv", "mp4") as $ext) { + $movie_path = preg_replace('/.jpg$/', ".$ext", $path); + $item = ORM::factory("item")->where("relative_path_cache", $movie_path)->find(); + if ($item->loaded) { + break; + } } } } @@ -116,8 +115,13 @@ class File_Proxy_Controller extends Controller { // We don't need to save the session for this request Session::abort_save(); - // Dump out the image - header("Content-Type: $item->mime_type"); + // Dump out the image. If the item is a movie, then its thumbnail will be a JPG. + if (in_array($item->mime_type, array("video/x-flv", "video/mp4"))) { + header("Content-type: image/jpeg"); + } else { + header("Content-Type: $item->mime_type"); + } + Kohana::close_buffers(false); $fd = fopen($file, "rb"); fpassthru($fd); diff --git a/modules/gallery/controllers/items.php b/modules/gallery/controllers/items.php index 13891726..7f60f2b7 100644 --- a/modules/gallery/controllers/items.php +++ b/modules/gallery/controllers/items.php @@ -25,6 +25,6 @@ class Items_Controller extends REST_Controller { // differently. We could also just delegate here, but it feels more appropriate // to have a single canonical resource mapping. access::required("view", $item); - return url::redirect($item->url(array(), true)); + return url::redirect($item->abs_url()); } } diff --git a/modules/gallery/controllers/l10n_client.php b/modules/gallery/controllers/l10n_client.php index 831c79c1..6e19310b 100644 --- a/modules/gallery/controllers/l10n_client.php +++ b/modules/gallery/controllers/l10n_client.php @@ -90,10 +90,15 @@ class L10n_Client_Controller extends Controller { } $session = Session::instance(); - $session->set("l10n_mode", - !$session->get("l10n_mode", false)); + $l10n_mode = $session->get("l10n_mode", false); + $session->set("l10n_mode", !$l10n_mode); - url::redirect("albums/1"); + $redirect_url = "admin/languages"; + if (!$l10n_mode) { + $redirect_url .= "#l10n-client"; + } + + url::redirect($redirect_url); } private static function _l10n_client_search_form() { diff --git a/modules/gallery/controllers/move.php b/modules/gallery/controllers/move.php index 93ef05a6..87b73436 100644 --- a/modules/gallery/controllers/move.php +++ b/modules/gallery/controllers/move.php @@ -43,7 +43,7 @@ class Move_Controller extends Controller { print json_encode( array("result" => "success", - "location" => url::site("albums/{$target->id}"))); + "location" => $target->url())); } public function show_sub_tree($source_id, $target_id) { diff --git a/modules/gallery/controllers/movies.php b/modules/gallery/controllers/movies.php index 30a5d78c..04e15315 100644 --- a/modules/gallery/controllers/movies.php +++ b/modules/gallery/controllers/movies.php @@ -72,34 +72,45 @@ class Movies_Controller extends Items_Controller { $form = photo::get_edit_form($photo); if ($valid = $form->validate()) { - // Make sure that there's not a conflict - if (Database::instance() - ->from("items") - ->where("parent_id", $photo->parent_id) - ->where("id <>", $photo->id) - ->where("name", $form->edit_photo->filename->value) - ->count_records()) { - $form->edit_photo->filename->add_error("conflict", 1); - $valid = false; + if ($form->edit_item->filename->value != $photo->name || + $form->edit_item->slug->value != $photo->slug) { + // Make sure that there's not a name or slug conflict + if ($row = Database::instance() + ->select(array("name", "slug")) + ->from("items") + ->where("parent_id", $photo->parent_id) + ->where("id <>", $photo->id) + ->open_paren() + ->where("name", $form->edit_item->filename->value) + ->orwhere("slug", $form->edit_item->slug->value) + ->close_paren() + ->get() + ->current()) { + if ($row->name == $form->edit_item->filename->value) { + $form->edit_item->filename->add_error("name_conflict", 1); + } + if ($row->slug == $form->edit_item->slug->value) { + $form->edit_item->slug->add_error("slug_conflict", 1); + } + $valid = false; + } } } if ($valid) { - $orig = clone $photo; - $photo->title = $form->edit_photo->title->value; - $photo->description = $form->edit_photo->description->value; - $photo->rename($form->edit_photo->filename->value); + $photo->title = $form->edit_item->title->value; + $photo->description = $form->edit_item->description->value; + $photo->slug = $form->edit_item->slug->value; + $photo->rename($form->edit_item->filename->value); $photo->save(); + module::event("item_edit_form_completed", $photo, $form); - module::event("item_updated", $orig, $photo); - - log::success("content", "Updated photo", "<a href=\"photos/$photo->id\">view</a>"); + log::success("content", "Updated movie", "<a href=\"{$photo->url()}\">view</a>"); message::success( - t("Saved photo %photo_title", array("photo_title" => p::clean($photo->title)))); + t("Saved movie %movie_title", array("movie_title" => $photo->title))); print json_encode( - array("result" => "success", - "location" => url::site("photos/$photo->id"))); + array("result" => "success")); } else { print json_encode( array("result" => "error", diff --git a/modules/gallery/controllers/packager.php b/modules/gallery/controllers/packager.php index 7b4d68f6..fbb1d07d 100644 --- a/modules/gallery/controllers/packager.php +++ b/modules/gallery/controllers/packager.php @@ -123,6 +123,10 @@ class Packager_Controller extends Controller { // Normalize dates $line = preg_replace("/,$root_created_timestamp,/", ",UNIX_TIMESTAMP(),", $line); $line = preg_replace("/,$root_updated_timestamp,/", ",UNIX_TIMESTAMP(),", $line); + + // Remove ENGINE= specifications + $line = preg_replace("/ENGINE=\S+ /", "", $line); + $buf .= $line; } $fd = fopen($sql_file, "wb"); diff --git a/modules/gallery/controllers/permissions.php b/modules/gallery/controllers/permissions.php index c776a0fd..5f4620b2 100644 --- a/modules/gallery/controllers/permissions.php +++ b/modules/gallery/controllers/permissions.php @@ -71,6 +71,13 @@ class Permissions_Controller extends Controller { access::reset($group, $perm->name, $item); break; } + + // If the active user just took away their own edit permissions, give it back. + if ($perm->name == "edit") { + if (!access::user_can(user::active(), "edit", $item)) { + access::allow($group, $perm->name, $item); + } + } } } diff --git a/modules/gallery/controllers/photos.php b/modules/gallery/controllers/photos.php index 6a62e859..79ad674a 100644 --- a/modules/gallery/controllers/photos.php +++ b/modules/gallery/controllers/photos.php @@ -62,37 +62,48 @@ class Photos_Controller extends Items_Controller { access::required("edit", $photo); $form = photo::get_edit_form($photo); + $valid = $form->validate(); if ($valid = $form->validate()) { - if ($form->edit_photo->filename->value != $photo->name) { - // Make sure that there's not a conflict - if (Database::instance() + if ($form->edit_item->filename->value != $photo->name || + $form->edit_item->slug->value != $photo->slug) { + // Make sure that there's not a name or slug conflict + if ($row = Database::instance() + ->select(array("name", "slug")) ->from("items") ->where("parent_id", $photo->parent_id) ->where("id <>", $photo->id) - ->where("name", $form->edit_photo->filename->value) - ->count_records()) { - $form->edit_photo->filename->add_error("conflict", 1); + ->open_paren() + ->where("name", $form->edit_item->filename->value) + ->orwhere("slug", $form->edit_item->slug->value) + ->close_paren() + ->get() + ->current()) { + if ($row->name == $form->edit_item->filename->value) { + $form->edit_item->filename->add_error("name_conflict", 1); + } + if ($row->slug == $form->edit_item->slug->value) { + $form->edit_item->slug->add_error("slug_conflict", 1); + } $valid = false; } } } if ($valid) { - $orig = clone $photo; - $photo->title = $form->edit_photo->title->value; - $photo->description = $form->edit_photo->description->value; - $photo->rename($form->edit_photo->filename->value); + $photo->title = $form->edit_item->title->value; + $photo->description = $form->edit_item->description->value; + $photo->slug = $form->edit_item->slug->value; + $photo->rename($form->edit_item->filename->value); $photo->save(); + module::event("item_edit_form_completed", $photo, $form); - module::event("item_updated", $orig, $photo); - - log::success("content", "Updated photo", "<a href=\"photos/$photo->id\">view</a>"); + log::success("content", "Updated photo", "<a href=\"{$photo->url()}\">view</a>"); message::success( - t("Saved photo %photo_title", array("photo_title" => p::clean($photo->title)))); + t("Saved photo %photo_title", + array("photo_title" => html::purify($photo->title)))); print json_encode( - array("result" => "success", - "location" => url::site("photos/$photo->id"))); + array("result" => "success")); } else { print json_encode( array("result" => "error", diff --git a/modules/gallery/controllers/quick.php b/modules/gallery/controllers/quick.php index de027c1b..2ac54754 100644 --- a/modules/gallery/controllers/quick.php +++ b/modules/gallery/controllers/quick.php @@ -18,20 +18,6 @@ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ class Quick_Controller extends Controller { - public function pane($id) { - $item = model_cache::get("item", $id); - if (!access::can("view", $item) || !access::can("edit", $item)) { - return ""; - } - - $view = new View("quick_pane.html"); - $page_type = Input::instance()->get("page_type"); - $view->button_list = gallery_quick::get_quick_buttons($item, $page_type); - $view->item = $item; - $view->page_type = $page_type; - print $view; - } - public function rotate($id, $dir) { access::verify_csrf(); $item = model_cache::get("item", $id); @@ -89,7 +75,7 @@ class Quick_Controller extends Controller { access::required("view", $item->parent()); access::required("edit", $item->parent()); - $msg = t("Made <b>%title</b> this album's cover", array("title" => p::purify($item->title))); + $msg = t("Made <b>%title</b> this album's cover", array("title" => html::purify($item->title))); item::make_album_cover($item); message::success($msg); @@ -105,10 +91,10 @@ class Quick_Controller extends Controller { if ($item->is_album()) { print t( "Delete the album <b>%title</b>? All photos and movies in the album will also be deleted.", - array("title" => p::purify($item->title))); + array("title" => html::purify($item->title))); } else { print t("Are you sure you want to delete <b>%title</b>?", - array("title" => p::purify($item->title))); + array("title" => html::purify($item->title))); } $form = item::get_delete_form($item); @@ -122,9 +108,9 @@ class Quick_Controller extends Controller { access::required("edit", $item); if ($item->is_album()) { - $msg = t("Deleted album <b>%title</b>", array("title" => p::purify($item->title))); + $msg = t("Deleted album <b>%title</b>", array("title" => html::purify($item->title))); } else { - $msg = t("Deleted photo <b>%title</b>", array("title" => p::purify($item->title))); + $msg = t("Deleted photo <b>%title</b>", array("title" => html::purify($item->title))); } $parent = $item->parent(); @@ -135,7 +121,7 @@ class Quick_Controller extends Controller { print json_encode(array("result" => "success", "reload" => 1)); } else { print json_encode(array("result" => "success", - "location" => url::site("albums/$parent->id"))); + "location" => $parent->url())); } } diff --git a/modules/gallery/controllers/simple_uploader.php b/modules/gallery/controllers/simple_uploader.php index 75a7b810..156d18ac 100644 --- a/modules/gallery/controllers/simple_uploader.php +++ b/modules/gallery/controllers/simple_uploader.php @@ -1,4 +1,3 @@ - <?php defined("SYSPATH") or die("No direct script access."); /** * Gallery - a web based photo album viewer and editor @@ -72,7 +71,7 @@ class Simple_Uploader_Controller extends Controller { unlink($temp_filename); } header("HTTP/1.1 500 Internal Server Error"); - print "ERROR:" . $e->getMessage(); + print "ERROR: " . $e->getMessage(); return; } unlink($temp_filename); diff --git a/modules/gallery/controllers/after_install.php b/modules/gallery/controllers/welcome_message.php index f066afe4..8fd1e0a0 100644 --- a/modules/gallery/controllers/after_install.php +++ b/modules/gallery/controllers/welcome_message.php @@ -17,13 +17,13 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ -class After_Install_Controller extends Controller { +class Welcome_Message_Controller extends Controller { public function index() { if (!user::active()->admin) { - url::redirect("albums/1"); + url::redirect(item::root()->abs_url()); } - $v = new View("after_install.html"); + $v = new View("welcome_message.html"); $v->user = user::active(); print $v; } diff --git a/modules/gallery/css/l10n_client.css b/modules/gallery/css/l10n_client.css index 51cbc753..9c1b12d0 100644 --- a/modules/gallery/css/l10n_client.css +++ b/modules/gallery/css/l10n_client.css @@ -42,9 +42,17 @@ cursor:pointer; display:block; position:absolute; right:0em; - padding: 0em .75em; height:2em; line-height:2em; + height:2em; line-height:2em; text-transform:uppercase; - text-align:center; background:#000;} + text-align:center; background:#000; +} +#l10n-client-toggler a { + font-size: 1em; + padding: .5em; +} +#l10n-client-toggler #gMinimizeL10n { + border-right: 1px solid #ffffff; +} /* Panel labels */ #l10n-client h2 { diff --git a/modules/gallery/css/quick.css b/modules/gallery/css/quick.css deleted file mode 100644 index 0e45eac2..00000000 --- a/modules/gallery/css/quick.css +++ /dev/null @@ -1,52 +0,0 @@ -#gQuickPane { - position: absolute; - top: 0; - left: 0; - text-align: center; - width: 100%; - height: auto; -} - -.gItem:hover { - background-color: #cfdeff; -} - -.gQuick { - border: none !important; - margin: 0 !important; - padding: 0 !important; -} - -#gQuickPane { - background: #000; - border-bottom: 1px solid #ccc; - opacity: 0.9; - position: absolute; - top: 0; - left: 0; -} - -#gQuickPane a { - cursor: pointer; - float: left; - margin: 4px; -} - -#gQuickPaneOptions { - background: #000; - float: left; - width: 100%; -} - -#gQuickPaneOptions li a { - display: block; - float: none; - width: auto; - margin: 0; - padding: .5em .5em .5em .8em; - text-align: left; -} - -#gQuickPaneOptions li a:hover { - background-color: #4d4d4d; -} diff --git a/modules/gallery/helpers/MY_html.php b/modules/gallery/helpers/MY_html.php new file mode 100644 index 00000000..b29f287f --- /dev/null +++ b/modules/gallery/helpers/MY_html.php @@ -0,0 +1,91 @@ +<?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 html extends html_Core { + /** + * Returns a string that is safe to be used in HTML (XSS protection). + * + * If $html is a string, the returned string will be HTML escaped. + * If $html is a SafeString instance, the returned string may contain + * unescaped HTML which is assumed to be safe. + * + * Example:<pre> + * <div><?= html::clean($php_var) ?> + * </pre> + */ + static function clean($html) { + return new SafeString($html); + } + + /** + * Returns a string that is safe to be used in HTML (XSS protection), + * purifying (filtering) the given HTML to ensure that the result contains + * only non-malicious HTML. + * + * Example:<pre> + * <div><?= html::purify($item->title) ?> + * </pre> + */ + static function purify($html) { + return SafeString::purify($html); + } + + /** + * Flags the given string as safe to be used in HTML (free of malicious HTML/JS). + * + * Example:<pre> + * // Parameters to t() are automatically escaped by default. + * // If the parameter is marked as clean, it won't get escaped. + * t('Go <a href="%url">there</a>', + * array("url" => html::mark_clean(url::current()))) + * </pre> + */ + static function mark_clean($html) { + return SafeString::of_safe_html($html); + } + + /** + * Escapes the given string for use in JavaScript. + * + * Example:<pre> + * <script type="text/javascript>" + * var some_js_string = <?= html::js_string($php_string) ?>; + * </script> + * </pre> + */ + static function js_string($string) { + return SafeString::of($string)->for_js(); + } + + /** + * Returns a string safe for use in HTML element attributes. + * + * Assumes that the HTML element attribute is already + * delimited by single or double quotes + * + * Example:<pre> + * <a title="<?= html::clean_for_attribute($php_var) ?>">; + * </script> + * </pre> + * @return the string escaped for use in HTML attributes. + */ + static function clean_attribute($string) { + return self::clean($string)->for_html_attr(); + } +} diff --git a/modules/gallery/helpers/MY_url.php b/modules/gallery/helpers/MY_url.php index c4967c52..368c947e 100644 --- a/modules/gallery/helpers/MY_url.php +++ b/modules/gallery/helpers/MY_url.php @@ -18,21 +18,6 @@ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ class url extends url_Core { - static function site($uri, $protocol=false) { - if (($pos = strpos($uri, "?")) !== false) { - list ($uri, $query) = explode("?", $uri, 2); - $query = "?$query"; - } else { - $query = ""; - } - - $parts = explode("/", $uri, 3); - if ($parts[0] == "albums" || $parts[0] == "photos") { - $uri = model_cache::get("item", $parts[1])->relative_path(); - } - return parent::site($uri . $query, $protocol); - } - static function parse_url() { if (Router::$controller) { return; @@ -55,20 +40,24 @@ class url extends url_Core { } /** - * Return the item that the uri is referencing + * Locate an item using the URI. We assume that the uri is in the form /a/b/c where each + * component matches up with an item slug. + * @param string $uri the uri fragment + * @return Item_Model */ static function get_item_from_uri($uri) { $current_uri = html_entity_decode($uri, ENT_QUOTES); - $item = ORM::factory("item")->where("relative_path_cache", $current_uri)->find(); + // In most cases, we'll have an exact match in the relative_url_cache item field. + // but failing that, walk down the tree until we find it. The fallback code will fix caches + // as it goes, so it'll never be run frequently. + $item = ORM::factory("item")->where("relative_url_cache", $current_uri)->find(); if (!$item->loaded) { - // It's possible that the relative path cache for the item we're looking for is out of date, - // so find it the hard way. $count = count(Router::$segments); foreach (ORM::factory("item") - ->where("name", html_entity_decode(Router::$segments[$count - 1], ENT_QUOTES)) + ->where("slug", html_entity_decode(Router::$segments[$count - 1], ENT_QUOTES)) ->where("level", $count + 1) ->find_all() as $match) { - if ($match->relative_path() == $current_uri) { + if ($match->relative_url() == $current_uri) { $item = $match; } } diff --git a/modules/gallery/helpers/access.php b/modules/gallery/helpers/access.php index c48f0b79..949aea84 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? @@ -78,18 +79,30 @@ class access_Core { * @return boolean */ static function can($perm_name, $item) { + return self::user_can(user::active(), $perm_name, $item); + } + + /** + * Does the user have this permission on this item? + * + * @param User_Model $user + * @param string $perm_name + * @param Item_Model $item + * @return boolean + */ + static function user_can($user, $perm_name, $item) { if (!$item->loaded) { return false; } - if (user::active()->admin) { + if ($user->admin) { return true; } $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; } } @@ -129,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"); @@ -153,11 +166,11 @@ class access_Core { // For view permissions, if any parent is self::DENY, then those parents lock this one. // Return $lock = ORM::factory("item") - ->where("`left` <= $item->left") - ->where("`right` >= $item->right") + ->where("`left_ptr` <= $item->left_ptr") + ->where("`right_ptr` >= $item->right_ptr") ->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(); @@ -205,6 +218,7 @@ class access_Core { } self::_update_htaccess_files($album, $group, $perm_name, $value); + model_cache::clear(); } /** @@ -240,7 +254,23 @@ 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); + } + + /** + * Recalculate the permissions for a given item and its hierarchy. $item must be an album. + */ + static function recalculate_permissions($item) { + foreach (self::_get_all_groups() as $group) { + foreach (ORM::factory("permission")->find_all() as $perm) { + if ($perm->name == "view") { + self::_update_access_view_cache($group, $item); + } else { + self::_update_access_non_view_cache($group, $perm->name, $item); + } + } + } + model_cache::clear(); } /** @@ -411,6 +441,7 @@ class access_Core { $cache_table = $perm_name == "view" ? "items" : "access_caches"; $db->query("ALTER TABLE {{$cache_table}} DROP `$field`"); $db->query("ALTER TABLE {access_intents} DROP `$field`"); + model_cache::clear(); ORM::factory("access_intent")->clear_cache(); } @@ -425,9 +456,11 @@ 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(); } @@ -457,11 +490,11 @@ class access_Core { // item, then its safe to propagate from here. if ($access->$field !== self::DENY) { $tmp_item = ORM::factory("item") - ->where("left <", $item->left) - ->where("right >", $item->right) + ->where("left_ptr <", $item->left_ptr) + ->where("right_ptr >", $item->right_ptr) ->join("access_intents", "access_intents.item_id", "items.id") ->where("access_intents.$field", self::DENY) - ->orderby("left", "DESC") + ->orderby("left_ptr", "DESC") ->limit(1) ->find(); if ($tmp_item->loaded) { @@ -474,26 +507,26 @@ class access_Core { // them according the rule above. So mark every permission below this level as UNKNOWN so // that we can tell which permissions have been changed, and which ones need to be updated. $db->update("items", array($field => self::UNKNOWN), - array("left >=" => $item->left, "right <=" => $item->right)); + array("left_ptr >=" => $item->left_ptr, "right_ptr <=" => $item->right_ptr)); $query = ORM::factory("access_intent") - ->select(array("access_intents.$field", "items.left", "items.right", "items.id")) + ->select(array("access_intents.$field", "items.left_ptr", "items.right_ptr", "items.id")) ->join("items", "items.id", "access_intents.item_id") - ->where("left >=", $item->left) - ->where("right <=", $item->right) + ->where("left_ptr >=", $item->left_ptr) + ->where("right_ptr <=", $item->right_ptr) ->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) { if ($row->$field == self::ALLOW) { // Propagate ALLOW for any row that is still UNKNOWN. $db->update("items", array($field => $row->$field), - array($field => self::UNKNOWN, "left >=" => $row->left, "right <=" => $row->right)); + array($field => self::UNKNOWN, "left_ptr >=" => $row->left_ptr, "right_ptr <=" => $row->right_ptr)); } else if ($row->$field == self::DENY) { // DENY overwrites everything below it $db->update("items", array($field => $row->$field), - array("left >=" => $row->left, "right <=" => $row->right)); + array("left_ptr >=" => $row->left_ptr, "right_ptr <=" => $row->right_ptr)); } } @@ -501,7 +534,7 @@ class access_Core { // DENY parent in the hierarchy to propagate from. So we'll still have a UNKNOWN values in // the hierarchy, and all of those are safe to change to ALLOW. $db->update("items", array($field => self::ALLOW), - array($field => self::UNKNOWN, "left >=" => $item->left, "right <=" => $item->right)); + array($field => self::UNKNOWN, "left_ptr >=" => $item->left_ptr, "right_ptr <=" => $item->right_ptr)); } /** @@ -526,13 +559,13 @@ 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) - ->orderby("left", "DESC") + ->where("left_ptr <", $item->left_ptr) + ->where("right_ptr >", $item->right_ptr) + ->where("$field IS NOT", self::UNKNOWN) + ->orderby("left_ptr", "DESC") ->limit(1) ->find(); if ($tmp_item->loaded) { @@ -543,20 +576,21 @@ class access_Core { // With non-view permissions, each level can override any permissions that came above it // so start at the top and work downwards, overlaying permissions as we go. $query = ORM::factory("access_intent") - ->select(array("access_intents.$field", "items.left", "items.right")) + ->select(array("access_intents.$field", "items.left_ptr", "items.right_ptr")) ->join("items", "items.id", "access_intents.item_id") - ->where("left >=", $item->left) - ->where("right <=", $item->right) - ->where("$field IS NOT", null) + ->where("left_ptr >=", $item->left_ptr) + ->where("right_ptr <=", $item->right_ptr) + ->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 " . - " AND `right` <= $row->right)"); + " WHERE `left_ptr` >= $row->left_ptr " . + " AND `right_ptr` <= $row->right_ptr)"); } } diff --git a/modules/gallery/helpers/album.php b/modules/gallery/helpers/album.php index 1197f243..dfb1e66d 100644 --- a/modules/gallery/helpers/album.php +++ b/modules/gallery/helpers/album.php @@ -30,9 +30,10 @@ class album_Core { * @param string $name the name of this new album (it will become the directory name on disk) * @param integer $title the title of the new album * @param string $description (optional) the longer description of this album + * @param string $slug (optional) the url component for this photo * @return Item_Model */ - static function create($parent, $name, $title, $description=null, $owner_id=null) { + static function create($parent, $name, $title, $description=null, $owner_id=null, $slug=null) { if (!$parent->loaded || !$parent->is_album()) { throw new Exception("@todo INVALID_PARENT"); } @@ -47,6 +48,10 @@ class album_Core { throw new Exception("@todo NAME_CANNOT_END_IN_PERIOD"); } + if (empty($slug)) { + $slug = item::convert_filename_to_slug($name); + } + $album = ORM::factory("item"); $album->type = "album"; $album->title = $title; @@ -55,15 +60,23 @@ class album_Core { $album->owner_id = $owner_id; $album->thumb_dirty = 1; $album->resize_dirty = 1; + $album->slug = $slug; $album->rand_key = ((float)mt_rand()) / (float)mt_getrandmax(); - $album->sort_column = "weight"; + $album->sort_column = "created"; $album->sort_order = "ASC"; + // Randomize the name or slug if there's a conflict + // @todo Improve this. Random numbers are not user friendly while (ORM::factory("item") ->where("parent_id", $parent->id) + ->open_paren() ->where("name", $album->name) + ->orwhere("slug", $album->slug) + ->close_paren() ->find()->id) { - $album->name = "{$name}-" . rand(); + $rand = rand(); + $album->name = "{$name}-$rand"; + $album->slug = "{$slug}-$rand"; } $album = $album->add_to_parent($parent); @@ -71,6 +84,8 @@ class album_Core { mkdir(dirname($album->thumb_path())); mkdir(dirname($album->resize_path())); + // @todo: publish this from inside Item_Model::save() when we refactor to the point where + // there's only one save() happening here. module::event("item_created", $album); return $album; @@ -82,28 +97,44 @@ class album_Core { ->label(t("Add an album to %album_title", array("album_title" => $parent->title))); $group->input("title")->label(t("Title")); $group->textarea("description")->label(t("Description")); - $group->input("name")->label(t("Directory Name")) + $group->input("name")->label(t("Directory name")) ->callback("item::validate_no_slashes") ->error_messages("no_slashes", t("The directory name can't contain the \"/\" character")); + $group->input("slug")->label(t("Internet Address")) + ->callback("item::validate_url_safe") + ->error_messages( + "not_url_safe", + t("The internet address should contain only letters, numbers, hyphens and underscores")); $group->hidden("type")->value("album"); $group->submit("")->value(t("Create")); $form->add_rules_from(ORM::factory("item")); + $form->script("") + ->url(url::abs_file("modules/gallery/js/albums_form_add.js")); return $form; } 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_album")->label(t("Edit Album")); + $group = $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); if ($parent->id != 1) { $group->input("dirname")->label(t("Directory Name"))->value($parent->name) + ->rules("required") + ->error_messages("name_conflict", t("There is already a photo or album with this name")) ->callback("item::validate_no_slashes") ->error_messages("no_slashes", t("The directory name can't contain a \"/\"")) ->callback("item::validate_no_trailing_period") ->error_messages("no_trailing_period", t("The directory name can't end in \".\"")); + $group->input("slug")->label(t("Internet Address"))->value($parent->slug) + ->error_messages( + "slug_conflict", t("There is already a photo or album with this internet address")) + ->callback("item::validate_url_safe") + ->error_messages( + "not_url_safe", + t("The internet address should contain only letters, numbers, hyphens and underscores")); } $sort_order = $group->group("sort_order", array("id" => "gAlbumSortOrder")) @@ -111,22 +142,33 @@ class album_Core { $sort_order->dropdown("column", array("id" => "gAlbumSortColumn")) ->label(t("Sort by")) - ->options(array("weight" => t("Order Added"), - "captured" => t("Capture Date"), - "created" => t("Creation Date"), - "title" => t("Title"), - "updated" => t("Updated Date"), - "view_count" => t("Number of views"), - "rand_key" => t("Random"))) + ->options(album::get_sort_order_options()) ->selected($parent->sort_column); $sort_order->dropdown("direction", array("id" => "gAlbumSortDirection")) ->label(t("Order")) ->options(array("ASC" => t("Ascending"), "DESC" => t("Descending"))) ->selected($parent->sort_order); + + module::event("item_edit_form", $parent, $form); + + $group = $form->group("buttons")->label(""); $group->hidden("type")->value("album"); $group->submit("")->value(t("Modify")); $form->add_rules_from(ORM::factory("item")); return $form; } + + /** + * Return a structured set of all the possible sort orders. + */ + static function get_sort_order_options() { + return array("weight" => t("Manual"), + "captured" => t("Date captured"), + "created" => t("Date uploaded"), + "title" => t("Title"), + "updated" => t("Date modified"), + "view_count" => t("Number of views"), + "rand_key" => t("Random")); + } } diff --git a/modules/gallery/helpers/gallery.php b/modules/gallery/helpers/gallery.php index a32ac484..813134eb 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 @@ -78,4 +78,232 @@ class gallery_Core { static function time($timestamp) { return date(module::get_var("gallery", "time_format", "H:i:s"), $timestamp); } + + static function site_menu($menu, $theme) { + if ($theme->page_type != "login") { + $menu->append(Menu::factory("link") + ->id("home") + ->label(t("Home")) + ->url(item::root()->url())); + + $item = $theme->item(); + + $can_edit = $item && access::can("edit", $item); + $can_add = $item && access::can("add", $item); + + if ($can_add) { + $menu->append($add_menu = Menu::factory("submenu") + ->id("add_menu") + ->label(t("Add"))); + $add_menu->append(Menu::factory("dialog") + ->id("add_photos_item") + ->label(t("Add photos")) + ->url(url::site("simple_uploader/app/$item->id"))); + if ($item->is_album()) { + $add_menu->append(Menu::factory("dialog") + ->id("add_album_item") + ->label(t("Add an album")) + ->url(url::site("form/add/albums/$item->id?type=album"))); + } + } + + $menu->append($options_menu = Menu::factory("submenu") + ->id("options_menu") + ->label(t("Photo options"))); + if ($item && ($can_edit || $can_add)) { + if ($can_edit) { + $options_menu->append(Menu::factory("dialog") + ->id("edit_item") + ->label($item->is_album() ? t("Edit album") : t("Edit photo")) + ->url(url::site("form/edit/{$item->type}s/$item->id"))); + } + + if ($item->is_album()) { + $options_menu->label(t("Album options")); + if ($can_edit) { + $options_menu->append(Menu::factory("dialog") + ->id("edit_permissions") + ->label(t("Edit permissions")) + ->url(url::site("permissions/browse/$item->id"))); + } + } + } + + if (user::active()->admin) { + $menu->append($admin_menu = Menu::factory("submenu") + ->id("admin_menu") + ->label(t("Admin"))); + gallery::admin_menu($admin_menu, $theme); + module::event("admin_menu", $admin_menu, $theme); + } + + module::event("site_menu", $menu, $theme); + } + } + + static function admin_menu($menu, $theme) { + $menu + ->append(Menu::factory("link") + ->id("dashboard") + ->label(t("Dashboard")) + ->url(url::site("admin"))) + ->append(Menu::factory("submenu") + ->id("settings_menu") + ->label(t("Settings")) + ->append(Menu::factory("link") + ->id("graphics_toolkits") + ->label(t("Graphics")) + ->url(url::site("admin/graphics"))) + ->append(Menu::factory("link") + ->id("languages") + ->label(t("Languages")) + ->url(url::site("admin/languages"))) + ->append(Menu::factory("link") + ->id("advanced") + ->label(t("Advanced")) + ->url(url::site("admin/advanced_settings")))) + ->append(Menu::factory("link") + ->id("modules") + ->label(t("Modules")) + ->url(url::site("admin/modules"))) + ->append(Menu::factory("submenu") + ->id("content_menu") + ->label(t("Content"))) + ->append(Menu::factory("submenu") + ->id("appearance_menu") + ->label(t("Appearance")) + ->append(Menu::factory("link") + ->id("themes") + ->label(t("Theme Choice")) + ->url(url::site("admin/themes"))) + ->append(Menu::factory("link") + ->id("theme_options") + ->label(t("Theme Options")) + ->url(url::site("admin/theme_options")))) + ->append(Menu::factory("submenu") + ->id("statistics_menu") + ->label(t("Statistics"))) + ->append(Menu::factory("link") + ->id("maintenance") + ->label(t("Maintenance")) + ->url(url::site("admin/maintenance"))); + return $menu; + } + + static function context_menu($menu, $theme, $item, $thumb_css_selector) { + $menu->append($options_menu = Menu::factory("submenu") + ->id("options_menu") + ->label(t("Options")) + ->css_class("ui-icon-carat-1-n")); + + if (access::can("edit", $item)) { + $page_type = $theme->page_type(); + switch ($item->type) { + case "movie": + $edit_title = t("Edit this movie"); + $delete_title = t("Delete this movie"); + break; + + case "album": + $edit_title = t("Edit this album"); + $delete_title = t("Delete this album"); + break; + + default: + $edit_title = t("Edit this photo"); + $delete_title = t("Delete this photo"); + break; + } + $cover_title = t("Choose as the album cover"); + $move_title = t("Move to another album"); + + $csrf = access::csrf_token(); + + $options_menu->append(Menu::factory("dialog") + ->id("edit") + ->label($edit_title) + ->css_class("ui-icon-pencil") + ->url(url::site("quick/form_edit/$item->id?page_type=$page_type"))); + + + if ($item->is_photo() && graphics::can("rotate")) { + $options_menu + ->append( + Menu::factory("ajax_link") + ->id("rotate_ccw") + ->label(t("Rotate 90° counter clockwise")) + ->css_class("ui-icon-rotate-ccw") + ->ajax_handler("function(data) { " . + "\$.gallery_replace_image(data, \$('$thumb_css_selector')) }") + ->url(url::site("quick/rotate/$item->id/ccw?csrf=$csrf&page_type=$page_type"))) + ->append( + Menu::factory("ajax_link") + ->id("rotate_cw") + ->label(t("Rotate 90° clockwise")) + ->css_class("ui-icon-rotate-cw") + ->ajax_handler("function(data) { " . + "\$.gallery_replace_image(data, \$('$thumb_css_selector')) }") + ->url(url::site("quick/rotate/$item->id/cw?csrf=$csrf&page_type=$page_type"))); + } + + // Don't move photos from the photo page; we don't yet have a good way of redirecting after + // move + if ($page_type == "album") { + $options_menu + ->append(Menu::factory("dialog") + ->id("move") + ->label($move_title) + ->css_class("ui-icon-folder-open") + ->url(url::site("move/browse/$item->id"))); + } + + $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 = " "; + } + if ($item->parent()->id != 1) { + $options_menu + ->append(Menu::factory("ajax_link") + ->id("make_album_cover") + ->label($cover_title) + ->css_class("ui-icon-star") + ->ajax_handler("function(data) { window.location.reload() }") + ->url(url::site("quick/make_album_cover/$item->id?csrf=$csrf"))); + } + $options_menu + ->append(Menu::factory("dialog") + ->id("delete") + ->label($delete_title) + ->css_class("ui-icon-trash") + ->css_id("gQuickDelete") + ->url(url::site("quick/form_delete/$item->id?csrf=$csrf&page_type=$page_type"))); + } + + if ($item->is_album()) { + $options_menu + ->append(Menu::factory("dialog") + ->id("add_item") + ->label(t("Add a photo")) + ->css_class("ui-icon-plus") + ->url(url::site("simple_uploader/app/$item->id"))) + ->append(Menu::factory("dialog") + ->id("add_album") + ->label(t("Add an album")) + ->css_class("ui-icon-note") + ->url(url::site("form/add/albums/$item->id?type=album"))) + ->append(Menu::factory("dialog") + ->id("edit_permissions") + ->label(t("Edit permissions")) + ->css_class("ui-icon-key") + ->url(url::site("permissions/browse/$item->id"))); + } + } + } }
\ No newline at end of file diff --git a/modules/gallery/helpers/gallery_event.php b/modules/gallery/helpers/gallery_event.php index aa11b7c0..64f2a9ff 100644 --- a/modules/gallery/helpers/gallery_event.php +++ b/modules/gallery/helpers/gallery_event.php @@ -23,7 +23,7 @@ class gallery_event_Core { access::add_group($group); } - static function group_before_delete($group) { + static function group_deleted($group) { access::delete_group($group); } @@ -31,10 +31,14 @@ class gallery_event_Core { access::add_item($item); } - static function item_before_delete($item) { + static function item_deleted($item) { access::delete_item($item); } + static function item_moved($item, $old_parent) { + access::recalculate_permissions($item->parent()); + } + static function user_login($user) { // If this user is an admin, check to see if there are any post-install tasks that we need // to run and take care of those now. @@ -43,4 +47,10 @@ class gallery_event_Core { module::clear_var("gallery", "choose_default_tookit"); } } + + static function item_index_data($item, $data) { + $data[] = $item->description; + $data[] = $item->name; + $data[] = $item->title; + } } diff --git a/modules/gallery/helpers/gallery_installer.php b/modules/gallery/helpers/gallery_installer.php index 28c1990f..a1856424 100644 --- a/modules/gallery/helpers/gallery_installer.php +++ b/modules/gallery/helpers/gallery_installer.php @@ -24,13 +24,13 @@ class gallery_installer { `id` int(9) NOT NULL auto_increment, `item_id` int(9), PRIMARY KEY (`id`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); $db->query("CREATE TABLE {access_intents} ( `id` int(9) NOT NULL auto_increment, `item_id` int(9), PRIMARY KEY (`id`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); $db->query("CREATE TABLE {caches} ( `id` int(9) NOT NULL auto_increment, @@ -40,7 +40,7 @@ class gallery_installer { `cache` longblob, PRIMARY KEY (`id`), KEY (`tags`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); $db->query("CREATE TABLE {graphics_rules} ( `id` int(9) NOT NULL auto_increment, @@ -51,7 +51,7 @@ class gallery_installer { `priority` int(9) NOT NULL, `target` varchar(32) NOT NULL, PRIMARY KEY (`id`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); $db->query("CREATE TABLE {incoming_translations} ( `id` int(9) NOT NULL auto_increment, @@ -63,7 +63,7 @@ class gallery_installer { PRIMARY KEY (`id`), UNIQUE KEY(`key`, `locale`), KEY `locale_key` (`locale`, `key`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); $db->query("CREATE TABLE {items} ( `id` int(9) NOT NULL auto_increment, @@ -72,7 +72,7 @@ class gallery_installer { `created` int(9) default NULL, `description` varchar(2048) default NULL, `height` int(9) default NULL, - `left` int(9) NOT NULL, + `left_ptr` int(9) NOT NULL, `level` int(9) NOT NULL, `mime_type` varchar(64) default NULL, `name` varchar(255) default NULL, @@ -80,10 +80,12 @@ class gallery_installer { `parent_id` int(9) NOT NULL, `rand_key` float default NULL, `relative_path_cache` varchar(255) default NULL, + `relative_url_cache` varchar(255) default NULL, `resize_dirty` boolean default 1, `resize_height` int(9) default NULL, `resize_width` int(9) default NULL, - `right` int(9) NOT NULL, + `right_ptr` int(9) NOT NULL, + `slug` varchar(255) default NULL, `sort_column` varchar(64) default NULL, `sort_order` char(4) default 'ASC', `thumb_dirty` boolean default 1, @@ -98,8 +100,9 @@ class gallery_installer { PRIMARY KEY (`id`), KEY `parent_id` (`parent_id`), KEY `type` (`type`), - KEY `random` (`rand_key`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + KEY `random` (`rand_key`), + KEY `weight` (`weight` DESC)) + DEFAULT CHARSET=utf8;"); $db->query("CREATE TABLE {logs} ( `id` int(9) NOT NULL auto_increment, @@ -112,7 +115,7 @@ class gallery_installer { `url` varchar(255) default NULL, `user_id` int(9) default 0, PRIMARY KEY (`id`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); $db->query("CREATE TABLE {messages} ( `id` int(9) NOT NULL auto_increment, @@ -121,7 +124,7 @@ class gallery_installer { `value` varchar(255) default NULL, PRIMARY KEY (`id`), UNIQUE KEY(`key`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); $db->query("CREATE TABLE {modules} ( `id` int(9) NOT NULL auto_increment, @@ -130,7 +133,7 @@ class gallery_installer { `version` int(9) default NULL, PRIMARY KEY (`id`), UNIQUE KEY(`name`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); $db->query("CREATE TABLE {outgoing_translations} ( `id` int(9) NOT NULL auto_increment, @@ -142,7 +145,7 @@ class gallery_installer { PRIMARY KEY (`id`), UNIQUE KEY(`key`, `locale`), KEY `locale_key` (`locale`, `key`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); $db->query("CREATE TABLE {permissions} ( `id` int(9) NOT NULL auto_increment, @@ -150,14 +153,14 @@ class gallery_installer { `name` varchar(64) default NULL, PRIMARY KEY (`id`), UNIQUE KEY(`name`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); $db->query("CREATE TABLE {sessions} ( `session_id` varchar(127) NOT NULL, `data` text NOT NULL, `last_activity` int(10) UNSIGNED NOT NULL, PRIMARY KEY (`session_id`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); $db->query("CREATE TABLE {tasks} ( `id` int(9) NOT NULL auto_increment, @@ -172,7 +175,7 @@ class gallery_installer { `updated` int(9) default NULL, PRIMARY KEY (`id`), KEY (`owner_id`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); $db->query("CREATE TABLE {themes} ( `id` int(9) NOT NULL auto_increment, @@ -180,7 +183,7 @@ class gallery_installer { `version` int(9) default NULL, PRIMARY KEY (`id`), UNIQUE KEY(`name`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); $db->query("CREATE TABLE {vars} ( `id` int(9) NOT NULL auto_increment, @@ -189,7 +192,7 @@ class gallery_installer { `value` text, PRIMARY KEY (`id`), UNIQUE KEY(`module_name`, `name`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); foreach (array("albums", "logs", "modules", "resizes", "thumbs", "tmp", "uploads") as $dir) { @mkdir(VARPATH . $dir); @@ -204,8 +207,8 @@ class gallery_installer { $root->type = "album"; $root->title = "Gallery"; $root->description = ""; - $root->left = 1; - $root->right = 2; + $root->left_ptr = 1; + $root->right_ptr = 2; $root->parent_id = 0; $root->level = 1; $root->thumb_dirty = 1; @@ -222,6 +225,7 @@ class gallery_installer { module::set_var("gallery", "resize_size", 640); module::set_var("gallery", "default_locale", "en_US"); module::set_var("gallery", "image_quality", 75); + module::set_var("gallery", "image_sharpen", 15); // Add rules for generating our thumbnails and resizes graphics::add_rule( @@ -258,7 +262,7 @@ class gallery_installer { module::set_var("gallery", "show_credits", 1); // @todo this string needs to be picked up by l10n_scanner module::set_var("gallery", "credits", "Powered by <a href=\"%url\">Gallery %version</a>"); - module::set_version("gallery", 7); + module::set_version("gallery", 12); } static function upgrade($version) { @@ -283,7 +287,7 @@ class gallery_installer { `cache` text, PRIMARY KEY (`id`), KEY (`tags`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); module::set_version("gallery", $version = 4); } @@ -305,6 +309,55 @@ 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); + } + + if ($version == 8) { + $db->query("ALTER TABLE {items} CHANGE COLUMN `left` `left_ptr` INT(9) NOT NULL;"); + $db->query("ALTER TABLE {items} CHANGE COLUMN `right` `right_ptr` INT(9) NOT NULL;"); + module::set_version("gallery", $version = 9); + } + + if ($version == 9) { + $db->query("ALTER TABLE {items} ADD KEY `weight` (`weight` DESC);"); + + module::set_version("gallery", $version = 10); + } + + if ($version == 10) { + module::set_var("gallery", "image_sharpen", 15); + + module::set_version("gallery", $version = 11); + } + + if ($version == 11) { + $db->query("ALTER TABLE {items} ADD COLUMN `relative_url_cache` varchar(255) DEFAULT NULL"); + $db->query("ALTER TABLE {items} ADD COLUMN `slug` varchar(255) DEFAULT NULL"); + + // This is imperfect since some of the slugs may contain invalid characters, but it'll do + // for now because we don't want a lengthy operation here. + $db->query("UPDATE {items} SET `slug` = `name`"); + + // Flush all path caches becuase we're going to start urlencoding them. + $db->query("UPDATE {items} SET `relative_url_cache` = NULL, `relative_path_cache` = NULL"); + module::set_version("gallery", $version = 12); + } } static function uninstall() { diff --git a/modules/gallery/helpers/gallery_menu.php b/modules/gallery/helpers/gallery_menu.php deleted file mode 100644 index b6f763b8..00000000 --- a/modules/gallery/helpers/gallery_menu.php +++ /dev/null @@ -1,167 +0,0 @@ -<?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 gallery_menu_Core { - static function site($menu, $theme) { - $is_admin = user::active()->admin; - - $menu->append(Menu::factory("link") - ->id("home") - ->label(t("Home")) - ->url(url::site("albums/1"))); - - $item = $theme->item(); - - $can_edit = $item && access::can("edit", $item) || $is_admin; - $can_add = $item && (access::can("add", $item) || $is_admin); - - if ($can_add) { - $menu->append(Menu::factory("dialog") - ->id("add_photos_item") - ->label(t("Add photos")) - ->url(url::site("simple_uploader/app/$item->id"))); - } - - if ($item && $can_edit || $can_add) { - $menu->append($options_menu = Menu::factory("submenu") - ->id("options_menu") - ->label(t("Options"))); - - if ($can_edit) { - $options_menu - ->append(Menu::factory("dialog") - ->id("edit_item") - ->label($item->is_album() ? t("Edit album") : t("Edit photo")) - ->url(url::site("form/edit/{$item->type}s/$item->id"))); - } - - // @todo Move album options menu to the album quick edit pane - if ($item->is_album()) { - if ($can_add) { - $options_menu - ->append(Menu::factory("dialog") - ->id("add_album") - ->label(t("Add an album")) - ->url(url::site("form/add/albums/$item->id?type=album"))); - } - - if ($can_edit) { - $options_menu - ->append(Menu::factory("dialog") - ->id("edit_permissions") - ->label(t("Edit permissions")) - ->url(url::site("permissions/browse/$item->id"))); - } - } - } - - if ($is_admin) { - $menu->append($admin_menu = Menu::factory("submenu") - ->id("admin_menu") - ->label(t("Admin"))); - self::admin($admin_menu, $theme); - foreach (module::active() as $module) { - if ($module->name == "gallery") { - continue; - } - $class = "{$module->name}_menu"; - if (method_exists($class, "admin")) { - call_user_func_array(array($class, "admin"), array(&$admin_menu, $theme)); - } - } - } - } - - static function album($menu, $theme) { - } - - static function tag($menu, $theme) { - } - - static function thumb($menu, $theme, $item) { - $menu->append(Menu::factory("submenu") - ->id("options_menu") - ->label(t("Options")) - ->css_class("gThumbMenu")); - } - - static function photo($menu, $theme) { - if (access::can("view_full", $theme->item())) { - $menu->append(Menu::factory("link") - ->id("fullsize") - ->label(t("View full size")) - ->url($theme->item()->file_url()) - ->css_class("gFullSizeLink")); - } - } - - static function admin($menu, $theme) { - $menu - ->append(Menu::factory("link") - ->id("dashboard") - ->label(t("Dashboard")) - ->url(url::site("admin"))) - ->append(Menu::factory("submenu") - ->id("settings_menu") - ->label(t("Settings")) - ->append(Menu::factory("link") - ->id("graphics_toolkits") - ->label(t("Graphics")) - ->url(url::site("admin/graphics"))) - ->append(Menu::factory("link") - ->id("languages") - ->label(t("Languages")) - ->url(url::site("admin/languages"))) - ->append(Menu::factory("link") - ->id("l10n_mode") - ->label(Session::instance()->get("l10n_mode", false) - ? t("Stop translating") : t("Start translating")) - ->url(url::site("l10n_client/toggle_l10n_mode?csrf=" . - access::csrf_token()))) - ->append(Menu::factory("link") - ->id("advanced") - ->label(t("Advanced")) - ->url(url::site("admin/advanced_settings")))) - ->append(Menu::factory("link") - ->id("modules") - ->label(t("Modules")) - ->url(url::site("admin/modules"))) - ->append(Menu::factory("submenu") - ->id("content_menu") - ->label(t("Content"))) - ->append(Menu::factory("submenu") - ->id("appearance_menu") - ->label(t("Appearance")) - ->append(Menu::factory("link") - ->id("themes") - ->label(t("Theme Choice")) - ->url(url::site("admin/themes"))) - ->append(Menu::factory("link") - ->id("theme_options") - ->label(t("Theme Options")) - ->url(url::site("admin/theme_options")))) - ->append(Menu::factory("submenu") - ->id("statistics_menu") - ->label(t("Statistics"))) - ->append(Menu::factory("link") - ->id("maintenance") - ->label(t("Maintenance")) - ->url(url::site("admin/maintenance"))); - } -} diff --git a/modules/gallery/helpers/gallery_quick.php b/modules/gallery/helpers/gallery_quick.php deleted file mode 100644 index d0ffc584..00000000 --- a/modules/gallery/helpers/gallery_quick.php +++ /dev/null @@ -1,144 +0,0 @@ -<?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 gallery_quick_Core { - static function get_quick_buttons($item, $page_type) { - $buttons = self::buttons($item, $page_type); - foreach (module::active() as $module) { - if ($module->name == "gallery") { - continue; - } - $class_name = "{$module->name}_quick"; - if (method_exists($class_name, "buttons")) { - $module_buttons = call_user_func(array($class_name, "buttons"), $item, $page_type); - foreach (array("left", "center", "right", "additional") as $position) { - if (!empty($module_buttons[$position])) { - $buttons[$position] = array_merge($buttons[$position], $module_buttons[$position]); - } - } - } - } - - $sorted_buttons->main = array(); - foreach (array("left", "center", "right") as $position) { - $sorted_buttons->main = array_merge($sorted_buttons->main, $buttons[$position]); - } - - $sorted_buttons->additional = $buttons["additional"]; - $max_display = empty($sorted_buttons->additional) ? 6 : 5; - if (count($sorted_buttons->main) >= $max_display) { - $to_move = array_slice($sorted_buttons->main, 5); - $sorted_buttons->additional = array_merge($to_move, $sorted_buttons->additional); - for ($i = count($sorted_buttons->main); $i >= 5; $i--) { - unset($sorted_buttons->main[$i]); - } - } - - return $sorted_buttons; - } - - static function buttons($item, $page_type) { - $elements = array("left" => array(), "center" => array(), "right" => array(), - "additional" => array()); - switch ($item->type) { - case "movie": - $edit_title = t("Edit this movie"); - $move_title = t("Move this movie to another album"); - $cover_title = t("Choose this movie as the album cover"); - $delete_title = t("Delete this movie"); - break; - case "album": - $edit_title = t("Edit this album"); - $move_title = t("Move this album to another album"); - $cover_title = t("Choose this album as the album cover"); - $delete_title = t("Delete this album"); - break; - default: - $edit_title = t("Edit this photo"); - $move_title = t("Move this photo to another album"); - $cover_title = t("Choose this photo as the album cover"); - $delete_title = t("Delete this photo"); - break; - } - - $csrf = access::csrf_token(); - $elements["left"][] = (object)array( - "title" => $edit_title, - "class" => "gDialogLink gButtonLink", - "icon" => "ui-icon-pencil", - "href" => url::site("quick/form_edit/$item->id?page_type=$page_type")); - - if ($item->is_photo() && graphics::can("rotate")) { - $elements["left"][] = - (object)array( - "title" => t("Rotate 90 degrees counter clockwise"), - "class" => "gButtonLink", - "icon" => "ui-icon-rotate-ccw", - "href" => url::site("quick/rotate/$item->id/ccw?csrf=$csrf&page_type=$page_type")); - $elements["left"][] = - (object)array( - "title" => t("Rotate 90 degrees clockwise"), - "class" => "gButtonLink", - "icon" => "ui-icon-rotate-cw", - "href" => url::site("quick/rotate/$item->id/cw?csrf=$csrf&page_type=$page_type")); - } - - // Don't move photos from the photo page; we don't yet have a good way of redirecting after move - if ($page_type == "album") { - $elements["left"][] = (object)array( - "title" => $move_title, - "class" => "gDialogLink gButtonLink", - "icon" => "ui-icon-folder-open", - "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" : ""; - $elements["right"][] = (object)array( - "title" => $cover_title, - "class" => "gButtonLink{$disabledState}", - "icon" => "ui-icon-star", - "href" => url::site("quick/make_album_cover/$item->id?csrf=$csrf&page_type=$page_type")); - - $elements["right"][] = (object)array( - "title" => $delete_title, - "class" => "gDialogLink gButtonLink", - "icon" => "ui-icon-trash", - "id" => "gQuickDelete", - "href" => url::site("quick/form_delete/$item->id?csrf=$csrf&page_type=$page_type")); - } - - if ($item->is_album()) { - $elements["additional"][] = (object)array( - "title" => t("Add a photo"), - "class" => "add_item gDialogLink", - "href" => url::site("simple_uploader/app/$item->id")); - $elements["additional"][] = (object)array( - "title" => t("Add an album"), - "class" => "add_album gDialogLink", - "href" => url::site("form/add/albums/$item->id?type=album")); - $elements["additional"][] = (object)array( - "title" => t("Edit permissions"), - "class" => "permissions gDialogLink", - "href" => url::site("permissions/browse/$item->id")); - } - return $elements; - } -} diff --git a/modules/gallery/helpers/gallery_rss.php b/modules/gallery/helpers/gallery_rss.php index 7daf6170..feeab88a 100644 --- a/modules/gallery/helpers/gallery_rss.php +++ b/modules/gallery/helpers/gallery_rss.php @@ -40,7 +40,6 @@ class gallery_rss_Core { $feed->max_pages = ceil($all_children->find_all()->count() / $limit); $feed->title = t("Recent Updates"); - $feed->link = url::abs_site("albums/1"); $feed->description = t("Recent Updates"); return $feed; @@ -50,11 +49,11 @@ class gallery_rss_Core { $feed->children = $item ->viewable() - ->descendants($limit, $offset, "photo"); - $feed->max_pages = ceil($item->viewable()->descendants_count("photo") / $limit); - $feed->title = p::purify($item->title); - $feed->link = url::abs_site("albums/{$item->id}"); - $feed->description = nl2br(p::purify($item->description)); + ->descendants($limit, $offset, array("type" => "photo")); + $feed->max_pages = ceil( + $item->viewable()->descendants_count(array("type" => "photo")) / $limit); + $feed->title = html::purify($item->title); + $feed->description = nl2br(html::purify($item->description)); return $feed; } diff --git a/modules/gallery/helpers/gallery_search.php b/modules/gallery/helpers/gallery_search.php deleted file mode 100644 index 2a4029d3..00000000 --- a/modules/gallery/helpers/gallery_search.php +++ /dev/null @@ -1,24 +0,0 @@ -<?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 gallery_search_Core { - static function item_index_data($item) { - return join(" ", array($item->description, $item->name, $item->title)); - } -} diff --git a/modules/gallery/helpers/gallery_task.php b/modules/gallery/helpers/gallery_task.php index 9ce2c4a0..1b56ab97 100644 --- a/modules/gallery/helpers/gallery_task.php +++ b/modules/gallery/helpers/gallery_task.php @@ -45,7 +45,7 @@ class gallery_task_Core { * @param Task_Model the task */ static function rebuild_dirty_images($task) { - $message = array(); + $errors = array(); try { $result = graphics::find_dirty_images_query(); $completed = $task->get("completed", 0); @@ -60,14 +60,15 @@ class gallery_task_Core { $item = ORM::factory("item", $row->id); if ($item->loaded) { - $success = graphics::generate($item); - if (!$success) { + try { + graphics::generate($item); $ignored[$item->id] = 1; - $message[] = t("Unable to rebuild images for '%title'", - array("title" => p::purify($item->title))); - } else { - $message[] = t("Successfully rebuilt images for '%title'", - array("title" => p::purify($item->title))); + $errors[] = t("Successfully rebuilt images for '%title'", + array("title" => html::purify($item->title))); + } catch (Exception $e) { + $errors[] = t("Unable to rebuild images for '%title'", + array("title" => html::purify($item->title))); + $errors[] = $e->__toString(); } } @@ -101,13 +102,15 @@ class gallery_task_Core { $task->done = true; $task->state = "error"; $task->status = $e->getMessage(); - $message[] = $e->__toString(); + $errors[] = $e->__toString(); + } + if ($errors) { + $task->log($errors); } - $task->log($message); } static function update_l10n(&$task) { - $message = array(); + $errors = array(); try { $start = microtime(true); $dirs = $task->get("dirs"); @@ -139,8 +142,8 @@ class gallery_task_Core { } } - $message[] = $task->status = t2("Finding files: found 1 file", - "Finding files: found %count files", count($files)); + $task->status = t2("Finding files: found 1 file", + "Finding files: found %count files", count($files)); if (!$dirs) { $task->set("mode", "scan_files"); @@ -165,8 +168,8 @@ class gallery_task_Core { } $total_files = $task->get("total_files"); - $message[] = $task->status = t2("Scanning files: scanned 1 file", - "Scanning files: scanned %count files", $total_files - count($files)); + $task->status = t2("Scanning files: scanned 1 file", + "Scanning files: scanned %count files", $total_files - count($files)); $task->percent_complete = 10 + 80 * ($total_files - count($files)) / $total_files; if (empty($files)) { @@ -177,7 +180,7 @@ class gallery_task_Core { break; case "fetch_updates": // 90% - 100% - $message = array_merge($message, l10n_client::fetch_updates()); + l10n_client::fetch_updates(); $task->done = true; $task->state = "success"; $task->status = t("Translations installed/updated"); @@ -191,8 +194,10 @@ class gallery_task_Core { $task->done = true; $task->state = "error"; $task->status = $e->getMessage(); - $message[] = $e->__toString(); + $errors[] = $e->__toString(); + } + if ($errors) { + $task->log($errors); } - $task->log($message); } }
\ No newline at end of file diff --git a/modules/gallery/helpers/gallery_theme.php b/modules/gallery/helpers/gallery_theme.php index 226b8a42..20dfeb04 100644 --- a/modules/gallery/helpers/gallery_theme.php +++ b/modules/gallery/helpers/gallery_theme.php @@ -22,67 +22,41 @@ class gallery_theme_Core { $session = Session::instance(); $buf = ""; if ($session->get("debug")) { - $theme->css("modules/gallery/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("debug.css"); } if (module::is_active("rss")) { if ($item = $theme->item()) { - $buf .= rss::feed_link("gallery/album/{$item->id}"); + if ($item->is_album()) { + $buf .= rss::feed_link("gallery/album/{$item->id}"); + } else { + $buf .= rss::feed_link("gallery/album/{$item->parent()->id}"); + } } else if ($tag = $theme->tag()) { $buf .= rss::feed_link("tag/tag/{$tag->id}"); } } 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; } - static function resize_top($theme, $item) { - if (access::can("edit", $item)) { - $edit_link = url::site("quick/pane/$item->id?page_type=photo"); - return "<div class=\"gQuick\" href=\"$edit_link\">"; - } - } - - static function resize_bottom($theme, $item) { - if (access::can("edit", $item)) { - return "</div>"; - } - } - - static function thumb_top($theme, $child) { - if (access::can("edit", $child)) { - $edit_link = url::site("quick/pane/$child->id?page_type=album"); - return "<div class=\"gQuick\" href=\"$edit_link\">"; - } - } - - static function thumb_bottom($theme, $child) { - if (access::can("edit", $child)) { - return "</div>"; - } - } - static function admin_head($theme) { + $theme->script("gallery.panel.js"); $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"); } } @@ -98,7 +72,7 @@ class gallery_theme_Core { if ($session->get("after_install")) { $session->delete("after_install"); - return new View("after_install_loader.html"); + return new View("welcome_message_loader.html"); } } @@ -123,4 +97,10 @@ class gallery_theme_Core { static function admin_credits() { return gallery_theme::credits(); } + + static function body_attributes() { + if (locales::is_rtl()) { + return 'class="rtl"'; + } + } }
\ No newline at end of file diff --git a/modules/gallery/helpers/graphics.php b/modules/gallery/helpers/graphics.php index db9b2ef5..78812794 100644 --- a/modules/gallery/helpers/graphics.php +++ b/modules/gallery/helpers/graphics.php @@ -102,12 +102,12 @@ class graphics_Core { /** * Rebuild the thumb and resize for the given item. * @param Item_Model $item - * @return true on successful generation */ static function generate($item) { if ($item->is_album()) { if (!$cover = $item->album_cover()) { - return false; + // This album has no cover; there's nothing to generate. + return; } $input_file = $cover->file_path(); $input_item = $cover; @@ -127,7 +127,7 @@ class graphics_Core { $item->thumb_dirty = 0; $item->resize_dirty = 0; $item->save(); - return true; + return; } try { @@ -176,10 +176,8 @@ class graphics_Core { // @todo we should handle this better. Kohana::log("error", "Caught exception rebuilding image: {$item->title}\n" . $e->getMessage() . "\n" . $e->getTraceAsString()); - return false; + throw $e; } - - return true; } /** @@ -195,6 +193,8 @@ class graphics_Core { self::init_toolkit(); } + module::event("graphics_resize", $input_file, $output_file, $options); + if (@filesize($input_file) == 0) { throw new Exception("@todo EMPTY_INPUT_FILE"); } @@ -204,11 +204,16 @@ class graphics_Core { // Image would get upscaled; do nothing copy($input_file, $output_file); } else { - Image::factory($input_file) + $image = Image::factory($input_file) ->resize($options["width"], $options["height"], $options["master"]) - ->quality(module::get_var("gallery", "image_quality")) - ->save($output_file); + ->quality(module::get_var("gallery", "image_quality")); + if (graphics::can("sharpen")) { + $image->sharpen(module::get_var("gallery", "image_sharpen")); + } + $image->save($output_file); } + + module::event("graphics_resize_completed", $input_file, $output_file, $options); } /** @@ -223,10 +228,14 @@ class graphics_Core { self::init_toolkit(); } + module::event("graphics_rotate", $input_file, $output_file, $options); + Image::factory($input_file) ->quality(module::get_var("gallery", "image_quality")) ->rotate($options["degrees"]) ->save($output_file); + + module::event("graphics_rotate_completed", $input_file, $output_file, $options); } /** @@ -249,6 +258,8 @@ class graphics_Core { self::init_toolkit(); } + module::event("graphics_composite", $input_file, $output_file, $options); + list ($width, $height) = getimagesize($input_file); list ($w_width, $w_height) = getimagesize($options["file"]); @@ -276,6 +287,9 @@ class graphics_Core { ->composite($options["file"], $x, $y, $options["transparency"]) ->quality(module::get_var("gallery", "image_quality")) ->save($output_file); + + + module::event("graphics_composite_completed", $input_file, $output_file, $options); } /** @@ -312,9 +326,9 @@ class graphics_Core { t2("One of your photos is out of date. <a %attrs>Click here to fix it</a>", "%count of your photos are out of date. <a %attrs>Click here to fix them</a>", $count, - array("attrs" => sprintf( + array("attrs" => html::mark_clean(sprintf( 'href="%s" class="gDialogLink"', - url::site("admin/maintenance/start/gallery_task::rebuild_dirty_images?csrf=__CSRF__")))), + url::site("admin/maintenance/start/gallery_task::rebuild_dirty_images?csrf=__CSRF__"))))), "graphics_dirty"); } } @@ -326,15 +340,101 @@ class graphics_Core { * GraphicsMagick we return the path to the directory containing the appropriate binaries. */ static function detect_toolkits() { + $toolkits = new stdClass(); + + // GD is special, it doesn't use exec() $gd = function_exists("gd_info") ? gd_info() : array(); - $exec = function_exists("exec"); + $toolkits->gd->name = "GD"; if (!isset($gd["GD Version"])) { - $gd["GD Version"] = false; + $toolkits->gd->installed = false; + $toolkits->gd->error = t("GD is not installed"); + } else { + $toolkits->gd->installed = true; + $toolkits->gd->version = $gd["GD Version"]; + $toolkits->gd->rotate = function_exists("imagerotate"); + $toolkits->gd->sharpen = function_exists("imageconvolution"); + $toolkits->gd->binary = ""; + $toolkits->gd->dir = ""; + + if (!$toolkits->gd->rotate && !$toolkits->gd->sharpen) { + $toolkits->gd->error = + t("You have GD version %version, but it lacks image rotation and sharpening.", + array("version" => $gd["GD Version"])); + } else if (!$toolkits->gd->rotate) { + $toolkits->gd->error = + t("You have GD version %version, but it lacks image rotation.", + array("version" => $gd["GD Version"])); + } else if (!$toolkits->gd->sharpen) { + $toolkits->gd->error = + t("You have GD version %version, but it lacks image sharpening.", + array("version" => $gd["GD Version"])); + } + } + + if (!function_exists("exec")) { + $toolkits->imagemagick->installed = false; + $toolkits->imagemagick->error = t("ImageMagick requires the <b>exec</b> function"); + + $toolkits->graphicsmagick->installed = false; + $toolkits->graphicsmagick->error = t("GraphicsMagick requires the <b>exec</b> function"); + } else { + putenv("PATH=" . getenv("PATH") . ":/usr/local/bin:/opt/local/bin:/opt/bin"); + + // @todo: consider refactoring the two segments below into a loop since they are so + // similar. + + // ImageMagick + $path = exec("which convert"); + $toolkits->imagemagick->name = "ImageMagick"; + if ($path) { + if (@is_file($path)) { + preg_match('/Version: \S+ (\S+)/', `convert -v`, $matches); + $version = $matches[1]; + + $toolkits->imagemagick->installed = true; + $toolkits->imagemagick->version = $version; + $toolkits->imagemagick->binary = $path; + $toolkits->imagemagick->dir = dirname($path); + $toolkits->imagemagick->rotate = true; + $toolkits->imagemagick->sharpen = true; + } else { + $toolkits->imagemagick->installed = false; + $toolkits->imagemagick->error = + t("ImageMagick is installed, but PHP's open_basedir restriction " . + "prevents Gallery from using it."); + } + } else { + $toolkits->imagemagick->installed = false; + $toolkits->imagemagick->error = t("We could not locate ImageMagick on your system."); + } + + // GraphicsMagick + $path = exec("which gm"); + $toolkits->graphicsmagick->name = "GraphicsMagick"; + if ($path) { + if (@is_file($path)) { + preg_match('/\S+ (\S+)/', `gm version`, $matches); + $version = $matches[1]; + + $toolkits->graphicsmagick->installed = true; + $toolkits->graphicsmagick->version = $version; + $toolkits->graphicsmagick->binary = $path; + $toolkits->graphicsmagick->dir = dirname($path); + $toolkits->graphicsmagick->rotate = true; + $toolkits->graphicsmagick->sharpen = true; + } else { + $toolkits->graphicsmagick->installed = false; + $toolkits->graphicsmagick->error = + t("GraphicsMagick is installed, but PHP's open_basedir restriction " . + "prevents Gallery from using it."); + } + } else { + $toolkits->graphicsmagick->installed = false; + $toolkits->graphicsmagick->error = t("We could not locate GraphicsMagick on your system."); + } } - putenv("PATH=" . getenv("PATH") . ":/usr/local/bin:/opt/local/bin:/opt/bin"); - return array("gd" => $gd, - "imagemagick" => $exec ? dirname(exec("which convert")) : false, - "graphicsmagick" => $exec ? dirname(exec("which gm")) : false); + + return $toolkits; } /** @@ -344,16 +444,17 @@ class graphics_Core { // Detect a graphics toolkit $toolkits = graphics::detect_toolkits(); foreach (array("imagemagick", "graphicsmagick", "gd") as $tk) { - if ($toolkits[$tk]) { + if ($toolkits->$tk->installed) { module::set_var("gallery", "graphics_toolkit", $tk); - module::set_var("gallery", "graphics_toolkit_path", $tk == "gd" ? "" : $toolkits[$tk]); + module::set_var("gallery", "graphics_toolkit_path", $toolkits->$tk->dir); break; } } + if (!module::get_var("gallery", "graphics_toolkit")) { site_status::warning( t("Graphics toolkit missing! Please <a href=\"%url\">choose a toolkit</a>", - array("url" => url::site("admin/graphics"))), + array("url" => html::mark_clean(url::site("admin/graphics")))), "missing_graphics_toolkit"); } } @@ -385,14 +486,18 @@ class graphics_Core { /** * Verify that a specific graphics function is available with the active toolkit. - * @param string $func (eg rotate, resize) + * @param string $func (eg rotate, sharpen) * @return boolean */ static function can($func) { - if (module::get_var("gallery", "graphics_toolkit") == "gd" && - $func == "rotate" && - !function_exists("imagerotate")) { - return false; + if (module::get_var("gallery", "graphics_toolkit") == "gd") { + switch ($func) { + case "rotate": + return function_exists("imagerotate"); + + case "sharpen": + return function_exists("imageconvolution"); + } } return true; diff --git a/modules/gallery/helpers/item.php b/modules/gallery/helpers/item.php index f40b5c97..588c08d4 100644 --- a/modules/gallery/helpers/item.php +++ b/modules/gallery/helpers/item.php @@ -53,7 +53,7 @@ class item_Core { access::required("view", $parent); access::required("edit", $parent); - model_cache::clear("item", $parent->album_cover_item_id); + model_cache::clear(); $parent->album_cover_item_id = $item->is_album() ? $item->album_cover_item_id : $item->id; $parent->thumb_dirty = 1; $parent->save(); @@ -69,7 +69,7 @@ class item_Core { access::required("edit", $album); @unlink($album->thumb_path()); - model_cache::clear("item", $album->album_cover_item_id) ; + model_cache::clear(); $album->album_cover_item_id = null; $album->thumb_width = 0; $album->thumb_height = 0; @@ -90,21 +90,9 @@ class item_Core { } } - static function validate_no_name_conflict($input) { - $itemid = Input::instance()->post("item"); - if (is_array($itemid)) { - $itemid = $itemid[0]; - } - $item = ORM::factory("item") - ->in("id", $itemid) - ->find(); - if (Database::instance() - ->from("items") - ->where("parent_id", $item->parent_id) - ->where("id <>", $item->id) - ->where("name", $input->value) - ->count_records()) { - $input->add_error("conflict", 1); + static function validate_url_safe($input) { + if (preg_match("/[^A-Za-z0-9-_]/", $input->value)) { + $input->add_error("not_url_safe", 1); } } @@ -121,6 +109,16 @@ class item_Core { } /** + * Convert a filename into something we can use as a url component. + * @param string $filename + */ + static function convert_filename_to_slug($filename) { + $result = pathinfo($filename, PATHINFO_FILENAME); + $result = preg_replace("/[^A-Za-z0-9-_]+/", "-", $result); + return trim($result, "-"); + } + + /** * Display delete confirmation message and form * @param object $item * @return string form @@ -129,12 +127,72 @@ class item_Core { if (Input::instance()->get("page_type") == "album") { $page_type = "album"; } else { - $page_type = "item"; + $page_type = "photo"; } - $form = new Forge("quick/delete/$item->id?page_type=$page_type", "", "post", array("id" => "gConfirmDelete")); + $form = new Forge( + "quick/delete/$item->id?page_type=$page_type", "", "post", array("id" => "gConfirmDelete")); $form->hidden("_method")->value("put"); $group = $form->group("confirm_delete")->label(t("Confirm Deletion")); $group->submit("")->value(t("Delete")); return $form; } + + /** + * Get the next weight value + */ + static function get_max_weight() { + // Guard against an empty result when we create the first item. It's unfortunate that we + // have to check this every time. + // @todo: figure out a better way to bootstrap the weight. + $result = Database::instance() + ->select("weight")->from("items") + ->orderby("weight", "desc")->limit(1) + ->get()->current(); + return ($result ? $result->weight : 0) + 1; + } + + /** + * Add a set of restrictions to any following queries to restrict access only to items + * viewable by the active user. + * @chainable + */ + static function viewable($model) { + $view_restrictions = array(); + if (!user::active()->admin) { + foreach (user::group_ids() as $id) { + // Separate the first restriction from the rest to make it easier for us to formulate + // our where clause below + if (empty($view_restrictions)) { + $view_restrictions[0] = "items.view_$id"; + } else { + $view_restrictions[1]["items.view_$id"] = access::ALLOW; + } + } + } + switch (count($view_restrictions)) { + case 0: + break; + + case 1: + $model->where($view_restrictions[0], access::ALLOW); + break; + + default: + $model->open_paren(); + $model->where($view_restrictions[0], access::ALLOW); + $model->orwhere($view_restrictions[1]); + $model->close_paren(); + break; + } + + return $model; + } + + /** + * Return the root Item_Model + * @return Item_Model + */ + static function root() { + return model_cache::get("item", 1); + } }
\ No newline at end of file diff --git a/modules/gallery/helpers/l10n_client.php b/modules/gallery/helpers/l10n_client.php index 6d4da0eb..3460cc65 100644 --- a/modules/gallery/helpers/l10n_client.php +++ b/modules/gallery/helpers/l10n_client.php @@ -74,7 +74,7 @@ class l10n_client_Core { $request->locales = array(); $request->messages = new stdClass(); - $locales = locale::installed(); + $locales = locales::installed(); foreach ($locales as $locale => $locale_data) { $request->locales[] = $locale; } @@ -113,10 +113,6 @@ class l10n_client_Core { // [{key:<key_1>, translation: <JSON encoded translation>, rev:<rev>, locale:<locale>}, // {key:<key_2>, ...} // ] - $count = count($response); - $message[] = t2("Installed 1 new / updated translation message", - "Installed %count new / updated translation messages", $count); - foreach ($response as $message_data) { // @todo Better input validation if (empty($message_data->key) || empty($message_data->translation) || @@ -153,7 +149,6 @@ class l10n_client_Core { $entry->translation = $translation; $entry->save(); } - return $message; } static function submit_translations() { diff --git a/modules/gallery/helpers/locale.php b/modules/gallery/helpers/locales.php index 41b78834..16dda2d7 100644 --- a/modules/gallery/helpers/locale.php +++ b/modules/gallery/helpers/locales.php @@ -21,8 +21,9 @@ /** * This is the API for handling locales. */ -class locale_Core { +class locales_Core { private static $locales; + private static $language_subtag_to_locale; /** * Return the list of available locales. @@ -55,6 +56,9 @@ class locale_Core { : array_merge($locales, array($default)); module::set_var("gallery", "installed_locales", join("|", $locales)); + + // Clear the cache + self::$locales = null; } // @todo Might want to add a localizable language name as well. @@ -105,6 +109,16 @@ class locale_Core { $l["zh_TW"] = "繁體中文"; // Chinese (TW) asort($l, SORT_LOCALE_STRING); self::$locales = $l; + + // Language subtag to (default) locale mapping + foreach ($l as $locale => $name) { + list ($language) = explode("_", $locale . "_"); + // The first one mentioned is the default + if (!isset($d[$language])) { + $d[$language] = $locale; + } + } + self::$language_subtag_to_locale = $d; } static function display_name($locale=null) { @@ -121,4 +135,80 @@ class locale_Core { list ($language, $territory) = explode('_', $locale . "_"); return in_array($language, array("he", "fa", "ar")); } + + /** + * Returns the best match comparing the HTTP accept-language header + * with the installed locales. + * @todo replace this with request::accepts_language() when we upgrade to Kohana 2.4 + */ + static function locale_from_http_request() { + $http_accept_language = Input::instance()->server("HTTP_ACCEPT_LANGUAGE"); + if ($http_accept_language) { + // Parse the HTTP header and build a preference list + // Example value: "de,en-us;q=0.7,en-uk,fr-fr;q=0.2" + $locale_preferences = array(); + foreach (explode(",", $http_accept_language) as $code) { + list ($requested_locale, $qvalue) = explode(";", $code . ";"); + $requested_locale = trim($requested_locale); + $qvalue = trim($qvalue); + if (preg_match("/^([a-z]{2,3})(?:[_-]([a-zA-Z]{2}))?/", $requested_locale, $matches)) { + $requested_locale = strtolower($matches[1]); + if (!empty($matches[2])) { + $requested_locale .= "_" . strtoupper($matches[2]); + } + $requested_locale = trim(str_replace("-", "_", $requested_locale)); + if (!strlen($qvalue)) { + // If not specified, default to 1. + $qvalue = 1; + } else { + // qvalue is expected to be something like "q=0.7" + list ($ignored, $qvalue) = explode("=", $qvalue . "=="); + $qvalue = floatval($qvalue); + } + $locale_preferences[] = array($requested_locale, $qvalue); + } + } + + // Compare and score requested locales with installed ones + $scored_locales = array(); + foreach ($locale_preferences as $requested_value) { + $scored_locale_match = self::_locale_match_score($requested_value); + if ($scored_locale_match) { + $scored_locales[] = $scored_locale_match; + } + } + + usort($scored_locales, array("locales", "_compare_locale_by_qvalue")); + + $best_match = array_shift($scored_locales); + if ($best_match) { + return $best_match[0]; + } + } + + return null; + } + + static function _compare_locale_by_qvalue($a, $b) { + $a = $a[1]; + $b = $b[1]; + if ($a == $b) { + return 0; + } + return $a < $b ? 1 : -1; + } + + private static function _locale_match_score($requested_locale_and_qvalue) { + list ($requested_locale, $qvalue) = $requested_locale_and_qvalue; + $installed = self::installed(); + if (isset($installed[$requested_locale])) { + return $requested_locale_and_qvalue; + } + list ($language) = explode("_", $requested_locale . "_"); + if (isset(self::$language_subtag_to_locale[$language]) && + isset($installed[self::$language_subtag_to_locale[$language]])) { + return array(self::$language_subtag_to_locale[$language], $qvalue * 0.66); + } + return null; + } }
\ No newline at end of file diff --git a/modules/gallery/helpers/model_cache.php b/modules/gallery/helpers/model_cache.php index 2649fdbd..a3e09862 100644 --- a/modules/gallery/helpers/model_cache.php +++ b/modules/gallery/helpers/model_cache.php @@ -32,10 +32,8 @@ class model_cache_Core { return self::$cache->$model_name->$field_name->$id; } - static function clear($model_name, $id, $field_name="id") { - if (!empty(self::$cache->$model_name->$field_name->$id)) { - unset(self::$cache->$model_name->$field_name->$id); - } + static function clear() { + self::$cache = new stdClass(); } static function set($model) { diff --git a/modules/gallery/helpers/module.php b/modules/gallery/helpers/module.php index 0d483206..a3088c38 100644 --- a/modules/gallery/helpers/module.php +++ b/modules/gallery/helpers/module.php @@ -119,6 +119,8 @@ class module_Core { $installer_class = "{$module_name}_installer"; if (method_exists($installer_class, "install")) { call_user_func_array(array($installer_class, "install"), array()); + } else { + module::set_version($module_name, 1); } module::load_modules(); @@ -145,6 +147,13 @@ class module_Core { $installer_class = "{$module_name}_installer"; if (method_exists($installer_class, "upgrade")) { call_user_func_array(array($installer_class, "upgrade"), array($version_before)); + } else { + $available = module::available(); + if (isset($available->$module_name->code_version)) { + module::set_version($module_name, $available->$module_name->code_version); + } else { + throw new Exception("@todo UNKNOWN_MODULE"); + } } module::load_modules(); @@ -274,11 +283,9 @@ class module_Core { array_shift($args); $function = str_replace(".", "_", $name); - foreach (self::$modules as $module) { - if (!$module->active) { - continue; - } - + // @todo: consider calling gallery_event first, since for things menus we need it to do some + // setup + foreach (self::$active as $module) { $class = "{$module->name}_event"; if (method_exists($class, $function)) { call_user_func_array(array($class, $function), $args); diff --git a/modules/gallery/helpers/movie.php b/modules/gallery/helpers/movie.php index d62ead76..59bf5c19 100644 --- a/modules/gallery/helpers/movie.php +++ b/modules/gallery/helpers/movie.php @@ -31,10 +31,11 @@ class movie_Core { * @param string $name the filename to use for this photo in the album * @param integer $title the title of the new photo * @param string $description (optional) the longer description of this photo + * @param string $slug (optional) the url component for this photo * @return Item_Model */ static function create($parent, $filename, $name, $title, - $description=null, $owner_id=null) { + $description=null, $owner_id=null, $slug=null) { if (!$parent->loaded || !$parent->is_album()) { throw new Exception("@todo INVALID_PARENT"); } @@ -67,6 +68,10 @@ class movie_Core { $name .= "." . $pi["extension"]; } + if (empty($slug)) { + $slug = item::convert_filename_to_slug($name); + } + $movie = ORM::factory("item"); $movie->type = "movie"; $movie->title = $title; @@ -79,15 +84,21 @@ class movie_Core { $movie->thumb_dirty = 1; $movie->resize_dirty = 1; $movie->sort_column = "weight"; + $movie->slug = $slug; $movie->rand_key = ((float)mt_rand()) / (float)mt_getrandmax(); // Randomize the name if there's a conflict + // @todo Improve this. Random numbers are not user friendly while (ORM::factory("item") ->where("parent_id", $parent->id) + ->open_paren() ->where("name", $movie->name) + ->orwhere("slug", $movie->slug) + ->close_paren() ->find()->id) { - // @todo Improve this. Random numbers are not user friendly - $movie->name = rand() . "." . $pi["extension"]; + $rand = rand(); + $movie->name = "{$name}.$rand.{$pi['extension']}"; + $movie->slug = "{$slug}-$rand"; } // This saves the photo @@ -102,6 +113,8 @@ class movie_Core { copy($filename, $movie->file_path()); + // @todo: publish this from inside Item_Model::save() when we refactor to the point where + // there's only one save() happening here. module::event("item_created", $movie); // Build our thumbnail @@ -139,7 +152,7 @@ class movie_Core { $cmd = escapeshellcmd($ffmpeg) . " -i " . escapeshellarg($input_file) . " -an -ss 00:00:03 -an -r 1 -vframes 1" . - " -y -f mjpeg " . escapeshellarg($output_file); + " -y -f mjpeg " . escapeshellarg($output_file) . " 2>&1"; exec($cmd); } diff --git a/modules/gallery/helpers/p.php b/modules/gallery/helpers/p.php deleted file mode 100644 index 862c769b..00000000 --- a/modules/gallery/helpers/p.php +++ /dev/null @@ -1,39 +0,0 @@ -<?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 p_Core { - private static $_purifier = null; - static function clean($dirty_html) { - return html::specialchars($dirty_html); - } - - static function purify($dirty_html) { - if (empty(self::$_purifier)) { - require_once(dirname(__file__) . "/../lib/HTMLPurifier/HTMLPurifier.auto.php"); - $config = HTMLPurifier_Config::createDefault(); - foreach (Kohana::config('purifier') as $category => $key_value) { - foreach ($key_value as $key => $value) { - $config->set("$category.$key", $value); - } - } - self::$_purifier = new HTMLPurifier($config); - } - return self::$_purifier->purify($dirty_html); - } -} diff --git a/modules/gallery/helpers/photo.php b/modules/gallery/helpers/photo.php index e8a4f357..3d9fbe69 100644 --- a/modules/gallery/helpers/photo.php +++ b/modules/gallery/helpers/photo.php @@ -31,10 +31,11 @@ class photo_Core { * @param string $name the filename to use for this photo in the album * @param integer $title the title of the new photo * @param string $description (optional) the longer description of this photo + * @param string $slug (optional) the url component for this photo * @return Item_Model */ static function create($parent, $filename, $name, $title, - $description=null, $owner_id=null) { + $description=null, $owner_id=null, $slug=null) { if (!$parent->loaded || !$parent->is_album()) { throw new Exception("@todo INVALID_PARENT"); } @@ -66,6 +67,10 @@ class photo_Core { $name .= "." . $pi["extension"]; } + if (empty($slug)) { + $slug = item::convert_filename_to_slug($name); + } + $photo = ORM::factory("item"); $photo->type = "photo"; $photo->title = $title; @@ -78,15 +83,21 @@ class photo_Core { $photo->thumb_dirty = 1; $photo->resize_dirty = 1; $photo->sort_column = "weight"; + $photo->slug = $slug; $photo->rand_key = ((float)mt_rand()) / (float)mt_getrandmax(); - // Randomize the name if there's a conflict + // Randomize the name or slug if there's a conflict + // @todo Improve this. Random numbers are not user friendly while (ORM::factory("item") ->where("parent_id", $parent->id) + ->open_paren() ->where("name", $photo->name) + ->orwhere("slug", $photo->slug) + ->close_paren() ->find()->id) { - // @todo Improve this. Random numbers are not user friendly - $photo->name = rand() . "." . $pi["extension"]; + $rand = rand(); + $photo->name = "{$name}.$rand.{$pi['extension']}"; + $photo->slug = "{$slug}-$rand"; } // This saves the photo @@ -105,10 +116,18 @@ class photo_Core { copy($filename, $photo->file_path()); + // @todo: publish this from inside Item_Model::save() when we refactor to the point where + // there's only one save() happening here. module::event("item_created", $photo); - // Build our thumbnail/resizes - graphics::generate($photo); + // Build our thumbnail/resizes. If we fail to build thumbnail/resize we assume that the image + // is bad in some way and discard it. + try { + graphics::generate($photo); + } catch (Exception $e) { + $photo->delete(); + throw $e; + } // If the parent has no cover item, make this it. if (access::can("edit", $parent) && $parent->album_cover_item_id == null) { @@ -121,10 +140,15 @@ class photo_Core { static function get_add_form($parent) { $form = new Forge("albums/{$parent->id}", "", "post", array("id" => "gAddPhotoForm")); $group = $form->group("add_photo")->label( - t("Add Photo to %album_title", array("album_title" =>$parent->title))); + t("Add Photo to %album_title", array("album_title" => $parent->title))); $group->input("title")->label(t("Title")); $group->textarea("description")->label(t("Description")); $group->input("name")->label(t("Filename")); + $group->input("slug")->label(t("Internet Address"))->value($photo->slug) + ->callback("item::validate_url_safe") + ->error_messages( + "not_url_safe", + t("The internet address should contain only letters, numbers, hyphens and underscores")); $group->upload("file")->label(t("File"))->rules("required|allow[jpg,png,gif,flv,mp4]"); $group->hidden("type")->value("photo"); $group->submit("")->value(t("Upload")); @@ -135,16 +159,26 @@ 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_photo")->label(t("Edit Photo")); + $group = $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) - ->error_messages("conflict", t("There is already a file with this name")) + ->error_messages("name_conflict", t("There is already a photo or album with this name")) ->callback("item::validate_no_slashes") ->error_messages("no_slashes", t("The photo name can't contain a \"/\"")) ->callback("item::validate_no_trailing_period") ->error_messages("no_trailing_period", t("The photo name can't end in \".\"")); + $group->input("slug")->label(t("Internet Address"))->value($photo->slug) + ->callback("item::validate_url_safe") + ->error_messages( + "slug_conflict", t("There is already a photo or album with this internet address")) + ->error_messages( + "not_url_safe", + t("The internet address should contain only letters, numbers, hyphens and underscores")); + + module::event("item_edit_form", $photo, $form); + $group = $form->group("buttons")->label(""); $group->submit("")->value(t("Modify")); $form->add_rules_from(ORM::factory("item")); return $form; diff --git a/modules/gallery/helpers/task.php b/modules/gallery/helpers/task.php index 6a9f63c2..9fa04305 100644 --- a/modules/gallery/helpers/task.php +++ b/modules/gallery/helpers/task.php @@ -84,10 +84,11 @@ class task_Core { } $task->save(); } catch (Exception $e) { + Kohana::log("error", $e->__toString()); $task->log($e->__toString()); $task->state = "error"; $task->done = true; - $task->status = $e->getMessage(); + $task->status = substr($e->getMessage(), 0, 255); $task->save(); } diff --git a/modules/gallery/js/albums_form_add.js b/modules/gallery/js/albums_form_add.js index 06a364f3..43166f27 100644 --- a/modules/gallery/js/albums_form_add.js +++ b/modules/gallery/js/albums_form_add.js @@ -1,12 +1,23 @@ $("#gAddAlbumForm input[name=title]").change( function() { $("#gAddAlbumForm input[name=name]").attr( - "value", $("#gAddAlbumForm input[name=title]").attr("value"). - replace(/\s+/g, "_").replace(/\.+$/, "")); + "value", $("#gAddAlbumForm input[name=title]").attr("value") + .replace(/[\s\/]+/g, "-").replace(/\.+$/, "")); + $("#gAddAlbumForm input[name=slug]").attr( + "value", $("#gAddAlbumForm input[name=title]").attr("value") + .replace(/[^A-Za-z0-9-_]+/g, "-") + .replace(/^-+/, "") + .replace(/-+$/, "")); }); $("#gAddAlbumForm input[name=title]").keyup( function() { $("#gAddAlbumForm input[name=name]").attr( - "value", $("#gAddAlbumForm input[name=title]").attr("value"). - replace(/\s+/g, "_").replace(/\.+$/, "")); + "value", $("#gAddAlbumForm input[name=title]").attr("value") + .replace(/[\s\/]+/g, "-") + .replace(/\.+$/, "")); + $("#gAddAlbumForm input[name=slug]").attr( + "value", $("#gAddAlbumForm input[name=title]").attr("value") + .replace(/[^A-Za-z0-9-_]+/g, "-") + .replace(/^-+/, "") + .replace(/-+$/, "")); }); diff --git a/modules/gallery/js/l10n_client.js b/modules/gallery/js/l10n_client.js index f5be5058..35986e5a 100644 --- a/modules/gallery/js/l10n_client.js +++ b/modules/gallery/js/l10n_client.js @@ -58,7 +58,8 @@ jQuery.extend(Gallery, { case 1: $('#l10n-client-string-select, #l10n-client-string-editor, #l10n-client .labels .label').show(); $('#l10n-client').height('22em').removeClass('hidden'); - $('#l10n-client-toggler').text(MSG_CLOSE_X); + //$('#l10n-client').slideUp(); + $('#gMinimizeL10n').text("_"); /* * This CSS clashes with Gallery's CSS, probably due to * YUI's grid / floats. @@ -72,7 +73,7 @@ jQuery.extend(Gallery, { $('#l10n-client-string-select, #l10n-client-string-editor, #l10n-client .labels .label').hide(); $('#l10n-client').height('2em').addClass('hidden'); // TODO: Localize this message - $('#l10n-client-toggler').text(MSG_TRANSLATE_TEXT); + $('#gMinimizeL10n').text(MSG_TRANSLATE_TEXT); /* if(!$.browser.msie) { $('body').css('border-bottom', '0px'); @@ -197,13 +198,26 @@ Gallery.behaviors.l10nClient = function(context) { }); // When l10n_client window is clicked, toggle based on current state. - $('#l10n-client-toggler').click(function() { + $('#gMinimizeL10n').click(function() { if($('#l10n-client').is('.hidden')) { Gallery.l10nClient.toggle(1); } else { Gallery.l10nClient.toggle(0); } }); + + // Close the l10n client using an AJAX call and refreshing the page + $('#gCloseL10n').click(function(event) { + $.ajax({ + type: "GET", + url: toggle_l10n_mode_url, + data: "csrf=" + csrf, + success: function() { + window.location.reload(true); + } + }); + event.preventDefault(); + }); // Register keybindings using jQuery hotkeys // TODO: Either remove hotkeys code or add query.hotkeys.js. diff --git a/modules/gallery/js/quick.js b/modules/gallery/js/quick.js deleted file mode 100644 index 3ac97f8e..00000000 --- a/modules/gallery/js/quick.js +++ /dev/null @@ -1,82 +0,0 @@ -$(document).ready(function() { - if ($("#gAlbumGrid").length) { - // @todo Add quick edit pane for album (meta, move, permissions, delete) - $(".gItem").hover(show_quick, function() {}); - } - if ($("#gPhoto").length) { - $("#gPhoto").hover(show_quick, function() {}); - } -}); - -var show_quick = function() { - var cont = $(this); - var quick = $(this).find(".gQuick"); - var img = cont.find(".gThumbnail,.gResize"); - $("#gQuickPane").remove(); - cont.append("<div id=\"gQuickPane\"></div>"); - $("#gQuickPane").hide(); - cont.hover(function() {}, hide_quick); - $.get( - quick.attr("href"), - {}, - function(data, textStatus) { - $("#gQuickPane").html(data).slideDown("fast"); - $(".ui-state-default").hover( - function() { - $(this).addClass("ui-state-hover"); - }, - function() { - $(this).removeClass("ui-state-hover"); - } - ); - $("#gQuickPane a:not(.options)").click(function(e) { - e.preventDefault(); - quick_do(cont, $(this), img); - }); - $("#gQuickPane a.options").click(function(e) { - e.preventDefault(); - $("#gQuickPaneOptions").slideToggle("fast"); - }); - } - ); -}; - -var quick_do = function(cont, pane, img) { - if (pane.hasClass("ui-state-disabled")) { - return false; - } - if (pane.hasClass("gDialogLink")) { - openDialog(pane); - } else { - img.css("opacity", "0.1"); - cont.addClass("gLoadingLarge"); - $.ajax({ - type: "GET", - url: pane.attr("href"), - dataType: "json", - success: function(data) { - img.css("opacity", "1"); - cont.removeClass("gLoadingLarge"); - if (data.src) { - img.attr("width", data.width); - img.attr("height", data.height); - img.attr("src", data.src); - if (data.height > data.width) { - img.css("margin-top", -32); - } else { - img.css("margin-top", 0); - } - } else if (data.location) { - window.location = data.location; - } else if (data.reload) { - window.location.reload(); - } - } - }); - } - return false; -}; - -var hide_quick = function() { - $("#gQuickPane").remove(); -}; diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier.auto.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier.auto.php deleted file mode 100644 index 2e2c685e..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier.auto.php +++ /dev/null @@ -1,11 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * This is a stub include that automatically configures the include path. - */ - -set_include_path(dirname(__FILE__) . PATH_SEPARATOR . get_include_path() ); -require_once 'HTMLPurifier/Bootstrap.php'; -require_once 'HTMLPurifier.autoload.php'; - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier.autoload.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier.autoload.php deleted file mode 100644 index a9f1cc31..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier.autoload.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * @file - * Convenience file that registers autoload handler for HTML Purifier. - */ - -if (function_exists('spl_autoload_register') && function_exists('spl_autoload_unregister')) { - // We need unregister for our pre-registering functionality - HTMLPurifier_Bootstrap::registerAutoload(); - if (function_exists('__autoload')) { - // Be polite and ensure that userland autoload gets retained - spl_autoload_register('__autoload'); - } -} elseif (!function_exists('__autoload')) { - function __autoload($class) { - return HTMLPurifier_Bootstrap::autoload($class); - } -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier.func.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier.func.php deleted file mode 100644 index 141d7f5f..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier.func.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * @file - * Defines a function wrapper for HTML Purifier for quick use. - * @note ''HTMLPurifier()'' is NOT the same as ''new HTMLPurifier()'' - */ - -/** - * Purify HTML. - * @param $html String HTML to purify - * @param $config Configuration to use, can be any value accepted by - * HTMLPurifier_Config::create() - */ -function HTMLPurifier($html, $config = null) { - static $purifier = false; - if (!$purifier) { - $purifier = new HTMLPurifier(); - } - return $purifier->purify($html, $config); -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier.includes.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier.includes.php deleted file mode 100644 index e57f2ab3..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier.includes.php +++ /dev/null @@ -1,208 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * @file - * This file was auto-generated by generate-includes.php and includes all of - * the core files required by HTML Purifier. Use this if performance is a - * primary concern and you are using an opcode cache. PLEASE DO NOT EDIT THIS - * FILE, changes will be overwritten the next time the script is run. - * - * @version 4.0.0 - * - * @warning - * You must *not* include any other HTML Purifier files before this file, - * because 'require' not 'require_once' is used. - * - * @warning - * This file requires that the include path contains the HTML Purifier - * library directory; this is not auto-set. - */ - -require 'HTMLPurifier.php'; -require 'HTMLPurifier/AttrCollections.php'; -require 'HTMLPurifier/AttrDef.php'; -require 'HTMLPurifier/AttrTransform.php'; -require 'HTMLPurifier/AttrTypes.php'; -require 'HTMLPurifier/AttrValidator.php'; -require 'HTMLPurifier/Bootstrap.php'; -require 'HTMLPurifier/Definition.php'; -require 'HTMLPurifier/CSSDefinition.php'; -require 'HTMLPurifier/ChildDef.php'; -require 'HTMLPurifier/Config.php'; -require 'HTMLPurifier/ConfigSchema.php'; -require 'HTMLPurifier/ContentSets.php'; -require 'HTMLPurifier/Context.php'; -require 'HTMLPurifier/DefinitionCache.php'; -require 'HTMLPurifier/DefinitionCacheFactory.php'; -require 'HTMLPurifier/Doctype.php'; -require 'HTMLPurifier/DoctypeRegistry.php'; -require 'HTMLPurifier/ElementDef.php'; -require 'HTMLPurifier/Encoder.php'; -require 'HTMLPurifier/EntityLookup.php'; -require 'HTMLPurifier/EntityParser.php'; -require 'HTMLPurifier/ErrorCollector.php'; -require 'HTMLPurifier/ErrorStruct.php'; -require 'HTMLPurifier/Exception.php'; -require 'HTMLPurifier/Filter.php'; -require 'HTMLPurifier/Generator.php'; -require 'HTMLPurifier/HTMLDefinition.php'; -require 'HTMLPurifier/HTMLModule.php'; -require 'HTMLPurifier/HTMLModuleManager.php'; -require 'HTMLPurifier/IDAccumulator.php'; -require 'HTMLPurifier/Injector.php'; -require 'HTMLPurifier/Language.php'; -require 'HTMLPurifier/LanguageFactory.php'; -require 'HTMLPurifier/Length.php'; -require 'HTMLPurifier/Lexer.php'; -require 'HTMLPurifier/PercentEncoder.php'; -require 'HTMLPurifier/PropertyList.php'; -require 'HTMLPurifier/PropertyListIterator.php'; -require 'HTMLPurifier/Strategy.php'; -require 'HTMLPurifier/StringHash.php'; -require 'HTMLPurifier/StringHashParser.php'; -require 'HTMLPurifier/TagTransform.php'; -require 'HTMLPurifier/Token.php'; -require 'HTMLPurifier/TokenFactory.php'; -require 'HTMLPurifier/URI.php'; -require 'HTMLPurifier/URIDefinition.php'; -require 'HTMLPurifier/URIFilter.php'; -require 'HTMLPurifier/URIParser.php'; -require 'HTMLPurifier/URIScheme.php'; -require 'HTMLPurifier/URISchemeRegistry.php'; -require 'HTMLPurifier/UnitConverter.php'; -require 'HTMLPurifier/VarParser.php'; -require 'HTMLPurifier/VarParserException.php'; -require 'HTMLPurifier/AttrDef/CSS.php'; -require 'HTMLPurifier/AttrDef/Enum.php'; -require 'HTMLPurifier/AttrDef/Integer.php'; -require 'HTMLPurifier/AttrDef/Lang.php'; -require 'HTMLPurifier/AttrDef/Switch.php'; -require 'HTMLPurifier/AttrDef/Text.php'; -require 'HTMLPurifier/AttrDef/URI.php'; -require 'HTMLPurifier/AttrDef/CSS/Number.php'; -require 'HTMLPurifier/AttrDef/CSS/AlphaValue.php'; -require 'HTMLPurifier/AttrDef/CSS/Background.php'; -require 'HTMLPurifier/AttrDef/CSS/BackgroundPosition.php'; -require 'HTMLPurifier/AttrDef/CSS/Border.php'; -require 'HTMLPurifier/AttrDef/CSS/Color.php'; -require 'HTMLPurifier/AttrDef/CSS/Composite.php'; -require 'HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php'; -require 'HTMLPurifier/AttrDef/CSS/Filter.php'; -require 'HTMLPurifier/AttrDef/CSS/Font.php'; -require 'HTMLPurifier/AttrDef/CSS/FontFamily.php'; -require 'HTMLPurifier/AttrDef/CSS/ImportantDecorator.php'; -require 'HTMLPurifier/AttrDef/CSS/Length.php'; -require 'HTMLPurifier/AttrDef/CSS/ListStyle.php'; -require 'HTMLPurifier/AttrDef/CSS/Multiple.php'; -require 'HTMLPurifier/AttrDef/CSS/Percentage.php'; -require 'HTMLPurifier/AttrDef/CSS/TextDecoration.php'; -require 'HTMLPurifier/AttrDef/CSS/URI.php'; -require 'HTMLPurifier/AttrDef/HTML/Bool.php'; -require 'HTMLPurifier/AttrDef/HTML/Nmtokens.php'; -require 'HTMLPurifier/AttrDef/HTML/Class.php'; -require 'HTMLPurifier/AttrDef/HTML/Color.php'; -require 'HTMLPurifier/AttrDef/HTML/FrameTarget.php'; -require 'HTMLPurifier/AttrDef/HTML/ID.php'; -require 'HTMLPurifier/AttrDef/HTML/Pixels.php'; -require 'HTMLPurifier/AttrDef/HTML/Length.php'; -require 'HTMLPurifier/AttrDef/HTML/LinkTypes.php'; -require 'HTMLPurifier/AttrDef/HTML/MultiLength.php'; -require 'HTMLPurifier/AttrDef/URI/Email.php'; -require 'HTMLPurifier/AttrDef/URI/Host.php'; -require 'HTMLPurifier/AttrDef/URI/IPv4.php'; -require 'HTMLPurifier/AttrDef/URI/IPv6.php'; -require 'HTMLPurifier/AttrDef/URI/Email/SimpleCheck.php'; -require 'HTMLPurifier/AttrTransform/Background.php'; -require 'HTMLPurifier/AttrTransform/BdoDir.php'; -require 'HTMLPurifier/AttrTransform/BgColor.php'; -require 'HTMLPurifier/AttrTransform/BoolToCSS.php'; -require 'HTMLPurifier/AttrTransform/Border.php'; -require 'HTMLPurifier/AttrTransform/EnumToCSS.php'; -require 'HTMLPurifier/AttrTransform/ImgRequired.php'; -require 'HTMLPurifier/AttrTransform/ImgSpace.php'; -require 'HTMLPurifier/AttrTransform/Input.php'; -require 'HTMLPurifier/AttrTransform/Lang.php'; -require 'HTMLPurifier/AttrTransform/Length.php'; -require 'HTMLPurifier/AttrTransform/Name.php'; -require 'HTMLPurifier/AttrTransform/NameSync.php'; -require 'HTMLPurifier/AttrTransform/SafeEmbed.php'; -require 'HTMLPurifier/AttrTransform/SafeObject.php'; -require 'HTMLPurifier/AttrTransform/SafeParam.php'; -require 'HTMLPurifier/AttrTransform/ScriptRequired.php'; -require 'HTMLPurifier/AttrTransform/Textarea.php'; -require 'HTMLPurifier/ChildDef/Chameleon.php'; -require 'HTMLPurifier/ChildDef/Custom.php'; -require 'HTMLPurifier/ChildDef/Empty.php'; -require 'HTMLPurifier/ChildDef/Required.php'; -require 'HTMLPurifier/ChildDef/Optional.php'; -require 'HTMLPurifier/ChildDef/StrictBlockquote.php'; -require 'HTMLPurifier/ChildDef/Table.php'; -require 'HTMLPurifier/DefinitionCache/Decorator.php'; -require 'HTMLPurifier/DefinitionCache/Null.php'; -require 'HTMLPurifier/DefinitionCache/Serializer.php'; -require 'HTMLPurifier/DefinitionCache/Decorator/Cleanup.php'; -require 'HTMLPurifier/DefinitionCache/Decorator/Memory.php'; -require 'HTMLPurifier/HTMLModule/Bdo.php'; -require 'HTMLPurifier/HTMLModule/CommonAttributes.php'; -require 'HTMLPurifier/HTMLModule/Edit.php'; -require 'HTMLPurifier/HTMLModule/Forms.php'; -require 'HTMLPurifier/HTMLModule/Hypertext.php'; -require 'HTMLPurifier/HTMLModule/Image.php'; -require 'HTMLPurifier/HTMLModule/Legacy.php'; -require 'HTMLPurifier/HTMLModule/List.php'; -require 'HTMLPurifier/HTMLModule/Name.php'; -require 'HTMLPurifier/HTMLModule/NonXMLCommonAttributes.php'; -require 'HTMLPurifier/HTMLModule/Object.php'; -require 'HTMLPurifier/HTMLModule/Presentation.php'; -require 'HTMLPurifier/HTMLModule/Proprietary.php'; -require 'HTMLPurifier/HTMLModule/Ruby.php'; -require 'HTMLPurifier/HTMLModule/SafeEmbed.php'; -require 'HTMLPurifier/HTMLModule/SafeObject.php'; -require 'HTMLPurifier/HTMLModule/Scripting.php'; -require 'HTMLPurifier/HTMLModule/StyleAttribute.php'; -require 'HTMLPurifier/HTMLModule/Tables.php'; -require 'HTMLPurifier/HTMLModule/Target.php'; -require 'HTMLPurifier/HTMLModule/Text.php'; -require 'HTMLPurifier/HTMLModule/Tidy.php'; -require 'HTMLPurifier/HTMLModule/XMLCommonAttributes.php'; -require 'HTMLPurifier/HTMLModule/Tidy/Name.php'; -require 'HTMLPurifier/HTMLModule/Tidy/Proprietary.php'; -require 'HTMLPurifier/HTMLModule/Tidy/XHTMLAndHTML4.php'; -require 'HTMLPurifier/HTMLModule/Tidy/Strict.php'; -require 'HTMLPurifier/HTMLModule/Tidy/Transitional.php'; -require 'HTMLPurifier/HTMLModule/Tidy/XHTML.php'; -require 'HTMLPurifier/Injector/AutoParagraph.php'; -require 'HTMLPurifier/Injector/DisplayLinkURI.php'; -require 'HTMLPurifier/Injector/Linkify.php'; -require 'HTMLPurifier/Injector/PurifierLinkify.php'; -require 'HTMLPurifier/Injector/RemoveEmpty.php'; -require 'HTMLPurifier/Injector/SafeObject.php'; -require 'HTMLPurifier/Lexer/DOMLex.php'; -require 'HTMLPurifier/Lexer/DirectLex.php'; -require 'HTMLPurifier/Strategy/Composite.php'; -require 'HTMLPurifier/Strategy/Core.php'; -require 'HTMLPurifier/Strategy/FixNesting.php'; -require 'HTMLPurifier/Strategy/MakeWellFormed.php'; -require 'HTMLPurifier/Strategy/RemoveForeignElements.php'; -require 'HTMLPurifier/Strategy/ValidateAttributes.php'; -require 'HTMLPurifier/TagTransform/Font.php'; -require 'HTMLPurifier/TagTransform/Simple.php'; -require 'HTMLPurifier/Token/Comment.php'; -require 'HTMLPurifier/Token/Tag.php'; -require 'HTMLPurifier/Token/Empty.php'; -require 'HTMLPurifier/Token/End.php'; -require 'HTMLPurifier/Token/Start.php'; -require 'HTMLPurifier/Token/Text.php'; -require 'HTMLPurifier/URIFilter/DisableExternal.php'; -require 'HTMLPurifier/URIFilter/DisableExternalResources.php'; -require 'HTMLPurifier/URIFilter/HostBlacklist.php'; -require 'HTMLPurifier/URIFilter/MakeAbsolute.php'; -require 'HTMLPurifier/URIFilter/Munge.php'; -require 'HTMLPurifier/URIScheme/ftp.php'; -require 'HTMLPurifier/URIScheme/http.php'; -require 'HTMLPurifier/URIScheme/https.php'; -require 'HTMLPurifier/URIScheme/mailto.php'; -require 'HTMLPurifier/URIScheme/news.php'; -require 'HTMLPurifier/URIScheme/nntp.php'; -require 'HTMLPurifier/VarParser/Flexible.php'; -require 'HTMLPurifier/VarParser/Native.php'; diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier.kses.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier.kses.php deleted file mode 100644 index 4e404879..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier.kses.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * @file - * Emulation layer for code that used kses(), substituting in HTML Purifier. - */ - -require_once dirname(__FILE__) . '/HTMLPurifier.auto.php'; - -function kses($string, $allowed_html, $allowed_protocols = null) { - $config = HTMLPurifier_Config::createDefault(); - $allowed_elements = array(); - $allowed_attributes = array(); - foreach ($allowed_html as $element => $attributes) { - $allowed_elements[$element] = true; - foreach ($attributes as $attribute => $x) { - $allowed_attributes["$element.$attribute"] = true; - } - } - $config->set('HTML.AllowedElements', $allowed_elements); - $config->set('HTML.AllowedAttributes', $allowed_attributes); - $allowed_schemes = array(); - if ($allowed_protocols !== null) { - $config->set('URI.AllowedSchemes', $allowed_protocols); - } - $purifier = new HTMLPurifier($config); - return $purifier->purify($string); -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier.path.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier.path.php deleted file mode 100644 index 8a38372e..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier.path.php +++ /dev/null @@ -1,11 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * @file - * Convenience stub file that adds HTML Purifier's library file to the path - * without any other side-effects. - */ - -set_include_path(dirname(__FILE__) . PATH_SEPARATOR . get_include_path() ); - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier.php deleted file mode 100644 index 71e90632..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier.php +++ /dev/null @@ -1,237 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/*! @mainpage - * - * HTML Purifier is an HTML filter that will take an arbitrary snippet of - * HTML and rigorously test, validate and filter it into a version that - * is safe for output onto webpages. It achieves this by: - * - * -# Lexing (parsing into tokens) the document, - * -# Executing various strategies on the tokens: - * -# Removing all elements not in the whitelist, - * -# Making the tokens well-formed, - * -# Fixing the nesting of the nodes, and - * -# Validating attributes of the nodes; and - * -# Generating HTML from the purified tokens. - * - * However, most users will only need to interface with the HTMLPurifier - * and HTMLPurifier_Config. - */ - -/* - HTML Purifier 4.0.0 - Standards Compliant HTML Filtering - Copyright (C) 2006-2008 Edward Z. Yang - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/** - * Facade that coordinates HTML Purifier's subsystems in order to purify HTML. - * - * @note There are several points in which configuration can be specified - * for HTML Purifier. The precedence of these (from lowest to - * highest) is as follows: - * -# Instance: new HTMLPurifier($config) - * -# Invocation: purify($html, $config) - * These configurations are entirely independent of each other and - * are *not* merged (this behavior may change in the future). - * - * @todo We need an easier way to inject strategies using the configuration - * object. - */ -class HTMLPurifier -{ - - /** Version of HTML Purifier */ - public $version = '4.0.0'; - - /** Constant with version of HTML Purifier */ - const VERSION = '4.0.0'; - - /** Global configuration object */ - public $config; - - /** Array of extra HTMLPurifier_Filter objects to run on HTML, for backwards compatibility */ - private $filters = array(); - - /** Single instance of HTML Purifier */ - private static $instance; - - protected $strategy, $generator; - - /** - * Resultant HTMLPurifier_Context of last run purification. Is an array - * of contexts if the last called method was purifyArray(). - */ - public $context; - - /** - * Initializes the purifier. - * @param $config Optional HTMLPurifier_Config object for all instances of - * the purifier, if omitted, a default configuration is - * supplied (which can be overridden on a per-use basis). - * The parameter can also be any type that - * HTMLPurifier_Config::create() supports. - */ - public function __construct($config = null) { - - $this->config = HTMLPurifier_Config::create($config); - - $this->strategy = new HTMLPurifier_Strategy_Core(); - - } - - /** - * Adds a filter to process the output. First come first serve - * @param $filter HTMLPurifier_Filter object - */ - public function addFilter($filter) { - trigger_error('HTMLPurifier->addFilter() is deprecated, use configuration directives in the Filter namespace or Filter.Custom', E_USER_WARNING); - $this->filters[] = $filter; - } - - /** - * Filters an HTML snippet/document to be XSS-free and standards-compliant. - * - * @param $html String of HTML to purify - * @param $config HTMLPurifier_Config object for this operation, if omitted, - * defaults to the config object specified during this - * object's construction. The parameter can also be any type - * that HTMLPurifier_Config::create() supports. - * @return Purified HTML - */ - public function purify($html, $config = null) { - - // :TODO: make the config merge in, instead of replace - $config = $config ? HTMLPurifier_Config::create($config) : $this->config; - - // implementation is partially environment dependant, partially - // configuration dependant - $lexer = HTMLPurifier_Lexer::create($config); - - $context = new HTMLPurifier_Context(); - - // setup HTML generator - $this->generator = new HTMLPurifier_Generator($config, $context); - $context->register('Generator', $this->generator); - - // set up global context variables - if ($config->get('Core.CollectErrors')) { - // may get moved out if other facilities use it - $language_factory = HTMLPurifier_LanguageFactory::instance(); - $language = $language_factory->create($config, $context); - $context->register('Locale', $language); - - $error_collector = new HTMLPurifier_ErrorCollector($context); - $context->register('ErrorCollector', $error_collector); - } - - // setup id_accumulator context, necessary due to the fact that - // AttrValidator can be called from many places - $id_accumulator = HTMLPurifier_IDAccumulator::build($config, $context); - $context->register('IDAccumulator', $id_accumulator); - - $html = HTMLPurifier_Encoder::convertToUTF8($html, $config, $context); - - // setup filters - $filter_flags = $config->getBatch('Filter'); - $custom_filters = $filter_flags['Custom']; - unset($filter_flags['Custom']); - $filters = array(); - foreach ($filter_flags as $filter => $flag) { - if (!$flag) continue; - if (strpos($filter, '.') !== false) continue; - $class = "HTMLPurifier_Filter_$filter"; - $filters[] = new $class; - } - foreach ($custom_filters as $filter) { - // maybe "HTMLPurifier_Filter_$filter", but be consistent with AutoFormat - $filters[] = $filter; - } - $filters = array_merge($filters, $this->filters); - // maybe prepare(), but later - - for ($i = 0, $filter_size = count($filters); $i < $filter_size; $i++) { - $html = $filters[$i]->preFilter($html, $config, $context); - } - - // purified HTML - $html = - $this->generator->generateFromTokens( - // list of tokens - $this->strategy->execute( - // list of un-purified tokens - $lexer->tokenizeHTML( - // un-purified HTML - $html, $config, $context - ), - $config, $context - ) - ); - - for ($i = $filter_size - 1; $i >= 0; $i--) { - $html = $filters[$i]->postFilter($html, $config, $context); - } - - $html = HTMLPurifier_Encoder::convertFromUTF8($html, $config, $context); - $this->context =& $context; - return $html; - } - - /** - * Filters an array of HTML snippets - * @param $config Optional HTMLPurifier_Config object for this operation. - * See HTMLPurifier::purify() for more details. - * @return Array of purified HTML - */ - public function purifyArray($array_of_html, $config = null) { - $context_array = array(); - foreach ($array_of_html as $key => $html) { - $array_of_html[$key] = $this->purify($html, $config); - $context_array[$key] = $this->context; - } - $this->context = $context_array; - return $array_of_html; - } - - /** - * Singleton for enforcing just one HTML Purifier in your system - * @param $prototype Optional prototype HTMLPurifier instance to - * overload singleton with, or HTMLPurifier_Config - * instance to configure the generated version with. - */ - public static function instance($prototype = null) { - if (!self::$instance || $prototype) { - if ($prototype instanceof HTMLPurifier) { - self::$instance = $prototype; - } elseif ($prototype) { - self::$instance = new HTMLPurifier($prototype); - } else { - self::$instance = new HTMLPurifier(); - } - } - return self::$instance; - } - - /** - * @note Backwards compatibility, see instance() - */ - public static function getInstance($prototype = null) { - return HTMLPurifier::instance($prototype); - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier.safe-includes.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier.safe-includes.php deleted file mode 100644 index 5f0e1d8f..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier.safe-includes.php +++ /dev/null @@ -1,202 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * @file - * This file was auto-generated by generate-includes.php and includes all of - * the core files required by HTML Purifier. This is a convenience stub that - * includes all files using dirname(__FILE__) and require_once. PLEASE DO NOT - * EDIT THIS FILE, changes will be overwritten the next time the script is run. - * - * Changes to include_path are not necessary. - */ - -$__dir = dirname(__FILE__); - -require_once $__dir . '/HTMLPurifier.php'; -require_once $__dir . '/HTMLPurifier/AttrCollections.php'; -require_once $__dir . '/HTMLPurifier/AttrDef.php'; -require_once $__dir . '/HTMLPurifier/AttrTransform.php'; -require_once $__dir . '/HTMLPurifier/AttrTypes.php'; -require_once $__dir . '/HTMLPurifier/AttrValidator.php'; -require_once $__dir . '/HTMLPurifier/Bootstrap.php'; -require_once $__dir . '/HTMLPurifier/Definition.php'; -require_once $__dir . '/HTMLPurifier/CSSDefinition.php'; -require_once $__dir . '/HTMLPurifier/ChildDef.php'; -require_once $__dir . '/HTMLPurifier/Config.php'; -require_once $__dir . '/HTMLPurifier/ConfigSchema.php'; -require_once $__dir . '/HTMLPurifier/ContentSets.php'; -require_once $__dir . '/HTMLPurifier/Context.php'; -require_once $__dir . '/HTMLPurifier/DefinitionCache.php'; -require_once $__dir . '/HTMLPurifier/DefinitionCacheFactory.php'; -require_once $__dir . '/HTMLPurifier/Doctype.php'; -require_once $__dir . '/HTMLPurifier/DoctypeRegistry.php'; -require_once $__dir . '/HTMLPurifier/ElementDef.php'; -require_once $__dir . '/HTMLPurifier/Encoder.php'; -require_once $__dir . '/HTMLPurifier/EntityLookup.php'; -require_once $__dir . '/HTMLPurifier/EntityParser.php'; -require_once $__dir . '/HTMLPurifier/ErrorCollector.php'; -require_once $__dir . '/HTMLPurifier/ErrorStruct.php'; -require_once $__dir . '/HTMLPurifier/Exception.php'; -require_once $__dir . '/HTMLPurifier/Filter.php'; -require_once $__dir . '/HTMLPurifier/Generator.php'; -require_once $__dir . '/HTMLPurifier/HTMLDefinition.php'; -require_once $__dir . '/HTMLPurifier/HTMLModule.php'; -require_once $__dir . '/HTMLPurifier/HTMLModuleManager.php'; -require_once $__dir . '/HTMLPurifier/IDAccumulator.php'; -require_once $__dir . '/HTMLPurifier/Injector.php'; -require_once $__dir . '/HTMLPurifier/Language.php'; -require_once $__dir . '/HTMLPurifier/LanguageFactory.php'; -require_once $__dir . '/HTMLPurifier/Length.php'; -require_once $__dir . '/HTMLPurifier/Lexer.php'; -require_once $__dir . '/HTMLPurifier/PercentEncoder.php'; -require_once $__dir . '/HTMLPurifier/PropertyList.php'; -require_once $__dir . '/HTMLPurifier/PropertyListIterator.php'; -require_once $__dir . '/HTMLPurifier/Strategy.php'; -require_once $__dir . '/HTMLPurifier/StringHash.php'; -require_once $__dir . '/HTMLPurifier/StringHashParser.php'; -require_once $__dir . '/HTMLPurifier/TagTransform.php'; -require_once $__dir . '/HTMLPurifier/Token.php'; -require_once $__dir . '/HTMLPurifier/TokenFactory.php'; -require_once $__dir . '/HTMLPurifier/URI.php'; -require_once $__dir . '/HTMLPurifier/URIDefinition.php'; -require_once $__dir . '/HTMLPurifier/URIFilter.php'; -require_once $__dir . '/HTMLPurifier/URIParser.php'; -require_once $__dir . '/HTMLPurifier/URIScheme.php'; -require_once $__dir . '/HTMLPurifier/URISchemeRegistry.php'; -require_once $__dir . '/HTMLPurifier/UnitConverter.php'; -require_once $__dir . '/HTMLPurifier/VarParser.php'; -require_once $__dir . '/HTMLPurifier/VarParserException.php'; -require_once $__dir . '/HTMLPurifier/AttrDef/CSS.php'; -require_once $__dir . '/HTMLPurifier/AttrDef/Enum.php'; -require_once $__dir . '/HTMLPurifier/AttrDef/Integer.php'; -require_once $__dir . '/HTMLPurifier/AttrDef/Lang.php'; -require_once $__dir . '/HTMLPurifier/AttrDef/Switch.php'; -require_once $__dir . '/HTMLPurifier/AttrDef/Text.php'; -require_once $__dir . '/HTMLPurifier/AttrDef/URI.php'; -require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Number.php'; -require_once $__dir . '/HTMLPurifier/AttrDef/CSS/AlphaValue.php'; -require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Background.php'; -require_once $__dir . '/HTMLPurifier/AttrDef/CSS/BackgroundPosition.php'; -require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Border.php'; -require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Color.php'; -require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Composite.php'; -require_once $__dir . '/HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php'; -require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Filter.php'; -require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Font.php'; -require_once $__dir . '/HTMLPurifier/AttrDef/CSS/FontFamily.php'; -require_once $__dir . '/HTMLPurifier/AttrDef/CSS/ImportantDecorator.php'; -require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Length.php'; -require_once $__dir . '/HTMLPurifier/AttrDef/CSS/ListStyle.php'; -require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Multiple.php'; -require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Percentage.php'; -require_once $__dir . '/HTMLPurifier/AttrDef/CSS/TextDecoration.php'; -require_once $__dir . '/HTMLPurifier/AttrDef/CSS/URI.php'; -require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Bool.php'; -require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Nmtokens.php'; -require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Class.php'; -require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Color.php'; -require_once $__dir . '/HTMLPurifier/AttrDef/HTML/FrameTarget.php'; -require_once $__dir . '/HTMLPurifier/AttrDef/HTML/ID.php'; -require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Pixels.php'; -require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Length.php'; -require_once $__dir . '/HTMLPurifier/AttrDef/HTML/LinkTypes.php'; -require_once $__dir . '/HTMLPurifier/AttrDef/HTML/MultiLength.php'; -require_once $__dir . '/HTMLPurifier/AttrDef/URI/Email.php'; -require_once $__dir . '/HTMLPurifier/AttrDef/URI/Host.php'; -require_once $__dir . '/HTMLPurifier/AttrDef/URI/IPv4.php'; -require_once $__dir . '/HTMLPurifier/AttrDef/URI/IPv6.php'; -require_once $__dir . '/HTMLPurifier/AttrDef/URI/Email/SimpleCheck.php'; -require_once $__dir . '/HTMLPurifier/AttrTransform/Background.php'; -require_once $__dir . '/HTMLPurifier/AttrTransform/BdoDir.php'; -require_once $__dir . '/HTMLPurifier/AttrTransform/BgColor.php'; -require_once $__dir . '/HTMLPurifier/AttrTransform/BoolToCSS.php'; -require_once $__dir . '/HTMLPurifier/AttrTransform/Border.php'; -require_once $__dir . '/HTMLPurifier/AttrTransform/EnumToCSS.php'; -require_once $__dir . '/HTMLPurifier/AttrTransform/ImgRequired.php'; -require_once $__dir . '/HTMLPurifier/AttrTransform/ImgSpace.php'; -require_once $__dir . '/HTMLPurifier/AttrTransform/Input.php'; -require_once $__dir . '/HTMLPurifier/AttrTransform/Lang.php'; -require_once $__dir . '/HTMLPurifier/AttrTransform/Length.php'; -require_once $__dir . '/HTMLPurifier/AttrTransform/Name.php'; -require_once $__dir . '/HTMLPurifier/AttrTransform/NameSync.php'; -require_once $__dir . '/HTMLPurifier/AttrTransform/SafeEmbed.php'; -require_once $__dir . '/HTMLPurifier/AttrTransform/SafeObject.php'; -require_once $__dir . '/HTMLPurifier/AttrTransform/SafeParam.php'; -require_once $__dir . '/HTMLPurifier/AttrTransform/ScriptRequired.php'; -require_once $__dir . '/HTMLPurifier/AttrTransform/Textarea.php'; -require_once $__dir . '/HTMLPurifier/ChildDef/Chameleon.php'; -require_once $__dir . '/HTMLPurifier/ChildDef/Custom.php'; -require_once $__dir . '/HTMLPurifier/ChildDef/Empty.php'; -require_once $__dir . '/HTMLPurifier/ChildDef/Required.php'; -require_once $__dir . '/HTMLPurifier/ChildDef/Optional.php'; -require_once $__dir . '/HTMLPurifier/ChildDef/StrictBlockquote.php'; -require_once $__dir . '/HTMLPurifier/ChildDef/Table.php'; -require_once $__dir . '/HTMLPurifier/DefinitionCache/Decorator.php'; -require_once $__dir . '/HTMLPurifier/DefinitionCache/Null.php'; -require_once $__dir . '/HTMLPurifier/DefinitionCache/Serializer.php'; -require_once $__dir . '/HTMLPurifier/DefinitionCache/Decorator/Cleanup.php'; -require_once $__dir . '/HTMLPurifier/DefinitionCache/Decorator/Memory.php'; -require_once $__dir . '/HTMLPurifier/HTMLModule/Bdo.php'; -require_once $__dir . '/HTMLPurifier/HTMLModule/CommonAttributes.php'; -require_once $__dir . '/HTMLPurifier/HTMLModule/Edit.php'; -require_once $__dir . '/HTMLPurifier/HTMLModule/Forms.php'; -require_once $__dir . '/HTMLPurifier/HTMLModule/Hypertext.php'; -require_once $__dir . '/HTMLPurifier/HTMLModule/Image.php'; -require_once $__dir . '/HTMLPurifier/HTMLModule/Legacy.php'; -require_once $__dir . '/HTMLPurifier/HTMLModule/List.php'; -require_once $__dir . '/HTMLPurifier/HTMLModule/Name.php'; -require_once $__dir . '/HTMLPurifier/HTMLModule/NonXMLCommonAttributes.php'; -require_once $__dir . '/HTMLPurifier/HTMLModule/Object.php'; -require_once $__dir . '/HTMLPurifier/HTMLModule/Presentation.php'; -require_once $__dir . '/HTMLPurifier/HTMLModule/Proprietary.php'; -require_once $__dir . '/HTMLPurifier/HTMLModule/Ruby.php'; -require_once $__dir . '/HTMLPurifier/HTMLModule/SafeEmbed.php'; -require_once $__dir . '/HTMLPurifier/HTMLModule/SafeObject.php'; -require_once $__dir . '/HTMLPurifier/HTMLModule/Scripting.php'; -require_once $__dir . '/HTMLPurifier/HTMLModule/StyleAttribute.php'; -require_once $__dir . '/HTMLPurifier/HTMLModule/Tables.php'; -require_once $__dir . '/HTMLPurifier/HTMLModule/Target.php'; -require_once $__dir . '/HTMLPurifier/HTMLModule/Text.php'; -require_once $__dir . '/HTMLPurifier/HTMLModule/Tidy.php'; -require_once $__dir . '/HTMLPurifier/HTMLModule/XMLCommonAttributes.php'; -require_once $__dir . '/HTMLPurifier/HTMLModule/Tidy/Name.php'; -require_once $__dir . '/HTMLPurifier/HTMLModule/Tidy/Proprietary.php'; -require_once $__dir . '/HTMLPurifier/HTMLModule/Tidy/XHTMLAndHTML4.php'; -require_once $__dir . '/HTMLPurifier/HTMLModule/Tidy/Strict.php'; -require_once $__dir . '/HTMLPurifier/HTMLModule/Tidy/Transitional.php'; -require_once $__dir . '/HTMLPurifier/HTMLModule/Tidy/XHTML.php'; -require_once $__dir . '/HTMLPurifier/Injector/AutoParagraph.php'; -require_once $__dir . '/HTMLPurifier/Injector/DisplayLinkURI.php'; -require_once $__dir . '/HTMLPurifier/Injector/Linkify.php'; -require_once $__dir . '/HTMLPurifier/Injector/PurifierLinkify.php'; -require_once $__dir . '/HTMLPurifier/Injector/RemoveEmpty.php'; -require_once $__dir . '/HTMLPurifier/Injector/SafeObject.php'; -require_once $__dir . '/HTMLPurifier/Lexer/DOMLex.php'; -require_once $__dir . '/HTMLPurifier/Lexer/DirectLex.php'; -require_once $__dir . '/HTMLPurifier/Strategy/Composite.php'; -require_once $__dir . '/HTMLPurifier/Strategy/Core.php'; -require_once $__dir . '/HTMLPurifier/Strategy/FixNesting.php'; -require_once $__dir . '/HTMLPurifier/Strategy/MakeWellFormed.php'; -require_once $__dir . '/HTMLPurifier/Strategy/RemoveForeignElements.php'; -require_once $__dir . '/HTMLPurifier/Strategy/ValidateAttributes.php'; -require_once $__dir . '/HTMLPurifier/TagTransform/Font.php'; -require_once $__dir . '/HTMLPurifier/TagTransform/Simple.php'; -require_once $__dir . '/HTMLPurifier/Token/Comment.php'; -require_once $__dir . '/HTMLPurifier/Token/Tag.php'; -require_once $__dir . '/HTMLPurifier/Token/Empty.php'; -require_once $__dir . '/HTMLPurifier/Token/End.php'; -require_once $__dir . '/HTMLPurifier/Token/Start.php'; -require_once $__dir . '/HTMLPurifier/Token/Text.php'; -require_once $__dir . '/HTMLPurifier/URIFilter/DisableExternal.php'; -require_once $__dir . '/HTMLPurifier/URIFilter/DisableExternalResources.php'; -require_once $__dir . '/HTMLPurifier/URIFilter/HostBlacklist.php'; -require_once $__dir . '/HTMLPurifier/URIFilter/MakeAbsolute.php'; -require_once $__dir . '/HTMLPurifier/URIFilter/Munge.php'; -require_once $__dir . '/HTMLPurifier/URIScheme/ftp.php'; -require_once $__dir . '/HTMLPurifier/URIScheme/http.php'; -require_once $__dir . '/HTMLPurifier/URIScheme/https.php'; -require_once $__dir . '/HTMLPurifier/URIScheme/mailto.php'; -require_once $__dir . '/HTMLPurifier/URIScheme/news.php'; -require_once $__dir . '/HTMLPurifier/URIScheme/nntp.php'; -require_once $__dir . '/HTMLPurifier/VarParser/Flexible.php'; -require_once $__dir . '/HTMLPurifier/VarParser/Native.php'; diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrCollections.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrCollections.php deleted file mode 100644 index d5ccfdb5..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrCollections.php +++ /dev/null @@ -1,128 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Defines common attribute collections that modules reference - */ - -class HTMLPurifier_AttrCollections -{ - - /** - * Associative array of attribute collections, indexed by name - */ - public $info = array(); - - /** - * Performs all expansions on internal data for use by other inclusions - * It also collects all attribute collection extensions from - * modules - * @param $attr_types HTMLPurifier_AttrTypes instance - * @param $modules Hash array of HTMLPurifier_HTMLModule members - */ - public function __construct($attr_types, $modules) { - // load extensions from the modules - foreach ($modules as $module) { - foreach ($module->attr_collections as $coll_i => $coll) { - if (!isset($this->info[$coll_i])) { - $this->info[$coll_i] = array(); - } - foreach ($coll as $attr_i => $attr) { - if ($attr_i === 0 && isset($this->info[$coll_i][$attr_i])) { - // merge in includes - $this->info[$coll_i][$attr_i] = array_merge( - $this->info[$coll_i][$attr_i], $attr); - continue; - } - $this->info[$coll_i][$attr_i] = $attr; - } - } - } - // perform internal expansions and inclusions - foreach ($this->info as $name => $attr) { - // merge attribute collections that include others - $this->performInclusions($this->info[$name]); - // replace string identifiers with actual attribute objects - $this->expandIdentifiers($this->info[$name], $attr_types); - } - } - - /** - * Takes a reference to an attribute associative array and performs - * all inclusions specified by the zero index. - * @param &$attr Reference to attribute array - */ - public function performInclusions(&$attr) { - if (!isset($attr[0])) return; - $merge = $attr[0]; - $seen = array(); // recursion guard - // loop through all the inclusions - for ($i = 0; isset($merge[$i]); $i++) { - if (isset($seen[$merge[$i]])) continue; - $seen[$merge[$i]] = true; - // foreach attribute of the inclusion, copy it over - if (!isset($this->info[$merge[$i]])) continue; - foreach ($this->info[$merge[$i]] as $key => $value) { - if (isset($attr[$key])) continue; // also catches more inclusions - $attr[$key] = $value; - } - if (isset($this->info[$merge[$i]][0])) { - // recursion - $merge = array_merge($merge, $this->info[$merge[$i]][0]); - } - } - unset($attr[0]); - } - - /** - * Expands all string identifiers in an attribute array by replacing - * them with the appropriate values inside HTMLPurifier_AttrTypes - * @param &$attr Reference to attribute array - * @param $attr_types HTMLPurifier_AttrTypes instance - */ - public function expandIdentifiers(&$attr, $attr_types) { - - // because foreach will process new elements we add, make sure we - // skip duplicates - $processed = array(); - - foreach ($attr as $def_i => $def) { - // skip inclusions - if ($def_i === 0) continue; - - if (isset($processed[$def_i])) continue; - - // determine whether or not attribute is required - if ($required = (strpos($def_i, '*') !== false)) { - // rename the definition - unset($attr[$def_i]); - $def_i = trim($def_i, '*'); - $attr[$def_i] = $def; - } - - $processed[$def_i] = true; - - // if we've already got a literal object, move on - if (is_object($def)) { - // preserve previous required - $attr[$def_i]->required = ($required || $attr[$def_i]->required); - continue; - } - - if ($def === false) { - unset($attr[$def_i]); - continue; - } - - if ($t = $attr_types->get($def)) { - $attr[$def_i] = $t; - $attr[$def_i]->required = $required; - } else { - unset($attr[$def_i]); - } - } - - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef.php deleted file mode 100644 index 7fac54e8..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef.php +++ /dev/null @@ -1,87 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Base class for all validating attribute definitions. - * - * This family of classes forms the core for not only HTML attribute validation, - * but also any sort of string that needs to be validated or cleaned (which - * means CSS properties and composite definitions are defined here too). - * Besides defining (through code) what precisely makes the string valid, - * subclasses are also responsible for cleaning the code if possible. - */ - -abstract class HTMLPurifier_AttrDef -{ - - /** - * Tells us whether or not an HTML attribute is minimized. Has no - * meaning in other contexts. - */ - public $minimized = false; - - /** - * Tells us whether or not an HTML attribute is required. Has no - * meaning in other contexts - */ - public $required = false; - - /** - * Validates and cleans passed string according to a definition. - * - * @param $string String to be validated and cleaned. - * @param $config Mandatory HTMLPurifier_Config object. - * @param $context Mandatory HTMLPurifier_AttrContext object. - */ - abstract public function validate($string, $config, $context); - - /** - * Convenience method that parses a string as if it were CDATA. - * - * This method process a string in the manner specified at - * <http://www.w3.org/TR/html4/types.html#h-6.2> by removing - * leading and trailing whitespace, ignoring line feeds, and replacing - * carriage returns and tabs with spaces. While most useful for HTML - * attributes specified as CDATA, it can also be applied to most CSS - * values. - * - * @note This method is not entirely standards compliant, as trim() removes - * more types of whitespace than specified in the spec. In practice, - * this is rarely a problem, as those extra characters usually have - * already been removed by HTMLPurifier_Encoder. - * - * @warning This processing is inconsistent with XML's whitespace handling - * as specified by section 3.3.3 and referenced XHTML 1.0 section - * 4.7. However, note that we are NOT necessarily - * parsing XML, thus, this behavior may still be correct. We - * assume that newlines have been normalized. - */ - public function parseCDATA($string) { - $string = trim($string); - $string = str_replace(array("\n", "\t", "\r"), ' ', $string); - return $string; - } - - /** - * Factory method for creating this class from a string. - * @param $string String construction info - * @return Created AttrDef object corresponding to $string - */ - public function make($string) { - // default implementation, return a flyweight of this object. - // If $string has an effect on the returned object (i.e. you - // need to overload this method), it is best - // to clone or instantiate new copies. (Instantiation is safer.) - return $this; - } - - /** - * Removes spaces from rgb(0, 0, 0) so that shorthand CSS properties work - * properly. THIS IS A HACK! - */ - protected function mungeRgb($string) { - return preg_replace('/rgb\((\d+)\s*,\s*(\d+)\s*,\s*(\d+)\)/', 'rgb(\1,\2,\3)', $string); - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS.php deleted file mode 100644 index 275bb81f..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS.php +++ /dev/null @@ -1,87 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Validates the HTML attribute style, otherwise known as CSS. - * @note We don't implement the whole CSS specification, so it might be - * difficult to reuse this component in the context of validating - * actual stylesheet declarations. - * @note If we were really serious about validating the CSS, we would - * tokenize the styles and then parse the tokens. Obviously, we - * are not doing that. Doing that could seriously harm performance, - * but would make these components a lot more viable for a CSS - * filtering solution. - */ -class HTMLPurifier_AttrDef_CSS extends HTMLPurifier_AttrDef -{ - - public function validate($css, $config, $context) { - - $css = $this->parseCDATA($css); - - $definition = $config->getCSSDefinition(); - - // we're going to break the spec and explode by semicolons. - // This is because semicolon rarely appears in escaped form - // Doing this is generally flaky but fast - // IT MIGHT APPEAR IN URIs, see HTMLPurifier_AttrDef_CSSURI - // for details - - $declarations = explode(';', $css); - $propvalues = array(); - - /** - * Name of the current CSS property being validated. - */ - $property = false; - $context->register('CurrentCSSProperty', $property); - - foreach ($declarations as $declaration) { - if (!$declaration) continue; - if (!strpos($declaration, ':')) continue; - list($property, $value) = explode(':', $declaration, 2); - $property = trim($property); - $value = trim($value); - $ok = false; - do { - if (isset($definition->info[$property])) { - $ok = true; - break; - } - if (ctype_lower($property)) break; - $property = strtolower($property); - if (isset($definition->info[$property])) { - $ok = true; - break; - } - } while(0); - if (!$ok) continue; - // inefficient call, since the validator will do this again - if (strtolower(trim($value)) !== 'inherit') { - // inherit works for everything (but only on the base property) - $result = $definition->info[$property]->validate( - $value, $config, $context ); - } else { - $result = 'inherit'; - } - if ($result === false) continue; - $propvalues[$property] = $result; - } - - $context->destroy('CurrentCSSProperty'); - - // procedure does not write the new CSS simultaneously, so it's - // slightly inefficient, but it's the only way of getting rid of - // duplicates. Perhaps config to optimize it, but not now. - - $new_declarations = ''; - foreach ($propvalues as $prop => $value) { - $new_declarations .= "$prop:$value;"; - } - - return $new_declarations ? $new_declarations : false; - - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/AlphaValue.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/AlphaValue.php deleted file mode 100644 index 00a24212..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/AlphaValue.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -class HTMLPurifier_AttrDef_CSS_AlphaValue extends HTMLPurifier_AttrDef_CSS_Number -{ - - public function __construct() { - parent::__construct(false); // opacity is non-negative, but we will clamp it - } - - public function validate($number, $config, $context) { - $result = parent::validate($number, $config, $context); - if ($result === false) return $result; - $float = (float) $result; - if ($float < 0.0) $result = '0'; - if ($float > 1.0) $result = '1'; - return $result; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/Background.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/Background.php deleted file mode 100644 index 0c40512a..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/Background.php +++ /dev/null @@ -1,87 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Validates shorthand CSS property background. - * @warning Does not support url tokens that have internal spaces. - */ -class HTMLPurifier_AttrDef_CSS_Background extends HTMLPurifier_AttrDef -{ - - /** - * Local copy of component validators. - * @note See HTMLPurifier_AttrDef_Font::$info for a similar impl. - */ - protected $info; - - public function __construct($config) { - $def = $config->getCSSDefinition(); - $this->info['background-color'] = $def->info['background-color']; - $this->info['background-image'] = $def->info['background-image']; - $this->info['background-repeat'] = $def->info['background-repeat']; - $this->info['background-attachment'] = $def->info['background-attachment']; - $this->info['background-position'] = $def->info['background-position']; - } - - public function validate($string, $config, $context) { - - // regular pre-processing - $string = $this->parseCDATA($string); - if ($string === '') return false; - - // munge rgb() decl if necessary - $string = $this->mungeRgb($string); - - // assumes URI doesn't have spaces in it - $bits = explode(' ', strtolower($string)); // bits to process - - $caught = array(); - $caught['color'] = false; - $caught['image'] = false; - $caught['repeat'] = false; - $caught['attachment'] = false; - $caught['position'] = false; - - $i = 0; // number of catches - $none = false; - - foreach ($bits as $bit) { - if ($bit === '') continue; - foreach ($caught as $key => $status) { - if ($key != 'position') { - if ($status !== false) continue; - $r = $this->info['background-' . $key]->validate($bit, $config, $context); - } else { - $r = $bit; - } - if ($r === false) continue; - if ($key == 'position') { - if ($caught[$key] === false) $caught[$key] = ''; - $caught[$key] .= $r . ' '; - } else { - $caught[$key] = $r; - } - $i++; - break; - } - } - - if (!$i) return false; - if ($caught['position'] !== false) { - $caught['position'] = $this->info['background-position']-> - validate($caught['position'], $config, $context); - } - - $ret = array(); - foreach ($caught as $value) { - if ($value === false) continue; - $ret[] = $value; - } - - if (empty($ret)) return false; - return implode(' ', $ret); - - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/BackgroundPosition.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/BackgroundPosition.php deleted file mode 100644 index e067a754..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/BackgroundPosition.php +++ /dev/null @@ -1,126 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/* W3C says: - [ // adjective and number must be in correct order, even if - // you could switch them without introducing ambiguity. - // some browsers support that syntax - [ - <percentage> | <length> | left | center | right - ] - [ - <percentage> | <length> | top | center | bottom - ]? - ] | - [ // this signifies that the vertical and horizontal adjectives - // can be arbitrarily ordered, however, there can only be two, - // one of each, or none at all - [ - left | center | right - ] || - [ - top | center | bottom - ] - ] - top, left = 0% - center, (none) = 50% - bottom, right = 100% -*/ - -/* QuirksMode says: - keyword + length/percentage must be ordered correctly, as per W3C - - Internet Explorer and Opera, however, support arbitrary ordering. We - should fix it up. - - Minor issue though, not strictly necessary. -*/ - -// control freaks may appreciate the ability to convert these to -// percentages or something, but it's not necessary - -/** - * Validates the value of background-position. - */ -class HTMLPurifier_AttrDef_CSS_BackgroundPosition extends HTMLPurifier_AttrDef -{ - - protected $length; - protected $percentage; - - public function __construct() { - $this->length = new HTMLPurifier_AttrDef_CSS_Length(); - $this->percentage = new HTMLPurifier_AttrDef_CSS_Percentage(); - } - - public function validate($string, $config, $context) { - $string = $this->parseCDATA($string); - $bits = explode(' ', $string); - - $keywords = array(); - $keywords['h'] = false; // left, right - $keywords['v'] = false; // top, bottom - $keywords['c'] = false; // center - $measures = array(); - - $i = 0; - - $lookup = array( - 'top' => 'v', - 'bottom' => 'v', - 'left' => 'h', - 'right' => 'h', - 'center' => 'c' - ); - - foreach ($bits as $bit) { - if ($bit === '') continue; - - // test for keyword - $lbit = ctype_lower($bit) ? $bit : strtolower($bit); - if (isset($lookup[$lbit])) { - $status = $lookup[$lbit]; - $keywords[$status] = $lbit; - $i++; - } - - // test for length - $r = $this->length->validate($bit, $config, $context); - if ($r !== false) { - $measures[] = $r; - $i++; - } - - // test for percentage - $r = $this->percentage->validate($bit, $config, $context); - if ($r !== false) { - $measures[] = $r; - $i++; - } - - } - - if (!$i) return false; // no valid values were caught - - - $ret = array(); - - // first keyword - if ($keywords['h']) $ret[] = $keywords['h']; - elseif (count($measures)) $ret[] = array_shift($measures); - elseif ($keywords['c']) { - $ret[] = $keywords['c']; - $keywords['c'] = false; // prevent re-use: center = center center - } - - if ($keywords['v']) $ret[] = $keywords['v']; - elseif (count($measures)) $ret[] = array_shift($measures); - elseif ($keywords['c']) $ret[] = $keywords['c']; - - if (empty($ret)) return false; - return implode(' ', $ret); - - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/Border.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/Border.php deleted file mode 100644 index 629e74f6..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/Border.php +++ /dev/null @@ -1,43 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Validates the border property as defined by CSS. - */ -class HTMLPurifier_AttrDef_CSS_Border extends HTMLPurifier_AttrDef -{ - - /** - * Local copy of properties this property is shorthand for. - */ - protected $info = array(); - - public function __construct($config) { - $def = $config->getCSSDefinition(); - $this->info['border-width'] = $def->info['border-width']; - $this->info['border-style'] = $def->info['border-style']; - $this->info['border-top-color'] = $def->info['border-top-color']; - } - - public function validate($string, $config, $context) { - $string = $this->parseCDATA($string); - $string = $this->mungeRgb($string); - $bits = explode(' ', $string); - $done = array(); // segments we've finished - $ret = ''; // return value - foreach ($bits as $bit) { - foreach ($this->info as $propname => $validator) { - if (isset($done[$propname])) continue; - $r = $validator->validate($bit, $config, $context); - if ($r !== false) { - $ret .= $r . ' '; - $done[$propname] = true; - break; - } - } - } - return rtrim($ret); - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/Color.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/Color.php deleted file mode 100644 index 54ee2490..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/Color.php +++ /dev/null @@ -1,78 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Validates Color as defined by CSS. - */ -class HTMLPurifier_AttrDef_CSS_Color extends HTMLPurifier_AttrDef -{ - - public function validate($color, $config, $context) { - - static $colors = null; - if ($colors === null) $colors = $config->get('Core.ColorKeywords'); - - $color = trim($color); - if ($color === '') return false; - - $lower = strtolower($color); - if (isset($colors[$lower])) return $colors[$lower]; - - if (strpos($color, 'rgb(') !== false) { - // rgb literal handling - $length = strlen($color); - if (strpos($color, ')') !== $length - 1) return false; - $triad = substr($color, 4, $length - 4 - 1); - $parts = explode(',', $triad); - if (count($parts) !== 3) return false; - $type = false; // to ensure that they're all the same type - $new_parts = array(); - foreach ($parts as $part) { - $part = trim($part); - if ($part === '') return false; - $length = strlen($part); - if ($part[$length - 1] === '%') { - // handle percents - if (!$type) { - $type = 'percentage'; - } elseif ($type !== 'percentage') { - return false; - } - $num = (float) substr($part, 0, $length - 1); - if ($num < 0) $num = 0; - if ($num > 100) $num = 100; - $new_parts[] = "$num%"; - } else { - // handle integers - if (!$type) { - $type = 'integer'; - } elseif ($type !== 'integer') { - return false; - } - $num = (int) $part; - if ($num < 0) $num = 0; - if ($num > 255) $num = 255; - $new_parts[] = (string) $num; - } - } - $new_triad = implode(',', $new_parts); - $color = "rgb($new_triad)"; - } else { - // hexadecimal handling - if ($color[0] === '#') { - $hex = substr($color, 1); - } else { - $hex = $color; - $color = '#' . $color; - } - $length = strlen($hex); - if ($length !== 3 && $length !== 6) return false; - if (!ctype_xdigit($hex)) return false; - } - - return $color; - - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/Composite.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/Composite.php deleted file mode 100644 index 14038b8a..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/Composite.php +++ /dev/null @@ -1,38 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Allows multiple validators to attempt to validate attribute. - * - * Composite is just what it sounds like: a composite of many validators. - * This means that multiple HTMLPurifier_AttrDef objects will have a whack - * at the string. If one of them passes, that's what is returned. This is - * especially useful for CSS values, which often are a choice between - * an enumerated set of predefined values or a flexible data type. - */ -class HTMLPurifier_AttrDef_CSS_Composite extends HTMLPurifier_AttrDef -{ - - /** - * List of HTMLPurifier_AttrDef objects that may process strings - * @todo Make protected - */ - public $defs; - - /** - * @param $defs List of HTMLPurifier_AttrDef objects - */ - public function __construct($defs) { - $this->defs = $defs; - } - - public function validate($string, $config, $context) { - foreach ($this->defs as $i => $def) { - $result = $this->defs[$i]->validate($string, $config, $context); - if ($result !== false) return $result; - } - return false; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php deleted file mode 100644 index eb0c5113..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php +++ /dev/null @@ -1,28 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Decorator which enables CSS properties to be disabled for specific elements. - */ -class HTMLPurifier_AttrDef_CSS_DenyElementDecorator extends HTMLPurifier_AttrDef -{ - public $def, $element; - - /** - * @param $def Definition to wrap - * @param $element Element to deny - */ - public function __construct($def, $element) { - $this->def = $def; - $this->element = $element; - } - /** - * Checks if CurrentToken is set and equal to $this->element - */ - public function validate($string, $config, $context) { - $token = $context->get('CurrentToken', true); - if ($token && $token->name == $this->element) return false; - return $this->def->validate($string, $config, $context); - } -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/Filter.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/Filter.php deleted file mode 100644 index 8ba8bfdc..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/Filter.php +++ /dev/null @@ -1,54 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Microsoft's proprietary filter: CSS property - * @note Currently supports the alpha filter. In the future, this will - * probably need an extensible framework - */ -class HTMLPurifier_AttrDef_CSS_Filter extends HTMLPurifier_AttrDef -{ - - protected $intValidator; - - public function __construct() { - $this->intValidator = new HTMLPurifier_AttrDef_Integer(); - } - - public function validate($value, $config, $context) { - $value = $this->parseCDATA($value); - if ($value === 'none') return $value; - // if we looped this we could support multiple filters - $function_length = strcspn($value, '('); - $function = trim(substr($value, 0, $function_length)); - if ($function !== 'alpha' && - $function !== 'Alpha' && - $function !== 'progid:DXImageTransform.Microsoft.Alpha' - ) return false; - $cursor = $function_length + 1; - $parameters_length = strcspn($value, ')', $cursor); - $parameters = substr($value, $cursor, $parameters_length); - $params = explode(',', $parameters); - $ret_params = array(); - $lookup = array(); - foreach ($params as $param) { - list($key, $value) = explode('=', $param); - $key = trim($key); - $value = trim($value); - if (isset($lookup[$key])) continue; - if ($key !== 'opacity') continue; - $value = $this->intValidator->validate($value, $config, $context); - if ($value === false) continue; - $int = (int) $value; - if ($int > 100) $value = '100'; - if ($int < 0) $value = '0'; - $ret_params[] = "$key=$value"; - $lookup[$key] = true; - } - $ret_parameters = implode(',', $ret_params); - $ret_function = "$function($ret_parameters)"; - return $ret_function; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/Font.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/Font.php deleted file mode 100644 index f5131e7e..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/Font.php +++ /dev/null @@ -1,149 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Validates shorthand CSS property font. - */ -class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef -{ - - /** - * Local copy of component validators. - * - * @note If we moved specific CSS property definitions to their own - * classes instead of having them be assembled at run time by - * CSSDefinition, this wouldn't be necessary. We'd instantiate - * our own copies. - */ - protected $info = array(); - - public function __construct($config) { - $def = $config->getCSSDefinition(); - $this->info['font-style'] = $def->info['font-style']; - $this->info['font-variant'] = $def->info['font-variant']; - $this->info['font-weight'] = $def->info['font-weight']; - $this->info['font-size'] = $def->info['font-size']; - $this->info['line-height'] = $def->info['line-height']; - $this->info['font-family'] = $def->info['font-family']; - } - - public function validate($string, $config, $context) { - - static $system_fonts = array( - 'caption' => true, - 'icon' => true, - 'menu' => true, - 'message-box' => true, - 'small-caption' => true, - 'status-bar' => true - ); - - // regular pre-processing - $string = $this->parseCDATA($string); - if ($string === '') return false; - - // check if it's one of the keywords - $lowercase_string = strtolower($string); - if (isset($system_fonts[$lowercase_string])) { - return $lowercase_string; - } - - $bits = explode(' ', $string); // bits to process - $stage = 0; // this indicates what we're looking for - $caught = array(); // which stage 0 properties have we caught? - $stage_1 = array('font-style', 'font-variant', 'font-weight'); - $final = ''; // output - - for ($i = 0, $size = count($bits); $i < $size; $i++) { - if ($bits[$i] === '') continue; - switch ($stage) { - - // attempting to catch font-style, font-variant or font-weight - case 0: - foreach ($stage_1 as $validator_name) { - if (isset($caught[$validator_name])) continue; - $r = $this->info[$validator_name]->validate( - $bits[$i], $config, $context); - if ($r !== false) { - $final .= $r . ' '; - $caught[$validator_name] = true; - break; - } - } - // all three caught, continue on - if (count($caught) >= 3) $stage = 1; - if ($r !== false) break; - - // attempting to catch font-size and perhaps line-height - case 1: - $found_slash = false; - if (strpos($bits[$i], '/') !== false) { - list($font_size, $line_height) = - explode('/', $bits[$i]); - if ($line_height === '') { - // ooh, there's a space after the slash! - $line_height = false; - $found_slash = true; - } - } else { - $font_size = $bits[$i]; - $line_height = false; - } - $r = $this->info['font-size']->validate( - $font_size, $config, $context); - if ($r !== false) { - $final .= $r; - // attempt to catch line-height - if ($line_height === false) { - // we need to scroll forward - for ($j = $i + 1; $j < $size; $j++) { - if ($bits[$j] === '') continue; - if ($bits[$j] === '/') { - if ($found_slash) { - return false; - } else { - $found_slash = true; - continue; - } - } - $line_height = $bits[$j]; - break; - } - } else { - // slash already found - $found_slash = true; - $j = $i; - } - if ($found_slash) { - $i = $j; - $r = $this->info['line-height']->validate( - $line_height, $config, $context); - if ($r !== false) { - $final .= '/' . $r; - } - } - $final .= ' '; - $stage = 2; - break; - } - return false; - - // attempting to catch font-family - case 2: - $font_family = - implode(' ', array_slice($bits, $i, $size - $i)); - $r = $this->info['font-family']->validate( - $font_family, $config, $context); - if ($r !== false) { - $final .= $r . ' '; - // processing completed successfully - return rtrim($final); - } - return false; - } - } - return false; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/FontFamily.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/FontFamily.php deleted file mode 100644 index 33435c76..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/FontFamily.php +++ /dev/null @@ -1,90 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Validates a font family list according to CSS spec - * @todo whitelisting allowed fonts would be nice - */ -class HTMLPurifier_AttrDef_CSS_FontFamily extends HTMLPurifier_AttrDef -{ - - public function validate($string, $config, $context) { - static $generic_names = array( - 'serif' => true, - 'sans-serif' => true, - 'monospace' => true, - 'fantasy' => true, - 'cursive' => true - ); - - // assume that no font names contain commas in them - $fonts = explode(',', $string); - $final = ''; - foreach($fonts as $font) { - $font = trim($font); - if ($font === '') continue; - // match a generic name - if (isset($generic_names[$font])) { - $final .= $font . ', '; - continue; - } - // match a quoted name - if ($font[0] === '"' || $font[0] === "'") { - $length = strlen($font); - if ($length <= 2) continue; - $quote = $font[0]; - if ($font[$length - 1] !== $quote) continue; - $font = substr($font, 1, $length - 2); - - $new_font = ''; - for ($i = 0, $c = strlen($font); $i < $c; $i++) { - if ($font[$i] === '\\') { - $i++; - if ($i >= $c) { - $new_font .= '\\'; - break; - } - if (ctype_xdigit($font[$i])) { - $code = $font[$i]; - for ($a = 1, $i++; $i < $c && $a < 6; $i++, $a++) { - if (!ctype_xdigit($font[$i])) break; - $code .= $font[$i]; - } - // We have to be extremely careful when adding - // new characters, to make sure we're not breaking - // the encoding. - $char = HTMLPurifier_Encoder::unichr(hexdec($code)); - if (HTMLPurifier_Encoder::cleanUTF8($char) === '') continue; - $new_font .= $char; - if ($i < $c && trim($font[$i]) !== '') $i--; - continue; - } - if ($font[$i] === "\n") continue; - } - $new_font .= $font[$i]; - } - - $font = $new_font; - } - // $font is a pure representation of the font name - - if (ctype_alnum($font) && $font !== '') { - // very simple font, allow it in unharmed - $final .= $font . ', '; - continue; - } - - // complicated font, requires quoting - - // armor single quotes and new lines - $font = str_replace("\\", "\\\\", $font); - $font = str_replace("'", "\\'", $font); - $final .= "'$font', "; - } - $final = rtrim($final, ', '); - if ($final === '') return false; - return $final; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/ImportantDecorator.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/ImportantDecorator.php deleted file mode 100644 index c47c3003..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/ImportantDecorator.php +++ /dev/null @@ -1,40 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Decorator which enables !important to be used in CSS values. - */ -class HTMLPurifier_AttrDef_CSS_ImportantDecorator extends HTMLPurifier_AttrDef -{ - public $def, $allow; - - /** - * @param $def Definition to wrap - * @param $allow Whether or not to allow !important - */ - public function __construct($def, $allow = false) { - $this->def = $def; - $this->allow = $allow; - } - /** - * Intercepts and removes !important if necessary - */ - public function validate($string, $config, $context) { - // test for ! and important tokens - $string = trim($string); - $is_important = false; - // :TODO: optimization: test directly for !important and ! important - if (strlen($string) >= 9 && substr($string, -9) === 'important') { - $temp = rtrim(substr($string, 0, -9)); - // use a temp, because we might want to restore important - if (strlen($temp) >= 1 && substr($temp, -1) === '!') { - $string = rtrim(substr($temp, 0, -1)); - $is_important = true; - } - } - $string = $this->def->validate($string, $config, $context); - if ($this->allow && $is_important) $string .= ' !important'; - return $string; - } -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/Length.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/Length.php deleted file mode 100644 index e055643e..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/Length.php +++ /dev/null @@ -1,47 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Represents a Length as defined by CSS. - */ -class HTMLPurifier_AttrDef_CSS_Length extends HTMLPurifier_AttrDef -{ - - protected $min, $max; - - /** - * @param HTMLPurifier_Length $max Minimum length, or null for no bound. String is also acceptable. - * @param HTMLPurifier_Length $max Maximum length, or null for no bound. String is also acceptable. - */ - public function __construct($min = null, $max = null) { - $this->min = $min !== null ? HTMLPurifier_Length::make($min) : null; - $this->max = $max !== null ? HTMLPurifier_Length::make($max) : null; - } - - public function validate($string, $config, $context) { - $string = $this->parseCDATA($string); - - // Optimizations - if ($string === '') return false; - if ($string === '0') return '0'; - if (strlen($string) === 1) return false; - - $length = HTMLPurifier_Length::make($string); - if (!$length->isValid()) return false; - - if ($this->min) { - $c = $length->compareTo($this->min); - if ($c === false) return false; - if ($c < 0) return false; - } - if ($this->max) { - $c = $length->compareTo($this->max); - if ($c === false) return false; - if ($c > 0) return false; - } - - return $length->toString(); - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/ListStyle.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/ListStyle.php deleted file mode 100644 index 008e96d7..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/ListStyle.php +++ /dev/null @@ -1,78 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Validates shorthand CSS property list-style. - * @warning Does not support url tokens that have internal spaces. - */ -class HTMLPurifier_AttrDef_CSS_ListStyle extends HTMLPurifier_AttrDef -{ - - /** - * Local copy of component validators. - * @note See HTMLPurifier_AttrDef_CSS_Font::$info for a similar impl. - */ - protected $info; - - public function __construct($config) { - $def = $config->getCSSDefinition(); - $this->info['list-style-type'] = $def->info['list-style-type']; - $this->info['list-style-position'] = $def->info['list-style-position']; - $this->info['list-style-image'] = $def->info['list-style-image']; - } - - public function validate($string, $config, $context) { - - // regular pre-processing - $string = $this->parseCDATA($string); - if ($string === '') return false; - - // assumes URI doesn't have spaces in it - $bits = explode(' ', strtolower($string)); // bits to process - - $caught = array(); - $caught['type'] = false; - $caught['position'] = false; - $caught['image'] = false; - - $i = 0; // number of catches - $none = false; - - foreach ($bits as $bit) { - if ($i >= 3) return; // optimization bit - if ($bit === '') continue; - foreach ($caught as $key => $status) { - if ($status !== false) continue; - $r = $this->info['list-style-' . $key]->validate($bit, $config, $context); - if ($r === false) continue; - if ($r === 'none') { - if ($none) continue; - else $none = true; - if ($key == 'image') continue; - } - $caught[$key] = $r; - $i++; - break; - } - } - - if (!$i) return false; - - $ret = array(); - - // construct type - if ($caught['type']) $ret[] = $caught['type']; - - // construct image - if ($caught['image']) $ret[] = $caught['image']; - - // construct position - if ($caught['position']) $ret[] = $caught['position']; - - if (empty($ret)) return false; - return implode(' ', $ret); - - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/Multiple.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/Multiple.php deleted file mode 100644 index 825197d2..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/Multiple.php +++ /dev/null @@ -1,58 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Framework class for strings that involve multiple values. - * - * Certain CSS properties such as border-width and margin allow multiple - * lengths to be specified. This class can take a vanilla border-width - * definition and multiply it, usually into a max of four. - * - * @note Even though the CSS specification isn't clear about it, inherit - * can only be used alone: it will never manifest as part of a multi - * shorthand declaration. Thus, this class does not allow inherit. - */ -class HTMLPurifier_AttrDef_CSS_Multiple extends HTMLPurifier_AttrDef -{ - - /** - * Instance of component definition to defer validation to. - * @todo Make protected - */ - public $single; - - /** - * Max number of values allowed. - * @todo Make protected - */ - public $max; - - /** - * @param $single HTMLPurifier_AttrDef to multiply - * @param $max Max number of values allowed (usually four) - */ - public function __construct($single, $max = 4) { - $this->single = $single; - $this->max = $max; - } - - public function validate($string, $config, $context) { - $string = $this->parseCDATA($string); - if ($string === '') return false; - $parts = explode(' ', $string); // parseCDATA replaced \r, \t and \n - $length = count($parts); - $final = ''; - for ($i = 0, $num = 0; $i < $length && $num < $this->max; $i++) { - if (ctype_space($parts[$i])) continue; - $result = $this->single->validate($parts[$i], $config, $context); - if ($result !== false) { - $final .= $result . ' '; - $num++; - } - } - if ($final === '') return false; - return rtrim($final); - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/Number.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/Number.php deleted file mode 100644 index 6a7a2605..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/Number.php +++ /dev/null @@ -1,69 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Validates a number as defined by the CSS spec. - */ -class HTMLPurifier_AttrDef_CSS_Number extends HTMLPurifier_AttrDef -{ - - /** - * Bool indicating whether or not only positive values allowed. - */ - protected $non_negative = false; - - /** - * @param $non_negative Bool indicating whether negatives are forbidden - */ - public function __construct($non_negative = false) { - $this->non_negative = $non_negative; - } - - /** - * @warning Some contexts do not pass $config, $context. These - * variables should not be used without checking HTMLPurifier_Length - */ - public function validate($number, $config, $context) { - - $number = $this->parseCDATA($number); - - if ($number === '') return false; - if ($number === '0') return '0'; - - $sign = ''; - switch ($number[0]) { - case '-': - if ($this->non_negative) return false; - $sign = '-'; - case '+': - $number = substr($number, 1); - } - - if (ctype_digit($number)) { - $number = ltrim($number, '0'); - return $number ? $sign . $number : '0'; - } - - // Period is the only non-numeric character allowed - if (strpos($number, '.') === false) return false; - - list($left, $right) = explode('.', $number, 2); - - if ($left === '' && $right === '') return false; - if ($left !== '' && !ctype_digit($left)) return false; - - $left = ltrim($left, '0'); - $right = rtrim($right, '0'); - - if ($right === '') { - return $left ? $sign . $left : '0'; - } elseif (!ctype_digit($right)) { - return false; - } - - return $sign . $left . '.' . $right; - - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/Percentage.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/Percentage.php deleted file mode 100644 index 1dcca1a8..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/Percentage.php +++ /dev/null @@ -1,40 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Validates a Percentage as defined by the CSS spec. - */ -class HTMLPurifier_AttrDef_CSS_Percentage extends HTMLPurifier_AttrDef -{ - - /** - * Instance of HTMLPurifier_AttrDef_CSS_Number to defer number validation - */ - protected $number_def; - - /** - * @param Bool indicating whether to forbid negative values - */ - public function __construct($non_negative = false) { - $this->number_def = new HTMLPurifier_AttrDef_CSS_Number($non_negative); - } - - public function validate($string, $config, $context) { - - $string = $this->parseCDATA($string); - - if ($string === '') return false; - $length = strlen($string); - if ($length === 1) return false; - if ($string[$length - 1] !== '%') return false; - - $number = substr($string, 0, $length - 1); - $number = $this->number_def->validate($number, $config, $context); - - if ($number === false) return false; - return "$number%"; - - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/TextDecoration.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/TextDecoration.php deleted file mode 100644 index 912811f9..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/TextDecoration.php +++ /dev/null @@ -1,38 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Validates the value for the CSS property text-decoration - * @note This class could be generalized into a version that acts sort of - * like Enum except you can compound the allowed values. - */ -class HTMLPurifier_AttrDef_CSS_TextDecoration extends HTMLPurifier_AttrDef -{ - - public function validate($string, $config, $context) { - - static $allowed_values = array( - 'line-through' => true, - 'overline' => true, - 'underline' => true, - ); - - $string = strtolower($this->parseCDATA($string)); - - if ($string === 'none') return $string; - - $parts = explode(' ', $string); - $final = ''; - foreach ($parts as $part) { - if (isset($allowed_values[$part])) { - $final .= $part . ' '; - } - } - $final = rtrim($final); - if ($final === '') return false; - return $final; - - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/URI.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/URI.php deleted file mode 100644 index d09c87bc..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/CSS/URI.php +++ /dev/null @@ -1,56 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Validates a URI in CSS syntax, which uses url('http://example.com') - * @note While theoretically speaking a URI in a CSS document could - * be non-embedded, as of CSS2 there is no such usage so we're - * generalizing it. This may need to be changed in the future. - * @warning Since HTMLPurifier_AttrDef_CSS blindly uses semicolons as - * the separator, you cannot put a literal semicolon in - * in the URI. Try percent encoding it, in that case. - */ -class HTMLPurifier_AttrDef_CSS_URI extends HTMLPurifier_AttrDef_URI -{ - - public function __construct() { - parent::__construct(true); // always embedded - } - - public function validate($uri_string, $config, $context) { - // parse the URI out of the string and then pass it onto - // the parent object - - $uri_string = $this->parseCDATA($uri_string); - if (strpos($uri_string, 'url(') !== 0) return false; - $uri_string = substr($uri_string, 4); - $new_length = strlen($uri_string) - 1; - if ($uri_string[$new_length] != ')') return false; - $uri = trim(substr($uri_string, 0, $new_length)); - - if (!empty($uri) && ($uri[0] == "'" || $uri[0] == '"')) { - $quote = $uri[0]; - $new_length = strlen($uri) - 1; - if ($uri[$new_length] !== $quote) return false; - $uri = substr($uri, 1, $new_length - 1); - } - - $keys = array( '(', ')', ',', ' ', '"', "'"); - $values = array('\\(', '\\)', '\\,', '\\ ', '\\"', "\\'"); - $uri = str_replace($values, $keys, $uri); - - $result = parent::validate($uri, $config, $context); - - if ($result === false) return false; - - // escape necessary characters according to CSS spec - // except for the comma, none of these should appear in the - // URI at all - $result = str_replace($keys, $values, $result); - - return "url($result)"; - - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/Enum.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/Enum.php deleted file mode 100644 index 59745e6d..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/Enum.php +++ /dev/null @@ -1,65 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -// Enum = Enumerated -/** - * Validates a keyword against a list of valid values. - * @warning The case-insensitive compare of this function uses PHP's - * built-in strtolower and ctype_lower functions, which may - * cause problems with international comparisons - */ -class HTMLPurifier_AttrDef_Enum extends HTMLPurifier_AttrDef -{ - - /** - * Lookup table of valid values. - * @todo Make protected - */ - public $valid_values = array(); - - /** - * Bool indicating whether or not enumeration is case sensitive. - * @note In general this is always case insensitive. - */ - protected $case_sensitive = false; // values according to W3C spec - - /** - * @param $valid_values List of valid values - * @param $case_sensitive Bool indicating whether or not case sensitive - */ - public function __construct( - $valid_values = array(), $case_sensitive = false - ) { - $this->valid_values = array_flip($valid_values); - $this->case_sensitive = $case_sensitive; - } - - public function validate($string, $config, $context) { - $string = trim($string); - if (!$this->case_sensitive) { - // we may want to do full case-insensitive libraries - $string = ctype_lower($string) ? $string : strtolower($string); - } - $result = isset($this->valid_values[$string]); - - return $result ? $string : false; - } - - /** - * @param $string In form of comma-delimited list of case-insensitive - * valid values. Example: "foo,bar,baz". Prepend "s:" to make - * case sensitive - */ - public function make($string) { - if (strlen($string) > 2 && $string[0] == 's' && $string[1] == ':') { - $string = substr($string, 2); - $sensitive = true; - } else { - $sensitive = false; - } - $values = explode(',', $string); - return new HTMLPurifier_AttrDef_Enum($values, $sensitive); - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/HTML/Bool.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/HTML/Bool.php deleted file mode 100644 index ccd8dca5..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/HTML/Bool.php +++ /dev/null @@ -1,28 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Validates a boolean attribute - */ -class HTMLPurifier_AttrDef_HTML_Bool extends HTMLPurifier_AttrDef -{ - - protected $name; - public $minimized = true; - - public function __construct($name = false) {$this->name = $name;} - - public function validate($string, $config, $context) { - if (empty($string)) return false; - return $this->name; - } - - /** - * @param $string Name of attribute - */ - public function make($string) { - return new HTMLPurifier_AttrDef_HTML_Bool($string); - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/HTML/Class.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/HTML/Class.php deleted file mode 100644 index 219b59fe..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/HTML/Class.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Implements special behavior for class attribute (normally NMTOKENS) - */ -class HTMLPurifier_AttrDef_HTML_Class extends HTMLPurifier_AttrDef_HTML_Nmtokens -{ - protected function split($string, $config, $context) { - // really, this twiddle should be lazy loaded - $name = $config->getDefinition('HTML')->doctype->name; - if ($name == "XHTML 1.1" || $name == "XHTML 2.0") { - return parent::split($string, $config, $context); - } else { - return preg_split('/\s+/', $string); - } - } - protected function filter($tokens, $config, $context) { - $allowed = $config->get('Attr.AllowedClasses'); - $forbidden = $config->get('Attr.ForbiddenClasses'); - $ret = array(); - foreach ($tokens as $token) { - if ( - ($allowed === null || isset($allowed[$token])) && - !isset($forbidden[$token]) && - // We need this O(n) check because of PHP's array - // implementation that casts -0 to 0. - !in_array($token, $ret, true) - ) { - $ret[] = $token; - } - } - return $ret; - } -} diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/HTML/Color.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/HTML/Color.php deleted file mode 100644 index 7fdf0a15..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/HTML/Color.php +++ /dev/null @@ -1,32 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Validates a color according to the HTML spec. - */ -class HTMLPurifier_AttrDef_HTML_Color extends HTMLPurifier_AttrDef -{ - - public function validate($string, $config, $context) { - - static $colors = null; - if ($colors === null) $colors = $config->get('Core.ColorKeywords'); - - $string = trim($string); - - if (empty($string)) return false; - if (isset($colors[$string])) return $colors[$string]; - if ($string[0] === '#') $hex = substr($string, 1); - else $hex = $string; - - $length = strlen($hex); - if ($length !== 3 && $length !== 6) return false; - if (!ctype_xdigit($hex)) return false; - if ($length === 3) $hex = $hex[0].$hex[0].$hex[1].$hex[1].$hex[2].$hex[2]; - - return "#$hex"; - - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/HTML/FrameTarget.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/HTML/FrameTarget.php deleted file mode 100644 index 306a210c..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/HTML/FrameTarget.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Special-case enum attribute definition that lazy loads allowed frame targets - */ -class HTMLPurifier_AttrDef_HTML_FrameTarget extends HTMLPurifier_AttrDef_Enum -{ - - public $valid_values = false; // uninitialized value - protected $case_sensitive = false; - - public function __construct() {} - - public function validate($string, $config, $context) { - if ($this->valid_values === false) $this->valid_values = $config->get('Attr.AllowedFrameTargets'); - return parent::validate($string, $config, $context); - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/HTML/ID.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/HTML/ID.php deleted file mode 100644 index 609b5eeb..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/HTML/ID.php +++ /dev/null @@ -1,70 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Validates the HTML attribute ID. - * @warning Even though this is the id processor, it - * will ignore the directive Attr:IDBlacklist, since it will only - * go according to the ID accumulator. Since the accumulator is - * automatically generated, it will have already absorbed the - * blacklist. If you're hacking around, make sure you use load()! - */ - -class HTMLPurifier_AttrDef_HTML_ID extends HTMLPurifier_AttrDef -{ - - // ref functionality disabled, since we also have to verify - // whether or not the ID it refers to exists - - public function validate($id, $config, $context) { - - if (!$config->get('Attr.EnableID')) return false; - - $id = trim($id); // trim it first - - if ($id === '') return false; - - $prefix = $config->get('Attr.IDPrefix'); - if ($prefix !== '') { - $prefix .= $config->get('Attr.IDPrefixLocal'); - // prevent re-appending the prefix - if (strpos($id, $prefix) !== 0) $id = $prefix . $id; - } elseif ($config->get('Attr.IDPrefixLocal') !== '') { - trigger_error('%Attr.IDPrefixLocal cannot be used unless '. - '%Attr.IDPrefix is set', E_USER_WARNING); - } - - //if (!$this->ref) { - $id_accumulator =& $context->get('IDAccumulator'); - if (isset($id_accumulator->ids[$id])) return false; - //} - - // we purposely avoid using regex, hopefully this is faster - - if (ctype_alpha($id)) { - $result = true; - } else { - if (!ctype_alpha(@$id[0])) return false; - $trim = trim( // primitive style of regexps, I suppose - $id, - 'A..Za..z0..9:-._' - ); - $result = ($trim === ''); - } - - $regexp = $config->get('Attr.IDBlacklistRegexp'); - if ($regexp && preg_match($regexp, $id)) { - return false; - } - - if (/*!$this->ref && */$result) $id_accumulator->add($id); - - // if no change was made to the ID, return the result - // else, return the new id if stripping whitespace made it - // valid, or return false. - return $result ? $id : false; - - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/HTML/Length.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/HTML/Length.php deleted file mode 100644 index 7eec741a..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/HTML/Length.php +++ /dev/null @@ -1,41 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Validates the HTML type length (not to be confused with CSS's length). - * - * This accepts integer pixels or percentages as lengths for certain - * HTML attributes. - */ - -class HTMLPurifier_AttrDef_HTML_Length extends HTMLPurifier_AttrDef_HTML_Pixels -{ - - public function validate($string, $config, $context) { - - $string = trim($string); - if ($string === '') return false; - - $parent_result = parent::validate($string, $config, $context); - if ($parent_result !== false) return $parent_result; - - $length = strlen($string); - $last_char = $string[$length - 1]; - - if ($last_char !== '%') return false; - - $points = substr($string, 0, $length - 1); - - if (!is_numeric($points)) return false; - - $points = (int) $points; - - if ($points < 0) return '0%'; - if ($points > 100) return '100%'; - - return ((string) $points) . '%'; - - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/HTML/LinkTypes.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/HTML/LinkTypes.php deleted file mode 100644 index 8b89ceb1..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/HTML/LinkTypes.php +++ /dev/null @@ -1,53 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Validates a rel/rev link attribute against a directive of allowed values - * @note We cannot use Enum because link types allow multiple - * values. - * @note Assumes link types are ASCII text - */ -class HTMLPurifier_AttrDef_HTML_LinkTypes extends HTMLPurifier_AttrDef -{ - - /** Name config attribute to pull. */ - protected $name; - - public function __construct($name) { - $configLookup = array( - 'rel' => 'AllowedRel', - 'rev' => 'AllowedRev' - ); - if (!isset($configLookup[$name])) { - trigger_error('Unrecognized attribute name for link '. - 'relationship.', E_USER_ERROR); - return; - } - $this->name = $configLookup[$name]; - } - - public function validate($string, $config, $context) { - - $allowed = $config->get('Attr.' . $this->name); - if (empty($allowed)) return false; - - $string = $this->parseCDATA($string); - $parts = explode(' ', $string); - - // lookup to prevent duplicates - $ret_lookup = array(); - foreach ($parts as $part) { - $part = strtolower(trim($part)); - if (!isset($allowed[$part])) continue; - $ret_lookup[$part] = true; - } - - if (empty($ret_lookup)) return false; - $string = implode(' ', array_keys($ret_lookup)); - - return $string; - - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/HTML/MultiLength.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/HTML/MultiLength.php deleted file mode 100644 index 78ee7839..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/HTML/MultiLength.php +++ /dev/null @@ -1,41 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Validates a MultiLength as defined by the HTML spec. - * - * A multilength is either a integer (pixel count), a percentage, or - * a relative number. - */ -class HTMLPurifier_AttrDef_HTML_MultiLength extends HTMLPurifier_AttrDef_HTML_Length -{ - - public function validate($string, $config, $context) { - - $string = trim($string); - if ($string === '') return false; - - $parent_result = parent::validate($string, $config, $context); - if ($parent_result !== false) return $parent_result; - - $length = strlen($string); - $last_char = $string[$length - 1]; - - if ($last_char !== '*') return false; - - $int = substr($string, 0, $length - 1); - - if ($int == '') return '*'; - if (!is_numeric($int)) return false; - - $int = (int) $int; - - if ($int < 0) return false; - if ($int == 0) return '0'; - if ($int == 1) return '*'; - return ((string) $int) . '*'; - - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/HTML/Nmtokens.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/HTML/Nmtokens.php deleted file mode 100644 index 8aa8c58d..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/HTML/Nmtokens.php +++ /dev/null @@ -1,52 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Validates contents based on NMTOKENS attribute type. - */ -class HTMLPurifier_AttrDef_HTML_Nmtokens extends HTMLPurifier_AttrDef -{ - - public function validate($string, $config, $context) { - - $string = trim($string); - - // early abort: '' and '0' (strings that convert to false) are invalid - if (!$string) return false; - - $tokens = $this->split($string, $config, $context); - $tokens = $this->filter($tokens, $config, $context); - if (empty($tokens)) return false; - return implode(' ', $tokens); - - } - - /** - * Splits a space separated list of tokens into its constituent parts. - */ - protected function split($string, $config, $context) { - // OPTIMIZABLE! - // do the preg_match, capture all subpatterns for reformulation - - // we don't support U+00A1 and up codepoints or - // escaping because I don't know how to do that with regexps - // and plus it would complicate optimization efforts (you never - // see that anyway). - $pattern = '/(?:(?<=\s)|\A)'. // look behind for space or string start - '((?:--|-?[A-Za-z_])[A-Za-z_\-0-9]*)'. - '(?:(?=\s)|\z)/'; // look ahead for space or string end - preg_match_all($pattern, $string, $matches); - return $matches[1]; - } - - /** - * Template method for removing certain tokens based on arbitrary criteria. - * @note If we wanted to be really functional, we'd do an array_filter - * with a callback. But... we're not. - */ - protected function filter($tokens, $config, $context) { - return $tokens; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/HTML/Pixels.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/HTML/Pixels.php deleted file mode 100644 index 93f08341..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/HTML/Pixels.php +++ /dev/null @@ -1,48 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Validates an integer representation of pixels according to the HTML spec. - */ -class HTMLPurifier_AttrDef_HTML_Pixels extends HTMLPurifier_AttrDef -{ - - protected $max; - - public function __construct($max = null) { - $this->max = $max; - } - - public function validate($string, $config, $context) { - - $string = trim($string); - if ($string === '0') return $string; - if ($string === '') return false; - $length = strlen($string); - if (substr($string, $length - 2) == 'px') { - $string = substr($string, 0, $length - 2); - } - if (!is_numeric($string)) return false; - $int = (int) $string; - - if ($int < 0) return '0'; - - // upper-bound value, extremely high values can - // crash operating systems, see <http://ha.ckers.org/imagecrash.html> - // WARNING, above link WILL crash you if you're using Windows - - if ($this->max !== null && $int > $this->max) return (string) $this->max; - - return (string) $int; - - } - - public function make($string) { - if ($string === '') $max = null; - else $max = (int) $string; - $class = get_class($this); - return new $class($max); - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/Integer.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/Integer.php deleted file mode 100644 index 12671cdc..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/Integer.php +++ /dev/null @@ -1,73 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Validates an integer. - * @note While this class was modeled off the CSS definition, no currently - * allowed CSS uses this type. The properties that do are: widows, - * orphans, z-index, counter-increment, counter-reset. Some of the - * HTML attributes, however, find use for a non-negative version of this. - */ -class HTMLPurifier_AttrDef_Integer extends HTMLPurifier_AttrDef -{ - - /** - * Bool indicating whether or not negative values are allowed - */ - protected $negative = true; - - /** - * Bool indicating whether or not zero is allowed - */ - protected $zero = true; - - /** - * Bool indicating whether or not positive values are allowed - */ - protected $positive = true; - - /** - * @param $negative Bool indicating whether or not negative values are allowed - * @param $zero Bool indicating whether or not zero is allowed - * @param $positive Bool indicating whether or not positive values are allowed - */ - public function __construct( - $negative = true, $zero = true, $positive = true - ) { - $this->negative = $negative; - $this->zero = $zero; - $this->positive = $positive; - } - - public function validate($integer, $config, $context) { - - $integer = $this->parseCDATA($integer); - if ($integer === '') return false; - - // we could possibly simply typecast it to integer, but there are - // certain fringe cases that must not return an integer. - - // clip leading sign - if ( $this->negative && $integer[0] === '-' ) { - $digits = substr($integer, 1); - if ($digits === '0') $integer = '0'; // rm minus sign for zero - } elseif( $this->positive && $integer[0] === '+' ) { - $digits = $integer = substr($integer, 1); // rm unnecessary plus - } else { - $digits = $integer; - } - - // test if it's numeric - if (!ctype_digit($digits)) return false; - - // perform scope tests - if (!$this->zero && $integer == 0) return false; - if (!$this->positive && $integer > 0) return false; - if (!$this->negative && $integer < 0) return false; - - return $integer; - - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/Lang.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/Lang.php deleted file mode 100644 index 9257476f..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/Lang.php +++ /dev/null @@ -1,73 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Validates the HTML attribute lang, effectively a language code. - * @note Built according to RFC 3066, which obsoleted RFC 1766 - */ -class HTMLPurifier_AttrDef_Lang extends HTMLPurifier_AttrDef -{ - - public function validate($string, $config, $context) { - - $string = trim($string); - if (!$string) return false; - - $subtags = explode('-', $string); - $num_subtags = count($subtags); - - if ($num_subtags == 0) return false; // sanity check - - // process primary subtag : $subtags[0] - $length = strlen($subtags[0]); - switch ($length) { - case 0: - return false; - case 1: - if (! ($subtags[0] == 'x' || $subtags[0] == 'i') ) { - return false; - } - break; - case 2: - case 3: - if (! ctype_alpha($subtags[0]) ) { - return false; - } elseif (! ctype_lower($subtags[0]) ) { - $subtags[0] = strtolower($subtags[0]); - } - break; - default: - return false; - } - - $new_string = $subtags[0]; - if ($num_subtags == 1) return $new_string; - - // process second subtag : $subtags[1] - $length = strlen($subtags[1]); - if ($length == 0 || ($length == 1 && $subtags[1] != 'x') || $length > 8 || !ctype_alnum($subtags[1])) { - return $new_string; - } - if (!ctype_lower($subtags[1])) $subtags[1] = strtolower($subtags[1]); - - $new_string .= '-' . $subtags[1]; - if ($num_subtags == 2) return $new_string; - - // process all other subtags, index 2 and up - for ($i = 2; $i < $num_subtags; $i++) { - $length = strlen($subtags[$i]); - if ($length == 0 || $length > 8 || !ctype_alnum($subtags[$i])) { - return $new_string; - } - if (!ctype_lower($subtags[$i])) { - $subtags[$i] = strtolower($subtags[$i]); - } - $new_string .= '-' . $subtags[$i]; - } - - return $new_string; - - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/Switch.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/Switch.php deleted file mode 100644 index f990931f..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/Switch.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Decorator that, depending on a token, switches between two definitions. - */ -class HTMLPurifier_AttrDef_Switch -{ - - protected $tag; - protected $withTag, $withoutTag; - - /** - * @param string $tag Tag name to switch upon - * @param HTMLPurifier_AttrDef $with_tag Call if token matches tag - * @param HTMLPurifier_AttrDef $without_tag Call if token doesn't match, or there is no token - */ - public function __construct($tag, $with_tag, $without_tag) { - $this->tag = $tag; - $this->withTag = $with_tag; - $this->withoutTag = $without_tag; - } - - public function validate($string, $config, $context) { - $token = $context->get('CurrentToken', true); - if (!$token || $token->name !== $this->tag) { - return $this->withoutTag->validate($string, $config, $context); - } else { - return $this->withTag->validate($string, $config, $context); - } - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/Text.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/Text.php deleted file mode 100644 index fc21e656..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/Text.php +++ /dev/null @@ -1,15 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Validates arbitrary text according to the HTML spec. - */ -class HTMLPurifier_AttrDef_Text extends HTMLPurifier_AttrDef -{ - - public function validate($string, $config, $context) { - return $this->parseCDATA($string); - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/URI.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/URI.php deleted file mode 100644 index 8b9b61c8..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/URI.php +++ /dev/null @@ -1,77 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Validates a URI as defined by RFC 3986. - * @note Scheme-specific mechanics deferred to HTMLPurifier_URIScheme - */ -class HTMLPurifier_AttrDef_URI extends HTMLPurifier_AttrDef -{ - - protected $parser; - protected $embedsResource; - - /** - * @param $embeds_resource_resource Does the URI here result in an extra HTTP request? - */ - public function __construct($embeds_resource = false) { - $this->parser = new HTMLPurifier_URIParser(); - $this->embedsResource = (bool) $embeds_resource; - } - - public function make($string) { - $embeds = (bool) $string; - return new HTMLPurifier_AttrDef_URI($embeds); - } - - public function validate($uri, $config, $context) { - - if ($config->get('URI.Disable')) return false; - - $uri = $this->parseCDATA($uri); - - // parse the URI - $uri = $this->parser->parse($uri); - if ($uri === false) return false; - - // add embedded flag to context for validators - $context->register('EmbeddedURI', $this->embedsResource); - - $ok = false; - do { - - // generic validation - $result = $uri->validate($config, $context); - if (!$result) break; - - // chained filtering - $uri_def = $config->getDefinition('URI'); - $result = $uri_def->filter($uri, $config, $context); - if (!$result) break; - - // scheme-specific validation - $scheme_obj = $uri->getSchemeObj($config, $context); - if (!$scheme_obj) break; - if ($this->embedsResource && !$scheme_obj->browsable) break; - $result = $scheme_obj->validate($uri, $config, $context); - if (!$result) break; - - // Post chained filtering - $result = $uri_def->postFilter($uri, $config, $context); - if (!$result) break; - - // survived gauntlet - $ok = true; - - } while (false); - - $context->destroy('EmbeddedURI'); - if (!$ok) return false; - - // back to string - return $uri->toString(); - - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/URI/Email.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/URI/Email.php deleted file mode 100644 index da4324fa..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/URI/Email.php +++ /dev/null @@ -1,17 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -abstract class HTMLPurifier_AttrDef_URI_Email extends HTMLPurifier_AttrDef -{ - - /** - * Unpacks a mailbox into its display-name and address - */ - function unpack($string) { - // needs to be implemented - } - -} - -// sub-implementations - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/URI/Email/SimpleCheck.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/URI/Email/SimpleCheck.php deleted file mode 100644 index 045613c6..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/URI/Email/SimpleCheck.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Primitive email validation class based on the regexp found at - * http://www.regular-expressions.info/email.html - */ -class HTMLPurifier_AttrDef_URI_Email_SimpleCheck extends HTMLPurifier_AttrDef_URI_Email -{ - - public function validate($string, $config, $context) { - // no support for named mailboxes i.e. "Bob <bob@example.com>" - // that needs more percent encoding to be done - if ($string == '') return false; - $string = trim($string); - $result = preg_match('/^[A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i', $string); - return $result ? $string : false; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/URI/Host.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/URI/Host.php deleted file mode 100644 index 69373559..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/URI/Host.php +++ /dev/null @@ -1,62 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Validates a host according to the IPv4, IPv6 and DNS (future) specifications. - */ -class HTMLPurifier_AttrDef_URI_Host extends HTMLPurifier_AttrDef -{ - - /** - * Instance of HTMLPurifier_AttrDef_URI_IPv4 sub-validator - */ - protected $ipv4; - - /** - * Instance of HTMLPurifier_AttrDef_URI_IPv6 sub-validator - */ - protected $ipv6; - - public function __construct() { - $this->ipv4 = new HTMLPurifier_AttrDef_URI_IPv4(); - $this->ipv6 = new HTMLPurifier_AttrDef_URI_IPv6(); - } - - public function validate($string, $config, $context) { - $length = strlen($string); - if ($string === '') return ''; - if ($length > 1 && $string[0] === '[' && $string[$length-1] === ']') { - //IPv6 - $ip = substr($string, 1, $length - 2); - $valid = $this->ipv6->validate($ip, $config, $context); - if ($valid === false) return false; - return '['. $valid . ']'; - } - - // need to do checks on unusual encodings too - $ipv4 = $this->ipv4->validate($string, $config, $context); - if ($ipv4 !== false) return $ipv4; - - // A regular domain name. - - // This breaks I18N domain names, but we don't have proper IRI support, - // so force users to insert Punycode. If there's complaining we'll - // try to fix things into an international friendly form. - - // The productions describing this are: - $a = '[a-z]'; // alpha - $an = '[a-z0-9]'; // alphanum - $and = '[a-z0-9-]'; // alphanum | "-" - // domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum - $domainlabel = "$an($and*$an)?"; - // toplabel = alpha | alpha *( alphanum | "-" ) alphanum - $toplabel = "$a($and*$an)?"; - // hostname = *( domainlabel "." ) toplabel [ "." ] - $match = preg_match("/^($domainlabel\.)*$toplabel\.?$/i", $string); - if (!$match) return false; - - return $string; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/URI/IPv4.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/URI/IPv4.php deleted file mode 100644 index 996e5be6..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/URI/IPv4.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Validates an IPv4 address - * @author Feyd @ forums.devnetwork.net (public domain) - */ -class HTMLPurifier_AttrDef_URI_IPv4 extends HTMLPurifier_AttrDef -{ - - /** - * IPv4 regex, protected so that IPv6 can reuse it - */ - protected $ip4; - - public function validate($aIP, $config, $context) { - - if (!$this->ip4) $this->_loadRegex(); - - if (preg_match('#^' . $this->ip4 . '$#s', $aIP)) - { - return $aIP; - } - - return false; - - } - - /** - * Lazy load function to prevent regex from being stuffed in - * cache. - */ - protected function _loadRegex() { - $oct = '(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])'; // 0-255 - $this->ip4 = "(?:{$oct}\\.{$oct}\\.{$oct}\\.{$oct})"; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/URI/IPv6.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/URI/IPv6.php deleted file mode 100644 index a4cf60f6..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrDef/URI/IPv6.php +++ /dev/null @@ -1,99 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Validates an IPv6 address. - * @author Feyd @ forums.devnetwork.net (public domain) - * @note This function requires brackets to have been removed from address - * in URI. - */ -class HTMLPurifier_AttrDef_URI_IPv6 extends HTMLPurifier_AttrDef_URI_IPv4 -{ - - public function validate($aIP, $config, $context) { - - if (!$this->ip4) $this->_loadRegex(); - - $original = $aIP; - - $hex = '[0-9a-fA-F]'; - $blk = '(?:' . $hex . '{1,4})'; - $pre = '(?:/(?:12[0-8]|1[0-1][0-9]|[1-9][0-9]|[0-9]))'; // /0 - /128 - - // prefix check - if (strpos($aIP, '/') !== false) - { - if (preg_match('#' . $pre . '$#s', $aIP, $find)) - { - $aIP = substr($aIP, 0, 0-strlen($find[0])); - unset($find); - } - else - { - return false; - } - } - - // IPv4-compatiblity check - if (preg_match('#(?<=:'.')' . $this->ip4 . '$#s', $aIP, $find)) - { - $aIP = substr($aIP, 0, 0-strlen($find[0])); - $ip = explode('.', $find[0]); - $ip = array_map('dechex', $ip); - $aIP .= $ip[0] . $ip[1] . ':' . $ip[2] . $ip[3]; - unset($find, $ip); - } - - // compression check - $aIP = explode('::', $aIP); - $c = count($aIP); - if ($c > 2) - { - return false; - } - elseif ($c == 2) - { - list($first, $second) = $aIP; - $first = explode(':', $first); - $second = explode(':', $second); - - if (count($first) + count($second) > 8) - { - return false; - } - - while(count($first) < 8) - { - array_push($first, '0'); - } - - array_splice($first, 8 - count($second), 8, $second); - $aIP = $first; - unset($first,$second); - } - else - { - $aIP = explode(':', $aIP[0]); - } - $c = count($aIP); - - if ($c != 8) - { - return false; - } - - // All the pieces should be 16-bit hex strings. Are they? - foreach ($aIP as $piece) - { - if (!preg_match('#^[0-9a-fA-F]{4}$#s', sprintf('%04s', $piece))) - { - return false; - } - } - - return $original; - - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform.php deleted file mode 100644 index d8c24663..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform.php +++ /dev/null @@ -1,56 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Processes an entire attribute array for corrections needing multiple values. - * - * Occasionally, a certain attribute will need to be removed and popped onto - * another value. Instead of creating a complex return syntax for - * HTMLPurifier_AttrDef, we just pass the whole attribute array to a - * specialized object and have that do the special work. That is the - * family of HTMLPurifier_AttrTransform. - * - * An attribute transformation can be assigned to run before or after - * HTMLPurifier_AttrDef validation. See HTMLPurifier_HTMLDefinition for - * more details. - */ - -abstract class HTMLPurifier_AttrTransform -{ - - /** - * Abstract: makes changes to the attributes dependent on multiple values. - * - * @param $attr Assoc array of attributes, usually from - * HTMLPurifier_Token_Tag::$attr - * @param $config Mandatory HTMLPurifier_Config object. - * @param $context Mandatory HTMLPurifier_Context object - * @returns Processed attribute array. - */ - abstract public function transform($attr, $config, $context); - - /** - * Prepends CSS properties to the style attribute, creating the - * attribute if it doesn't exist. - * @param $attr Attribute array to process (passed by reference) - * @param $css CSS to prepend - */ - public function prependCSS(&$attr, $css) { - $attr['style'] = isset($attr['style']) ? $attr['style'] : ''; - $attr['style'] = $css . $attr['style']; - } - - /** - * Retrieves and removes an attribute - * @param $attr Attribute array to process (passed by reference) - * @param $key Key of attribute to confiscate - */ - public function confiscateAttr(&$attr, $key) { - if (!isset($attr[$key])) return null; - $value = $attr[$key]; - unset($attr[$key]); - return $value; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/Background.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/Background.php deleted file mode 100644 index dcac7c2d..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/Background.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Pre-transform that changes proprietary background attribute to CSS. - */ -class HTMLPurifier_AttrTransform_Background extends HTMLPurifier_AttrTransform { - - public function transform($attr, $config, $context) { - - if (!isset($attr['background'])) return $attr; - - $background = $this->confiscateAttr($attr, 'background'); - // some validation should happen here - - $this->prependCSS($attr, "background-image:url($background);"); - - return $attr; - - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/BdoDir.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/BdoDir.php deleted file mode 100644 index ade24fdc..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/BdoDir.php +++ /dev/null @@ -1,19 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -// this MUST be placed in post, as it assumes that any value in dir is valid - -/** - * Post-trasnform that ensures that bdo tags have the dir attribute set. - */ -class HTMLPurifier_AttrTransform_BdoDir extends HTMLPurifier_AttrTransform -{ - - public function transform($attr, $config, $context) { - if (isset($attr['dir'])) return $attr; - $attr['dir'] = $config->get('Attr.DefaultTextDir'); - return $attr; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/BgColor.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/BgColor.php deleted file mode 100644 index 9d759fb4..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/BgColor.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Pre-transform that changes deprecated bgcolor attribute to CSS. - */ -class HTMLPurifier_AttrTransform_BgColor extends HTMLPurifier_AttrTransform { - - public function transform($attr, $config, $context) { - - if (!isset($attr['bgcolor'])) return $attr; - - $bgcolor = $this->confiscateAttr($attr, 'bgcolor'); - // some validation should happen here - - $this->prependCSS($attr, "background-color:$bgcolor;"); - - return $attr; - - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/BoolToCSS.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/BoolToCSS.php deleted file mode 100644 index d8ee2ece..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/BoolToCSS.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Pre-transform that changes converts a boolean attribute to fixed CSS - */ -class HTMLPurifier_AttrTransform_BoolToCSS extends HTMLPurifier_AttrTransform { - - /** - * Name of boolean attribute that is trigger - */ - protected $attr; - - /** - * CSS declarations to add to style, needs trailing semicolon - */ - protected $css; - - /** - * @param $attr string attribute name to convert from - * @param $css string CSS declarations to add to style (needs semicolon) - */ - public function __construct($attr, $css) { - $this->attr = $attr; - $this->css = $css; - } - - public function transform($attr, $config, $context) { - if (!isset($attr[$this->attr])) return $attr; - unset($attr[$this->attr]); - $this->prependCSS($attr, $this->css); - return $attr; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/Border.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/Border.php deleted file mode 100644 index 7909249e..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/Border.php +++ /dev/null @@ -1,18 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Pre-transform that changes deprecated border attribute to CSS. - */ -class HTMLPurifier_AttrTransform_Border extends HTMLPurifier_AttrTransform { - - public function transform($attr, $config, $context) { - if (!isset($attr['border'])) return $attr; - $border_width = $this->confiscateAttr($attr, 'border'); - // some validation should happen here - $this->prependCSS($attr, "border:{$border_width}px solid;"); - return $attr; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/EnumToCSS.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/EnumToCSS.php deleted file mode 100644 index 12c77264..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/EnumToCSS.php +++ /dev/null @@ -1,58 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Generic pre-transform that converts an attribute with a fixed number of - * values (enumerated) to CSS. - */ -class HTMLPurifier_AttrTransform_EnumToCSS extends HTMLPurifier_AttrTransform { - - /** - * Name of attribute to transform from - */ - protected $attr; - - /** - * Lookup array of attribute values to CSS - */ - protected $enumToCSS = array(); - - /** - * Case sensitivity of the matching - * @warning Currently can only be guaranteed to work with ASCII - * values. - */ - protected $caseSensitive = false; - - /** - * @param $attr String attribute name to transform from - * @param $enumToCSS Lookup array of attribute values to CSS - * @param $case_sensitive Boolean case sensitivity indicator, default false - */ - public function __construct($attr, $enum_to_css, $case_sensitive = false) { - $this->attr = $attr; - $this->enumToCSS = $enum_to_css; - $this->caseSensitive = (bool) $case_sensitive; - } - - public function transform($attr, $config, $context) { - - if (!isset($attr[$this->attr])) return $attr; - - $value = trim($attr[$this->attr]); - unset($attr[$this->attr]); - - if (!$this->caseSensitive) $value = strtolower($value); - - if (!isset($this->enumToCSS[$value])) { - return $attr; - } - - $this->prependCSS($attr, $this->enumToCSS[$value]); - - return $attr; - - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/ImgRequired.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/ImgRequired.php deleted file mode 100644 index a1e5a83a..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/ImgRequired.php +++ /dev/null @@ -1,42 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -// must be called POST validation - -/** - * Transform that supplies default values for the src and alt attributes - * in img tags, as well as prevents the img tag from being removed - * because of a missing alt tag. This needs to be registered as both - * a pre and post attribute transform. - */ -class HTMLPurifier_AttrTransform_ImgRequired extends HTMLPurifier_AttrTransform -{ - - public function transform($attr, $config, $context) { - - $src = true; - if (!isset($attr['src'])) { - if ($config->get('Core.RemoveInvalidImg')) return $attr; - $attr['src'] = $config->get('Attr.DefaultInvalidImage'); - $src = false; - } - - if (!isset($attr['alt'])) { - if ($src) { - $alt = $config->get('Attr.DefaultImageAlt'); - if ($alt === null) { - $attr['alt'] = basename($attr['src']); - } else { - $attr['alt'] = $alt; - } - } else { - $attr['alt'] = $config->get('Attr.DefaultInvalidImageAlt'); - } - } - - return $attr; - - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/ImgSpace.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/ImgSpace.php deleted file mode 100644 index 571dccf2..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/ImgSpace.php +++ /dev/null @@ -1,44 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Pre-transform that changes deprecated hspace and vspace attributes to CSS - */ -class HTMLPurifier_AttrTransform_ImgSpace extends HTMLPurifier_AttrTransform { - - protected $attr; - protected $css = array( - 'hspace' => array('left', 'right'), - 'vspace' => array('top', 'bottom') - ); - - public function __construct($attr) { - $this->attr = $attr; - if (!isset($this->css[$attr])) { - trigger_error(htmlspecialchars($attr) . ' is not valid space attribute'); - } - } - - public function transform($attr, $config, $context) { - - if (!isset($attr[$this->attr])) return $attr; - - $width = $this->confiscateAttr($attr, $this->attr); - // some validation could happen here - - if (!isset($this->css[$this->attr])) return $attr; - - $style = ''; - foreach ($this->css[$this->attr] as $suffix) { - $property = "margin-$suffix"; - $style .= "$property:{$width}px;"; - } - - $this->prependCSS($attr, $style); - - return $attr; - - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/Input.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/Input.php deleted file mode 100644 index de105bca..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/Input.php +++ /dev/null @@ -1,40 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Performs miscellaneous cross attribute validation and filtering for - * input elements. This is meant to be a post-transform. - */ -class HTMLPurifier_AttrTransform_Input extends HTMLPurifier_AttrTransform { - - protected $pixels; - - public function __construct() { - $this->pixels = new HTMLPurifier_AttrDef_HTML_Pixels(); - } - - public function transform($attr, $config, $context) { - if (!isset($attr['type'])) $t = 'text'; - else $t = strtolower($attr['type']); - if (isset($attr['checked']) && $t !== 'radio' && $t !== 'checkbox') { - unset($attr['checked']); - } - if (isset($attr['maxlength']) && $t !== 'text' && $t !== 'password') { - unset($attr['maxlength']); - } - if (isset($attr['size']) && $t !== 'text' && $t !== 'password') { - $result = $this->pixels->validate($attr['size'], $config, $context); - if ($result === false) unset($attr['size']); - else $attr['size'] = $result; - } - if (isset($attr['src']) && $t !== 'image') { - unset($attr['src']); - } - if (!isset($attr['value']) && ($t === 'radio' || $t === 'checkbox')) { - $attr['value'] = ''; - } - return $attr; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/Lang.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/Lang.php deleted file mode 100644 index 54c9330d..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/Lang.php +++ /dev/null @@ -1,28 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Post-transform that copies lang's value to xml:lang (and vice-versa) - * @note Theoretically speaking, this could be a pre-transform, but putting - * post is more efficient. - */ -class HTMLPurifier_AttrTransform_Lang extends HTMLPurifier_AttrTransform -{ - - public function transform($attr, $config, $context) { - - $lang = isset($attr['lang']) ? $attr['lang'] : false; - $xml_lang = isset($attr['xml:lang']) ? $attr['xml:lang'] : false; - - if ($lang !== false && $xml_lang === false) { - $attr['xml:lang'] = $lang; - } elseif ($xml_lang !== false) { - $attr['lang'] = $xml_lang; - } - - return $attr; - - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/Length.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/Length.php deleted file mode 100644 index fa7c9117..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/Length.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Class for handling width/height length attribute transformations to CSS - */ -class HTMLPurifier_AttrTransform_Length extends HTMLPurifier_AttrTransform -{ - - protected $name; - protected $cssName; - - public function __construct($name, $css_name = null) { - $this->name = $name; - $this->cssName = $css_name ? $css_name : $name; - } - - public function transform($attr, $config, $context) { - if (!isset($attr[$this->name])) return $attr; - $length = $this->confiscateAttr($attr, $this->name); - if(ctype_digit($length)) $length .= 'px'; - $this->prependCSS($attr, $this->cssName . ":$length;"); - return $attr; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/Name.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/Name.php deleted file mode 100644 index e0bf924f..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/Name.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Pre-transform that changes deprecated name attribute to ID if necessary - */ -class HTMLPurifier_AttrTransform_Name extends HTMLPurifier_AttrTransform -{ - - public function transform($attr, $config, $context) { - // Abort early if we're using relaxed definition of name - if ($config->get('HTML.Attr.Name.UseCDATA')) return $attr; - if (!isset($attr['name'])) return $attr; - $id = $this->confiscateAttr($attr, 'name'); - if ( isset($attr['id'])) return $attr; - $attr['id'] = $id; - return $attr; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/NameSync.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/NameSync.php deleted file mode 100644 index 5e60392f..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/NameSync.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Post-transform that performs validation to the name attribute; if - * it is present with an equivalent id attribute, it is passed through; - * otherwise validation is performed. - */ -class HTMLPurifier_AttrTransform_NameSync extends HTMLPurifier_AttrTransform -{ - - public function __construct() { - $this->idDef = new HTMLPurifier_AttrDef_HTML_ID(); - } - - public function transform($attr, $config, $context) { - if (!isset($attr['name'])) return $attr; - $name = $attr['name']; - if (isset($attr['id']) && $attr['id'] === $name) return $attr; - $result = $this->idDef->validate($name, $config, $context); - if ($result === false) unset($attr['name']); - else $attr['name'] = $result; - return $attr; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/SafeEmbed.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/SafeEmbed.php deleted file mode 100644 index 25d97f20..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/SafeEmbed.php +++ /dev/null @@ -1,15 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -class HTMLPurifier_AttrTransform_SafeEmbed extends HTMLPurifier_AttrTransform -{ - public $name = "SafeEmbed"; - - public function transform($attr, $config, $context) { - $attr['allowscriptaccess'] = 'never'; - $attr['allownetworking'] = 'internal'; - $attr['type'] = 'application/x-shockwave-flash'; - return $attr; - } -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/SafeObject.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/SafeObject.php deleted file mode 100644 index 013e341b..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/SafeObject.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Writes default type for all objects. Currently only supports flash. - */ -class HTMLPurifier_AttrTransform_SafeObject extends HTMLPurifier_AttrTransform -{ - public $name = "SafeObject"; - - function transform($attr, $config, $context) { - if (!isset($attr['type'])) $attr['type'] = 'application/x-shockwave-flash'; - return $attr; - } -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/SafeParam.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/SafeParam.php deleted file mode 100644 index e677feae..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/SafeParam.php +++ /dev/null @@ -1,50 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Validates name/value pairs in param tags to be used in safe objects. This - * will only allow name values it recognizes, and pre-fill certain attributes - * with required values. - * - * @note - * This class only supports Flash. In the future, Quicktime support - * may be added. - * - * @warning - * This class expects an injector to add the necessary parameters tags. - */ -class HTMLPurifier_AttrTransform_SafeParam extends HTMLPurifier_AttrTransform -{ - public $name = "SafeParam"; - private $uri; - - public function __construct() { - $this->uri = new HTMLPurifier_AttrDef_URI(true); // embedded - } - - public function transform($attr, $config, $context) { - // If we add support for other objects, we'll need to alter the - // transforms. - switch ($attr['name']) { - // application/x-shockwave-flash - // Keep this synchronized with Injector/SafeObject.php - case 'allowScriptAccess': - $attr['value'] = 'never'; - break; - case 'allowNetworking': - $attr['value'] = 'internal'; - break; - case 'wmode': - $attr['value'] = 'window'; - break; - case 'movie': - $attr['value'] = $this->uri->validate($attr['value'], $config, $context); - break; - // add other cases to support other param name/value pairs - default: - $attr['name'] = $attr['value'] = null; - } - return $attr; - } -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/ScriptRequired.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/ScriptRequired.php deleted file mode 100644 index 9a659780..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/ScriptRequired.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Implements required attribute stipulation for <script> - */ -class HTMLPurifier_AttrTransform_ScriptRequired extends HTMLPurifier_AttrTransform -{ - public function transform($attr, $config, $context) { - if (!isset($attr['type'])) { - $attr['type'] = 'text/javascript'; - } - return $attr; - } -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/Textarea.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/Textarea.php deleted file mode 100644 index e1b632fb..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTransform/Textarea.php +++ /dev/null @@ -1,18 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Sets height/width defaults for <textarea> - */ -class HTMLPurifier_AttrTransform_Textarea extends HTMLPurifier_AttrTransform -{ - - public function transform($attr, $config, $context) { - // Calculated from Firefox - if (!isset($attr['cols'])) $attr['cols'] = '22'; - if (!isset($attr['rows'])) $attr['rows'] = '3'; - return $attr; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTypes.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTypes.php deleted file mode 100644 index 347d18a2..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrTypes.php +++ /dev/null @@ -1,77 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Provides lookup array of attribute types to HTMLPurifier_AttrDef objects - */ -class HTMLPurifier_AttrTypes -{ - /** - * Lookup array of attribute string identifiers to concrete implementations - */ - protected $info = array(); - - /** - * Constructs the info array, supplying default implementations for attribute - * types. - */ - public function __construct() { - // pseudo-types, must be instantiated via shorthand - $this->info['Enum'] = new HTMLPurifier_AttrDef_Enum(); - $this->info['Bool'] = new HTMLPurifier_AttrDef_HTML_Bool(); - - $this->info['CDATA'] = new HTMLPurifier_AttrDef_Text(); - $this->info['ID'] = new HTMLPurifier_AttrDef_HTML_ID(); - $this->info['Length'] = new HTMLPurifier_AttrDef_HTML_Length(); - $this->info['MultiLength'] = new HTMLPurifier_AttrDef_HTML_MultiLength(); - $this->info['NMTOKENS'] = new HTMLPurifier_AttrDef_HTML_Nmtokens(); - $this->info['Pixels'] = new HTMLPurifier_AttrDef_HTML_Pixels(); - $this->info['Text'] = new HTMLPurifier_AttrDef_Text(); - $this->info['URI'] = new HTMLPurifier_AttrDef_URI(); - $this->info['LanguageCode'] = new HTMLPurifier_AttrDef_Lang(); - $this->info['Color'] = new HTMLPurifier_AttrDef_HTML_Color(); - - // unimplemented aliases - $this->info['ContentType'] = new HTMLPurifier_AttrDef_Text(); - $this->info['ContentTypes'] = new HTMLPurifier_AttrDef_Text(); - $this->info['Charsets'] = new HTMLPurifier_AttrDef_Text(); - $this->info['Character'] = new HTMLPurifier_AttrDef_Text(); - - // "proprietary" types - $this->info['Class'] = new HTMLPurifier_AttrDef_HTML_Class(); - - // number is really a positive integer (one or more digits) - // FIXME: ^^ not always, see start and value of list items - $this->info['Number'] = new HTMLPurifier_AttrDef_Integer(false, false, true); - } - - /** - * Retrieves a type - * @param $type String type name - * @return Object AttrDef for type - */ - public function get($type) { - - // determine if there is any extra info tacked on - if (strpos($type, '#') !== false) list($type, $string) = explode('#', $type, 2); - else $string = ''; - - if (!isset($this->info[$type])) { - trigger_error('Cannot retrieve undefined attribute type ' . $type, E_USER_ERROR); - return; - } - - return $this->info[$type]->make($string); - - } - - /** - * Sets a new implementation for a type - * @param $type String type name - * @param $impl Object AttrDef for type - */ - public function set($type, $impl) { - $this->info[$type] = $impl; - } -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrValidator.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrValidator.php deleted file mode 100644 index d5a01770..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/AttrValidator.php +++ /dev/null @@ -1,162 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Validates the attributes of a token. Doesn't manage required attributes - * very well. The only reason we factored this out was because RemoveForeignElements - * also needed it besides ValidateAttributes. - */ -class HTMLPurifier_AttrValidator -{ - - /** - * Validates the attributes of a token, returning a modified token - * that has valid tokens - * @param $token Reference to token to validate. We require a reference - * because the operation this class performs on the token are - * not atomic, so the context CurrentToken to be updated - * throughout - * @param $config Instance of HTMLPurifier_Config - * @param $context Instance of HTMLPurifier_Context - */ - public function validateToken(&$token, &$config, $context) { - - $definition = $config->getHTMLDefinition(); - $e =& $context->get('ErrorCollector', true); - - // initialize IDAccumulator if necessary - $ok =& $context->get('IDAccumulator', true); - if (!$ok) { - $id_accumulator = HTMLPurifier_IDAccumulator::build($config, $context); - $context->register('IDAccumulator', $id_accumulator); - } - - // initialize CurrentToken if necessary - $current_token =& $context->get('CurrentToken', true); - if (!$current_token) $context->register('CurrentToken', $token); - - if ( - !$token instanceof HTMLPurifier_Token_Start && - !$token instanceof HTMLPurifier_Token_Empty - ) return $token; - - // create alias to global definition array, see also $defs - // DEFINITION CALL - $d_defs = $definition->info_global_attr; - - // don't update token until the very end, to ensure an atomic update - $attr = $token->attr; - - // do global transformations (pre) - // nothing currently utilizes this - foreach ($definition->info_attr_transform_pre as $transform) { - $attr = $transform->transform($o = $attr, $config, $context); - if ($e) { - if ($attr != $o) $e->send(E_NOTICE, 'AttrValidator: Attributes transformed', $o, $attr); - } - } - - // do local transformations only applicable to this element (pre) - // ex. <p align="right"> to <p style="text-align:right;"> - foreach ($definition->info[$token->name]->attr_transform_pre as $transform) { - $attr = $transform->transform($o = $attr, $config, $context); - if ($e) { - if ($attr != $o) $e->send(E_NOTICE, 'AttrValidator: Attributes transformed', $o, $attr); - } - } - - // create alias to this element's attribute definition array, see - // also $d_defs (global attribute definition array) - // DEFINITION CALL - $defs = $definition->info[$token->name]->attr; - - $attr_key = false; - $context->register('CurrentAttr', $attr_key); - - // iterate through all the attribute keypairs - // Watch out for name collisions: $key has previously been used - foreach ($attr as $attr_key => $value) { - - // call the definition - if ( isset($defs[$attr_key]) ) { - // there is a local definition defined - if ($defs[$attr_key] === false) { - // We've explicitly been told not to allow this element. - // This is usually when there's a global definition - // that must be overridden. - // Theoretically speaking, we could have a - // AttrDef_DenyAll, but this is faster! - $result = false; - } else { - // validate according to the element's definition - $result = $defs[$attr_key]->validate( - $value, $config, $context - ); - } - } elseif ( isset($d_defs[$attr_key]) ) { - // there is a global definition defined, validate according - // to the global definition - $result = $d_defs[$attr_key]->validate( - $value, $config, $context - ); - } else { - // system never heard of the attribute? DELETE! - $result = false; - } - - // put the results into effect - if ($result === false || $result === null) { - // this is a generic error message that should replaced - // with more specific ones when possible - if ($e) $e->send(E_ERROR, 'AttrValidator: Attribute removed'); - - // remove the attribute - unset($attr[$attr_key]); - } elseif (is_string($result)) { - // generally, if a substitution is happening, there - // was some sort of implicit correction going on. We'll - // delegate it to the attribute classes to say exactly what. - - // simple substitution - $attr[$attr_key] = $result; - } else { - // nothing happens - } - - // we'd also want slightly more complicated substitution - // involving an array as the return value, - // although we're not sure how colliding attributes would - // resolve (certain ones would be completely overriden, - // others would prepend themselves). - } - - $context->destroy('CurrentAttr'); - - // post transforms - - // global (error reporting untested) - foreach ($definition->info_attr_transform_post as $transform) { - $attr = $transform->transform($o = $attr, $config, $context); - if ($e) { - if ($attr != $o) $e->send(E_NOTICE, 'AttrValidator: Attributes transformed', $o, $attr); - } - } - - // local (error reporting untested) - foreach ($definition->info[$token->name]->attr_transform_post as $transform) { - $attr = $transform->transform($o = $attr, $config, $context); - if ($e) { - if ($attr != $o) $e->send(E_NOTICE, 'AttrValidator: Attributes transformed', $o, $attr); - } - } - - $token->attr = $attr; - - // destroy CurrentToken if we made it ourselves - if (!$current_token) $context->destroy('CurrentToken'); - - } - - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Bootstrap.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Bootstrap.php deleted file mode 100644 index 5963fd94..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Bootstrap.php +++ /dev/null @@ -1,98 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -// constants are slow, so we use as few as possible -if (!defined('HTMLPURIFIER_PREFIX')) { - define('HTMLPURIFIER_PREFIX', realpath(dirname(__FILE__) . '/..')); -} - -// accomodations for versions earlier than 5.0.2 -// borrowed from PHP_Compat, LGPL licensed, by Aidan Lister <aidan@php.net> -if (!defined('PHP_EOL')) { - switch (strtoupper(substr(PHP_OS, 0, 3))) { - case 'WIN': - define('PHP_EOL', "\r\n"); - break; - case 'DAR': - define('PHP_EOL', "\r"); - break; - default: - define('PHP_EOL', "\n"); - } -} - -/** - * Bootstrap class that contains meta-functionality for HTML Purifier such as - * the autoload function. - * - * @note - * This class may be used without any other files from HTML Purifier. - */ -class HTMLPurifier_Bootstrap -{ - - /** - * Autoload function for HTML Purifier - * @param $class Class to load - */ - public static function autoload($class) { - $file = HTMLPurifier_Bootstrap::getPath($class); - if (!$file) return false; - require HTMLPURIFIER_PREFIX . '/' . $file; - return true; - } - - /** - * Returns the path for a specific class. - */ - public static function getPath($class) { - if (strncmp('HTMLPurifier', $class, 12) !== 0) return false; - // Custom implementations - if (strncmp('HTMLPurifier_Language_', $class, 22) === 0) { - $code = str_replace('_', '-', substr($class, 22)); - $file = 'HTMLPurifier/Language/classes/' . $code . '.php'; - } else { - $file = str_replace('_', '/', $class) . '.php'; - } - if (!file_exists(HTMLPURIFIER_PREFIX . '/' . $file)) return false; - return $file; - } - - /** - * "Pre-registers" our autoloader on the SPL stack. - */ - public static function registerAutoload() { - $autoload = array('HTMLPurifier_Bootstrap', 'autoload'); - if ( ($funcs = spl_autoload_functions()) === false ) { - spl_autoload_register($autoload); - } elseif (function_exists('spl_autoload_unregister')) { - $compat = version_compare(PHP_VERSION, '5.1.2', '<=') && - version_compare(PHP_VERSION, '5.1.0', '>='); - foreach ($funcs as $func) { - if (is_array($func)) { - // :TRICKY: There are some compatibility issues and some - // places where we need to error out - $reflector = new ReflectionMethod($func[0], $func[1]); - if (!$reflector->isStatic()) { - throw new Exception(' - HTML Purifier autoloader registrar is not compatible - with non-static object methods due to PHP Bug #44144; - Please do not use HTMLPurifier.autoload.php (or any - file that includes this file); instead, place the code: - spl_autoload_register(array(\'HTMLPurifier_Bootstrap\', \'autoload\')) - after your own autoloaders. - '); - } - // Suprisingly, spl_autoload_register supports the - // Class::staticMethod callback format, although call_user_func doesn't - if ($compat) $func = implode('::', $func); - } - spl_autoload_unregister($func); - } - spl_autoload_register($autoload); - foreach ($funcs as $func) spl_autoload_register($func); - } - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/CSSDefinition.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/CSSDefinition.php deleted file mode 100644 index 17bf9931..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/CSSDefinition.php +++ /dev/null @@ -1,292 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Defines allowed CSS attributes and what their values are. - * @see HTMLPurifier_HTMLDefinition - */ -class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition -{ - - public $type = 'CSS'; - - /** - * Assoc array of attribute name to definition object. - */ - public $info = array(); - - /** - * Constructs the info array. The meat of this class. - */ - protected function doSetup($config) { - - $this->info['text-align'] = new HTMLPurifier_AttrDef_Enum( - array('left', 'right', 'center', 'justify'), false); - - $border_style = - $this->info['border-bottom-style'] = - $this->info['border-right-style'] = - $this->info['border-left-style'] = - $this->info['border-top-style'] = new HTMLPurifier_AttrDef_Enum( - array('none', 'hidden', 'dotted', 'dashed', 'solid', 'double', - 'groove', 'ridge', 'inset', 'outset'), false); - - $this->info['border-style'] = new HTMLPurifier_AttrDef_CSS_Multiple($border_style); - - $this->info['clear'] = new HTMLPurifier_AttrDef_Enum( - array('none', 'left', 'right', 'both'), false); - $this->info['float'] = new HTMLPurifier_AttrDef_Enum( - array('none', 'left', 'right'), false); - $this->info['font-style'] = new HTMLPurifier_AttrDef_Enum( - array('normal', 'italic', 'oblique'), false); - $this->info['font-variant'] = new HTMLPurifier_AttrDef_Enum( - array('normal', 'small-caps'), false); - - $uri_or_none = new HTMLPurifier_AttrDef_CSS_Composite( - array( - new HTMLPurifier_AttrDef_Enum(array('none')), - new HTMLPurifier_AttrDef_CSS_URI() - ) - ); - - $this->info['list-style-position'] = new HTMLPurifier_AttrDef_Enum( - array('inside', 'outside'), false); - $this->info['list-style-type'] = new HTMLPurifier_AttrDef_Enum( - array('disc', 'circle', 'square', 'decimal', 'lower-roman', - 'upper-roman', 'lower-alpha', 'upper-alpha', 'none'), false); - $this->info['list-style-image'] = $uri_or_none; - - $this->info['list-style'] = new HTMLPurifier_AttrDef_CSS_ListStyle($config); - - $this->info['text-transform'] = new HTMLPurifier_AttrDef_Enum( - array('capitalize', 'uppercase', 'lowercase', 'none'), false); - $this->info['color'] = new HTMLPurifier_AttrDef_CSS_Color(); - - $this->info['background-image'] = $uri_or_none; - $this->info['background-repeat'] = new HTMLPurifier_AttrDef_Enum( - array('repeat', 'repeat-x', 'repeat-y', 'no-repeat') - ); - $this->info['background-attachment'] = new HTMLPurifier_AttrDef_Enum( - array('scroll', 'fixed') - ); - $this->info['background-position'] = new HTMLPurifier_AttrDef_CSS_BackgroundPosition(); - - $border_color = - $this->info['border-top-color'] = - $this->info['border-bottom-color'] = - $this->info['border-left-color'] = - $this->info['border-right-color'] = - $this->info['background-color'] = new HTMLPurifier_AttrDef_CSS_Composite(array( - new HTMLPurifier_AttrDef_Enum(array('transparent')), - new HTMLPurifier_AttrDef_CSS_Color() - )); - - $this->info['background'] = new HTMLPurifier_AttrDef_CSS_Background($config); - - $this->info['border-color'] = new HTMLPurifier_AttrDef_CSS_Multiple($border_color); - - $border_width = - $this->info['border-top-width'] = - $this->info['border-bottom-width'] = - $this->info['border-left-width'] = - $this->info['border-right-width'] = new HTMLPurifier_AttrDef_CSS_Composite(array( - new HTMLPurifier_AttrDef_Enum(array('thin', 'medium', 'thick')), - new HTMLPurifier_AttrDef_CSS_Length('0') //disallow negative - )); - - $this->info['border-width'] = new HTMLPurifier_AttrDef_CSS_Multiple($border_width); - - $this->info['letter-spacing'] = new HTMLPurifier_AttrDef_CSS_Composite(array( - new HTMLPurifier_AttrDef_Enum(array('normal')), - new HTMLPurifier_AttrDef_CSS_Length() - )); - - $this->info['word-spacing'] = new HTMLPurifier_AttrDef_CSS_Composite(array( - new HTMLPurifier_AttrDef_Enum(array('normal')), - new HTMLPurifier_AttrDef_CSS_Length() - )); - - $this->info['font-size'] = new HTMLPurifier_AttrDef_CSS_Composite(array( - new HTMLPurifier_AttrDef_Enum(array('xx-small', 'x-small', - 'small', 'medium', 'large', 'x-large', 'xx-large', - 'larger', 'smaller')), - new HTMLPurifier_AttrDef_CSS_Percentage(), - new HTMLPurifier_AttrDef_CSS_Length() - )); - - $this->info['line-height'] = new HTMLPurifier_AttrDef_CSS_Composite(array( - new HTMLPurifier_AttrDef_Enum(array('normal')), - new HTMLPurifier_AttrDef_CSS_Number(true), // no negatives - new HTMLPurifier_AttrDef_CSS_Length('0'), - new HTMLPurifier_AttrDef_CSS_Percentage(true) - )); - - $margin = - $this->info['margin-top'] = - $this->info['margin-bottom'] = - $this->info['margin-left'] = - $this->info['margin-right'] = new HTMLPurifier_AttrDef_CSS_Composite(array( - new HTMLPurifier_AttrDef_CSS_Length(), - new HTMLPurifier_AttrDef_CSS_Percentage(), - new HTMLPurifier_AttrDef_Enum(array('auto')) - )); - - $this->info['margin'] = new HTMLPurifier_AttrDef_CSS_Multiple($margin); - - // non-negative - $padding = - $this->info['padding-top'] = - $this->info['padding-bottom'] = - $this->info['padding-left'] = - $this->info['padding-right'] = new HTMLPurifier_AttrDef_CSS_Composite(array( - new HTMLPurifier_AttrDef_CSS_Length('0'), - new HTMLPurifier_AttrDef_CSS_Percentage(true) - )); - - $this->info['padding'] = new HTMLPurifier_AttrDef_CSS_Multiple($padding); - - $this->info['text-indent'] = new HTMLPurifier_AttrDef_CSS_Composite(array( - new HTMLPurifier_AttrDef_CSS_Length(), - new HTMLPurifier_AttrDef_CSS_Percentage() - )); - - $trusted_wh = new HTMLPurifier_AttrDef_CSS_Composite(array( - new HTMLPurifier_AttrDef_CSS_Length('0'), - new HTMLPurifier_AttrDef_CSS_Percentage(true), - new HTMLPurifier_AttrDef_Enum(array('auto')) - )); - $max = $config->get('CSS.MaxImgLength'); - - $this->info['width'] = - $this->info['height'] = - $max === null ? - $trusted_wh : - new HTMLPurifier_AttrDef_Switch('img', - // For img tags: - new HTMLPurifier_AttrDef_CSS_Composite(array( - new HTMLPurifier_AttrDef_CSS_Length('0', $max), - new HTMLPurifier_AttrDef_Enum(array('auto')) - )), - // For everyone else: - $trusted_wh - ); - - $this->info['text-decoration'] = new HTMLPurifier_AttrDef_CSS_TextDecoration(); - - $this->info['font-family'] = new HTMLPurifier_AttrDef_CSS_FontFamily(); - - // this could use specialized code - $this->info['font-weight'] = new HTMLPurifier_AttrDef_Enum( - array('normal', 'bold', 'bolder', 'lighter', '100', '200', '300', - '400', '500', '600', '700', '800', '900'), false); - - // MUST be called after other font properties, as it references - // a CSSDefinition object - $this->info['font'] = new HTMLPurifier_AttrDef_CSS_Font($config); - - // same here - $this->info['border'] = - $this->info['border-bottom'] = - $this->info['border-top'] = - $this->info['border-left'] = - $this->info['border-right'] = new HTMLPurifier_AttrDef_CSS_Border($config); - - $this->info['border-collapse'] = new HTMLPurifier_AttrDef_Enum(array( - 'collapse', 'separate')); - - $this->info['caption-side'] = new HTMLPurifier_AttrDef_Enum(array( - 'top', 'bottom')); - - $this->info['table-layout'] = new HTMLPurifier_AttrDef_Enum(array( - 'auto', 'fixed')); - - $this->info['vertical-align'] = new HTMLPurifier_AttrDef_CSS_Composite(array( - new HTMLPurifier_AttrDef_Enum(array('baseline', 'sub', 'super', - 'top', 'text-top', 'middle', 'bottom', 'text-bottom')), - new HTMLPurifier_AttrDef_CSS_Length(), - new HTMLPurifier_AttrDef_CSS_Percentage() - )); - - $this->info['border-spacing'] = new HTMLPurifier_AttrDef_CSS_Multiple(new HTMLPurifier_AttrDef_CSS_Length(), 2); - - // partial support - $this->info['white-space'] = new HTMLPurifier_AttrDef_Enum(array('nowrap')); - - if ($config->get('CSS.Proprietary')) { - $this->doSetupProprietary($config); - } - - if ($config->get('CSS.AllowTricky')) { - $this->doSetupTricky($config); - } - - $allow_important = $config->get('CSS.AllowImportant'); - // wrap all attr-defs with decorator that handles !important - foreach ($this->info as $k => $v) { - $this->info[$k] = new HTMLPurifier_AttrDef_CSS_ImportantDecorator($v, $allow_important); - } - - $this->setupConfigStuff($config); - } - - protected function doSetupProprietary($config) { - // Internet Explorer only scrollbar colors - $this->info['scrollbar-arrow-color'] = new HTMLPurifier_AttrDef_CSS_Color(); - $this->info['scrollbar-base-color'] = new HTMLPurifier_AttrDef_CSS_Color(); - $this->info['scrollbar-darkshadow-color'] = new HTMLPurifier_AttrDef_CSS_Color(); - $this->info['scrollbar-face-color'] = new HTMLPurifier_AttrDef_CSS_Color(); - $this->info['scrollbar-highlight-color'] = new HTMLPurifier_AttrDef_CSS_Color(); - $this->info['scrollbar-shadow-color'] = new HTMLPurifier_AttrDef_CSS_Color(); - - // technically not proprietary, but CSS3, and no one supports it - $this->info['opacity'] = new HTMLPurifier_AttrDef_CSS_AlphaValue(); - $this->info['-moz-opacity'] = new HTMLPurifier_AttrDef_CSS_AlphaValue(); - $this->info['-khtml-opacity'] = new HTMLPurifier_AttrDef_CSS_AlphaValue(); - - // only opacity, for now - $this->info['filter'] = new HTMLPurifier_AttrDef_CSS_Filter(); - - } - - protected function doSetupTricky($config) { - $this->info['display'] = new HTMLPurifier_AttrDef_Enum(array( - 'inline', 'block', 'list-item', 'run-in', 'compact', - 'marker', 'table', 'inline-table', 'table-row-group', - 'table-header-group', 'table-footer-group', 'table-row', - 'table-column-group', 'table-column', 'table-cell', 'table-caption', 'none' - )); - $this->info['visibility'] = new HTMLPurifier_AttrDef_Enum(array( - 'visible', 'hidden', 'collapse' - )); - $this->info['overflow'] = new HTMLPurifier_AttrDef_Enum(array('visible', 'hidden', 'auto', 'scroll')); - } - - - /** - * Performs extra config-based processing. Based off of - * HTMLPurifier_HTMLDefinition. - * @todo Refactor duplicate elements into common class (probably using - * composition, not inheritance). - */ - protected function setupConfigStuff($config) { - - // setup allowed elements - $support = "(for information on implementing this, see the ". - "support forums) "; - $allowed_attributes = $config->get('CSS.AllowedProperties'); - if ($allowed_attributes !== null) { - foreach ($this->info as $name => $d) { - if(!isset($allowed_attributes[$name])) unset($this->info[$name]); - unset($allowed_attributes[$name]); - } - // emit errors - foreach ($allowed_attributes as $name => $d) { - // :TODO: Is this htmlspecialchars() call really necessary? - $name = htmlspecialchars($name); - trigger_error("Style attribute '$name' is not supported $support", E_USER_WARNING); - } - } - - } -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ChildDef.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ChildDef.php deleted file mode 100644 index 5533012c..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ChildDef.php +++ /dev/null @@ -1,48 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Defines allowed child nodes and validates tokens against it. - */ -abstract class HTMLPurifier_ChildDef -{ - /** - * Type of child definition, usually right-most part of class name lowercase. - * Used occasionally in terms of context. - */ - public $type; - - /** - * Bool that indicates whether or not an empty array of children is okay - * - * This is necessary for redundant checking when changes affecting - * a child node may cause a parent node to now be disallowed. - */ - public $allow_empty; - - /** - * Lookup array of all elements that this definition could possibly allow - */ - public $elements = array(); - - /** - * Get lookup of tag names that should not close this element automatically. - * All other elements will do so. - */ - public function getAllowedElements($config) { - return $this->elements; - } - - /** - * Validates nodes according to definition and returns modification. - * - * @param $tokens_of_children Array of HTMLPurifier_Token - * @param $config HTMLPurifier_Config object - * @param $context HTMLPurifier_Context object - * @return bool true to leave nodes as is - * @return bool false to remove parent node - * @return array of replacement child tokens - */ - abstract public function validateChildren($tokens_of_children, $config, $context); -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ChildDef/Chameleon.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ChildDef/Chameleon.php deleted file mode 100644 index e70d53e8..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ChildDef/Chameleon.php +++ /dev/null @@ -1,48 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Definition that uses different definitions depending on context. - * - * The del and ins tags are notable because they allow different types of - * elements depending on whether or not they're in a block or inline context. - * Chameleon allows this behavior to happen by using two different - * definitions depending on context. While this somewhat generalized, - * it is specifically intended for those two tags. - */ -class HTMLPurifier_ChildDef_Chameleon extends HTMLPurifier_ChildDef -{ - - /** - * Instance of the definition object to use when inline. Usually stricter. - */ - public $inline; - - /** - * Instance of the definition object to use when block. - */ - public $block; - - public $type = 'chameleon'; - - /** - * @param $inline List of elements to allow when inline. - * @param $block List of elements to allow when block. - */ - public function __construct($inline, $block) { - $this->inline = new HTMLPurifier_ChildDef_Optional($inline); - $this->block = new HTMLPurifier_ChildDef_Optional($block); - $this->elements = $this->block->elements; - } - - public function validateChildren($tokens_of_children, $config, $context) { - if ($context->get('IsInline') === false) { - return $this->block->validateChildren( - $tokens_of_children, $config, $context); - } else { - return $this->inline->validateChildren( - $tokens_of_children, $config, $context); - } - } -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ChildDef/Custom.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ChildDef/Custom.php deleted file mode 100644 index 37093d86..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ChildDef/Custom.php +++ /dev/null @@ -1,90 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Custom validation class, accepts DTD child definitions - * - * @warning Currently this class is an all or nothing proposition, that is, - * it will only give a bool return value. - */ -class HTMLPurifier_ChildDef_Custom extends HTMLPurifier_ChildDef -{ - public $type = 'custom'; - public $allow_empty = false; - /** - * Allowed child pattern as defined by the DTD - */ - public $dtd_regex; - /** - * PCRE regex derived from $dtd_regex - * @private - */ - private $_pcre_regex; - /** - * @param $dtd_regex Allowed child pattern from the DTD - */ - public function __construct($dtd_regex) { - $this->dtd_regex = $dtd_regex; - $this->_compileRegex(); - } - /** - * Compiles the PCRE regex from a DTD regex ($dtd_regex to $_pcre_regex) - */ - protected function _compileRegex() { - $raw = str_replace(' ', '', $this->dtd_regex); - if ($raw{0} != '(') { - $raw = "($raw)"; - } - $el = '[#a-zA-Z0-9_.-]+'; - $reg = $raw; - - // COMPLICATED! AND MIGHT BE BUGGY! I HAVE NO CLUE WHAT I'M - // DOING! Seriously: if there's problems, please report them. - - // collect all elements into the $elements array - preg_match_all("/$el/", $reg, $matches); - foreach ($matches[0] as $match) { - $this->elements[$match] = true; - } - - // setup all elements as parentheticals with leading commas - $reg = preg_replace("/$el/", '(,\\0)', $reg); - - // remove commas when they were not solicited - $reg = preg_replace("/([^,(|]\(+),/", '\\1', $reg); - - // remove all non-paranthetical commas: they are handled by first regex - $reg = preg_replace("/,\(/", '(', $reg); - - $this->_pcre_regex = $reg; - } - public function validateChildren($tokens_of_children, $config, $context) { - $list_of_children = ''; - $nesting = 0; // depth into the nest - foreach ($tokens_of_children as $token) { - if (!empty($token->is_whitespace)) continue; - - $is_child = ($nesting == 0); // direct - - if ($token instanceof HTMLPurifier_Token_Start) { - $nesting++; - } elseif ($token instanceof HTMLPurifier_Token_End) { - $nesting--; - } - - if ($is_child) { - $list_of_children .= $token->name . ','; - } - } - // add leading comma to deal with stray comma declarations - $list_of_children = ',' . rtrim($list_of_children, ','); - $okay = - preg_match( - '/^,?'.$this->_pcre_regex.'$/', - $list_of_children - ); - - return (bool) $okay; - } -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ChildDef/Empty.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ChildDef/Empty.php deleted file mode 100644 index 30df7700..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ChildDef/Empty.php +++ /dev/null @@ -1,20 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Definition that disallows all elements. - * @warning validateChildren() in this class is actually never called, because - * empty elements are corrected in HTMLPurifier_Strategy_MakeWellFormed - * before child definitions are parsed in earnest by - * HTMLPurifier_Strategy_FixNesting. - */ -class HTMLPurifier_ChildDef_Empty extends HTMLPurifier_ChildDef -{ - public $allow_empty = true; - public $type = 'empty'; - public function __construct() {} - public function validateChildren($tokens_of_children, $config, $context) { - return array(); - } -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ChildDef/Optional.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ChildDef/Optional.php deleted file mode 100644 index ea368c75..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ChildDef/Optional.php +++ /dev/null @@ -1,26 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Definition that allows a set of elements, and allows no children. - * @note This is a hack to reuse code from HTMLPurifier_ChildDef_Required, - * really, one shouldn't inherit from the other. Only altered behavior - * is to overload a returned false with an array. Thus, it will never - * return false. - */ -class HTMLPurifier_ChildDef_Optional extends HTMLPurifier_ChildDef_Required -{ - public $allow_empty = true; - public $type = 'optional'; - public function validateChildren($tokens_of_children, $config, $context) { - $result = parent::validateChildren($tokens_of_children, $config, $context); - // we assume that $tokens_of_children is not modified - if ($result === false) { - if (empty($tokens_of_children)) return true; - elseif ($this->whitespace) return $tokens_of_children; - else return array(); - } - return $result; - } -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ChildDef/Required.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ChildDef/Required.php deleted file mode 100644 index f21ab23a..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ChildDef/Required.php +++ /dev/null @@ -1,117 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Definition that allows a set of elements, but disallows empty children. - */ -class HTMLPurifier_ChildDef_Required extends HTMLPurifier_ChildDef -{ - /** - * Lookup table of allowed elements. - * @public - */ - public $elements = array(); - /** - * Whether or not the last passed node was all whitespace. - */ - protected $whitespace = false; - /** - * @param $elements List of allowed element names (lowercase). - */ - public function __construct($elements) { - if (is_string($elements)) { - $elements = str_replace(' ', '', $elements); - $elements = explode('|', $elements); - } - $keys = array_keys($elements); - if ($keys == array_keys($keys)) { - $elements = array_flip($elements); - foreach ($elements as $i => $x) { - $elements[$i] = true; - if (empty($i)) unset($elements[$i]); // remove blank - } - } - $this->elements = $elements; - } - public $allow_empty = false; - public $type = 'required'; - public function validateChildren($tokens_of_children, $config, $context) { - // Flag for subclasses - $this->whitespace = false; - - // if there are no tokens, delete parent node - if (empty($tokens_of_children)) return false; - - // the new set of children - $result = array(); - - // current depth into the nest - $nesting = 0; - - // whether or not we're deleting a node - $is_deleting = false; - - // whether or not parsed character data is allowed - // this controls whether or not we silently drop a tag - // or generate escaped HTML from it - $pcdata_allowed = isset($this->elements['#PCDATA']); - - // a little sanity check to make sure it's not ALL whitespace - $all_whitespace = true; - - // some configuration - $escape_invalid_children = $config->get('Core.EscapeInvalidChildren'); - - // generator - $gen = new HTMLPurifier_Generator($config, $context); - - foreach ($tokens_of_children as $token) { - if (!empty($token->is_whitespace)) { - $result[] = $token; - continue; - } - $all_whitespace = false; // phew, we're not talking about whitespace - - $is_child = ($nesting == 0); - - if ($token instanceof HTMLPurifier_Token_Start) { - $nesting++; - } elseif ($token instanceof HTMLPurifier_Token_End) { - $nesting--; - } - - if ($is_child) { - $is_deleting = false; - if (!isset($this->elements[$token->name])) { - $is_deleting = true; - if ($pcdata_allowed && $token instanceof HTMLPurifier_Token_Text) { - $result[] = $token; - } elseif ($pcdata_allowed && $escape_invalid_children) { - $result[] = new HTMLPurifier_Token_Text( - $gen->generateFromToken($token) - ); - } - continue; - } - } - if (!$is_deleting || ($pcdata_allowed && $token instanceof HTMLPurifier_Token_Text)) { - $result[] = $token; - } elseif ($pcdata_allowed && $escape_invalid_children) { - $result[] = - new HTMLPurifier_Token_Text( - $gen->generateFromToken($token) - ); - } else { - // drop silently - } - } - if (empty($result)) return false; - if ($all_whitespace) { - $this->whitespace = true; - return false; - } - if ($tokens_of_children == $result) return true; - return $result; - } -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ChildDef/StrictBlockquote.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ChildDef/StrictBlockquote.php deleted file mode 100644 index ca907c12..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ChildDef/StrictBlockquote.php +++ /dev/null @@ -1,88 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Takes the contents of blockquote when in strict and reformats for validation. - */ -class HTMLPurifier_ChildDef_StrictBlockquote extends HTMLPurifier_ChildDef_Required -{ - protected $real_elements; - protected $fake_elements; - public $allow_empty = true; - public $type = 'strictblockquote'; - protected $init = false; - - /** - * @note We don't want MakeWellFormed to auto-close inline elements since - * they might be allowed. - */ - public function getAllowedElements($config) { - $this->init($config); - return $this->fake_elements; - } - - public function validateChildren($tokens_of_children, $config, $context) { - - $this->init($config); - - // trick the parent class into thinking it allows more - $this->elements = $this->fake_elements; - $result = parent::validateChildren($tokens_of_children, $config, $context); - $this->elements = $this->real_elements; - - if ($result === false) return array(); - if ($result === true) $result = $tokens_of_children; - - $def = $config->getHTMLDefinition(); - $block_wrap_start = new HTMLPurifier_Token_Start($def->info_block_wrapper); - $block_wrap_end = new HTMLPurifier_Token_End( $def->info_block_wrapper); - $is_inline = false; - $depth = 0; - $ret = array(); - - // assuming that there are no comment tokens - foreach ($result as $i => $token) { - $token = $result[$i]; - // ifs are nested for readability - if (!$is_inline) { - if (!$depth) { - if ( - ($token instanceof HTMLPurifier_Token_Text && !$token->is_whitespace) || - (!$token instanceof HTMLPurifier_Token_Text && !isset($this->elements[$token->name])) - ) { - $is_inline = true; - $ret[] = $block_wrap_start; - } - } - } else { - if (!$depth) { - // starting tokens have been inline text / empty - if ($token instanceof HTMLPurifier_Token_Start || $token instanceof HTMLPurifier_Token_Empty) { - if (isset($this->elements[$token->name])) { - // ended - $ret[] = $block_wrap_end; - $is_inline = false; - } - } - } - } - $ret[] = $token; - if ($token instanceof HTMLPurifier_Token_Start) $depth++; - if ($token instanceof HTMLPurifier_Token_End) $depth--; - } - if ($is_inline) $ret[] = $block_wrap_end; - return $ret; - } - - private function init($config) { - if (!$this->init) { - $def = $config->getHTMLDefinition(); - // allow all inline elements - $this->real_elements = $this->elements; - $this->fake_elements = $def->info_content_sets['Flow']; - $this->fake_elements['#PCDATA'] = true; - $this->init = true; - } - } -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ChildDef/Table.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ChildDef/Table.php deleted file mode 100644 index 96870ac5..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ChildDef/Table.php +++ /dev/null @@ -1,142 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Definition for tables - */ -class HTMLPurifier_ChildDef_Table extends HTMLPurifier_ChildDef -{ - public $allow_empty = false; - public $type = 'table'; - public $elements = array('tr' => true, 'tbody' => true, 'thead' => true, - 'tfoot' => true, 'caption' => true, 'colgroup' => true, 'col' => true); - public function __construct() {} - public function validateChildren($tokens_of_children, $config, $context) { - if (empty($tokens_of_children)) return false; - - // this ensures that the loop gets run one last time before closing - // up. It's a little bit of a hack, but it works! Just make sure you - // get rid of the token later. - $tokens_of_children[] = false; - - // only one of these elements is allowed in a table - $caption = false; - $thead = false; - $tfoot = false; - - // as many of these as you want - $cols = array(); - $content = array(); - - $nesting = 0; // current depth so we can determine nodes - $is_collecting = false; // are we globbing together tokens to package - // into one of the collectors? - $collection = array(); // collected nodes - $tag_index = 0; // the first node might be whitespace, - // so this tells us where the start tag is - - foreach ($tokens_of_children as $token) { - $is_child = ($nesting == 0); - - if ($token === false) { - // terminating sequence started - } elseif ($token instanceof HTMLPurifier_Token_Start) { - $nesting++; - } elseif ($token instanceof HTMLPurifier_Token_End) { - $nesting--; - } - - // handle node collection - if ($is_collecting) { - if ($is_child) { - // okay, let's stash the tokens away - // first token tells us the type of the collection - switch ($collection[$tag_index]->name) { - case 'tr': - case 'tbody': - $content[] = $collection; - break; - case 'caption': - if ($caption !== false) break; - $caption = $collection; - break; - case 'thead': - case 'tfoot': - // access the appropriate variable, $thead or $tfoot - $var = $collection[$tag_index]->name; - if ($$var === false) { - $$var = $collection; - } else { - // transmutate the first and less entries into - // tbody tags, and then put into content - $collection[$tag_index]->name = 'tbody'; - $collection[count($collection)-1]->name = 'tbody'; - $content[] = $collection; - } - break; - case 'colgroup': - $cols[] = $collection; - break; - } - $collection = array(); - $is_collecting = false; - $tag_index = 0; - } else { - // add the node to the collection - $collection[] = $token; - } - } - - // terminate - if ($token === false) break; - - if ($is_child) { - // determine what we're dealing with - if ($token->name == 'col') { - // the only empty tag in the possie, we can handle it - // immediately - $cols[] = array_merge($collection, array($token)); - $collection = array(); - $tag_index = 0; - continue; - } - switch($token->name) { - case 'caption': - case 'colgroup': - case 'thead': - case 'tfoot': - case 'tbody': - case 'tr': - $is_collecting = true; - $collection[] = $token; - continue; - default: - if (!empty($token->is_whitespace)) { - $collection[] = $token; - $tag_index++; - } - continue; - } - } - } - - if (empty($content)) return false; - - $ret = array(); - if ($caption !== false) $ret = array_merge($ret, $caption); - if ($cols !== false) foreach ($cols as $token_array) $ret = array_merge($ret, $token_array); - if ($thead !== false) $ret = array_merge($ret, $thead); - if ($tfoot !== false) $ret = array_merge($ret, $tfoot); - foreach ($content as $token_array) $ret = array_merge($ret, $token_array); - if (!empty($collection) && $is_collecting == false){ - // grab the trailing space - $ret = array_merge($ret, $collection); - } - - array_pop($tokens_of_children); // remove phantom token - - return ($ret === $tokens_of_children) ? true : $ret; - - } -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Config.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Config.php deleted file mode 100644 index 28529e7f..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Config.php +++ /dev/null @@ -1,580 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Configuration object that triggers customizable behavior. - * - * @warning This class is strongly defined: that means that the class - * will fail if an undefined directive is retrieved or set. - * - * @note Many classes that could (although many times don't) use the - * configuration object make it a mandatory parameter. This is - * because a configuration object should always be forwarded, - * otherwise, you run the risk of missing a parameter and then - * being stumped when a configuration directive doesn't work. - * - * @todo Reconsider some of the public member variables - */ -class HTMLPurifier_Config -{ - - /** - * HTML Purifier's version - */ - public $version = '4.0.0'; - - /** - * Bool indicator whether or not to automatically finalize - * the object if a read operation is done - */ - public $autoFinalize = true; - - // protected member variables - - /** - * Namespace indexed array of serials for specific namespaces (see - * getSerial() for more info). - */ - protected $serials = array(); - - /** - * Serial for entire configuration object - */ - protected $serial; - - /** - * Parser for variables - */ - protected $parser; - - /** - * Reference HTMLPurifier_ConfigSchema for value checking - * @note This is public for introspective purposes. Please don't - * abuse! - */ - public $def; - - /** - * Indexed array of definitions - */ - protected $definitions; - - /** - * Bool indicator whether or not config is finalized - */ - protected $finalized = false; - - /** - * Property list containing configuration directives. - */ - protected $plist; - - /** - * Whether or not a set is taking place due to an - * alias lookup. - */ - private $aliasMode; - - /** - * Set to false if you do not want line and file numbers in errors - * (useful when unit testing) - */ - public $chatty = true; - - /** - * Current lock; only gets to this namespace are allowed. - */ - private $lock; - - /** - * @param $definition HTMLPurifier_ConfigSchema that defines what directives - * are allowed. - */ - public function __construct($definition, $parent = null) { - $parent = $parent ? $parent : $definition->defaultPlist; - $this->plist = new HTMLPurifier_PropertyList($parent); - $this->def = $definition; // keep a copy around for checking - $this->parser = new HTMLPurifier_VarParser_Flexible(); - } - - /** - * Convenience constructor that creates a config object based on a mixed var - * @param mixed $config Variable that defines the state of the config - * object. Can be: a HTMLPurifier_Config() object, - * an array of directives based on loadArray(), - * or a string filename of an ini file. - * @param HTMLPurifier_ConfigSchema Schema object - * @return Configured HTMLPurifier_Config object - */ - public static function create($config, $schema = null) { - if ($config instanceof HTMLPurifier_Config) { - // pass-through - return $config; - } - if (!$schema) { - $ret = HTMLPurifier_Config::createDefault(); - } else { - $ret = new HTMLPurifier_Config($schema); - } - if (is_string($config)) $ret->loadIni($config); - elseif (is_array($config)) $ret->loadArray($config); - return $ret; - } - - /** - * Creates a new config object that inherits from a previous one. - * @param HTMLPurifier_Config $config Configuration object to inherit - * from. - * @return HTMLPurifier_Config object with $config as its parent. - */ - public static function inherit(HTMLPurifier_Config $config) { - return new HTMLPurifier_Config($config->def, $config->plist); - } - - /** - * Convenience constructor that creates a default configuration object. - * @return Default HTMLPurifier_Config object. - */ - public static function createDefault() { - $definition = HTMLPurifier_ConfigSchema::instance(); - $config = new HTMLPurifier_Config($definition); - return $config; - } - - /** - * Retreives a value from the configuration. - * @param $key String key - */ - public function get($key, $a = null) { - if ($a !== null) { - $this->triggerError("Using deprecated API: use \$config->get('$key.$a') instead", E_USER_WARNING); - $key = "$key.$a"; - } - if (!$this->finalized) $this->autoFinalize(); - if (!isset($this->def->info[$key])) { - // can't add % due to SimpleTest bug - $this->triggerError('Cannot retrieve value of undefined directive ' . htmlspecialchars($key), - E_USER_WARNING); - return; - } - if (isset($this->def->info[$key]->isAlias)) { - $d = $this->def->info[$key]; - $this->triggerError('Cannot get value from aliased directive, use real name ' . $d->key, - E_USER_ERROR); - return; - } - if ($this->lock) { - list($ns) = explode('.', $key); - if ($ns !== $this->lock) { - $this->triggerError('Cannot get value of namespace ' . $ns . ' when lock for ' . $this->lock . ' is active, this probably indicates a Definition setup method is accessing directives that are not within its namespace', E_USER_ERROR); - return; - } - } - return $this->plist->get($key); - } - - /** - * Retreives an array of directives to values from a given namespace - * @param $namespace String namespace - */ - public function getBatch($namespace) { - if (!$this->finalized) $this->autoFinalize(); - $full = $this->getAll(); - if (!isset($full[$namespace])) { - $this->triggerError('Cannot retrieve undefined namespace ' . htmlspecialchars($namespace), - E_USER_WARNING); - return; - } - return $full[$namespace]; - } - - /** - * Returns a md5 signature of a segment of the configuration object - * that uniquely identifies that particular configuration - * @note Revision is handled specially and is removed from the batch - * before processing! - * @param $namespace Namespace to get serial for - */ - public function getBatchSerial($namespace) { - if (empty($this->serials[$namespace])) { - $batch = $this->getBatch($namespace); - unset($batch['DefinitionRev']); - $this->serials[$namespace] = md5(serialize($batch)); - } - return $this->serials[$namespace]; - } - - /** - * Returns a md5 signature for the entire configuration object - * that uniquely identifies that particular configuration - */ - public function getSerial() { - if (empty($this->serial)) { - $this->serial = md5(serialize($this->getAll())); - } - return $this->serial; - } - - /** - * Retrieves all directives, organized by namespace - * @warning This is a pretty inefficient function, avoid if you can - */ - public function getAll() { - if (!$this->finalized) $this->autoFinalize(); - $ret = array(); - foreach ($this->plist->squash() as $name => $value) { - list($ns, $key) = explode('.', $name, 2); - $ret[$ns][$key] = $value; - } - return $ret; - } - - /** - * Sets a value to configuration. - * @param $key String key - * @param $value Mixed value - */ - public function set($key, $value, $a = null) { - if (strpos($key, '.') === false) { - $namespace = $key; - $directive = $value; - $value = $a; - $key = "$key.$directive"; - $this->triggerError("Using deprecated API: use \$config->set('$key', ...) instead", E_USER_NOTICE); - } else { - list($namespace) = explode('.', $key); - } - if ($this->isFinalized('Cannot set directive after finalization')) return; - if (!isset($this->def->info[$key])) { - $this->triggerError('Cannot set undefined directive ' . htmlspecialchars($key) . ' to value', - E_USER_WARNING); - return; - } - $def = $this->def->info[$key]; - - if (isset($def->isAlias)) { - if ($this->aliasMode) { - $this->triggerError('Double-aliases not allowed, please fix '. - 'ConfigSchema bug with' . $key, E_USER_ERROR); - return; - } - $this->aliasMode = true; - $this->set($def->key, $value); - $this->aliasMode = false; - $this->triggerError("$key is an alias, preferred directive name is {$def->key}", E_USER_NOTICE); - return; - } - - // Raw type might be negative when using the fully optimized form - // of stdclass, which indicates allow_null == true - $rtype = is_int($def) ? $def : $def->type; - if ($rtype < 0) { - $type = -$rtype; - $allow_null = true; - } else { - $type = $rtype; - $allow_null = isset($def->allow_null); - } - - try { - $value = $this->parser->parse($value, $type, $allow_null); - } catch (HTMLPurifier_VarParserException $e) { - $this->triggerError('Value for ' . $key . ' is of invalid type, should be ' . HTMLPurifier_VarParser::getTypeName($type), E_USER_WARNING); - return; - } - if (is_string($value) && is_object($def)) { - // resolve value alias if defined - if (isset($def->aliases[$value])) { - $value = $def->aliases[$value]; - } - // check to see if the value is allowed - if (isset($def->allowed) && !isset($def->allowed[$value])) { - $this->triggerError('Value not supported, valid values are: ' . - $this->_listify($def->allowed), E_USER_WARNING); - return; - } - } - $this->plist->set($key, $value); - - // reset definitions if the directives they depend on changed - // this is a very costly process, so it's discouraged - // with finalization - if ($namespace == 'HTML' || $namespace == 'CSS' || $namespace == 'URI') { - $this->definitions[$namespace] = null; - } - - $this->serials[$namespace] = false; - } - - /** - * Convenience function for error reporting - */ - private function _listify($lookup) { - $list = array(); - foreach ($lookup as $name => $b) $list[] = $name; - return implode(', ', $list); - } - - /** - * Retrieves object reference to the HTML definition. - * @param $raw Return a copy that has not been setup yet. Must be - * called before it's been setup, otherwise won't work. - */ - public function getHTMLDefinition($raw = false) { - return $this->getDefinition('HTML', $raw); - } - - /** - * Retrieves object reference to the CSS definition - * @param $raw Return a copy that has not been setup yet. Must be - * called before it's been setup, otherwise won't work. - */ - public function getCSSDefinition($raw = false) { - return $this->getDefinition('CSS', $raw); - } - - /** - * Retrieves a definition - * @param $type Type of definition: HTML, CSS, etc - * @param $raw Whether or not definition should be returned raw - */ - public function getDefinition($type, $raw = false) { - if (!$this->finalized) $this->autoFinalize(); - // temporarily suspend locks, so we can handle recursive definition calls - $lock = $this->lock; - $this->lock = null; - $factory = HTMLPurifier_DefinitionCacheFactory::instance(); - $cache = $factory->create($type, $this); - $this->lock = $lock; - if (!$raw) { - // see if we can quickly supply a definition - if (!empty($this->definitions[$type])) { - if (!$this->definitions[$type]->setup) { - $this->definitions[$type]->setup($this); - $cache->set($this->definitions[$type], $this); - } - return $this->definitions[$type]; - } - // memory check missed, try cache - $this->definitions[$type] = $cache->get($this); - if ($this->definitions[$type]) { - // definition in cache, return it - return $this->definitions[$type]; - } - } elseif ( - !empty($this->definitions[$type]) && - !$this->definitions[$type]->setup - ) { - // raw requested, raw in memory, quick return - return $this->definitions[$type]; - } - // quick checks failed, let's create the object - if ($type == 'HTML') { - $this->definitions[$type] = new HTMLPurifier_HTMLDefinition(); - } elseif ($type == 'CSS') { - $this->definitions[$type] = new HTMLPurifier_CSSDefinition(); - } elseif ($type == 'URI') { - $this->definitions[$type] = new HTMLPurifier_URIDefinition(); - } else { - throw new HTMLPurifier_Exception("Definition of $type type not supported"); - } - // quick abort if raw - if ($raw) { - if (is_null($this->get($type . '.DefinitionID'))) { - // fatally error out if definition ID not set - throw new HTMLPurifier_Exception("Cannot retrieve raw version without specifying %$type.DefinitionID"); - } - return $this->definitions[$type]; - } - // set it up - $this->lock = $type; - $this->definitions[$type]->setup($this); - $this->lock = null; - // save in cache - $cache->set($this->definitions[$type], $this); - return $this->definitions[$type]; - } - - /** - * Loads configuration values from an array with the following structure: - * Namespace.Directive => Value - * @param $config_array Configuration associative array - */ - public function loadArray($config_array) { - if ($this->isFinalized('Cannot load directives after finalization')) return; - foreach ($config_array as $key => $value) { - $key = str_replace('_', '.', $key); - if (strpos($key, '.') !== false) { - $this->set($key, $value); - } else { - $namespace = $key; - $namespace_values = $value; - foreach ($namespace_values as $directive => $value) { - $this->set($namespace .'.'. $directive, $value); - } - } - } - } - - /** - * Returns a list of array(namespace, directive) for all directives - * that are allowed in a web-form context as per an allowed - * namespaces/directives list. - * @param $allowed List of allowed namespaces/directives - */ - public static function getAllowedDirectivesForForm($allowed, $schema = null) { - if (!$schema) { - $schema = HTMLPurifier_ConfigSchema::instance(); - } - if ($allowed !== true) { - if (is_string($allowed)) $allowed = array($allowed); - $allowed_ns = array(); - $allowed_directives = array(); - $blacklisted_directives = array(); - foreach ($allowed as $ns_or_directive) { - if (strpos($ns_or_directive, '.') !== false) { - // directive - if ($ns_or_directive[0] == '-') { - $blacklisted_directives[substr($ns_or_directive, 1)] = true; - } else { - $allowed_directives[$ns_or_directive] = true; - } - } else { - // namespace - $allowed_ns[$ns_or_directive] = true; - } - } - } - $ret = array(); - foreach ($schema->info as $key => $def) { - list($ns, $directive) = explode('.', $key, 2); - if ($allowed !== true) { - if (isset($blacklisted_directives["$ns.$directive"])) continue; - if (!isset($allowed_directives["$ns.$directive"]) && !isset($allowed_ns[$ns])) continue; - } - if (isset($def->isAlias)) continue; - if ($directive == 'DefinitionID' || $directive == 'DefinitionRev') continue; - $ret[] = array($ns, $directive); - } - return $ret; - } - - /** - * Loads configuration values from $_GET/$_POST that were posted - * via ConfigForm - * @param $array $_GET or $_POST array to import - * @param $index Index/name that the config variables are in - * @param $allowed List of allowed namespaces/directives - * @param $mq_fix Boolean whether or not to enable magic quotes fix - * @param $schema Instance of HTMLPurifier_ConfigSchema to use, if not global copy - */ - public static function loadArrayFromForm($array, $index = false, $allowed = true, $mq_fix = true, $schema = null) { - $ret = HTMLPurifier_Config::prepareArrayFromForm($array, $index, $allowed, $mq_fix, $schema); - $config = HTMLPurifier_Config::create($ret, $schema); - return $config; - } - - /** - * Merges in configuration values from $_GET/$_POST to object. NOT STATIC. - * @note Same parameters as loadArrayFromForm - */ - public function mergeArrayFromForm($array, $index = false, $allowed = true, $mq_fix = true) { - $ret = HTMLPurifier_Config::prepareArrayFromForm($array, $index, $allowed, $mq_fix, $this->def); - $this->loadArray($ret); - } - - /** - * Prepares an array from a form into something usable for the more - * strict parts of HTMLPurifier_Config - */ - public static function prepareArrayFromForm($array, $index = false, $allowed = true, $mq_fix = true, $schema = null) { - if ($index !== false) $array = (isset($array[$index]) && is_array($array[$index])) ? $array[$index] : array(); - $mq = $mq_fix && function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc(); - - $allowed = HTMLPurifier_Config::getAllowedDirectivesForForm($allowed, $schema); - $ret = array(); - foreach ($allowed as $key) { - list($ns, $directive) = $key; - $skey = "$ns.$directive"; - if (!empty($array["Null_$skey"])) { - $ret[$ns][$directive] = null; - continue; - } - if (!isset($array[$skey])) continue; - $value = $mq ? stripslashes($array[$skey]) : $array[$skey]; - $ret[$ns][$directive] = $value; - } - return $ret; - } - - /** - * Loads configuration values from an ini file - * @param $filename Name of ini file - */ - public function loadIni($filename) { - if ($this->isFinalized('Cannot load directives after finalization')) return; - $array = parse_ini_file($filename, true); - $this->loadArray($array); - } - - /** - * Checks whether or not the configuration object is finalized. - * @param $error String error message, or false for no error - */ - public function isFinalized($error = false) { - if ($this->finalized && $error) { - $this->triggerError($error, E_USER_ERROR); - } - return $this->finalized; - } - - /** - * Finalizes configuration only if auto finalize is on and not - * already finalized - */ - public function autoFinalize() { - if ($this->autoFinalize) { - $this->finalize(); - } else { - $this->plist->squash(true); - } - } - - /** - * Finalizes a configuration object, prohibiting further change - */ - public function finalize() { - $this->finalized = true; - unset($this->parser); - } - - /** - * Produces a nicely formatted error message by supplying the - * stack frame information from two levels up and OUTSIDE of - * HTMLPurifier_Config. - */ - protected function triggerError($msg, $no) { - // determine previous stack frame - $backtrace = debug_backtrace(); - if ($this->chatty && isset($backtrace[1])) { - $frame = $backtrace[1]; - $extra = " on line {$frame['line']} in file {$frame['file']}"; - } else { - $extra = ''; - } - trigger_error($msg . $extra, $no); - } - - /** - * Returns a serialized form of the configuration object that can - * be reconstituted. - */ - public function serialize() { - $this->getDefinition('HTML'); - $this->getDefinition('CSS'); - $this->getDefinition('URI'); - return serialize($this); - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema.php deleted file mode 100644 index d6e4c78b..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema.php +++ /dev/null @@ -1,158 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Configuration definition, defines directives and their defaults. - */ -class HTMLPurifier_ConfigSchema { - - /** - * Defaults of the directives and namespaces. - * @note This shares the exact same structure as HTMLPurifier_Config::$conf - */ - public $defaults = array(); - - /** - * The default property list. Do not edit this property list. - */ - public $defaultPlist; - - /** - * Definition of the directives. The structure of this is: - * - * array( - * 'Namespace' => array( - * 'Directive' => new stdclass(), - * ) - * ) - * - * The stdclass may have the following properties: - * - * - If isAlias isn't set: - * - type: Integer type of directive, see HTMLPurifier_VarParser for definitions - * - allow_null: If set, this directive allows null values - * - aliases: If set, an associative array of value aliases to real values - * - allowed: If set, a lookup array of allowed (string) values - * - If isAlias is set: - * - namespace: Namespace this directive aliases to - * - name: Directive name this directive aliases to - * - * In certain degenerate cases, stdclass will actually be an integer. In - * that case, the value is equivalent to an stdclass with the type - * property set to the integer. If the integer is negative, type is - * equal to the absolute value of integer, and allow_null is true. - * - * This class is friendly with HTMLPurifier_Config. If you need introspection - * about the schema, you're better of using the ConfigSchema_Interchange, - * which uses more memory but has much richer information. - */ - public $info = array(); - - /** - * Application-wide singleton - */ - static protected $singleton; - - public function __construct() { - $this->defaultPlist = new HTMLPurifier_PropertyList(); - } - - /** - * Unserializes the default ConfigSchema. - */ - public static function makeFromSerial() { - return unserialize(file_get_contents(HTMLPURIFIER_PREFIX . '/HTMLPurifier/ConfigSchema/schema.ser')); - } - - /** - * Retrieves an instance of the application-wide configuration definition. - */ - public static function instance($prototype = null) { - if ($prototype !== null) { - HTMLPurifier_ConfigSchema::$singleton = $prototype; - } elseif (HTMLPurifier_ConfigSchema::$singleton === null || $prototype === true) { - HTMLPurifier_ConfigSchema::$singleton = HTMLPurifier_ConfigSchema::makeFromSerial(); - } - return HTMLPurifier_ConfigSchema::$singleton; - } - - /** - * Defines a directive for configuration - * @warning Will fail of directive's namespace is defined. - * @warning This method's signature is slightly different from the legacy - * define() static method! Beware! - * @param $namespace Namespace the directive is in - * @param $name Key of directive - * @param $default Default value of directive - * @param $type Allowed type of the directive. See - * HTMLPurifier_DirectiveDef::$type for allowed values - * @param $allow_null Whether or not to allow null values - */ - public function add($key, $default, $type, $allow_null) { - $obj = new stdclass(); - $obj->type = is_int($type) ? $type : HTMLPurifier_VarParser::$types[$type]; - if ($allow_null) $obj->allow_null = true; - $this->info[$key] = $obj; - $this->defaults[$key] = $default; - $this->defaultPlist->set($key, $default); - } - - /** - * Defines a directive value alias. - * - * Directive value aliases are convenient for developers because it lets - * them set a directive to several values and get the same result. - * @param $namespace Directive's namespace - * @param $name Name of Directive - * @param $aliases Hash of aliased values to the real alias - */ - public function addValueAliases($key, $aliases) { - if (!isset($this->info[$key]->aliases)) { - $this->info[$key]->aliases = array(); - } - foreach ($aliases as $alias => $real) { - $this->info[$key]->aliases[$alias] = $real; - } - } - - /** - * Defines a set of allowed values for a directive. - * @warning This is slightly different from the corresponding static - * method definition. - * @param $namespace Namespace of directive - * @param $name Name of directive - * @param $allowed Lookup array of allowed values - */ - public function addAllowedValues($key, $allowed) { - $this->info[$key]->allowed = $allowed; - } - - /** - * Defines a directive alias for backwards compatibility - * @param $namespace - * @param $name Directive that will be aliased - * @param $new_namespace - * @param $new_name Directive that the alias will be to - */ - public function addAlias($key, $new_key) { - $obj = new stdclass; - $obj->key = $new_key; - $obj->isAlias = true; - $this->info[$key] = $obj; - } - - /** - * Replaces any stdclass that only has the type property with type integer. - */ - public function postProcess() { - foreach ($this->info as $key => $v) { - if (count((array) $v) == 1) { - $this->info[$key] = $v->type; - } elseif (count((array) $v) == 2 && isset($v->allow_null)) { - $this->info[$key] = -$v->type; - } - } - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/Builder/ConfigSchema.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/Builder/ConfigSchema.php deleted file mode 100644 index 723f3a6c..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/Builder/ConfigSchema.php +++ /dev/null @@ -1,44 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Converts HTMLPurifier_ConfigSchema_Interchange to our runtime - * representation used to perform checks on user configuration. - */ -class HTMLPurifier_ConfigSchema_Builder_ConfigSchema -{ - - public function build($interchange) { - $schema = new HTMLPurifier_ConfigSchema(); - foreach ($interchange->directives as $d) { - $schema->add( - $d->id->key, - $d->default, - $d->type, - $d->typeAllowsNull - ); - if ($d->allowed !== null) { - $schema->addAllowedValues( - $d->id->key, - $d->allowed - ); - } - foreach ($d->aliases as $alias) { - $schema->addAlias( - $alias->key, - $d->id->key - ); - } - if ($d->valueAliases !== null) { - $schema->addValueAliases( - $d->id->key, - $d->valueAliases - ); - } - } - $schema->postProcess(); - return $schema; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/Builder/Xml.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/Builder/Xml.php deleted file mode 100644 index 6712b17b..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/Builder/Xml.php +++ /dev/null @@ -1,106 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Converts HTMLPurifier_ConfigSchema_Interchange to an XML format, - * which can be further processed to generate documentation. - */ -class HTMLPurifier_ConfigSchema_Builder_Xml extends XMLWriter -{ - - protected $interchange; - private $namespace; - - protected function writeHTMLDiv($html) { - $this->startElement('div'); - - $purifier = HTMLPurifier::getInstance(); - $html = $purifier->purify($html); - $this->writeAttribute('xmlns', 'http://www.w3.org/1999/xhtml'); - $this->writeRaw($html); - - $this->endElement(); // div - } - - protected function export($var) { - if ($var === array()) return 'array()'; - return var_export($var, true); - } - - public function build($interchange) { - // global access, only use as last resort - $this->interchange = $interchange; - - $this->setIndent(true); - $this->startDocument('1.0', 'UTF-8'); - $this->startElement('configdoc'); - $this->writeElement('title', $interchange->name); - - foreach ($interchange->directives as $directive) { - $this->buildDirective($directive); - } - - if ($this->namespace) $this->endElement(); // namespace - - $this->endElement(); // configdoc - $this->flush(); - } - - public function buildDirective($directive) { - - // Kludge, although I suppose having a notion of a "root namespace" - // certainly makes things look nicer when documentation is built. - // Depends on things being sorted. - if (!$this->namespace || $this->namespace !== $directive->id->getRootNamespace()) { - if ($this->namespace) $this->endElement(); // namespace - $this->namespace = $directive->id->getRootNamespace(); - $this->startElement('namespace'); - $this->writeAttribute('id', $this->namespace); - $this->writeElement('name', $this->namespace); - } - - $this->startElement('directive'); - $this->writeAttribute('id', $directive->id->toString()); - - $this->writeElement('name', $directive->id->getDirective()); - - $this->startElement('aliases'); - foreach ($directive->aliases as $alias) $this->writeElement('alias', $alias->toString()); - $this->endElement(); // aliases - - $this->startElement('constraints'); - if ($directive->version) $this->writeElement('version', $directive->version); - $this->startElement('type'); - if ($directive->typeAllowsNull) $this->writeAttribute('allow-null', 'yes'); - $this->text($directive->type); - $this->endElement(); // type - if ($directive->allowed) { - $this->startElement('allowed'); - foreach ($directive->allowed as $value => $x) $this->writeElement('value', $value); - $this->endElement(); // allowed - } - $this->writeElement('default', $this->export($directive->default)); - $this->writeAttribute('xml:space', 'preserve'); - if ($directive->external) { - $this->startElement('external'); - foreach ($directive->external as $project) $this->writeElement('project', $project); - $this->endElement(); - } - $this->endElement(); // constraints - - if ($directive->deprecatedVersion) { - $this->startElement('deprecated'); - $this->writeElement('version', $directive->deprecatedVersion); - $this->writeElement('use', $directive->deprecatedUse->toString()); - $this->endElement(); // deprecated - } - - $this->startElement('description'); - $this->writeHTMLDiv($directive->description); - $this->endElement(); // description - - $this->endElement(); // directive - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/Exception.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/Exception.php deleted file mode 100644 index 47881599..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/Exception.php +++ /dev/null @@ -1,11 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Exceptions related to configuration schema - */ -class HTMLPurifier_ConfigSchema_Exception extends HTMLPurifier_Exception -{ - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/Interchange.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/Interchange.php deleted file mode 100644 index 9f2e7ff7..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/Interchange.php +++ /dev/null @@ -1,42 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Generic schema interchange format that can be converted to a runtime - * representation (HTMLPurifier_ConfigSchema) or HTML documentation. Members - * are completely validated. - */ -class HTMLPurifier_ConfigSchema_Interchange -{ - - /** - * Name of the application this schema is describing. - */ - public $name; - - /** - * Array of Directive ID => array(directive info) - */ - public $directives = array(); - - /** - * Adds a directive array to $directives - */ - public function addDirective($directive) { - if (isset($this->directives[$i = $directive->id->toString()])) { - throw new HTMLPurifier_ConfigSchema_Exception("Cannot redefine directive '$i'"); - } - $this->directives[$i] = $directive; - } - - /** - * Convenience function to perform standard validation. Throws exception - * on failed validation. - */ - public function validate() { - $validator = new HTMLPurifier_ConfigSchema_Validator(); - return $validator->validate($this); - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/Interchange/Directive.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/Interchange/Directive.php deleted file mode 100644 index f502d473..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/Interchange/Directive.php +++ /dev/null @@ -1,77 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Interchange component class describing configuration directives. - */ -class HTMLPurifier_ConfigSchema_Interchange_Directive -{ - - /** - * ID of directive, instance of HTMLPurifier_ConfigSchema_Interchange_Id. - */ - public $id; - - /** - * String type, e.g. 'integer' or 'istring'. - */ - public $type; - - /** - * Default value, e.g. 3 or 'DefaultVal'. - */ - public $default; - - /** - * HTML description. - */ - public $description; - - /** - * Boolean whether or not null is allowed as a value. - */ - public $typeAllowsNull = false; - - /** - * Lookup table of allowed scalar values, e.g. array('allowed' => true). - * Null if all values are allowed. - */ - public $allowed; - - /** - * List of aliases for the directive, - * e.g. array(new HTMLPurifier_ConfigSchema_Interchange_Id('Ns', 'Dir'))). - */ - public $aliases = array(); - - /** - * Hash of value aliases, e.g. array('alt' => 'real'). Null if value - * aliasing is disabled (necessary for non-scalar types). - */ - public $valueAliases; - - /** - * Version of HTML Purifier the directive was introduced, e.g. '1.3.1'. - * Null if the directive has always existed. - */ - public $version; - - /** - * ID of directive that supercedes this old directive, is an instance - * of HTMLPurifier_ConfigSchema_Interchange_Id. Null if not deprecated. - */ - public $deprecatedUse; - - /** - * Version of HTML Purifier this directive was deprecated. Null if not - * deprecated. - */ - public $deprecatedVersion; - - /** - * List of external projects this directive depends on, e.g. array('CSSTidy'). - */ - public $external = array(); - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/Interchange/Id.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/Interchange/Id.php deleted file mode 100644 index bfdbca53..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/Interchange/Id.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Represents a directive ID in the interchange format. - */ -class HTMLPurifier_ConfigSchema_Interchange_Id -{ - - public $key; - - public function __construct($key) { - $this->key = $key; - } - - /** - * @warning This is NOT magic, to ensure that people don't abuse SPL and - * cause problems for PHP 5.0 support. - */ - public function toString() { - return $this->key; - } - - public function getRootNamespace() { - return substr($this->key, 0, strpos($this->key, ".")); - } - - public function getDirective() { - return substr($this->key, strpos($this->key, ".") + 1); - } - - public static function make($id) { - return new HTMLPurifier_ConfigSchema_Interchange_Id($id); - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/InterchangeBuilder.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/InterchangeBuilder.php deleted file mode 100644 index 3195cc0b..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/InterchangeBuilder.php +++ /dev/null @@ -1,180 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -class HTMLPurifier_ConfigSchema_InterchangeBuilder -{ - - /** - * Used for processing DEFAULT, nothing else. - */ - protected $varParser; - - public function __construct($varParser = null) { - $this->varParser = $varParser ? $varParser : new HTMLPurifier_VarParser_Native(); - } - - public static function buildFromDirectory($dir = null) { - $builder = new HTMLPurifier_ConfigSchema_InterchangeBuilder(); - $interchange = new HTMLPurifier_ConfigSchema_Interchange(); - return $builder->buildDir($interchange, $dir); - } - - public function buildDir($interchange, $dir = null) { - if (!$dir) $dir = HTMLPURIFIER_PREFIX . '/HTMLPurifier/ConfigSchema/schema'; - if (file_exists($dir . '/info.ini')) { - $info = parse_ini_file($dir . '/info.ini'); - $interchange->name = $info['name']; - } - - $files = array(); - $dh = opendir($dir); - while (false !== ($file = readdir($dh))) { - if (!$file || $file[0] == '.' || strrchr($file, '.') !== '.txt') { - continue; - } - $files[] = $file; - } - closedir($dh); - - sort($files); - foreach ($files as $file) { - $this->buildFile($interchange, $dir . '/' . $file); - } - - return $interchange; - } - - public function buildFile($interchange, $file) { - $parser = new HTMLPurifier_StringHashParser(); - $this->build( - $interchange, - new HTMLPurifier_StringHash( $parser->parseFile($file) ) - ); - } - - /** - * Builds an interchange object based on a hash. - * @param $interchange HTMLPurifier_ConfigSchema_Interchange object to build - * @param $hash HTMLPurifier_ConfigSchema_StringHash source data - */ - public function build($interchange, $hash) { - if (!$hash instanceof HTMLPurifier_StringHash) { - $hash = new HTMLPurifier_StringHash($hash); - } - if (!isset($hash['ID'])) { - throw new HTMLPurifier_ConfigSchema_Exception('Hash does not have any ID'); - } - if (strpos($hash['ID'], '.') === false) { - if (count($hash) == 2 && isset($hash['DESCRIPTION'])) { - $hash->offsetGet('DESCRIPTION'); // prevent complaining - } else { - throw new HTMLPurifier_ConfigSchema_Exception('All directives must have a namespace'); - } - } else { - $this->buildDirective($interchange, $hash); - } - $this->_findUnused($hash); - } - - public function buildDirective($interchange, $hash) { - $directive = new HTMLPurifier_ConfigSchema_Interchange_Directive(); - - // These are required elements: - $directive->id = $this->id($hash->offsetGet('ID')); - $id = $directive->id->toString(); // convenience - - if (isset($hash['TYPE'])) { - $type = explode('/', $hash->offsetGet('TYPE')); - if (isset($type[1])) $directive->typeAllowsNull = true; - $directive->type = $type[0]; - } else { - throw new HTMLPurifier_ConfigSchema_Exception("TYPE in directive hash '$id' not defined"); - } - - if (isset($hash['DEFAULT'])) { - try { - $directive->default = $this->varParser->parse($hash->offsetGet('DEFAULT'), $directive->type, $directive->typeAllowsNull); - } catch (HTMLPurifier_VarParserException $e) { - throw new HTMLPurifier_ConfigSchema_Exception($e->getMessage() . " in DEFAULT in directive hash '$id'"); - } - } - - if (isset($hash['DESCRIPTION'])) { - $directive->description = $hash->offsetGet('DESCRIPTION'); - } - - if (isset($hash['ALLOWED'])) { - $directive->allowed = $this->lookup($this->evalArray($hash->offsetGet('ALLOWED'))); - } - - if (isset($hash['VALUE-ALIASES'])) { - $directive->valueAliases = $this->evalArray($hash->offsetGet('VALUE-ALIASES')); - } - - if (isset($hash['ALIASES'])) { - $raw_aliases = trim($hash->offsetGet('ALIASES')); - $aliases = preg_split('/\s*,\s*/', $raw_aliases); - foreach ($aliases as $alias) { - $directive->aliases[] = $this->id($alias); - } - } - - if (isset($hash['VERSION'])) { - $directive->version = $hash->offsetGet('VERSION'); - } - - if (isset($hash['DEPRECATED-USE'])) { - $directive->deprecatedUse = $this->id($hash->offsetGet('DEPRECATED-USE')); - } - - if (isset($hash['DEPRECATED-VERSION'])) { - $directive->deprecatedVersion = $hash->offsetGet('DEPRECATED-VERSION'); - } - - if (isset($hash['EXTERNAL'])) { - $directive->external = preg_split('/\s*,\s*/', trim($hash->offsetGet('EXTERNAL'))); - } - - $interchange->addDirective($directive); - } - - /** - * Evaluates an array PHP code string without array() wrapper - */ - protected function evalArray($contents) { - return eval('return array('. $contents .');'); - } - - /** - * Converts an array list into a lookup array. - */ - protected function lookup($array) { - $ret = array(); - foreach ($array as $val) $ret[$val] = true; - return $ret; - } - - /** - * Convenience function that creates an HTMLPurifier_ConfigSchema_Interchange_Id - * object based on a string Id. - */ - protected function id($id) { - return HTMLPurifier_ConfigSchema_Interchange_Id::make($id); - } - - /** - * Triggers errors for any unused keys passed in the hash; such keys - * may indicate typos, missing values, etc. - * @param $hash Instance of ConfigSchema_StringHash to check. - */ - protected function _findUnused($hash) { - $accessed = $hash->getAccessed(); - foreach ($hash as $k => $v) { - if (!isset($accessed[$k])) { - trigger_error("String hash key '$k' not used by builder", E_USER_NOTICE); - } - } - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/Validator.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/Validator.php deleted file mode 100644 index aed7be46..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/Validator.php +++ /dev/null @@ -1,206 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Performs validations on HTMLPurifier_ConfigSchema_Interchange - * - * @note If you see '// handled by InterchangeBuilder', that means a - * design decision in that class would prevent this validation from - * ever being necessary. We have them anyway, however, for - * redundancy. - */ -class HTMLPurifier_ConfigSchema_Validator -{ - - /** - * Easy to access global objects. - */ - protected $interchange, $aliases; - - /** - * Context-stack to provide easy to read error messages. - */ - protected $context = array(); - - /** - * HTMLPurifier_VarParser to test default's type. - */ - protected $parser; - - public function __construct() { - $this->parser = new HTMLPurifier_VarParser(); - } - - /** - * Validates a fully-formed interchange object. Throws an - * HTMLPurifier_ConfigSchema_Exception if there's a problem. - */ - public function validate($interchange) { - $this->interchange = $interchange; - $this->aliases = array(); - // PHP is a bit lax with integer <=> string conversions in - // arrays, so we don't use the identical !== comparison - foreach ($interchange->directives as $i => $directive) { - $id = $directive->id->toString(); - if ($i != $id) $this->error(false, "Integrity violation: key '$i' does not match internal id '$id'"); - $this->validateDirective($directive); - } - return true; - } - - /** - * Validates a HTMLPurifier_ConfigSchema_Interchange_Id object. - */ - public function validateId($id) { - $id_string = $id->toString(); - $this->context[] = "id '$id_string'"; - if (!$id instanceof HTMLPurifier_ConfigSchema_Interchange_Id) { - // handled by InterchangeBuilder - $this->error(false, 'is not an instance of HTMLPurifier_ConfigSchema_Interchange_Id'); - } - // keys are now unconstrained (we might want to narrow down to A-Za-z0-9.) - // we probably should check that it has at least one namespace - $this->with($id, 'key') - ->assertNotEmpty() - ->assertIsString(); // implicit assertIsString handled by InterchangeBuilder - array_pop($this->context); - } - - /** - * Validates a HTMLPurifier_ConfigSchema_Interchange_Directive object. - */ - public function validateDirective($d) { - $id = $d->id->toString(); - $this->context[] = "directive '$id'"; - $this->validateId($d->id); - - $this->with($d, 'description') - ->assertNotEmpty(); - - // BEGIN - handled by InterchangeBuilder - $this->with($d, 'type') - ->assertNotEmpty(); - $this->with($d, 'typeAllowsNull') - ->assertIsBool(); - try { - // This also tests validity of $d->type - $this->parser->parse($d->default, $d->type, $d->typeAllowsNull); - } catch (HTMLPurifier_VarParserException $e) { - $this->error('default', 'had error: ' . $e->getMessage()); - } - // END - handled by InterchangeBuilder - - if (!is_null($d->allowed) || !empty($d->valueAliases)) { - // allowed and valueAliases require that we be dealing with - // strings, so check for that early. - $d_int = HTMLPurifier_VarParser::$types[$d->type]; - if (!isset(HTMLPurifier_VarParser::$stringTypes[$d_int])) { - $this->error('type', 'must be a string type when used with allowed or value aliases'); - } - } - - $this->validateDirectiveAllowed($d); - $this->validateDirectiveValueAliases($d); - $this->validateDirectiveAliases($d); - - array_pop($this->context); - } - - /** - * Extra validation if $allowed member variable of - * HTMLPurifier_ConfigSchema_Interchange_Directive is defined. - */ - public function validateDirectiveAllowed($d) { - if (is_null($d->allowed)) return; - $this->with($d, 'allowed') - ->assertNotEmpty() - ->assertIsLookup(); // handled by InterchangeBuilder - if (is_string($d->default) && !isset($d->allowed[$d->default])) { - $this->error('default', 'must be an allowed value'); - } - $this->context[] = 'allowed'; - foreach ($d->allowed as $val => $x) { - if (!is_string($val)) $this->error("value $val", 'must be a string'); - } - array_pop($this->context); - } - - /** - * Extra validation if $valueAliases member variable of - * HTMLPurifier_ConfigSchema_Interchange_Directive is defined. - */ - public function validateDirectiveValueAliases($d) { - if (is_null($d->valueAliases)) return; - $this->with($d, 'valueAliases') - ->assertIsArray(); // handled by InterchangeBuilder - $this->context[] = 'valueAliases'; - foreach ($d->valueAliases as $alias => $real) { - if (!is_string($alias)) $this->error("alias $alias", 'must be a string'); - if (!is_string($real)) $this->error("alias target $real from alias '$alias'", 'must be a string'); - if ($alias === $real) { - $this->error("alias '$alias'", "must not be an alias to itself"); - } - } - if (!is_null($d->allowed)) { - foreach ($d->valueAliases as $alias => $real) { - if (isset($d->allowed[$alias])) { - $this->error("alias '$alias'", 'must not be an allowed value'); - } elseif (!isset($d->allowed[$real])) { - $this->error("alias '$alias'", 'must be an alias to an allowed value'); - } - } - } - array_pop($this->context); - } - - /** - * Extra validation if $aliases member variable of - * HTMLPurifier_ConfigSchema_Interchange_Directive is defined. - */ - public function validateDirectiveAliases($d) { - $this->with($d, 'aliases') - ->assertIsArray(); // handled by InterchangeBuilder - $this->context[] = 'aliases'; - foreach ($d->aliases as $alias) { - $this->validateId($alias); - $s = $alias->toString(); - if (isset($this->interchange->directives[$s])) { - $this->error("alias '$s'", 'collides with another directive'); - } - if (isset($this->aliases[$s])) { - $other_directive = $this->aliases[$s]; - $this->error("alias '$s'", "collides with alias for directive '$other_directive'"); - } - $this->aliases[$s] = $d->id->toString(); - } - array_pop($this->context); - } - - // protected helper functions - - /** - * Convenience function for generating HTMLPurifier_ConfigSchema_ValidatorAtom - * for validating simple member variables of objects. - */ - protected function with($obj, $member) { - return new HTMLPurifier_ConfigSchema_ValidatorAtom($this->getFormattedContext(), $obj, $member); - } - - /** - * Emits an error, providing helpful context. - */ - protected function error($target, $msg) { - if ($target !== false) $prefix = ucfirst($target) . ' in ' . $this->getFormattedContext(); - else $prefix = ucfirst($this->getFormattedContext()); - throw new HTMLPurifier_ConfigSchema_Exception(trim($prefix . ' ' . $msg)); - } - - /** - * Returns a formatted context string. - */ - protected function getFormattedContext() { - return implode(' in ', array_reverse($this->context)); - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/ValidatorAtom.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/ValidatorAtom.php deleted file mode 100644 index 4c591fed..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/ValidatorAtom.php +++ /dev/null @@ -1,66 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Fluent interface for validating the contents of member variables. - * This should be immutable. See HTMLPurifier_ConfigSchema_Validator for - * use-cases. We name this an 'atom' because it's ONLY for validations that - * are independent and usually scalar. - */ -class HTMLPurifier_ConfigSchema_ValidatorAtom -{ - - protected $context, $obj, $member, $contents; - - public function __construct($context, $obj, $member) { - $this->context = $context; - $this->obj = $obj; - $this->member = $member; - $this->contents =& $obj->$member; - } - - public function assertIsString() { - if (!is_string($this->contents)) $this->error('must be a string'); - return $this; - } - - public function assertIsBool() { - if (!is_bool($this->contents)) $this->error('must be a boolean'); - return $this; - } - - public function assertIsArray() { - if (!is_array($this->contents)) $this->error('must be an array'); - return $this; - } - - public function assertNotNull() { - if ($this->contents === null) $this->error('must not be null'); - return $this; - } - - public function assertAlnum() { - $this->assertIsString(); - if (!ctype_alnum($this->contents)) $this->error('must be alphanumeric'); - return $this; - } - - public function assertNotEmpty() { - if (empty($this->contents)) $this->error('must not be empty'); - return $this; - } - - public function assertIsLookup() { - $this->assertIsArray(); - foreach ($this->contents as $v) { - if ($v !== true) $this->error('must be a lookup array'); - } - return $this; - } - - protected function error($msg) { - throw new HTMLPurifier_ConfigSchema_Exception(ucfirst($this->member) . ' in ' . $this->context . ' ' . $msg); - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema.ser b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema.ser Binary files differdeleted file mode 100644 index bbf12f9c..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema.ser +++ /dev/null diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Attr.AllowedClasses.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Attr.AllowedClasses.txt deleted file mode 100644 index 0517fed0..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Attr.AllowedClasses.txt +++ /dev/null @@ -1,8 +0,0 @@ -Attr.AllowedClasses -TYPE: lookup/null -VERSION: 4.0.0 -DEFAULT: null ---DESCRIPTION-- -List of allowed class values in the class attribute. By default, this is null, -which means all classes are allowed. ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Attr.AllowedFrameTargets.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Attr.AllowedFrameTargets.txt deleted file mode 100644 index 249edd64..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Attr.AllowedFrameTargets.txt +++ /dev/null @@ -1,12 +0,0 @@ -Attr.AllowedFrameTargets -TYPE: lookup -DEFAULT: array() ---DESCRIPTION-- -Lookup table of all allowed link frame targets. Some commonly used link -targets include _blank, _self, _parent and _top. Values should be -lowercase, as validation will be done in a case-sensitive manner despite -W3C's recommendation. XHTML 1.0 Strict does not permit the target attribute -so this directive will have no effect in that doctype. XHTML 1.1 does not -enable the Target module by default, you will have to manually enable it -(see the module documentation for more details.) ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Attr.AllowedRel.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Attr.AllowedRel.txt deleted file mode 100644 index 9a8fa6a2..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Attr.AllowedRel.txt +++ /dev/null @@ -1,9 +0,0 @@ -Attr.AllowedRel -TYPE: lookup -VERSION: 1.6.0 -DEFAULT: array() ---DESCRIPTION-- -List of allowed forward document relationships in the rel attribute. Common -values may be nofollow or print. By default, this is empty, meaning that no -document relationships are allowed. ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Attr.AllowedRev.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Attr.AllowedRev.txt deleted file mode 100644 index b0178834..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Attr.AllowedRev.txt +++ /dev/null @@ -1,9 +0,0 @@ -Attr.AllowedRev -TYPE: lookup -VERSION: 1.6.0 -DEFAULT: array() ---DESCRIPTION-- -List of allowed reverse document relationships in the rev attribute. This -attribute is a bit of an edge-case; if you don't know what it is for, stay -away. ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Attr.ClassUseCDATA.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Attr.ClassUseCDATA.txt deleted file mode 100644 index e774b823..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Attr.ClassUseCDATA.txt +++ /dev/null @@ -1,19 +0,0 @@ -Attr.ClassUseCDATA -TYPE: bool/null -DEFAULT: null -VERSION: 4.0.0 ---DESCRIPTION-- -If null, class will auto-detect the doctype and, if matching XHTML 1.1 or -XHTML 2.0, will use the restrictive NMTOKENS specification of class. Otherwise, -it will use a relaxed CDATA definition. If true, the relaxed CDATA definition -is forced; if false, the NMTOKENS definition is forced. To get behavior -of HTML Purifier prior to 4.0.0, set this directive to false. - -Some rational behind the auto-detection: -in previous versions of HTML Purifier, it was assumed that the form of -class was NMTOKENS, as specified by the XHTML Modularization (representing -XHTML 1.1 and XHTML 2.0). The DTDs for HTML 4.01 and XHTML 1.0, however -specify class as CDATA. HTML 5 effectively defines it as CDATA, but -with the additional constraint that each name should be unique (this is not -explicitly outlined in previous specifications). ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Attr.DefaultImageAlt.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Attr.DefaultImageAlt.txt deleted file mode 100644 index 533165e1..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Attr.DefaultImageAlt.txt +++ /dev/null @@ -1,11 +0,0 @@ -Attr.DefaultImageAlt -TYPE: string/null -DEFAULT: null -VERSION: 3.2.0 ---DESCRIPTION-- -This is the content of the alt tag of an image if the user had not -previously specified an alt attribute. This applies to all images without -a valid alt attribute, as opposed to %Attr.DefaultInvalidImageAlt, which -only applies to invalid images, and overrides in the case of an invalid image. -Default behavior with null is to use the basename of the src tag for the alt. ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Attr.DefaultInvalidImage.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Attr.DefaultInvalidImage.txt deleted file mode 100644 index 9eb7e384..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Attr.DefaultInvalidImage.txt +++ /dev/null @@ -1,9 +0,0 @@ -Attr.DefaultInvalidImage -TYPE: string -DEFAULT: '' ---DESCRIPTION-- -This is the default image an img tag will be pointed to if it does not have -a valid src attribute. In future versions, we may allow the image tag to -be removed completely, but due to design issues, this is not possible right -now. ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Attr.DefaultInvalidImageAlt.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Attr.DefaultInvalidImageAlt.txt deleted file mode 100644 index 2f17bf47..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Attr.DefaultInvalidImageAlt.txt +++ /dev/null @@ -1,8 +0,0 @@ -Attr.DefaultInvalidImageAlt -TYPE: string -DEFAULT: 'Invalid image' ---DESCRIPTION-- -This is the content of the alt tag of an invalid image if the user had not -previously specified an alt attribute. It has no effect when the image is -valid but there was no alt attribute present. ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Attr.DefaultTextDir.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Attr.DefaultTextDir.txt deleted file mode 100644 index 52654b53..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Attr.DefaultTextDir.txt +++ /dev/null @@ -1,10 +0,0 @@ -Attr.DefaultTextDir -TYPE: string -DEFAULT: 'ltr' ---DESCRIPTION-- -Defines the default text direction (ltr or rtl) of the document being -parsed. This generally is the same as the value of the dir attribute in -HTML, or ltr if that is not specified. ---ALLOWED-- -'ltr', 'rtl' ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Attr.EnableID.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Attr.EnableID.txt deleted file mode 100644 index 6440d210..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Attr.EnableID.txt +++ /dev/null @@ -1,16 +0,0 @@ -Attr.EnableID -TYPE: bool -DEFAULT: false -VERSION: 1.2.0 ---DESCRIPTION-- -Allows the ID attribute in HTML. This is disabled by default due to the -fact that without proper configuration user input can easily break the -validation of a webpage by specifying an ID that is already on the -surrounding HTML. If you don't mind throwing caution to the wind, enable -this directive, but I strongly recommend you also consider blacklisting IDs -you use (%Attr.IDBlacklist) or prefixing all user supplied IDs -(%Attr.IDPrefix). When set to true HTML Purifier reverts to the behavior of -pre-1.2.0 versions. ---ALIASES-- -HTML.EnableAttrID ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Attr.ForbiddenClasses.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Attr.ForbiddenClasses.txt deleted file mode 100644 index f31d226f..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Attr.ForbiddenClasses.txt +++ /dev/null @@ -1,8 +0,0 @@ -Attr.ForbiddenClasses -TYPE: lookup -VERSION: 4.0.0 -DEFAULT: array() ---DESCRIPTION-- -List of forbidden class values in the class attribute. By default, this is -empty, which means that no classes are forbidden. See also %Attr.AllowedClasses. ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Attr.IDBlacklist.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Attr.IDBlacklist.txt deleted file mode 100644 index 5f2b5e3d..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Attr.IDBlacklist.txt +++ /dev/null @@ -1,5 +0,0 @@ -Attr.IDBlacklist -TYPE: list -DEFAULT: array() -DESCRIPTION: Array of IDs not allowed in the document. ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Attr.IDBlacklistRegexp.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Attr.IDBlacklistRegexp.txt deleted file mode 100644 index 6f582458..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Attr.IDBlacklistRegexp.txt +++ /dev/null @@ -1,9 +0,0 @@ -Attr.IDBlacklistRegexp -TYPE: string/null -VERSION: 1.6.0 -DEFAULT: NULL ---DESCRIPTION-- -PCRE regular expression to be matched against all IDs. If the expression is -matches, the ID is rejected. Use this with care: may cause significant -degradation. ID matching is done after all other validation. ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Attr.IDPrefix.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Attr.IDPrefix.txt deleted file mode 100644 index cc49d43f..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Attr.IDPrefix.txt +++ /dev/null @@ -1,12 +0,0 @@ -Attr.IDPrefix -TYPE: string -VERSION: 1.2.0 -DEFAULT: '' ---DESCRIPTION-- -String to prefix to IDs. If you have no idea what IDs your pages may use, -you may opt to simply add a prefix to all user-submitted ID attributes so -that they are still usable, but will not conflict with core page IDs. -Example: setting the directive to 'user_' will result in a user submitted -'foo' to become 'user_foo' Be sure to set %HTML.EnableAttrID to true -before using this. ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Attr.IDPrefixLocal.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Attr.IDPrefixLocal.txt deleted file mode 100644 index 2c5924a7..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Attr.IDPrefixLocal.txt +++ /dev/null @@ -1,14 +0,0 @@ -Attr.IDPrefixLocal -TYPE: string -VERSION: 1.2.0 -DEFAULT: '' ---DESCRIPTION-- -Temporary prefix for IDs used in conjunction with %Attr.IDPrefix. If you -need to allow multiple sets of user content on web page, you may need to -have a seperate prefix that changes with each iteration. This way, -seperately submitted user content displayed on the same page doesn't -clobber each other. Ideal values are unique identifiers for the content it -represents (i.e. the id of the row in the database). Be sure to add a -seperator (like an underscore) at the end. Warning: this directive will -not work unless %Attr.IDPrefix is set to a non-empty value! ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/AutoFormat.AutoParagraph.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/AutoFormat.AutoParagraph.txt deleted file mode 100644 index d5caa1bb..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/AutoFormat.AutoParagraph.txt +++ /dev/null @@ -1,31 +0,0 @@ -AutoFormat.AutoParagraph -TYPE: bool -VERSION: 2.0.1 -DEFAULT: false ---DESCRIPTION-- - -<p> - This directive turns on auto-paragraphing, where double newlines are - converted in to paragraphs whenever possible. Auto-paragraphing: -</p> -<ul> - <li>Always applies to inline elements or text in the root node,</li> - <li>Applies to inline elements or text with double newlines in nodes - that allow paragraph tags,</li> - <li>Applies to double newlines in paragraph tags</li> -</ul> -<p> - <code>p</code> tags must be allowed for this directive to take effect. - We do not use <code>br</code> tags for paragraphing, as that is - semantically incorrect. -</p> -<p> - To prevent auto-paragraphing as a content-producer, refrain from using - double-newlines except to specify a new paragraph or in contexts where - it has special meaning (whitespace usually has no meaning except in - tags like <code>pre</code>, so this should not be difficult.) To prevent - the paragraphing of inline text adjacent to block elements, wrap them - in <code>div</code> tags (the behavior is slightly different outside of - the root node.) -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/AutoFormat.Custom.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/AutoFormat.Custom.txt deleted file mode 100644 index 2a476481..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/AutoFormat.Custom.txt +++ /dev/null @@ -1,12 +0,0 @@ -AutoFormat.Custom -TYPE: list -VERSION: 2.0.1 -DEFAULT: array() ---DESCRIPTION-- - -<p> - This directive can be used to add custom auto-format injectors. - Specify an array of injector names (class name minus the prefix) - or concrete implementations. Injector class must exist. -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/AutoFormat.DisplayLinkURI.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/AutoFormat.DisplayLinkURI.txt deleted file mode 100644 index 663064a3..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/AutoFormat.DisplayLinkURI.txt +++ /dev/null @@ -1,11 +0,0 @@ -AutoFormat.DisplayLinkURI -TYPE: bool -VERSION: 3.2.0 -DEFAULT: false ---DESCRIPTION-- -<p> - This directive turns on the in-text display of URIs in <a> tags, and disables - those links. For example, <a href="http://example.com">example</a> becomes - example (<a>http://example.com</a>). -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/AutoFormat.Linkify.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/AutoFormat.Linkify.txt deleted file mode 100644 index 3a48ba96..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/AutoFormat.Linkify.txt +++ /dev/null @@ -1,12 +0,0 @@ -AutoFormat.Linkify -TYPE: bool -VERSION: 2.0.1 -DEFAULT: false ---DESCRIPTION-- - -<p> - This directive turns on linkification, auto-linking http, ftp and - https URLs. <code>a</code> tags with the <code>href</code> attribute - must be allowed. -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/AutoFormat.PurifierLinkify.DocURL.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/AutoFormat.PurifierLinkify.DocURL.txt deleted file mode 100644 index db58b134..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/AutoFormat.PurifierLinkify.DocURL.txt +++ /dev/null @@ -1,12 +0,0 @@ -AutoFormat.PurifierLinkify.DocURL -TYPE: string -VERSION: 2.0.1 -DEFAULT: '#%s' -ALIASES: AutoFormatParam.PurifierLinkifyDocURL ---DESCRIPTION-- -<p> - Location of configuration documentation to link to, let %s substitute - into the configuration's namespace and directive names sans the percent - sign. -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/AutoFormat.PurifierLinkify.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/AutoFormat.PurifierLinkify.txt deleted file mode 100644 index 7996488b..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/AutoFormat.PurifierLinkify.txt +++ /dev/null @@ -1,12 +0,0 @@ -AutoFormat.PurifierLinkify -TYPE: bool -VERSION: 2.0.1 -DEFAULT: false ---DESCRIPTION-- - -<p> - Internal auto-formatter that converts configuration directives in - syntax <a>%Namespace.Directive</a> to links. <code>a</code> tags - with the <code>href</code> attribute must be allowed. -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions.txt deleted file mode 100644 index 35c393b4..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions.txt +++ /dev/null @@ -1,11 +0,0 @@ -AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions -TYPE: lookup -VERSION: 4.0.0 -DEFAULT: array('td' => true, 'th' => true) ---DESCRIPTION-- -<p> - When %AutoFormat.RemoveEmpty and %AutoFormat.RemoveEmpty.RemoveNbsp - are enabled, this directive defines what HTML elements should not be - removede if they have only a non-breaking space in them. -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.RemoveNbsp.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.RemoveNbsp.txt deleted file mode 100644 index ca17eb1d..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.RemoveNbsp.txt +++ /dev/null @@ -1,15 +0,0 @@ -AutoFormat.RemoveEmpty.RemoveNbsp -TYPE: bool -VERSION: 4.0.0 -DEFAULT: false ---DESCRIPTION-- -<p> - When enabled, HTML Purifier will treat any elements that contain only - non-breaking spaces as well as regular whitespace as empty, and remove - them when %AutoForamt.RemoveEmpty is enabled. -</p> -<p> - See %AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions for a list of elements - that don't have this behavior applied to them. -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.txt deleted file mode 100644 index 34657ba4..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.txt +++ /dev/null @@ -1,46 +0,0 @@ -AutoFormat.RemoveEmpty -TYPE: bool -VERSION: 3.2.0 -DEFAULT: false ---DESCRIPTION-- -<p> - When enabled, HTML Purifier will attempt to remove empty elements that - contribute no semantic information to the document. The following types - of nodes will be removed: -</p> -<ul><li> - Tags with no attributes and no content, and that are not empty - elements (remove <code><a></a></code> but not - <code><br /></code>), and - </li> - <li> - Tags with no content, except for:<ul> - <li>The <code>colgroup</code> element, or</li> - <li> - Elements with the <code>id</code> or <code>name</code> attribute, - when those attributes are permitted on those elements. - </li> - </ul></li> -</ul> -<p> - Please be very careful when using this functionality; while it may not - seem that empty elements contain useful information, they can alter the - layout of a document given appropriate styling. This directive is most - useful when you are processing machine-generated HTML, please avoid using - it on regular user HTML. -</p> -<p> - Elements that contain only whitespace will be treated as empty. Non-breaking - spaces, however, do not count as whitespace. See - %AutoFormat.RemoveEmpty.RemoveNbsp for alternate behavior. -</p> -<p> - This algorithm is not perfect; you may still notice some empty tags, - particularly if a node had elements, but those elements were later removed - because they were not permitted in that context, or tags that, after - being auto-closed by another tag, where empty. This is for safety reasons - to prevent clever code from breaking validation. The general rule of thumb: - if a tag looked empty on the way in, it will get removed; if HTML Purifier - made it empty, it will stay. -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/CSS.AllowImportant.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/CSS.AllowImportant.txt deleted file mode 100644 index b324608f..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/CSS.AllowImportant.txt +++ /dev/null @@ -1,8 +0,0 @@ -CSS.AllowImportant -TYPE: bool -DEFAULT: false -VERSION: 3.1.0 ---DESCRIPTION-- -This parameter determines whether or not !important cascade modifiers should -be allowed in user CSS. If false, !important will stripped. ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/CSS.AllowTricky.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/CSS.AllowTricky.txt deleted file mode 100644 index 748be0ee..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/CSS.AllowTricky.txt +++ /dev/null @@ -1,11 +0,0 @@ -CSS.AllowTricky -TYPE: bool -DEFAULT: false -VERSION: 3.1.0 ---DESCRIPTION-- -This parameter determines whether or not to allow "tricky" CSS properties and -values. Tricky CSS properties/values can drastically modify page layout or -be used for deceptive practices but do not directly constitute a security risk. -For example, <code>display:none;</code> is considered a tricky property that -will only be allowed if this directive is set to true. ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/CSS.AllowedProperties.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/CSS.AllowedProperties.txt deleted file mode 100644 index 460112eb..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/CSS.AllowedProperties.txt +++ /dev/null @@ -1,18 +0,0 @@ -CSS.AllowedProperties -TYPE: lookup/null -VERSION: 3.1.0 -DEFAULT: NULL ---DESCRIPTION-- - -<p> - If HTML Purifier's style attributes set is unsatisfactory for your needs, - you can overload it with your own list of tags to allow. Note that this - method is subtractive: it does its job by taking away from HTML Purifier - usual feature set, so you cannot add an attribute that HTML Purifier never - supported in the first place. -</p> -<p> - <strong>Warning:</strong> If another directive conflicts with the - elements here, <em>that</em> directive will win and override. -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/CSS.DefinitionRev.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/CSS.DefinitionRev.txt deleted file mode 100644 index 5cb7dda3..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/CSS.DefinitionRev.txt +++ /dev/null @@ -1,11 +0,0 @@ -CSS.DefinitionRev -TYPE: int -VERSION: 2.0.0 -DEFAULT: 1 ---DESCRIPTION-- - -<p> - Revision identifier for your custom definition. See - %HTML.DefinitionRev for details. -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/CSS.MaxImgLength.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/CSS.MaxImgLength.txt deleted file mode 100644 index 7a329147..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/CSS.MaxImgLength.txt +++ /dev/null @@ -1,16 +0,0 @@ -CSS.MaxImgLength -TYPE: string/null -DEFAULT: '1200px' -VERSION: 3.1.1 ---DESCRIPTION-- -<p> - This parameter sets the maximum allowed length on <code>img</code> tags, - effectively the <code>width</code> and <code>height</code> properties. - Only absolute units of measurement (in, pt, pc, mm, cm) and pixels (px) are allowed. This is - in place to prevent imagecrash attacks, disable with null at your own risk. - This directive is similar to %HTML.MaxImgLength, and both should be - concurrently edited, although there are - subtle differences in the input format (the CSS max is a number with - a unit). -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/CSS.Proprietary.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/CSS.Proprietary.txt deleted file mode 100644 index 148eedb8..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/CSS.Proprietary.txt +++ /dev/null @@ -1,10 +0,0 @@ -CSS.Proprietary -TYPE: bool -VERSION: 3.0.0 -DEFAULT: false ---DESCRIPTION-- - -<p> - Whether or not to allow safe, proprietary CSS values. -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Cache.DefinitionImpl.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Cache.DefinitionImpl.txt deleted file mode 100644 index c486724c..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Cache.DefinitionImpl.txt +++ /dev/null @@ -1,14 +0,0 @@ -Cache.DefinitionImpl -TYPE: string/null -VERSION: 2.0.0 -DEFAULT: 'Serializer' ---DESCRIPTION-- - -This directive defines which method to use when caching definitions, -the complex data-type that makes HTML Purifier tick. Set to null -to disable caching (not recommended, as you will see a definite -performance degradation). - ---ALIASES-- -Core.DefinitionCache ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Cache.SerializerPath.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Cache.SerializerPath.txt deleted file mode 100644 index 54036507..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Cache.SerializerPath.txt +++ /dev/null @@ -1,13 +0,0 @@ -Cache.SerializerPath -TYPE: string/null -VERSION: 2.0.0 -DEFAULT: NULL ---DESCRIPTION-- - -<p> - Absolute path with no trailing slash to store serialized definitions in. - Default is within the - HTML Purifier library inside DefinitionCache/Serializer. This - path must be writable by the webserver. -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Core.AggressivelyFixLt.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Core.AggressivelyFixLt.txt deleted file mode 100644 index 568cbf3b..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Core.AggressivelyFixLt.txt +++ /dev/null @@ -1,18 +0,0 @@ -Core.AggressivelyFixLt -TYPE: bool -VERSION: 2.1.0 -DEFAULT: true ---DESCRIPTION-- -<p> - This directive enables aggressive pre-filter fixes HTML Purifier can - perform in order to ensure that open angled-brackets do not get killed - during parsing stage. Enabling this will result in two preg_replace_callback - calls and at least two preg_replace calls for every HTML document parsed; - if your users make very well-formed HTML, you can set this directive false. - This has no effect when DirectLex is used. -</p> -<p> - <strong>Notice:</strong> This directive's default turned from false to true - in HTML Purifier 3.2.0. -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Core.CollectErrors.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Core.CollectErrors.txt deleted file mode 100644 index d7317911..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Core.CollectErrors.txt +++ /dev/null @@ -1,12 +0,0 @@ -Core.CollectErrors -TYPE: bool -VERSION: 2.0.0 -DEFAULT: false ---DESCRIPTION-- - -Whether or not to collect errors found while filtering the document. This -is a useful way to give feedback to your users. <strong>Warning:</strong> -Currently this feature is very patchy and experimental, with lots of -possible error messages not yet implemented. It will not cause any -problems, but it may not help your users either. ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Core.ColorKeywords.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Core.ColorKeywords.txt deleted file mode 100644 index 08b381d3..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Core.ColorKeywords.txt +++ /dev/null @@ -1,28 +0,0 @@ -Core.ColorKeywords -TYPE: hash -VERSION: 2.0.0 ---DEFAULT-- -array ( - 'maroon' => '#800000', - 'red' => '#FF0000', - 'orange' => '#FFA500', - 'yellow' => '#FFFF00', - 'olive' => '#808000', - 'purple' => '#800080', - 'fuchsia' => '#FF00FF', - 'white' => '#FFFFFF', - 'lime' => '#00FF00', - 'green' => '#008000', - 'navy' => '#000080', - 'blue' => '#0000FF', - 'aqua' => '#00FFFF', - 'teal' => '#008080', - 'black' => '#000000', - 'silver' => '#C0C0C0', - 'gray' => '#808080', -) ---DESCRIPTION-- - -Lookup array of color names to six digit hexadecimal number corresponding -to color, with preceding hash mark. Used when parsing colors. ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Core.ConvertDocumentToFragment.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Core.ConvertDocumentToFragment.txt deleted file mode 100644 index 64b114fc..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Core.ConvertDocumentToFragment.txt +++ /dev/null @@ -1,14 +0,0 @@ -Core.ConvertDocumentToFragment -TYPE: bool -DEFAULT: true ---DESCRIPTION-- - -This parameter determines whether or not the filter should convert -input that is a full document with html and body tags to a fragment -of just the contents of a body tag. This parameter is simply something -HTML Purifier can do during an edge-case: for most inputs, this -processing is not necessary. - ---ALIASES-- -Core.AcceptFullDocuments ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Core.DirectLexLineNumberSyncInterval.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Core.DirectLexLineNumberSyncInterval.txt deleted file mode 100644 index 36f16e07..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Core.DirectLexLineNumberSyncInterval.txt +++ /dev/null @@ -1,17 +0,0 @@ -Core.DirectLexLineNumberSyncInterval -TYPE: int -VERSION: 2.0.0 -DEFAULT: 0 ---DESCRIPTION-- - -<p> - Specifies the number of tokens the DirectLex line number tracking - implementations should process before attempting to resyncronize the - current line count by manually counting all previous new-lines. When - at 0, this functionality is disabled. Lower values will decrease - performance, and this is only strictly necessary if the counting - algorithm is buggy (in which case you should report it as a bug). - This has no effect when %Core.MaintainLineNumbers is disabled or DirectLex is - not being used. -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Core.Encoding.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Core.Encoding.txt deleted file mode 100644 index 8bfb47c3..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Core.Encoding.txt +++ /dev/null @@ -1,15 +0,0 @@ -Core.Encoding -TYPE: istring -DEFAULT: 'utf-8' ---DESCRIPTION-- -If for some reason you are unable to convert all webpages to UTF-8, you can -use this directive as a stop-gap compatibility change to let HTML Purifier -deal with non UTF-8 input. This technique has notable deficiencies: -absolutely no characters outside of the selected character encoding will be -preserved, not even the ones that have been ampersand escaped (this is due -to a UTF-8 specific <em>feature</em> that automatically resolves all -entities), making it pretty useless for anything except the most I18N-blind -applications, although %Core.EscapeNonASCIICharacters offers fixes this -trouble with another tradeoff. This directive only accepts ISO-8859-1 if -iconv is not enabled. ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Core.EscapeInvalidChildren.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Core.EscapeInvalidChildren.txt deleted file mode 100644 index 4d5b5055..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Core.EscapeInvalidChildren.txt +++ /dev/null @@ -1,10 +0,0 @@ -Core.EscapeInvalidChildren -TYPE: bool -DEFAULT: false ---DESCRIPTION-- -When true, a child is found that is not allowed in the context of the -parent element will be transformed into text as if it were ASCII. When -false, that element and all internal tags will be dropped, though text will -be preserved. There is no option for dropping the element but preserving -child nodes. ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Core.EscapeInvalidTags.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Core.EscapeInvalidTags.txt deleted file mode 100644 index a7a5b249..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Core.EscapeInvalidTags.txt +++ /dev/null @@ -1,7 +0,0 @@ -Core.EscapeInvalidTags -TYPE: bool -DEFAULT: false ---DESCRIPTION-- -When true, invalid tags will be written back to the document as plain text. -Otherwise, they are silently dropped. ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Core.EscapeNonASCIICharacters.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Core.EscapeNonASCIICharacters.txt deleted file mode 100644 index abb49994..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Core.EscapeNonASCIICharacters.txt +++ /dev/null @@ -1,13 +0,0 @@ -Core.EscapeNonASCIICharacters -TYPE: bool -VERSION: 1.4.0 -DEFAULT: false ---DESCRIPTION-- -This directive overcomes a deficiency in %Core.Encoding by blindly -converting all non-ASCII characters into decimal numeric entities before -converting it to its native encoding. This means that even characters that -can be expressed in the non-UTF-8 encoding will be entity-ized, which can -be a real downer for encodings like Big5. It also assumes that the ASCII -repetoire is available, although this is the case for almost all encodings. -Anyway, use UTF-8! ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Core.HiddenElements.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Core.HiddenElements.txt deleted file mode 100644 index 915391ed..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Core.HiddenElements.txt +++ /dev/null @@ -1,19 +0,0 @@ -Core.HiddenElements -TYPE: lookup ---DEFAULT-- -array ( - 'script' => true, - 'style' => true, -) ---DESCRIPTION-- - -<p> - This directive is a lookup array of elements which should have their - contents removed when they are not allowed by the HTML definition. - For example, the contents of a <code>script</code> tag are not - normally shown in a document, so if script tags are to be removed, - their contents should be removed to. This is opposed to a <code>b</code> - tag, which defines some presentational changes but does not hide its - contents. -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Core.Language.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Core.Language.txt deleted file mode 100644 index 233fca14..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Core.Language.txt +++ /dev/null @@ -1,10 +0,0 @@ -Core.Language -TYPE: string -VERSION: 2.0.0 -DEFAULT: 'en' ---DESCRIPTION-- - -ISO 639 language code for localizable things in HTML Purifier to use, -which is mainly error reporting. There is currently only an English (en) -translation, so this directive is currently useless. ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Core.LexerImpl.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Core.LexerImpl.txt deleted file mode 100644 index 8983e2cc..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Core.LexerImpl.txt +++ /dev/null @@ -1,34 +0,0 @@ -Core.LexerImpl -TYPE: mixed/null -VERSION: 2.0.0 -DEFAULT: NULL ---DESCRIPTION-- - -<p> - This parameter determines what lexer implementation can be used. The - valid values are: -</p> -<dl> - <dt><em>null</em></dt> - <dd> - Recommended, the lexer implementation will be auto-detected based on - your PHP-version and configuration. - </dd> - <dt><em>string</em> lexer identifier</dt> - <dd> - This is a slim way of manually overridding the implementation. - Currently recognized values are: DOMLex (the default PHP5 -implementation) - and DirectLex (the default PHP4 implementation). Only use this if - you know what you are doing: usually, the auto-detection will - manage things for cases you aren't even aware of. - </dd> - <dt><em>object</em> lexer instance</dt> - <dd> - Super-advanced: you can specify your own, custom, implementation that - implements the interface defined by <code>HTMLPurifier_Lexer</code>. - I may remove this option simply because I don't expect anyone - to use it. - </dd> -</dl> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Core.MaintainLineNumbers.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Core.MaintainLineNumbers.txt deleted file mode 100644 index eb841a75..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Core.MaintainLineNumbers.txt +++ /dev/null @@ -1,16 +0,0 @@ -Core.MaintainLineNumbers -TYPE: bool/null -VERSION: 2.0.0 -DEFAULT: NULL ---DESCRIPTION-- - -<p> - If true, HTML Purifier will add line number information to all tokens. - This is useful when error reporting is turned on, but can result in - significant performance degradation and should not be used when - unnecessary. This directive must be used with the DirectLex lexer, - as the DOMLex lexer does not (yet) support this functionality. - If the value is null, an appropriate value will be selected based - on other configuration. -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Core.RemoveInvalidImg.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Core.RemoveInvalidImg.txt deleted file mode 100644 index 4070c2a0..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Core.RemoveInvalidImg.txt +++ /dev/null @@ -1,12 +0,0 @@ -Core.RemoveInvalidImg -TYPE: bool -DEFAULT: true -VERSION: 1.3.0 ---DESCRIPTION-- - -<p> - This directive enables pre-emptive URI checking in <code>img</code> - tags, as the attribute validation strategy is not authorized to - remove elements from the document. Revert to pre-1.3.0 behavior by setting to false. -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Core.RemoveScriptContents.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Core.RemoveScriptContents.txt deleted file mode 100644 index a4cd966d..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Core.RemoveScriptContents.txt +++ /dev/null @@ -1,12 +0,0 @@ -Core.RemoveScriptContents -TYPE: bool/null -DEFAULT: NULL -VERSION: 2.0.0 -DEPRECATED-VERSION: 2.1.0 -DEPRECATED-USE: Core.HiddenElements ---DESCRIPTION-- -<p> - This directive enables HTML Purifier to remove not only script tags - but all of their contents. -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Filter.Custom.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Filter.Custom.txt deleted file mode 100644 index 3db50ef2..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Filter.Custom.txt +++ /dev/null @@ -1,11 +0,0 @@ -Filter.Custom -TYPE: list -VERSION: 3.1.0 -DEFAULT: array() ---DESCRIPTION-- -<p> - This directive can be used to add custom filters; it is nearly the - equivalent of the now deprecated <code>HTMLPurifier->addFilter()</code> - method. Specify an array of concrete implementations. -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.Escaping.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.Escaping.txt deleted file mode 100644 index 16829bcd..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.Escaping.txt +++ /dev/null @@ -1,14 +0,0 @@ -Filter.ExtractStyleBlocks.Escaping -TYPE: bool -VERSION: 3.0.0 -DEFAULT: true -ALIASES: Filter.ExtractStyleBlocksEscaping, FilterParam.ExtractStyleBlocksEscaping ---DESCRIPTION-- - -<p> - Whether or not to escape the dangerous characters <, > and & - as \3C, \3E and \26, respectively. This is can be safely set to false - if the contents of StyleBlocks will be placed in an external stylesheet, - where there is no risk of it being interpreted as HTML. -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.Scope.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.Scope.txt deleted file mode 100644 index 7f95f54d..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.Scope.txt +++ /dev/null @@ -1,29 +0,0 @@ -Filter.ExtractStyleBlocks.Scope -TYPE: string/null -VERSION: 3.0.0 -DEFAULT: NULL -ALIASES: Filter.ExtractStyleBlocksScope, FilterParam.ExtractStyleBlocksScope ---DESCRIPTION-- - -<p> - If you would like users to be able to define external stylesheets, but - only allow them to specify CSS declarations for a specific node and - prevent them from fiddling with other elements, use this directive. - It accepts any valid CSS selector, and will prepend this to any - CSS declaration extracted from the document. For example, if this - directive is set to <code>#user-content</code> and a user uses the - selector <code>a:hover</code>, the final selector will be - <code>#user-content a:hover</code>. -</p> -<p> - The comma shorthand may be used; consider the above example, with - <code>#user-content, #user-content2</code>, the final selector will - be <code>#user-content a:hover, #user-content2 a:hover</code>. -</p> -<p> - <strong>Warning:</strong> It is possible for users to bypass this measure - using a naughty + selector. This is a bug in CSS Tidy 1.3, not HTML - Purifier, and I am working to get it fixed. Until then, HTML Purifier - performs a basic check to prevent this. -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.TidyImpl.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.TidyImpl.txt deleted file mode 100644 index 6c231b2d..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.TidyImpl.txt +++ /dev/null @@ -1,16 +0,0 @@ -Filter.ExtractStyleBlocks.TidyImpl -TYPE: mixed/null -VERSION: 3.1.0 -DEFAULT: NULL -ALIASES: FilterParam.ExtractStyleBlocksTidyImpl ---DESCRIPTION-- -<p> - If left NULL, HTML Purifier will attempt to instantiate a <code>csstidy</code> - class to use for internal cleaning. This will usually be good enough. -</p> -<p> - However, for trusted user input, you can set this to <code>false</code> to - disable cleaning. In addition, you can supply your own concrete implementation - of Tidy's interface to use, although I don't know why you'd want to do that. -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.txt deleted file mode 100644 index 078d0874..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.txt +++ /dev/null @@ -1,74 +0,0 @@ -Filter.ExtractStyleBlocks -TYPE: bool -VERSION: 3.1.0 -DEFAULT: false -EXTERNAL: CSSTidy ---DESCRIPTION-- -<p> - This directive turns on the style block extraction filter, which removes - <code>style</code> blocks from input HTML, cleans them up with CSSTidy, - and places them in the <code>StyleBlocks</code> context variable, for further - use by you, usually to be placed in an external stylesheet, or a - <code>style</code> block in the <code>head</code> of your document. -</p> -<p> - Sample usage: -</p> -<pre><![CDATA[ -<?php - header('Content-type: text/html; charset=utf-8'); - echo '<?xml version="1.0" encoding="UTF-8"?>'; -?> -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> -<head> - <title>Filter.ExtractStyleBlocks</title> -<?php - require_once '/path/to/library/HTMLPurifier.auto.php'; - require_once '/path/to/csstidy.class.php'; - - $dirty = '<style>body {color:#F00;}</style> Some text'; - - $config = HTMLPurifier_Config::createDefault(); - $config->set('Filter', 'ExtractStyleBlocks', true); - $purifier = new HTMLPurifier($config); - - $html = $purifier->purify($dirty); - - // This implementation writes the stylesheets to the styles/ directory. - // You can also echo the styles inside the document, but it's a bit - // more difficult to make sure they get interpreted properly by - // browsers; try the usual CSS armoring techniques. - $styles = $purifier->context->get('StyleBlocks'); - $dir = 'styles/'; - if (!is_dir($dir)) mkdir($dir); - $hash = sha1($_GET['html']); - foreach ($styles as $i => $style) { - file_put_contents($name = $dir . $hash . "_$i"); - echo '<link rel="stylesheet" type="text/css" href="'.$name.'" />'; - } -?> -</head> -<body> - <div> - <?php echo $html; ?> - </div> -</b]]><![CDATA[ody> -</html> -]]></pre> -<p> - <strong>Warning:</strong> It is possible for a user to mount an - imagecrash attack using this CSS. Counter-measures are difficult; - it is not simply enough to limit the range of CSS lengths (using - relative lengths with many nesting levels allows for large values - to be attained without actually specifying them in the stylesheet), - and the flexible nature of selectors makes it difficult to selectively - disable lengths on image tags (HTML Purifier, however, does disable - CSS width and height in inline styling). There are probably two effective - counter measures: an explicit width and height set to auto in all - images in your document (unlikely) or the disabling of width and - height (somewhat reasonable). Whether or not these measures should be - used is left to the reader. -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Filter.YouTube.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Filter.YouTube.txt deleted file mode 100644 index 7fa6536b..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Filter.YouTube.txt +++ /dev/null @@ -1,11 +0,0 @@ -Filter.YouTube -TYPE: bool -VERSION: 3.1.0 -DEFAULT: false ---DESCRIPTION-- -<p> - This directive enables YouTube video embedding in HTML Purifier. Check - <a href="http://htmlpurifier.org/docs/enduser-youtube.html">this document - on embedding videos</a> for more information on what this filter does. -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.Allowed.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.Allowed.txt deleted file mode 100644 index 3e231d2d..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.Allowed.txt +++ /dev/null @@ -1,22 +0,0 @@ -HTML.Allowed -TYPE: itext/null -VERSION: 2.0.0 -DEFAULT: NULL ---DESCRIPTION-- - -<p> - This is a convenience directive that rolls the functionality of - %HTML.AllowedElements and %HTML.AllowedAttributes into one directive. - Specify elements and attributes that are allowed using: - <code>element1[attr1|attr2],element2...</code>. You can also use - newlines instead of commas to separate elements. -</p> -<p> - <strong>Warning</strong>: - All of the constraints on the component directives are still enforced. - The syntax is a <em>subset</em> of TinyMCE's <code>valid_elements</code> - whitelist: directly copy-pasting it here will probably result in - broken whitelists. If %HTML.AllowedElements or %HTML.AllowedAttributes - are set, this directive has no effect. -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.AllowedAttributes.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.AllowedAttributes.txt deleted file mode 100644 index fcf093f1..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.AllowedAttributes.txt +++ /dev/null @@ -1,19 +0,0 @@ -HTML.AllowedAttributes -TYPE: lookup/null -VERSION: 1.3.0 -DEFAULT: NULL ---DESCRIPTION-- - -<p> - If HTML Purifier's attribute set is unsatisfactory, overload it! - The syntax is "tag.attr" or "*.attr" for the global attributes - (style, id, class, dir, lang, xml:lang). -</p> -<p> - <strong>Warning:</strong> If another directive conflicts with the - elements here, <em>that</em> directive will win and override. For - example, %HTML.EnableAttrID will take precedence over *.id in this - directive. You must set that directive to true before you can use - IDs at all. -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.AllowedElements.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.AllowedElements.txt deleted file mode 100644 index 888d5581..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.AllowedElements.txt +++ /dev/null @@ -1,18 +0,0 @@ -HTML.AllowedElements -TYPE: lookup/null -VERSION: 1.3.0 -DEFAULT: NULL ---DESCRIPTION-- -<p> - If HTML Purifier's tag set is unsatisfactory for your needs, you - can overload it with your own list of tags to allow. Note that this - method is subtractive: it does its job by taking away from HTML Purifier - usual feature set, so you cannot add a tag that HTML Purifier never - supported in the first place (like embed, form or head). If you - change this, you probably also want to change %HTML.AllowedAttributes. -</p> -<p> - <strong>Warning:</strong> If another directive conflicts with the - elements here, <em>that</em> directive will win and override. -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.AllowedModules.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.AllowedModules.txt deleted file mode 100644 index 5a59a55c..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.AllowedModules.txt +++ /dev/null @@ -1,20 +0,0 @@ -HTML.AllowedModules -TYPE: lookup/null -VERSION: 2.0.0 -DEFAULT: NULL ---DESCRIPTION-- - -<p> - A doctype comes with a set of usual modules to use. Without having - to mucking about with the doctypes, you can quickly activate or - disable these modules by specifying which modules you wish to allow - with this directive. This is most useful for unit testing specific - modules, although end users may find it useful for their own ends. -</p> -<p> - If you specify a module that does not exist, the manager will silently - fail to use it, so be careful! User-defined modules are not affected - by this directive. Modules defined in %HTML.CoreModules are not - affected by this directive. -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.Attr.Name.UseCDATA.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.Attr.Name.UseCDATA.txt deleted file mode 100644 index 151fb7b8..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.Attr.Name.UseCDATA.txt +++ /dev/null @@ -1,11 +0,0 @@ -HTML.Attr.Name.UseCDATA -TYPE: bool -DEFAULT: false -VERSION: 4.0.0 ---DESCRIPTION-- -The W3C specification DTD defines the name attribute to be CDATA, not ID, due -to limitations of DTD. In certain documents, this relaxed behavior is desired, -whether it is to specify duplicate names, or to specify names that would be -illegal IDs (for example, names that begin with a digit.) Set this configuration -directive to true to use the relaxed parsing rules. ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.BlockWrapper.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.BlockWrapper.txt deleted file mode 100644 index 45ae469e..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.BlockWrapper.txt +++ /dev/null @@ -1,18 +0,0 @@ -HTML.BlockWrapper -TYPE: string -VERSION: 1.3.0 -DEFAULT: 'p' ---DESCRIPTION-- - -<p> - String name of element to wrap inline elements that are inside a block - context. This only occurs in the children of blockquote in strict mode. -</p> -<p> - Example: by default value, - <code><blockquote>Foo</blockquote></code> would become - <code><blockquote><p>Foo</p></blockquote></code>. - The <code><p></code> tags can be replaced with whatever you desire, - as long as it is a block level element. -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.CoreModules.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.CoreModules.txt deleted file mode 100644 index 52461887..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.CoreModules.txt +++ /dev/null @@ -1,23 +0,0 @@ -HTML.CoreModules -TYPE: lookup -VERSION: 2.0.0 ---DEFAULT-- -array ( - 'Structure' => true, - 'Text' => true, - 'Hypertext' => true, - 'List' => true, - 'NonXMLCommonAttributes' => true, - 'XMLCommonAttributes' => true, - 'CommonAttributes' => true, -) ---DESCRIPTION-- - -<p> - Certain modularized doctypes (XHTML, namely), have certain modules - that must be included for the doctype to be an conforming document - type: put those modules here. By default, XHTML's core modules - are used. You can set this to a blank array to disable core module - protection, but this is not recommended. -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.CustomDoctype.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.CustomDoctype.txt deleted file mode 100644 index a64e3d7c..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.CustomDoctype.txt +++ /dev/null @@ -1,9 +0,0 @@ -HTML.CustomDoctype -TYPE: string/null -VERSION: 2.0.1 -DEFAULT: NULL ---DESCRIPTION-- - -A custom doctype for power-users who defined there own document -type. This directive only applies when %HTML.Doctype is blank. ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.DefinitionID.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.DefinitionID.txt deleted file mode 100644 index 103db754..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.DefinitionID.txt +++ /dev/null @@ -1,33 +0,0 @@ -HTML.DefinitionID -TYPE: string/null -DEFAULT: NULL -VERSION: 2.0.0 ---DESCRIPTION-- - -<p> - Unique identifier for a custom-built HTML definition. If you edit - the raw version of the HTMLDefinition, introducing changes that the - configuration object does not reflect, you must specify this variable. - If you change your custom edits, you should change this directive, or - clear your cache. Example: -</p> -<pre> -$config = HTMLPurifier_Config::createDefault(); -$config->set('HTML', 'DefinitionID', '1'); -$def = $config->getHTMLDefinition(); -$def->addAttribute('a', 'tabindex', 'Number'); -</pre> -<p> - In the above example, the configuration is still at the defaults, but - using the advanced API, an extra attribute has been added. The - configuration object normally has no way of knowing that this change - has taken place, so it needs an extra directive: %HTML.DefinitionID. - If someone else attempts to use the default configuration, these two - pieces of code will not clobber each other in the cache, since one has - an extra directive attached to it. -</p> -<p> - You <em>must</em> specify a value to this directive to use the - advanced API features. -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.DefinitionRev.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.DefinitionRev.txt deleted file mode 100644 index 229ae026..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.DefinitionRev.txt +++ /dev/null @@ -1,16 +0,0 @@ -HTML.DefinitionRev -TYPE: int -VERSION: 2.0.0 -DEFAULT: 1 ---DESCRIPTION-- - -<p> - Revision identifier for your custom definition specified in - %HTML.DefinitionID. This serves the same purpose: uniquely identifying - your custom definition, but this one does so in a chronological - context: revision 3 is more up-to-date then revision 2. Thus, when - this gets incremented, the cache handling is smart enough to clean - up any older revisions of your definition as well as flush the - cache. -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.Doctype.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.Doctype.txt deleted file mode 100644 index 9dab497f..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.Doctype.txt +++ /dev/null @@ -1,11 +0,0 @@ -HTML.Doctype -TYPE: string/null -DEFAULT: NULL ---DESCRIPTION-- -Doctype to use during filtering. Technically speaking this is not actually -a doctype (as it does not identify a corresponding DTD), but we are using -this name for sake of simplicity. When non-blank, this will override any -older directives like %HTML.XHTML or %HTML.Strict. ---ALLOWED-- -'HTML 4.01 Transitional', 'HTML 4.01 Strict', 'XHTML 1.0 Transitional', 'XHTML 1.0 Strict', 'XHTML 1.1' ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.ForbiddenAttributes.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.ForbiddenAttributes.txt deleted file mode 100644 index 57358f9b..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.ForbiddenAttributes.txt +++ /dev/null @@ -1,21 +0,0 @@ -HTML.ForbiddenAttributes -TYPE: lookup -VERSION: 3.1.0 -DEFAULT: array() ---DESCRIPTION-- -<p> - While this directive is similar to %HTML.AllowedAttributes, for - forwards-compatibility with XML, this attribute has a different syntax. Instead of - <code>tag.attr</code>, use <code>tag@attr</code>. To disallow <code>href</code> - attributes in <code>a</code> tags, set this directive to - <code>a@href</code>. You can also disallow an attribute globally with - <code>attr</code> or <code>*@attr</code> (either syntax is fine; the latter - is provided for consistency with %HTML.AllowedAttributes). -</p> -<p> - <strong>Warning:</strong> This directive complements %HTML.ForbiddenElements, - accordingly, check - out that directive for a discussion of why you - should think twice before using this directive. -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.ForbiddenElements.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.ForbiddenElements.txt deleted file mode 100644 index 93a53e14..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.ForbiddenElements.txt +++ /dev/null @@ -1,20 +0,0 @@ -HTML.ForbiddenElements -TYPE: lookup -VERSION: 3.1.0 -DEFAULT: array() ---DESCRIPTION-- -<p> - This was, perhaps, the most requested feature ever in HTML - Purifier. Please don't abuse it! This is the logical inverse of - %HTML.AllowedElements, and it will override that directive, or any - other directive. -</p> -<p> - If possible, %HTML.Allowed is recommended over this directive, because it - can sometimes be difficult to tell whether or not you've forbidden all of - the behavior you would like to disallow. If you forbid <code>img</code> - with the expectation of preventing images on your site, you'll be in for - a nasty surprise when people start using the <code>background-image</code> - CSS property. -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.MaxImgLength.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.MaxImgLength.txt deleted file mode 100644 index e424c386..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.MaxImgLength.txt +++ /dev/null @@ -1,14 +0,0 @@ -HTML.MaxImgLength -TYPE: int/null -DEFAULT: 1200 -VERSION: 3.1.1 ---DESCRIPTION-- -<p> - This directive controls the maximum number of pixels in the width and - height attributes in <code>img</code> tags. This is - in place to prevent imagecrash attacks, disable with null at your own risk. - This directive is similar to %CSS.MaxImgLength, and both should be - concurrently edited, although there are - subtle differences in the input format (the HTML max is an integer). -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.Parent.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.Parent.txt deleted file mode 100644 index 62e8e160..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.Parent.txt +++ /dev/null @@ -1,12 +0,0 @@ -HTML.Parent -TYPE: string -VERSION: 1.3.0 -DEFAULT: 'div' ---DESCRIPTION-- - -<p> - String name of element that HTML fragment passed to library will be - inserted in. An interesting variation would be using span as the - parent element, meaning that only inline tags would be allowed. -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.Proprietary.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.Proprietary.txt deleted file mode 100644 index dfb72049..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.Proprietary.txt +++ /dev/null @@ -1,12 +0,0 @@ -HTML.Proprietary -TYPE: bool -VERSION: 3.1.0 -DEFAULT: false ---DESCRIPTION-- -<p> - Whether or not to allow proprietary elements and attributes in your - documents, as per <code>HTMLPurifier_HTMLModule_Proprietary</code>. - <strong>Warning:</strong> This can cause your documents to stop - validating! -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.SafeEmbed.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.SafeEmbed.txt deleted file mode 100644 index f635a685..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.SafeEmbed.txt +++ /dev/null @@ -1,14 +0,0 @@ -HTML.SafeEmbed -TYPE: bool -VERSION: 3.1.1 -DEFAULT: false ---DESCRIPTION-- -<p> - Whether or not to permit embed tags in documents, with a number of extra - security features added to prevent script execution. This is similar to - what websites like MySpace do to embed tags. Embed is a proprietary - element and will cause your website to stop validating. You probably want - to enable this with %HTML.SafeObject. - <strong>Highly experimental.</strong> -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.SafeObject.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.SafeObject.txt deleted file mode 100644 index 32967b88..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.SafeObject.txt +++ /dev/null @@ -1,14 +0,0 @@ -HTML.SafeObject -TYPE: bool -VERSION: 3.1.1 -DEFAULT: false ---DESCRIPTION-- -<p> - Whether or not to permit object tags in documents, with a number of extra - security features added to prevent script execution. This is similar to - what websites like MySpace do to object tags. You may also want to - enable %HTML.SafeEmbed for maximum interoperability with Internet Explorer, - although embed tags will cause your website to stop validating. - <strong>Highly experimental.</strong> -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.Strict.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.Strict.txt deleted file mode 100644 index a8b1de56..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.Strict.txt +++ /dev/null @@ -1,9 +0,0 @@ -HTML.Strict -TYPE: bool -VERSION: 1.3.0 -DEFAULT: false -DEPRECATED-VERSION: 1.7.0 -DEPRECATED-USE: HTML.Doctype ---DESCRIPTION-- -Determines whether or not to use Transitional (loose) or Strict rulesets. ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.TidyAdd.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.TidyAdd.txt deleted file mode 100644 index b4c271b7..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.TidyAdd.txt +++ /dev/null @@ -1,8 +0,0 @@ -HTML.TidyAdd -TYPE: lookup -VERSION: 2.0.0 -DEFAULT: array() ---DESCRIPTION-- - -Fixes to add to the default set of Tidy fixes as per your level. ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.TidyLevel.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.TidyLevel.txt deleted file mode 100644 index 4186ccd0..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.TidyLevel.txt +++ /dev/null @@ -1,24 +0,0 @@ -HTML.TidyLevel -TYPE: string -VERSION: 2.0.0 -DEFAULT: 'medium' ---DESCRIPTION-- - -<p>General level of cleanliness the Tidy module should enforce. -There are four allowed values:</p> -<dl> - <dt>none</dt> - <dd>No extra tidying should be done</dd> - <dt>light</dt> - <dd>Only fix elements that would be discarded otherwise due to - lack of support in doctype</dd> - <dt>medium</dt> - <dd>Enforce best practices</dd> - <dt>heavy</dt> - <dd>Transform all deprecated elements and attributes to standards - compliant equivalents</dd> -</dl> - ---ALLOWED-- -'none', 'light', 'medium', 'heavy' ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.TidyRemove.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.TidyRemove.txt deleted file mode 100644 index 996762bd..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.TidyRemove.txt +++ /dev/null @@ -1,8 +0,0 @@ -HTML.TidyRemove -TYPE: lookup -VERSION: 2.0.0 -DEFAULT: array() ---DESCRIPTION-- - -Fixes to remove from the default set of Tidy fixes as per your level. ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.Trusted.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.Trusted.txt deleted file mode 100644 index 89133b1a..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.Trusted.txt +++ /dev/null @@ -1,8 +0,0 @@ -HTML.Trusted -TYPE: bool -VERSION: 2.0.0 -DEFAULT: false ---DESCRIPTION-- -Indicates whether or not the user input is trusted or not. If the input is -trusted, a more expansive set of allowed tags and attributes will be used. ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.XHTML.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.XHTML.txt deleted file mode 100644 index 2a47e384..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/HTML.XHTML.txt +++ /dev/null @@ -1,11 +0,0 @@ -HTML.XHTML -TYPE: bool -DEFAULT: true -VERSION: 1.1.0 -DEPRECATED-VERSION: 1.7.0 -DEPRECATED-USE: HTML.Doctype ---DESCRIPTION-- -Determines whether or not output is XHTML 1.0 or HTML 4.01 flavor. ---ALIASES-- -Core.XHTML ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Output.CommentScriptContents.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Output.CommentScriptContents.txt deleted file mode 100644 index 08921fde..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Output.CommentScriptContents.txt +++ /dev/null @@ -1,10 +0,0 @@ -Output.CommentScriptContents -TYPE: bool -VERSION: 2.0.0 -DEFAULT: true ---DESCRIPTION-- -Determines whether or not HTML Purifier should attempt to fix up the -contents of script tags for legacy browsers with comments. ---ALIASES-- -Core.CommentScriptContents ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Output.Newline.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Output.Newline.txt deleted file mode 100644 index 79f8ad82..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Output.Newline.txt +++ /dev/null @@ -1,13 +0,0 @@ -Output.Newline -TYPE: string/null -VERSION: 2.0.1 -DEFAULT: NULL ---DESCRIPTION-- - -<p> - Newline string to format final output with. If left null, HTML Purifier - will auto-detect the default newline type of the system and use that; - you can manually override it here. Remember, \r\n is Windows, \r - is Mac, and \n is Unix. -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Output.SortAttr.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Output.SortAttr.txt deleted file mode 100644 index 232b0236..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Output.SortAttr.txt +++ /dev/null @@ -1,14 +0,0 @@ -Output.SortAttr -TYPE: bool -VERSION: 3.2.0 -DEFAULT: false ---DESCRIPTION-- -<p> - If true, HTML Purifier will sort attributes by name before writing them back - to the document, converting a tag like: <code><el b="" a="" c="" /></code> - to <code><el a="" b="" c="" /></code>. This is a workaround for - a bug in FCKeditor which causes it to swap attributes order, adding noise - to text diffs. If you're not seeing this bug, chances are, you don't need - this directive. -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Output.TidyFormat.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Output.TidyFormat.txt deleted file mode 100644 index 06bab00a..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Output.TidyFormat.txt +++ /dev/null @@ -1,25 +0,0 @@ -Output.TidyFormat -TYPE: bool -VERSION: 1.1.1 -DEFAULT: false ---DESCRIPTION-- -<p> - Determines whether or not to run Tidy on the final output for pretty - formatting reasons, such as indentation and wrap. -</p> -<p> - This can greatly improve readability for editors who are hand-editing - the HTML, but is by no means necessary as HTML Purifier has already - fixed all major errors the HTML may have had. Tidy is a non-default - extension, and this directive will silently fail if Tidy is not - available. -</p> -<p> - If you are looking to make the overall look of your page's source - better, I recommend running Tidy on the entire page rather than just - user-content (after all, the indentation relative to the containing - blocks will be incorrect). -</p> ---ALIASES-- -Core.TidyFormat ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Test.ForceNoIconv.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Test.ForceNoIconv.txt deleted file mode 100644 index 071bc029..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/Test.ForceNoIconv.txt +++ /dev/null @@ -1,7 +0,0 @@ -Test.ForceNoIconv -TYPE: bool -DEFAULT: false ---DESCRIPTION-- -When set to true, HTMLPurifier_Encoder will act as if iconv does not exist -and use only pure PHP implementations. ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.AllowedSchemes.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.AllowedSchemes.txt deleted file mode 100644 index 98fdfe92..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.AllowedSchemes.txt +++ /dev/null @@ -1,15 +0,0 @@ -URI.AllowedSchemes -TYPE: lookup ---DEFAULT-- -array ( - 'http' => true, - 'https' => true, - 'mailto' => true, - 'ftp' => true, - 'nntp' => true, - 'news' => true, -) ---DESCRIPTION-- -Whitelist that defines the schemes that a URI is allowed to have. This -prevents XSS attacks from using pseudo-schemes like javascript or mocha. ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.Base.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.Base.txt deleted file mode 100644 index 876f0680..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.Base.txt +++ /dev/null @@ -1,17 +0,0 @@ -URI.Base -TYPE: string/null -VERSION: 2.1.0 -DEFAULT: NULL ---DESCRIPTION-- - -<p> - The base URI is the URI of the document this purified HTML will be - inserted into. This information is important if HTML Purifier needs - to calculate absolute URIs from relative URIs, such as when %URI.MakeAbsolute - is on. You may use a non-absolute URI for this value, but behavior - may vary (%URI.MakeAbsolute deals nicely with both absolute and - relative paths, but forwards-compatibility is not guaranteed). - <strong>Warning:</strong> If set, the scheme on this URI - overrides the one specified by %URI.DefaultScheme. -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.DefaultScheme.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.DefaultScheme.txt deleted file mode 100644 index 728e378c..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.DefaultScheme.txt +++ /dev/null @@ -1,10 +0,0 @@ -URI.DefaultScheme -TYPE: string -DEFAULT: 'http' ---DESCRIPTION-- - -<p> - Defines through what scheme the output will be served, in order to - select the proper object validator when no scheme information is present. -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.DefinitionID.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.DefinitionID.txt deleted file mode 100644 index f05312ba..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.DefinitionID.txt +++ /dev/null @@ -1,11 +0,0 @@ -URI.DefinitionID -TYPE: string/null -VERSION: 2.1.0 -DEFAULT: NULL ---DESCRIPTION-- - -<p> - Unique identifier for a custom-built URI definition. If you want - to add custom URIFilters, you must specify this value. -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.DefinitionRev.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.DefinitionRev.txt deleted file mode 100644 index 80cfea93..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.DefinitionRev.txt +++ /dev/null @@ -1,11 +0,0 @@ -URI.DefinitionRev -TYPE: int -VERSION: 2.1.0 -DEFAULT: 1 ---DESCRIPTION-- - -<p> - Revision identifier for your custom definition. See - %HTML.DefinitionRev for details. -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.Disable.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.Disable.txt deleted file mode 100644 index 71ce025a..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.Disable.txt +++ /dev/null @@ -1,14 +0,0 @@ -URI.Disable -TYPE: bool -VERSION: 1.3.0 -DEFAULT: false ---DESCRIPTION-- - -<p> - Disables all URIs in all forms. Not sure why you'd want to do that - (after all, the Internet's founded on the notion of a hyperlink). -</p> - ---ALIASES-- -Attr.DisableURI ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.DisableExternal.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.DisableExternal.txt deleted file mode 100644 index 13c122c8..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.DisableExternal.txt +++ /dev/null @@ -1,11 +0,0 @@ -URI.DisableExternal -TYPE: bool -VERSION: 1.2.0 -DEFAULT: false ---DESCRIPTION-- -Disables links to external websites. This is a highly effective anti-spam -and anti-pagerank-leech measure, but comes at a hefty price: nolinks or -images outside of your domain will be allowed. Non-linkified URIs will -still be preserved. If you want to be able to link to subdomains or use -absolute URIs, specify %URI.Host for your website. ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.DisableExternalResources.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.DisableExternalResources.txt deleted file mode 100644 index abcc1efd..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.DisableExternalResources.txt +++ /dev/null @@ -1,13 +0,0 @@ -URI.DisableExternalResources -TYPE: bool -VERSION: 1.3.0 -DEFAULT: false ---DESCRIPTION-- -Disables the embedding of external resources, preventing users from -embedding things like images from other hosts. This prevents access -tracking (good for email viewers), bandwidth leeching, cross-site request -forging, goatse.cx posting, and other nasties, but also results in a loss -of end-user functionality (they can't directly post a pic they posted from -Flickr anymore). Use it if you don't have a robust user-content moderation -team. ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.DisableResources.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.DisableResources.txt deleted file mode 100644 index 51e6ea91..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.DisableResources.txt +++ /dev/null @@ -1,12 +0,0 @@ -URI.DisableResources -TYPE: bool -VERSION: 1.3.0 -DEFAULT: false ---DESCRIPTION-- - -<p> - Disables embedding resources, essentially meaning no pictures. You can - still link to them though. See %URI.DisableExternalResources for why - this might be a good idea. -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.Host.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.Host.txt deleted file mode 100644 index ee83b121..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.Host.txt +++ /dev/null @@ -1,19 +0,0 @@ -URI.Host -TYPE: string/null -VERSION: 1.2.0 -DEFAULT: NULL ---DESCRIPTION-- - -<p> - Defines the domain name of the server, so we can determine whether or - an absolute URI is from your website or not. Not strictly necessary, - as users should be using relative URIs to reference resources on your - website. It will, however, let you use absolute URIs to link to - subdomains of the domain you post here: i.e. example.com will allow - sub.example.com. However, higher up domains will still be excluded: - if you set %URI.Host to sub.example.com, example.com will be blocked. - <strong>Note:</strong> This directive overrides %URI.Base because - a given page may be on a sub-domain, but you wish HTML Purifier to be - more relaxed and allow some of the parent domains too. -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.HostBlacklist.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.HostBlacklist.txt deleted file mode 100644 index 0b6df762..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.HostBlacklist.txt +++ /dev/null @@ -1,9 +0,0 @@ -URI.HostBlacklist -TYPE: list -VERSION: 1.3.0 -DEFAULT: array() ---DESCRIPTION-- -List of strings that are forbidden in the host of any URI. Use it to kill -domain names of spam, etc. Note that it will catch anything in the domain, -so <tt>moo.com</tt> will catch <tt>moo.com.example.com</tt>. ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.MakeAbsolute.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.MakeAbsolute.txt deleted file mode 100644 index 4214900a..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.MakeAbsolute.txt +++ /dev/null @@ -1,13 +0,0 @@ -URI.MakeAbsolute -TYPE: bool -VERSION: 2.1.0 -DEFAULT: false ---DESCRIPTION-- - -<p> - Converts all URIs into absolute forms. This is useful when the HTML - being filtered assumes a specific base path, but will actually be - viewed in a different context (and setting an alternate base URI is - not possible). %URI.Base must be set for this directive to work. -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.Munge.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.Munge.txt deleted file mode 100644 index 58c81dcc..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.Munge.txt +++ /dev/null @@ -1,83 +0,0 @@ -URI.Munge -TYPE: string/null -VERSION: 1.3.0 -DEFAULT: NULL ---DESCRIPTION-- - -<p> - Munges all browsable (usually http, https and ftp) - absolute URIs into another URI, usually a URI redirection service. - This directive accepts a URI, formatted with a <code>%s</code> where - the url-encoded original URI should be inserted (sample: - <code>http://www.google.com/url?q=%s</code>). -</p> -<p> - Uses for this directive: -</p> -<ul> - <li> - Prevent PageRank leaks, while being fairly transparent - to users (you may also want to add some client side JavaScript to - override the text in the statusbar). <strong>Notice</strong>: - Many security experts believe that this form of protection does not deter spam-bots. - </li> - <li> - Redirect users to a splash page telling them they are leaving your - website. While this is poor usability practice, it is often mandated - in corporate environments. - </li> -</ul> -<p> - Prior to HTML Purifier 3.1.1, this directive also enabled the munging - of browsable external resources, which could break things if your redirection - script was a splash page or used <code>meta</code> tags. To revert to - previous behavior, please use %URI.MungeResources. -</p> -<p> - You may want to also use %URI.MungeSecretKey along with this directive - in order to enforce what URIs your redirector script allows. Open - redirector scripts can be a security risk and negatively affect the - reputation of your domain name. -</p> -<p> - Starting with HTML Purifier 3.1.1, there is also these substitutions: -</p> -<table> - <thead> - <tr> - <th>Key</th> - <th>Description</th> - <th>Example <code><a href=""></code></th> - </tr> - </thead> - <tbody> - <tr> - <td>%r</td> - <td>1 - The URI embeds a resource<br />(blank) - The URI is merely a link</td> - <td></td> - </tr> - <tr> - <td>%n</td> - <td>The name of the tag this URI came from</td> - <td>a</td> - </tr> - <tr> - <td>%m</td> - <td>The name of the attribute this URI came from</td> - <td>href</td> - </tr> - <tr> - <td>%p</td> - <td>The name of the CSS property this URI came from, or blank if irrelevant</td> - <td></td> - </tr> - </tbody> -</table> -<p> - Admittedly, these letters are somewhat arbitrary; the only stipulation - was that they couldn't be a through f. r is for resource (I would have preferred - e, but you take what you can get), n is for name, m - was picked because it came after n (and I couldn't use a), p is for - property. -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.MungeResources.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.MungeResources.txt deleted file mode 100644 index 6fce0fdc..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.MungeResources.txt +++ /dev/null @@ -1,17 +0,0 @@ -URI.MungeResources -TYPE: bool -VERSION: 3.1.1 -DEFAULT: false ---DESCRIPTION-- -<p> - If true, any URI munging directives like %URI.Munge - will also apply to embedded resources, such as <code><img src=""></code>. - Be careful enabling this directive if you have a redirector script - that does not use the <code>Location</code> HTTP header; all of your images - and other embedded resources will break. -</p> -<p> - <strong>Warning:</strong> It is strongly advised you use this in conjunction - %URI.MungeSecretKey to mitigate the security risk of an open redirector. -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.MungeSecretKey.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.MungeSecretKey.txt deleted file mode 100644 index 0d00f62e..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.MungeSecretKey.txt +++ /dev/null @@ -1,30 +0,0 @@ -URI.MungeSecretKey -TYPE: string/null -VERSION: 3.1.1 -DEFAULT: NULL ---DESCRIPTION-- -<p> - This directive enables secure checksum generation along with %URI.Munge. - It should be set to a secure key that is not shared with anyone else. - The checksum can be placed in the URI using %t. Use of this checksum - affords an additional level of protection by allowing a redirector - to check if a URI has passed through HTML Purifier with this line: -</p> - -<pre>$checksum === sha1($secret_key . ':' . $url)</pre> - -<p> - If the output is TRUE, the redirector script should accept the URI. -</p> - -<p> - Please note that it would still be possible for an attacker to procure - secure hashes en-mass by abusing your website's Preview feature or the - like, but this service affords an additional level of protection - that should be combined with website blacklisting. -</p> - -<p> - Remember this has no effect if %URI.Munge is not on. -</p> ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.OverrideAllowedSchemes.txt b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.OverrideAllowedSchemes.txt deleted file mode 100644 index 23331a4e..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/URI.OverrideAllowedSchemes.txt +++ /dev/null @@ -1,9 +0,0 @@ -URI.OverrideAllowedSchemes -TYPE: bool -DEFAULT: true ---DESCRIPTION-- -If this is set to true (which it is by default), you can override -%URI.AllowedSchemes by simply registering a HTMLPurifier_URIScheme to the -registry. If false, you will also have to update that directive in order -to add more schemes. ---# vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/info.ini b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/info.ini deleted file mode 100644 index 5de4505e..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ConfigSchema/schema/info.ini +++ /dev/null @@ -1,3 +0,0 @@ -name = "HTML Purifier" - -; vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ContentSets.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ContentSets.php deleted file mode 100644 index dce28289..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ContentSets.php +++ /dev/null @@ -1,155 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * @todo Unit test - */ -class HTMLPurifier_ContentSets -{ - - /** - * List of content set strings (pipe seperators) indexed by name. - */ - public $info = array(); - - /** - * List of content set lookups (element => true) indexed by name. - * @note This is in HTMLPurifier_HTMLDefinition->info_content_sets - */ - public $lookup = array(); - - /** - * Synchronized list of defined content sets (keys of info) - */ - protected $keys = array(); - /** - * Synchronized list of defined content values (values of info) - */ - protected $values = array(); - - /** - * Merges in module's content sets, expands identifiers in the content - * sets and populates the keys, values and lookup member variables. - * @param $modules List of HTMLPurifier_HTMLModule - */ - public function __construct($modules) { - if (!is_array($modules)) $modules = array($modules); - // populate content_sets based on module hints - // sorry, no way of overloading - foreach ($modules as $module_i => $module) { - foreach ($module->content_sets as $key => $value) { - $temp = $this->convertToLookup($value); - if (isset($this->lookup[$key])) { - // add it into the existing content set - $this->lookup[$key] = array_merge($this->lookup[$key], $temp); - } else { - $this->lookup[$key] = $temp; - } - } - } - $old_lookup = false; - while ($old_lookup !== $this->lookup) { - $old_lookup = $this->lookup; - foreach ($this->lookup as $i => $set) { - $add = array(); - foreach ($set as $element => $x) { - if (isset($this->lookup[$element])) { - $add += $this->lookup[$element]; - unset($this->lookup[$i][$element]); - } - } - $this->lookup[$i] += $add; - } - } - - foreach ($this->lookup as $key => $lookup) { - $this->info[$key] = implode(' | ', array_keys($lookup)); - } - $this->keys = array_keys($this->info); - $this->values = array_values($this->info); - } - - /** - * Accepts a definition; generates and assigns a ChildDef for it - * @param $def HTMLPurifier_ElementDef reference - * @param $module Module that defined the ElementDef - */ - public function generateChildDef(&$def, $module) { - if (!empty($def->child)) return; // already done! - $content_model = $def->content_model; - if (is_string($content_model)) { - // Assume that $this->keys is alphanumeric - $def->content_model = preg_replace_callback( - '/\b(' . implode('|', $this->keys) . ')\b/', - array($this, 'generateChildDefCallback'), - $content_model - ); - //$def->content_model = str_replace( - // $this->keys, $this->values, $content_model); - } - $def->child = $this->getChildDef($def, $module); - } - - public function generateChildDefCallback($matches) { - return $this->info[$matches[0]]; - } - - /** - * Instantiates a ChildDef based on content_model and content_model_type - * member variables in HTMLPurifier_ElementDef - * @note This will also defer to modules for custom HTMLPurifier_ChildDef - * subclasses that need content set expansion - * @param $def HTMLPurifier_ElementDef to have ChildDef extracted - * @return HTMLPurifier_ChildDef corresponding to ElementDef - */ - public function getChildDef($def, $module) { - $value = $def->content_model; - if (is_object($value)) { - trigger_error( - 'Literal object child definitions should be stored in '. - 'ElementDef->child not ElementDef->content_model', - E_USER_NOTICE - ); - return $value; - } - switch ($def->content_model_type) { - case 'required': - return new HTMLPurifier_ChildDef_Required($value); - case 'optional': - return new HTMLPurifier_ChildDef_Optional($value); - case 'empty': - return new HTMLPurifier_ChildDef_Empty(); - case 'custom': - return new HTMLPurifier_ChildDef_Custom($value); - } - // defer to its module - $return = false; - if ($module->defines_child_def) { // save a func call - $return = $module->getChildDef($def); - } - if ($return !== false) return $return; - // error-out - trigger_error( - 'Could not determine which ChildDef class to instantiate', - E_USER_ERROR - ); - return false; - } - - /** - * Converts a string list of elements separated by pipes into - * a lookup array. - * @param $string List of elements - * @return Lookup array of elements - */ - protected function convertToLookup($string) { - $array = explode('|', str_replace(' ', '', $string)); - $ret = array(); - foreach ($array as $i => $k) { - $ret[$k] = true; - } - return $ret; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Context.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Context.php deleted file mode 100644 index 92d31582..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Context.php +++ /dev/null @@ -1,82 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Registry object that contains information about the current context. - * @warning Is a bit buggy when variables are set to null: it thinks - * they don't exist! So use false instead, please. - * @note Since the variables Context deals with may not be objects, - * references are very important here! Do not remove! - */ -class HTMLPurifier_Context -{ - - /** - * Private array that stores the references. - */ - private $_storage = array(); - - /** - * Registers a variable into the context. - * @param $name String name - * @param $ref Reference to variable to be registered - */ - public function register($name, &$ref) { - if (isset($this->_storage[$name])) { - trigger_error("Name $name produces collision, cannot re-register", - E_USER_ERROR); - return; - } - $this->_storage[$name] =& $ref; - } - - /** - * Retrieves a variable reference from the context. - * @param $name String name - * @param $ignore_error Boolean whether or not to ignore error - */ - public function &get($name, $ignore_error = false) { - if (!isset($this->_storage[$name])) { - if (!$ignore_error) { - trigger_error("Attempted to retrieve non-existent variable $name", - E_USER_ERROR); - } - $var = null; // so we can return by reference - return $var; - } - return $this->_storage[$name]; - } - - /** - * Destorys a variable in the context. - * @param $name String name - */ - public function destroy($name) { - if (!isset($this->_storage[$name])) { - trigger_error("Attempted to destroy non-existent variable $name", - E_USER_ERROR); - return; - } - unset($this->_storage[$name]); - } - - /** - * Checks whether or not the variable exists. - * @param $name String name - */ - public function exists($name) { - return isset($this->_storage[$name]); - } - - /** - * Loads a series of variables from an associative array - * @param $context_array Assoc array of variables to load - */ - public function loadArray($context_array) { - foreach ($context_array as $key => $discard) { - $this->register($key, $context_array[$key]); - } - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Definition.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Definition.php deleted file mode 100644 index fa758a19..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Definition.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Super-class for definition datatype objects, implements serialization - * functions for the class. - */ -abstract class HTMLPurifier_Definition -{ - - /** - * Has setup() been called yet? - */ - public $setup = false; - - /** - * What type of definition is it? - */ - public $type; - - /** - * Sets up the definition object into the final form, something - * not done by the constructor - * @param $config HTMLPurifier_Config instance - */ - abstract protected function doSetup($config); - - /** - * Setup function that aborts if already setup - * @param $config HTMLPurifier_Config instance - */ - public function setup($config) { - if ($this->setup) return; - $this->setup = true; - $this->doSetup($config); - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/DefinitionCache.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/DefinitionCache.php deleted file mode 100644 index bb03e72d..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/DefinitionCache.php +++ /dev/null @@ -1,108 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Abstract class representing Definition cache managers that implements - * useful common methods and is a factory. - * @todo Create a separate maintenance file advanced users can use to - * cache their custom HTMLDefinition, which can be loaded - * via a configuration directive - * @todo Implement memcached - */ -abstract class HTMLPurifier_DefinitionCache -{ - - public $type; - - /** - * @param $name Type of definition objects this instance of the - * cache will handle. - */ - public function __construct($type) { - $this->type = $type; - } - - /** - * Generates a unique identifier for a particular configuration - * @param Instance of HTMLPurifier_Config - */ - public function generateKey($config) { - return $config->version . ',' . // possibly replace with function calls - $config->getBatchSerial($this->type) . ',' . - $config->get($this->type . '.DefinitionRev'); - } - - /** - * Tests whether or not a key is old with respect to the configuration's - * version and revision number. - * @param $key Key to test - * @param $config Instance of HTMLPurifier_Config to test against - */ - public function isOld($key, $config) { - if (substr_count($key, ',') < 2) return true; - list($version, $hash, $revision) = explode(',', $key, 3); - $compare = version_compare($version, $config->version); - // version mismatch, is always old - if ($compare != 0) return true; - // versions match, ids match, check revision number - if ( - $hash == $config->getBatchSerial($this->type) && - $revision < $config->get($this->type . '.DefinitionRev') - ) return true; - return false; - } - - /** - * Checks if a definition's type jives with the cache's type - * @note Throws an error on failure - * @param $def Definition object to check - * @return Boolean true if good, false if not - */ - public function checkDefType($def) { - if ($def->type !== $this->type) { - trigger_error("Cannot use definition of type {$def->type} in cache for {$this->type}"); - return false; - } - return true; - } - - /** - * Adds a definition object to the cache - */ - abstract public function add($def, $config); - - /** - * Unconditionally saves a definition object to the cache - */ - abstract public function set($def, $config); - - /** - * Replace an object in the cache - */ - abstract public function replace($def, $config); - - /** - * Retrieves a definition object from the cache - */ - abstract public function get($config); - - /** - * Removes a definition object to the cache - */ - abstract public function remove($config); - - /** - * Clears all objects from cache - */ - abstract public function flush($config); - - /** - * Clears all expired (older version or revision) objects from cache - * @note Be carefuly implementing this method as flush. Flush must - * not interfere with other Definition types, and cleanup() - * should not be repeatedly called by userland code. - */ - abstract public function cleanup($config); - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/DefinitionCache/Decorator.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/DefinitionCache/Decorator.php deleted file mode 100644 index 2b2dffb3..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/DefinitionCache/Decorator.php +++ /dev/null @@ -1,62 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -class HTMLPurifier_DefinitionCache_Decorator extends HTMLPurifier_DefinitionCache -{ - - /** - * Cache object we are decorating - */ - public $cache; - - public function __construct() {} - - /** - * Lazy decorator function - * @param $cache Reference to cache object to decorate - */ - public function decorate(&$cache) { - $decorator = $this->copy(); - // reference is necessary for mocks in PHP 4 - $decorator->cache =& $cache; - $decorator->type = $cache->type; - return $decorator; - } - - /** - * Cross-compatible clone substitute - */ - public function copy() { - return new HTMLPurifier_DefinitionCache_Decorator(); - } - - public function add($def, $config) { - return $this->cache->add($def, $config); - } - - public function set($def, $config) { - return $this->cache->set($def, $config); - } - - public function replace($def, $config) { - return $this->cache->replace($def, $config); - } - - public function get($config) { - return $this->cache->get($config); - } - - public function remove($config) { - return $this->cache->remove($config); - } - - public function flush($config) { - return $this->cache->flush($config); - } - - public function cleanup($config) { - return $this->cache->cleanup($config); - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/DefinitionCache/Decorator/Cleanup.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/DefinitionCache/Decorator/Cleanup.php deleted file mode 100644 index 5ff42414..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/DefinitionCache/Decorator/Cleanup.php +++ /dev/null @@ -1,43 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Definition cache decorator class that cleans up the cache - * whenever there is a cache miss. - */ -class HTMLPurifier_DefinitionCache_Decorator_Cleanup extends - HTMLPurifier_DefinitionCache_Decorator -{ - - public $name = 'Cleanup'; - - public function copy() { - return new HTMLPurifier_DefinitionCache_Decorator_Cleanup(); - } - - public function add($def, $config) { - $status = parent::add($def, $config); - if (!$status) parent::cleanup($config); - return $status; - } - - public function set($def, $config) { - $status = parent::set($def, $config); - if (!$status) parent::cleanup($config); - return $status; - } - - public function replace($def, $config) { - $status = parent::replace($def, $config); - if (!$status) parent::cleanup($config); - return $status; - } - - public function get($config) { - $ret = parent::get($config); - if (!$ret) parent::cleanup($config); - return $ret; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/DefinitionCache/Decorator/Memory.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/DefinitionCache/Decorator/Memory.php deleted file mode 100644 index 8b25085b..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/DefinitionCache/Decorator/Memory.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Definition cache decorator class that saves all cache retrievals - * to PHP's memory; good for unit tests or circumstances where - * there are lots of configuration objects floating around. - */ -class HTMLPurifier_DefinitionCache_Decorator_Memory extends - HTMLPurifier_DefinitionCache_Decorator -{ - - protected $definitions; - public $name = 'Memory'; - - public function copy() { - return new HTMLPurifier_DefinitionCache_Decorator_Memory(); - } - - public function add($def, $config) { - $status = parent::add($def, $config); - if ($status) $this->definitions[$this->generateKey($config)] = $def; - return $status; - } - - public function set($def, $config) { - $status = parent::set($def, $config); - if ($status) $this->definitions[$this->generateKey($config)] = $def; - return $status; - } - - public function replace($def, $config) { - $status = parent::replace($def, $config); - if ($status) $this->definitions[$this->generateKey($config)] = $def; - return $status; - } - - public function get($config) { - $key = $this->generateKey($config); - if (isset($this->definitions[$key])) return $this->definitions[$key]; - $this->definitions[$key] = parent::get($config); - return $this->definitions[$key]; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/DefinitionCache/Decorator/Template.php.in b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/DefinitionCache/Decorator/Template.php.in deleted file mode 100644 index 21a8fcfd..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/DefinitionCache/Decorator/Template.php.in +++ /dev/null @@ -1,47 +0,0 @@ -<?php - -require_once 'HTMLPurifier/DefinitionCache/Decorator.php'; - -/** - * Definition cache decorator template. - */ -class HTMLPurifier_DefinitionCache_Decorator_Template extends - HTMLPurifier_DefinitionCache_Decorator -{ - - var $name = 'Template'; // replace this - - function copy() { - // replace class name with yours - return new HTMLPurifier_DefinitionCache_Decorator_Template(); - } - - // remove methods you don't need - - function add($def, $config) { - return parent::add($def, $config); - } - - function set($def, $config) { - return parent::set($def, $config); - } - - function replace($def, $config) { - return parent::replace($def, $config); - } - - function get($config) { - return parent::get($config); - } - - function flush() { - return parent::flush(); - } - - function cleanup($config) { - return parent::cleanup($config); - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/DefinitionCache/Null.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/DefinitionCache/Null.php deleted file mode 100644 index 404c28f1..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/DefinitionCache/Null.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Null cache object to use when no caching is on. - */ -class HTMLPurifier_DefinitionCache_Null extends HTMLPurifier_DefinitionCache -{ - - public function add($def, $config) { - return false; - } - - public function set($def, $config) { - return false; - } - - public function replace($def, $config) { - return false; - } - - public function remove($config) { - return false; - } - - public function get($config) { - return false; - } - - public function flush($config) { - return false; - } - - public function cleanup($config) { - return false; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/DefinitionCache/Serializer.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/DefinitionCache/Serializer.php deleted file mode 100644 index 414a7d4b..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/DefinitionCache/Serializer.php +++ /dev/null @@ -1,172 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -class HTMLPurifier_DefinitionCache_Serializer extends - HTMLPurifier_DefinitionCache -{ - - public function add($def, $config) { - if (!$this->checkDefType($def)) return; - $file = $this->generateFilePath($config); - if (file_exists($file)) return false; - if (!$this->_prepareDir($config)) return false; - return $this->_write($file, serialize($def)); - } - - public function set($def, $config) { - if (!$this->checkDefType($def)) return; - $file = $this->generateFilePath($config); - if (!$this->_prepareDir($config)) return false; - return $this->_write($file, serialize($def)); - } - - public function replace($def, $config) { - if (!$this->checkDefType($def)) return; - $file = $this->generateFilePath($config); - if (!file_exists($file)) return false; - if (!$this->_prepareDir($config)) return false; - return $this->_write($file, serialize($def)); - } - - public function get($config) { - $file = $this->generateFilePath($config); - if (!file_exists($file)) return false; - return unserialize(file_get_contents($file)); - } - - public function remove($config) { - $file = $this->generateFilePath($config); - if (!file_exists($file)) return false; - return unlink($file); - } - - public function flush($config) { - if (!$this->_prepareDir($config)) return false; - $dir = $this->generateDirectoryPath($config); - $dh = opendir($dir); - while (false !== ($filename = readdir($dh))) { - if (empty($filename)) continue; - if ($filename[0] === '.') continue; - unlink($dir . '/' . $filename); - } - } - - public function cleanup($config) { - if (!$this->_prepareDir($config)) return false; - $dir = $this->generateDirectoryPath($config); - $dh = opendir($dir); - while (false !== ($filename = readdir($dh))) { - if (empty($filename)) continue; - if ($filename[0] === '.') continue; - $key = substr($filename, 0, strlen($filename) - 4); - if ($this->isOld($key, $config)) unlink($dir . '/' . $filename); - } - } - - /** - * Generates the file path to the serial file corresponding to - * the configuration and definition name - * @todo Make protected - */ - public function generateFilePath($config) { - $key = $this->generateKey($config); - return $this->generateDirectoryPath($config) . '/' . $key . '.ser'; - } - - /** - * Generates the path to the directory contain this cache's serial files - * @note No trailing slash - * @todo Make protected - */ - public function generateDirectoryPath($config) { - $base = $this->generateBaseDirectoryPath($config); - return $base . '/' . $this->type; - } - - /** - * Generates path to base directory that contains all definition type - * serials - * @todo Make protected - */ - public function generateBaseDirectoryPath($config) { - $base = $config->get('Cache.SerializerPath'); - $base = is_null($base) ? HTMLPURIFIER_PREFIX . '/HTMLPurifier/DefinitionCache/Serializer' : $base; - return $base; - } - - /** - * Convenience wrapper function for file_put_contents - * @param $file File name to write to - * @param $data Data to write into file - * @return Number of bytes written if success, or false if failure. - */ - private function _write($file, $data) { - return file_put_contents($file, $data); - } - - /** - * Prepares the directory that this type stores the serials in - * @return True if successful - */ - private function _prepareDir($config) { - $directory = $this->generateDirectoryPath($config); - if (!is_dir($directory)) { - $base = $this->generateBaseDirectoryPath($config); - if (!is_dir($base)) { - trigger_error('Base directory '.$base.' does not exist, - please create or change using %Cache.SerializerPath', - E_USER_WARNING); - return false; - } elseif (!$this->_testPermissions($base)) { - return false; - } - $old = umask(0022); // disable group and world writes - mkdir($directory); - umask($old); - } elseif (!$this->_testPermissions($directory)) { - return false; - } - return true; - } - - /** - * Tests permissions on a directory and throws out friendly - * error messages and attempts to chmod it itself if possible - */ - private function _testPermissions($dir) { - // early abort, if it is writable, everything is hunky-dory - if (is_writable($dir)) return true; - if (!is_dir($dir)) { - // generally, you'll want to handle this beforehand - // so a more specific error message can be given - trigger_error('Directory '.$dir.' does not exist', - E_USER_WARNING); - return false; - } - if (function_exists('posix_getuid')) { - // POSIX system, we can give more specific advice - if (fileowner($dir) === posix_getuid()) { - // we can chmod it ourselves - chmod($dir, 0755); - return true; - } elseif (filegroup($dir) === posix_getgid()) { - $chmod = '775'; - } else { - // PHP's probably running as nobody, so we'll - // need to give global permissions - $chmod = '777'; - } - trigger_error('Directory '.$dir.' not writable, '. - 'please chmod to ' . $chmod, - E_USER_WARNING); - } else { - // generic error message - trigger_error('Directory '.$dir.' not writable, '. - 'please alter file permissions', - E_USER_WARNING); - } - return false; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/DefinitionCache/Serializer/README b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/DefinitionCache/Serializer/README deleted file mode 100755 index 2e35c1c3..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/DefinitionCache/Serializer/README +++ /dev/null @@ -1,3 +0,0 @@ -This is a dummy file to prevent Git from ignoring this empty directory. - - vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/DefinitionCacheFactory.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/DefinitionCacheFactory.php deleted file mode 100644 index 24814cda..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/DefinitionCacheFactory.php +++ /dev/null @@ -1,91 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Responsible for creating definition caches. - */ -class HTMLPurifier_DefinitionCacheFactory -{ - - protected $caches = array('Serializer' => array()); - protected $implementations = array(); - protected $decorators = array(); - - /** - * Initialize default decorators - */ - public function setup() { - $this->addDecorator('Cleanup'); - } - - /** - * Retrieves an instance of global definition cache factory. - */ - public static function instance($prototype = null) { - static $instance; - if ($prototype !== null) { - $instance = $prototype; - } elseif ($instance === null || $prototype === true) { - $instance = new HTMLPurifier_DefinitionCacheFactory(); - $instance->setup(); - } - return $instance; - } - - /** - * Registers a new definition cache object - * @param $short Short name of cache object, for reference - * @param $long Full class name of cache object, for construction - */ - public function register($short, $long) { - $this->implementations[$short] = $long; - } - - /** - * Factory method that creates a cache object based on configuration - * @param $name Name of definitions handled by cache - * @param $config Instance of HTMLPurifier_Config - */ - public function create($type, $config) { - $method = $config->get('Cache.DefinitionImpl'); - if ($method === null) { - return new HTMLPurifier_DefinitionCache_Null($type); - } - if (!empty($this->caches[$method][$type])) { - return $this->caches[$method][$type]; - } - if ( - isset($this->implementations[$method]) && - class_exists($class = $this->implementations[$method], false) - ) { - $cache = new $class($type); - } else { - if ($method != 'Serializer') { - trigger_error("Unrecognized DefinitionCache $method, using Serializer instead", E_USER_WARNING); - } - $cache = new HTMLPurifier_DefinitionCache_Serializer($type); - } - foreach ($this->decorators as $decorator) { - $new_cache = $decorator->decorate($cache); - // prevent infinite recursion in PHP 4 - unset($cache); - $cache = $new_cache; - } - $this->caches[$method][$type] = $cache; - return $this->caches[$method][$type]; - } - - /** - * Registers a decorator to add to all new cache objects - * @param - */ - public function addDecorator($decorator) { - if (is_string($decorator)) { - $class = "HTMLPurifier_DefinitionCache_Decorator_$decorator"; - $decorator = new $class; - } - $this->decorators[$decorator->name] = $decorator; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Doctype.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Doctype.php deleted file mode 100644 index ab417793..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Doctype.php +++ /dev/null @@ -1,60 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Represents a document type, contains information on which modules - * need to be loaded. - * @note This class is inspected by Printer_HTMLDefinition->renderDoctype. - * If structure changes, please update that function. - */ -class HTMLPurifier_Doctype -{ - /** - * Full name of doctype - */ - public $name; - - /** - * List of standard modules (string identifiers or literal objects) - * that this doctype uses - */ - public $modules = array(); - - /** - * List of modules to use for tidying up code - */ - public $tidyModules = array(); - - /** - * Is the language derived from XML (i.e. XHTML)? - */ - public $xml = true; - - /** - * List of aliases for this doctype - */ - public $aliases = array(); - - /** - * Public DTD identifier - */ - public $dtdPublic; - - /** - * System DTD identifier - */ - public $dtdSystem; - - public function __construct($name = null, $xml = true, $modules = array(), - $tidyModules = array(), $aliases = array(), $dtd_public = null, $dtd_system = null - ) { - $this->name = $name; - $this->xml = $xml; - $this->modules = $modules; - $this->tidyModules = $tidyModules; - $this->aliases = $aliases; - $this->dtdPublic = $dtd_public; - $this->dtdSystem = $dtd_system; - } -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/DoctypeRegistry.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/DoctypeRegistry.php deleted file mode 100644 index bb685761..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/DoctypeRegistry.php +++ /dev/null @@ -1,103 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -class HTMLPurifier_DoctypeRegistry -{ - - /** - * Hash of doctype names to doctype objects - */ - protected $doctypes; - - /** - * Lookup table of aliases to real doctype names - */ - protected $aliases; - - /** - * Registers a doctype to the registry - * @note Accepts a fully-formed doctype object, or the - * parameters for constructing a doctype object - * @param $doctype Name of doctype or literal doctype object - * @param $modules Modules doctype will load - * @param $modules_for_modes Modules doctype will load for certain modes - * @param $aliases Alias names for doctype - * @return Editable registered doctype - */ - public function register($doctype, $xml = true, $modules = array(), - $tidy_modules = array(), $aliases = array(), $dtd_public = null, $dtd_system = null - ) { - if (!is_array($modules)) $modules = array($modules); - if (!is_array($tidy_modules)) $tidy_modules = array($tidy_modules); - if (!is_array($aliases)) $aliases = array($aliases); - if (!is_object($doctype)) { - $doctype = new HTMLPurifier_Doctype( - $doctype, $xml, $modules, $tidy_modules, $aliases, $dtd_public, $dtd_system - ); - } - $this->doctypes[$doctype->name] = $doctype; - $name = $doctype->name; - // hookup aliases - foreach ($doctype->aliases as $alias) { - if (isset($this->doctypes[$alias])) continue; - $this->aliases[$alias] = $name; - } - // remove old aliases - if (isset($this->aliases[$name])) unset($this->aliases[$name]); - return $doctype; - } - - /** - * Retrieves reference to a doctype of a certain name - * @note This function resolves aliases - * @note When possible, use the more fully-featured make() - * @param $doctype Name of doctype - * @return Editable doctype object - */ - public function get($doctype) { - if (isset($this->aliases[$doctype])) $doctype = $this->aliases[$doctype]; - if (!isset($this->doctypes[$doctype])) { - trigger_error('Doctype ' . htmlspecialchars($doctype) . ' does not exist', E_USER_ERROR); - $anon = new HTMLPurifier_Doctype($doctype); - return $anon; - } - return $this->doctypes[$doctype]; - } - - /** - * Creates a doctype based on a configuration object, - * will perform initialization on the doctype - * @note Use this function to get a copy of doctype that config - * can hold on to (this is necessary in order to tell - * Generator whether or not the current document is XML - * based or not). - */ - public function make($config) { - return clone $this->get($this->getDoctypeFromConfig($config)); - } - - /** - * Retrieves the doctype from the configuration object - */ - public function getDoctypeFromConfig($config) { - // recommended test - $doctype = $config->get('HTML.Doctype'); - if (!empty($doctype)) return $doctype; - $doctype = $config->get('HTML.CustomDoctype'); - if (!empty($doctype)) return $doctype; - // backwards-compatibility - if ($config->get('HTML.XHTML')) { - $doctype = 'XHTML 1.0'; - } else { - $doctype = 'HTML 4.01'; - } - if ($config->get('HTML.Strict')) { - $doctype .= ' Strict'; - } else { - $doctype .= ' Transitional'; - } - return $doctype; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ElementDef.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ElementDef.php deleted file mode 100644 index c4f5df97..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ElementDef.php +++ /dev/null @@ -1,176 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Structure that stores an HTML element definition. Used by - * HTMLPurifier_HTMLDefinition and HTMLPurifier_HTMLModule. - * @note This class is inspected by HTMLPurifier_Printer_HTMLDefinition. - * Please update that class too. - * @warning If you add new properties to this class, you MUST update - * the mergeIn() method. - */ -class HTMLPurifier_ElementDef -{ - - /** - * Does the definition work by itself, or is it created solely - * for the purpose of merging into another definition? - */ - public $standalone = true; - - /** - * Associative array of attribute name to HTMLPurifier_AttrDef - * @note Before being processed by HTMLPurifier_AttrCollections - * when modules are finalized during - * HTMLPurifier_HTMLDefinition->setup(), this array may also - * contain an array at index 0 that indicates which attribute - * collections to load into the full array. It may also - * contain string indentifiers in lieu of HTMLPurifier_AttrDef, - * see HTMLPurifier_AttrTypes on how they are expanded during - * HTMLPurifier_HTMLDefinition->setup() processing. - */ - public $attr = array(); - - /** - * Indexed list of tag's HTMLPurifier_AttrTransform to be done before validation - */ - public $attr_transform_pre = array(); - - /** - * Indexed list of tag's HTMLPurifier_AttrTransform to be done after validation - */ - public $attr_transform_post = array(); - - /** - * HTMLPurifier_ChildDef of this tag. - */ - public $child; - - /** - * Abstract string representation of internal ChildDef rules. See - * HTMLPurifier_ContentSets for how this is parsed and then transformed - * into an HTMLPurifier_ChildDef. - * @warning This is a temporary variable that is not available after - * being processed by HTMLDefinition - */ - public $content_model; - - /** - * Value of $child->type, used to determine which ChildDef to use, - * used in combination with $content_model. - * @warning This must be lowercase - * @warning This is a temporary variable that is not available after - * being processed by HTMLDefinition - */ - public $content_model_type; - - - - /** - * Does the element have a content model (#PCDATA | Inline)*? This - * is important for chameleon ins and del processing in - * HTMLPurifier_ChildDef_Chameleon. Dynamically set: modules don't - * have to worry about this one. - */ - public $descendants_are_inline = false; - - /** - * List of the names of required attributes this element has. Dynamically - * populated by HTMLPurifier_HTMLDefinition::getElement - */ - public $required_attr = array(); - - /** - * Lookup table of tags excluded from all descendants of this tag. - * @note SGML permits exclusions for all descendants, but this is - * not possible with DTDs or XML Schemas. W3C has elected to - * use complicated compositions of content_models to simulate - * exclusion for children, but we go the simpler, SGML-style - * route of flat-out exclusions, which correctly apply to - * all descendants and not just children. Note that the XHTML - * Modularization Abstract Modules are blithely unaware of such - * distinctions. - */ - public $excludes = array(); - - /** - * This tag is explicitly auto-closed by the following tags. - */ - public $autoclose = array(); - - /** - * Whether or not this is a formatting element affected by the - * "Active Formatting Elements" algorithm. - */ - public $formatting; - - /** - * Low-level factory constructor for creating new standalone element defs - */ - public static function create($content_model, $content_model_type, $attr) { - $def = new HTMLPurifier_ElementDef(); - $def->content_model = $content_model; - $def->content_model_type = $content_model_type; - $def->attr = $attr; - return $def; - } - - /** - * Merges the values of another element definition into this one. - * Values from the new element def take precedence if a value is - * not mergeable. - */ - public function mergeIn($def) { - - // later keys takes precedence - foreach($def->attr as $k => $v) { - if ($k === 0) { - // merge in the includes - // sorry, no way to override an include - foreach ($v as $v2) { - $this->attr[0][] = $v2; - } - continue; - } - if ($v === false) { - if (isset($this->attr[$k])) unset($this->attr[$k]); - continue; - } - $this->attr[$k] = $v; - } - $this->_mergeAssocArray($this->attr_transform_pre, $def->attr_transform_pre); - $this->_mergeAssocArray($this->attr_transform_post, $def->attr_transform_post); - $this->_mergeAssocArray($this->excludes, $def->excludes); - - if(!empty($def->content_model)) { - $this->content_model = - str_replace("#SUPER", $this->content_model, $def->content_model); - $this->child = false; - } - if(!empty($def->content_model_type)) { - $this->content_model_type = $def->content_model_type; - $this->child = false; - } - if(!is_null($def->child)) $this->child = $def->child; - if(!is_null($def->formatting)) $this->formatting = $def->formatting; - if($def->descendants_are_inline) $this->descendants_are_inline = $def->descendants_are_inline; - - } - - /** - * Merges one array into another, removes values which equal false - * @param $a1 Array by reference that is merged into - * @param $a2 Array that merges into $a1 - */ - private function _mergeAssocArray(&$a1, $a2) { - foreach ($a2 as $k => $v) { - if ($v === false) { - if (isset($a1[$k])) unset($a1[$k]); - continue; - } - $a1[$k] = $v; - } - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Encoder.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Encoder.php deleted file mode 100644 index fd09eaa1..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Encoder.php +++ /dev/null @@ -1,426 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * A UTF-8 specific character encoder that handles cleaning and transforming. - * @note All functions in this class should be static. - */ -class HTMLPurifier_Encoder -{ - - /** - * Constructor throws fatal error if you attempt to instantiate class - */ - private function __construct() { - trigger_error('Cannot instantiate encoder, call methods statically', E_USER_ERROR); - } - - /** - * Error-handler that mutes errors, alternative to shut-up operator. - */ - public static function muteErrorHandler() {} - - /** - * Cleans a UTF-8 string for well-formedness and SGML validity - * - * It will parse according to UTF-8 and return a valid UTF8 string, with - * non-SGML codepoints excluded. - * - * @note Just for reference, the non-SGML code points are 0 to 31 and - * 127 to 159, inclusive. However, we allow code points 9, 10 - * and 13, which are the tab, line feed and carriage return - * respectively. 128 and above the code points map to multibyte - * UTF-8 representations. - * - * @note Fallback code adapted from utf8ToUnicode by Henri Sivonen and - * hsivonen@iki.fi at <http://iki.fi/hsivonen/php-utf8/> under the - * LGPL license. Notes on what changed are inside, but in general, - * the original code transformed UTF-8 text into an array of integer - * Unicode codepoints. Understandably, transforming that back to - * a string would be somewhat expensive, so the function was modded to - * directly operate on the string. However, this discourages code - * reuse, and the logic enumerated here would be useful for any - * function that needs to be able to understand UTF-8 characters. - * As of right now, only smart lossless character encoding converters - * would need that, and I'm probably not going to implement them. - * Once again, PHP 6 should solve all our problems. - */ - public static function cleanUTF8($str, $force_php = false) { - - // UTF-8 validity is checked since PHP 4.3.5 - // This is an optimization: if the string is already valid UTF-8, no - // need to do PHP stuff. 99% of the time, this will be the case. - // The regexp matches the XML char production, as well as well as excluding - // non-SGML codepoints U+007F to U+009F - if (preg_match('/^[\x{9}\x{A}\x{D}\x{20}-\x{7E}\x{A0}-\x{D7FF}\x{E000}-\x{FFFD}\x{10000}-\x{10FFFF}]*$/Du', $str)) { - return $str; - } - - $mState = 0; // cached expected number of octets after the current octet - // until the beginning of the next UTF8 character sequence - $mUcs4 = 0; // cached Unicode character - $mBytes = 1; // cached expected number of octets in the current sequence - - // original code involved an $out that was an array of Unicode - // codepoints. Instead of having to convert back into UTF-8, we've - // decided to directly append valid UTF-8 characters onto a string - // $out once they're done. $char accumulates raw bytes, while $mUcs4 - // turns into the Unicode code point, so there's some redundancy. - - $out = ''; - $char = ''; - - $len = strlen($str); - for($i = 0; $i < $len; $i++) { - $in = ord($str{$i}); - $char .= $str[$i]; // append byte to char - if (0 == $mState) { - // When mState is zero we expect either a US-ASCII character - // or a multi-octet sequence. - if (0 == (0x80 & ($in))) { - // US-ASCII, pass straight through. - if (($in <= 31 || $in == 127) && - !($in == 9 || $in == 13 || $in == 10) // save \r\t\n - ) { - // control characters, remove - } else { - $out .= $char; - } - // reset - $char = ''; - $mBytes = 1; - } elseif (0xC0 == (0xE0 & ($in))) { - // First octet of 2 octet sequence - $mUcs4 = ($in); - $mUcs4 = ($mUcs4 & 0x1F) << 6; - $mState = 1; - $mBytes = 2; - } elseif (0xE0 == (0xF0 & ($in))) { - // First octet of 3 octet sequence - $mUcs4 = ($in); - $mUcs4 = ($mUcs4 & 0x0F) << 12; - $mState = 2; - $mBytes = 3; - } elseif (0xF0 == (0xF8 & ($in))) { - // First octet of 4 octet sequence - $mUcs4 = ($in); - $mUcs4 = ($mUcs4 & 0x07) << 18; - $mState = 3; - $mBytes = 4; - } elseif (0xF8 == (0xFC & ($in))) { - // First octet of 5 octet sequence. - // - // This is illegal because the encoded codepoint must be - // either: - // (a) not the shortest form or - // (b) outside the Unicode range of 0-0x10FFFF. - // Rather than trying to resynchronize, we will carry on - // until the end of the sequence and let the later error - // handling code catch it. - $mUcs4 = ($in); - $mUcs4 = ($mUcs4 & 0x03) << 24; - $mState = 4; - $mBytes = 5; - } elseif (0xFC == (0xFE & ($in))) { - // First octet of 6 octet sequence, see comments for 5 - // octet sequence. - $mUcs4 = ($in); - $mUcs4 = ($mUcs4 & 1) << 30; - $mState = 5; - $mBytes = 6; - } else { - // Current octet is neither in the US-ASCII range nor a - // legal first octet of a multi-octet sequence. - $mState = 0; - $mUcs4 = 0; - $mBytes = 1; - $char = ''; - } - } else { - // When mState is non-zero, we expect a continuation of the - // multi-octet sequence - if (0x80 == (0xC0 & ($in))) { - // Legal continuation. - $shift = ($mState - 1) * 6; - $tmp = $in; - $tmp = ($tmp & 0x0000003F) << $shift; - $mUcs4 |= $tmp; - - if (0 == --$mState) { - // End of the multi-octet sequence. mUcs4 now contains - // the final Unicode codepoint to be output - - // Check for illegal sequences and codepoints. - - // From Unicode 3.1, non-shortest form is illegal - if (((2 == $mBytes) && ($mUcs4 < 0x0080)) || - ((3 == $mBytes) && ($mUcs4 < 0x0800)) || - ((4 == $mBytes) && ($mUcs4 < 0x10000)) || - (4 < $mBytes) || - // From Unicode 3.2, surrogate characters = illegal - (($mUcs4 & 0xFFFFF800) == 0xD800) || - // Codepoints outside the Unicode range are illegal - ($mUcs4 > 0x10FFFF) - ) { - - } elseif (0xFEFF != $mUcs4 && // omit BOM - // check for valid Char unicode codepoints - ( - 0x9 == $mUcs4 || - 0xA == $mUcs4 || - 0xD == $mUcs4 || - (0x20 <= $mUcs4 && 0x7E >= $mUcs4) || - // 7F-9F is not strictly prohibited by XML, - // but it is non-SGML, and thus we don't allow it - (0xA0 <= $mUcs4 && 0xD7FF >= $mUcs4) || - (0x10000 <= $mUcs4 && 0x10FFFF >= $mUcs4) - ) - ) { - $out .= $char; - } - // initialize UTF8 cache (reset) - $mState = 0; - $mUcs4 = 0; - $mBytes = 1; - $char = ''; - } - } else { - // ((0xC0 & (*in) != 0x80) && (mState != 0)) - // Incomplete multi-octet sequence. - // used to result in complete fail, but we'll reset - $mState = 0; - $mUcs4 = 0; - $mBytes = 1; - $char =''; - } - } - } - return $out; - } - - /** - * Translates a Unicode codepoint into its corresponding UTF-8 character. - * @note Based on Feyd's function at - * <http://forums.devnetwork.net/viewtopic.php?p=191404#191404>, - * which is in public domain. - * @note While we're going to do code point parsing anyway, a good - * optimization would be to refuse to translate code points that - * are non-SGML characters. However, this could lead to duplication. - * @note This is very similar to the unichr function in - * maintenance/generate-entity-file.php (although this is superior, - * due to its sanity checks). - */ - - // +----------+----------+----------+----------+ - // | 33222222 | 22221111 | 111111 | | - // | 10987654 | 32109876 | 54321098 | 76543210 | bit - // +----------+----------+----------+----------+ - // | | | | 0xxxxxxx | 1 byte 0x00000000..0x0000007F - // | | | 110yyyyy | 10xxxxxx | 2 byte 0x00000080..0x000007FF - // | | 1110zzzz | 10yyyyyy | 10xxxxxx | 3 byte 0x00000800..0x0000FFFF - // | 11110www | 10wwzzzz | 10yyyyyy | 10xxxxxx | 4 byte 0x00010000..0x0010FFFF - // +----------+----------+----------+----------+ - // | 00000000 | 00011111 | 11111111 | 11111111 | Theoretical upper limit of legal scalars: 2097151 (0x001FFFFF) - // | 00000000 | 00010000 | 11111111 | 11111111 | Defined upper limit of legal scalar codes - // +----------+----------+----------+----------+ - - public static function unichr($code) { - if($code > 1114111 or $code < 0 or - ($code >= 55296 and $code <= 57343) ) { - // bits are set outside the "valid" range as defined - // by UNICODE 4.1.0 - return ''; - } - - $x = $y = $z = $w = 0; - if ($code < 128) { - // regular ASCII character - $x = $code; - } else { - // set up bits for UTF-8 - $x = ($code & 63) | 128; - if ($code < 2048) { - $y = (($code & 2047) >> 6) | 192; - } else { - $y = (($code & 4032) >> 6) | 128; - if($code < 65536) { - $z = (($code >> 12) & 15) | 224; - } else { - $z = (($code >> 12) & 63) | 128; - $w = (($code >> 18) & 7) | 240; - } - } - } - // set up the actual character - $ret = ''; - if($w) $ret .= chr($w); - if($z) $ret .= chr($z); - if($y) $ret .= chr($y); - $ret .= chr($x); - - return $ret; - } - - /** - * Converts a string to UTF-8 based on configuration. - */ - public static function convertToUTF8($str, $config, $context) { - $encoding = $config->get('Core.Encoding'); - if ($encoding === 'utf-8') return $str; - static $iconv = null; - if ($iconv === null) $iconv = function_exists('iconv'); - set_error_handler(array('HTMLPurifier_Encoder', 'muteErrorHandler')); - if ($iconv && !$config->get('Test.ForceNoIconv')) { - $str = iconv($encoding, 'utf-8//IGNORE', $str); - if ($str === false) { - // $encoding is not a valid encoding - restore_error_handler(); - trigger_error('Invalid encoding ' . $encoding, E_USER_ERROR); - return ''; - } - // If the string is bjorked by Shift_JIS or a similar encoding - // that doesn't support all of ASCII, convert the naughty - // characters to their true byte-wise ASCII/UTF-8 equivalents. - $str = strtr($str, HTMLPurifier_Encoder::testEncodingSupportsASCII($encoding)); - restore_error_handler(); - return $str; - } elseif ($encoding === 'iso-8859-1') { - $str = utf8_encode($str); - restore_error_handler(); - return $str; - } - trigger_error('Encoding not supported, please install iconv', E_USER_ERROR); - } - - /** - * Converts a string from UTF-8 based on configuration. - * @note Currently, this is a lossy conversion, with unexpressable - * characters being omitted. - */ - public static function convertFromUTF8($str, $config, $context) { - $encoding = $config->get('Core.Encoding'); - if ($encoding === 'utf-8') return $str; - static $iconv = null; - if ($iconv === null) $iconv = function_exists('iconv'); - if ($escape = $config->get('Core.EscapeNonASCIICharacters')) { - $str = HTMLPurifier_Encoder::convertToASCIIDumbLossless($str); - } - set_error_handler(array('HTMLPurifier_Encoder', 'muteErrorHandler')); - if ($iconv && !$config->get('Test.ForceNoIconv')) { - // Undo our previous fix in convertToUTF8, otherwise iconv will barf - $ascii_fix = HTMLPurifier_Encoder::testEncodingSupportsASCII($encoding); - if (!$escape && !empty($ascii_fix)) { - $clear_fix = array(); - foreach ($ascii_fix as $utf8 => $native) $clear_fix[$utf8] = ''; - $str = strtr($str, $clear_fix); - } - $str = strtr($str, array_flip($ascii_fix)); - // Normal stuff - $str = iconv('utf-8', $encoding . '//IGNORE', $str); - restore_error_handler(); - return $str; - } elseif ($encoding === 'iso-8859-1') { - $str = utf8_decode($str); - restore_error_handler(); - return $str; - } - trigger_error('Encoding not supported', E_USER_ERROR); - } - - /** - * Lossless (character-wise) conversion of HTML to ASCII - * @param $str UTF-8 string to be converted to ASCII - * @returns ASCII encoded string with non-ASCII character entity-ized - * @warning Adapted from MediaWiki, claiming fair use: this is a common - * algorithm. If you disagree with this license fudgery, - * implement it yourself. - * @note Uses decimal numeric entities since they are best supported. - * @note This is a DUMB function: it has no concept of keeping - * character entities that the projected character encoding - * can allow. We could possibly implement a smart version - * but that would require it to also know which Unicode - * codepoints the charset supported (not an easy task). - * @note Sort of with cleanUTF8() but it assumes that $str is - * well-formed UTF-8 - */ - public static function convertToASCIIDumbLossless($str) { - $bytesleft = 0; - $result = ''; - $working = 0; - $len = strlen($str); - for( $i = 0; $i < $len; $i++ ) { - $bytevalue = ord( $str[$i] ); - if( $bytevalue <= 0x7F ) { //0xxx xxxx - $result .= chr( $bytevalue ); - $bytesleft = 0; - } elseif( $bytevalue <= 0xBF ) { //10xx xxxx - $working = $working << 6; - $working += ($bytevalue & 0x3F); - $bytesleft--; - if( $bytesleft <= 0 ) { - $result .= "&#" . $working . ";"; - } - } elseif( $bytevalue <= 0xDF ) { //110x xxxx - $working = $bytevalue & 0x1F; - $bytesleft = 1; - } elseif( $bytevalue <= 0xEF ) { //1110 xxxx - $working = $bytevalue & 0x0F; - $bytesleft = 2; - } else { //1111 0xxx - $working = $bytevalue & 0x07; - $bytesleft = 3; - } - } - return $result; - } - - /** - * This expensive function tests whether or not a given character - * encoding supports ASCII. 7/8-bit encodings like Shift_JIS will - * fail this test, and require special processing. Variable width - * encodings shouldn't ever fail. - * - * @param string $encoding Encoding name to test, as per iconv format - * @param bool $bypass Whether or not to bypass the precompiled arrays. - * @return Array of UTF-8 characters to their corresponding ASCII, - * which can be used to "undo" any overzealous iconv action. - */ - public static function testEncodingSupportsASCII($encoding, $bypass = false) { - static $encodings = array(); - if (!$bypass) { - if (isset($encodings[$encoding])) return $encodings[$encoding]; - $lenc = strtolower($encoding); - switch ($lenc) { - case 'shift_jis': - return array("\xC2\xA5" => '\\', "\xE2\x80\xBE" => '~'); - case 'johab': - return array("\xE2\x82\xA9" => '\\'); - } - if (strpos($lenc, 'iso-8859-') === 0) return array(); - } - $ret = array(); - set_error_handler(array('HTMLPurifier_Encoder', 'muteErrorHandler')); - if (iconv('UTF-8', $encoding, 'a') === false) return false; - for ($i = 0x20; $i <= 0x7E; $i++) { // all printable ASCII chars - $c = chr($i); // UTF-8 char - $r = iconv('UTF-8', "$encoding//IGNORE", $c); // initial conversion - if ( - $r === '' || - // This line is needed for iconv implementations that do not - // omit characters that do not exist in the target character set - ($r === $c && iconv($encoding, 'UTF-8//IGNORE', $r) !== $c) - ) { - // Reverse engineer: what's the UTF-8 equiv of this byte - // sequence? This assumes that there's no variable width - // encoding that doesn't support ASCII. - $ret[iconv($encoding, 'UTF-8//IGNORE', $c)] = $c; - } - } - restore_error_handler(); - $encodings[$encoding] = $ret; - return $ret; - } - - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/EntityLookup.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/EntityLookup.php deleted file mode 100644 index 96dd5d4e..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/EntityLookup.php +++ /dev/null @@ -1,44 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Object that provides entity lookup table from entity name to character - */ -class HTMLPurifier_EntityLookup { - - /** - * Assoc array of entity name to character represented. - */ - public $table; - - /** - * Sets up the entity lookup table from the serialized file contents. - * @note The serialized contents are versioned, but were generated - * using the maintenance script generate_entity_file.php - * @warning This is not in constructor to help enforce the Singleton - */ - public function setup($file = false) { - if (!$file) { - $file = HTMLPURIFIER_PREFIX . '/HTMLPurifier/EntityLookup/entities.ser'; - } - $this->table = unserialize(file_get_contents($file)); - } - - /** - * Retrieves sole instance of the object. - * @param Optional prototype of custom lookup table to overload with. - */ - public static function instance($prototype = false) { - // no references, since PHP doesn't copy unless modified - static $instance = null; - if ($prototype) { - $instance = $prototype; - } elseif (!$instance) { - $instance = new HTMLPurifier_EntityLookup(); - $instance->setup(); - } - return $instance; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/EntityLookup/entities.ser b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/EntityLookup/entities.ser deleted file mode 100644 index f2b8b8f2..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/EntityLookup/entities.ser +++ /dev/null @@ -1 +0,0 @@ -a:246:{s:4:"nbsp";s:2:" ";s:5:"iexcl";s:2:"¡";s:4:"cent";s:2:"¢";s:5:"pound";s:2:"£";s:6:"curren";s:2:"¤";s:3:"yen";s:2:"¥";s:6:"brvbar";s:2:"¦";s:4:"sect";s:2:"§";s:3:"uml";s:2:"¨";s:4:"copy";s:2:"©";s:4:"ordf";s:2:"ª";s:5:"laquo";s:2:"«";s:3:"not";s:2:"¬";s:3:"shy";s:2:"";s:3:"reg";s:2:"®";s:4:"macr";s:2:"¯";s:3:"deg";s:2:"°";s:6:"plusmn";s:2:"±";s:5:"acute";s:2:"´";s:5:"micro";s:2:"µ";s:4:"para";s:2:"¶";s:6:"middot";s:2:"·";s:5:"cedil";s:2:"¸";s:4:"ordm";s:2:"º";s:5:"raquo";s:2:"»";s:6:"iquest";s:2:"¿";s:6:"Agrave";s:2:"À";s:6:"Aacute";s:2:"Á";s:5:"Acirc";s:2:"Â";s:6:"Atilde";s:2:"Ã";s:4:"Auml";s:2:"Ä";s:5:"Aring";s:2:"Å";s:5:"AElig";s:2:"Æ";s:6:"Ccedil";s:2:"Ç";s:6:"Egrave";s:2:"È";s:6:"Eacute";s:2:"É";s:5:"Ecirc";s:2:"Ê";s:4:"Euml";s:2:"Ë";s:6:"Igrave";s:2:"Ì";s:6:"Iacute";s:2:"Í";s:5:"Icirc";s:2:"Î";s:4:"Iuml";s:2:"Ï";s:3:"ETH";s:2:"Ð";s:6:"Ntilde";s:2:"Ñ";s:6:"Ograve";s:2:"Ò";s:6:"Oacute";s:2:"Ó";s:5:"Ocirc";s:2:"Ô";s:6:"Otilde";s:2:"Õ";s:4:"Ouml";s:2:"Ö";s:5:"times";s:2:"×";s:6:"Oslash";s:2:"Ø";s:6:"Ugrave";s:2:"Ù";s:6:"Uacute";s:2:"Ú";s:5:"Ucirc";s:2:"Û";s:4:"Uuml";s:2:"Ü";s:6:"Yacute";s:2:"Ý";s:5:"THORN";s:2:"Þ";s:5:"szlig";s:2:"ß";s:6:"agrave";s:2:"à";s:6:"aacute";s:2:"á";s:5:"acirc";s:2:"â";s:6:"atilde";s:2:"ã";s:4:"auml";s:2:"ä";s:5:"aring";s:2:"å";s:5:"aelig";s:2:"æ";s:6:"ccedil";s:2:"ç";s:6:"egrave";s:2:"è";s:6:"eacute";s:2:"é";s:5:"ecirc";s:2:"ê";s:4:"euml";s:2:"ë";s:6:"igrave";s:2:"ì";s:6:"iacute";s:2:"í";s:5:"icirc";s:2:"î";s:4:"iuml";s:2:"ï";s:3:"eth";s:2:"ð";s:6:"ntilde";s:2:"ñ";s:6:"ograve";s:2:"ò";s:6:"oacute";s:2:"ó";s:5:"ocirc";s:2:"ô";s:6:"otilde";s:2:"õ";s:4:"ouml";s:2:"ö";s:6:"divide";s:2:"÷";s:6:"oslash";s:2:"ø";s:6:"ugrave";s:2:"ù";s:6:"uacute";s:2:"ú";s:5:"ucirc";s:2:"û";s:4:"uuml";s:2:"ü";s:6:"yacute";s:2:"ý";s:5:"thorn";s:2:"þ";s:4:"yuml";s:2:"ÿ";s:4:"quot";s:1:""";s:3:"amp";s:1:"&";s:2:"lt";s:1:"<";s:2:"gt";s:1:">";s:4:"apos";s:1:"'";s:5:"OElig";s:2:"Œ";s:5:"oelig";s:2:"œ";s:6:"Scaron";s:2:"Š";s:6:"scaron";s:2:"š";s:4:"Yuml";s:2:"Ÿ";s:4:"circ";s:2:"ˆ";s:5:"tilde";s:2:"˜";s:4:"ensp";s:3:" ";s:4:"emsp";s:3:" ";s:6:"thinsp";s:3:" ";s:4:"zwnj";s:3:"";s:3:"zwj";s:3:"";s:3:"lrm";s:3:"";s:3:"rlm";s:3:"";s:5:"ndash";s:3:"–";s:5:"mdash";s:3:"—";s:5:"lsquo";s:3:"‘";s:5:"rsquo";s:3:"’";s:5:"sbquo";s:3:"‚";s:5:"ldquo";s:3:"“";s:5:"rdquo";s:3:"”";s:5:"bdquo";s:3:"„";s:6:"dagger";s:3:"†";s:6:"Dagger";s:3:"‡";s:6:"permil";s:3:"‰";s:6:"lsaquo";s:3:"‹";s:6:"rsaquo";s:3:"›";s:4:"euro";s:3:"€";s:4:"fnof";s:2:"ƒ";s:5:"Alpha";s:2:"Α";s:4:"Beta";s:2:"Β";s:5:"Gamma";s:2:"Γ";s:5:"Delta";s:2:"Δ";s:7:"Epsilon";s:2:"Ε";s:4:"Zeta";s:2:"Ζ";s:3:"Eta";s:2:"Η";s:5:"Theta";s:2:"Θ";s:4:"Iota";s:2:"Ι";s:5:"Kappa";s:2:"Κ";s:6:"Lambda";s:2:"Λ";s:2:"Mu";s:2:"Μ";s:2:"Nu";s:2:"Ν";s:2:"Xi";s:2:"Ξ";s:7:"Omicron";s:2:"Ο";s:2:"Pi";s:2:"Π";s:3:"Rho";s:2:"Ρ";s:5:"Sigma";s:2:"Σ";s:3:"Tau";s:2:"Τ";s:7:"Upsilon";s:2:"Υ";s:3:"Phi";s:2:"Φ";s:3:"Chi";s:2:"Χ";s:3:"Psi";s:2:"Ψ";s:5:"Omega";s:2:"Ω";s:5:"alpha";s:2:"α";s:4:"beta";s:2:"β";s:5:"gamma";s:2:"γ";s:5:"delta";s:2:"δ";s:7:"epsilon";s:2:"ε";s:4:"zeta";s:2:"ζ";s:3:"eta";s:2:"η";s:5:"theta";s:2:"θ";s:4:"iota";s:2:"ι";s:5:"kappa";s:2:"κ";s:6:"lambda";s:2:"λ";s:2:"mu";s:2:"μ";s:2:"nu";s:2:"ν";s:2:"xi";s:2:"ξ";s:7:"omicron";s:2:"ο";s:2:"pi";s:2:"π";s:3:"rho";s:2:"ρ";s:6:"sigmaf";s:2:"ς";s:5:"sigma";s:2:"σ";s:3:"tau";s:2:"τ";s:7:"upsilon";s:2:"υ";s:3:"phi";s:2:"φ";s:3:"chi";s:2:"χ";s:3:"psi";s:2:"ψ";s:5:"omega";s:2:"ω";s:8:"thetasym";s:2:"ϑ";s:5:"upsih";s:2:"ϒ";s:3:"piv";s:2:"ϖ";s:4:"bull";s:3:"•";s:6:"hellip";s:3:"…";s:5:"prime";s:3:"′";s:5:"Prime";s:3:"″";s:5:"oline";s:3:"‾";s:5:"frasl";s:3:"⁄";s:6:"weierp";s:3:"℘";s:5:"image";s:3:"ℑ";s:4:"real";s:3:"ℜ";s:5:"trade";s:3:"™";s:7:"alefsym";s:3:"ℵ";s:4:"larr";s:3:"←";s:4:"uarr";s:3:"↑";s:4:"rarr";s:3:"→";s:4:"darr";s:3:"↓";s:4:"harr";s:3:"↔";s:5:"crarr";s:3:"↵";s:4:"lArr";s:3:"⇐";s:4:"uArr";s:3:"⇑";s:4:"rArr";s:3:"⇒";s:4:"dArr";s:3:"⇓";s:4:"hArr";s:3:"⇔";s:6:"forall";s:3:"∀";s:4:"part";s:3:"∂";s:5:"exist";s:3:"∃";s:5:"empty";s:3:"∅";s:5:"nabla";s:3:"∇";s:4:"isin";s:3:"∈";s:5:"notin";s:3:"∉";s:2:"ni";s:3:"∋";s:4:"prod";s:3:"∏";s:3:"sum";s:3:"∑";s:5:"minus";s:3:"−";s:6:"lowast";s:3:"∗";s:5:"radic";s:3:"√";s:4:"prop";s:3:"∝";s:5:"infin";s:3:"∞";s:3:"ang";s:3:"∠";s:3:"and";s:3:"∧";s:2:"or";s:3:"∨";s:3:"cap";s:3:"∩";s:3:"cup";s:3:"∪";s:3:"int";s:3:"∫";s:3:"sim";s:3:"∼";s:4:"cong";s:3:"≅";s:5:"asymp";s:3:"≈";s:2:"ne";s:3:"≠";s:5:"equiv";s:3:"≡";s:2:"le";s:3:"≤";s:2:"ge";s:3:"≥";s:3:"sub";s:3:"⊂";s:3:"sup";s:3:"⊃";s:4:"nsub";s:3:"⊄";s:4:"sube";s:3:"⊆";s:4:"supe";s:3:"⊇";s:5:"oplus";s:3:"⊕";s:6:"otimes";s:3:"⊗";s:4:"perp";s:3:"⊥";s:4:"sdot";s:3:"⋅";s:5:"lceil";s:3:"⌈";s:5:"rceil";s:3:"⌉";s:6:"lfloor";s:3:"⌊";s:6:"rfloor";s:3:"⌋";s:4:"lang";s:3:"〈";s:4:"rang";s:3:"〉";s:3:"loz";s:3:"◊";s:6:"spades";s:3:"♠";s:5:"clubs";s:3:"♣";s:6:"hearts";s:3:"♥";s:5:"diams";s:3:"♦";}
\ No newline at end of file diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/EntityParser.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/EntityParser.php deleted file mode 100644 index 6e102ca7..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/EntityParser.php +++ /dev/null @@ -1,144 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -// if want to implement error collecting here, we'll need to use some sort -// of global data (probably trigger_error) because it's impossible to pass -// $config or $context to the callback functions. - -/** - * Handles referencing and derefencing character entities - */ -class HTMLPurifier_EntityParser -{ - - /** - * Reference to entity lookup table. - */ - protected $_entity_lookup; - - /** - * Callback regex string for parsing entities. - */ - protected $_substituteEntitiesRegex = -'/&(?:[#]x([a-fA-F0-9]+)|[#]0*(\d+)|([A-Za-z_:][A-Za-z0-9.\-_:]*));?/'; -// 1. hex 2. dec 3. string (XML style) - - - /** - * Decimal to parsed string conversion table for special entities. - */ - protected $_special_dec2str = - array( - 34 => '"', - 38 => '&', - 39 => "'", - 60 => '<', - 62 => '>' - ); - - /** - * Stripped entity names to decimal conversion table for special entities. - */ - protected $_special_ent2dec = - array( - 'quot' => 34, - 'amp' => 38, - 'lt' => 60, - 'gt' => 62 - ); - - /** - * Substitutes non-special entities with their parsed equivalents. Since - * running this whenever you have parsed character is t3h 5uck, we run - * it before everything else. - * - * @param $string String to have non-special entities parsed. - * @returns Parsed string. - */ - public function substituteNonSpecialEntities($string) { - // it will try to detect missing semicolons, but don't rely on it - return preg_replace_callback( - $this->_substituteEntitiesRegex, - array($this, 'nonSpecialEntityCallback'), - $string - ); - } - - /** - * Callback function for substituteNonSpecialEntities() that does the work. - * - * @param $matches PCRE matches array, with 0 the entire match, and - * either index 1, 2 or 3 set with a hex value, dec value, - * or string (respectively). - * @returns Replacement string. - */ - - protected function nonSpecialEntityCallback($matches) { - // replaces all but big five - $entity = $matches[0]; - $is_num = (@$matches[0][1] === '#'); - if ($is_num) { - $is_hex = (@$entity[2] === 'x'); - $code = $is_hex ? hexdec($matches[1]) : (int) $matches[2]; - - // abort for special characters - if (isset($this->_special_dec2str[$code])) return $entity; - - return HTMLPurifier_Encoder::unichr($code); - } else { - if (isset($this->_special_ent2dec[$matches[3]])) return $entity; - if (!$this->_entity_lookup) { - $this->_entity_lookup = HTMLPurifier_EntityLookup::instance(); - } - if (isset($this->_entity_lookup->table[$matches[3]])) { - return $this->_entity_lookup->table[$matches[3]]; - } else { - return $entity; - } - } - } - - /** - * Substitutes only special entities with their parsed equivalents. - * - * @notice We try to avoid calling this function because otherwise, it - * would have to be called a lot (for every parsed section). - * - * @param $string String to have non-special entities parsed. - * @returns Parsed string. - */ - public function substituteSpecialEntities($string) { - return preg_replace_callback( - $this->_substituteEntitiesRegex, - array($this, 'specialEntityCallback'), - $string); - } - - /** - * Callback function for substituteSpecialEntities() that does the work. - * - * This callback has same syntax as nonSpecialEntityCallback(). - * - * @param $matches PCRE-style matches array, with 0 the entire match, and - * either index 1, 2 or 3 set with a hex value, dec value, - * or string (respectively). - * @returns Replacement string. - */ - protected function specialEntityCallback($matches) { - $entity = $matches[0]; - $is_num = (@$matches[0][1] === '#'); - if ($is_num) { - $is_hex = (@$entity[2] === 'x'); - $int = $is_hex ? hexdec($matches[1]) : (int) $matches[2]; - return isset($this->_special_dec2str[$int]) ? - $this->_special_dec2str[$int] : - $entity; - } else { - return isset($this->_special_ent2dec[$matches[3]]) ? - $this->_special_ent2dec[$matches[3]] : - $entity; - } - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ErrorCollector.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ErrorCollector.php deleted file mode 100644 index cc6275ef..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ErrorCollector.php +++ /dev/null @@ -1,209 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Error collection class that enables HTML Purifier to report HTML - * problems back to the user - */ -class HTMLPurifier_ErrorCollector -{ - - /** - * Identifiers for the returned error array. These are purposely numeric - * so list() can be used. - */ - const LINENO = 0; - const SEVERITY = 1; - const MESSAGE = 2; - const CHILDREN = 3; - - protected $errors; - protected $_current; - protected $_stacks = array(array()); - protected $locale; - protected $generator; - protected $context; - - protected $lines = array(); - - public function __construct($context) { - $this->locale =& $context->get('Locale'); - $this->context = $context; - $this->_current =& $this->_stacks[0]; - $this->errors =& $this->_stacks[0]; - } - - /** - * Sends an error message to the collector for later use - * @param $severity int Error severity, PHP error style (don't use E_USER_) - * @param $msg string Error message text - * @param $subst1 string First substitution for $msg - * @param $subst2 string ... - */ - public function send($severity, $msg) { - - $args = array(); - if (func_num_args() > 2) { - $args = func_get_args(); - array_shift($args); - unset($args[0]); - } - - $token = $this->context->get('CurrentToken', true); - $line = $token ? $token->line : $this->context->get('CurrentLine', true); - $col = $token ? $token->col : $this->context->get('CurrentCol', true); - $attr = $this->context->get('CurrentAttr', true); - - // perform special substitutions, also add custom parameters - $subst = array(); - if (!is_null($token)) { - $args['CurrentToken'] = $token; - } - if (!is_null($attr)) { - $subst['$CurrentAttr.Name'] = $attr; - if (isset($token->attr[$attr])) $subst['$CurrentAttr.Value'] = $token->attr[$attr]; - } - - if (empty($args)) { - $msg = $this->locale->getMessage($msg); - } else { - $msg = $this->locale->formatMessage($msg, $args); - } - - if (!empty($subst)) $msg = strtr($msg, $subst); - - // (numerically indexed) - $error = array( - self::LINENO => $line, - self::SEVERITY => $severity, - self::MESSAGE => $msg, - self::CHILDREN => array() - ); - $this->_current[] = $error; - - - // NEW CODE BELOW ... - - $struct = null; - // Top-level errors are either: - // TOKEN type, if $value is set appropriately, or - // "syntax" type, if $value is null - $new_struct = new HTMLPurifier_ErrorStruct(); - $new_struct->type = HTMLPurifier_ErrorStruct::TOKEN; - if ($token) $new_struct->value = clone $token; - if (is_int($line) && is_int($col)) { - if (isset($this->lines[$line][$col])) { - $struct = $this->lines[$line][$col]; - } else { - $struct = $this->lines[$line][$col] = $new_struct; - } - // These ksorts may present a performance problem - ksort($this->lines[$line], SORT_NUMERIC); - } else { - if (isset($this->lines[-1])) { - $struct = $this->lines[-1]; - } else { - $struct = $this->lines[-1] = $new_struct; - } - } - ksort($this->lines, SORT_NUMERIC); - - // Now, check if we need to operate on a lower structure - if (!empty($attr)) { - $struct = $struct->getChild(HTMLPurifier_ErrorStruct::ATTR, $attr); - if (!$struct->value) { - $struct->value = array($attr, 'PUT VALUE HERE'); - } - } - if (!empty($cssprop)) { - $struct = $struct->getChild(HTMLPurifier_ErrorStruct::CSSPROP, $cssprop); - if (!$struct->value) { - // if we tokenize CSS this might be a little more difficult to do - $struct->value = array($cssprop, 'PUT VALUE HERE'); - } - } - - // Ok, structs are all setup, now time to register the error - $struct->addError($severity, $msg); - } - - /** - * Retrieves raw error data for custom formatter to use - * @param List of arrays in format of array(line of error, - * error severity, error message, - * recursive sub-errors array) - */ - public function getRaw() { - return $this->errors; - } - - /** - * Default HTML formatting implementation for error messages - * @param $config Configuration array, vital for HTML output nature - * @param $errors Errors array to display; used for recursion. - */ - public function getHTMLFormatted($config, $errors = null) { - $ret = array(); - - $this->generator = new HTMLPurifier_Generator($config, $this->context); - if ($errors === null) $errors = $this->errors; - - // 'At line' message needs to be removed - - // generation code for new structure goes here. It needs to be recursive. - foreach ($this->lines as $line => $col_array) { - if ($line == -1) continue; - foreach ($col_array as $col => $struct) { - $this->_renderStruct($ret, $struct, $line, $col); - } - } - if (isset($this->lines[-1])) { - $this->_renderStruct($ret, $this->lines[-1]); - } - - if (empty($errors)) { - return '<p>' . $this->locale->getMessage('ErrorCollector: No errors') . '</p>'; - } else { - return '<ul><li>' . implode('</li><li>', $ret) . '</li></ul>'; - } - - } - - private function _renderStruct(&$ret, $struct, $line = null, $col = null) { - $stack = array($struct); - $context_stack = array(array()); - while ($current = array_pop($stack)) { - $context = array_pop($context_stack); - foreach ($current->errors as $error) { - list($severity, $msg) = $error; - $string = ''; - $string .= '<div>'; - // W3C uses an icon to indicate the severity of the error. - $error = $this->locale->getErrorName($severity); - $string .= "<span class=\"error e$severity\"><strong>$error</strong></span> "; - if (!is_null($line) && !is_null($col)) { - $string .= "<em class=\"location\">Line $line, Column $col: </em> "; - } else { - $string .= '<em class="location">End of Document: </em> '; - } - $string .= '<strong class="description">' . $this->generator->escape($msg) . '</strong> '; - $string .= '</div>'; - // Here, have a marker for the character on the column appropriate. - // Be sure to clip extremely long lines. - //$string .= '<pre>'; - //$string .= ''; - //$string .= '</pre>'; - $ret[] = $string; - } - foreach ($current->children as $type => $array) { - $context[] = $current; - $stack = array_merge($stack, array_reverse($array, true)); - for ($i = count($array); $i > 0; $i--) { - $context_stack[] = $context; - } - } - } - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ErrorStruct.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ErrorStruct.php deleted file mode 100644 index 721c88c1..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/ErrorStruct.php +++ /dev/null @@ -1,60 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Records errors for particular segments of an HTML document such as tokens, - * attributes or CSS properties. They can contain error structs (which apply - * to components of what they represent), but their main purpose is to hold - * errors applying to whatever struct is being used. - */ -class HTMLPurifier_ErrorStruct -{ - - /** - * Possible values for $children first-key. Note that top-level structures - * are automatically token-level. - */ - const TOKEN = 0; - const ATTR = 1; - const CSSPROP = 2; - - /** - * Type of this struct. - */ - public $type; - - /** - * Value of the struct we are recording errors for. There are various - * values for this: - * - TOKEN: Instance of HTMLPurifier_Token - * - ATTR: array('attr-name', 'value') - * - CSSPROP: array('prop-name', 'value') - */ - public $value; - - /** - * Errors registered for this structure. - */ - public $errors = array(); - - /** - * Child ErrorStructs that are from this structure. For example, a TOKEN - * ErrorStruct would contain ATTR ErrorStructs. This is a multi-dimensional - * array in structure: [TYPE]['identifier'] - */ - public $children = array(); - - public function getChild($type, $id) { - if (!isset($this->children[$type][$id])) { - $this->children[$type][$id] = new HTMLPurifier_ErrorStruct(); - $this->children[$type][$id]->type = $type; - } - return $this->children[$type][$id]; - } - - public function addError($severity, $message) { - $this->errors[] = array($severity, $message); - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Exception.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Exception.php deleted file mode 100644 index 1882ee68..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Exception.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Global exception class for HTML Purifier; any exceptions we throw - * are from here. - */ -class HTMLPurifier_Exception extends Exception -{ - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Filter.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Filter.php deleted file mode 100644 index e0469101..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Filter.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Represents a pre or post processing filter on HTML Purifier's output - * - * Sometimes, a little ad-hoc fixing of HTML has to be done before - * it gets sent through HTML Purifier: you can use filters to acheive - * this effect. For instance, YouTube videos can be preserved using - * this manner. You could have used a decorator for this task, but - * PHP's support for them is not terribly robust, so we're going - * to just loop through the filters. - * - * Filters should be exited first in, last out. If there are three filters, - * named 1, 2 and 3, the order of execution should go 1->preFilter, - * 2->preFilter, 3->preFilter, purify, 3->postFilter, 2->postFilter, - * 1->postFilter. - * - * @note Methods are not declared abstract as it is perfectly legitimate - * for an implementation not to want anything to happen on a step - */ - -class HTMLPurifier_Filter -{ - - /** - * Name of the filter for identification purposes - */ - public $name; - - /** - * Pre-processor function, handles HTML before HTML Purifier - */ - public function preFilter($html, $config, $context) { - return $html; - } - - /** - * Post-processor function, handles HTML after HTML Purifier - */ - public function postFilter($html, $config, $context) { - return $html; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Filter/ExtractStyleBlocks.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Filter/ExtractStyleBlocks.php deleted file mode 100644 index f97b3cb3..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Filter/ExtractStyleBlocks.php +++ /dev/null @@ -1,135 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * This filter extracts <style> blocks from input HTML, cleans them up - * using CSSTidy, and then places them in $purifier->context->get('StyleBlocks') - * so they can be used elsewhere in the document. - * - * @note - * See tests/HTMLPurifier/Filter/ExtractStyleBlocksTest.php for - * sample usage. - * - * @note - * This filter can also be used on stylesheets not included in the - * document--something purists would probably prefer. Just directly - * call HTMLPurifier_Filter_ExtractStyleBlocks->cleanCSS() - */ -class HTMLPurifier_Filter_ExtractStyleBlocks extends HTMLPurifier_Filter -{ - - public $name = 'ExtractStyleBlocks'; - private $_styleMatches = array(); - private $_tidy; - - public function __construct() { - $this->_tidy = new csstidy(); - } - - /** - * Save the contents of CSS blocks to style matches - * @param $matches preg_replace style $matches array - */ - protected function styleCallback($matches) { - $this->_styleMatches[] = $matches[1]; - } - - /** - * Removes inline <style> tags from HTML, saves them for later use - * @todo Extend to indicate non-text/css style blocks - */ - public function preFilter($html, $config, $context) { - $tidy = $config->get('Filter.ExtractStyleBlocks.TidyImpl'); - if ($tidy !== null) $this->_tidy = $tidy; - $html = preg_replace_callback('#<style(?:\s.*)?>(.+)</style>#isU', array($this, 'styleCallback'), $html); - $style_blocks = $this->_styleMatches; - $this->_styleMatches = array(); // reset - $context->register('StyleBlocks', $style_blocks); // $context must not be reused - if ($this->_tidy) { - foreach ($style_blocks as &$style) { - $style = $this->cleanCSS($style, $config, $context); - } - } - return $html; - } - - /** - * Takes CSS (the stuff found in <style>) and cleans it. - * @warning Requires CSSTidy <http://csstidy.sourceforge.net/> - * @param $css CSS styling to clean - * @param $config Instance of HTMLPurifier_Config - * @param $context Instance of HTMLPurifier_Context - * @return Cleaned CSS - */ - public function cleanCSS($css, $config, $context) { - // prepare scope - $scope = $config->get('Filter.ExtractStyleBlocks.Scope'); - if ($scope !== null) { - $scopes = array_map('trim', explode(',', $scope)); - } else { - $scopes = array(); - } - // remove comments from CSS - $css = trim($css); - if (strncmp('<!--', $css, 4) === 0) { - $css = substr($css, 4); - } - if (strlen($css) > 3 && substr($css, -3) == '-->') { - $css = substr($css, 0, -3); - } - $css = trim($css); - $this->_tidy->parse($css); - $css_definition = $config->getDefinition('CSS'); - foreach ($this->_tidy->css as $k => $decls) { - // $decls are all CSS declarations inside an @ selector - $new_decls = array(); - foreach ($decls as $selector => $style) { - $selector = trim($selector); - if ($selector === '') continue; // should not happen - if ($selector[0] === '+') { - if ($selector !== '' && $selector[0] === '+') continue; - } - if (!empty($scopes)) { - $new_selector = array(); // because multiple ones are possible - $selectors = array_map('trim', explode(',', $selector)); - foreach ($scopes as $s1) { - foreach ($selectors as $s2) { - $new_selector[] = "$s1 $s2"; - } - } - $selector = implode(', ', $new_selector); // now it's a string - } - foreach ($style as $name => $value) { - if (!isset($css_definition->info[$name])) { - unset($style[$name]); - continue; - } - $def = $css_definition->info[$name]; - $ret = $def->validate($value, $config, $context); - if ($ret === false) unset($style[$name]); - else $style[$name] = $ret; - } - $new_decls[$selector] = $style; - } - $this->_tidy->css[$k] = $new_decls; - } - // remove stuff that shouldn't be used, could be reenabled - // after security risks are analyzed - $this->_tidy->import = array(); - $this->_tidy->charset = null; - $this->_tidy->namespace = null; - $css = $this->_tidy->print->plain(); - // we are going to escape any special characters <>& to ensure - // that no funny business occurs (i.e. </style> in a font-family prop). - if ($config->get('Filter.ExtractStyleBlocks.Escaping')) { - $css = str_replace( - array('<', '>', '&'), - array('\3C ', '\3E ', '\26 '), - $css - ); - } - return $css; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Filter/YouTube.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Filter/YouTube.php deleted file mode 100644 index aa3c17a0..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Filter/YouTube.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -class HTMLPurifier_Filter_YouTube extends HTMLPurifier_Filter -{ - - public $name = 'YouTube'; - - public function preFilter($html, $config, $context) { - $pre_regex = '#<object[^>]+>.+?'. - 'http://www.youtube.com/v/([A-Za-z0-9\-_]+).+?</object>#s'; - $pre_replace = '<span class="youtube-embed">\1</span>'; - return preg_replace($pre_regex, $pre_replace, $html); - } - - public function postFilter($html, $config, $context) { - $post_regex = '#<span class="youtube-embed">([A-Za-z0-9\-_]+)</span>#'; - return preg_replace_callback($post_regex, array($this, 'postFilterCallback'), $html); - } - - protected function armorUrl($url) { - return str_replace('--', '--', $url); - } - - protected function postFilterCallback($matches) { - $url = $this->armorUrl($matches[1]); - return '<object width="425" height="350" type="application/x-shockwave-flash" '. - 'data="http://www.youtube.com/v/'.$url.'">'. - '<param name="movie" value="http://www.youtube.com/v/'.$url.'"></param>'. - '<!--[if IE]>'. - '<embed src="http://www.youtube.com/v/'.$url.'"'. - 'type="application/x-shockwave-flash"'. - 'wmode="transparent" width="425" height="350" />'. - '<![endif]-->'. - '</object>'; - - } -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Generator.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Generator.php deleted file mode 100644 index 22e841c1..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Generator.php +++ /dev/null @@ -1,183 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Generates HTML from tokens. - * @todo Refactor interface so that configuration/context is determined - * upon instantiation, no need for messy generateFromTokens() calls - * @todo Make some of the more internal functions protected, and have - * unit tests work around that - */ -class HTMLPurifier_Generator -{ - - /** - * Whether or not generator should produce XML output - */ - private $_xhtml = true; - - /** - * :HACK: Whether or not generator should comment the insides of <script> tags - */ - private $_scriptFix = false; - - /** - * Cache of HTMLDefinition during HTML output to determine whether or - * not attributes should be minimized. - */ - private $_def; - - /** - * Cache of %Output.SortAttr - */ - private $_sortAttr; - - /** - * Configuration for the generator - */ - protected $config; - - /** - * @param $config Instance of HTMLPurifier_Config - * @param $context Instance of HTMLPurifier_Context - */ - public function __construct($config, $context) { - $this->config = $config; - $this->_scriptFix = $config->get('Output.CommentScriptContents'); - $this->_sortAttr = $config->get('Output.SortAttr'); - $this->_def = $config->getHTMLDefinition(); - $this->_xhtml = $this->_def->doctype->xml; - } - - /** - * Generates HTML from an array of tokens. - * @param $tokens Array of HTMLPurifier_Token - * @param $config HTMLPurifier_Config object - * @return Generated HTML - */ - public function generateFromTokens($tokens) { - if (!$tokens) return ''; - - // Basic algorithm - $html = ''; - for ($i = 0, $size = count($tokens); $i < $size; $i++) { - if ($this->_scriptFix && $tokens[$i]->name === 'script' - && $i + 2 < $size && $tokens[$i+2] instanceof HTMLPurifier_Token_End) { - // script special case - // the contents of the script block must be ONE token - // for this to work. - $html .= $this->generateFromToken($tokens[$i++]); - $html .= $this->generateScriptFromToken($tokens[$i++]); - } - $html .= $this->generateFromToken($tokens[$i]); - } - - // Tidy cleanup - if (extension_loaded('tidy') && $this->config->get('Output.TidyFormat')) { - $tidy = new Tidy; - $tidy->parseString($html, array( - 'indent'=> true, - 'output-xhtml' => $this->_xhtml, - 'show-body-only' => true, - 'indent-spaces' => 2, - 'wrap' => 68, - ), 'utf8'); - $tidy->cleanRepair(); - $html = (string) $tidy; // explicit cast necessary - } - - // Normalize newlines to system defined value - $nl = $this->config->get('Output.Newline'); - if ($nl === null) $nl = PHP_EOL; - if ($nl !== "\n") $html = str_replace("\n", $nl, $html); - return $html; - } - - /** - * Generates HTML from a single token. - * @param $token HTMLPurifier_Token object. - * @return Generated HTML - */ - public function generateFromToken($token) { - if (!$token instanceof HTMLPurifier_Token) { - trigger_error('Cannot generate HTML from non-HTMLPurifier_Token object', E_USER_WARNING); - return ''; - - } elseif ($token instanceof HTMLPurifier_Token_Start) { - $attr = $this->generateAttributes($token->attr, $token->name); - return '<' . $token->name . ($attr ? ' ' : '') . $attr . '>'; - - } elseif ($token instanceof HTMLPurifier_Token_End) { - return '</' . $token->name . '>'; - - } elseif ($token instanceof HTMLPurifier_Token_Empty) { - $attr = $this->generateAttributes($token->attr, $token->name); - return '<' . $token->name . ($attr ? ' ' : '') . $attr . - ( $this->_xhtml ? ' /': '' ) // <br /> v. <br> - . '>'; - - } elseif ($token instanceof HTMLPurifier_Token_Text) { - return $this->escape($token->data, ENT_NOQUOTES); - - } elseif ($token instanceof HTMLPurifier_Token_Comment) { - return '<!--' . $token->data . '-->'; - } else { - return ''; - - } - } - - /** - * Special case processor for the contents of script tags - * @warning This runs into problems if there's already a literal - * --> somewhere inside the script contents. - */ - public function generateScriptFromToken($token) { - if (!$token instanceof HTMLPurifier_Token_Text) return $this->generateFromToken($token); - // Thanks <http://lachy.id.au/log/2005/05/script-comments> - $data = preg_replace('#//\s*$#', '', $token->data); - return '<!--//--><![CDATA[//><!--' . "\n" . trim($data) . "\n" . '//--><!]]>'; - } - - /** - * Generates attribute declarations from attribute array. - * @note This does not include the leading or trailing space. - * @param $assoc_array_of_attributes Attribute array - * @param $element Name of element attributes are for, used to check - * attribute minimization. - * @return Generate HTML fragment for insertion. - */ - public function generateAttributes($assoc_array_of_attributes, $element = false) { - $html = ''; - if ($this->_sortAttr) ksort($assoc_array_of_attributes); - foreach ($assoc_array_of_attributes as $key => $value) { - if (!$this->_xhtml) { - // Remove namespaced attributes - if (strpos($key, ':') !== false) continue; - // Check if we should minimize the attribute: val="val" -> val - if ($element && !empty($this->_def->info[$element]->attr[$key]->minimized)) { - $html .= $key . ' '; - continue; - } - } - $html .= $key.'="'.$this->escape($value).'" '; - } - return rtrim($html); - } - - /** - * Escapes raw text data. - * @todo This really ought to be protected, but until we have a facility - * for properly generating HTML here w/o using tokens, it stays - * public. - * @param $string String data to escape for HTML. - * @param $quote Quoting style, like htmlspecialchars. ENT_NOQUOTES is - * permissible for non-attribute output. - * @return String escaped data. - */ - public function escape($string, $quote = ENT_COMPAT) { - return htmlspecialchars($string, $quote, 'UTF-8'); - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLDefinition.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLDefinition.php deleted file mode 100644 index 0195ce4c..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLDefinition.php +++ /dev/null @@ -1,420 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Definition of the purified HTML that describes allowed children, - * attributes, and many other things. - * - * Conventions: - * - * All member variables that are prefixed with info - * (including the main $info array) are used by HTML Purifier internals - * and should not be directly edited when customizing the HTMLDefinition. - * They can usually be set via configuration directives or custom - * modules. - * - * On the other hand, member variables without the info prefix are used - * internally by the HTMLDefinition and MUST NOT be used by other HTML - * Purifier internals. Many of them, however, are public, and may be - * edited by userspace code to tweak the behavior of HTMLDefinition. - * - * @note This class is inspected by Printer_HTMLDefinition; please - * update that class if things here change. - * - * @warning Directives that change this object's structure must be in - * the HTML or Attr namespace! - */ -class HTMLPurifier_HTMLDefinition extends HTMLPurifier_Definition -{ - - // FULLY-PUBLIC VARIABLES --------------------------------------------- - - /** - * Associative array of element names to HTMLPurifier_ElementDef - */ - public $info = array(); - - /** - * Associative array of global attribute name to attribute definition. - */ - public $info_global_attr = array(); - - /** - * String name of parent element HTML will be going into. - */ - public $info_parent = 'div'; - - /** - * Definition for parent element, allows parent element to be a - * tag that's not allowed inside the HTML fragment. - */ - public $info_parent_def; - - /** - * String name of element used to wrap inline elements in block context - * @note This is rarely used except for BLOCKQUOTEs in strict mode - */ - public $info_block_wrapper = 'p'; - - /** - * Associative array of deprecated tag name to HTMLPurifier_TagTransform - */ - public $info_tag_transform = array(); - - /** - * Indexed list of HTMLPurifier_AttrTransform to be performed before validation. - */ - public $info_attr_transform_pre = array(); - - /** - * Indexed list of HTMLPurifier_AttrTransform to be performed after validation. - */ - public $info_attr_transform_post = array(); - - /** - * Nested lookup array of content set name (Block, Inline) to - * element name to whether or not it belongs in that content set. - */ - public $info_content_sets = array(); - - /** - * Indexed list of HTMLPurifier_Injector to be used. - */ - public $info_injector = array(); - - /** - * Doctype object - */ - public $doctype; - - - - // RAW CUSTOMIZATION STUFF -------------------------------------------- - - /** - * Adds a custom attribute to a pre-existing element - * @note This is strictly convenience, and does not have a corresponding - * method in HTMLPurifier_HTMLModule - * @param $element_name String element name to add attribute to - * @param $attr_name String name of attribute - * @param $def Attribute definition, can be string or object, see - * HTMLPurifier_AttrTypes for details - */ - public function addAttribute($element_name, $attr_name, $def) { - $module = $this->getAnonymousModule(); - if (!isset($module->info[$element_name])) { - $element = $module->addBlankElement($element_name); - } else { - $element = $module->info[$element_name]; - } - $element->attr[$attr_name] = $def; - } - - /** - * Adds a custom element to your HTML definition - * @note See HTMLPurifier_HTMLModule::addElement for detailed - * parameter and return value descriptions. - */ - public function addElement($element_name, $type, $contents, $attr_collections, $attributes = array()) { - $module = $this->getAnonymousModule(); - // assume that if the user is calling this, the element - // is safe. This may not be a good idea - $element = $module->addElement($element_name, $type, $contents, $attr_collections, $attributes); - return $element; - } - - /** - * Adds a blank element to your HTML definition, for overriding - * existing behavior - * @note See HTMLPurifier_HTMLModule::addBlankElement for detailed - * parameter and return value descriptions. - */ - public function addBlankElement($element_name) { - $module = $this->getAnonymousModule(); - $element = $module->addBlankElement($element_name); - return $element; - } - - /** - * Retrieves a reference to the anonymous module, so you can - * bust out advanced features without having to make your own - * module. - */ - public function getAnonymousModule() { - if (!$this->_anonModule) { - $this->_anonModule = new HTMLPurifier_HTMLModule(); - $this->_anonModule->name = 'Anonymous'; - } - return $this->_anonModule; - } - - private $_anonModule; - - - // PUBLIC BUT INTERNAL VARIABLES -------------------------------------- - - public $type = 'HTML'; - public $manager; /**< Instance of HTMLPurifier_HTMLModuleManager */ - - /** - * Performs low-cost, preliminary initialization. - */ - public function __construct() { - $this->manager = new HTMLPurifier_HTMLModuleManager(); - } - - protected function doSetup($config) { - $this->processModules($config); - $this->setupConfigStuff($config); - unset($this->manager); - - // cleanup some of the element definitions - foreach ($this->info as $k => $v) { - unset($this->info[$k]->content_model); - unset($this->info[$k]->content_model_type); - } - } - - /** - * Extract out the information from the manager - */ - protected function processModules($config) { - - if ($this->_anonModule) { - // for user specific changes - // this is late-loaded so we don't have to deal with PHP4 - // reference wonky-ness - $this->manager->addModule($this->_anonModule); - unset($this->_anonModule); - } - - $this->manager->setup($config); - $this->doctype = $this->manager->doctype; - - foreach ($this->manager->modules as $module) { - foreach($module->info_tag_transform as $k => $v) { - if ($v === false) unset($this->info_tag_transform[$k]); - else $this->info_tag_transform[$k] = $v; - } - foreach($module->info_attr_transform_pre as $k => $v) { - if ($v === false) unset($this->info_attr_transform_pre[$k]); - else $this->info_attr_transform_pre[$k] = $v; - } - foreach($module->info_attr_transform_post as $k => $v) { - if ($v === false) unset($this->info_attr_transform_post[$k]); - else $this->info_attr_transform_post[$k] = $v; - } - foreach ($module->info_injector as $k => $v) { - if ($v === false) unset($this->info_injector[$k]); - else $this->info_injector[$k] = $v; - } - } - - $this->info = $this->manager->getElements(); - $this->info_content_sets = $this->manager->contentSets->lookup; - - } - - /** - * Sets up stuff based on config. We need a better way of doing this. - */ - protected function setupConfigStuff($config) { - - $block_wrapper = $config->get('HTML.BlockWrapper'); - if (isset($this->info_content_sets['Block'][$block_wrapper])) { - $this->info_block_wrapper = $block_wrapper; - } else { - trigger_error('Cannot use non-block element as block wrapper', - E_USER_ERROR); - } - - $parent = $config->get('HTML.Parent'); - $def = $this->manager->getElement($parent, true); - if ($def) { - $this->info_parent = $parent; - $this->info_parent_def = $def; - } else { - trigger_error('Cannot use unrecognized element as parent', - E_USER_ERROR); - $this->info_parent_def = $this->manager->getElement($this->info_parent, true); - } - - // support template text - $support = "(for information on implementing this, see the ". - "support forums) "; - - // setup allowed elements ----------------------------------------- - - $allowed_elements = $config->get('HTML.AllowedElements'); - $allowed_attributes = $config->get('HTML.AllowedAttributes'); // retrieve early - - if (!is_array($allowed_elements) && !is_array($allowed_attributes)) { - $allowed = $config->get('HTML.Allowed'); - if (is_string($allowed)) { - list($allowed_elements, $allowed_attributes) = $this->parseTinyMCEAllowedList($allowed); - } - } - - if (is_array($allowed_elements)) { - foreach ($this->info as $name => $d) { - if(!isset($allowed_elements[$name])) unset($this->info[$name]); - unset($allowed_elements[$name]); - } - // emit errors - foreach ($allowed_elements as $element => $d) { - $element = htmlspecialchars($element); // PHP doesn't escape errors, be careful! - trigger_error("Element '$element' is not supported $support", E_USER_WARNING); - } - } - - // setup allowed attributes --------------------------------------- - - $allowed_attributes_mutable = $allowed_attributes; // by copy! - if (is_array($allowed_attributes)) { - - // This actually doesn't do anything, since we went away from - // global attributes. It's possible that userland code uses - // it, but HTMLModuleManager doesn't! - foreach ($this->info_global_attr as $attr => $x) { - $keys = array($attr, "*@$attr", "*.$attr"); - $delete = true; - foreach ($keys as $key) { - if ($delete && isset($allowed_attributes[$key])) { - $delete = false; - } - if (isset($allowed_attributes_mutable[$key])) { - unset($allowed_attributes_mutable[$key]); - } - } - if ($delete) unset($this->info_global_attr[$attr]); - } - - foreach ($this->info as $tag => $info) { - foreach ($info->attr as $attr => $x) { - $keys = array("$tag@$attr", $attr, "*@$attr", "$tag.$attr", "*.$attr"); - $delete = true; - foreach ($keys as $key) { - if ($delete && isset($allowed_attributes[$key])) { - $delete = false; - } - if (isset($allowed_attributes_mutable[$key])) { - unset($allowed_attributes_mutable[$key]); - } - } - if ($delete) unset($this->info[$tag]->attr[$attr]); - } - } - // emit errors - foreach ($allowed_attributes_mutable as $elattr => $d) { - $bits = preg_split('/[.@]/', $elattr, 2); - $c = count($bits); - switch ($c) { - case 2: - if ($bits[0] !== '*') { - $element = htmlspecialchars($bits[0]); - $attribute = htmlspecialchars($bits[1]); - if (!isset($this->info[$element])) { - trigger_error("Cannot allow attribute '$attribute' if element '$element' is not allowed/supported $support"); - } else { - trigger_error("Attribute '$attribute' in element '$element' not supported $support", - E_USER_WARNING); - } - break; - } - // otherwise fall through - case 1: - $attribute = htmlspecialchars($bits[0]); - trigger_error("Global attribute '$attribute' is not ". - "supported in any elements $support", - E_USER_WARNING); - break; - } - } - - } - - // setup forbidden elements --------------------------------------- - - $forbidden_elements = $config->get('HTML.ForbiddenElements'); - $forbidden_attributes = $config->get('HTML.ForbiddenAttributes'); - - foreach ($this->info as $tag => $info) { - if (isset($forbidden_elements[$tag])) { - unset($this->info[$tag]); - continue; - } - foreach ($info->attr as $attr => $x) { - if ( - isset($forbidden_attributes["$tag@$attr"]) || - isset($forbidden_attributes["*@$attr"]) || - isset($forbidden_attributes[$attr]) - ) { - unset($this->info[$tag]->attr[$attr]); - continue; - } // this segment might get removed eventually - elseif (isset($forbidden_attributes["$tag.$attr"])) { - // $tag.$attr are not user supplied, so no worries! - trigger_error("Error with $tag.$attr: tag.attr syntax not supported for HTML.ForbiddenAttributes; use tag@attr instead", E_USER_WARNING); - } - } - } - foreach ($forbidden_attributes as $key => $v) { - if (strlen($key) < 2) continue; - if ($key[0] != '*') continue; - if ($key[1] == '.') { - trigger_error("Error with $key: *.attr syntax not supported for HTML.ForbiddenAttributes; use attr instead", E_USER_WARNING); - } - } - - // setup injectors ----------------------------------------------------- - foreach ($this->info_injector as $i => $injector) { - if ($injector->checkNeeded($config) !== false) { - // remove injector that does not have it's required - // elements/attributes present, and is thus not needed. - unset($this->info_injector[$i]); - } - } - } - - /** - * Parses a TinyMCE-flavored Allowed Elements and Attributes list into - * separate lists for processing. Format is element[attr1|attr2],element2... - * @warning Although it's largely drawn from TinyMCE's implementation, - * it is different, and you'll probably have to modify your lists - * @param $list String list to parse - * @param array($allowed_elements, $allowed_attributes) - * @todo Give this its own class, probably static interface - */ - public function parseTinyMCEAllowedList($list) { - - $list = str_replace(array(' ', "\t"), '', $list); - - $elements = array(); - $attributes = array(); - - $chunks = preg_split('/(,|[\n\r]+)/', $list); - foreach ($chunks as $chunk) { - if (empty($chunk)) continue; - // remove TinyMCE element control characters - if (!strpos($chunk, '[')) { - $element = $chunk; - $attr = false; - } else { - list($element, $attr) = explode('[', $chunk); - } - if ($element !== '*') $elements[$element] = true; - if (!$attr) continue; - $attr = substr($attr, 0, strlen($attr) - 1); // remove trailing ] - $attr = explode('|', $attr); - foreach ($attr as $key) { - $attributes["$element.$key"] = true; - } - } - - return array($elements, $attributes); - - } - - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule.php deleted file mode 100644 index 44b6f33f..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule.php +++ /dev/null @@ -1,244 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Represents an XHTML 1.1 module, with information on elements, tags - * and attributes. - * @note Even though this is technically XHTML 1.1, it is also used for - * regular HTML parsing. We are using modulization as a convenient - * way to represent the internals of HTMLDefinition, and our - * implementation is by no means conforming and does not directly - * use the normative DTDs or XML schemas. - * @note The public variables in a module should almost directly - * correspond to the variables in HTMLPurifier_HTMLDefinition. - * However, the prefix info carries no special meaning in these - * objects (include it anyway if that's the correspondence though). - * @todo Consider making some member functions protected - */ - -class HTMLPurifier_HTMLModule -{ - - // -- Overloadable ---------------------------------------------------- - - /** - * Short unique string identifier of the module - */ - public $name; - - /** - * Informally, a list of elements this module changes. Not used in - * any significant way. - */ - public $elements = array(); - - /** - * Associative array of element names to element definitions. - * Some definitions may be incomplete, to be merged in later - * with the full definition. - */ - public $info = array(); - - /** - * Associative array of content set names to content set additions. - * This is commonly used to, say, add an A element to the Inline - * content set. This corresponds to an internal variable $content_sets - * and NOT info_content_sets member variable of HTMLDefinition. - */ - public $content_sets = array(); - - /** - * Associative array of attribute collection names to attribute - * collection additions. More rarely used for adding attributes to - * the global collections. Example is the StyleAttribute module adding - * the style attribute to the Core. Corresponds to HTMLDefinition's - * attr_collections->info, since the object's data is only info, - * with extra behavior associated with it. - */ - public $attr_collections = array(); - - /** - * Associative array of deprecated tag name to HTMLPurifier_TagTransform - */ - public $info_tag_transform = array(); - - /** - * List of HTMLPurifier_AttrTransform to be performed before validation. - */ - public $info_attr_transform_pre = array(); - - /** - * List of HTMLPurifier_AttrTransform to be performed after validation. - */ - public $info_attr_transform_post = array(); - - /** - * List of HTMLPurifier_Injector to be performed during well-formedness fixing. - * An injector will only be invoked if all of it's pre-requisites are met; - * if an injector fails setup, there will be no error; it will simply be - * silently disabled. - */ - public $info_injector = array(); - - /** - * Boolean flag that indicates whether or not getChildDef is implemented. - * For optimization reasons: may save a call to a function. Be sure - * to set it if you do implement getChildDef(), otherwise it will have - * no effect! - */ - public $defines_child_def = false; - - /** - * Boolean flag whether or not this module is safe. If it is not safe, all - * of its members are unsafe. Modules are safe by default (this might be - * slightly dangerous, but it doesn't make much sense to force HTML Purifier, - * which is based off of safe HTML, to explicitly say, "This is safe," even - * though there are modules which are "unsafe") - * - * @note Previously, safety could be applied at an element level granularity. - * We've removed this ability, so in order to add "unsafe" elements - * or attributes, a dedicated module with this property set to false - * must be used. - */ - public $safe = true; - - /** - * Retrieves a proper HTMLPurifier_ChildDef subclass based on - * content_model and content_model_type member variables of - * the HTMLPurifier_ElementDef class. There is a similar function - * in HTMLPurifier_HTMLDefinition. - * @param $def HTMLPurifier_ElementDef instance - * @return HTMLPurifier_ChildDef subclass - */ - public function getChildDef($def) {return false;} - - // -- Convenience ----------------------------------------------------- - - /** - * Convenience function that sets up a new element - * @param $element Name of element to add - * @param $type What content set should element be registered to? - * Set as false to skip this step. - * @param $contents Allowed children in form of: - * "$content_model_type: $content_model" - * @param $attr_includes What attribute collections to register to - * element? - * @param $attr What unique attributes does the element define? - * @note See ElementDef for in-depth descriptions of these parameters. - * @return Created element definition object, so you - * can set advanced parameters - */ - public function addElement($element, $type, $contents, $attr_includes = array(), $attr = array()) { - $this->elements[] = $element; - // parse content_model - list($content_model_type, $content_model) = $this->parseContents($contents); - // merge in attribute inclusions - $this->mergeInAttrIncludes($attr, $attr_includes); - // add element to content sets - if ($type) $this->addElementToContentSet($element, $type); - // create element - $this->info[$element] = HTMLPurifier_ElementDef::create( - $content_model, $content_model_type, $attr - ); - // literal object $contents means direct child manipulation - if (!is_string($contents)) $this->info[$element]->child = $contents; - return $this->info[$element]; - } - - /** - * Convenience function that creates a totally blank, non-standalone - * element. - * @param $element Name of element to create - * @return Created element - */ - public function addBlankElement($element) { - if (!isset($this->info[$element])) { - $this->elements[] = $element; - $this->info[$element] = new HTMLPurifier_ElementDef(); - $this->info[$element]->standalone = false; - } else { - trigger_error("Definition for $element already exists in module, cannot redefine"); - } - return $this->info[$element]; - } - - /** - * Convenience function that registers an element to a content set - * @param Element to register - * @param Name content set (warning: case sensitive, usually upper-case - * first letter) - */ - public function addElementToContentSet($element, $type) { - if (!isset($this->content_sets[$type])) $this->content_sets[$type] = ''; - else $this->content_sets[$type] .= ' | '; - $this->content_sets[$type] .= $element; - } - - /** - * Convenience function that transforms single-string contents - * into separate content model and content model type - * @param $contents Allowed children in form of: - * "$content_model_type: $content_model" - * @note If contents is an object, an array of two nulls will be - * returned, and the callee needs to take the original $contents - * and use it directly. - */ - public function parseContents($contents) { - if (!is_string($contents)) return array(null, null); // defer - switch ($contents) { - // check for shorthand content model forms - case 'Empty': - return array('empty', ''); - case 'Inline': - return array('optional', 'Inline | #PCDATA'); - case 'Flow': - return array('optional', 'Flow | #PCDATA'); - } - list($content_model_type, $content_model) = explode(':', $contents); - $content_model_type = strtolower(trim($content_model_type)); - $content_model = trim($content_model); - return array($content_model_type, $content_model); - } - - /** - * Convenience function that merges a list of attribute includes into - * an attribute array. - * @param $attr Reference to attr array to modify - * @param $attr_includes Array of includes / string include to merge in - */ - public function mergeInAttrIncludes(&$attr, $attr_includes) { - if (!is_array($attr_includes)) { - if (empty($attr_includes)) $attr_includes = array(); - else $attr_includes = array($attr_includes); - } - $attr[0] = $attr_includes; - } - - /** - * Convenience function that generates a lookup table with boolean - * true as value. - * @param $list List of values to turn into a lookup - * @note You can also pass an arbitrary number of arguments in - * place of the regular argument - * @return Lookup array equivalent of list - */ - public function makeLookup($list) { - if (is_string($list)) $list = func_get_args(); - $ret = array(); - foreach ($list as $value) { - if (is_null($value)) continue; - $ret[$value] = true; - } - return $ret; - } - - /** - * Lazy load construction of the module after determining whether - * or not it's needed, and also when a finalized configuration object - * is available. - * @param $config Instance of HTMLPurifier_Config - */ - public function setup($config) {} - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Bdo.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Bdo.php deleted file mode 100644 index 745b4b62..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Bdo.php +++ /dev/null @@ -1,31 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * XHTML 1.1 Bi-directional Text Module, defines elements that - * declare directionality of content. Text Extension Module. - */ -class HTMLPurifier_HTMLModule_Bdo extends HTMLPurifier_HTMLModule -{ - - public $name = 'Bdo'; - public $attr_collections = array( - 'I18N' => array('dir' => false) - ); - - public function setup($config) { - $bdo = $this->addElement( - 'bdo', 'Inline', 'Inline', array('Core', 'Lang'), - array( - 'dir' => 'Enum#ltr,rtl', // required - // The Abstract Module specification has the attribute - // inclusions wrong for bdo: bdo allows Lang - ) - ); - $bdo->attr_transform_post['required-dir'] = new HTMLPurifier_AttrTransform_BdoDir(); - - $this->attr_collections['I18N']['dir'] = 'Enum#ltr,rtl'; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/CommonAttributes.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/CommonAttributes.php deleted file mode 100644 index 44b3779b..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/CommonAttributes.php +++ /dev/null @@ -1,26 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -class HTMLPurifier_HTMLModule_CommonAttributes extends HTMLPurifier_HTMLModule -{ - public $name = 'CommonAttributes'; - - public $attr_collections = array( - 'Core' => array( - 0 => array('Style'), - // 'xml:space' => false, - 'class' => 'Class', - 'id' => 'ID', - 'title' => 'CDATA', - ), - 'Lang' => array(), - 'I18N' => array( - 0 => array('Lang'), // proprietary, for xml:lang/lang - ), - 'Common' => array( - 0 => array('Core', 'I18N') - ) - ); - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Edit.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Edit.php deleted file mode 100644 index 3275bd5f..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Edit.php +++ /dev/null @@ -1,38 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * XHTML 1.1 Edit Module, defines editing-related elements. Text Extension - * Module. - */ -class HTMLPurifier_HTMLModule_Edit extends HTMLPurifier_HTMLModule -{ - - public $name = 'Edit'; - - public function setup($config) { - $contents = 'Chameleon: #PCDATA | Inline ! #PCDATA | Flow'; - $attr = array( - 'cite' => 'URI', - // 'datetime' => 'Datetime', // not implemented - ); - $this->addElement('del', 'Inline', $contents, 'Common', $attr); - $this->addElement('ins', 'Inline', $contents, 'Common', $attr); - } - - // HTML 4.01 specifies that ins/del must not contain block - // elements when used in an inline context, chameleon is - // a complicated workaround to acheive this effect - - // Inline context ! Block context (exclamation mark is - // separator, see getChildDef for parsing) - - public $defines_child_def = true; - public function getChildDef($def) { - if ($def->content_model_type != 'chameleon') return false; - $value = explode('!', $def->content_model); - return new HTMLPurifier_ChildDef_Chameleon($value[0], $value[1]); - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Forms.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Forms.php deleted file mode 100644 index b8211abd..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Forms.php +++ /dev/null @@ -1,118 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * XHTML 1.1 Forms module, defines all form-related elements found in HTML 4. - */ -class HTMLPurifier_HTMLModule_Forms extends HTMLPurifier_HTMLModule -{ - public $name = 'Forms'; - public $safe = false; - - public $content_sets = array( - 'Block' => 'Form', - 'Inline' => 'Formctrl', - ); - - public function setup($config) { - $form = $this->addElement('form', 'Form', - 'Required: Heading | List | Block | fieldset', 'Common', array( - 'accept' => 'ContentTypes', - 'accept-charset' => 'Charsets', - 'action*' => 'URI', - 'method' => 'Enum#get,post', - // really ContentType, but these two are the only ones used today - 'enctype' => 'Enum#application/x-www-form-urlencoded,multipart/form-data', - )); - $form->excludes = array('form' => true); - - $input = $this->addElement('input', 'Formctrl', 'Empty', 'Common', array( - 'accept' => 'ContentTypes', - 'accesskey' => 'Character', - 'alt' => 'Text', - 'checked' => 'Bool#checked', - 'disabled' => 'Bool#disabled', - 'maxlength' => 'Number', - 'name' => 'CDATA', - 'readonly' => 'Bool#readonly', - 'size' => 'Number', - 'src' => 'URI#embeds', - 'tabindex' => 'Number', - 'type' => 'Enum#text,password,checkbox,button,radio,submit,reset,file,hidden,image', - 'value' => 'CDATA', - )); - $input->attr_transform_post[] = new HTMLPurifier_AttrTransform_Input(); - - $this->addElement('select', 'Formctrl', 'Required: optgroup | option', 'Common', array( - 'disabled' => 'Bool#disabled', - 'multiple' => 'Bool#multiple', - 'name' => 'CDATA', - 'size' => 'Number', - 'tabindex' => 'Number', - )); - - $this->addElement('option', false, 'Optional: #PCDATA', 'Common', array( - 'disabled' => 'Bool#disabled', - 'label' => 'Text', - 'selected' => 'Bool#selected', - 'value' => 'CDATA', - )); - // It's illegal for there to be more than one selected, but not - // be multiple. Also, no selected means undefined behavior. This might - // be difficult to implement; perhaps an injector, or a context variable. - - $textarea = $this->addElement('textarea', 'Formctrl', 'Optional: #PCDATA', 'Common', array( - 'accesskey' => 'Character', - 'cols*' => 'Number', - 'disabled' => 'Bool#disabled', - 'name' => 'CDATA', - 'readonly' => 'Bool#readonly', - 'rows*' => 'Number', - 'tabindex' => 'Number', - )); - $textarea->attr_transform_pre[] = new HTMLPurifier_AttrTransform_Textarea(); - - $button = $this->addElement('button', 'Formctrl', 'Optional: #PCDATA | Heading | List | Block | Inline', 'Common', array( - 'accesskey' => 'Character', - 'disabled' => 'Bool#disabled', - 'name' => 'CDATA', - 'tabindex' => 'Number', - 'type' => 'Enum#button,submit,reset', - 'value' => 'CDATA', - )); - - // For exclusions, ideally we'd specify content sets, not literal elements - $button->excludes = $this->makeLookup( - 'form', 'fieldset', // Form - 'input', 'select', 'textarea', 'label', 'button', // Formctrl - 'a' // as per HTML 4.01 spec, this is omitted by modularization - ); - - // Extra exclusion: img usemap="" is not permitted within this element. - // We'll omit this for now, since we don't have any good way of - // indicating it yet. - - // This is HIGHLY user-unfriendly; we need a custom child-def for this - $this->addElement('fieldset', 'Form', 'Custom: (#WS?,legend,(Flow|#PCDATA)*)', 'Common'); - - $label = $this->addElement('label', 'Formctrl', 'Optional: #PCDATA | Inline', 'Common', array( - 'accesskey' => 'Character', - // 'for' => 'IDREF', // IDREF not implemented, cannot allow - )); - $label->excludes = array('label' => true); - - $this->addElement('legend', false, 'Optional: #PCDATA | Inline', 'Common', array( - 'accesskey' => 'Character', - )); - - $this->addElement('optgroup', false, 'Required: option', 'Common', array( - 'disabled' => 'Bool#disabled', - 'label*' => 'Text', - )); - - // Don't forget an injector for <isindex>. This one's a little complex - // because it maps to multiple elements. - - } -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Hypertext.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Hypertext.php deleted file mode 100644 index ec95bb6f..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Hypertext.php +++ /dev/null @@ -1,31 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * XHTML 1.1 Hypertext Module, defines hypertext links. Core Module. - */ -class HTMLPurifier_HTMLModule_Hypertext extends HTMLPurifier_HTMLModule -{ - - public $name = 'Hypertext'; - - public function setup($config) { - $a = $this->addElement( - 'a', 'Inline', 'Inline', 'Common', - array( - // 'accesskey' => 'Character', - // 'charset' => 'Charset', - 'href' => 'URI', - // 'hreflang' => 'LanguageCode', - 'rel' => new HTMLPurifier_AttrDef_HTML_LinkTypes('rel'), - 'rev' => new HTMLPurifier_AttrDef_HTML_LinkTypes('rev'), - // 'tabindex' => 'Number', - // 'type' => 'ContentType', - ) - ); - $a->formatting = true; - $a->excludes = array('a' => true); - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Image.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Image.php deleted file mode 100644 index eb61c038..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Image.php +++ /dev/null @@ -1,40 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * XHTML 1.1 Image Module provides basic image embedding. - * @note There is specialized code for removing empty images in - * HTMLPurifier_Strategy_RemoveForeignElements - */ -class HTMLPurifier_HTMLModule_Image extends HTMLPurifier_HTMLModule -{ - - public $name = 'Image'; - - public function setup($config) { - $max = $config->get('HTML.MaxImgLength'); - $img = $this->addElement( - 'img', 'Inline', 'Empty', 'Common', - array( - 'alt*' => 'Text', - // According to the spec, it's Length, but percents can - // be abused, so we allow only Pixels. - 'height' => 'Pixels#' . $max, - 'width' => 'Pixels#' . $max, - 'longdesc' => 'URI', - 'src*' => new HTMLPurifier_AttrDef_URI(true), // embedded - ) - ); - if ($max === null || $config->get('HTML.Trusted')) { - $img->attr['height'] = - $img->attr['width'] = 'Length'; - } - - // kind of strange, but splitting things up would be inefficient - $img->attr_transform_pre[] = - $img->attr_transform_post[] = - new HTMLPurifier_AttrTransform_ImgRequired(); - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Legacy.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Legacy.php deleted file mode 100644 index a65c6170..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Legacy.php +++ /dev/null @@ -1,143 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * XHTML 1.1 Legacy module defines elements that were previously - * deprecated. - * - * @note Not all legacy elements have been implemented yet, which - * is a bit of a reverse problem as compared to browsers! In - * addition, this legacy module may implement a bit more than - * mandated by XHTML 1.1. - * - * This module can be used in combination with TransformToStrict in order - * to transform as many deprecated elements as possible, but retain - * questionably deprecated elements that do not have good alternatives - * as well as transform elements that don't have an implementation. - * See docs/ref-strictness.txt for more details. - */ - -class HTMLPurifier_HTMLModule_Legacy extends HTMLPurifier_HTMLModule -{ - - public $name = 'Legacy'; - - public function setup($config) { - - $this->addElement('basefont', 'Inline', 'Empty', false, array( - 'color' => 'Color', - 'face' => 'Text', // extremely broad, we should - 'size' => 'Text', // tighten it - 'id' => 'ID' - )); - $this->addElement('center', 'Block', 'Flow', 'Common'); - $this->addElement('dir', 'Block', 'Required: li', 'Common', array( - 'compact' => 'Bool#compact' - )); - $this->addElement('font', 'Inline', 'Inline', array('Core', 'I18N'), array( - 'color' => 'Color', - 'face' => 'Text', // extremely broad, we should - 'size' => 'Text', // tighten it - )); - $this->addElement('menu', 'Block', 'Required: li', 'Common', array( - 'compact' => 'Bool#compact' - )); - - $s = $this->addElement('s', 'Inline', 'Inline', 'Common'); - $s->formatting = true; - - $strike = $this->addElement('strike', 'Inline', 'Inline', 'Common'); - $strike->formatting = true; - - $u = $this->addElement('u', 'Inline', 'Inline', 'Common'); - $u->formatting = true; - - // setup modifications to old elements - - $align = 'Enum#left,right,center,justify'; - - $address = $this->addBlankElement('address'); - $address->content_model = 'Inline | #PCDATA | p'; - $address->content_model_type = 'optional'; - $address->child = false; - - $blockquote = $this->addBlankElement('blockquote'); - $blockquote->content_model = 'Flow | #PCDATA'; - $blockquote->content_model_type = 'optional'; - $blockquote->child = false; - - $br = $this->addBlankElement('br'); - $br->attr['clear'] = 'Enum#left,all,right,none'; - - $caption = $this->addBlankElement('caption'); - $caption->attr['align'] = 'Enum#top,bottom,left,right'; - - $div = $this->addBlankElement('div'); - $div->attr['align'] = $align; - - $dl = $this->addBlankElement('dl'); - $dl->attr['compact'] = 'Bool#compact'; - - for ($i = 1; $i <= 6; $i++) { - $h = $this->addBlankElement("h$i"); - $h->attr['align'] = $align; - } - - $hr = $this->addBlankElement('hr'); - $hr->attr['align'] = $align; - $hr->attr['noshade'] = 'Bool#noshade'; - $hr->attr['size'] = 'Pixels'; - $hr->attr['width'] = 'Length'; - - $img = $this->addBlankElement('img'); - $img->attr['align'] = 'Enum#top,middle,bottom,left,right'; - $img->attr['border'] = 'Pixels'; - $img->attr['hspace'] = 'Pixels'; - $img->attr['vspace'] = 'Pixels'; - - // figure out this integer business - - $li = $this->addBlankElement('li'); - $li->attr['value'] = new HTMLPurifier_AttrDef_Integer(); - $li->attr['type'] = 'Enum#s:1,i,I,a,A,disc,square,circle'; - - $ol = $this->addBlankElement('ol'); - $ol->attr['compact'] = 'Bool#compact'; - $ol->attr['start'] = new HTMLPurifier_AttrDef_Integer(); - $ol->attr['type'] = 'Enum#s:1,i,I,a,A'; - - $p = $this->addBlankElement('p'); - $p->attr['align'] = $align; - - $pre = $this->addBlankElement('pre'); - $pre->attr['width'] = 'Number'; - - // script omitted - - $table = $this->addBlankElement('table'); - $table->attr['align'] = 'Enum#left,center,right'; - $table->attr['bgcolor'] = 'Color'; - - $tr = $this->addBlankElement('tr'); - $tr->attr['bgcolor'] = 'Color'; - - $th = $this->addBlankElement('th'); - $th->attr['bgcolor'] = 'Color'; - $th->attr['height'] = 'Length'; - $th->attr['nowrap'] = 'Bool#nowrap'; - $th->attr['width'] = 'Length'; - - $td = $this->addBlankElement('td'); - $td->attr['bgcolor'] = 'Color'; - $td->attr['height'] = 'Length'; - $td->attr['nowrap'] = 'Bool#nowrap'; - $td->attr['width'] = 'Length'; - - $ul = $this->addBlankElement('ul'); - $ul->attr['compact'] = 'Bool#compact'; - $ul->attr['type'] = 'Enum#square,disc,circle'; - - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/List.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/List.php deleted file mode 100644 index db2d5324..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/List.php +++ /dev/null @@ -1,35 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * XHTML 1.1 List Module, defines list-oriented elements. Core Module. - */ -class HTMLPurifier_HTMLModule_List extends HTMLPurifier_HTMLModule -{ - - public $name = 'List'; - - // According to the abstract schema, the List content set is a fully formed - // one or more expr, but it invariably occurs in an optional declaration - // so we're not going to do that subtlety. It might cause trouble - // if a user defines "List" and expects that multiple lists are - // allowed to be specified, but then again, that's not very intuitive. - // Furthermore, the actual XML Schema may disagree. Regardless, - // we don't have support for such nested expressions without using - // the incredibly inefficient and draconic Custom ChildDef. - - public $content_sets = array('Flow' => 'List'); - - public function setup($config) { - $this->addElement('ol', 'List', 'Required: li', 'Common'); - $this->addElement('ul', 'List', 'Required: li', 'Common'); - $this->addElement('dl', 'List', 'Required: dt | dd', 'Common'); - - $this->addElement('li', false, 'Flow', 'Common'); - - $this->addElement('dd', false, 'Flow', 'Common'); - $this->addElement('dt', false, 'Inline', 'Common'); - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Name.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Name.php deleted file mode 100644 index c7e27afb..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Name.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -class HTMLPurifier_HTMLModule_Name extends HTMLPurifier_HTMLModule -{ - - public $name = 'Name'; - - public function setup($config) { - $elements = array('a', 'applet', 'form', 'frame', 'iframe', 'img', 'map'); - foreach ($elements as $name) { - $element = $this->addBlankElement($name); - $element->attr['name'] = 'CDATA'; - if (!$config->get('HTML.Attr.Name.UseCDATA')) { - $element->attr_transform_post['NameSync'] = new HTMLPurifier_AttrTransform_NameSync(); - } - } - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/NonXMLCommonAttributes.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/NonXMLCommonAttributes.php deleted file mode 100644 index 8b493ac4..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/NonXMLCommonAttributes.php +++ /dev/null @@ -1,14 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -class HTMLPurifier_HTMLModule_NonXMLCommonAttributes extends HTMLPurifier_HTMLModule -{ - public $name = 'NonXMLCommonAttributes'; - - public $attr_collections = array( - 'Lang' => array( - 'lang' => 'LanguageCode', - ) - ); -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Object.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Object.php deleted file mode 100644 index 9277dd56..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Object.php +++ /dev/null @@ -1,47 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * XHTML 1.1 Object Module, defines elements for generic object inclusion - * @warning Users will commonly use <embed> to cater to legacy browsers: this - * module does not allow this sort of behavior - */ -class HTMLPurifier_HTMLModule_Object extends HTMLPurifier_HTMLModule -{ - - public $name = 'Object'; - public $safe = false; - - public function setup($config) { - - $this->addElement('object', 'Inline', 'Optional: #PCDATA | Flow | param', 'Common', - array( - 'archive' => 'URI', - 'classid' => 'URI', - 'codebase' => 'URI', - 'codetype' => 'Text', - 'data' => 'URI', - 'declare' => 'Bool#declare', - 'height' => 'Length', - 'name' => 'CDATA', - 'standby' => 'Text', - 'tabindex' => 'Number', - 'type' => 'ContentType', - 'width' => 'Length' - ) - ); - - $this->addElement('param', false, 'Empty', false, - array( - 'id' => 'ID', - 'name*' => 'Text', - 'type' => 'Text', - 'value' => 'Text', - 'valuetype' => 'Enum#data,ref,object' - ) - ); - - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Presentation.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Presentation.php deleted file mode 100644 index 6745977b..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Presentation.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * XHTML 1.1 Presentation Module, defines simple presentation-related - * markup. Text Extension Module. - * @note The official XML Schema and DTD specs further divide this into - * two modules: - * - Block Presentation (hr) - * - Inline Presentation (b, big, i, small, sub, sup, tt) - * We have chosen not to heed this distinction, as content_sets - * provides satisfactory disambiguation. - */ -class HTMLPurifier_HTMLModule_Presentation extends HTMLPurifier_HTMLModule -{ - - public $name = 'Presentation'; - - public function setup($config) { - $this->addElement('hr', 'Block', 'Empty', 'Common'); - $this->addElement('sub', 'Inline', 'Inline', 'Common'); - $this->addElement('sup', 'Inline', 'Inline', 'Common'); - $b = $this->addElement('b', 'Inline', 'Inline', 'Common'); - $b->formatting = true; - $big = $this->addElement('big', 'Inline', 'Inline', 'Common'); - $big->formatting = true; - $i = $this->addElement('i', 'Inline', 'Inline', 'Common'); - $i->formatting = true; - $small = $this->addElement('small', 'Inline', 'Inline', 'Common'); - $small->formatting = true; - $tt = $this->addElement('tt', 'Inline', 'Inline', 'Common'); - $tt->formatting = true; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Proprietary.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Proprietary.php deleted file mode 100644 index 176de468..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Proprietary.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Module defines proprietary tags and attributes in HTML. - * @warning If this module is enabled, standards-compliance is off! - */ -class HTMLPurifier_HTMLModule_Proprietary extends HTMLPurifier_HTMLModule -{ - - public $name = 'Proprietary'; - - public function setup($config) { - - $this->addElement('marquee', 'Inline', 'Flow', 'Common', - array( - 'direction' => 'Enum#left,right,up,down', - 'behavior' => 'Enum#alternate', - 'width' => 'Length', - 'height' => 'Length', - 'scrolldelay' => 'Number', - 'scrollamount' => 'Number', - 'loop' => 'Number', - 'bgcolor' => 'Color', - 'hspace' => 'Pixels', - 'vspace' => 'Pixels', - ) - ); - - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Ruby.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Ruby.php deleted file mode 100644 index c3f0cbb2..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Ruby.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * XHTML 1.1 Ruby Annotation Module, defines elements that indicate - * short runs of text alongside base text for annotation or pronounciation. - */ -class HTMLPurifier_HTMLModule_Ruby extends HTMLPurifier_HTMLModule -{ - - public $name = 'Ruby'; - - public function setup($config) { - $this->addElement('ruby', 'Inline', - 'Custom: ((rb, (rt | (rp, rt, rp))) | (rbc, rtc, rtc?))', - 'Common'); - $this->addElement('rbc', false, 'Required: rb', 'Common'); - $this->addElement('rtc', false, 'Required: rt', 'Common'); - $rb = $this->addElement('rb', false, 'Inline', 'Common'); - $rb->excludes = array('ruby' => true); - $rt = $this->addElement('rt', false, 'Inline', 'Common', array('rbspan' => 'Number')); - $rt->excludes = array('ruby' => true); - $this->addElement('rp', false, 'Optional: #PCDATA', 'Common'); - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/SafeEmbed.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/SafeEmbed.php deleted file mode 100644 index 1fd57145..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/SafeEmbed.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * A "safe" embed module. See SafeObject. This is a proprietary element. - */ -class HTMLPurifier_HTMLModule_SafeEmbed extends HTMLPurifier_HTMLModule -{ - - public $name = 'SafeEmbed'; - - public function setup($config) { - - $max = $config->get('HTML.MaxImgLength'); - $embed = $this->addElement( - 'embed', 'Inline', 'Empty', 'Common', - array( - 'src*' => 'URI#embedded', - 'type' => 'Enum#application/x-shockwave-flash', - 'width' => 'Pixels#' . $max, - 'height' => 'Pixels#' . $max, - 'allowscriptaccess' => 'Enum#never', - 'allownetworking' => 'Enum#internal', - 'wmode' => 'Enum#window', - 'name' => 'ID', - ) - ); - $embed->attr_transform_post[] = new HTMLPurifier_AttrTransform_SafeEmbed(); - - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/SafeObject.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/SafeObject.php deleted file mode 100644 index 4378d2c6..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/SafeObject.php +++ /dev/null @@ -1,50 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * A "safe" object module. In theory, objects permitted by this module will - * be safe, and untrusted users can be allowed to embed arbitrary flash objects - * (maybe other types too, but only Flash is supported as of right now). - * Highly experimental. - */ -class HTMLPurifier_HTMLModule_SafeObject extends HTMLPurifier_HTMLModule -{ - - public $name = 'SafeObject'; - - public function setup($config) { - - // These definitions are not intrinsically safe: the attribute transforms - // are a vital part of ensuring safety. - - $max = $config->get('HTML.MaxImgLength'); - $object = $this->addElement( - 'object', - 'Inline', - 'Optional: param | Flow | #PCDATA', - 'Common', - array( - // While technically not required by the spec, we're forcing - // it to this value. - 'type' => 'Enum#application/x-shockwave-flash', - 'width' => 'Pixels#' . $max, - 'height' => 'Pixels#' . $max, - 'data' => 'URI#embedded' - ) - ); - $object->attr_transform_post[] = new HTMLPurifier_AttrTransform_SafeObject(); - - $param = $this->addElement('param', false, 'Empty', false, - array( - 'id' => 'ID', - 'name*' => 'Text', - 'value' => 'Text' - ) - ); - $param->attr_transform_post[] = new HTMLPurifier_AttrTransform_SafeParam(); - $this->info_injector[] = 'SafeObject'; - - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Scripting.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Scripting.php deleted file mode 100644 index 08502a62..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Scripting.php +++ /dev/null @@ -1,54 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/* - -WARNING: THIS MODULE IS EXTREMELY DANGEROUS AS IT ENABLES INLINE SCRIPTING -INSIDE HTML PURIFIER DOCUMENTS. USE ONLY WITH TRUSTED USER INPUT!!! - -*/ - -/** - * XHTML 1.1 Scripting module, defines elements that are used to contain - * information pertaining to executable scripts or the lack of support - * for executable scripts. - * @note This module does not contain inline scripting elements - */ -class HTMLPurifier_HTMLModule_Scripting extends HTMLPurifier_HTMLModule -{ - public $name = 'Scripting'; - public $elements = array('script', 'noscript'); - public $content_sets = array('Block' => 'script | noscript', 'Inline' => 'script | noscript'); - public $safe = false; - - public function setup($config) { - // TODO: create custom child-definition for noscript that - // auto-wraps stray #PCDATA in a similar manner to - // blockquote's custom definition (we would use it but - // blockquote's contents are optional while noscript's contents - // are required) - - // TODO: convert this to new syntax, main problem is getting - // both content sets working - - // In theory, this could be safe, but I don't see any reason to - // allow it. - $this->info['noscript'] = new HTMLPurifier_ElementDef(); - $this->info['noscript']->attr = array( 0 => array('Common') ); - $this->info['noscript']->content_model = 'Heading | List | Block'; - $this->info['noscript']->content_model_type = 'required'; - - $this->info['script'] = new HTMLPurifier_ElementDef(); - $this->info['script']->attr = array( - 'defer' => new HTMLPurifier_AttrDef_Enum(array('defer')), - 'src' => new HTMLPurifier_AttrDef_URI(true), - 'type' => new HTMLPurifier_AttrDef_Enum(array('text/javascript')) - ); - $this->info['script']->content_model = '#PCDATA'; - $this->info['script']->content_model_type = 'optional'; - $this->info['script']->attr_transform_pre['type'] = - $this->info['script']->attr_transform_post['type'] = - new HTMLPurifier_AttrTransform_ScriptRequired(); - } -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/StyleAttribute.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/StyleAttribute.php deleted file mode 100644 index 47285ceb..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/StyleAttribute.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * XHTML 1.1 Edit Module, defines editing-related elements. Text Extension - * Module. - */ -class HTMLPurifier_HTMLModule_StyleAttribute extends HTMLPurifier_HTMLModule -{ - - public $name = 'StyleAttribute'; - public $attr_collections = array( - // The inclusion routine differs from the Abstract Modules but - // is in line with the DTD and XML Schemas. - 'Style' => array('style' => false), // see constructor - 'Core' => array(0 => array('Style')) - ); - - public function setup($config) { - $this->attr_collections['Style']['style'] = new HTMLPurifier_AttrDef_CSS(); - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Tables.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Tables.php deleted file mode 100644 index d0fd0251..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Tables.php +++ /dev/null @@ -1,66 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * XHTML 1.1 Tables Module, fully defines accessible table elements. - */ -class HTMLPurifier_HTMLModule_Tables extends HTMLPurifier_HTMLModule -{ - - public $name = 'Tables'; - - public function setup($config) { - - $this->addElement('caption', false, 'Inline', 'Common'); - - $this->addElement('table', 'Block', - new HTMLPurifier_ChildDef_Table(), 'Common', - array( - 'border' => 'Pixels', - 'cellpadding' => 'Length', - 'cellspacing' => 'Length', - 'frame' => 'Enum#void,above,below,hsides,lhs,rhs,vsides,box,border', - 'rules' => 'Enum#none,groups,rows,cols,all', - 'summary' => 'Text', - 'width' => 'Length' - ) - ); - - // common attributes - $cell_align = array( - 'align' => 'Enum#left,center,right,justify,char', - 'charoff' => 'Length', - 'valign' => 'Enum#top,middle,bottom,baseline', - ); - - $cell_t = array_merge( - array( - 'abbr' => 'Text', - 'colspan' => 'Number', - 'rowspan' => 'Number', - ), - $cell_align - ); - $this->addElement('td', false, 'Flow', 'Common', $cell_t); - $this->addElement('th', false, 'Flow', 'Common', $cell_t); - - $this->addElement('tr', false, 'Required: td | th', 'Common', $cell_align); - - $cell_col = array_merge( - array( - 'span' => 'Number', - 'width' => 'MultiLength', - ), - $cell_align - ); - $this->addElement('col', false, 'Empty', 'Common', $cell_col); - $this->addElement('colgroup', false, 'Optional: col', 'Common', $cell_col); - - $this->addElement('tbody', false, 'Required: tr', 'Common', $cell_align); - $this->addElement('thead', false, 'Required: tr', 'Common', $cell_align); - $this->addElement('tfoot', false, 'Required: tr', 'Common', $cell_align); - - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Target.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Target.php deleted file mode 100644 index 58fa3fae..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Target.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * XHTML 1.1 Target Module, defines target attribute in link elements. - */ -class HTMLPurifier_HTMLModule_Target extends HTMLPurifier_HTMLModule -{ - - public $name = 'Target'; - - public function setup($config) { - $elements = array('a'); - foreach ($elements as $name) { - $e = $this->addBlankElement($name); - $e->attr = array( - 'target' => new HTMLPurifier_AttrDef_HTML_FrameTarget() - ); - } - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Text.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Text.php deleted file mode 100644 index 768d3f91..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Text.php +++ /dev/null @@ -1,71 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * XHTML 1.1 Text Module, defines basic text containers. Core Module. - * @note In the normative XML Schema specification, this module - * is further abstracted into the following modules: - * - Block Phrasal (address, blockquote, pre, h1, h2, h3, h4, h5, h6) - * - Block Structural (div, p) - * - Inline Phrasal (abbr, acronym, cite, code, dfn, em, kbd, q, samp, strong, var) - * - Inline Structural (br, span) - * This module, functionally, does not distinguish between these - * sub-modules, but the code is internally structured to reflect - * these distinctions. - */ -class HTMLPurifier_HTMLModule_Text extends HTMLPurifier_HTMLModule -{ - - public $name = 'Text'; - public $content_sets = array( - 'Flow' => 'Heading | Block | Inline' - ); - - public function setup($config) { - - // Inline Phrasal ------------------------------------------------- - $this->addElement('abbr', 'Inline', 'Inline', 'Common'); - $this->addElement('acronym', 'Inline', 'Inline', 'Common'); - $this->addElement('cite', 'Inline', 'Inline', 'Common'); - $this->addElement('dfn', 'Inline', 'Inline', 'Common'); - $this->addElement('kbd', 'Inline', 'Inline', 'Common'); - $this->addElement('q', 'Inline', 'Inline', 'Common', array('cite' => 'URI')); - $this->addElement('samp', 'Inline', 'Inline', 'Common'); - $this->addElement('var', 'Inline', 'Inline', 'Common'); - - $em = $this->addElement('em', 'Inline', 'Inline', 'Common'); - $em->formatting = true; - - $strong = $this->addElement('strong', 'Inline', 'Inline', 'Common'); - $strong->formatting = true; - - $code = $this->addElement('code', 'Inline', 'Inline', 'Common'); - $code->formatting = true; - - // Inline Structural ---------------------------------------------- - $this->addElement('span', 'Inline', 'Inline', 'Common'); - $this->addElement('br', 'Inline', 'Empty', 'Core'); - - // Block Phrasal -------------------------------------------------- - $this->addElement('address', 'Block', 'Inline', 'Common'); - $this->addElement('blockquote', 'Block', 'Optional: Heading | Block | List', 'Common', array('cite' => 'URI') ); - $pre = $this->addElement('pre', 'Block', 'Inline', 'Common'); - $pre->excludes = $this->makeLookup( - 'img', 'big', 'small', 'object', 'applet', 'font', 'basefont' ); - $this->addElement('h1', 'Heading', 'Inline', 'Common'); - $this->addElement('h2', 'Heading', 'Inline', 'Common'); - $this->addElement('h3', 'Heading', 'Inline', 'Common'); - $this->addElement('h4', 'Heading', 'Inline', 'Common'); - $this->addElement('h5', 'Heading', 'Inline', 'Common'); - $this->addElement('h6', 'Heading', 'Inline', 'Common'); - - // Block Structural ----------------------------------------------- - $p = $this->addElement('p', 'Block', 'Inline', 'Common'); - $p->autoclose = array_flip(array("address", "blockquote", "center", "dir", "div", "dl", "fieldset", "ol", "p", "ul")); - - $this->addElement('div', 'Block', 'Flow', 'Common'); - - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Tidy.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Tidy.php deleted file mode 100644 index b39823aa..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Tidy.php +++ /dev/null @@ -1,207 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Abstract class for a set of proprietary modules that clean up (tidy) - * poorly written HTML. - * @todo Figure out how to protect some of these methods/properties - */ -class HTMLPurifier_HTMLModule_Tidy extends HTMLPurifier_HTMLModule -{ - - /** - * List of supported levels. Index zero is a special case "no fixes" - * level. - */ - public $levels = array(0 => 'none', 'light', 'medium', 'heavy'); - - /** - * Default level to place all fixes in. Disabled by default - */ - public $defaultLevel = null; - - /** - * Lists of fixes used by getFixesForLevel(). Format is: - * HTMLModule_Tidy->fixesForLevel[$level] = array('fix-1', 'fix-2'); - */ - public $fixesForLevel = array( - 'light' => array(), - 'medium' => array(), - 'heavy' => array() - ); - - /** - * Lazy load constructs the module by determining the necessary - * fixes to create and then delegating to the populate() function. - * @todo Wildcard matching and error reporting when an added or - * subtracted fix has no effect. - */ - public function setup($config) { - - // create fixes, initialize fixesForLevel - $fixes = $this->makeFixes(); - $this->makeFixesForLevel($fixes); - - // figure out which fixes to use - $level = $config->get('HTML.TidyLevel'); - $fixes_lookup = $this->getFixesForLevel($level); - - // get custom fix declarations: these need namespace processing - $add_fixes = $config->get('HTML.TidyAdd'); - $remove_fixes = $config->get('HTML.TidyRemove'); - - foreach ($fixes as $name => $fix) { - // needs to be refactored a little to implement globbing - if ( - isset($remove_fixes[$name]) || - (!isset($add_fixes[$name]) && !isset($fixes_lookup[$name])) - ) { - unset($fixes[$name]); - } - } - - // populate this module with necessary fixes - $this->populate($fixes); - - } - - /** - * Retrieves all fixes per a level, returning fixes for that specific - * level as well as all levels below it. - * @param $level String level identifier, see $levels for valid values - * @return Lookup up table of fixes - */ - public function getFixesForLevel($level) { - if ($level == $this->levels[0]) { - return array(); - } - $activated_levels = array(); - for ($i = 1, $c = count($this->levels); $i < $c; $i++) { - $activated_levels[] = $this->levels[$i]; - if ($this->levels[$i] == $level) break; - } - if ($i == $c) { - trigger_error( - 'Tidy level ' . htmlspecialchars($level) . ' not recognized', - E_USER_WARNING - ); - return array(); - } - $ret = array(); - foreach ($activated_levels as $level) { - foreach ($this->fixesForLevel[$level] as $fix) { - $ret[$fix] = true; - } - } - return $ret; - } - - /** - * Dynamically populates the $fixesForLevel member variable using - * the fixes array. It may be custom overloaded, used in conjunction - * with $defaultLevel, or not used at all. - */ - public function makeFixesForLevel($fixes) { - if (!isset($this->defaultLevel)) return; - if (!isset($this->fixesForLevel[$this->defaultLevel])) { - trigger_error( - 'Default level ' . $this->defaultLevel . ' does not exist', - E_USER_ERROR - ); - return; - } - $this->fixesForLevel[$this->defaultLevel] = array_keys($fixes); - } - - /** - * Populates the module with transforms and other special-case code - * based on a list of fixes passed to it - * @param $lookup Lookup table of fixes to activate - */ - public function populate($fixes) { - foreach ($fixes as $name => $fix) { - // determine what the fix is for - list($type, $params) = $this->getFixType($name); - switch ($type) { - case 'attr_transform_pre': - case 'attr_transform_post': - $attr = $params['attr']; - if (isset($params['element'])) { - $element = $params['element']; - if (empty($this->info[$element])) { - $e = $this->addBlankElement($element); - } else { - $e = $this->info[$element]; - } - } else { - $type = "info_$type"; - $e = $this; - } - // PHP does some weird parsing when I do - // $e->$type[$attr], so I have to assign a ref. - $f =& $e->$type; - $f[$attr] = $fix; - break; - case 'tag_transform': - $this->info_tag_transform[$params['element']] = $fix; - break; - case 'child': - case 'content_model_type': - $element = $params['element']; - if (empty($this->info[$element])) { - $e = $this->addBlankElement($element); - } else { - $e = $this->info[$element]; - } - $e->$type = $fix; - break; - default: - trigger_error("Fix type $type not supported", E_USER_ERROR); - break; - } - } - } - - /** - * Parses a fix name and determines what kind of fix it is, as well - * as other information defined by the fix - * @param $name String name of fix - * @return array(string $fix_type, array $fix_parameters) - * @note $fix_parameters is type dependant, see populate() for usage - * of these parameters - */ - public function getFixType($name) { - // parse it - $property = $attr = null; - if (strpos($name, '#') !== false) list($name, $property) = explode('#', $name); - if (strpos($name, '@') !== false) list($name, $attr) = explode('@', $name); - - // figure out the parameters - $params = array(); - if ($name !== '') $params['element'] = $name; - if (!is_null($attr)) $params['attr'] = $attr; - - // special case: attribute transform - if (!is_null($attr)) { - if (is_null($property)) $property = 'pre'; - $type = 'attr_transform_' . $property; - return array($type, $params); - } - - // special case: tag transform - if (is_null($property)) { - return array('tag_transform', $params); - } - - return array($property, $params); - - } - - /** - * Defines all fixes the module will perform in a compact - * associative array of fix name to fix implementation. - */ - public function makeFixes() {} - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Tidy/Name.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Tidy/Name.php deleted file mode 100644 index d537bf2b..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Tidy/Name.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Name is deprecated, but allowed in strict doctypes, so onl - */ -class HTMLPurifier_HTMLModule_Tidy_Name extends HTMLPurifier_HTMLModule_Tidy -{ - public $name = 'Tidy_Name'; - public $defaultLevel = 'heavy'; - public function makeFixes() { - - $r = array(); - - // @name for img, a ----------------------------------------------- - // Technically, it's allowed even on strict, so we allow authors to use - // it. However, it's deprecated in future versions of XHTML. - $r['img@name'] = - $r['a@name'] = new HTMLPurifier_AttrTransform_Name(); - - return $r; - } -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Tidy/Proprietary.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Tidy/Proprietary.php deleted file mode 100644 index f6aa6b03..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Tidy/Proprietary.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -class HTMLPurifier_HTMLModule_Tidy_Proprietary extends HTMLPurifier_HTMLModule_Tidy -{ - - public $name = 'Tidy_Proprietary'; - public $defaultLevel = 'light'; - - public function makeFixes() { - $r = array(); - $r['table@background'] = new HTMLPurifier_AttrTransform_Background(); - $r['td@background'] = new HTMLPurifier_AttrTransform_Background(); - $r['th@background'] = new HTMLPurifier_AttrTransform_Background(); - $r['tr@background'] = new HTMLPurifier_AttrTransform_Background(); - $r['thead@background'] = new HTMLPurifier_AttrTransform_Background(); - $r['tfoot@background'] = new HTMLPurifier_AttrTransform_Background(); - $r['tbody@background'] = new HTMLPurifier_AttrTransform_Background(); - return $r; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Tidy/Strict.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Tidy/Strict.php deleted file mode 100644 index ed11d406..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Tidy/Strict.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -class HTMLPurifier_HTMLModule_Tidy_Strict extends HTMLPurifier_HTMLModule_Tidy_XHTMLAndHTML4 -{ - public $name = 'Tidy_Strict'; - public $defaultLevel = 'light'; - - public function makeFixes() { - $r = parent::makeFixes(); - $r['blockquote#content_model_type'] = 'strictblockquote'; - return $r; - } - - public $defines_child_def = true; - public function getChildDef($def) { - if ($def->content_model_type != 'strictblockquote') return parent::getChildDef($def); - return new HTMLPurifier_ChildDef_StrictBlockquote($def->content_model); - } -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Tidy/Transitional.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Tidy/Transitional.php deleted file mode 100644 index a9d3a571..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Tidy/Transitional.php +++ /dev/null @@ -1,9 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -class HTMLPurifier_HTMLModule_Tidy_Transitional extends HTMLPurifier_HTMLModule_Tidy_XHTMLAndHTML4 -{ - public $name = 'Tidy_Transitional'; - public $defaultLevel = 'heavy'; -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Tidy/XHTML.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Tidy/XHTML.php deleted file mode 100644 index a48fdcc9..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Tidy/XHTML.php +++ /dev/null @@ -1,17 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -class HTMLPurifier_HTMLModule_Tidy_XHTML extends HTMLPurifier_HTMLModule_Tidy -{ - - public $name = 'Tidy_XHTML'; - public $defaultLevel = 'medium'; - - public function makeFixes() { - $r = array(); - $r['@lang'] = new HTMLPurifier_AttrTransform_Lang(); - return $r; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Tidy/XHTMLAndHTML4.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Tidy/XHTMLAndHTML4.php deleted file mode 100644 index 65d57a95..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/Tidy/XHTMLAndHTML4.php +++ /dev/null @@ -1,161 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -class HTMLPurifier_HTMLModule_Tidy_XHTMLAndHTML4 extends HTMLPurifier_HTMLModule_Tidy -{ - - public function makeFixes() { - - $r = array(); - - // == deprecated tag transforms =================================== - - $r['font'] = new HTMLPurifier_TagTransform_Font(); - $r['menu'] = new HTMLPurifier_TagTransform_Simple('ul'); - $r['dir'] = new HTMLPurifier_TagTransform_Simple('ul'); - $r['center'] = new HTMLPurifier_TagTransform_Simple('div', 'text-align:center;'); - $r['u'] = new HTMLPurifier_TagTransform_Simple('span', 'text-decoration:underline;'); - $r['s'] = new HTMLPurifier_TagTransform_Simple('span', 'text-decoration:line-through;'); - $r['strike'] = new HTMLPurifier_TagTransform_Simple('span', 'text-decoration:line-through;'); - - // == deprecated attribute transforms ============================= - - $r['caption@align'] = - new HTMLPurifier_AttrTransform_EnumToCSS('align', array( - // we're following IE's behavior, not Firefox's, due - // to the fact that no one supports caption-side:right, - // W3C included (with CSS 2.1). This is a slightly - // unreasonable attribute! - 'left' => 'text-align:left;', - 'right' => 'text-align:right;', - 'top' => 'caption-side:top;', - 'bottom' => 'caption-side:bottom;' // not supported by IE - )); - - // @align for img ------------------------------------------------- - $r['img@align'] = - new HTMLPurifier_AttrTransform_EnumToCSS('align', array( - 'left' => 'float:left;', - 'right' => 'float:right;', - 'top' => 'vertical-align:top;', - 'middle' => 'vertical-align:middle;', - 'bottom' => 'vertical-align:baseline;', - )); - - // @align for table ----------------------------------------------- - $r['table@align'] = - new HTMLPurifier_AttrTransform_EnumToCSS('align', array( - 'left' => 'float:left;', - 'center' => 'margin-left:auto;margin-right:auto;', - 'right' => 'float:right;' - )); - - // @align for hr ----------------------------------------------- - $r['hr@align'] = - new HTMLPurifier_AttrTransform_EnumToCSS('align', array( - // we use both text-align and margin because these work - // for different browsers (IE and Firefox, respectively) - // and the melange makes for a pretty cross-compatible - // solution - 'left' => 'margin-left:0;margin-right:auto;text-align:left;', - 'center' => 'margin-left:auto;margin-right:auto;text-align:center;', - 'right' => 'margin-left:auto;margin-right:0;text-align:right;' - )); - - // @align for h1, h2, h3, h4, h5, h6, p, div ---------------------- - // {{{ - $align_lookup = array(); - $align_values = array('left', 'right', 'center', 'justify'); - foreach ($align_values as $v) $align_lookup[$v] = "text-align:$v;"; - // }}} - $r['h1@align'] = - $r['h2@align'] = - $r['h3@align'] = - $r['h4@align'] = - $r['h5@align'] = - $r['h6@align'] = - $r['p@align'] = - $r['div@align'] = - new HTMLPurifier_AttrTransform_EnumToCSS('align', $align_lookup); - - // @bgcolor for table, tr, td, th --------------------------------- - $r['table@bgcolor'] = - $r['td@bgcolor'] = - $r['th@bgcolor'] = - new HTMLPurifier_AttrTransform_BgColor(); - - // @border for img ------------------------------------------------ - $r['img@border'] = new HTMLPurifier_AttrTransform_Border(); - - // @clear for br -------------------------------------------------- - $r['br@clear'] = - new HTMLPurifier_AttrTransform_EnumToCSS('clear', array( - 'left' => 'clear:left;', - 'right' => 'clear:right;', - 'all' => 'clear:both;', - 'none' => 'clear:none;', - )); - - // @height for td, th --------------------------------------------- - $r['td@height'] = - $r['th@height'] = - new HTMLPurifier_AttrTransform_Length('height'); - - // @hspace for img ------------------------------------------------ - $r['img@hspace'] = new HTMLPurifier_AttrTransform_ImgSpace('hspace'); - - // @noshade for hr ------------------------------------------------ - // this transformation is not precise but often good enough. - // different browsers use different styles to designate noshade - $r['hr@noshade'] = - new HTMLPurifier_AttrTransform_BoolToCSS( - 'noshade', - 'color:#808080;background-color:#808080;border:0;' - ); - - // @nowrap for td, th --------------------------------------------- - $r['td@nowrap'] = - $r['th@nowrap'] = - new HTMLPurifier_AttrTransform_BoolToCSS( - 'nowrap', - 'white-space:nowrap;' - ); - - // @size for hr -------------------------------------------------- - $r['hr@size'] = new HTMLPurifier_AttrTransform_Length('size', 'height'); - - // @type for li, ol, ul ------------------------------------------- - // {{{ - $ul_types = array( - 'disc' => 'list-style-type:disc;', - 'square' => 'list-style-type:square;', - 'circle' => 'list-style-type:circle;' - ); - $ol_types = array( - '1' => 'list-style-type:decimal;', - 'i' => 'list-style-type:lower-roman;', - 'I' => 'list-style-type:upper-roman;', - 'a' => 'list-style-type:lower-alpha;', - 'A' => 'list-style-type:upper-alpha;' - ); - $li_types = $ul_types + $ol_types; - // }}} - - $r['ul@type'] = new HTMLPurifier_AttrTransform_EnumToCSS('type', $ul_types); - $r['ol@type'] = new HTMLPurifier_AttrTransform_EnumToCSS('type', $ol_types, true); - $r['li@type'] = new HTMLPurifier_AttrTransform_EnumToCSS('type', $li_types, true); - - // @vspace for img ------------------------------------------------ - $r['img@vspace'] = new HTMLPurifier_AttrTransform_ImgSpace('vspace'); - - // @width for hr, td, th ------------------------------------------ - $r['td@width'] = - $r['th@width'] = - $r['hr@width'] = new HTMLPurifier_AttrTransform_Length('width'); - - return $r; - - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/XMLCommonAttributes.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/XMLCommonAttributes.php deleted file mode 100644 index abe458e8..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModule/XMLCommonAttributes.php +++ /dev/null @@ -1,14 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -class HTMLPurifier_HTMLModule_XMLCommonAttributes extends HTMLPurifier_HTMLModule -{ - public $name = 'XMLCommonAttributes'; - - public $attr_collections = array( - 'Lang' => array( - 'xml:lang' => 'LanguageCode', - ) - ); -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModuleManager.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModuleManager.php deleted file mode 100644 index fbf477fe..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/HTMLModuleManager.php +++ /dev/null @@ -1,403 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -class HTMLPurifier_HTMLModuleManager -{ - - /** - * Instance of HTMLPurifier_DoctypeRegistry - */ - public $doctypes; - - /** - * Instance of current doctype - */ - public $doctype; - - /** - * Instance of HTMLPurifier_AttrTypes - */ - public $attrTypes; - - /** - * Active instances of modules for the specified doctype are - * indexed, by name, in this array. - */ - public $modules = array(); - - /** - * Array of recognized HTMLPurifier_Module instances, indexed by - * module's class name. This array is usually lazy loaded, but a - * user can overload a module by pre-emptively registering it. - */ - public $registeredModules = array(); - - /** - * List of extra modules that were added by the user using addModule(). - * These get unconditionally merged into the current doctype, whatever - * it may be. - */ - public $userModules = array(); - - /** - * Associative array of element name to list of modules that have - * definitions for the element; this array is dynamically filled. - */ - public $elementLookup = array(); - - /** List of prefixes we should use for registering small names */ - public $prefixes = array('HTMLPurifier_HTMLModule_'); - - public $contentSets; /**< Instance of HTMLPurifier_ContentSets */ - public $attrCollections; /**< Instance of HTMLPurifier_AttrCollections */ - - /** If set to true, unsafe elements and attributes will be allowed */ - public $trusted = false; - - public function __construct() { - - // editable internal objects - $this->attrTypes = new HTMLPurifier_AttrTypes(); - $this->doctypes = new HTMLPurifier_DoctypeRegistry(); - - // setup basic modules - $common = array( - 'CommonAttributes', 'Text', 'Hypertext', 'List', - 'Presentation', 'Edit', 'Bdo', 'Tables', 'Image', - 'StyleAttribute', - // Unsafe: - 'Scripting', 'Object', 'Forms', - // Sorta legacy, but present in strict: - 'Name', - ); - $transitional = array('Legacy', 'Target'); - $xml = array('XMLCommonAttributes'); - $non_xml = array('NonXMLCommonAttributes'); - - // setup basic doctypes - $this->doctypes->register( - 'HTML 4.01 Transitional', false, - array_merge($common, $transitional, $non_xml), - array('Tidy_Transitional', 'Tidy_Proprietary'), - array(), - '-//W3C//DTD HTML 4.01 Transitional//EN', - 'http://www.w3.org/TR/html4/loose.dtd' - ); - - $this->doctypes->register( - 'HTML 4.01 Strict', false, - array_merge($common, $non_xml), - array('Tidy_Strict', 'Tidy_Proprietary', 'Tidy_Name'), - array(), - '-//W3C//DTD HTML 4.01//EN', - 'http://www.w3.org/TR/html4/strict.dtd' - ); - - $this->doctypes->register( - 'XHTML 1.0 Transitional', true, - array_merge($common, $transitional, $xml, $non_xml), - array('Tidy_Transitional', 'Tidy_XHTML', 'Tidy_Proprietary', 'Tidy_Name'), - array(), - '-//W3C//DTD XHTML 1.0 Transitional//EN', - 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd' - ); - - $this->doctypes->register( - 'XHTML 1.0 Strict', true, - array_merge($common, $xml, $non_xml), - array('Tidy_Strict', 'Tidy_XHTML', 'Tidy_Strict', 'Tidy_Proprietary', 'Tidy_Name'), - array(), - '-//W3C//DTD XHTML 1.0 Strict//EN', - 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd' - ); - - $this->doctypes->register( - 'XHTML 1.1', true, - array_merge($common, $xml, array('Ruby')), - array('Tidy_Strict', 'Tidy_XHTML', 'Tidy_Proprietary', 'Tidy_Strict', 'Tidy_Name'), // Tidy_XHTML1_1 - array(), - '-//W3C//DTD XHTML 1.1//EN', - 'http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd' - ); - - } - - /** - * Registers a module to the recognized module list, useful for - * overloading pre-existing modules. - * @param $module Mixed: string module name, with or without - * HTMLPurifier_HTMLModule prefix, or instance of - * subclass of HTMLPurifier_HTMLModule. - * @param $overload Boolean whether or not to overload previous modules. - * If this is not set, and you do overload a module, - * HTML Purifier will complain with a warning. - * @note This function will not call autoload, you must instantiate - * (and thus invoke) autoload outside the method. - * @note If a string is passed as a module name, different variants - * will be tested in this order: - * - Check for HTMLPurifier_HTMLModule_$name - * - Check all prefixes with $name in order they were added - * - Check for literal object name - * - Throw fatal error - * If your object name collides with an internal class, specify - * your module manually. All modules must have been included - * externally: registerModule will not perform inclusions for you! - */ - public function registerModule($module, $overload = false) { - if (is_string($module)) { - // attempt to load the module - $original_module = $module; - $ok = false; - foreach ($this->prefixes as $prefix) { - $module = $prefix . $original_module; - if (class_exists($module)) { - $ok = true; - break; - } - } - if (!$ok) { - $module = $original_module; - if (!class_exists($module)) { - trigger_error($original_module . ' module does not exist', - E_USER_ERROR); - return; - } - } - $module = new $module(); - } - if (empty($module->name)) { - trigger_error('Module instance of ' . get_class($module) . ' must have name'); - return; - } - if (!$overload && isset($this->registeredModules[$module->name])) { - trigger_error('Overloading ' . $module->name . ' without explicit overload parameter', E_USER_WARNING); - } - $this->registeredModules[$module->name] = $module; - } - - /** - * Adds a module to the current doctype by first registering it, - * and then tacking it on to the active doctype - */ - public function addModule($module) { - $this->registerModule($module); - if (is_object($module)) $module = $module->name; - $this->userModules[] = $module; - } - - /** - * Adds a class prefix that registerModule() will use to resolve a - * string name to a concrete class - */ - public function addPrefix($prefix) { - $this->prefixes[] = $prefix; - } - - /** - * Performs processing on modules, after being called you may - * use getElement() and getElements() - * @param $config Instance of HTMLPurifier_Config - */ - public function setup($config) { - - $this->trusted = $config->get('HTML.Trusted'); - - // generate - $this->doctype = $this->doctypes->make($config); - $modules = $this->doctype->modules; - - // take out the default modules that aren't allowed - $lookup = $config->get('HTML.AllowedModules'); - $special_cases = $config->get('HTML.CoreModules'); - - if (is_array($lookup)) { - foreach ($modules as $k => $m) { - if (isset($special_cases[$m])) continue; - if (!isset($lookup[$m])) unset($modules[$k]); - } - } - - // add proprietary module (this gets special treatment because - // it is completely removed from doctypes, etc.) - if ($config->get('HTML.Proprietary')) { - $modules[] = 'Proprietary'; - } - - // add SafeObject/Safeembed modules - if ($config->get('HTML.SafeObject')) { - $modules[] = 'SafeObject'; - } - if ($config->get('HTML.SafeEmbed')) { - $modules[] = 'SafeEmbed'; - } - - // merge in custom modules - $modules = array_merge($modules, $this->userModules); - - foreach ($modules as $module) { - $this->processModule($module); - $this->modules[$module]->setup($config); - } - - foreach ($this->doctype->tidyModules as $module) { - $this->processModule($module); - $this->modules[$module]->setup($config); - } - - // prepare any injectors - foreach ($this->modules as $module) { - $n = array(); - foreach ($module->info_injector as $i => $injector) { - if (!is_object($injector)) { - $class = "HTMLPurifier_Injector_$injector"; - $injector = new $class; - } - $n[$injector->name] = $injector; - } - $module->info_injector = $n; - } - - // setup lookup table based on all valid modules - foreach ($this->modules as $module) { - foreach ($module->info as $name => $def) { - if (!isset($this->elementLookup[$name])) { - $this->elementLookup[$name] = array(); - } - $this->elementLookup[$name][] = $module->name; - } - } - - // note the different choice - $this->contentSets = new HTMLPurifier_ContentSets( - // content set assembly deals with all possible modules, - // not just ones deemed to be "safe" - $this->modules - ); - $this->attrCollections = new HTMLPurifier_AttrCollections( - $this->attrTypes, - // there is no way to directly disable a global attribute, - // but using AllowedAttributes or simply not including - // the module in your custom doctype should be sufficient - $this->modules - ); - } - - /** - * Takes a module and adds it to the active module collection, - * registering it if necessary. - */ - public function processModule($module) { - if (!isset($this->registeredModules[$module]) || is_object($module)) { - $this->registerModule($module); - } - $this->modules[$module] = $this->registeredModules[$module]; - } - - /** - * Retrieves merged element definitions. - * @return Array of HTMLPurifier_ElementDef - */ - public function getElements() { - - $elements = array(); - foreach ($this->modules as $module) { - if (!$this->trusted && !$module->safe) continue; - foreach ($module->info as $name => $v) { - if (isset($elements[$name])) continue; - $elements[$name] = $this->getElement($name); - } - } - - // remove dud elements, this happens when an element that - // appeared to be safe actually wasn't - foreach ($elements as $n => $v) { - if ($v === false) unset($elements[$n]); - } - - return $elements; - - } - - /** - * Retrieves a single merged element definition - * @param $name Name of element - * @param $trusted Boolean trusted overriding parameter: set to true - * if you want the full version of an element - * @return Merged HTMLPurifier_ElementDef - * @note You may notice that modules are getting iterated over twice (once - * in getElements() and once here). This - * is because - */ - public function getElement($name, $trusted = null) { - - if (!isset($this->elementLookup[$name])) { - return false; - } - - // setup global state variables - $def = false; - if ($trusted === null) $trusted = $this->trusted; - - // iterate through each module that has registered itself to this - // element - foreach($this->elementLookup[$name] as $module_name) { - - $module = $this->modules[$module_name]; - - // refuse to create/merge from a module that is deemed unsafe-- - // pretend the module doesn't exist--when trusted mode is not on. - if (!$trusted && !$module->safe) { - continue; - } - - // clone is used because, ideally speaking, the original - // definition should not be modified. Usually, this will - // make no difference, but for consistency's sake - $new_def = clone $module->info[$name]; - - if (!$def && $new_def->standalone) { - $def = $new_def; - } elseif ($def) { - // This will occur even if $new_def is standalone. In practice, - // this will usually result in a full replacement. - $def->mergeIn($new_def); - } else { - // :TODO: - // non-standalone definitions that don't have a standalone - // to merge into could be deferred to the end - continue; - } - - // attribute value expansions - $this->attrCollections->performInclusions($def->attr); - $this->attrCollections->expandIdentifiers($def->attr, $this->attrTypes); - - // descendants_are_inline, for ChildDef_Chameleon - if (is_string($def->content_model) && - strpos($def->content_model, 'Inline') !== false) { - if ($name != 'del' && $name != 'ins') { - // this is for you, ins/del - $def->descendants_are_inline = true; - } - } - - $this->contentSets->generateChildDef($def, $module); - } - - // This can occur if there is a blank definition, but no base to - // mix it in with - if (!$def) return false; - - // add information on required attributes - foreach ($def->attr as $attr_name => $attr_def) { - if ($attr_def->required) { - $def->required_attr[] = $attr_name; - } - } - - return $def; - - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/IDAccumulator.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/IDAccumulator.php deleted file mode 100644 index ea454e82..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/IDAccumulator.php +++ /dev/null @@ -1,53 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Component of HTMLPurifier_AttrContext that accumulates IDs to prevent dupes - * @note In Slashdot-speak, dupe means duplicate. - * @note The default constructor does not accept $config or $context objects: - * use must use the static build() factory method to perform initialization. - */ -class HTMLPurifier_IDAccumulator -{ - - /** - * Lookup table of IDs we've accumulated. - * @public - */ - public $ids = array(); - - /** - * Builds an IDAccumulator, also initializing the default blacklist - * @param $config Instance of HTMLPurifier_Config - * @param $context Instance of HTMLPurifier_Context - * @return Fully initialized HTMLPurifier_IDAccumulator - */ - public static function build($config, $context) { - $id_accumulator = new HTMLPurifier_IDAccumulator(); - $id_accumulator->load($config->get('Attr.IDBlacklist')); - return $id_accumulator; - } - - /** - * Add an ID to the lookup table. - * @param $id ID to be added. - * @return Bool status, true if success, false if there's a dupe - */ - public function add($id) { - if (isset($this->ids[$id])) return false; - return $this->ids[$id] = true; - } - - /** - * Load a list of IDs into the lookup table - * @param $array_of_ids Array of IDs to load - * @note This function doesn't care about duplicates - */ - public function load($array_of_ids) { - foreach ($array_of_ids as $id) { - $this->ids[$id] = true; - } - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Injector.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Injector.php deleted file mode 100644 index 3e1f5875..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Injector.php +++ /dev/null @@ -1,239 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Injects tokens into the document while parsing for well-formedness. - * This enables "formatter-like" functionality such as auto-paragraphing, - * smiley-ification and linkification to take place. - * - * A note on how handlers create changes; this is done by assigning a new - * value to the $token reference. These values can take a variety of forms and - * are best described HTMLPurifier_Strategy_MakeWellFormed->processToken() - * documentation. - * - * @todo Allow injectors to request a re-run on their output. This - * would help if an operation is recursive. - */ -abstract class HTMLPurifier_Injector -{ - - /** - * Advisory name of injector, this is for friendly error messages - */ - public $name; - - /** - * Instance of HTMLPurifier_HTMLDefinition - */ - protected $htmlDefinition; - - /** - * Reference to CurrentNesting variable in Context. This is an array - * list of tokens that we are currently "inside" - */ - protected $currentNesting; - - /** - * Reference to InputTokens variable in Context. This is an array - * list of the input tokens that are being processed. - */ - protected $inputTokens; - - /** - * Reference to InputIndex variable in Context. This is an integer - * array index for $this->inputTokens that indicates what token - * is currently being processed. - */ - protected $inputIndex; - - /** - * Array of elements and attributes this injector creates and therefore - * need to be allowed by the definition. Takes form of - * array('element' => array('attr', 'attr2'), 'element2') - */ - public $needed = array(); - - /** - * Index of inputTokens to rewind to. - */ - protected $rewind = false; - - /** - * Rewind to a spot to re-perform processing. This is useful if you - * deleted a node, and now need to see if this change affected any - * earlier nodes. Rewinding does not affect other injectors, and can - * result in infinite loops if not used carefully. - * @warning HTML Purifier will prevent you from fast-forwarding with this - * function. - */ - public function rewind($index) { - $this->rewind = $index; - } - - /** - * Retrieves rewind, and then unsets it. - */ - public function getRewind() { - $r = $this->rewind; - $this->rewind = false; - return $r; - } - - /** - * Prepares the injector by giving it the config and context objects: - * this allows references to important variables to be made within - * the injector. This function also checks if the HTML environment - * will work with the Injector (see checkNeeded()). - * @param $config Instance of HTMLPurifier_Config - * @param $context Instance of HTMLPurifier_Context - * @return Boolean false if success, string of missing needed element/attribute if failure - */ - public function prepare($config, $context) { - $this->htmlDefinition = $config->getHTMLDefinition(); - // Even though this might fail, some unit tests ignore this and - // still test checkNeeded, so be careful. Maybe get rid of that - // dependency. - $result = $this->checkNeeded($config); - if ($result !== false) return $result; - $this->currentNesting =& $context->get('CurrentNesting'); - $this->inputTokens =& $context->get('InputTokens'); - $this->inputIndex =& $context->get('InputIndex'); - return false; - } - - /** - * This function checks if the HTML environment - * will work with the Injector: if p tags are not allowed, the - * Auto-Paragraphing injector should not be enabled. - * @param $config Instance of HTMLPurifier_Config - * @param $context Instance of HTMLPurifier_Context - * @return Boolean false if success, string of missing needed element/attribute if failure - */ - public function checkNeeded($config) { - $def = $config->getHTMLDefinition(); - foreach ($this->needed as $element => $attributes) { - if (is_int($element)) $element = $attributes; - if (!isset($def->info[$element])) return $element; - if (!is_array($attributes)) continue; - foreach ($attributes as $name) { - if (!isset($def->info[$element]->attr[$name])) return "$element.$name"; - } - } - return false; - } - - /** - * Tests if the context node allows a certain element - * @param $name Name of element to test for - * @return True if element is allowed, false if it is not - */ - public function allowsElement($name) { - if (!empty($this->currentNesting)) { - $parent_token = array_pop($this->currentNesting); - $this->currentNesting[] = $parent_token; - $parent = $this->htmlDefinition->info[$parent_token->name]; - } else { - $parent = $this->htmlDefinition->info_parent_def; - } - if (!isset($parent->child->elements[$name]) || isset($parent->excludes[$name])) { - return false; - } - // check for exclusion - for ($i = count($this->currentNesting) - 2; $i >= 0; $i--) { - $node = $this->currentNesting[$i]; - $def = $this->htmlDefinition->info[$node->name]; - if (isset($def->excludes[$name])) return false; - } - return true; - } - - /** - * Iterator function, which starts with the next token and continues until - * you reach the end of the input tokens. - * @warning Please prevent previous references from interfering with this - * functions by setting $i = null beforehand! - * @param &$i Current integer index variable for inputTokens - * @param &$current Current token variable. Do NOT use $token, as that variable is also a reference - */ - protected function forward(&$i, &$current) { - if ($i === null) $i = $this->inputIndex + 1; - else $i++; - if (!isset($this->inputTokens[$i])) return false; - $current = $this->inputTokens[$i]; - return true; - } - - /** - * Similar to _forward, but accepts a third parameter $nesting (which - * should be initialized at 0) and stops when we hit the end tag - * for the node $this->inputIndex starts in. - */ - protected function forwardUntilEndToken(&$i, &$current, &$nesting) { - $result = $this->forward($i, $current); - if (!$result) return false; - if ($nesting === null) $nesting = 0; - if ($current instanceof HTMLPurifier_Token_Start) $nesting++; - elseif ($current instanceof HTMLPurifier_Token_End) { - if ($nesting <= 0) return false; - $nesting--; - } - return true; - } - - /** - * Iterator function, starts with the previous token and continues until - * you reach the beginning of input tokens. - * @warning Please prevent previous references from interfering with this - * functions by setting $i = null beforehand! - * @param &$i Current integer index variable for inputTokens - * @param &$current Current token variable. Do NOT use $token, as that variable is also a reference - */ - protected function backward(&$i, &$current) { - if ($i === null) $i = $this->inputIndex - 1; - else $i--; - if ($i < 0) return false; - $current = $this->inputTokens[$i]; - return true; - } - - /** - * Initializes the iterator at the current position. Use in a do {} while; - * loop to force the _forward and _backward functions to start at the - * current location. - * @warning Please prevent previous references from interfering with this - * functions by setting $i = null beforehand! - * @param &$i Current integer index variable for inputTokens - * @param &$current Current token variable. Do NOT use $token, as that variable is also a reference - */ - protected function current(&$i, &$current) { - if ($i === null) $i = $this->inputIndex; - $current = $this->inputTokens[$i]; - } - - /** - * Handler that is called when a text token is processed - */ - public function handleText(&$token) {} - - /** - * Handler that is called when a start or empty token is processed - */ - public function handleElement(&$token) {} - - /** - * Handler that is called when an end token is processed - */ - public function handleEnd(&$token) { - $this->notifyEnd($token); - } - - /** - * Notifier that is called when an end token is processed - * @note This differs from handlers in that the token is read-only - * @deprecated - */ - public function notifyEnd($token) {} - - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Injector/AutoParagraph.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Injector/AutoParagraph.php deleted file mode 100644 index c5444dbe..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Injector/AutoParagraph.php +++ /dev/null @@ -1,340 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Injector that auto paragraphs text in the root node based on - * double-spacing. - * @todo Ensure all states are unit tested, including variations as well. - * @todo Make a graph of the flow control for this Injector. - */ -class HTMLPurifier_Injector_AutoParagraph extends HTMLPurifier_Injector -{ - - public $name = 'AutoParagraph'; - public $needed = array('p'); - - private function _pStart() { - $par = new HTMLPurifier_Token_Start('p'); - $par->armor['MakeWellFormed_TagClosedError'] = true; - return $par; - } - - public function handleText(&$token) { - $text = $token->data; - // Does the current parent allow <p> tags? - if ($this->allowsElement('p')) { - if (empty($this->currentNesting) || strpos($text, "\n\n") !== false) { - // Note that we have differing behavior when dealing with text - // in the anonymous root node, or a node inside the document. - // If the text as a double-newline, the treatment is the same; - // if it doesn't, see the next if-block if you're in the document. - - $i = $nesting = null; - if (!$this->forwardUntilEndToken($i, $current, $nesting) && $token->is_whitespace) { - // State 1.1: ... ^ (whitespace, then document end) - // ---- - // This is a degenerate case - } else { - // State 1.2: PAR1 - // ---- - - // State 1.3: PAR1\n\nPAR2 - // ------------ - - // State 1.4: <div>PAR1\n\nPAR2 (see State 2) - // ------------ - $token = array($this->_pStart()); - $this->_splitText($text, $token); - } - } else { - // State 2: <div>PAR1... (similar to 1.4) - // ---- - - // We're in an element that allows paragraph tags, but we're not - // sure if we're going to need them. - if ($this->_pLookAhead()) { - // State 2.1: <div>PAR1<b>PAR1\n\nPAR2 - // ---- - // Note: This will always be the first child, since any - // previous inline element would have triggered this very - // same routine, and found the double newline. One possible - // exception would be a comment. - $token = array($this->_pStart(), $token); - } else { - // State 2.2.1: <div>PAR1<div> - // ---- - - // State 2.2.2: <div>PAR1<b>PAR1</b></div> - // ---- - } - } - // Is the current parent a <p> tag? - } elseif ( - !empty($this->currentNesting) && - $this->currentNesting[count($this->currentNesting)-1]->name == 'p' - ) { - // State 3.1: ...<p>PAR1 - // ---- - - // State 3.2: ...<p>PAR1\n\nPAR2 - // ------------ - $token = array(); - $this->_splitText($text, $token); - // Abort! - } else { - // State 4.1: ...<b>PAR1 - // ---- - - // State 4.2: ...<b>PAR1\n\nPAR2 - // ------------ - } - } - - public function handleElement(&$token) { - // We don't have to check if we're already in a <p> tag for block - // tokens, because the tag would have been autoclosed by MakeWellFormed. - if ($this->allowsElement('p')) { - if (!empty($this->currentNesting)) { - if ($this->_isInline($token)) { - // State 1: <div>...<b> - // --- - - // Check if this token is adjacent to the parent token - // (seek backwards until token isn't whitespace) - $i = null; - $this->backward($i, $prev); - - if (!$prev instanceof HTMLPurifier_Token_Start) { - // Token wasn't adjacent - - if ( - $prev instanceof HTMLPurifier_Token_Text && - substr($prev->data, -2) === "\n\n" - ) { - // State 1.1.4: <div><p>PAR1</p>\n\n<b> - // --- - - // Quite frankly, this should be handled by splitText - $token = array($this->_pStart(), $token); - } else { - // State 1.1.1: <div><p>PAR1</p><b> - // --- - - // State 1.1.2: <div><br /><b> - // --- - - // State 1.1.3: <div>PAR<b> - // --- - } - - } else { - // State 1.2.1: <div><b> - // --- - - // Lookahead to see if <p> is needed. - if ($this->_pLookAhead()) { - // State 1.3.1: <div><b>PAR1\n\nPAR2 - // --- - $token = array($this->_pStart(), $token); - } else { - // State 1.3.2: <div><b>PAR1</b></div> - // --- - - // State 1.3.3: <div><b>PAR1</b><div></div>\n\n</div> - // --- - } - } - } else { - // State 2.3: ...<div> - // ----- - } - } else { - if ($this->_isInline($token)) { - // State 3.1: <b> - // --- - // This is where the {p} tag is inserted, not reflected in - // inputTokens yet, however. - $token = array($this->_pStart(), $token); - } else { - // State 3.2: <div> - // ----- - } - - $i = null; - if ($this->backward($i, $prev)) { - if ( - !$prev instanceof HTMLPurifier_Token_Text - ) { - // State 3.1.1: ...</p>{p}<b> - // --- - - // State 3.2.1: ...</p><div> - // ----- - - if (!is_array($token)) $token = array($token); - array_unshift($token, new HTMLPurifier_Token_Text("\n\n")); - } else { - // State 3.1.2: ...</p>\n\n{p}<b> - // --- - - // State 3.2.2: ...</p>\n\n<div> - // ----- - - // Note: PAR<ELEM> cannot occur because PAR would have been - // wrapped in <p> tags. - } - } - } - } else { - // State 2.2: <ul><li> - // ---- - - // State 2.4: <p><b> - // --- - } - } - - /** - * Splits up a text in paragraph tokens and appends them - * to the result stream that will replace the original - * @param $data String text data that will be processed - * into paragraphs - * @param $result Reference to array of tokens that the - * tags will be appended onto - * @param $config Instance of HTMLPurifier_Config - * @param $context Instance of HTMLPurifier_Context - */ - private function _splitText($data, &$result) { - $raw_paragraphs = explode("\n\n", $data); - $paragraphs = array(); // without empty paragraphs - $needs_start = false; - $needs_end = false; - - $c = count($raw_paragraphs); - if ($c == 1) { - // There were no double-newlines, abort quickly. In theory this - // should never happen. - $result[] = new HTMLPurifier_Token_Text($data); - return; - } - for ($i = 0; $i < $c; $i++) { - $par = $raw_paragraphs[$i]; - if (trim($par) !== '') { - $paragraphs[] = $par; - } else { - if ($i == 0) { - // Double newline at the front - if (empty($result)) { - // The empty result indicates that the AutoParagraph - // injector did not add any start paragraph tokens. - // This means that we have been in a paragraph for - // a while, and the newline means we should start a new one. - $result[] = new HTMLPurifier_Token_End('p'); - $result[] = new HTMLPurifier_Token_Text("\n\n"); - // However, the start token should only be added if - // there is more processing to be done (i.e. there are - // real paragraphs in here). If there are none, the - // next start paragraph tag will be handled by the - // next call to the injector - $needs_start = true; - } else { - // We just started a new paragraph! - // Reinstate a double-newline for presentation's sake, since - // it was in the source code. - array_unshift($result, new HTMLPurifier_Token_Text("\n\n")); - } - } elseif ($i + 1 == $c) { - // Double newline at the end - // There should be a trailing </p> when we're finally done. - $needs_end = true; - } - } - } - - // Check if this was just a giant blob of whitespace. Move this earlier, - // perhaps? - if (empty($paragraphs)) { - return; - } - - // Add the start tag indicated by \n\n at the beginning of $data - if ($needs_start) { - $result[] = $this->_pStart(); - } - - // Append the paragraphs onto the result - foreach ($paragraphs as $par) { - $result[] = new HTMLPurifier_Token_Text($par); - $result[] = new HTMLPurifier_Token_End('p'); - $result[] = new HTMLPurifier_Token_Text("\n\n"); - $result[] = $this->_pStart(); - } - - // Remove trailing start token; Injector will handle this later if - // it was indeed needed. This prevents from needing to do a lookahead, - // at the cost of a lookbehind later. - array_pop($result); - - // If there is no need for an end tag, remove all of it and let - // MakeWellFormed close it later. - if (!$needs_end) { - array_pop($result); // removes \n\n - array_pop($result); // removes </p> - } - - } - - /** - * Returns true if passed token is inline (and, ergo, allowed in - * paragraph tags) - */ - private function _isInline($token) { - return isset($this->htmlDefinition->info['p']->child->elements[$token->name]); - } - - /** - * Looks ahead in the token list and determines whether or not we need - * to insert a <p> tag. - */ - private function _pLookAhead() { - $this->current($i, $current); - if ($current instanceof HTMLPurifier_Token_Start) $nesting = 1; - else $nesting = 0; - $ok = false; - while ($this->forwardUntilEndToken($i, $current, $nesting)) { - $result = $this->_checkNeedsP($current); - if ($result !== null) { - $ok = $result; - break; - } - } - return $ok; - } - - /** - * Determines if a particular token requires an earlier inline token - * to get a paragraph. This should be used with _forwardUntilEndToken - */ - private function _checkNeedsP($current) { - if ($current instanceof HTMLPurifier_Token_Start){ - if (!$this->_isInline($current)) { - // <div>PAR1<div> - // ---- - // Terminate early, since we hit a block element - return false; - } - } elseif ($current instanceof HTMLPurifier_Token_Text) { - if (strpos($current->data, "\n\n") !== false) { - // <div>PAR1<b>PAR1\n\nPAR2 - // ---- - return true; - } else { - // <div>PAR1<b>PAR1... - // ---- - } - } - return null; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Injector/DisplayLinkURI.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Injector/DisplayLinkURI.php deleted file mode 100644 index 9df45fb2..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Injector/DisplayLinkURI.php +++ /dev/null @@ -1,26 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Injector that displays the URL of an anchor instead of linking to it, in addition to showing the text of the link. - */ -class HTMLPurifier_Injector_DisplayLinkURI extends HTMLPurifier_Injector -{ - - public $name = 'DisplayLinkURI'; - public $needed = array('a'); - - public function handleElement(&$token) { - } - - public function handleEnd(&$token) { - if (isset($token->start->attr['href'])){ - $url = $token->start->attr['href']; - unset($token->start->attr['href']); - $token = array($token, new HTMLPurifier_Token_Text(" ($url)")); - } else { - // nothing to display - } - } -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Injector/Linkify.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Injector/Linkify.php deleted file mode 100644 index 8daf70ea..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Injector/Linkify.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Injector that converts http, https and ftp text URLs to actual links. - */ -class HTMLPurifier_Injector_Linkify extends HTMLPurifier_Injector -{ - - public $name = 'Linkify'; - public $needed = array('a' => array('href')); - - public function handleText(&$token) { - if (!$this->allowsElement('a')) return; - - if (strpos($token->data, '://') === false) { - // our really quick heuristic failed, abort - // this may not work so well if we want to match things like - // "google.com", but then again, most people don't - return; - } - - // there is/are URL(s). Let's split the string: - // Note: this regex is extremely permissive - $bits = preg_split('#((?:https?|ftp)://[^\s\'"<>()]+)#S', $token->data, -1, PREG_SPLIT_DELIM_CAPTURE); - - $token = array(); - - // $i = index - // $c = count - // $l = is link - for ($i = 0, $c = count($bits), $l = false; $i < $c; $i++, $l = !$l) { - if (!$l) { - if ($bits[$i] === '') continue; - $token[] = new HTMLPurifier_Token_Text($bits[$i]); - } else { - $token[] = new HTMLPurifier_Token_Start('a', array('href' => $bits[$i])); - $token[] = new HTMLPurifier_Token_Text($bits[$i]); - $token[] = new HTMLPurifier_Token_End('a'); - } - } - - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Injector/PurifierLinkify.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Injector/PurifierLinkify.php deleted file mode 100644 index a67b3894..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Injector/PurifierLinkify.php +++ /dev/null @@ -1,45 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Injector that converts configuration directive syntax %Namespace.Directive - * to links - */ -class HTMLPurifier_Injector_PurifierLinkify extends HTMLPurifier_Injector -{ - - public $name = 'PurifierLinkify'; - public $docURL; - public $needed = array('a' => array('href')); - - public function prepare($config, $context) { - $this->docURL = $config->get('AutoFormat.PurifierLinkify.DocURL'); - return parent::prepare($config, $context); - } - - public function handleText(&$token) { - if (!$this->allowsElement('a')) return; - if (strpos($token->data, '%') === false) return; - - $bits = preg_split('#%([a-z0-9]+\.[a-z0-9]+)#Si', $token->data, -1, PREG_SPLIT_DELIM_CAPTURE); - $token = array(); - - // $i = index - // $c = count - // $l = is link - for ($i = 0, $c = count($bits), $l = false; $i < $c; $i++, $l = !$l) { - if (!$l) { - if ($bits[$i] === '') continue; - $token[] = new HTMLPurifier_Token_Text($bits[$i]); - } else { - $token[] = new HTMLPurifier_Token_Start('a', - array('href' => str_replace('%s', $bits[$i], $this->docURL))); - $token[] = new HTMLPurifier_Token_Text('%' . $bits[$i]); - $token[] = new HTMLPurifier_Token_End('a'); - } - } - - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Injector/RemoveEmpty.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Injector/RemoveEmpty.php deleted file mode 100644 index c4c26ef7..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Injector/RemoveEmpty.php +++ /dev/null @@ -1,51 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -class HTMLPurifier_Injector_RemoveEmpty extends HTMLPurifier_Injector -{ - - private $context, $config, $attrValidator, $removeNbsp, $removeNbspExceptions; - - public function prepare($config, $context) { - parent::prepare($config, $context); - $this->config = $config; - $this->context = $context; - $this->removeNbsp = $config->get('AutoFormat.RemoveEmpty.RemoveNbsp'); - $this->removeNbspExceptions = $config->get('AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions'); - $this->attrValidator = new HTMLPurifier_AttrValidator(); - } - - public function handleElement(&$token) { - if (!$token instanceof HTMLPurifier_Token_Start) return; - $next = false; - for ($i = $this->inputIndex + 1, $c = count($this->inputTokens); $i < $c; $i++) { - $next = $this->inputTokens[$i]; - if ($next instanceof HTMLPurifier_Token_Text) { - if ($next->is_whitespace) continue; - if ($this->removeNbsp && !isset($this->removeNbspExceptions[$token->name])) { - $plain = str_replace("\xC2\xA0", "", $next->data); - $isWsOrNbsp = $plain === '' || ctype_space($plain); - if ($isWsOrNbsp) continue; - } - } - break; - } - if (!$next || ($next instanceof HTMLPurifier_Token_End && $next->name == $token->name)) { - if ($token->name == 'colgroup') return; - $this->attrValidator->validateToken($token, $this->config, $this->context); - $token->armor['ValidateAttributes'] = true; - if (isset($token->attr['id']) || isset($token->attr['name'])) return; - $token = $i - $this->inputIndex + 1; - for ($b = $this->inputIndex - 1; $b > 0; $b--) { - $prev = $this->inputTokens[$b]; - if ($prev instanceof HTMLPurifier_Token_Text && $prev->is_whitespace) continue; - break; - } - // This is safe because we removed the token that triggered this. - $this->rewind($b - 1); - return; - } - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Injector/SafeObject.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Injector/SafeObject.php deleted file mode 100644 index 42d8fd40..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Injector/SafeObject.php +++ /dev/null @@ -1,87 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Adds important param elements to inside of object in order to make - * things safe. - */ -class HTMLPurifier_Injector_SafeObject extends HTMLPurifier_Injector -{ - public $name = 'SafeObject'; - public $needed = array('object', 'param'); - - protected $objectStack = array(); - protected $paramStack = array(); - - // Keep this synchronized with AttrTransform/SafeParam.php - protected $addParam = array( - 'allowScriptAccess' => 'never', - 'allowNetworking' => 'internal', - ); - protected $allowedParam = array( - 'wmode' => true, - 'movie' => true, - ); - - public function prepare($config, $context) { - parent::prepare($config, $context); - } - - public function handleElement(&$token) { - if ($token->name == 'object') { - $this->objectStack[] = $token; - $this->paramStack[] = array(); - $new = array($token); - foreach ($this->addParam as $name => $value) { - $new[] = new HTMLPurifier_Token_Empty('param', array('name' => $name, 'value' => $value)); - } - $token = $new; - } elseif ($token->name == 'param') { - $nest = count($this->currentNesting) - 1; - if ($nest >= 0 && $this->currentNesting[$nest]->name === 'object') { - $i = count($this->objectStack) - 1; - if (!isset($token->attr['name'])) { - $token = false; - return; - } - $n = $token->attr['name']; - // We need this fix because YouTube doesn't supply a data - // attribute, which we need if a type is specified. This is - // *very* Flash specific. - if (!isset($this->objectStack[$i]->attr['data']) && $token->attr['name'] == 'movie') { - $this->objectStack[$i]->attr['data'] = $token->attr['value']; - } - // Check if the parameter is the correct value but has not - // already been added - if ( - !isset($this->paramStack[$i][$n]) && - isset($this->addParam[$n]) && - $token->attr['name'] === $this->addParam[$n] - ) { - // keep token, and add to param stack - $this->paramStack[$i][$n] = true; - } elseif (isset($this->allowedParam[$n])) { - // keep token, don't do anything to it - // (could possibly check for duplicates here) - } else { - $token = false; - } - } else { - // not directly inside an object, DENY! - $token = false; - } - } - } - - public function handleEnd(&$token) { - // This is the WRONG way of handling the object and param stacks; - // we should be inserting them directly on the relevant object tokens - // so that the global stack handling handles it. - if ($token->name == 'object') { - array_pop($this->objectStack); - array_pop($this->paramStack); - } - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Language.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Language.php deleted file mode 100644 index 2fdfc147..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Language.php +++ /dev/null @@ -1,163 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Represents a language and defines localizable string formatting and - * other functions, as well as the localized messages for HTML Purifier. - */ -class HTMLPurifier_Language -{ - - /** - * ISO 639 language code of language. Prefers shortest possible version - */ - public $code = 'en'; - - /** - * Fallback language code - */ - public $fallback = false; - - /** - * Array of localizable messages - */ - public $messages = array(); - - /** - * Array of localizable error codes - */ - public $errorNames = array(); - - /** - * True if no message file was found for this language, so English - * is being used instead. Check this if you'd like to notify the - * user that they've used a non-supported language. - */ - public $error = false; - - /** - * Has the language object been loaded yet? - * @todo Make it private, fix usage in HTMLPurifier_LanguageTest - */ - public $_loaded = false; - - /** - * Instances of HTMLPurifier_Config and HTMLPurifier_Context - */ - protected $config, $context; - - public function __construct($config, $context) { - $this->config = $config; - $this->context = $context; - } - - /** - * Loads language object with necessary info from factory cache - * @note This is a lazy loader - */ - public function load() { - if ($this->_loaded) return; - $factory = HTMLPurifier_LanguageFactory::instance(); - $factory->loadLanguage($this->code); - foreach ($factory->keys as $key) { - $this->$key = $factory->cache[$this->code][$key]; - } - $this->_loaded = true; - } - - /** - * Retrieves a localised message. - * @param $key string identifier of message - * @return string localised message - */ - public function getMessage($key) { - if (!$this->_loaded) $this->load(); - if (!isset($this->messages[$key])) return "[$key]"; - return $this->messages[$key]; - } - - /** - * Retrieves a localised error name. - * @param $int integer error number, corresponding to PHP's error - * reporting - * @return string localised message - */ - public function getErrorName($int) { - if (!$this->_loaded) $this->load(); - if (!isset($this->errorNames[$int])) return "[Error: $int]"; - return $this->errorNames[$int]; - } - - /** - * Converts an array list into a string readable representation - */ - public function listify($array) { - $sep = $this->getMessage('Item separator'); - $sep_last = $this->getMessage('Item separator last'); - $ret = ''; - for ($i = 0, $c = count($array); $i < $c; $i++) { - if ($i == 0) { - } elseif ($i + 1 < $c) { - $ret .= $sep; - } else { - $ret .= $sep_last; - } - $ret .= $array[$i]; - } - return $ret; - } - - /** - * Formats a localised message with passed parameters - * @param $key string identifier of message - * @param $args Parameters to substitute in - * @return string localised message - * @todo Implement conditionals? Right now, some messages make - * reference to line numbers, but those aren't always available - */ - public function formatMessage($key, $args = array()) { - if (!$this->_loaded) $this->load(); - if (!isset($this->messages[$key])) return "[$key]"; - $raw = $this->messages[$key]; - $subst = array(); - $generator = false; - foreach ($args as $i => $value) { - if (is_object($value)) { - if ($value instanceof HTMLPurifier_Token) { - // factor this out some time - if (!$generator) $generator = $this->context->get('Generator'); - if (isset($value->name)) $subst['$'.$i.'.Name'] = $value->name; - if (isset($value->data)) $subst['$'.$i.'.Data'] = $value->data; - $subst['$'.$i.'.Compact'] = - $subst['$'.$i.'.Serialized'] = $generator->generateFromToken($value); - // a more complex algorithm for compact representation - // could be introduced for all types of tokens. This - // may need to be factored out into a dedicated class - if (!empty($value->attr)) { - $stripped_token = clone $value; - $stripped_token->attr = array(); - $subst['$'.$i.'.Compact'] = $generator->generateFromToken($stripped_token); - } - $subst['$'.$i.'.Line'] = $value->line ? $value->line : 'unknown'; - } - continue; - } elseif (is_array($value)) { - $keys = array_keys($value); - if (array_keys($keys) === $keys) { - // list - $subst['$'.$i] = $this->listify($value); - } else { - // associative array - // no $i implementation yet, sorry - $subst['$'.$i.'.Keys'] = $this->listify($keys); - $subst['$'.$i.'.Values'] = $this->listify(array_values($value)); - } - continue; - } - $subst['$' . $i] = $value; - } - return strtr($raw, $subst); - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Language/classes/en-x-test.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Language/classes/en-x-test.php deleted file mode 100644 index 2682b60a..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Language/classes/en-x-test.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -// private class for unit testing - -class HTMLPurifier_Language_en_x_test extends HTMLPurifier_Language -{ - - - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Language/messages/en-x-test.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Language/messages/en-x-test.php deleted file mode 100644 index 13755643..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Language/messages/en-x-test.php +++ /dev/null @@ -1,11 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -// private language message file for unit testing purposes - -$fallback = 'en'; - -$messages = array( - 'HTMLPurifier' => 'HTML Purifier X' -); - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Language/messages/en-x-testmini.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Language/messages/en-x-testmini.php deleted file mode 100644 index 3fa9ef19..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Language/messages/en-x-testmini.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -// private language message file for unit testing purposes -// this language file has no class associated with it - -$fallback = 'en'; - -$messages = array( - 'HTMLPurifier' => 'HTML Purifier XNone' -); - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Language/messages/en.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Language/messages/en.php deleted file mode 100644 index 5377e5a3..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Language/messages/en.php +++ /dev/null @@ -1,62 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -$fallback = false; - -$messages = array( - -'HTMLPurifier' => 'HTML Purifier', - -// for unit testing purposes -'LanguageFactoryTest: Pizza' => 'Pizza', -'LanguageTest: List' => '$1', -'LanguageTest: Hash' => '$1.Keys; $1.Values', - -'Item separator' => ', ', -'Item separator last' => ' and ', // non-Harvard style - -'ErrorCollector: No errors' => 'No errors detected. However, because error reporting is still incomplete, there may have been errors that the error collector was not notified of; please inspect the output HTML carefully.', -'ErrorCollector: At line' => ' at line $line', -'ErrorCollector: Incidental errors' => 'Incidental errors', - -'Lexer: Unclosed comment' => 'Unclosed comment', -'Lexer: Unescaped lt' => 'Unescaped less-than sign (<) should be <', -'Lexer: Missing gt' => 'Missing greater-than sign (>), previous less-than sign (<) should be escaped', -'Lexer: Missing attribute key' => 'Attribute declaration has no key', -'Lexer: Missing end quote' => 'Attribute declaration has no end quote', - -'Strategy_RemoveForeignElements: Tag transform' => '<$1> element transformed into $CurrentToken.Serialized', -'Strategy_RemoveForeignElements: Missing required attribute' => '$CurrentToken.Compact element missing required attribute $1', -'Strategy_RemoveForeignElements: Foreign element to text' => 'Unrecognized $CurrentToken.Serialized tag converted to text', -'Strategy_RemoveForeignElements: Foreign element removed' => 'Unrecognized $CurrentToken.Serialized tag removed', -'Strategy_RemoveForeignElements: Comment removed' => 'Comment containing "$CurrentToken.Data" removed', -'Strategy_RemoveForeignElements: Foreign meta element removed' => 'Unrecognized $CurrentToken.Serialized meta tag and all descendants removed', -'Strategy_RemoveForeignElements: Token removed to end' => 'Tags and text starting from $1 element where removed to end', -'Strategy_RemoveForeignElements: Trailing hyphen in comment removed' => 'Trailing hyphen(s) in comment removed', -'Strategy_RemoveForeignElements: Hyphens in comment collapsed' => 'Double hyphens in comments are not allowed, and were collapsed into single hyphens', - -'Strategy_MakeWellFormed: Unnecessary end tag removed' => 'Unnecessary $CurrentToken.Serialized tag removed', -'Strategy_MakeWellFormed: Unnecessary end tag to text' => 'Unnecessary $CurrentToken.Serialized tag converted to text', -'Strategy_MakeWellFormed: Tag auto closed' => '$1.Compact started on line $1.Line auto-closed by $CurrentToken.Compact', -'Strategy_MakeWellFormed: Tag carryover' => '$1.Compact started on line $1.Line auto-continued into $CurrentToken.Compact', -'Strategy_MakeWellFormed: Stray end tag removed' => 'Stray $CurrentToken.Serialized tag removed', -'Strategy_MakeWellFormed: Stray end tag to text' => 'Stray $CurrentToken.Serialized tag converted to text', -'Strategy_MakeWellFormed: Tag closed by element end' => '$1.Compact tag started on line $1.Line closed by end of $CurrentToken.Serialized', -'Strategy_MakeWellFormed: Tag closed by document end' => '$1.Compact tag started on line $1.Line closed by end of document', - -'Strategy_FixNesting: Node removed' => '$CurrentToken.Compact node removed', -'Strategy_FixNesting: Node excluded' => '$CurrentToken.Compact node removed due to descendant exclusion by ancestor element', -'Strategy_FixNesting: Node reorganized' => 'Contents of $CurrentToken.Compact node reorganized to enforce its content model', -'Strategy_FixNesting: Node contents removed' => 'Contents of $CurrentToken.Compact node removed', - -'AttrValidator: Attributes transformed' => 'Attributes on $CurrentToken.Compact transformed from $1.Keys to $2.Keys', -'AttrValidator: Attribute removed' => '$CurrentAttr.Name attribute on $CurrentToken.Compact removed', - -); - -$errorNames = array( - E_ERROR => 'Error', - E_WARNING => 'Warning', - E_NOTICE => 'Notice' -); - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/LanguageFactory.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/LanguageFactory.php deleted file mode 100644 index 34f6d733..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/LanguageFactory.php +++ /dev/null @@ -1,198 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Class responsible for generating HTMLPurifier_Language objects, managing - * caching and fallbacks. - * @note Thanks to MediaWiki for the general logic, although this version - * has been entirely rewritten - * @todo Serialized cache for languages - */ -class HTMLPurifier_LanguageFactory -{ - - /** - * Cache of language code information used to load HTMLPurifier_Language objects - * Structure is: $factory->cache[$language_code][$key] = $value - * @value array map - */ - public $cache; - - /** - * Valid keys in the HTMLPurifier_Language object. Designates which - * variables to slurp out of a message file. - * @value array list - */ - public $keys = array('fallback', 'messages', 'errorNames'); - - /** - * Instance of HTMLPurifier_AttrDef_Lang to validate language codes - * @value object HTMLPurifier_AttrDef_Lang - */ - protected $validator; - - /** - * Cached copy of dirname(__FILE__), directory of current file without - * trailing slash - * @value string filename - */ - protected $dir; - - /** - * Keys whose contents are a hash map and can be merged - * @value array lookup - */ - protected $mergeable_keys_map = array('messages' => true, 'errorNames' => true); - - /** - * Keys whose contents are a list and can be merged - * @value array lookup - */ - protected $mergeable_keys_list = array(); - - /** - * Retrieve sole instance of the factory. - * @param $prototype Optional prototype to overload sole instance with, - * or bool true to reset to default factory. - */ - public static function instance($prototype = null) { - static $instance = null; - if ($prototype !== null) { - $instance = $prototype; - } elseif ($instance === null || $prototype == true) { - $instance = new HTMLPurifier_LanguageFactory(); - $instance->setup(); - } - return $instance; - } - - /** - * Sets up the singleton, much like a constructor - * @note Prevents people from getting this outside of the singleton - */ - public function setup() { - $this->validator = new HTMLPurifier_AttrDef_Lang(); - $this->dir = HTMLPURIFIER_PREFIX . '/HTMLPurifier'; - } - - /** - * Creates a language object, handles class fallbacks - * @param $config Instance of HTMLPurifier_Config - * @param $context Instance of HTMLPurifier_Context - * @param $code Code to override configuration with. Private parameter. - */ - public function create($config, $context, $code = false) { - - // validate language code - if ($code === false) { - $code = $this->validator->validate( - $config->get('Core.Language'), $config, $context - ); - } else { - $code = $this->validator->validate($code, $config, $context); - } - if ($code === false) $code = 'en'; // malformed code becomes English - - $pcode = str_replace('-', '_', $code); // make valid PHP classname - static $depth = 0; // recursion protection - - if ($code == 'en') { - $lang = new HTMLPurifier_Language($config, $context); - } else { - $class = 'HTMLPurifier_Language_' . $pcode; - $file = $this->dir . '/Language/classes/' . $code . '.php'; - if (file_exists($file) || class_exists($class, false)) { - $lang = new $class($config, $context); - } else { - // Go fallback - $raw_fallback = $this->getFallbackFor($code); - $fallback = $raw_fallback ? $raw_fallback : 'en'; - $depth++; - $lang = $this->create($config, $context, $fallback); - if (!$raw_fallback) { - $lang->error = true; - } - $depth--; - } - } - - $lang->code = $code; - - return $lang; - - } - - /** - * Returns the fallback language for language - * @note Loads the original language into cache - * @param $code string language code - */ - public function getFallbackFor($code) { - $this->loadLanguage($code); - return $this->cache[$code]['fallback']; - } - - /** - * Loads language into the cache, handles message file and fallbacks - * @param $code string language code - */ - public function loadLanguage($code) { - static $languages_seen = array(); // recursion guard - - // abort if we've already loaded it - if (isset($this->cache[$code])) return; - - // generate filename - $filename = $this->dir . '/Language/messages/' . $code . '.php'; - - // default fallback : may be overwritten by the ensuing include - $fallback = ($code != 'en') ? 'en' : false; - - // load primary localisation - if (!file_exists($filename)) { - // skip the include: will rely solely on fallback - $filename = $this->dir . '/Language/messages/en.php'; - $cache = array(); - } else { - include $filename; - $cache = compact($this->keys); - } - - // load fallback localisation - if (!empty($fallback)) { - - // infinite recursion guard - if (isset($languages_seen[$code])) { - trigger_error('Circular fallback reference in language ' . - $code, E_USER_ERROR); - $fallback = 'en'; - } - $language_seen[$code] = true; - - // load the fallback recursively - $this->loadLanguage($fallback); - $fallback_cache = $this->cache[$fallback]; - - // merge fallback with current language - foreach ( $this->keys as $key ) { - if (isset($cache[$key]) && isset($fallback_cache[$key])) { - if (isset($this->mergeable_keys_map[$key])) { - $cache[$key] = $cache[$key] + $fallback_cache[$key]; - } elseif (isset($this->mergeable_keys_list[$key])) { - $cache[$key] = array_merge( $fallback_cache[$key], $cache[$key] ); - } - } else { - $cache[$key] = $fallback_cache[$key]; - } - } - - } - - // save to cache for later retrieval - $this->cache[$code] = $cache; - - return; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Length.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Length.php deleted file mode 100644 index ca276155..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Length.php +++ /dev/null @@ -1,115 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Represents a measurable length, with a string numeric magnitude - * and a unit. This object is immutable. - */ -class HTMLPurifier_Length -{ - - /** - * String numeric magnitude. - */ - protected $n; - - /** - * String unit. False is permitted if $n = 0. - */ - protected $unit; - - /** - * Whether or not this length is valid. Null if not calculated yet. - */ - protected $isValid; - - /** - * Lookup array of units recognized by CSS 2.1 - */ - protected static $allowedUnits = array( - 'em' => true, 'ex' => true, 'px' => true, 'in' => true, - 'cm' => true, 'mm' => true, 'pt' => true, 'pc' => true - ); - - /** - * @param number $n Magnitude - * @param string $u Unit - */ - public function __construct($n = '0', $u = false) { - $this->n = (string) $n; - $this->unit = $u !== false ? (string) $u : false; - } - - /** - * @param string $s Unit string, like '2em' or '3.4in' - * @warning Does not perform validation. - */ - static public function make($s) { - if ($s instanceof HTMLPurifier_Length) return $s; - $n_length = strspn($s, '1234567890.+-'); - $n = substr($s, 0, $n_length); - $unit = substr($s, $n_length); - if ($unit === '') $unit = false; - return new HTMLPurifier_Length($n, $unit); - } - - /** - * Validates the number and unit. - */ - protected function validate() { - // Special case: - if ($this->n === '+0' || $this->n === '-0') $this->n = '0'; - if ($this->n === '0' && $this->unit === false) return true; - if (!ctype_lower($this->unit)) $this->unit = strtolower($this->unit); - if (!isset(HTMLPurifier_Length::$allowedUnits[$this->unit])) return false; - // Hack: - $def = new HTMLPurifier_AttrDef_CSS_Number(); - $result = $def->validate($this->n, false, false); - if ($result === false) return false; - $this->n = $result; - return true; - } - - /** - * Returns string representation of number. - */ - public function toString() { - if (!$this->isValid()) return false; - return $this->n . $this->unit; - } - - /** - * Retrieves string numeric magnitude. - */ - public function getN() {return $this->n;} - - /** - * Retrieves string unit. - */ - public function getUnit() {return $this->unit;} - - /** - * Returns true if this length unit is valid. - */ - public function isValid() { - if ($this->isValid === null) $this->isValid = $this->validate(); - return $this->isValid; - } - - /** - * Compares two lengths, and returns 1 if greater, -1 if less and 0 if equal. - * @warning If both values are too large or small, this calculation will - * not work properly - */ - public function compareTo($l) { - if ($l === false) return false; - if ($l->unit !== $this->unit) { - $converter = new HTMLPurifier_UnitConverter(); - $l = $converter->convert($l, $this->unit); - if ($l === false) return false; - } - return $this->n - $l->n; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Lexer.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Lexer.php deleted file mode 100644 index 9f20a412..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Lexer.php +++ /dev/null @@ -1,298 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Forgivingly lexes HTML (SGML-style) markup into tokens. - * - * A lexer parses a string of SGML-style markup and converts them into - * corresponding tokens. It doesn't check for well-formedness, although its - * internal mechanism may make this automatic (such as the case of - * HTMLPurifier_Lexer_DOMLex). There are several implementations to choose - * from. - * - * A lexer is HTML-oriented: it might work with XML, but it's not - * recommended, as we adhere to a subset of the specification for optimization - * reasons. This might change in the future. Also, most tokenizers are not - * expected to handle DTDs or PIs. - * - * This class should not be directly instantiated, but you may use create() to - * retrieve a default copy of the lexer. Being a supertype, this class - * does not actually define any implementation, but offers commonly used - * convenience functions for subclasses. - * - * @note The unit tests will instantiate this class for testing purposes, as - * many of the utility functions require a class to be instantiated. - * This means that, even though this class is not runnable, it will - * not be declared abstract. - * - * @par - * - * @note - * We use tokens rather than create a DOM representation because DOM would: - * - * @par - * -# Require more processing and memory to create, - * -# Is not streamable, and - * -# Has the entire document structure (html and body not needed). - * - * @par - * However, DOM is helpful in that it makes it easy to move around nodes - * without a lot of lookaheads to see when a tag is closed. This is a - * limitation of the token system and some workarounds would be nice. - */ -class HTMLPurifier_Lexer -{ - - /** - * Whether or not this lexer implements line-number/column-number tracking. - * If it does, set to true. - */ - public $tracksLineNumbers = false; - - // -- STATIC ---------------------------------------------------------- - - /** - * Retrieves or sets the default Lexer as a Prototype Factory. - * - * By default HTMLPurifier_Lexer_DOMLex will be returned. There are - * a few exceptions involving special features that only DirectLex - * implements. - * - * @note The behavior of this class has changed, rather than accepting - * a prototype object, it now accepts a configuration object. - * To specify your own prototype, set %Core.LexerImpl to it. - * This change in behavior de-singletonizes the lexer object. - * - * @param $config Instance of HTMLPurifier_Config - * @return Concrete lexer. - */ - public static function create($config) { - - if (!($config instanceof HTMLPurifier_Config)) { - $lexer = $config; - trigger_error("Passing a prototype to - HTMLPurifier_Lexer::create() is deprecated, please instead - use %Core.LexerImpl", E_USER_WARNING); - } else { - $lexer = $config->get('Core.LexerImpl'); - } - - $needs_tracking = - $config->get('Core.MaintainLineNumbers') || - $config->get('Core.CollectErrors'); - - $inst = null; - if (is_object($lexer)) { - $inst = $lexer; - } else { - - if (is_null($lexer)) { do { - // auto-detection algorithm - - if ($needs_tracking) { - $lexer = 'DirectLex'; - break; - } - - if ( - class_exists('DOMDocument') && - method_exists('DOMDocument', 'loadHTML') && - !extension_loaded('domxml') - ) { - // check for DOM support, because while it's part of the - // core, it can be disabled compile time. Also, the PECL - // domxml extension overrides the default DOM, and is evil - // and nasty and we shan't bother to support it - $lexer = 'DOMLex'; - } else { - $lexer = 'DirectLex'; - } - - } while(0); } // do..while so we can break - - // instantiate recognized string names - switch ($lexer) { - case 'DOMLex': - $inst = new HTMLPurifier_Lexer_DOMLex(); - break; - case 'DirectLex': - $inst = new HTMLPurifier_Lexer_DirectLex(); - break; - case 'PH5P': - $inst = new HTMLPurifier_Lexer_PH5P(); - break; - default: - throw new HTMLPurifier_Exception("Cannot instantiate unrecognized Lexer type " . htmlspecialchars($lexer)); - } - } - - if (!$inst) throw new HTMLPurifier_Exception('No lexer was instantiated'); - - // once PHP DOM implements native line numbers, or we - // hack out something using XSLT, remove this stipulation - if ($needs_tracking && !$inst->tracksLineNumbers) { - throw new HTMLPurifier_Exception('Cannot use lexer that does not support line numbers with Core.MaintainLineNumbers or Core.CollectErrors (use DirectLex instead)'); - } - - return $inst; - - } - - // -- CONVENIENCE MEMBERS --------------------------------------------- - - public function __construct() { - $this->_entity_parser = new HTMLPurifier_EntityParser(); - } - - /** - * Most common entity to raw value conversion table for special entities. - */ - protected $_special_entity2str = - array( - '"' => '"', - '&' => '&', - '<' => '<', - '>' => '>', - ''' => "'", - ''' => "'", - ''' => "'" - ); - - /** - * Parses special entities into the proper characters. - * - * This string will translate escaped versions of the special characters - * into the correct ones. - * - * @warning - * You should be able to treat the output of this function as - * completely parsed, but that's only because all other entities should - * have been handled previously in substituteNonSpecialEntities() - * - * @param $string String character data to be parsed. - * @returns Parsed character data. - */ - public function parseData($string) { - - // following functions require at least one character - if ($string === '') return ''; - - // subtracts amps that cannot possibly be escaped - $num_amp = substr_count($string, '&') - substr_count($string, '& ') - - ($string[strlen($string)-1] === '&' ? 1 : 0); - - if (!$num_amp) return $string; // abort if no entities - $num_esc_amp = substr_count($string, '&'); - $string = strtr($string, $this->_special_entity2str); - - // code duplication for sake of optimization, see above - $num_amp_2 = substr_count($string, '&') - substr_count($string, '& ') - - ($string[strlen($string)-1] === '&' ? 1 : 0); - - if ($num_amp_2 <= $num_esc_amp) return $string; - - // hmm... now we have some uncommon entities. Use the callback. - $string = $this->_entity_parser->substituteSpecialEntities($string); - return $string; - } - - /** - * Lexes an HTML string into tokens. - * - * @param $string String HTML. - * @return HTMLPurifier_Token array representation of HTML. - */ - public function tokenizeHTML($string, $config, $context) { - trigger_error('Call to abstract class', E_USER_ERROR); - } - - /** - * Translates CDATA sections into regular sections (through escaping). - * - * @param $string HTML string to process. - * @returns HTML with CDATA sections escaped. - */ - protected static function escapeCDATA($string) { - return preg_replace_callback( - '/<!\[CDATA\[(.+?)\]\]>/s', - array('HTMLPurifier_Lexer', 'CDATACallback'), - $string - ); - } - - /** - * Special CDATA case that is especially convoluted for <script> - */ - protected static function escapeCommentedCDATA($string) { - return preg_replace_callback( - '#<!--//--><!\[CDATA\[//><!--(.+?)//--><!\]\]>#s', - array('HTMLPurifier_Lexer', 'CDATACallback'), - $string - ); - } - - /** - * Callback function for escapeCDATA() that does the work. - * - * @warning Though this is public in order to let the callback happen, - * calling it directly is not recommended. - * @params $matches PCRE matches array, with index 0 the entire match - * and 1 the inside of the CDATA section. - * @returns Escaped internals of the CDATA section. - */ - protected static function CDATACallback($matches) { - // not exactly sure why the character set is needed, but whatever - return htmlspecialchars($matches[1], ENT_COMPAT, 'UTF-8'); - } - - /** - * Takes a piece of HTML and normalizes it by converting entities, fixing - * encoding, extracting bits, and other good stuff. - * @todo Consider making protected - */ - public function normalize($html, $config, $context) { - - // normalize newlines to \n - $html = str_replace("\r\n", "\n", $html); - $html = str_replace("\r", "\n", $html); - - if ($config->get('HTML.Trusted')) { - // escape convoluted CDATA - $html = $this->escapeCommentedCDATA($html); - } - - // escape CDATA - $html = $this->escapeCDATA($html); - - // extract body from document if applicable - if ($config->get('Core.ConvertDocumentToFragment')) { - $html = $this->extractBody($html); - } - - // expand entities that aren't the big five - $html = $this->_entity_parser->substituteNonSpecialEntities($html); - - // clean into wellformed UTF-8 string for an SGML context: this has - // to be done after entity expansion because the entities sometimes - // represent non-SGML characters (horror, horror!) - $html = HTMLPurifier_Encoder::cleanUTF8($html); - - return $html; - } - - /** - * Takes a string of HTML (fragment or document) and returns the content - * @todo Consider making protected - */ - public function extractBody($html) { - $matches = array(); - $result = preg_match('!<body[^>]*>(.*)</body>!is', $html, $matches); - if ($result) { - return $matches[1]; - } else { - return $html; - } - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Lexer/DOMLex.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Lexer/DOMLex.php deleted file mode 100644 index 4b78c611..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Lexer/DOMLex.php +++ /dev/null @@ -1,213 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Parser that uses PHP 5's DOM extension (part of the core). - * - * In PHP 5, the DOM XML extension was revamped into DOM and added to the core. - * It gives us a forgiving HTML parser, which we use to transform the HTML - * into a DOM, and then into the tokens. It is blazingly fast (for large - * documents, it performs twenty times faster than - * HTMLPurifier_Lexer_DirectLex,and is the default choice for PHP 5. - * - * @note Any empty elements will have empty tokens associated with them, even if - * this is prohibited by the spec. This is cannot be fixed until the spec - * comes into play. - * - * @note PHP's DOM extension does not actually parse any entities, we use - * our own function to do that. - * - * @warning DOM tends to drop whitespace, which may wreak havoc on indenting. - * If this is a huge problem, due to the fact that HTML is hand - * edited and you are unable to get a parser cache that caches the - * the output of HTML Purifier while keeping the original HTML lying - * around, you may want to run Tidy on the resulting output or use - * HTMLPurifier_DirectLex - */ - -class HTMLPurifier_Lexer_DOMLex extends HTMLPurifier_Lexer -{ - - private $factory; - - public function __construct() { - // setup the factory - parent::__construct(); - $this->factory = new HTMLPurifier_TokenFactory(); - } - - public function tokenizeHTML($html, $config, $context) { - - $html = $this->normalize($html, $config, $context); - - // attempt to armor stray angled brackets that cannot possibly - // form tags and thus are probably being used as emoticons - if ($config->get('Core.AggressivelyFixLt')) { - $char = '[^a-z!\/]'; - $comment = "/<!--(.*?)(-->|\z)/is"; - $html = preg_replace_callback($comment, array($this, 'callbackArmorCommentEntities'), $html); - do { - $old = $html; - $html = preg_replace("/<($char)/i", '<\\1', $html); - } while ($html !== $old); - $html = preg_replace_callback($comment, array($this, 'callbackUndoCommentSubst'), $html); // fix comments - } - - // preprocess html, essential for UTF-8 - $html = $this->wrapHTML($html, $config, $context); - - $doc = new DOMDocument(); - $doc->encoding = 'UTF-8'; // theoretically, the above has this covered - - set_error_handler(array($this, 'muteErrorHandler')); - $doc->loadHTML($html); - restore_error_handler(); - - $tokens = array(); - $this->tokenizeDOM( - $doc->getElementsByTagName('html')->item(0)-> // <html> - getElementsByTagName('body')->item(0)-> // <body> - getElementsByTagName('div')->item(0) // <div> - , $tokens); - return $tokens; - } - - /** - * Recursive function that tokenizes a node, putting it into an accumulator. - * - * @param $node DOMNode to be tokenized. - * @param $tokens Array-list of already tokenized tokens. - * @param $collect Says whether or start and close are collected, set to - * false at first recursion because it's the implicit DIV - * tag you're dealing with. - * @returns Tokens of node appended to previously passed tokens. - */ - protected function tokenizeDOM($node, &$tokens, $collect = false) { - - // intercept non element nodes. WE MUST catch all of them, - // but we're not getting the character reference nodes because - // those should have been preprocessed - if ($node->nodeType === XML_TEXT_NODE) { - $tokens[] = $this->factory->createText($node->data); - return; - } elseif ($node->nodeType === XML_CDATA_SECTION_NODE) { - // undo libxml's special treatment of <script> and <style> tags - $last = end($tokens); - $data = $node->data; - // (note $node->tagname is already normalized) - if ($last instanceof HTMLPurifier_Token_Start && ($last->name == 'script' || $last->name == 'style')) { - $new_data = trim($data); - if (substr($new_data, 0, 4) === '<!--') { - $data = substr($new_data, 4); - if (substr($data, -3) === '-->') { - $data = substr($data, 0, -3); - } else { - // Highly suspicious! Not sure what to do... - } - } - } - $tokens[] = $this->factory->createText($this->parseData($data)); - return; - } elseif ($node->nodeType === XML_COMMENT_NODE) { - // this is code is only invoked for comments in script/style in versions - // of libxml pre-2.6.28 (regular comments, of course, are still - // handled regularly) - $tokens[] = $this->factory->createComment($node->data); - return; - } elseif ( - // not-well tested: there may be other nodes we have to grab - $node->nodeType !== XML_ELEMENT_NODE - ) { - return; - } - - $attr = $node->hasAttributes() ? - $this->transformAttrToAssoc($node->attributes) : - array(); - - // We still have to make sure that the element actually IS empty - if (!$node->childNodes->length) { - if ($collect) { - $tokens[] = $this->factory->createEmpty($node->tagName, $attr); - } - } else { - if ($collect) { // don't wrap on first iteration - $tokens[] = $this->factory->createStart( - $tag_name = $node->tagName, // somehow, it get's dropped - $attr - ); - } - foreach ($node->childNodes as $node) { - // remember, it's an accumulator. Otherwise, we'd have - // to use array_merge - $this->tokenizeDOM($node, $tokens, true); - } - if ($collect) { - $tokens[] = $this->factory->createEnd($tag_name); - } - } - - } - - /** - * Converts a DOMNamedNodeMap of DOMAttr objects into an assoc array. - * - * @param $attribute_list DOMNamedNodeMap of DOMAttr objects. - * @returns Associative array of attributes. - */ - protected function transformAttrToAssoc($node_map) { - // NamedNodeMap is documented very well, so we're using undocumented - // features, namely, the fact that it implements Iterator and - // has a ->length attribute - if ($node_map->length === 0) return array(); - $array = array(); - foreach ($node_map as $attr) { - $array[$attr->name] = $attr->value; - } - return $array; - } - - /** - * An error handler that mutes all errors - */ - public function muteErrorHandler($errno, $errstr) {} - - /** - * Callback function for undoing escaping of stray angled brackets - * in comments - */ - public function callbackUndoCommentSubst($matches) { - return '<!--' . strtr($matches[1], array('&'=>'&','<'=>'<')) . $matches[2]; - } - - /** - * Callback function that entity-izes ampersands in comments so that - * callbackUndoCommentSubst doesn't clobber them - */ - public function callbackArmorCommentEntities($matches) { - return '<!--' . str_replace('&', '&', $matches[1]) . $matches[2]; - } - - /** - * Wraps an HTML fragment in the necessary HTML - */ - protected function wrapHTML($html, $config, $context) { - $def = $config->getDefinition('HTML'); - $ret = ''; - - if (!empty($def->doctype->dtdPublic) || !empty($def->doctype->dtdSystem)) { - $ret .= '<!DOCTYPE html '; - if (!empty($def->doctype->dtdPublic)) $ret .= 'PUBLIC "' . $def->doctype->dtdPublic . '" '; - if (!empty($def->doctype->dtdSystem)) $ret .= '"' . $def->doctype->dtdSystem . '" '; - $ret .= '>'; - } - - $ret .= '<html><head>'; - $ret .= '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />'; - // No protection if $html contains a stray </div>! - $ret .= '</head><body><div>'.$html.'</div></body></html>'; - return $ret; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Lexer/DirectLex.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Lexer/DirectLex.php deleted file mode 100644 index eb421b23..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Lexer/DirectLex.php +++ /dev/null @@ -1,490 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Our in-house implementation of a parser. - * - * A pure PHP parser, DirectLex has absolutely no dependencies, making - * it a reasonably good default for PHP4. Written with efficiency in mind, - * it can be four times faster than HTMLPurifier_Lexer_PEARSax3, although it - * pales in comparison to HTMLPurifier_Lexer_DOMLex. - * - * @todo Reread XML spec and document differences. - */ -class HTMLPurifier_Lexer_DirectLex extends HTMLPurifier_Lexer -{ - - public $tracksLineNumbers = true; - - /** - * Whitespace characters for str(c)spn. - */ - protected $_whitespace = "\x20\x09\x0D\x0A"; - - /** - * Callback function for script CDATA fudge - * @param $matches, in form of array(opening tag, contents, closing tag) - */ - protected function scriptCallback($matches) { - return $matches[1] . htmlspecialchars($matches[2], ENT_COMPAT, 'UTF-8') . $matches[3]; - } - - public function tokenizeHTML($html, $config, $context) { - - // special normalization for script tags without any armor - // our "armor" heurstic is a < sign any number of whitespaces after - // the first script tag - if ($config->get('HTML.Trusted')) { - $html = preg_replace_callback('#(<script[^>]*>)(\s*[^<].+?)(</script>)#si', - array($this, 'scriptCallback'), $html); - } - - $html = $this->normalize($html, $config, $context); - - $cursor = 0; // our location in the text - $inside_tag = false; // whether or not we're parsing the inside of a tag - $array = array(); // result array - - // This is also treated to mean maintain *column* numbers too - $maintain_line_numbers = $config->get('Core.MaintainLineNumbers'); - - if ($maintain_line_numbers === null) { - // automatically determine line numbering by checking - // if error collection is on - $maintain_line_numbers = $config->get('Core.CollectErrors'); - } - - if ($maintain_line_numbers) { - $current_line = 1; - $current_col = 0; - $length = strlen($html); - } else { - $current_line = false; - $current_col = false; - $length = false; - } - $context->register('CurrentLine', $current_line); - $context->register('CurrentCol', $current_col); - $nl = "\n"; - // how often to manually recalculate. This will ALWAYS be right, - // but it's pretty wasteful. Set to 0 to turn off - $synchronize_interval = $config->get('Core.DirectLexLineNumberSyncInterval'); - - $e = false; - if ($config->get('Core.CollectErrors')) { - $e =& $context->get('ErrorCollector'); - } - - // for testing synchronization - $loops = 0; - - while(++$loops) { - - // $cursor is either at the start of a token, or inside of - // a tag (i.e. there was a < immediately before it), as indicated - // by $inside_tag - - if ($maintain_line_numbers) { - - // $rcursor, however, is always at the start of a token. - $rcursor = $cursor - (int) $inside_tag; - - // Column number is cheap, so we calculate it every round. - // We're interested at the *end* of the newline string, so - // we need to add strlen($nl) == 1 to $nl_pos before subtracting it - // from our "rcursor" position. - $nl_pos = strrpos($html, $nl, $rcursor - $length); - $current_col = $rcursor - (is_bool($nl_pos) ? 0 : $nl_pos + 1); - - // recalculate lines - if ( - $synchronize_interval && // synchronization is on - $cursor > 0 && // cursor is further than zero - $loops % $synchronize_interval === 0 // time to synchronize! - ) { - $current_line = 1 + $this->substrCount($html, $nl, 0, $cursor); - } - - } - - $position_next_lt = strpos($html, '<', $cursor); - $position_next_gt = strpos($html, '>', $cursor); - - // triggers on "<b>asdf</b>" but not "asdf <b></b>" - // special case to set up context - if ($position_next_lt === $cursor) { - $inside_tag = true; - $cursor++; - } - - if (!$inside_tag && $position_next_lt !== false) { - // We are not inside tag and there still is another tag to parse - $token = new - HTMLPurifier_Token_Text( - $this->parseData( - substr( - $html, $cursor, $position_next_lt - $cursor - ) - ) - ); - if ($maintain_line_numbers) { - $token->rawPosition($current_line, $current_col); - $current_line += $this->substrCount($html, $nl, $cursor, $position_next_lt - $cursor); - } - $array[] = $token; - $cursor = $position_next_lt + 1; - $inside_tag = true; - continue; - } elseif (!$inside_tag) { - // We are not inside tag but there are no more tags - // If we're already at the end, break - if ($cursor === strlen($html)) break; - // Create Text of rest of string - $token = new - HTMLPurifier_Token_Text( - $this->parseData( - substr( - $html, $cursor - ) - ) - ); - if ($maintain_line_numbers) $token->rawPosition($current_line, $current_col); - $array[] = $token; - break; - } elseif ($inside_tag && $position_next_gt !== false) { - // We are in tag and it is well formed - // Grab the internals of the tag - $strlen_segment = $position_next_gt - $cursor; - - if ($strlen_segment < 1) { - // there's nothing to process! - $token = new HTMLPurifier_Token_Text('<'); - $cursor++; - continue; - } - - $segment = substr($html, $cursor, $strlen_segment); - - if ($segment === false) { - // somehow, we attempted to access beyond the end of - // the string, defense-in-depth, reported by Nate Abele - break; - } - - // Check if it's a comment - if ( - substr($segment, 0, 3) === '!--' - ) { - // re-determine segment length, looking for --> - $position_comment_end = strpos($html, '-->', $cursor); - if ($position_comment_end === false) { - // uh oh, we have a comment that extends to - // infinity. Can't be helped: set comment - // end position to end of string - if ($e) $e->send(E_WARNING, 'Lexer: Unclosed comment'); - $position_comment_end = strlen($html); - $end = true; - } else { - $end = false; - } - $strlen_segment = $position_comment_end - $cursor; - $segment = substr($html, $cursor, $strlen_segment); - $token = new - HTMLPurifier_Token_Comment( - substr( - $segment, 3, $strlen_segment - 3 - ) - ); - if ($maintain_line_numbers) { - $token->rawPosition($current_line, $current_col); - $current_line += $this->substrCount($html, $nl, $cursor, $strlen_segment); - } - $array[] = $token; - $cursor = $end ? $position_comment_end : $position_comment_end + 3; - $inside_tag = false; - continue; - } - - // Check if it's an end tag - $is_end_tag = (strpos($segment,'/') === 0); - if ($is_end_tag) { - $type = substr($segment, 1); - $token = new HTMLPurifier_Token_End($type); - if ($maintain_line_numbers) { - $token->rawPosition($current_line, $current_col); - $current_line += $this->substrCount($html, $nl, $cursor, $position_next_gt - $cursor); - } - $array[] = $token; - $inside_tag = false; - $cursor = $position_next_gt + 1; - continue; - } - - // Check leading character is alnum, if not, we may - // have accidently grabbed an emoticon. Translate into - // text and go our merry way - if (!ctype_alpha($segment[0])) { - // XML: $segment[0] !== '_' && $segment[0] !== ':' - if ($e) $e->send(E_NOTICE, 'Lexer: Unescaped lt'); - $token = new HTMLPurifier_Token_Text('<'); - if ($maintain_line_numbers) { - $token->rawPosition($current_line, $current_col); - $current_line += $this->substrCount($html, $nl, $cursor, $position_next_gt - $cursor); - } - $array[] = $token; - $inside_tag = false; - continue; - } - - // Check if it is explicitly self closing, if so, remove - // trailing slash. Remember, we could have a tag like <br>, so - // any later token processing scripts must convert improperly - // classified EmptyTags from StartTags. - $is_self_closing = (strrpos($segment,'/') === $strlen_segment-1); - if ($is_self_closing) { - $strlen_segment--; - $segment = substr($segment, 0, $strlen_segment); - } - - // Check if there are any attributes - $position_first_space = strcspn($segment, $this->_whitespace); - - if ($position_first_space >= $strlen_segment) { - if ($is_self_closing) { - $token = new HTMLPurifier_Token_Empty($segment); - } else { - $token = new HTMLPurifier_Token_Start($segment); - } - if ($maintain_line_numbers) { - $token->rawPosition($current_line, $current_col); - $current_line += $this->substrCount($html, $nl, $cursor, $position_next_gt - $cursor); - } - $array[] = $token; - $inside_tag = false; - $cursor = $position_next_gt + 1; - continue; - } - - // Grab out all the data - $type = substr($segment, 0, $position_first_space); - $attribute_string = - trim( - substr( - $segment, $position_first_space - ) - ); - if ($attribute_string) { - $attr = $this->parseAttributeString( - $attribute_string - , $config, $context - ); - } else { - $attr = array(); - } - - if ($is_self_closing) { - $token = new HTMLPurifier_Token_Empty($type, $attr); - } else { - $token = new HTMLPurifier_Token_Start($type, $attr); - } - if ($maintain_line_numbers) { - $token->rawPosition($current_line, $current_col); - $current_line += $this->substrCount($html, $nl, $cursor, $position_next_gt - $cursor); - } - $array[] = $token; - $cursor = $position_next_gt + 1; - $inside_tag = false; - continue; - } else { - // inside tag, but there's no ending > sign - if ($e) $e->send(E_WARNING, 'Lexer: Missing gt'); - $token = new - HTMLPurifier_Token_Text( - '<' . - $this->parseData( - substr($html, $cursor) - ) - ); - if ($maintain_line_numbers) $token->rawPosition($current_line, $current_col); - // no cursor scroll? Hmm... - $array[] = $token; - break; - } - break; - } - - $context->destroy('CurrentLine'); - $context->destroy('CurrentCol'); - return $array; - } - - /** - * PHP 5.0.x compatible substr_count that implements offset and length - */ - protected function substrCount($haystack, $needle, $offset, $length) { - static $oldVersion; - if ($oldVersion === null) { - $oldVersion = version_compare(PHP_VERSION, '5.1', '<'); - } - if ($oldVersion) { - $haystack = substr($haystack, $offset, $length); - return substr_count($haystack, $needle); - } else { - return substr_count($haystack, $needle, $offset, $length); - } - } - - /** - * Takes the inside of an HTML tag and makes an assoc array of attributes. - * - * @param $string Inside of tag excluding name. - * @returns Assoc array of attributes. - */ - public function parseAttributeString($string, $config, $context) { - $string = (string) $string; // quick typecast - - if ($string == '') return array(); // no attributes - - $e = false; - if ($config->get('Core.CollectErrors')) { - $e =& $context->get('ErrorCollector'); - } - - // let's see if we can abort as quickly as possible - // one equal sign, no spaces => one attribute - $num_equal = substr_count($string, '='); - $has_space = strpos($string, ' '); - if ($num_equal === 0 && !$has_space) { - // bool attribute - return array($string => $string); - } elseif ($num_equal === 1 && !$has_space) { - // only one attribute - list($key, $quoted_value) = explode('=', $string); - $quoted_value = trim($quoted_value); - if (!$key) { - if ($e) $e->send(E_ERROR, 'Lexer: Missing attribute key'); - return array(); - } - if (!$quoted_value) return array($key => ''); - $first_char = @$quoted_value[0]; - $last_char = @$quoted_value[strlen($quoted_value)-1]; - - $same_quote = ($first_char == $last_char); - $open_quote = ($first_char == '"' || $first_char == "'"); - - if ( $same_quote && $open_quote) { - // well behaved - $value = substr($quoted_value, 1, strlen($quoted_value) - 2); - } else { - // not well behaved - if ($open_quote) { - if ($e) $e->send(E_ERROR, 'Lexer: Missing end quote'); - $value = substr($quoted_value, 1); - } else { - $value = $quoted_value; - } - } - if ($value === false) $value = ''; - return array($key => $value); - } - - // setup loop environment - $array = array(); // return assoc array of attributes - $cursor = 0; // current position in string (moves forward) - $size = strlen($string); // size of the string (stays the same) - - // if we have unquoted attributes, the parser expects a terminating - // space, so let's guarantee that there's always a terminating space. - $string .= ' '; - - while(true) { - - if ($cursor >= $size) { - break; - } - - $cursor += ($value = strspn($string, $this->_whitespace, $cursor)); - // grab the key - - $key_begin = $cursor; //we're currently at the start of the key - - // scroll past all characters that are the key (not whitespace or =) - $cursor += strcspn($string, $this->_whitespace . '=', $cursor); - - $key_end = $cursor; // now at the end of the key - - $key = substr($string, $key_begin, $key_end - $key_begin); - - if (!$key) { - if ($e) $e->send(E_ERROR, 'Lexer: Missing attribute key'); - $cursor += strcspn($string, $this->_whitespace, $cursor + 1); // prevent infinite loop - continue; // empty key - } - - // scroll past all whitespace - $cursor += strspn($string, $this->_whitespace, $cursor); - - if ($cursor >= $size) { - $array[$key] = $key; - break; - } - - // if the next character is an equal sign, we've got a regular - // pair, otherwise, it's a bool attribute - $first_char = @$string[$cursor]; - - if ($first_char == '=') { - // key="value" - - $cursor++; - $cursor += strspn($string, $this->_whitespace, $cursor); - - if ($cursor === false) { - $array[$key] = ''; - break; - } - - // we might be in front of a quote right now - - $char = @$string[$cursor]; - - if ($char == '"' || $char == "'") { - // it's quoted, end bound is $char - $cursor++; - $value_begin = $cursor; - $cursor = strpos($string, $char, $cursor); - $value_end = $cursor; - } else { - // it's not quoted, end bound is whitespace - $value_begin = $cursor; - $cursor += strcspn($string, $this->_whitespace, $cursor); - $value_end = $cursor; - } - - // we reached a premature end - if ($cursor === false) { - $cursor = $size; - $value_end = $cursor; - } - - $value = substr($string, $value_begin, $value_end - $value_begin); - if ($value === false) $value = ''; - $array[$key] = $this->parseData($value); - $cursor++; - - } else { - // boolattr - if ($key !== '') { - $array[$key] = $key; - } else { - // purely theoretical - if ($e) $e->send(E_ERROR, 'Lexer: Missing attribute key'); - } - - } - } - return $array; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Lexer/PEARSax3.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Lexer/PEARSax3.php deleted file mode 100644 index 57173455..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Lexer/PEARSax3.php +++ /dev/null @@ -1,106 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Proof-of-concept lexer that uses the PEAR package XML_HTMLSax3 to parse HTML. - * - * PEAR, not suprisingly, also has a SAX parser for HTML. I don't know - * very much about implementation, but it's fairly well written. However, that - * abstraction comes at a price: performance. You need to have it installed, - * and if the API changes, it might break our adapter. Not sure whether or not - * it's UTF-8 aware, but it has some entity parsing trouble (in all areas, - * text and attributes). - * - * Quite personally, I don't recommend using the PEAR class, and the defaults - * don't use it. The unit tests do perform the tests on the SAX parser too, but - * whatever it does for poorly formed HTML is up to it. - * - * @todo Generalize so that XML_HTMLSax is also supported. - * - * @warning Entity-resolution inside attributes is broken. - */ - -class HTMLPurifier_Lexer_PEARSax3 extends HTMLPurifier_Lexer -{ - - /** - * Internal accumulator array for SAX parsers. - */ - protected $tokens = array(); - - public function tokenizeHTML($string, $config, $context) { - - $this->tokens = array(); - - $string = $this->normalize($string, $config, $context); - - $parser = new XML_HTMLSax3(); - $parser->set_object($this); - $parser->set_element_handler('openHandler','closeHandler'); - $parser->set_data_handler('dataHandler'); - $parser->set_escape_handler('escapeHandler'); - - // doesn't seem to work correctly for attributes - $parser->set_option('XML_OPTION_ENTITIES_PARSED', 1); - - $parser->parse($string); - - return $this->tokens; - - } - - /** - * Open tag event handler, interface is defined by PEAR package. - */ - public function openHandler(&$parser, $name, $attrs, $closed) { - // entities are not resolved in attrs - foreach ($attrs as $key => $attr) { - $attrs[$key] = $this->parseData($attr); - } - if ($closed) { - $this->tokens[] = new HTMLPurifier_Token_Empty($name, $attrs); - } else { - $this->tokens[] = new HTMLPurifier_Token_Start($name, $attrs); - } - return true; - } - - /** - * Close tag event handler, interface is defined by PEAR package. - */ - public function closeHandler(&$parser, $name) { - // HTMLSax3 seems to always send empty tags an extra close tag - // check and ignore if you see it: - // [TESTME] to make sure it doesn't overreach - if ($this->tokens[count($this->tokens)-1] instanceof HTMLPurifier_Token_Empty) { - return true; - } - $this->tokens[] = new HTMLPurifier_Token_End($name); - return true; - } - - /** - * Data event handler, interface is defined by PEAR package. - */ - public function dataHandler(&$parser, $data) { - $this->tokens[] = new HTMLPurifier_Token_Text($data); - return true; - } - - /** - * Escaped text handler, interface is defined by PEAR package. - */ - public function escapeHandler(&$parser, $data) { - if (strpos($data, '--') === 0) { - $this->tokens[] = new HTMLPurifier_Token_Comment($data); - } - // CDATA is handled elsewhere, but if it was handled here: - //if (strpos($data, '[CDATA[') === 0) { - // $this->tokens[] = new HTMLPurifier_Token_Text( - // substr($data, 7, strlen($data) - 9) ); - //} - return true; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Lexer/PH5P.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Lexer/PH5P.php deleted file mode 100644 index 731c3171..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Lexer/PH5P.php +++ /dev/null @@ -1,3906 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Experimental HTML5-based parser using Jeroen van der Meer's PH5P library. - * Occupies space in the HTML5 pseudo-namespace, which may cause conflicts. - * - * @note - * Recent changes to PHP's DOM extension have resulted in some fatal - * error conditions with the original version of PH5P. Pending changes, - * this lexer will punt to DirectLex if DOM throughs an exception. - */ - -class HTMLPurifier_Lexer_PH5P extends HTMLPurifier_Lexer_DOMLex { - - public function tokenizeHTML($html, $config, $context) { - $new_html = $this->normalize($html, $config, $context); - $new_html = $this->wrapHTML($new_html, $config, $context); - try { - $parser = new HTML5($new_html); - $doc = $parser->save(); - } catch (DOMException $e) { - // Uh oh, it failed. Punt to DirectLex. - $lexer = new HTMLPurifier_Lexer_DirectLex(); - $context->register('PH5PError', $e); // save the error, so we can detect it - return $lexer->tokenizeHTML($html, $config, $context); // use original HTML - } - $tokens = array(); - $this->tokenizeDOM( - $doc->getElementsByTagName('html')->item(0)-> // <html> - getElementsByTagName('body')->item(0)-> // <body> - getElementsByTagName('div')->item(0) // <div> - , $tokens); - return $tokens; - } - -} - -/* - -Copyright 2007 Jeroen van der Meer <http://jero.net/> - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -*/ - -class HTML5 { - private $data; - private $char; - private $EOF; - private $state; - private $tree; - private $token; - private $content_model; - private $escape = false; - private $entities = array('AElig;','AElig','AMP;','AMP','Aacute;','Aacute', - 'Acirc;','Acirc','Agrave;','Agrave','Alpha;','Aring;','Aring','Atilde;', - 'Atilde','Auml;','Auml','Beta;','COPY;','COPY','Ccedil;','Ccedil','Chi;', - 'Dagger;','Delta;','ETH;','ETH','Eacute;','Eacute','Ecirc;','Ecirc','Egrave;', - 'Egrave','Epsilon;','Eta;','Euml;','Euml','GT;','GT','Gamma;','Iacute;', - 'Iacute','Icirc;','Icirc','Igrave;','Igrave','Iota;','Iuml;','Iuml','Kappa;', - 'LT;','LT','Lambda;','Mu;','Ntilde;','Ntilde','Nu;','OElig;','Oacute;', - 'Oacute','Ocirc;','Ocirc','Ograve;','Ograve','Omega;','Omicron;','Oslash;', - 'Oslash','Otilde;','Otilde','Ouml;','Ouml','Phi;','Pi;','Prime;','Psi;', - 'QUOT;','QUOT','REG;','REG','Rho;','Scaron;','Sigma;','THORN;','THORN', - 'TRADE;','Tau;','Theta;','Uacute;','Uacute','Ucirc;','Ucirc','Ugrave;', - 'Ugrave','Upsilon;','Uuml;','Uuml','Xi;','Yacute;','Yacute','Yuml;','Zeta;', - 'aacute;','aacute','acirc;','acirc','acute;','acute','aelig;','aelig', - 'agrave;','agrave','alefsym;','alpha;','amp;','amp','and;','ang;','apos;', - 'aring;','aring','asymp;','atilde;','atilde','auml;','auml','bdquo;','beta;', - 'brvbar;','brvbar','bull;','cap;','ccedil;','ccedil','cedil;','cedil', - 'cent;','cent','chi;','circ;','clubs;','cong;','copy;','copy','crarr;', - 'cup;','curren;','curren','dArr;','dagger;','darr;','deg;','deg','delta;', - 'diams;','divide;','divide','eacute;','eacute','ecirc;','ecirc','egrave;', - 'egrave','empty;','emsp;','ensp;','epsilon;','equiv;','eta;','eth;','eth', - 'euml;','euml','euro;','exist;','fnof;','forall;','frac12;','frac12', - 'frac14;','frac14','frac34;','frac34','frasl;','gamma;','ge;','gt;','gt', - 'hArr;','harr;','hearts;','hellip;','iacute;','iacute','icirc;','icirc', - 'iexcl;','iexcl','igrave;','igrave','image;','infin;','int;','iota;', - 'iquest;','iquest','isin;','iuml;','iuml','kappa;','lArr;','lambda;','lang;', - 'laquo;','laquo','larr;','lceil;','ldquo;','le;','lfloor;','lowast;','loz;', - 'lrm;','lsaquo;','lsquo;','lt;','lt','macr;','macr','mdash;','micro;','micro', - 'middot;','middot','minus;','mu;','nabla;','nbsp;','nbsp','ndash;','ne;', - 'ni;','not;','not','notin;','nsub;','ntilde;','ntilde','nu;','oacute;', - 'oacute','ocirc;','ocirc','oelig;','ograve;','ograve','oline;','omega;', - 'omicron;','oplus;','or;','ordf;','ordf','ordm;','ordm','oslash;','oslash', - 'otilde;','otilde','otimes;','ouml;','ouml','para;','para','part;','permil;', - 'perp;','phi;','pi;','piv;','plusmn;','plusmn','pound;','pound','prime;', - 'prod;','prop;','psi;','quot;','quot','rArr;','radic;','rang;','raquo;', - 'raquo','rarr;','rceil;','rdquo;','real;','reg;','reg','rfloor;','rho;', - 'rlm;','rsaquo;','rsquo;','sbquo;','scaron;','sdot;','sect;','sect','shy;', - 'shy','sigma;','sigmaf;','sim;','spades;','sub;','sube;','sum;','sup1;', - 'sup1','sup2;','sup2','sup3;','sup3','sup;','supe;','szlig;','szlig','tau;', - 'there4;','theta;','thetasym;','thinsp;','thorn;','thorn','tilde;','times;', - 'times','trade;','uArr;','uacute;','uacute','uarr;','ucirc;','ucirc', - 'ugrave;','ugrave','uml;','uml','upsih;','upsilon;','uuml;','uuml','weierp;', - 'xi;','yacute;','yacute','yen;','yen','yuml;','yuml','zeta;','zwj;','zwnj;'); - - const PCDATA = 0; - const RCDATA = 1; - const CDATA = 2; - const PLAINTEXT = 3; - - const DOCTYPE = 0; - const STARTTAG = 1; - const ENDTAG = 2; - const COMMENT = 3; - const CHARACTR = 4; - const EOF = 5; - - public function __construct($data) { - $data = str_replace("\r\n", "\n", $data); - $data = str_replace("\r", null, $data); - - $this->data = $data; - $this->char = -1; - $this->EOF = strlen($data); - $this->tree = new HTML5TreeConstructer; - $this->content_model = self::PCDATA; - - $this->state = 'data'; - - while($this->state !== null) { - $this->{$this->state.'State'}(); - } - } - - public function save() { - return $this->tree->save(); - } - - private function char() { - return ($this->char < $this->EOF) - ? $this->data[$this->char] - : false; - } - - private function character($s, $l = 0) { - if($s + $l < $this->EOF) { - if($l === 0) { - return $this->data[$s]; - } else { - return substr($this->data, $s, $l); - } - } - } - - private function characters($char_class, $start) { - return preg_replace('#^(['.$char_class.']+).*#s', '\\1', substr($this->data, $start)); - } - - private function dataState() { - // Consume the next input character - $this->char++; - $char = $this->char(); - - if($char === '&' && ($this->content_model === self::PCDATA || $this->content_model === self::RCDATA)) { - /* U+0026 AMPERSAND (&) - When the content model flag is set to one of the PCDATA or RCDATA - states: switch to the entity data state. Otherwise: treat it as per - the "anything else" entry below. */ - $this->state = 'entityData'; - - } elseif($char === '-') { - /* If the content model flag is set to either the RCDATA state or - the CDATA state, and the escape flag is false, and there are at - least three characters before this one in the input stream, and the - last four characters in the input stream, including this one, are - U+003C LESS-THAN SIGN, U+0021 EXCLAMATION MARK, U+002D HYPHEN-MINUS, - and U+002D HYPHEN-MINUS ("<!--"), then set the escape flag to true. */ - if(($this->content_model === self::RCDATA || $this->content_model === - self::CDATA) && $this->escape === false && - $this->char >= 3 && $this->character($this->char - 4, 4) === '<!--') { - $this->escape = true; - } - - /* In any case, emit the input character as a character token. Stay - in the data state. */ - $this->emitToken(array( - 'type' => self::CHARACTR, - 'data' => $char - )); - - /* U+003C LESS-THAN SIGN (<) */ - } elseif($char === '<' && ($this->content_model === self::PCDATA || - (($this->content_model === self::RCDATA || - $this->content_model === self::CDATA) && $this->escape === false))) { - /* When the content model flag is set to the PCDATA state: switch - to the tag open state. - - When the content model flag is set to either the RCDATA state or - the CDATA state and the escape flag is false: switch to the tag - open state. - - Otherwise: treat it as per the "anything else" entry below. */ - $this->state = 'tagOpen'; - - /* U+003E GREATER-THAN SIGN (>) */ - } elseif($char === '>') { - /* If the content model flag is set to either the RCDATA state or - the CDATA state, and the escape flag is true, and the last three - characters in the input stream including this one are U+002D - HYPHEN-MINUS, U+002D HYPHEN-MINUS, U+003E GREATER-THAN SIGN ("-->"), - set the escape flag to false. */ - if(($this->content_model === self::RCDATA || - $this->content_model === self::CDATA) && $this->escape === true && - $this->character($this->char, 3) === '-->') { - $this->escape = false; - } - - /* In any case, emit the input character as a character token. - Stay in the data state. */ - $this->emitToken(array( - 'type' => self::CHARACTR, - 'data' => $char - )); - - } elseif($this->char === $this->EOF) { - /* EOF - Emit an end-of-file token. */ - $this->EOF(); - - } elseif($this->content_model === self::PLAINTEXT) { - /* When the content model flag is set to the PLAINTEXT state - THIS DIFFERS GREATLY FROM THE SPEC: Get the remaining characters of - the text and emit it as a character token. */ - $this->emitToken(array( - 'type' => self::CHARACTR, - 'data' => substr($this->data, $this->char) - )); - - $this->EOF(); - - } else { - /* Anything else - THIS DIFFERS GREATLY FROM THE SPEC: Get as many character that - otherwise would also be treated as a character token and emit it - as a single character token. Stay in the data state. */ - $len = strcspn($this->data, '<&', $this->char); - $char = substr($this->data, $this->char, $len); - $this->char += $len - 1; - - $this->emitToken(array( - 'type' => self::CHARACTR, - 'data' => $char - )); - - $this->state = 'data'; - } - } - - private function entityDataState() { - // Attempt to consume an entity. - $entity = $this->entity(); - - // If nothing is returned, emit a U+0026 AMPERSAND character token. - // Otherwise, emit the character token that was returned. - $char = (!$entity) ? '&' : $entity; - $this->emitToken(array( - 'type' => self::CHARACTR, - 'data' => $char - )); - - // Finally, switch to the data state. - $this->state = 'data'; - } - - private function tagOpenState() { - switch($this->content_model) { - case self::RCDATA: - case self::CDATA: - /* If the next input character is a U+002F SOLIDUS (/) character, - consume it and switch to the close tag open state. If the next - input character is not a U+002F SOLIDUS (/) character, emit a - U+003C LESS-THAN SIGN character token and switch to the data - state to process the next input character. */ - if($this->character($this->char + 1) === '/') { - $this->char++; - $this->state = 'closeTagOpen'; - - } else { - $this->emitToken(array( - 'type' => self::CHARACTR, - 'data' => '<' - )); - - $this->state = 'data'; - } - break; - - case self::PCDATA: - // If the content model flag is set to the PCDATA state - // Consume the next input character: - $this->char++; - $char = $this->char(); - - if($char === '!') { - /* U+0021 EXCLAMATION MARK (!) - Switch to the markup declaration open state. */ - $this->state = 'markupDeclarationOpen'; - - } elseif($char === '/') { - /* U+002F SOLIDUS (/) - Switch to the close tag open state. */ - $this->state = 'closeTagOpen'; - - } elseif(preg_match('/^[A-Za-z]$/', $char)) { - /* U+0041 LATIN LETTER A through to U+005A LATIN LETTER Z - Create a new start tag token, set its tag name to the lowercase - version of the input character (add 0x0020 to the character's code - point), then switch to the tag name state. (Don't emit the token - yet; further details will be filled in before it is emitted.) */ - $this->token = array( - 'name' => strtolower($char), - 'type' => self::STARTTAG, - 'attr' => array() - ); - - $this->state = 'tagName'; - - } elseif($char === '>') { - /* U+003E GREATER-THAN SIGN (>) - Parse error. Emit a U+003C LESS-THAN SIGN character token and a - U+003E GREATER-THAN SIGN character token. Switch to the data state. */ - $this->emitToken(array( - 'type' => self::CHARACTR, - 'data' => '<>' - )); - - $this->state = 'data'; - - } elseif($char === '?') { - /* U+003F QUESTION MARK (?) - Parse error. Switch to the bogus comment state. */ - $this->state = 'bogusComment'; - - } else { - /* Anything else - Parse error. Emit a U+003C LESS-THAN SIGN character token and - reconsume the current input character in the data state. */ - $this->emitToken(array( - 'type' => self::CHARACTR, - 'data' => '<' - )); - - $this->char--; - $this->state = 'data'; - } - break; - } - } - - private function closeTagOpenState() { - $next_node = strtolower($this->characters('A-Za-z', $this->char + 1)); - $the_same = count($this->tree->stack) > 0 && $next_node === end($this->tree->stack)->nodeName; - - if(($this->content_model === self::RCDATA || $this->content_model === self::CDATA) && - (!$the_same || ($the_same && (!preg_match('/[\t\n\x0b\x0c >\/]/', - $this->character($this->char + 1 + strlen($next_node))) || $this->EOF === $this->char)))) { - /* If the content model flag is set to the RCDATA or CDATA states then - examine the next few characters. If they do not match the tag name of - the last start tag token emitted (case insensitively), or if they do but - they are not immediately followed by one of the following characters: - * U+0009 CHARACTER TABULATION - * U+000A LINE FEED (LF) - * U+000B LINE TABULATION - * U+000C FORM FEED (FF) - * U+0020 SPACE - * U+003E GREATER-THAN SIGN (>) - * U+002F SOLIDUS (/) - * EOF - ...then there is a parse error. Emit a U+003C LESS-THAN SIGN character - token, a U+002F SOLIDUS character token, and switch to the data state - to process the next input character. */ - $this->emitToken(array( - 'type' => self::CHARACTR, - 'data' => '</' - )); - - $this->state = 'data'; - - } else { - /* Otherwise, if the content model flag is set to the PCDATA state, - or if the next few characters do match that tag name, consume the - next input character: */ - $this->char++; - $char = $this->char(); - - if(preg_match('/^[A-Za-z]$/', $char)) { - /* U+0041 LATIN LETTER A through to U+005A LATIN LETTER Z - Create a new end tag token, set its tag name to the lowercase version - of the input character (add 0x0020 to the character's code point), then - switch to the tag name state. (Don't emit the token yet; further details - will be filled in before it is emitted.) */ - $this->token = array( - 'name' => strtolower($char), - 'type' => self::ENDTAG - ); - - $this->state = 'tagName'; - - } elseif($char === '>') { - /* U+003E GREATER-THAN SIGN (>) - Parse error. Switch to the data state. */ - $this->state = 'data'; - - } elseif($this->char === $this->EOF) { - /* EOF - Parse error. Emit a U+003C LESS-THAN SIGN character token and a U+002F - SOLIDUS character token. Reconsume the EOF character in the data state. */ - $this->emitToken(array( - 'type' => self::CHARACTR, - 'data' => '</' - )); - - $this->char--; - $this->state = 'data'; - - } else { - /* Parse error. Switch to the bogus comment state. */ - $this->state = 'bogusComment'; - } - } - } - - private function tagNameState() { - // Consume the next input character: - $this->char++; - $char = $this->character($this->char); - - if(preg_match('/^[\t\n\x0b\x0c ]$/', $char)) { - /* U+0009 CHARACTER TABULATION - U+000A LINE FEED (LF) - U+000B LINE TABULATION - U+000C FORM FEED (FF) - U+0020 SPACE - Switch to the before attribute name state. */ - $this->state = 'beforeAttributeName'; - - } elseif($char === '>') { - /* U+003E GREATER-THAN SIGN (>) - Emit the current tag token. Switch to the data state. */ - $this->emitToken($this->token); - $this->state = 'data'; - - } elseif($this->char === $this->EOF) { - /* EOF - Parse error. Emit the current tag token. Reconsume the EOF - character in the data state. */ - $this->emitToken($this->token); - - $this->char--; - $this->state = 'data'; - - } elseif($char === '/') { - /* U+002F SOLIDUS (/) - Parse error unless this is a permitted slash. Switch to the before - attribute name state. */ - $this->state = 'beforeAttributeName'; - - } else { - /* Anything else - Append the current input character to the current tag token's tag name. - Stay in the tag name state. */ - $this->token['name'] .= strtolower($char); - $this->state = 'tagName'; - } - } - - private function beforeAttributeNameState() { - // Consume the next input character: - $this->char++; - $char = $this->character($this->char); - - if(preg_match('/^[\t\n\x0b\x0c ]$/', $char)) { - /* U+0009 CHARACTER TABULATION - U+000A LINE FEED (LF) - U+000B LINE TABULATION - U+000C FORM FEED (FF) - U+0020 SPACE - Stay in the before attribute name state. */ - $this->state = 'beforeAttributeName'; - - } elseif($char === '>') { - /* U+003E GREATER-THAN SIGN (>) - Emit the current tag token. Switch to the data state. */ - $this->emitToken($this->token); - $this->state = 'data'; - - } elseif($char === '/') { - /* U+002F SOLIDUS (/) - Parse error unless this is a permitted slash. Stay in the before - attribute name state. */ - $this->state = 'beforeAttributeName'; - - } elseif($this->char === $this->EOF) { - /* EOF - Parse error. Emit the current tag token. Reconsume the EOF - character in the data state. */ - $this->emitToken($this->token); - - $this->char--; - $this->state = 'data'; - - } else { - /* Anything else - Start a new attribute in the current tag token. Set that attribute's - name to the current input character, and its value to the empty string. - Switch to the attribute name state. */ - $this->token['attr'][] = array( - 'name' => strtolower($char), - 'value' => null - ); - - $this->state = 'attributeName'; - } - } - - private function attributeNameState() { - // Consume the next input character: - $this->char++; - $char = $this->character($this->char); - - if(preg_match('/^[\t\n\x0b\x0c ]$/', $char)) { - /* U+0009 CHARACTER TABULATION - U+000A LINE FEED (LF) - U+000B LINE TABULATION - U+000C FORM FEED (FF) - U+0020 SPACE - Stay in the before attribute name state. */ - $this->state = 'afterAttributeName'; - - } elseif($char === '=') { - /* U+003D EQUALS SIGN (=) - Switch to the before attribute value state. */ - $this->state = 'beforeAttributeValue'; - - } elseif($char === '>') { - /* U+003E GREATER-THAN SIGN (>) - Emit the current tag token. Switch to the data state. */ - $this->emitToken($this->token); - $this->state = 'data'; - - } elseif($char === '/' && $this->character($this->char + 1) !== '>') { - /* U+002F SOLIDUS (/) - Parse error unless this is a permitted slash. Switch to the before - attribute name state. */ - $this->state = 'beforeAttributeName'; - - } elseif($this->char === $this->EOF) { - /* EOF - Parse error. Emit the current tag token. Reconsume the EOF - character in the data state. */ - $this->emitToken($this->token); - - $this->char--; - $this->state = 'data'; - - } else { - /* Anything else - Append the current input character to the current attribute's name. - Stay in the attribute name state. */ - $last = count($this->token['attr']) - 1; - $this->token['attr'][$last]['name'] .= strtolower($char); - - $this->state = 'attributeName'; - } - } - - private function afterAttributeNameState() { - // Consume the next input character: - $this->char++; - $char = $this->character($this->char); - - if(preg_match('/^[\t\n\x0b\x0c ]$/', $char)) { - /* U+0009 CHARACTER TABULATION - U+000A LINE FEED (LF) - U+000B LINE TABULATION - U+000C FORM FEED (FF) - U+0020 SPACE - Stay in the after attribute name state. */ - $this->state = 'afterAttributeName'; - - } elseif($char === '=') { - /* U+003D EQUALS SIGN (=) - Switch to the before attribute value state. */ - $this->state = 'beforeAttributeValue'; - - } elseif($char === '>') { - /* U+003E GREATER-THAN SIGN (>) - Emit the current tag token. Switch to the data state. */ - $this->emitToken($this->token); - $this->state = 'data'; - - } elseif($char === '/' && $this->character($this->char + 1) !== '>') { - /* U+002F SOLIDUS (/) - Parse error unless this is a permitted slash. Switch to the - before attribute name state. */ - $this->state = 'beforeAttributeName'; - - } elseif($this->char === $this->EOF) { - /* EOF - Parse error. Emit the current tag token. Reconsume the EOF - character in the data state. */ - $this->emitToken($this->token); - - $this->char--; - $this->state = 'data'; - - } else { - /* Anything else - Start a new attribute in the current tag token. Set that attribute's - name to the current input character, and its value to the empty string. - Switch to the attribute name state. */ - $this->token['attr'][] = array( - 'name' => strtolower($char), - 'value' => null - ); - - $this->state = 'attributeName'; - } - } - - private function beforeAttributeValueState() { - // Consume the next input character: - $this->char++; - $char = $this->character($this->char); - - if(preg_match('/^[\t\n\x0b\x0c ]$/', $char)) { - /* U+0009 CHARACTER TABULATION - U+000A LINE FEED (LF) - U+000B LINE TABULATION - U+000C FORM FEED (FF) - U+0020 SPACE - Stay in the before attribute value state. */ - $this->state = 'beforeAttributeValue'; - - } elseif($char === '"') { - /* U+0022 QUOTATION MARK (") - Switch to the attribute value (double-quoted) state. */ - $this->state = 'attributeValueDoubleQuoted'; - - } elseif($char === '&') { - /* U+0026 AMPERSAND (&) - Switch to the attribute value (unquoted) state and reconsume - this input character. */ - $this->char--; - $this->state = 'attributeValueUnquoted'; - - } elseif($char === '\'') { - /* U+0027 APOSTROPHE (') - Switch to the attribute value (single-quoted) state. */ - $this->state = 'attributeValueSingleQuoted'; - - } elseif($char === '>') { - /* U+003E GREATER-THAN SIGN (>) - Emit the current tag token. Switch to the data state. */ - $this->emitToken($this->token); - $this->state = 'data'; - - } else { - /* Anything else - Append the current input character to the current attribute's value. - Switch to the attribute value (unquoted) state. */ - $last = count($this->token['attr']) - 1; - $this->token['attr'][$last]['value'] .= $char; - - $this->state = 'attributeValueUnquoted'; - } - } - - private function attributeValueDoubleQuotedState() { - // Consume the next input character: - $this->char++; - $char = $this->character($this->char); - - if($char === '"') { - /* U+0022 QUOTATION MARK (") - Switch to the before attribute name state. */ - $this->state = 'beforeAttributeName'; - - } elseif($char === '&') { - /* U+0026 AMPERSAND (&) - Switch to the entity in attribute value state. */ - $this->entityInAttributeValueState('double'); - - } elseif($this->char === $this->EOF) { - /* EOF - Parse error. Emit the current tag token. Reconsume the character - in the data state. */ - $this->emitToken($this->token); - - $this->char--; - $this->state = 'data'; - - } else { - /* Anything else - Append the current input character to the current attribute's value. - Stay in the attribute value (double-quoted) state. */ - $last = count($this->token['attr']) - 1; - $this->token['attr'][$last]['value'] .= $char; - - $this->state = 'attributeValueDoubleQuoted'; - } - } - - private function attributeValueSingleQuotedState() { - // Consume the next input character: - $this->char++; - $char = $this->character($this->char); - - if($char === '\'') { - /* U+0022 QUOTATION MARK (') - Switch to the before attribute name state. */ - $this->state = 'beforeAttributeName'; - - } elseif($char === '&') { - /* U+0026 AMPERSAND (&) - Switch to the entity in attribute value state. */ - $this->entityInAttributeValueState('single'); - - } elseif($this->char === $this->EOF) { - /* EOF - Parse error. Emit the current tag token. Reconsume the character - in the data state. */ - $this->emitToken($this->token); - - $this->char--; - $this->state = 'data'; - - } else { - /* Anything else - Append the current input character to the current attribute's value. - Stay in the attribute value (single-quoted) state. */ - $last = count($this->token['attr']) - 1; - $this->token['attr'][$last]['value'] .= $char; - - $this->state = 'attributeValueSingleQuoted'; - } - } - - private function attributeValueUnquotedState() { - // Consume the next input character: - $this->char++; - $char = $this->character($this->char); - - if(preg_match('/^[\t\n\x0b\x0c ]$/', $char)) { - /* U+0009 CHARACTER TABULATION - U+000A LINE FEED (LF) - U+000B LINE TABULATION - U+000C FORM FEED (FF) - U+0020 SPACE - Switch to the before attribute name state. */ - $this->state = 'beforeAttributeName'; - - } elseif($char === '&') { - /* U+0026 AMPERSAND (&) - Switch to the entity in attribute value state. */ - $this->entityInAttributeValueState(); - - } elseif($char === '>') { - /* U+003E GREATER-THAN SIGN (>) - Emit the current tag token. Switch to the data state. */ - $this->emitToken($this->token); - $this->state = 'data'; - - } else { - /* Anything else - Append the current input character to the current attribute's value. - Stay in the attribute value (unquoted) state. */ - $last = count($this->token['attr']) - 1; - $this->token['attr'][$last]['value'] .= $char; - - $this->state = 'attributeValueUnquoted'; - } - } - - private function entityInAttributeValueState() { - // Attempt to consume an entity. - $entity = $this->entity(); - - // If nothing is returned, append a U+0026 AMPERSAND character to the - // current attribute's value. Otherwise, emit the character token that - // was returned. - $char = (!$entity) - ? '&' - : $entity; - - $last = count($this->token['attr']) - 1; - $this->token['attr'][$last]['value'] .= $char; - } - - private function bogusCommentState() { - /* Consume every character up to the first U+003E GREATER-THAN SIGN - character (>) or the end of the file (EOF), whichever comes first. Emit - a comment token whose data is the concatenation of all the characters - starting from and including the character that caused the state machine - to switch into the bogus comment state, up to and including the last - consumed character before the U+003E character, if any, or up to the - end of the file otherwise. (If the comment was started by the end of - the file (EOF), the token is empty.) */ - $data = $this->characters('^>', $this->char); - $this->emitToken(array( - 'data' => $data, - 'type' => self::COMMENT - )); - - $this->char += strlen($data); - - /* Switch to the data state. */ - $this->state = 'data'; - - /* If the end of the file was reached, reconsume the EOF character. */ - if($this->char === $this->EOF) { - $this->char = $this->EOF - 1; - } - } - - private function markupDeclarationOpenState() { - /* If the next two characters are both U+002D HYPHEN-MINUS (-) - characters, consume those two characters, create a comment token whose - data is the empty string, and switch to the comment state. */ - if($this->character($this->char + 1, 2) === '--') { - $this->char += 2; - $this->state = 'comment'; - $this->token = array( - 'data' => null, - 'type' => self::COMMENT - ); - - /* Otherwise if the next seven chacacters are a case-insensitive match - for the word "DOCTYPE", then consume those characters and switch to the - DOCTYPE state. */ - } elseif(strtolower($this->character($this->char + 1, 7)) === 'doctype') { - $this->char += 7; - $this->state = 'doctype'; - - /* Otherwise, is is a parse error. Switch to the bogus comment state. - The next character that is consumed, if any, is the first character - that will be in the comment. */ - } else { - $this->char++; - $this->state = 'bogusComment'; - } - } - - private function commentState() { - /* Consume the next input character: */ - $this->char++; - $char = $this->char(); - - /* U+002D HYPHEN-MINUS (-) */ - if($char === '-') { - /* Switch to the comment dash state */ - $this->state = 'commentDash'; - - /* EOF */ - } elseif($this->char === $this->EOF) { - /* Parse error. Emit the comment token. Reconsume the EOF character - in the data state. */ - $this->emitToken($this->token); - $this->char--; - $this->state = 'data'; - - /* Anything else */ - } else { - /* Append the input character to the comment token's data. Stay in - the comment state. */ - $this->token['data'] .= $char; - } - } - - private function commentDashState() { - /* Consume the next input character: */ - $this->char++; - $char = $this->char(); - - /* U+002D HYPHEN-MINUS (-) */ - if($char === '-') { - /* Switch to the comment end state */ - $this->state = 'commentEnd'; - - /* EOF */ - } elseif($this->char === $this->EOF) { - /* Parse error. Emit the comment token. Reconsume the EOF character - in the data state. */ - $this->emitToken($this->token); - $this->char--; - $this->state = 'data'; - - /* Anything else */ - } else { - /* Append a U+002D HYPHEN-MINUS (-) character and the input - character to the comment token's data. Switch to the comment state. */ - $this->token['data'] .= '-'.$char; - $this->state = 'comment'; - } - } - - private function commentEndState() { - /* Consume the next input character: */ - $this->char++; - $char = $this->char(); - - if($char === '>') { - $this->emitToken($this->token); - $this->state = 'data'; - - } elseif($char === '-') { - $this->token['data'] .= '-'; - - } elseif($this->char === $this->EOF) { - $this->emitToken($this->token); - $this->char--; - $this->state = 'data'; - - } else { - $this->token['data'] .= '--'.$char; - $this->state = 'comment'; - } - } - - private function doctypeState() { - /* Consume the next input character: */ - $this->char++; - $char = $this->char(); - - if(preg_match('/^[\t\n\x0b\x0c ]$/', $char)) { - $this->state = 'beforeDoctypeName'; - - } else { - $this->char--; - $this->state = 'beforeDoctypeName'; - } - } - - private function beforeDoctypeNameState() { - /* Consume the next input character: */ - $this->char++; - $char = $this->char(); - - if(preg_match('/^[\t\n\x0b\x0c ]$/', $char)) { - // Stay in the before DOCTYPE name state. - - } elseif(preg_match('/^[a-z]$/', $char)) { - $this->token = array( - 'name' => strtoupper($char), - 'type' => self::DOCTYPE, - 'error' => true - ); - - $this->state = 'doctypeName'; - - } elseif($char === '>') { - $this->emitToken(array( - 'name' => null, - 'type' => self::DOCTYPE, - 'error' => true - )); - - $this->state = 'data'; - - } elseif($this->char === $this->EOF) { - $this->emitToken(array( - 'name' => null, - 'type' => self::DOCTYPE, - 'error' => true - )); - - $this->char--; - $this->state = 'data'; - - } else { - $this->token = array( - 'name' => $char, - 'type' => self::DOCTYPE, - 'error' => true - ); - - $this->state = 'doctypeName'; - } - } - - private function doctypeNameState() { - /* Consume the next input character: */ - $this->char++; - $char = $this->char(); - - if(preg_match('/^[\t\n\x0b\x0c ]$/', $char)) { - $this->state = 'AfterDoctypeName'; - - } elseif($char === '>') { - $this->emitToken($this->token); - $this->state = 'data'; - - } elseif(preg_match('/^[a-z]$/', $char)) { - $this->token['name'] .= strtoupper($char); - - } elseif($this->char === $this->EOF) { - $this->emitToken($this->token); - $this->char--; - $this->state = 'data'; - - } else { - $this->token['name'] .= $char; - } - - $this->token['error'] = ($this->token['name'] === 'HTML') - ? false - : true; - } - - private function afterDoctypeNameState() { - /* Consume the next input character: */ - $this->char++; - $char = $this->char(); - - if(preg_match('/^[\t\n\x0b\x0c ]$/', $char)) { - // Stay in the DOCTYPE name state. - - } elseif($char === '>') { - $this->emitToken($this->token); - $this->state = 'data'; - - } elseif($this->char === $this->EOF) { - $this->emitToken($this->token); - $this->char--; - $this->state = 'data'; - - } else { - $this->token['error'] = true; - $this->state = 'bogusDoctype'; - } - } - - private function bogusDoctypeState() { - /* Consume the next input character: */ - $this->char++; - $char = $this->char(); - - if($char === '>') { - $this->emitToken($this->token); - $this->state = 'data'; - - } elseif($this->char === $this->EOF) { - $this->emitToken($this->token); - $this->char--; - $this->state = 'data'; - - } else { - // Stay in the bogus DOCTYPE state. - } - } - - private function entity() { - $start = $this->char; - - // This section defines how to consume an entity. This definition is - // used when parsing entities in text and in attributes. - - // The behaviour depends on the identity of the next character (the - // one immediately after the U+0026 AMPERSAND character): - - switch($this->character($this->char + 1)) { - // U+0023 NUMBER SIGN (#) - case '#': - - // The behaviour further depends on the character after the - // U+0023 NUMBER SIGN: - switch($this->character($this->char + 1)) { - // U+0078 LATIN SMALL LETTER X - // U+0058 LATIN CAPITAL LETTER X - case 'x': - case 'X': - // Follow the steps below, but using the range of - // characters U+0030 DIGIT ZERO through to U+0039 DIGIT - // NINE, U+0061 LATIN SMALL LETTER A through to U+0066 - // LATIN SMALL LETTER F, and U+0041 LATIN CAPITAL LETTER - // A, through to U+0046 LATIN CAPITAL LETTER F (in other - // words, 0-9, A-F, a-f). - $char = 1; - $char_class = '0-9A-Fa-f'; - break; - - // Anything else - default: - // Follow the steps below, but using the range of - // characters U+0030 DIGIT ZERO through to U+0039 DIGIT - // NINE (i.e. just 0-9). - $char = 0; - $char_class = '0-9'; - break; - } - - // Consume as many characters as match the range of characters - // given above. - $this->char++; - $e_name = $this->characters($char_class, $this->char + $char + 1); - $entity = $this->character($start, $this->char); - $cond = strlen($e_name) > 0; - - // The rest of the parsing happens bellow. - break; - - // Anything else - default: - // Consume the maximum number of characters possible, with the - // consumed characters case-sensitively matching one of the - // identifiers in the first column of the entities table. - $e_name = $this->characters('0-9A-Za-z;', $this->char + 1); - $len = strlen($e_name); - - for($c = 1; $c <= $len; $c++) { - $id = substr($e_name, 0, $c); - $this->char++; - - if(in_array($id, $this->entities)) { - if ($e_name[$c-1] !== ';') { - if ($c < $len && $e_name[$c] == ';') { - $this->char++; // consume extra semicolon - } - } - $entity = $id; - break; - } - } - - $cond = isset($entity); - // The rest of the parsing happens bellow. - break; - } - - if(!$cond) { - // If no match can be made, then this is a parse error. No - // characters are consumed, and nothing is returned. - $this->char = $start; - return false; - } - - // Return a character token for the character corresponding to the - // entity name (as given by the second column of the entities table). - return html_entity_decode('&'.$entity.';', ENT_QUOTES, 'UTF-8'); - } - - private function emitToken($token) { - $emit = $this->tree->emitToken($token); - - if(is_int($emit)) { - $this->content_model = $emit; - - } elseif($token['type'] === self::ENDTAG) { - $this->content_model = self::PCDATA; - } - } - - private function EOF() { - $this->state = null; - $this->tree->emitToken(array( - 'type' => self::EOF - )); - } -} - -class HTML5TreeConstructer { - public $stack = array(); - - private $phase; - private $mode; - private $dom; - private $foster_parent = null; - private $a_formatting = array(); - - private $head_pointer = null; - private $form_pointer = null; - - private $scoping = array('button','caption','html','marquee','object','table','td','th'); - private $formatting = array('a','b','big','em','font','i','nobr','s','small','strike','strong','tt','u'); - private $special = array('address','area','base','basefont','bgsound', - 'blockquote','body','br','center','col','colgroup','dd','dir','div','dl', - 'dt','embed','fieldset','form','frame','frameset','h1','h2','h3','h4','h5', - 'h6','head','hr','iframe','image','img','input','isindex','li','link', - 'listing','menu','meta','noembed','noframes','noscript','ol','optgroup', - 'option','p','param','plaintext','pre','script','select','spacer','style', - 'tbody','textarea','tfoot','thead','title','tr','ul','wbr'); - - // The different phases. - const INIT_PHASE = 0; - const ROOT_PHASE = 1; - const MAIN_PHASE = 2; - const END_PHASE = 3; - - // The different insertion modes for the main phase. - const BEFOR_HEAD = 0; - const IN_HEAD = 1; - const AFTER_HEAD = 2; - const IN_BODY = 3; - const IN_TABLE = 4; - const IN_CAPTION = 5; - const IN_CGROUP = 6; - const IN_TBODY = 7; - const IN_ROW = 8; - const IN_CELL = 9; - const IN_SELECT = 10; - const AFTER_BODY = 11; - const IN_FRAME = 12; - const AFTR_FRAME = 13; - - // The different types of elements. - const SPECIAL = 0; - const SCOPING = 1; - const FORMATTING = 2; - const PHRASING = 3; - - const MARKER = 0; - - public function __construct() { - $this->phase = self::INIT_PHASE; - $this->mode = self::BEFOR_HEAD; - $this->dom = new DOMDocument; - - $this->dom->encoding = 'UTF-8'; - $this->dom->preserveWhiteSpace = true; - $this->dom->substituteEntities = true; - $this->dom->strictErrorChecking = false; - } - - // Process tag tokens - public function emitToken($token) { - switch($this->phase) { - case self::INIT_PHASE: return $this->initPhase($token); break; - case self::ROOT_PHASE: return $this->rootElementPhase($token); break; - case self::MAIN_PHASE: return $this->mainPhase($token); break; - case self::END_PHASE : return $this->trailingEndPhase($token); break; - } - } - - private function initPhase($token) { - /* Initially, the tree construction stage must handle each token - emitted from the tokenisation stage as follows: */ - - /* A DOCTYPE token that is marked as being in error - A comment token - A start tag token - An end tag token - A character token that is not one of one of U+0009 CHARACTER TABULATION, - U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF), - or U+0020 SPACE - An end-of-file token */ - if((isset($token['error']) && $token['error']) || - $token['type'] === HTML5::COMMENT || - $token['type'] === HTML5::STARTTAG || - $token['type'] === HTML5::ENDTAG || - $token['type'] === HTML5::EOF || - ($token['type'] === HTML5::CHARACTR && isset($token['data']) && - !preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data']))) { - /* This specification does not define how to handle this case. In - particular, user agents may ignore the entirety of this specification - altogether for such documents, and instead invoke special parse modes - with a greater emphasis on backwards compatibility. */ - - $this->phase = self::ROOT_PHASE; - return $this->rootElementPhase($token); - - /* A DOCTYPE token marked as being correct */ - } elseif(isset($token['error']) && !$token['error']) { - /* Append a DocumentType node to the Document node, with the name - attribute set to the name given in the DOCTYPE token (which will be - "HTML"), and the other attributes specific to DocumentType objects - set to null, empty lists, or the empty string as appropriate. */ - $doctype = new DOMDocumentType(null, null, 'HTML'); - - /* Then, switch to the root element phase of the tree construction - stage. */ - $this->phase = self::ROOT_PHASE; - - /* A character token that is one of one of U+0009 CHARACTER TABULATION, - U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF), - or U+0020 SPACE */ - } elseif(isset($token['data']) && preg_match('/^[\t\n\x0b\x0c ]+$/', - $token['data'])) { - /* Append that character to the Document node. */ - $text = $this->dom->createTextNode($token['data']); - $this->dom->appendChild($text); - } - } - - private function rootElementPhase($token) { - /* After the initial phase, as each token is emitted from the tokenisation - stage, it must be processed as described in this section. */ - - /* A DOCTYPE token */ - if($token['type'] === HTML5::DOCTYPE) { - // Parse error. Ignore the token. - - /* A comment token */ - } elseif($token['type'] === HTML5::COMMENT) { - /* Append a Comment node to the Document object with the data - attribute set to the data given in the comment token. */ - $comment = $this->dom->createComment($token['data']); - $this->dom->appendChild($comment); - - /* A character token that is one of one of U+0009 CHARACTER TABULATION, - U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF), - or U+0020 SPACE */ - } elseif($token['type'] === HTML5::CHARACTR && - preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])) { - /* Append that character to the Document node. */ - $text = $this->dom->createTextNode($token['data']); - $this->dom->appendChild($text); - - /* A character token that is not one of U+0009 CHARACTER TABULATION, - U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED - (FF), or U+0020 SPACE - A start tag token - An end tag token - An end-of-file token */ - } elseif(($token['type'] === HTML5::CHARACTR && - !preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])) || - $token['type'] === HTML5::STARTTAG || - $token['type'] === HTML5::ENDTAG || - $token['type'] === HTML5::EOF) { - /* Create an HTMLElement node with the tag name html, in the HTML - namespace. Append it to the Document object. Switch to the main - phase and reprocess the current token. */ - $html = $this->dom->createElement('html'); - $this->dom->appendChild($html); - $this->stack[] = $html; - - $this->phase = self::MAIN_PHASE; - return $this->mainPhase($token); - } - } - - private function mainPhase($token) { - /* Tokens in the main phase must be handled as follows: */ - - /* A DOCTYPE token */ - if($token['type'] === HTML5::DOCTYPE) { - // Parse error. Ignore the token. - - /* A start tag token with the tag name "html" */ - } elseif($token['type'] === HTML5::STARTTAG && $token['name'] === 'html') { - /* If this start tag token was not the first start tag token, then - it is a parse error. */ - - /* For each attribute on the token, check to see if the attribute - is already present on the top element of the stack of open elements. - If it is not, add the attribute and its corresponding value to that - element. */ - foreach($token['attr'] as $attr) { - if(!$this->stack[0]->hasAttribute($attr['name'])) { - $this->stack[0]->setAttribute($attr['name'], $attr['value']); - } - } - - /* An end-of-file token */ - } elseif($token['type'] === HTML5::EOF) { - /* Generate implied end tags. */ - $this->generateImpliedEndTags(); - - /* Anything else. */ - } else { - /* Depends on the insertion mode: */ - switch($this->mode) { - case self::BEFOR_HEAD: return $this->beforeHead($token); break; - case self::IN_HEAD: return $this->inHead($token); break; - case self::AFTER_HEAD: return $this->afterHead($token); break; - case self::IN_BODY: return $this->inBody($token); break; - case self::IN_TABLE: return $this->inTable($token); break; - case self::IN_CAPTION: return $this->inCaption($token); break; - case self::IN_CGROUP: return $this->inColumnGroup($token); break; - case self::IN_TBODY: return $this->inTableBody($token); break; - case self::IN_ROW: return $this->inRow($token); break; - case self::IN_CELL: return $this->inCell($token); break; - case self::IN_SELECT: return $this->inSelect($token); break; - case self::AFTER_BODY: return $this->afterBody($token); break; - case self::IN_FRAME: return $this->inFrameset($token); break; - case self::AFTR_FRAME: return $this->afterFrameset($token); break; - case self::END_PHASE: return $this->trailingEndPhase($token); break; - } - } - } - - private function beforeHead($token) { - /* Handle the token as follows: */ - - /* A character token that is one of one of U+0009 CHARACTER TABULATION, - U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF), - or U+0020 SPACE */ - if($token['type'] === HTML5::CHARACTR && - preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])) { - /* Append the character to the current node. */ - $this->insertText($token['data']); - - /* A comment token */ - } elseif($token['type'] === HTML5::COMMENT) { - /* Append a Comment node to the current node with the data attribute - set to the data given in the comment token. */ - $this->insertComment($token['data']); - - /* A start tag token with the tag name "head" */ - } elseif($token['type'] === HTML5::STARTTAG && $token['name'] === 'head') { - /* Create an element for the token, append the new element to the - current node and push it onto the stack of open elements. */ - $element = $this->insertElement($token); - - /* Set the head element pointer to this new element node. */ - $this->head_pointer = $element; - - /* Change the insertion mode to "in head". */ - $this->mode = self::IN_HEAD; - - /* A start tag token whose tag name is one of: "base", "link", "meta", - "script", "style", "title". Or an end tag with the tag name "html". - Or a character token that is not one of U+0009 CHARACTER TABULATION, - U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF), - or U+0020 SPACE. Or any other start tag token */ - } elseif($token['type'] === HTML5::STARTTAG || - ($token['type'] === HTML5::ENDTAG && $token['name'] === 'html') || - ($token['type'] === HTML5::CHARACTR && !preg_match('/^[\t\n\x0b\x0c ]$/', - $token['data']))) { - /* Act as if a start tag token with the tag name "head" and no - attributes had been seen, then reprocess the current token. */ - $this->beforeHead(array( - 'name' => 'head', - 'type' => HTML5::STARTTAG, - 'attr' => array() - )); - - return $this->inHead($token); - - /* Any other end tag */ - } elseif($token['type'] === HTML5::ENDTAG) { - /* Parse error. Ignore the token. */ - } - } - - private function inHead($token) { - /* Handle the token as follows: */ - - /* A character token that is one of one of U+0009 CHARACTER TABULATION, - U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF), - or U+0020 SPACE. - - THIS DIFFERS FROM THE SPEC: If the current node is either a title, style - or script element, append the character to the current node regardless - of its content. */ - if(($token['type'] === HTML5::CHARACTR && - preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])) || ( - $token['type'] === HTML5::CHARACTR && in_array(end($this->stack)->nodeName, - array('title', 'style', 'script')))) { - /* Append the character to the current node. */ - $this->insertText($token['data']); - - /* A comment token */ - } elseif($token['type'] === HTML5::COMMENT) { - /* Append a Comment node to the current node with the data attribute - set to the data given in the comment token. */ - $this->insertComment($token['data']); - - } elseif($token['type'] === HTML5::ENDTAG && - in_array($token['name'], array('title', 'style', 'script'))) { - array_pop($this->stack); - return HTML5::PCDATA; - - /* A start tag with the tag name "title" */ - } elseif($token['type'] === HTML5::STARTTAG && $token['name'] === 'title') { - /* Create an element for the token and append the new element to the - node pointed to by the head element pointer, or, if that is null - (innerHTML case), to the current node. */ - if($this->head_pointer !== null) { - $element = $this->insertElement($token, false); - $this->head_pointer->appendChild($element); - - } else { - $element = $this->insertElement($token); - } - - /* Switch the tokeniser's content model flag to the RCDATA state. */ - return HTML5::RCDATA; - - /* A start tag with the tag name "style" */ - } elseif($token['type'] === HTML5::STARTTAG && $token['name'] === 'style') { - /* Create an element for the token and append the new element to the - node pointed to by the head element pointer, or, if that is null - (innerHTML case), to the current node. */ - if($this->head_pointer !== null) { - $element = $this->insertElement($token, false); - $this->head_pointer->appendChild($element); - - } else { - $this->insertElement($token); - } - - /* Switch the tokeniser's content model flag to the CDATA state. */ - return HTML5::CDATA; - - /* A start tag with the tag name "script" */ - } elseif($token['type'] === HTML5::STARTTAG && $token['name'] === 'script') { - /* Create an element for the token. */ - $element = $this->insertElement($token, false); - $this->head_pointer->appendChild($element); - - /* Switch the tokeniser's content model flag to the CDATA state. */ - return HTML5::CDATA; - - /* A start tag with the tag name "base", "link", or "meta" */ - } elseif($token['type'] === HTML5::STARTTAG && in_array($token['name'], - array('base', 'link', 'meta'))) { - /* Create an element for the token and append the new element to the - node pointed to by the head element pointer, or, if that is null - (innerHTML case), to the current node. */ - if($this->head_pointer !== null) { - $element = $this->insertElement($token, false); - $this->head_pointer->appendChild($element); - array_pop($this->stack); - - } else { - $this->insertElement($token); - } - - /* An end tag with the tag name "head" */ - } elseif($token['type'] === HTML5::ENDTAG && $token['name'] === 'head') { - /* If the current node is a head element, pop the current node off - the stack of open elements. */ - if($this->head_pointer->isSameNode(end($this->stack))) { - array_pop($this->stack); - - /* Otherwise, this is a parse error. */ - } else { - // k - } - - /* Change the insertion mode to "after head". */ - $this->mode = self::AFTER_HEAD; - - /* A start tag with the tag name "head" or an end tag except "html". */ - } elseif(($token['type'] === HTML5::STARTTAG && $token['name'] === 'head') || - ($token['type'] === HTML5::ENDTAG && $token['name'] !== 'html')) { - // Parse error. Ignore the token. - - /* Anything else */ - } else { - /* If the current node is a head element, act as if an end tag - token with the tag name "head" had been seen. */ - if($this->head_pointer->isSameNode(end($this->stack))) { - $this->inHead(array( - 'name' => 'head', - 'type' => HTML5::ENDTAG - )); - - /* Otherwise, change the insertion mode to "after head". */ - } else { - $this->mode = self::AFTER_HEAD; - } - - /* Then, reprocess the current token. */ - return $this->afterHead($token); - } - } - - private function afterHead($token) { - /* Handle the token as follows: */ - - /* A character token that is one of one of U+0009 CHARACTER TABULATION, - U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF), - or U+0020 SPACE */ - if($token['type'] === HTML5::CHARACTR && - preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])) { - /* Append the character to the current node. */ - $this->insertText($token['data']); - - /* A comment token */ - } elseif($token['type'] === HTML5::COMMENT) { - /* Append a Comment node to the current node with the data attribute - set to the data given in the comment token. */ - $this->insertComment($token['data']); - - /* A start tag token with the tag name "body" */ - } elseif($token['type'] === HTML5::STARTTAG && $token['name'] === 'body') { - /* Insert a body element for the token. */ - $this->insertElement($token); - - /* Change the insertion mode to "in body". */ - $this->mode = self::IN_BODY; - - /* A start tag token with the tag name "frameset" */ - } elseif($token['type'] === HTML5::STARTTAG && $token['name'] === 'frameset') { - /* Insert a frameset element for the token. */ - $this->insertElement($token); - - /* Change the insertion mode to "in frameset". */ - $this->mode = self::IN_FRAME; - - /* A start tag token whose tag name is one of: "base", "link", "meta", - "script", "style", "title" */ - } elseif($token['type'] === HTML5::STARTTAG && in_array($token['name'], - array('base', 'link', 'meta', 'script', 'style', 'title'))) { - /* Parse error. Switch the insertion mode back to "in head" and - reprocess the token. */ - $this->mode = self::IN_HEAD; - return $this->inHead($token); - - /* Anything else */ - } else { - /* Act as if a start tag token with the tag name "body" and no - attributes had been seen, and then reprocess the current token. */ - $this->afterHead(array( - 'name' => 'body', - 'type' => HTML5::STARTTAG, - 'attr' => array() - )); - - return $this->inBody($token); - } - } - - private function inBody($token) { - /* Handle the token as follows: */ - - switch($token['type']) { - /* A character token */ - case HTML5::CHARACTR: - /* Reconstruct the active formatting elements, if any. */ - $this->reconstructActiveFormattingElements(); - - /* Append the token's character to the current node. */ - $this->insertText($token['data']); - break; - - /* A comment token */ - case HTML5::COMMENT: - /* Append a Comment node to the current node with the data - attribute set to the data given in the comment token. */ - $this->insertComment($token['data']); - break; - - case HTML5::STARTTAG: - switch($token['name']) { - /* A start tag token whose tag name is one of: "script", - "style" */ - case 'script': case 'style': - /* Process the token as if the insertion mode had been "in - head". */ - return $this->inHead($token); - break; - - /* A start tag token whose tag name is one of: "base", "link", - "meta", "title" */ - case 'base': case 'link': case 'meta': case 'title': - /* Parse error. Process the token as if the insertion mode - had been "in head". */ - return $this->inHead($token); - break; - - /* A start tag token with the tag name "body" */ - case 'body': - /* Parse error. If the second element on the stack of open - elements is not a body element, or, if the stack of open - elements has only one node on it, then ignore the token. - (innerHTML case) */ - if(count($this->stack) === 1 || $this->stack[1]->nodeName !== 'body') { - // Ignore - - /* Otherwise, for each attribute on the token, check to see - if the attribute is already present on the body element (the - second element) on the stack of open elements. If it is not, - add the attribute and its corresponding value to that - element. */ - } else { - foreach($token['attr'] as $attr) { - if(!$this->stack[1]->hasAttribute($attr['name'])) { - $this->stack[1]->setAttribute($attr['name'], $attr['value']); - } - } - } - break; - - /* A start tag whose tag name is one of: "address", - "blockquote", "center", "dir", "div", "dl", "fieldset", - "listing", "menu", "ol", "p", "ul" */ - case 'address': case 'blockquote': case 'center': case 'dir': - case 'div': case 'dl': case 'fieldset': case 'listing': - case 'menu': case 'ol': case 'p': case 'ul': - /* If the stack of open elements has a p element in scope, - then act as if an end tag with the tag name p had been - seen. */ - if($this->elementInScope('p')) { - $this->emitToken(array( - 'name' => 'p', - 'type' => HTML5::ENDTAG - )); - } - - /* Insert an HTML element for the token. */ - $this->insertElement($token); - break; - - /* A start tag whose tag name is "form" */ - case 'form': - /* If the form element pointer is not null, ignore the - token with a parse error. */ - if($this->form_pointer !== null) { - // Ignore. - - /* Otherwise: */ - } else { - /* If the stack of open elements has a p element in - scope, then act as if an end tag with the tag name p - had been seen. */ - if($this->elementInScope('p')) { - $this->emitToken(array( - 'name' => 'p', - 'type' => HTML5::ENDTAG - )); - } - - /* Insert an HTML element for the token, and set the - form element pointer to point to the element created. */ - $element = $this->insertElement($token); - $this->form_pointer = $element; - } - break; - - /* A start tag whose tag name is "li", "dd" or "dt" */ - case 'li': case 'dd': case 'dt': - /* If the stack of open elements has a p element in scope, - then act as if an end tag with the tag name p had been - seen. */ - if($this->elementInScope('p')) { - $this->emitToken(array( - 'name' => 'p', - 'type' => HTML5::ENDTAG - )); - } - - $stack_length = count($this->stack) - 1; - - for($n = $stack_length; 0 <= $n; $n--) { - /* 1. Initialise node to be the current node (the - bottommost node of the stack). */ - $stop = false; - $node = $this->stack[$n]; - $cat = $this->getElementCategory($node->tagName); - - /* 2. If node is an li, dd or dt element, then pop all - the nodes from the current node up to node, including - node, then stop this algorithm. */ - if($token['name'] === $node->tagName || ($token['name'] !== 'li' - && ($node->tagName === 'dd' || $node->tagName === 'dt'))) { - for($x = $stack_length; $x >= $n ; $x--) { - array_pop($this->stack); - } - - break; - } - - /* 3. If node is not in the formatting category, and is - not in the phrasing category, and is not an address or - div element, then stop this algorithm. */ - if($cat !== self::FORMATTING && $cat !== self::PHRASING && - $node->tagName !== 'address' && $node->tagName !== 'div') { - break; - } - } - - /* Finally, insert an HTML element with the same tag - name as the token's. */ - $this->insertElement($token); - break; - - /* A start tag token whose tag name is "plaintext" */ - case 'plaintext': - /* If the stack of open elements has a p element in scope, - then act as if an end tag with the tag name p had been - seen. */ - if($this->elementInScope('p')) { - $this->emitToken(array( - 'name' => 'p', - 'type' => HTML5::ENDTAG - )); - } - - /* Insert an HTML element for the token. */ - $this->insertElement($token); - - return HTML5::PLAINTEXT; - break; - - /* A start tag whose tag name is one of: "h1", "h2", "h3", "h4", - "h5", "h6" */ - case 'h1': case 'h2': case 'h3': case 'h4': case 'h5': case 'h6': - /* If the stack of open elements has a p element in scope, - then act as if an end tag with the tag name p had been seen. */ - if($this->elementInScope('p')) { - $this->emitToken(array( - 'name' => 'p', - 'type' => HTML5::ENDTAG - )); - } - - /* If the stack of open elements has in scope an element whose - tag name is one of "h1", "h2", "h3", "h4", "h5", or "h6", then - this is a parse error; pop elements from the stack until an - element with one of those tag names has been popped from the - stack. */ - while($this->elementInScope(array('h1', 'h2', 'h3', 'h4', 'h5', 'h6'))) { - array_pop($this->stack); - } - - /* Insert an HTML element for the token. */ - $this->insertElement($token); - break; - - /* A start tag whose tag name is "a" */ - case 'a': - /* If the list of active formatting elements contains - an element whose tag name is "a" between the end of the - list and the last marker on the list (or the start of - the list if there is no marker on the list), then this - is a parse error; act as if an end tag with the tag name - "a" had been seen, then remove that element from the list - of active formatting elements and the stack of open - elements if the end tag didn't already remove it (it - might not have if the element is not in table scope). */ - $leng = count($this->a_formatting); - - for($n = $leng - 1; $n >= 0; $n--) { - if($this->a_formatting[$n] === self::MARKER) { - break; - - } elseif($this->a_formatting[$n]->nodeName === 'a') { - $this->emitToken(array( - 'name' => 'a', - 'type' => HTML5::ENDTAG - )); - break; - } - } - - /* Reconstruct the active formatting elements, if any. */ - $this->reconstructActiveFormattingElements(); - - /* Insert an HTML element for the token. */ - $el = $this->insertElement($token); - - /* Add that element to the list of active formatting - elements. */ - $this->a_formatting[] = $el; - break; - - /* A start tag whose tag name is one of: "b", "big", "em", "font", - "i", "nobr", "s", "small", "strike", "strong", "tt", "u" */ - case 'b': case 'big': case 'em': case 'font': case 'i': - case 'nobr': case 's': case 'small': case 'strike': - case 'strong': case 'tt': case 'u': - /* Reconstruct the active formatting elements, if any. */ - $this->reconstructActiveFormattingElements(); - - /* Insert an HTML element for the token. */ - $el = $this->insertElement($token); - - /* Add that element to the list of active formatting - elements. */ - $this->a_formatting[] = $el; - break; - - /* A start tag token whose tag name is "button" */ - case 'button': - /* If the stack of open elements has a button element in scope, - then this is a parse error; act as if an end tag with the tag - name "button" had been seen, then reprocess the token. (We don't - do that. Unnecessary.) */ - if($this->elementInScope('button')) { - $this->inBody(array( - 'name' => 'button', - 'type' => HTML5::ENDTAG - )); - } - - /* Reconstruct the active formatting elements, if any. */ - $this->reconstructActiveFormattingElements(); - - /* Insert an HTML element for the token. */ - $this->insertElement($token); - - /* Insert a marker at the end of the list of active - formatting elements. */ - $this->a_formatting[] = self::MARKER; - break; - - /* A start tag token whose tag name is one of: "marquee", "object" */ - case 'marquee': case 'object': - /* Reconstruct the active formatting elements, if any. */ - $this->reconstructActiveFormattingElements(); - - /* Insert an HTML element for the token. */ - $this->insertElement($token); - - /* Insert a marker at the end of the list of active - formatting elements. */ - $this->a_formatting[] = self::MARKER; - break; - - /* A start tag token whose tag name is "xmp" */ - case 'xmp': - /* Reconstruct the active formatting elements, if any. */ - $this->reconstructActiveFormattingElements(); - - /* Insert an HTML element for the token. */ - $this->insertElement($token); - - /* Switch the content model flag to the CDATA state. */ - return HTML5::CDATA; - break; - - /* A start tag whose tag name is "table" */ - case 'table': - /* If the stack of open elements has a p element in scope, - then act as if an end tag with the tag name p had been seen. */ - if($this->elementInScope('p')) { - $this->emitToken(array( - 'name' => 'p', - 'type' => HTML5::ENDTAG - )); - } - - /* Insert an HTML element for the token. */ - $this->insertElement($token); - - /* Change the insertion mode to "in table". */ - $this->mode = self::IN_TABLE; - break; - - /* A start tag whose tag name is one of: "area", "basefont", - "bgsound", "br", "embed", "img", "param", "spacer", "wbr" */ - case 'area': case 'basefont': case 'bgsound': case 'br': - case 'embed': case 'img': case 'param': case 'spacer': - case 'wbr': - /* Reconstruct the active formatting elements, if any. */ - $this->reconstructActiveFormattingElements(); - - /* Insert an HTML element for the token. */ - $this->insertElement($token); - - /* Immediately pop the current node off the stack of open elements. */ - array_pop($this->stack); - break; - - /* A start tag whose tag name is "hr" */ - case 'hr': - /* If the stack of open elements has a p element in scope, - then act as if an end tag with the tag name p had been seen. */ - if($this->elementInScope('p')) { - $this->emitToken(array( - 'name' => 'p', - 'type' => HTML5::ENDTAG - )); - } - - /* Insert an HTML element for the token. */ - $this->insertElement($token); - - /* Immediately pop the current node off the stack of open elements. */ - array_pop($this->stack); - break; - - /* A start tag whose tag name is "image" */ - case 'image': - /* Parse error. Change the token's tag name to "img" and - reprocess it. (Don't ask.) */ - $token['name'] = 'img'; - return $this->inBody($token); - break; - - /* A start tag whose tag name is "input" */ - case 'input': - /* Reconstruct the active formatting elements, if any. */ - $this->reconstructActiveFormattingElements(); - - /* Insert an input element for the token. */ - $element = $this->insertElement($token, false); - - /* If the form element pointer is not null, then associate the - input element with the form element pointed to by the form - element pointer. */ - $this->form_pointer !== null - ? $this->form_pointer->appendChild($element) - : end($this->stack)->appendChild($element); - - /* Pop that input element off the stack of open elements. */ - array_pop($this->stack); - break; - - /* A start tag whose tag name is "isindex" */ - case 'isindex': - /* Parse error. */ - // w/e - - /* If the form element pointer is not null, - then ignore the token. */ - if($this->form_pointer === null) { - /* Act as if a start tag token with the tag name "form" had - been seen. */ - $this->inBody(array( - 'name' => 'body', - 'type' => HTML5::STARTTAG, - 'attr' => array() - )); - - /* Act as if a start tag token with the tag name "hr" had - been seen. */ - $this->inBody(array( - 'name' => 'hr', - 'type' => HTML5::STARTTAG, - 'attr' => array() - )); - - /* Act as if a start tag token with the tag name "p" had - been seen. */ - $this->inBody(array( - 'name' => 'p', - 'type' => HTML5::STARTTAG, - 'attr' => array() - )); - - /* Act as if a start tag token with the tag name "label" - had been seen. */ - $this->inBody(array( - 'name' => 'label', - 'type' => HTML5::STARTTAG, - 'attr' => array() - )); - - /* Act as if a stream of character tokens had been seen. */ - $this->insertText('This is a searchable index. '. - 'Insert your search keywords here: '); - - /* Act as if a start tag token with the tag name "input" - had been seen, with all the attributes from the "isindex" - token, except with the "name" attribute set to the value - "isindex" (ignoring any explicit "name" attribute). */ - $attr = $token['attr']; - $attr[] = array('name' => 'name', 'value' => 'isindex'); - - $this->inBody(array( - 'name' => 'input', - 'type' => HTML5::STARTTAG, - 'attr' => $attr - )); - - /* Act as if a stream of character tokens had been seen - (see below for what they should say). */ - $this->insertText('This is a searchable index. '. - 'Insert your search keywords here: '); - - /* Act as if an end tag token with the tag name "label" - had been seen. */ - $this->inBody(array( - 'name' => 'label', - 'type' => HTML5::ENDTAG - )); - - /* Act as if an end tag token with the tag name "p" had - been seen. */ - $this->inBody(array( - 'name' => 'p', - 'type' => HTML5::ENDTAG - )); - - /* Act as if a start tag token with the tag name "hr" had - been seen. */ - $this->inBody(array( - 'name' => 'hr', - 'type' => HTML5::ENDTAG - )); - - /* Act as if an end tag token with the tag name "form" had - been seen. */ - $this->inBody(array( - 'name' => 'form', - 'type' => HTML5::ENDTAG - )); - } - break; - - /* A start tag whose tag name is "textarea" */ - case 'textarea': - $this->insertElement($token); - - /* Switch the tokeniser's content model flag to the - RCDATA state. */ - return HTML5::RCDATA; - break; - - /* A start tag whose tag name is one of: "iframe", "noembed", - "noframes" */ - case 'iframe': case 'noembed': case 'noframes': - $this->insertElement($token); - - /* Switch the tokeniser's content model flag to the CDATA state. */ - return HTML5::CDATA; - break; - - /* A start tag whose tag name is "select" */ - case 'select': - /* Reconstruct the active formatting elements, if any. */ - $this->reconstructActiveFormattingElements(); - - /* Insert an HTML element for the token. */ - $this->insertElement($token); - - /* Change the insertion mode to "in select". */ - $this->mode = self::IN_SELECT; - break; - - /* A start or end tag whose tag name is one of: "caption", "col", - "colgroup", "frame", "frameset", "head", "option", "optgroup", - "tbody", "td", "tfoot", "th", "thead", "tr". */ - case 'caption': case 'col': case 'colgroup': case 'frame': - case 'frameset': case 'head': case 'option': case 'optgroup': - case 'tbody': case 'td': case 'tfoot': case 'th': case 'thead': - case 'tr': - // Parse error. Ignore the token. - break; - - /* A start or end tag whose tag name is one of: "event-source", - "section", "nav", "article", "aside", "header", "footer", - "datagrid", "command" */ - case 'event-source': case 'section': case 'nav': case 'article': - case 'aside': case 'header': case 'footer': case 'datagrid': - case 'command': - // Work in progress! - break; - - /* A start tag token not covered by the previous entries */ - default: - /* Reconstruct the active formatting elements, if any. */ - $this->reconstructActiveFormattingElements(); - - $this->insertElement($token, true, true); - break; - } - break; - - case HTML5::ENDTAG: - switch($token['name']) { - /* An end tag with the tag name "body" */ - case 'body': - /* If the second element in the stack of open elements is - not a body element, this is a parse error. Ignore the token. - (innerHTML case) */ - if(count($this->stack) < 2 || $this->stack[1]->nodeName !== 'body') { - // Ignore. - - /* If the current node is not the body element, then this - is a parse error. */ - } elseif(end($this->stack)->nodeName !== 'body') { - // Parse error. - } - - /* Change the insertion mode to "after body". */ - $this->mode = self::AFTER_BODY; - break; - - /* An end tag with the tag name "html" */ - case 'html': - /* Act as if an end tag with tag name "body" had been seen, - then, if that token wasn't ignored, reprocess the current - token. */ - $this->inBody(array( - 'name' => 'body', - 'type' => HTML5::ENDTAG - )); - - return $this->afterBody($token); - break; - - /* An end tag whose tag name is one of: "address", "blockquote", - "center", "dir", "div", "dl", "fieldset", "listing", "menu", - "ol", "pre", "ul" */ - case 'address': case 'blockquote': case 'center': case 'dir': - case 'div': case 'dl': case 'fieldset': case 'listing': - case 'menu': case 'ol': case 'pre': case 'ul': - /* If the stack of open elements has an element in scope - with the same tag name as that of the token, then generate - implied end tags. */ - if($this->elementInScope($token['name'])) { - $this->generateImpliedEndTags(); - - /* Now, if the current node is not an element with - the same tag name as that of the token, then this - is a parse error. */ - // w/e - - /* If the stack of open elements has an element in - scope with the same tag name as that of the token, - then pop elements from this stack until an element - with that tag name has been popped from the stack. */ - for($n = count($this->stack) - 1; $n >= 0; $n--) { - if($this->stack[$n]->nodeName === $token['name']) { - $n = -1; - } - - array_pop($this->stack); - } - } - break; - - /* An end tag whose tag name is "form" */ - case 'form': - /* If the stack of open elements has an element in scope - with the same tag name as that of the token, then generate - implied end tags. */ - if($this->elementInScope($token['name'])) { - $this->generateImpliedEndTags(); - - } - - if(end($this->stack)->nodeName !== $token['name']) { - /* Now, if the current node is not an element with the - same tag name as that of the token, then this is a parse - error. */ - // w/e - - } else { - /* Otherwise, if the current node is an element with - the same tag name as that of the token pop that element - from the stack. */ - array_pop($this->stack); - } - - /* In any case, set the form element pointer to null. */ - $this->form_pointer = null; - break; - - /* An end tag whose tag name is "p" */ - case 'p': - /* If the stack of open elements has a p element in scope, - then generate implied end tags, except for p elements. */ - if($this->elementInScope('p')) { - $this->generateImpliedEndTags(array('p')); - - /* If the current node is not a p element, then this is - a parse error. */ - // k - - /* If the stack of open elements has a p element in - scope, then pop elements from this stack until the stack - no longer has a p element in scope. */ - for($n = count($this->stack) - 1; $n >= 0; $n--) { - if($this->elementInScope('p')) { - array_pop($this->stack); - - } else { - break; - } - } - } - break; - - /* An end tag whose tag name is "dd", "dt", or "li" */ - case 'dd': case 'dt': case 'li': - /* If the stack of open elements has an element in scope - whose tag name matches the tag name of the token, then - generate implied end tags, except for elements with the - same tag name as the token. */ - if($this->elementInScope($token['name'])) { - $this->generateImpliedEndTags(array($token['name'])); - - /* If the current node is not an element with the same - tag name as the token, then this is a parse error. */ - // w/e - - /* If the stack of open elements has an element in scope - whose tag name matches the tag name of the token, then - pop elements from this stack until an element with that - tag name has been popped from the stack. */ - for($n = count($this->stack) - 1; $n >= 0; $n--) { - if($this->stack[$n]->nodeName === $token['name']) { - $n = -1; - } - - array_pop($this->stack); - } - } - break; - - /* An end tag whose tag name is one of: "h1", "h2", "h3", "h4", - "h5", "h6" */ - case 'h1': case 'h2': case 'h3': case 'h4': case 'h5': case 'h6': - $elements = array('h1', 'h2', 'h3', 'h4', 'h5', 'h6'); - - /* If the stack of open elements has in scope an element whose - tag name is one of "h1", "h2", "h3", "h4", "h5", or "h6", then - generate implied end tags. */ - if($this->elementInScope($elements)) { - $this->generateImpliedEndTags(); - - /* Now, if the current node is not an element with the same - tag name as that of the token, then this is a parse error. */ - // w/e - - /* If the stack of open elements has in scope an element - whose tag name is one of "h1", "h2", "h3", "h4", "h5", or - "h6", then pop elements from the stack until an element - with one of those tag names has been popped from the stack. */ - while($this->elementInScope($elements)) { - array_pop($this->stack); - } - } - break; - - /* An end tag whose tag name is one of: "a", "b", "big", "em", - "font", "i", "nobr", "s", "small", "strike", "strong", "tt", "u" */ - case 'a': case 'b': case 'big': case 'em': case 'font': - case 'i': case 'nobr': case 's': case 'small': case 'strike': - case 'strong': case 'tt': case 'u': - /* 1. Let the formatting element be the last element in - the list of active formatting elements that: - * is between the end of the list and the last scope - marker in the list, if any, or the start of the list - otherwise, and - * has the same tag name as the token. - */ - while(true) { - for($a = count($this->a_formatting) - 1; $a >= 0; $a--) { - if($this->a_formatting[$a] === self::MARKER) { - break; - - } elseif($this->a_formatting[$a]->tagName === $token['name']) { - $formatting_element = $this->a_formatting[$a]; - $in_stack = in_array($formatting_element, $this->stack, true); - $fe_af_pos = $a; - break; - } - } - - /* If there is no such node, or, if that node is - also in the stack of open elements but the element - is not in scope, then this is a parse error. Abort - these steps. The token is ignored. */ - if(!isset($formatting_element) || ($in_stack && - !$this->elementInScope($token['name']))) { - break; - - /* Otherwise, if there is such a node, but that node - is not in the stack of open elements, then this is a - parse error; remove the element from the list, and - abort these steps. */ - } elseif(isset($formatting_element) && !$in_stack) { - unset($this->a_formatting[$fe_af_pos]); - $this->a_formatting = array_merge($this->a_formatting); - break; - } - - /* 2. Let the furthest block be the topmost node in the - stack of open elements that is lower in the stack - than the formatting element, and is not an element in - the phrasing or formatting categories. There might - not be one. */ - $fe_s_pos = array_search($formatting_element, $this->stack, true); - $length = count($this->stack); - - for($s = $fe_s_pos + 1; $s < $length; $s++) { - $category = $this->getElementCategory($this->stack[$s]->nodeName); - - if($category !== self::PHRASING && $category !== self::FORMATTING) { - $furthest_block = $this->stack[$s]; - } - } - - /* 3. If there is no furthest block, then the UA must - skip the subsequent steps and instead just pop all - the nodes from the bottom of the stack of open - elements, from the current node up to the formatting - element, and remove the formatting element from the - list of active formatting elements. */ - if(!isset($furthest_block)) { - for($n = $length - 1; $n >= $fe_s_pos; $n--) { - array_pop($this->stack); - } - - unset($this->a_formatting[$fe_af_pos]); - $this->a_formatting = array_merge($this->a_formatting); - break; - } - - /* 4. Let the common ancestor be the element - immediately above the formatting element in the stack - of open elements. */ - $common_ancestor = $this->stack[$fe_s_pos - 1]; - - /* 5. If the furthest block has a parent node, then - remove the furthest block from its parent node. */ - if($furthest_block->parentNode !== null) { - $furthest_block->parentNode->removeChild($furthest_block); - } - - /* 6. Let a bookmark note the position of the - formatting element in the list of active formatting - elements relative to the elements on either side - of it in the list. */ - $bookmark = $fe_af_pos; - - /* 7. Let node and last node be the furthest block. - Follow these steps: */ - $node = $furthest_block; - $last_node = $furthest_block; - - while(true) { - for($n = array_search($node, $this->stack, true) - 1; $n >= 0; $n--) { - /* 7.1 Let node be the element immediately - prior to node in the stack of open elements. */ - $node = $this->stack[$n]; - - /* 7.2 If node is not in the list of active - formatting elements, then remove node from - the stack of open elements and then go back - to step 1. */ - if(!in_array($node, $this->a_formatting, true)) { - unset($this->stack[$n]); - $this->stack = array_merge($this->stack); - - } else { - break; - } - } - - /* 7.3 Otherwise, if node is the formatting - element, then go to the next step in the overall - algorithm. */ - if($node === $formatting_element) { - break; - - /* 7.4 Otherwise, if last node is the furthest - block, then move the aforementioned bookmark to - be immediately after the node in the list of - active formatting elements. */ - } elseif($last_node === $furthest_block) { - $bookmark = array_search($node, $this->a_formatting, true) + 1; - } - - /* 7.5 If node has any children, perform a - shallow clone of node, replace the entry for - node in the list of active formatting elements - with an entry for the clone, replace the entry - for node in the stack of open elements with an - entry for the clone, and let node be the clone. */ - if($node->hasChildNodes()) { - $clone = $node->cloneNode(); - $s_pos = array_search($node, $this->stack, true); - $a_pos = array_search($node, $this->a_formatting, true); - - $this->stack[$s_pos] = $clone; - $this->a_formatting[$a_pos] = $clone; - $node = $clone; - } - - /* 7.6 Insert last node into node, first removing - it from its previous parent node if any. */ - if($last_node->parentNode !== null) { - $last_node->parentNode->removeChild($last_node); - } - - $node->appendChild($last_node); - - /* 7.7 Let last node be node. */ - $last_node = $node; - } - - /* 8. Insert whatever last node ended up being in - the previous step into the common ancestor node, - first removing it from its previous parent node if - any. */ - if($last_node->parentNode !== null) { - $last_node->parentNode->removeChild($last_node); - } - - $common_ancestor->appendChild($last_node); - - /* 9. Perform a shallow clone of the formatting - element. */ - $clone = $formatting_element->cloneNode(); - - /* 10. Take all of the child nodes of the furthest - block and append them to the clone created in the - last step. */ - while($furthest_block->hasChildNodes()) { - $child = $furthest_block->firstChild; - $furthest_block->removeChild($child); - $clone->appendChild($child); - } - - /* 11. Append that clone to the furthest block. */ - $furthest_block->appendChild($clone); - - /* 12. Remove the formatting element from the list - of active formatting elements, and insert the clone - into the list of active formatting elements at the - position of the aforementioned bookmark. */ - $fe_af_pos = array_search($formatting_element, $this->a_formatting, true); - unset($this->a_formatting[$fe_af_pos]); - $this->a_formatting = array_merge($this->a_formatting); - - $af_part1 = array_slice($this->a_formatting, 0, $bookmark - 1); - $af_part2 = array_slice($this->a_formatting, $bookmark, count($this->a_formatting)); - $this->a_formatting = array_merge($af_part1, array($clone), $af_part2); - - /* 13. Remove the formatting element from the stack - of open elements, and insert the clone into the stack - of open elements immediately after (i.e. in a more - deeply nested position than) the position of the - furthest block in that stack. */ - $fe_s_pos = array_search($formatting_element, $this->stack, true); - $fb_s_pos = array_search($furthest_block, $this->stack, true); - unset($this->stack[$fe_s_pos]); - - $s_part1 = array_slice($this->stack, 0, $fb_s_pos); - $s_part2 = array_slice($this->stack, $fb_s_pos + 1, count($this->stack)); - $this->stack = array_merge($s_part1, array($clone), $s_part2); - - /* 14. Jump back to step 1 in this series of steps. */ - unset($formatting_element, $fe_af_pos, $fe_s_pos, $furthest_block); - } - break; - - /* An end tag token whose tag name is one of: "button", - "marquee", "object" */ - case 'button': case 'marquee': case 'object': - /* If the stack of open elements has an element in scope whose - tag name matches the tag name of the token, then generate implied - tags. */ - if($this->elementInScope($token['name'])) { - $this->generateImpliedEndTags(); - - /* Now, if the current node is not an element with the same - tag name as the token, then this is a parse error. */ - // k - - /* Now, if the stack of open elements has an element in scope - whose tag name matches the tag name of the token, then pop - elements from the stack until that element has been popped from - the stack, and clear the list of active formatting elements up - to the last marker. */ - for($n = count($this->stack) - 1; $n >= 0; $n--) { - if($this->stack[$n]->nodeName === $token['name']) { - $n = -1; - } - - array_pop($this->stack); - } - - $marker = end(array_keys($this->a_formatting, self::MARKER, true)); - - for($n = count($this->a_formatting) - 1; $n > $marker; $n--) { - array_pop($this->a_formatting); - } - } - break; - - /* Or an end tag whose tag name is one of: "area", "basefont", - "bgsound", "br", "embed", "hr", "iframe", "image", "img", - "input", "isindex", "noembed", "noframes", "param", "select", - "spacer", "table", "textarea", "wbr" */ - case 'area': case 'basefont': case 'bgsound': case 'br': - case 'embed': case 'hr': case 'iframe': case 'image': - case 'img': case 'input': case 'isindex': case 'noembed': - case 'noframes': case 'param': case 'select': case 'spacer': - case 'table': case 'textarea': case 'wbr': - // Parse error. Ignore the token. - break; - - /* An end tag token not covered by the previous entries */ - default: - for($n = count($this->stack) - 1; $n >= 0; $n--) { - /* Initialise node to be the current node (the bottommost - node of the stack). */ - $node = end($this->stack); - - /* If node has the same tag name as the end tag token, - then: */ - if($token['name'] === $node->nodeName) { - /* Generate implied end tags. */ - $this->generateImpliedEndTags(); - - /* If the tag name of the end tag token does not - match the tag name of the current node, this is a - parse error. */ - // k - - /* Pop all the nodes from the current node up to - node, including node, then stop this algorithm. */ - for($x = count($this->stack) - $n; $x >= $n; $x--) { - array_pop($this->stack); - } - - } else { - $category = $this->getElementCategory($node); - - if($category !== self::SPECIAL && $category !== self::SCOPING) { - /* Otherwise, if node is in neither the formatting - category nor the phrasing category, then this is a - parse error. Stop this algorithm. The end tag token - is ignored. */ - return false; - } - } - } - break; - } - break; - } - } - - private function inTable($token) { - $clear = array('html', 'table'); - - /* A character token that is one of one of U+0009 CHARACTER TABULATION, - U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF), - or U+0020 SPACE */ - if($token['type'] === HTML5::CHARACTR && - preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])) { - /* Append the character to the current node. */ - $text = $this->dom->createTextNode($token['data']); - end($this->stack)->appendChild($text); - - /* A comment token */ - } elseif($token['type'] === HTML5::COMMENT) { - /* Append a Comment node to the current node with the data - attribute set to the data given in the comment token. */ - $comment = $this->dom->createComment($token['data']); - end($this->stack)->appendChild($comment); - - /* A start tag whose tag name is "caption" */ - } elseif($token['type'] === HTML5::STARTTAG && - $token['name'] === 'caption') { - /* Clear the stack back to a table context. */ - $this->clearStackToTableContext($clear); - - /* Insert a marker at the end of the list of active - formatting elements. */ - $this->a_formatting[] = self::MARKER; - - /* Insert an HTML element for the token, then switch the - insertion mode to "in caption". */ - $this->insertElement($token); - $this->mode = self::IN_CAPTION; - - /* A start tag whose tag name is "colgroup" */ - } elseif($token['type'] === HTML5::STARTTAG && - $token['name'] === 'colgroup') { - /* Clear the stack back to a table context. */ - $this->clearStackToTableContext($clear); - - /* Insert an HTML element for the token, then switch the - insertion mode to "in column group". */ - $this->insertElement($token); - $this->mode = self::IN_CGROUP; - - /* A start tag whose tag name is "col" */ - } elseif($token['type'] === HTML5::STARTTAG && - $token['name'] === 'col') { - $this->inTable(array( - 'name' => 'colgroup', - 'type' => HTML5::STARTTAG, - 'attr' => array() - )); - - $this->inColumnGroup($token); - - /* A start tag whose tag name is one of: "tbody", "tfoot", "thead" */ - } elseif($token['type'] === HTML5::STARTTAG && in_array($token['name'], - array('tbody', 'tfoot', 'thead'))) { - /* Clear the stack back to a table context. */ - $this->clearStackToTableContext($clear); - - /* Insert an HTML element for the token, then switch the insertion - mode to "in table body". */ - $this->insertElement($token); - $this->mode = self::IN_TBODY; - - /* A start tag whose tag name is one of: "td", "th", "tr" */ - } elseif($token['type'] === HTML5::STARTTAG && - in_array($token['name'], array('td', 'th', 'tr'))) { - /* Act as if a start tag token with the tag name "tbody" had been - seen, then reprocess the current token. */ - $this->inTable(array( - 'name' => 'tbody', - 'type' => HTML5::STARTTAG, - 'attr' => array() - )); - - return $this->inTableBody($token); - - /* A start tag whose tag name is "table" */ - } elseif($token['type'] === HTML5::STARTTAG && - $token['name'] === 'table') { - /* Parse error. Act as if an end tag token with the tag name "table" - had been seen, then, if that token wasn't ignored, reprocess the - current token. */ - $this->inTable(array( - 'name' => 'table', - 'type' => HTML5::ENDTAG - )); - - return $this->mainPhase($token); - - /* An end tag whose tag name is "table" */ - } elseif($token['type'] === HTML5::ENDTAG && - $token['name'] === 'table') { - /* If the stack of open elements does not have an element in table - scope with the same tag name as the token, this is a parse error. - Ignore the token. (innerHTML case) */ - if(!$this->elementInScope($token['name'], true)) { - return false; - - /* Otherwise: */ - } else { - /* Generate implied end tags. */ - $this->generateImpliedEndTags(); - - /* Now, if the current node is not a table element, then this - is a parse error. */ - // w/e - - /* Pop elements from this stack until a table element has been - popped from the stack. */ - while(true) { - $current = end($this->stack)->nodeName; - array_pop($this->stack); - - if($current === 'table') { - break; - } - } - - /* Reset the insertion mode appropriately. */ - $this->resetInsertionMode(); - } - - /* An end tag whose tag name is one of: "body", "caption", "col", - "colgroup", "html", "tbody", "td", "tfoot", "th", "thead", "tr" */ - } elseif($token['type'] === HTML5::ENDTAG && in_array($token['name'], - array('body', 'caption', 'col', 'colgroup', 'html', 'tbody', 'td', - 'tfoot', 'th', 'thead', 'tr'))) { - // Parse error. Ignore the token. - - /* Anything else */ - } else { - /* Parse error. Process the token as if the insertion mode was "in - body", with the following exception: */ - - /* If the current node is a table, tbody, tfoot, thead, or tr - element, then, whenever a node would be inserted into the current - node, it must instead be inserted into the foster parent element. */ - if(in_array(end($this->stack)->nodeName, - array('table', 'tbody', 'tfoot', 'thead', 'tr'))) { - /* The foster parent element is the parent element of the last - table element in the stack of open elements, if there is a - table element and it has such a parent element. If there is no - table element in the stack of open elements (innerHTML case), - then the foster parent element is the first element in the - stack of open elements (the html element). Otherwise, if there - is a table element in the stack of open elements, but the last - table element in the stack of open elements has no parent, or - its parent node is not an element, then the foster parent - element is the element before the last table element in the - stack of open elements. */ - for($n = count($this->stack) - 1; $n >= 0; $n--) { - if($this->stack[$n]->nodeName === 'table') { - $table = $this->stack[$n]; - break; - } - } - - if(isset($table) && $table->parentNode !== null) { - $this->foster_parent = $table->parentNode; - - } elseif(!isset($table)) { - $this->foster_parent = $this->stack[0]; - - } elseif(isset($table) && ($table->parentNode === null || - $table->parentNode->nodeType !== XML_ELEMENT_NODE)) { - $this->foster_parent = $this->stack[$n - 1]; - } - } - - $this->inBody($token); - } - } - - private function inCaption($token) { - /* An end tag whose tag name is "caption" */ - if($token['type'] === HTML5::ENDTAG && $token['name'] === 'caption') { - /* If the stack of open elements does not have an element in table - scope with the same tag name as the token, this is a parse error. - Ignore the token. (innerHTML case) */ - if(!$this->elementInScope($token['name'], true)) { - // Ignore - - /* Otherwise: */ - } else { - /* Generate implied end tags. */ - $this->generateImpliedEndTags(); - - /* Now, if the current node is not a caption element, then this - is a parse error. */ - // w/e - - /* Pop elements from this stack until a caption element has - been popped from the stack. */ - while(true) { - $node = end($this->stack)->nodeName; - array_pop($this->stack); - - if($node === 'caption') { - break; - } - } - - /* Clear the list of active formatting elements up to the last - marker. */ - $this->clearTheActiveFormattingElementsUpToTheLastMarker(); - - /* Switch the insertion mode to "in table". */ - $this->mode = self::IN_TABLE; - } - - /* A start tag whose tag name is one of: "caption", "col", "colgroup", - "tbody", "td", "tfoot", "th", "thead", "tr", or an end tag whose tag - name is "table" */ - } elseif(($token['type'] === HTML5::STARTTAG && in_array($token['name'], - array('caption', 'col', 'colgroup', 'tbody', 'td', 'tfoot', 'th', - 'thead', 'tr'))) || ($token['type'] === HTML5::ENDTAG && - $token['name'] === 'table')) { - /* Parse error. Act as if an end tag with the tag name "caption" - had been seen, then, if that token wasn't ignored, reprocess the - current token. */ - $this->inCaption(array( - 'name' => 'caption', - 'type' => HTML5::ENDTAG - )); - - return $this->inTable($token); - - /* An end tag whose tag name is one of: "body", "col", "colgroup", - "html", "tbody", "td", "tfoot", "th", "thead", "tr" */ - } elseif($token['type'] === HTML5::ENDTAG && in_array($token['name'], - array('body', 'col', 'colgroup', 'html', 'tbody', 'tfoot', 'th', - 'thead', 'tr'))) { - // Parse error. Ignore the token. - - /* Anything else */ - } else { - /* Process the token as if the insertion mode was "in body". */ - $this->inBody($token); - } - } - - private function inColumnGroup($token) { - /* A character token that is one of one of U+0009 CHARACTER TABULATION, - U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF), - or U+0020 SPACE */ - if($token['type'] === HTML5::CHARACTR && - preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])) { - /* Append the character to the current node. */ - $text = $this->dom->createTextNode($token['data']); - end($this->stack)->appendChild($text); - - /* A comment token */ - } elseif($token['type'] === HTML5::COMMENT) { - /* Append a Comment node to the current node with the data - attribute set to the data given in the comment token. */ - $comment = $this->dom->createComment($token['data']); - end($this->stack)->appendChild($comment); - - /* A start tag whose tag name is "col" */ - } elseif($token['type'] === HTML5::STARTTAG && $token['name'] === 'col') { - /* Insert a col element for the token. Immediately pop the current - node off the stack of open elements. */ - $this->insertElement($token); - array_pop($this->stack); - - /* An end tag whose tag name is "colgroup" */ - } elseif($token['type'] === HTML5::ENDTAG && - $token['name'] === 'colgroup') { - /* If the current node is the root html element, then this is a - parse error, ignore the token. (innerHTML case) */ - if(end($this->stack)->nodeName === 'html') { - // Ignore - - /* Otherwise, pop the current node (which will be a colgroup - element) from the stack of open elements. Switch the insertion - mode to "in table". */ - } else { - array_pop($this->stack); - $this->mode = self::IN_TABLE; - } - - /* An end tag whose tag name is "col" */ - } elseif($token['type'] === HTML5::ENDTAG && $token['name'] === 'col') { - /* Parse error. Ignore the token. */ - - /* Anything else */ - } else { - /* Act as if an end tag with the tag name "colgroup" had been seen, - and then, if that token wasn't ignored, reprocess the current token. */ - $this->inColumnGroup(array( - 'name' => 'colgroup', - 'type' => HTML5::ENDTAG - )); - - return $this->inTable($token); - } - } - - private function inTableBody($token) { - $clear = array('tbody', 'tfoot', 'thead', 'html'); - - /* A start tag whose tag name is "tr" */ - if($token['type'] === HTML5::STARTTAG && $token['name'] === 'tr') { - /* Clear the stack back to a table body context. */ - $this->clearStackToTableContext($clear); - - /* Insert a tr element for the token, then switch the insertion - mode to "in row". */ - $this->insertElement($token); - $this->mode = self::IN_ROW; - - /* A start tag whose tag name is one of: "th", "td" */ - } elseif($token['type'] === HTML5::STARTTAG && - ($token['name'] === 'th' || $token['name'] === 'td')) { - /* Parse error. Act as if a start tag with the tag name "tr" had - been seen, then reprocess the current token. */ - $this->inTableBody(array( - 'name' => 'tr', - 'type' => HTML5::STARTTAG, - 'attr' => array() - )); - - return $this->inRow($token); - - /* An end tag whose tag name is one of: "tbody", "tfoot", "thead" */ - } elseif($token['type'] === HTML5::ENDTAG && - in_array($token['name'], array('tbody', 'tfoot', 'thead'))) { - /* If the stack of open elements does not have an element in table - scope with the same tag name as the token, this is a parse error. - Ignore the token. */ - if(!$this->elementInScope($token['name'], true)) { - // Ignore - - /* Otherwise: */ - } else { - /* Clear the stack back to a table body context. */ - $this->clearStackToTableContext($clear); - - /* Pop the current node from the stack of open elements. Switch - the insertion mode to "in table". */ - array_pop($this->stack); - $this->mode = self::IN_TABLE; - } - - /* A start tag whose tag name is one of: "caption", "col", "colgroup", - "tbody", "tfoot", "thead", or an end tag whose tag name is "table" */ - } elseif(($token['type'] === HTML5::STARTTAG && in_array($token['name'], - array('caption', 'col', 'colgroup', 'tbody', 'tfoor', 'thead'))) || - ($token['type'] === HTML5::STARTTAG && $token['name'] === 'table')) { - /* If the stack of open elements does not have a tbody, thead, or - tfoot element in table scope, this is a parse error. Ignore the - token. (innerHTML case) */ - if(!$this->elementInScope(array('tbody', 'thead', 'tfoot'), true)) { - // Ignore. - - /* Otherwise: */ - } else { - /* Clear the stack back to a table body context. */ - $this->clearStackToTableContext($clear); - - /* Act as if an end tag with the same tag name as the current - node ("tbody", "tfoot", or "thead") had been seen, then - reprocess the current token. */ - $this->inTableBody(array( - 'name' => end($this->stack)->nodeName, - 'type' => HTML5::ENDTAG - )); - - return $this->mainPhase($token); - } - - /* An end tag whose tag name is one of: "body", "caption", "col", - "colgroup", "html", "td", "th", "tr" */ - } elseif($token['type'] === HTML5::ENDTAG && in_array($token['name'], - array('body', 'caption', 'col', 'colgroup', 'html', 'td', 'th', 'tr'))) { - /* Parse error. Ignore the token. */ - - /* Anything else */ - } else { - /* Process the token as if the insertion mode was "in table". */ - $this->inTable($token); - } - } - - private function inRow($token) { - $clear = array('tr', 'html'); - - /* A start tag whose tag name is one of: "th", "td" */ - if($token['type'] === HTML5::STARTTAG && - ($token['name'] === 'th' || $token['name'] === 'td')) { - /* Clear the stack back to a table row context. */ - $this->clearStackToTableContext($clear); - - /* Insert an HTML element for the token, then switch the insertion - mode to "in cell". */ - $this->insertElement($token); - $this->mode = self::IN_CELL; - - /* Insert a marker at the end of the list of active formatting - elements. */ - $this->a_formatting[] = self::MARKER; - - /* An end tag whose tag name is "tr" */ - } elseif($token['type'] === HTML5::ENDTAG && $token['name'] === 'tr') { - /* If the stack of open elements does not have an element in table - scope with the same tag name as the token, this is a parse error. - Ignore the token. (innerHTML case) */ - if(!$this->elementInScope($token['name'], true)) { - // Ignore. - - /* Otherwise: */ - } else { - /* Clear the stack back to a table row context. */ - $this->clearStackToTableContext($clear); - - /* Pop the current node (which will be a tr element) from the - stack of open elements. Switch the insertion mode to "in table - body". */ - array_pop($this->stack); - $this->mode = self::IN_TBODY; - } - - /* A start tag whose tag name is one of: "caption", "col", "colgroup", - "tbody", "tfoot", "thead", "tr" or an end tag whose tag name is "table" */ - } elseif($token['type'] === HTML5::STARTTAG && in_array($token['name'], - array('caption', 'col', 'colgroup', 'tbody', 'tfoot', 'thead', 'tr'))) { - /* Act as if an end tag with the tag name "tr" had been seen, then, - if that token wasn't ignored, reprocess the current token. */ - $this->inRow(array( - 'name' => 'tr', - 'type' => HTML5::ENDTAG - )); - - return $this->inCell($token); - - /* An end tag whose tag name is one of: "tbody", "tfoot", "thead" */ - } elseif($token['type'] === HTML5::ENDTAG && - in_array($token['name'], array('tbody', 'tfoot', 'thead'))) { - /* If the stack of open elements does not have an element in table - scope with the same tag name as the token, this is a parse error. - Ignore the token. */ - if(!$this->elementInScope($token['name'], true)) { - // Ignore. - - /* Otherwise: */ - } else { - /* Otherwise, act as if an end tag with the tag name "tr" had - been seen, then reprocess the current token. */ - $this->inRow(array( - 'name' => 'tr', - 'type' => HTML5::ENDTAG - )); - - return $this->inCell($token); - } - - /* An end tag whose tag name is one of: "body", "caption", "col", - "colgroup", "html", "td", "th" */ - } elseif($token['type'] === HTML5::ENDTAG && in_array($token['name'], - array('body', 'caption', 'col', 'colgroup', 'html', 'td', 'th', 'tr'))) { - /* Parse error. Ignore the token. */ - - /* Anything else */ - } else { - /* Process the token as if the insertion mode was "in table". */ - $this->inTable($token); - } - } - - private function inCell($token) { - /* An end tag whose tag name is one of: "td", "th" */ - if($token['type'] === HTML5::ENDTAG && - ($token['name'] === 'td' || $token['name'] === 'th')) { - /* If the stack of open elements does not have an element in table - scope with the same tag name as that of the token, then this is a - parse error and the token must be ignored. */ - if(!$this->elementInScope($token['name'], true)) { - // Ignore. - - /* Otherwise: */ - } else { - /* Generate implied end tags, except for elements with the same - tag name as the token. */ - $this->generateImpliedEndTags(array($token['name'])); - - /* Now, if the current node is not an element with the same tag - name as the token, then this is a parse error. */ - // k - - /* Pop elements from this stack until an element with the same - tag name as the token has been popped from the stack. */ - while(true) { - $node = end($this->stack)->nodeName; - array_pop($this->stack); - - if($node === $token['name']) { - break; - } - } - - /* Clear the list of active formatting elements up to the last - marker. */ - $this->clearTheActiveFormattingElementsUpToTheLastMarker(); - - /* Switch the insertion mode to "in row". (The current node - will be a tr element at this point.) */ - $this->mode = self::IN_ROW; - } - - /* A start tag whose tag name is one of: "caption", "col", "colgroup", - "tbody", "td", "tfoot", "th", "thead", "tr" */ - } elseif($token['type'] === HTML5::STARTTAG && in_array($token['name'], - array('caption', 'col', 'colgroup', 'tbody', 'td', 'tfoot', 'th', - 'thead', 'tr'))) { - /* If the stack of open elements does not have a td or th element - in table scope, then this is a parse error; ignore the token. - (innerHTML case) */ - if(!$this->elementInScope(array('td', 'th'), true)) { - // Ignore. - - /* Otherwise, close the cell (see below) and reprocess the current - token. */ - } else { - $this->closeCell(); - return $this->inRow($token); - } - - /* A start tag whose tag name is one of: "caption", "col", "colgroup", - "tbody", "td", "tfoot", "th", "thead", "tr" */ - } elseif($token['type'] === HTML5::STARTTAG && in_array($token['name'], - array('caption', 'col', 'colgroup', 'tbody', 'td', 'tfoot', 'th', - 'thead', 'tr'))) { - /* If the stack of open elements does not have a td or th element - in table scope, then this is a parse error; ignore the token. - (innerHTML case) */ - if(!$this->elementInScope(array('td', 'th'), true)) { - // Ignore. - - /* Otherwise, close the cell (see below) and reprocess the current - token. */ - } else { - $this->closeCell(); - return $this->inRow($token); - } - - /* An end tag whose tag name is one of: "body", "caption", "col", - "colgroup", "html" */ - } elseif($token['type'] === HTML5::ENDTAG && in_array($token['name'], - array('body', 'caption', 'col', 'colgroup', 'html'))) { - /* Parse error. Ignore the token. */ - - /* An end tag whose tag name is one of: "table", "tbody", "tfoot", - "thead", "tr" */ - } elseif($token['type'] === HTML5::ENDTAG && in_array($token['name'], - array('table', 'tbody', 'tfoot', 'thead', 'tr'))) { - /* If the stack of open elements does not have an element in table - scope with the same tag name as that of the token (which can only - happen for "tbody", "tfoot" and "thead", or, in the innerHTML case), - then this is a parse error and the token must be ignored. */ - if(!$this->elementInScope($token['name'], true)) { - // Ignore. - - /* Otherwise, close the cell (see below) and reprocess the current - token. */ - } else { - $this->closeCell(); - return $this->inRow($token); - } - - /* Anything else */ - } else { - /* Process the token as if the insertion mode was "in body". */ - $this->inBody($token); - } - } - - private function inSelect($token) { - /* Handle the token as follows: */ - - /* A character token */ - if($token['type'] === HTML5::CHARACTR) { - /* Append the token's character to the current node. */ - $this->insertText($token['data']); - - /* A comment token */ - } elseif($token['type'] === HTML5::COMMENT) { - /* Append a Comment node to the current node with the data - attribute set to the data given in the comment token. */ - $this->insertComment($token['data']); - - /* A start tag token whose tag name is "option" */ - } elseif($token['type'] === HTML5::STARTTAG && - $token['name'] === 'option') { - /* If the current node is an option element, act as if an end tag - with the tag name "option" had been seen. */ - if(end($this->stack)->nodeName === 'option') { - $this->inSelect(array( - 'name' => 'option', - 'type' => HTML5::ENDTAG - )); - } - - /* Insert an HTML element for the token. */ - $this->insertElement($token); - - /* A start tag token whose tag name is "optgroup" */ - } elseif($token['type'] === HTML5::STARTTAG && - $token['name'] === 'optgroup') { - /* If the current node is an option element, act as if an end tag - with the tag name "option" had been seen. */ - if(end($this->stack)->nodeName === 'option') { - $this->inSelect(array( - 'name' => 'option', - 'type' => HTML5::ENDTAG - )); - } - - /* If the current node is an optgroup element, act as if an end tag - with the tag name "optgroup" had been seen. */ - if(end($this->stack)->nodeName === 'optgroup') { - $this->inSelect(array( - 'name' => 'optgroup', - 'type' => HTML5::ENDTAG - )); - } - - /* Insert an HTML element for the token. */ - $this->insertElement($token); - - /* An end tag token whose tag name is "optgroup" */ - } elseif($token['type'] === HTML5::ENDTAG && - $token['name'] === 'optgroup') { - /* First, if the current node is an option element, and the node - immediately before it in the stack of open elements is an optgroup - element, then act as if an end tag with the tag name "option" had - been seen. */ - $elements_in_stack = count($this->stack); - - if($this->stack[$elements_in_stack - 1]->nodeName === 'option' && - $this->stack[$elements_in_stack - 2]->nodeName === 'optgroup') { - $this->inSelect(array( - 'name' => 'option', - 'type' => HTML5::ENDTAG - )); - } - - /* If the current node is an optgroup element, then pop that node - from the stack of open elements. Otherwise, this is a parse error, - ignore the token. */ - if($this->stack[$elements_in_stack - 1] === 'optgroup') { - array_pop($this->stack); - } - - /* An end tag token whose tag name is "option" */ - } elseif($token['type'] === HTML5::ENDTAG && - $token['name'] === 'option') { - /* If the current node is an option element, then pop that node - from the stack of open elements. Otherwise, this is a parse error, - ignore the token. */ - if(end($this->stack)->nodeName === 'option') { - array_pop($this->stack); - } - - /* An end tag whose tag name is "select" */ - } elseif($token['type'] === HTML5::ENDTAG && - $token['name'] === 'select') { - /* If the stack of open elements does not have an element in table - scope with the same tag name as the token, this is a parse error. - Ignore the token. (innerHTML case) */ - if(!$this->elementInScope($token['name'], true)) { - // w/e - - /* Otherwise: */ - } else { - /* Pop elements from the stack of open elements until a select - element has been popped from the stack. */ - while(true) { - $current = end($this->stack)->nodeName; - array_pop($this->stack); - - if($current === 'select') { - break; - } - } - - /* Reset the insertion mode appropriately. */ - $this->resetInsertionMode(); - } - - /* A start tag whose tag name is "select" */ - } elseif($token['name'] === 'select' && - $token['type'] === HTML5::STARTTAG) { - /* Parse error. Act as if the token had been an end tag with the - tag name "select" instead. */ - $this->inSelect(array( - 'name' => 'select', - 'type' => HTML5::ENDTAG - )); - - /* An end tag whose tag name is one of: "caption", "table", "tbody", - "tfoot", "thead", "tr", "td", "th" */ - } elseif(in_array($token['name'], array('caption', 'table', 'tbody', - 'tfoot', 'thead', 'tr', 'td', 'th')) && $token['type'] === HTML5::ENDTAG) { - /* Parse error. */ - // w/e - - /* If the stack of open elements has an element in table scope with - the same tag name as that of the token, then act as if an end tag - with the tag name "select" had been seen, and reprocess the token. - Otherwise, ignore the token. */ - if($this->elementInScope($token['name'], true)) { - $this->inSelect(array( - 'name' => 'select', - 'type' => HTML5::ENDTAG - )); - - $this->mainPhase($token); - } - - /* Anything else */ - } else { - /* Parse error. Ignore the token. */ - } - } - - private function afterBody($token) { - /* Handle the token as follows: */ - - /* A character token that is one of one of U+0009 CHARACTER TABULATION, - U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF), - or U+0020 SPACE */ - if($token['type'] === HTML5::CHARACTR && - preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])) { - /* Process the token as it would be processed if the insertion mode - was "in body". */ - $this->inBody($token); - - /* A comment token */ - } elseif($token['type'] === HTML5::COMMENT) { - /* Append a Comment node to the first element in the stack of open - elements (the html element), with the data attribute set to the - data given in the comment token. */ - $comment = $this->dom->createComment($token['data']); - $this->stack[0]->appendChild($comment); - - /* An end tag with the tag name "html" */ - } elseif($token['type'] === HTML5::ENDTAG && $token['name'] === 'html') { - /* If the parser was originally created in order to handle the - setting of an element's innerHTML attribute, this is a parse error; - ignore the token. (The element will be an html element in this - case.) (innerHTML case) */ - - /* Otherwise, switch to the trailing end phase. */ - $this->phase = self::END_PHASE; - - /* Anything else */ - } else { - /* Parse error. Set the insertion mode to "in body" and reprocess - the token. */ - $this->mode = self::IN_BODY; - return $this->inBody($token); - } - } - - private function inFrameset($token) { - /* Handle the token as follows: */ - - /* A character token that is one of one of U+0009 CHARACTER TABULATION, - U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF), - U+000D CARRIAGE RETURN (CR), or U+0020 SPACE */ - if($token['type'] === HTML5::CHARACTR && - preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])) { - /* Append the character to the current node. */ - $this->insertText($token['data']); - - /* A comment token */ - } elseif($token['type'] === HTML5::COMMENT) { - /* Append a Comment node to the current node with the data - attribute set to the data given in the comment token. */ - $this->insertComment($token['data']); - - /* A start tag with the tag name "frameset" */ - } elseif($token['name'] === 'frameset' && - $token['type'] === HTML5::STARTTAG) { - $this->insertElement($token); - - /* An end tag with the tag name "frameset" */ - } elseif($token['name'] === 'frameset' && - $token['type'] === HTML5::ENDTAG) { - /* If the current node is the root html element, then this is a - parse error; ignore the token. (innerHTML case) */ - if(end($this->stack)->nodeName === 'html') { - // Ignore - - } else { - /* Otherwise, pop the current node from the stack of open - elements. */ - array_pop($this->stack); - - /* If the parser was not originally created in order to handle - the setting of an element's innerHTML attribute (innerHTML case), - and the current node is no longer a frameset element, then change - the insertion mode to "after frameset". */ - $this->mode = self::AFTR_FRAME; - } - - /* A start tag with the tag name "frame" */ - } elseif($token['name'] === 'frame' && - $token['type'] === HTML5::STARTTAG) { - /* Insert an HTML element for the token. */ - $this->insertElement($token); - - /* Immediately pop the current node off the stack of open elements. */ - array_pop($this->stack); - - /* A start tag with the tag name "noframes" */ - } elseif($token['name'] === 'noframes' && - $token['type'] === HTML5::STARTTAG) { - /* Process the token as if the insertion mode had been "in body". */ - $this->inBody($token); - - /* Anything else */ - } else { - /* Parse error. Ignore the token. */ - } - } - - private function afterFrameset($token) { - /* Handle the token as follows: */ - - /* A character token that is one of one of U+0009 CHARACTER TABULATION, - U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF), - U+000D CARRIAGE RETURN (CR), or U+0020 SPACE */ - if($token['type'] === HTML5::CHARACTR && - preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])) { - /* Append the character to the current node. */ - $this->insertText($token['data']); - - /* A comment token */ - } elseif($token['type'] === HTML5::COMMENT) { - /* Append a Comment node to the current node with the data - attribute set to the data given in the comment token. */ - $this->insertComment($token['data']); - - /* An end tag with the tag name "html" */ - } elseif($token['name'] === 'html' && - $token['type'] === HTML5::ENDTAG) { - /* Switch to the trailing end phase. */ - $this->phase = self::END_PHASE; - - /* A start tag with the tag name "noframes" */ - } elseif($token['name'] === 'noframes' && - $token['type'] === HTML5::STARTTAG) { - /* Process the token as if the insertion mode had been "in body". */ - $this->inBody($token); - - /* Anything else */ - } else { - /* Parse error. Ignore the token. */ - } - } - - private function trailingEndPhase($token) { - /* After the main phase, as each token is emitted from the tokenisation - stage, it must be processed as described in this section. */ - - /* A DOCTYPE token */ - if($token['type'] === HTML5::DOCTYPE) { - // Parse error. Ignore the token. - - /* A comment token */ - } elseif($token['type'] === HTML5::COMMENT) { - /* Append a Comment node to the Document object with the data - attribute set to the data given in the comment token. */ - $comment = $this->dom->createComment($token['data']); - $this->dom->appendChild($comment); - - /* A character token that is one of one of U+0009 CHARACTER TABULATION, - U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF), - or U+0020 SPACE */ - } elseif($token['type'] === HTML5::CHARACTR && - preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])) { - /* Process the token as it would be processed in the main phase. */ - $this->mainPhase($token); - - /* A character token that is not one of U+0009 CHARACTER TABULATION, - U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF), - or U+0020 SPACE. Or a start tag token. Or an end tag token. */ - } elseif(($token['type'] === HTML5::CHARACTR && - preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])) || - $token['type'] === HTML5::STARTTAG || $token['type'] === HTML5::ENDTAG) { - /* Parse error. Switch back to the main phase and reprocess the - token. */ - $this->phase = self::MAIN_PHASE; - return $this->mainPhase($token); - - /* An end-of-file token */ - } elseif($token['type'] === HTML5::EOF) { - /* OMG DONE!! */ - } - } - - private function insertElement($token, $append = true, $check = false) { - // Proprietary workaround for libxml2's limitations with tag names - if ($check) { - // Slightly modified HTML5 tag-name modification, - // removing anything that's not an ASCII letter, digit, or hyphen - $token['name'] = preg_replace('/[^a-z0-9-]/i', '', $token['name']); - // Remove leading hyphens and numbers - $token['name'] = ltrim($token['name'], '-0..9'); - // In theory, this should ever be needed, but just in case - if ($token['name'] === '') $token['name'] = 'span'; // arbitrary generic choice - } - - $el = $this->dom->createElement($token['name']); - - foreach($token['attr'] as $attr) { - if(!$el->hasAttribute($attr['name'])) { - $el->setAttribute($attr['name'], $attr['value']); - } - } - - $this->appendToRealParent($el); - $this->stack[] = $el; - - return $el; - } - - private function insertText($data) { - $text = $this->dom->createTextNode($data); - $this->appendToRealParent($text); - } - - private function insertComment($data) { - $comment = $this->dom->createComment($data); - $this->appendToRealParent($comment); - } - - private function appendToRealParent($node) { - if($this->foster_parent === null) { - end($this->stack)->appendChild($node); - - } elseif($this->foster_parent !== null) { - /* If the foster parent element is the parent element of the - last table element in the stack of open elements, then the new - node must be inserted immediately before the last table element - in the stack of open elements in the foster parent element; - otherwise, the new node must be appended to the foster parent - element. */ - for($n = count($this->stack) - 1; $n >= 0; $n--) { - if($this->stack[$n]->nodeName === 'table' && - $this->stack[$n]->parentNode !== null) { - $table = $this->stack[$n]; - break; - } - } - - if(isset($table) && $this->foster_parent->isSameNode($table->parentNode)) - $this->foster_parent->insertBefore($node, $table); - else - $this->foster_parent->appendChild($node); - - $this->foster_parent = null; - } - } - - private function elementInScope($el, $table = false) { - if(is_array($el)) { - foreach($el as $element) { - if($this->elementInScope($element, $table)) { - return true; - } - } - - return false; - } - - $leng = count($this->stack); - - for($n = 0; $n < $leng; $n++) { - /* 1. Initialise node to be the current node (the bottommost node of - the stack). */ - $node = $this->stack[$leng - 1 - $n]; - - if($node->tagName === $el) { - /* 2. If node is the target node, terminate in a match state. */ - return true; - - } elseif($node->tagName === 'table') { - /* 3. Otherwise, if node is a table element, terminate in a failure - state. */ - return false; - - } elseif($table === true && in_array($node->tagName, array('caption', 'td', - 'th', 'button', 'marquee', 'object'))) { - /* 4. Otherwise, if the algorithm is the "has an element in scope" - variant (rather than the "has an element in table scope" variant), - and node is one of the following, terminate in a failure state. */ - return false; - - } elseif($node === $node->ownerDocument->documentElement) { - /* 5. Otherwise, if node is an html element (root element), terminate - in a failure state. (This can only happen if the node is the topmost - node of the stack of open elements, and prevents the next step from - being invoked if there are no more elements in the stack.) */ - return false; - } - - /* Otherwise, set node to the previous entry in the stack of open - elements and return to step 2. (This will never fail, since the loop - will always terminate in the previous step if the top of the stack - is reached.) */ - } - } - - private function reconstructActiveFormattingElements() { - /* 1. If there are no entries in the list of active formatting elements, - then there is nothing to reconstruct; stop this algorithm. */ - $formatting_elements = count($this->a_formatting); - - if($formatting_elements === 0) { - return false; - } - - /* 3. Let entry be the last (most recently added) element in the list - of active formatting elements. */ - $entry = end($this->a_formatting); - - /* 2. If the last (most recently added) entry in the list of active - formatting elements is a marker, or if it is an element that is in the - stack of open elements, then there is nothing to reconstruct; stop this - algorithm. */ - if($entry === self::MARKER || in_array($entry, $this->stack, true)) { - return false; - } - - for($a = $formatting_elements - 1; $a >= 0; true) { - /* 4. If there are no entries before entry in the list of active - formatting elements, then jump to step 8. */ - if($a === 0) { - $step_seven = false; - break; - } - - /* 5. Let entry be the entry one earlier than entry in the list of - active formatting elements. */ - $a--; - $entry = $this->a_formatting[$a]; - - /* 6. If entry is neither a marker nor an element that is also in - thetack of open elements, go to step 4. */ - if($entry === self::MARKER || in_array($entry, $this->stack, true)) { - break; - } - } - - while(true) { - /* 7. Let entry be the element one later than entry in the list of - active formatting elements. */ - if(isset($step_seven) && $step_seven === true) { - $a++; - $entry = $this->a_formatting[$a]; - } - - /* 8. Perform a shallow clone of the element entry to obtain clone. */ - $clone = $entry->cloneNode(); - - /* 9. Append clone to the current node and push it onto the stack - of open elements so that it is the new current node. */ - end($this->stack)->appendChild($clone); - $this->stack[] = $clone; - - /* 10. Replace the entry for entry in the list with an entry for - clone. */ - $this->a_formatting[$a] = $clone; - - /* 11. If the entry for clone in the list of active formatting - elements is not the last entry in the list, return to step 7. */ - if(end($this->a_formatting) !== $clone) { - $step_seven = true; - } else { - break; - } - } - } - - private function clearTheActiveFormattingElementsUpToTheLastMarker() { - /* When the steps below require the UA to clear the list of active - formatting elements up to the last marker, the UA must perform the - following steps: */ - - while(true) { - /* 1. Let entry be the last (most recently added) entry in the list - of active formatting elements. */ - $entry = end($this->a_formatting); - - /* 2. Remove entry from the list of active formatting elements. */ - array_pop($this->a_formatting); - - /* 3. If entry was a marker, then stop the algorithm at this point. - The list has been cleared up to the last marker. */ - if($entry === self::MARKER) { - break; - } - } - } - - private function generateImpliedEndTags($exclude = array()) { - /* When the steps below require the UA to generate implied end tags, - then, if the current node is a dd element, a dt element, an li element, - a p element, a td element, a th element, or a tr element, the UA must - act as if an end tag with the respective tag name had been seen and - then generate implied end tags again. */ - $node = end($this->stack); - $elements = array_diff(array('dd', 'dt', 'li', 'p', 'td', 'th', 'tr'), $exclude); - - while(in_array(end($this->stack)->nodeName, $elements)) { - array_pop($this->stack); - } - } - - private function getElementCategory($node) { - $name = $node->tagName; - if(in_array($name, $this->special)) - return self::SPECIAL; - - elseif(in_array($name, $this->scoping)) - return self::SCOPING; - - elseif(in_array($name, $this->formatting)) - return self::FORMATTING; - - else - return self::PHRASING; - } - - private function clearStackToTableContext($elements) { - /* When the steps above require the UA to clear the stack back to a - table context, it means that the UA must, while the current node is not - a table element or an html element, pop elements from the stack of open - elements. If this causes any elements to be popped from the stack, then - this is a parse error. */ - while(true) { - $node = end($this->stack)->nodeName; - - if(in_array($node, $elements)) { - break; - } else { - array_pop($this->stack); - } - } - } - - private function resetInsertionMode() { - /* 1. Let last be false. */ - $last = false; - $leng = count($this->stack); - - for($n = $leng - 1; $n >= 0; $n--) { - /* 2. Let node be the last node in the stack of open elements. */ - $node = $this->stack[$n]; - - /* 3. If node is the first node in the stack of open elements, then - set last to true. If the element whose innerHTML attribute is being - set is neither a td element nor a th element, then set node to the - element whose innerHTML attribute is being set. (innerHTML case) */ - if($this->stack[0]->isSameNode($node)) { - $last = true; - } - - /* 4. If node is a select element, then switch the insertion mode to - "in select" and abort these steps. (innerHTML case) */ - if($node->nodeName === 'select') { - $this->mode = self::IN_SELECT; - break; - - /* 5. If node is a td or th element, then switch the insertion mode - to "in cell" and abort these steps. */ - } elseif($node->nodeName === 'td' || $node->nodeName === 'th') { - $this->mode = self::IN_CELL; - break; - - /* 6. If node is a tr element, then switch the insertion mode to - "in row" and abort these steps. */ - } elseif($node->nodeName === 'tr') { - $this->mode = self::IN_ROW; - break; - - /* 7. If node is a tbody, thead, or tfoot element, then switch the - insertion mode to "in table body" and abort these steps. */ - } elseif(in_array($node->nodeName, array('tbody', 'thead', 'tfoot'))) { - $this->mode = self::IN_TBODY; - break; - - /* 8. If node is a caption element, then switch the insertion mode - to "in caption" and abort these steps. */ - } elseif($node->nodeName === 'caption') { - $this->mode = self::IN_CAPTION; - break; - - /* 9. If node is a colgroup element, then switch the insertion mode - to "in column group" and abort these steps. (innerHTML case) */ - } elseif($node->nodeName === 'colgroup') { - $this->mode = self::IN_CGROUP; - break; - - /* 10. If node is a table element, then switch the insertion mode - to "in table" and abort these steps. */ - } elseif($node->nodeName === 'table') { - $this->mode = self::IN_TABLE; - break; - - /* 11. If node is a head element, then switch the insertion mode - to "in body" ("in body"! not "in head"!) and abort these steps. - (innerHTML case) */ - } elseif($node->nodeName === 'head') { - $this->mode = self::IN_BODY; - break; - - /* 12. If node is a body element, then switch the insertion mode to - "in body" and abort these steps. */ - } elseif($node->nodeName === 'body') { - $this->mode = self::IN_BODY; - break; - - /* 13. If node is a frameset element, then switch the insertion - mode to "in frameset" and abort these steps. (innerHTML case) */ - } elseif($node->nodeName === 'frameset') { - $this->mode = self::IN_FRAME; - break; - - /* 14. If node is an html element, then: if the head element - pointer is null, switch the insertion mode to "before head", - otherwise, switch the insertion mode to "after head". In either - case, abort these steps. (innerHTML case) */ - } elseif($node->nodeName === 'html') { - $this->mode = ($this->head_pointer === null) - ? self::BEFOR_HEAD - : self::AFTER_HEAD; - - break; - - /* 15. If last is true, then set the insertion mode to "in body" - and abort these steps. (innerHTML case) */ - } elseif($last) { - $this->mode = self::IN_BODY; - break; - } - } - } - - private function closeCell() { - /* If the stack of open elements has a td or th element in table scope, - then act as if an end tag token with that tag name had been seen. */ - foreach(array('td', 'th') as $cell) { - if($this->elementInScope($cell, true)) { - $this->inCell(array( - 'name' => $cell, - 'type' => HTML5::ENDTAG - )); - - break; - } - } - } - - public function save() { - return $this->dom; - } -} -?> diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/PercentEncoder.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/PercentEncoder.php deleted file mode 100644 index a8ad230d..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/PercentEncoder.php +++ /dev/null @@ -1,98 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Class that handles operations involving percent-encoding in URIs. - * - * @warning - * Be careful when reusing instances of PercentEncoder. The object - * you use for normalize() SHOULD NOT be used for encode(), or - * vice-versa. - */ -class HTMLPurifier_PercentEncoder -{ - - /** - * Reserved characters to preserve when using encode(). - */ - protected $preserve = array(); - - /** - * String of characters that should be preserved while using encode(). - */ - public function __construct($preserve = false) { - // unreserved letters, ought to const-ify - for ($i = 48; $i <= 57; $i++) $this->preserve[$i] = true; // digits - for ($i = 65; $i <= 90; $i++) $this->preserve[$i] = true; // upper-case - for ($i = 97; $i <= 122; $i++) $this->preserve[$i] = true; // lower-case - $this->preserve[45] = true; // Dash - - $this->preserve[46] = true; // Period . - $this->preserve[95] = true; // Underscore _ - $this->preserve[126]= true; // Tilde ~ - - // extra letters not to escape - if ($preserve !== false) { - for ($i = 0, $c = strlen($preserve); $i < $c; $i++) { - $this->preserve[ord($preserve[$i])] = true; - } - } - } - - /** - * Our replacement for urlencode, it encodes all non-reserved characters, - * as well as any extra characters that were instructed to be preserved. - * @note - * Assumes that the string has already been normalized, making any - * and all percent escape sequences valid. Percents will not be - * re-escaped, regardless of their status in $preserve - * @param $string String to be encoded - * @return Encoded string. - */ - public function encode($string) { - $ret = ''; - for ($i = 0, $c = strlen($string); $i < $c; $i++) { - if ($string[$i] !== '%' && !isset($this->preserve[$int = ord($string[$i])]) ) { - $ret .= '%' . sprintf('%02X', $int); - } else { - $ret .= $string[$i]; - } - } - return $ret; - } - - /** - * Fix up percent-encoding by decoding unreserved characters and normalizing. - * @warning This function is affected by $preserve, even though the - * usual desired behavior is for this not to preserve those - * characters. Be careful when reusing instances of PercentEncoder! - * @param $string String to normalize - */ - public function normalize($string) { - if ($string == '') return ''; - $parts = explode('%', $string); - $ret = array_shift($parts); - foreach ($parts as $part) { - $length = strlen($part); - if ($length < 2) { - $ret .= '%25' . $part; - continue; - } - $encoding = substr($part, 0, 2); - $text = substr($part, 2); - if (!ctype_xdigit($encoding)) { - $ret .= '%25' . $part; - continue; - } - $int = hexdec($encoding); - if (isset($this->preserve[$int])) { - $ret .= chr($int) . $text; - continue; - } - $encoding = strtoupper($encoding); - $ret .= '%' . $encoding . $text; - } - return $ret; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Printer.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Printer.php deleted file mode 100644 index a0d4a0fd..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Printer.php +++ /dev/null @@ -1,176 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -// OUT OF DATE, NEEDS UPDATING! -// USE XMLWRITER! - -class HTMLPurifier_Printer -{ - - /** - * Instance of HTMLPurifier_Generator for HTML generation convenience funcs - */ - protected $generator; - - /** - * Instance of HTMLPurifier_Config, for easy access - */ - protected $config; - - /** - * Initialize $generator. - */ - public function __construct() { - } - - /** - * Give generator necessary configuration if possible - */ - public function prepareGenerator($config) { - $all = $config->getAll(); - $context = new HTMLPurifier_Context(); - $this->generator = new HTMLPurifier_Generator($config, $context); - } - - /** - * Main function that renders object or aspect of that object - * @note Parameters vary depending on printer - */ - // function render() {} - - /** - * Returns a start tag - * @param $tag Tag name - * @param $attr Attribute array - */ - protected function start($tag, $attr = array()) { - return $this->generator->generateFromToken( - new HTMLPurifier_Token_Start($tag, $attr ? $attr : array()) - ); - } - - /** - * Returns an end teg - * @param $tag Tag name - */ - protected function end($tag) { - return $this->generator->generateFromToken( - new HTMLPurifier_Token_End($tag) - ); - } - - /** - * Prints a complete element with content inside - * @param $tag Tag name - * @param $contents Element contents - * @param $attr Tag attributes - * @param $escape Bool whether or not to escape contents - */ - protected function element($tag, $contents, $attr = array(), $escape = true) { - return $this->start($tag, $attr) . - ($escape ? $this->escape($contents) : $contents) . - $this->end($tag); - } - - protected function elementEmpty($tag, $attr = array()) { - return $this->generator->generateFromToken( - new HTMLPurifier_Token_Empty($tag, $attr) - ); - } - - protected function text($text) { - return $this->generator->generateFromToken( - new HTMLPurifier_Token_Text($text) - ); - } - - /** - * Prints a simple key/value row in a table. - * @param $name Key - * @param $value Value - */ - protected function row($name, $value) { - if (is_bool($value)) $value = $value ? 'On' : 'Off'; - return - $this->start('tr') . "\n" . - $this->element('th', $name) . "\n" . - $this->element('td', $value) . "\n" . - $this->end('tr') - ; - } - - /** - * Escapes a string for HTML output. - * @param $string String to escape - */ - protected function escape($string) { - $string = HTMLPurifier_Encoder::cleanUTF8($string); - $string = htmlspecialchars($string, ENT_COMPAT, 'UTF-8'); - return $string; - } - - /** - * Takes a list of strings and turns them into a single list - * @param $array List of strings - * @param $polite Bool whether or not to add an end before the last - */ - protected function listify($array, $polite = false) { - if (empty($array)) return 'None'; - $ret = ''; - $i = count($array); - foreach ($array as $value) { - $i--; - $ret .= $value; - if ($i > 0 && !($polite && $i == 1)) $ret .= ', '; - if ($polite && $i == 1) $ret .= 'and '; - } - return $ret; - } - - /** - * Retrieves the class of an object without prefixes, as well as metadata - * @param $obj Object to determine class of - * @param $prefix Further prefix to remove - */ - protected function getClass($obj, $sec_prefix = '') { - static $five = null; - if ($five === null) $five = version_compare(PHP_VERSION, '5', '>='); - $prefix = 'HTMLPurifier_' . $sec_prefix; - if (!$five) $prefix = strtolower($prefix); - $class = str_replace($prefix, '', get_class($obj)); - $lclass = strtolower($class); - $class .= '('; - switch ($lclass) { - case 'enum': - $values = array(); - foreach ($obj->valid_values as $value => $bool) { - $values[] = $value; - } - $class .= implode(', ', $values); - break; - case 'css_composite': - $values = array(); - foreach ($obj->defs as $def) { - $values[] = $this->getClass($def, $sec_prefix); - } - $class .= implode(', ', $values); - break; - case 'css_multiple': - $class .= $this->getClass($obj->single, $sec_prefix) . ', '; - $class .= $obj->max; - break; - case 'css_denyelementdecorator': - $class .= $this->getClass($obj->def, $sec_prefix) . ', '; - $class .= $obj->element; - break; - case 'css_importantdecorator': - $class .= $this->getClass($obj->def, $sec_prefix); - if ($obj->allow) $class .= ', !important'; - break; - } - $class .= ')'; - return $class; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Printer/CSSDefinition.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Printer/CSSDefinition.php deleted file mode 100644 index 0be17df7..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Printer/CSSDefinition.php +++ /dev/null @@ -1,38 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -class HTMLPurifier_Printer_CSSDefinition extends HTMLPurifier_Printer -{ - - protected $def; - - public function render($config) { - $this->def = $config->getCSSDefinition(); - $ret = ''; - - $ret .= $this->start('div', array('class' => 'HTMLPurifier_Printer')); - $ret .= $this->start('table'); - - $ret .= $this->element('caption', 'Properties ($info)'); - - $ret .= $this->start('thead'); - $ret .= $this->start('tr'); - $ret .= $this->element('th', 'Property', array('class' => 'heavy')); - $ret .= $this->element('th', 'Definition', array('class' => 'heavy', 'style' => 'width:auto;')); - $ret .= $this->end('tr'); - $ret .= $this->end('thead'); - - ksort($this->def->info); - foreach ($this->def->info as $property => $obj) { - $name = $this->getClass($obj, 'AttrDef_'); - $ret .= $this->row($property, $name); - } - - $ret .= $this->end('table'); - $ret .= $this->end('div'); - - return $ret; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Printer/ConfigForm.css b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Printer/ConfigForm.css deleted file mode 100644 index 3ff1a88a..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Printer/ConfigForm.css +++ /dev/null @@ -1,10 +0,0 @@ - -.hp-config {} - -.hp-config tbody th {text-align:right; padding-right:0.5em;} -.hp-config thead, .hp-config .namespace {background:#3C578C; color:#FFF;} -.hp-config .namespace th {text-align:center;} -.hp-config .verbose {display:none;} -.hp-config .controls {text-align:center;} - -/* vim: et sw=4 sts=4 */ diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Printer/ConfigForm.js b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Printer/ConfigForm.js deleted file mode 100644 index cba00c9b..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Printer/ConfigForm.js +++ /dev/null @@ -1,5 +0,0 @@ -function toggleWriteability(id_of_patient, checked) { - document.getElementById(id_of_patient).disabled = checked; -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Printer/ConfigForm.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Printer/ConfigForm.php deleted file mode 100644 index 4d391992..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Printer/ConfigForm.php +++ /dev/null @@ -1,368 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * @todo Rewrite to use Interchange objects - */ -class HTMLPurifier_Printer_ConfigForm extends HTMLPurifier_Printer -{ - - /** - * Printers for specific fields - */ - protected $fields = array(); - - /** - * Documentation URL, can have fragment tagged on end - */ - protected $docURL; - - /** - * Name of form element to stuff config in - */ - protected $name; - - /** - * Whether or not to compress directive names, clipping them off - * after a certain amount of letters. False to disable or integer letters - * before clipping. - */ - protected $compress = false; - - /** - * @param $name Form element name for directives to be stuffed into - * @param $doc_url String documentation URL, will have fragment tagged on - * @param $compress Integer max length before compressing a directive name, set to false to turn off - */ - public function __construct( - $name, $doc_url = null, $compress = false - ) { - parent::__construct(); - $this->docURL = $doc_url; - $this->name = $name; - $this->compress = $compress; - // initialize sub-printers - $this->fields[0] = new HTMLPurifier_Printer_ConfigForm_default(); - $this->fields[HTMLPurifier_VarParser::BOOL] = new HTMLPurifier_Printer_ConfigForm_bool(); - } - - /** - * Sets default column and row size for textareas in sub-printers - * @param $cols Integer columns of textarea, null to use default - * @param $rows Integer rows of textarea, null to use default - */ - public function setTextareaDimensions($cols = null, $rows = null) { - if ($cols) $this->fields['default']->cols = $cols; - if ($rows) $this->fields['default']->rows = $rows; - } - - /** - * Retrieves styling, in case it is not accessible by webserver - */ - public static function getCSS() { - return file_get_contents(HTMLPURIFIER_PREFIX . '/HTMLPurifier/Printer/ConfigForm.css'); - } - - /** - * Retrieves JavaScript, in case it is not accessible by webserver - */ - public static function getJavaScript() { - return file_get_contents(HTMLPURIFIER_PREFIX . '/HTMLPurifier/Printer/ConfigForm.js'); - } - - /** - * Returns HTML output for a configuration form - * @param $config Configuration object of current form state, or an array - * where [0] has an HTML namespace and [1] is being rendered. - * @param $allowed Optional namespace(s) and directives to restrict form to. - */ - public function render($config, $allowed = true, $render_controls = true) { - if (is_array($config) && isset($config[0])) { - $gen_config = $config[0]; - $config = $config[1]; - } else { - $gen_config = $config; - } - - $this->config = $config; - $this->genConfig = $gen_config; - $this->prepareGenerator($gen_config); - - $allowed = HTMLPurifier_Config::getAllowedDirectivesForForm($allowed, $config->def); - $all = array(); - foreach ($allowed as $key) { - list($ns, $directive) = $key; - $all[$ns][$directive] = $config->get($ns .'.'. $directive); - } - - $ret = ''; - $ret .= $this->start('table', array('class' => 'hp-config')); - $ret .= $this->start('thead'); - $ret .= $this->start('tr'); - $ret .= $this->element('th', 'Directive', array('class' => 'hp-directive')); - $ret .= $this->element('th', 'Value', array('class' => 'hp-value')); - $ret .= $this->end('tr'); - $ret .= $this->end('thead'); - foreach ($all as $ns => $directives) { - $ret .= $this->renderNamespace($ns, $directives); - } - if ($render_controls) { - $ret .= $this->start('tbody'); - $ret .= $this->start('tr'); - $ret .= $this->start('td', array('colspan' => 2, 'class' => 'controls')); - $ret .= $this->elementEmpty('input', array('type' => 'submit', 'value' => 'Submit')); - $ret .= '[<a href="?">Reset</a>]'; - $ret .= $this->end('td'); - $ret .= $this->end('tr'); - $ret .= $this->end('tbody'); - } - $ret .= $this->end('table'); - return $ret; - } - - /** - * Renders a single namespace - * @param $ns String namespace name - * @param $directive Associative array of directives to values - */ - protected function renderNamespace($ns, $directives) { - $ret = ''; - $ret .= $this->start('tbody', array('class' => 'namespace')); - $ret .= $this->start('tr'); - $ret .= $this->element('th', $ns, array('colspan' => 2)); - $ret .= $this->end('tr'); - $ret .= $this->end('tbody'); - $ret .= $this->start('tbody'); - foreach ($directives as $directive => $value) { - $ret .= $this->start('tr'); - $ret .= $this->start('th'); - if ($this->docURL) { - $url = str_replace('%s', urlencode("$ns.$directive"), $this->docURL); - $ret .= $this->start('a', array('href' => $url)); - } - $attr = array('for' => "{$this->name}:$ns.$directive"); - - // crop directive name if it's too long - if (!$this->compress || (strlen($directive) < $this->compress)) { - $directive_disp = $directive; - } else { - $directive_disp = substr($directive, 0, $this->compress - 2) . '...'; - $attr['title'] = $directive; - } - - $ret .= $this->element( - 'label', - $directive_disp, - // component printers must create an element with this id - $attr - ); - if ($this->docURL) $ret .= $this->end('a'); - $ret .= $this->end('th'); - - $ret .= $this->start('td'); - $def = $this->config->def->info["$ns.$directive"]; - if (is_int($def)) { - $allow_null = $def < 0; - $type = abs($def); - } else { - $type = $def->type; - $allow_null = isset($def->allow_null); - } - if (!isset($this->fields[$type])) $type = 0; // default - $type_obj = $this->fields[$type]; - if ($allow_null) { - $type_obj = new HTMLPurifier_Printer_ConfigForm_NullDecorator($type_obj); - } - $ret .= $type_obj->render($ns, $directive, $value, $this->name, array($this->genConfig, $this->config)); - $ret .= $this->end('td'); - $ret .= $this->end('tr'); - } - $ret .= $this->end('tbody'); - return $ret; - } - -} - -/** - * Printer decorator for directives that accept null - */ -class HTMLPurifier_Printer_ConfigForm_NullDecorator extends HTMLPurifier_Printer { - /** - * Printer being decorated - */ - protected $obj; - /** - * @param $obj Printer to decorate - */ - public function __construct($obj) { - parent::__construct(); - $this->obj = $obj; - } - public function render($ns, $directive, $value, $name, $config) { - if (is_array($config) && isset($config[0])) { - $gen_config = $config[0]; - $config = $config[1]; - } else { - $gen_config = $config; - } - $this->prepareGenerator($gen_config); - - $ret = ''; - $ret .= $this->start('label', array('for' => "$name:Null_$ns.$directive")); - $ret .= $this->element('span', "$ns.$directive:", array('class' => 'verbose')); - $ret .= $this->text(' Null/Disabled'); - $ret .= $this->end('label'); - $attr = array( - 'type' => 'checkbox', - 'value' => '1', - 'class' => 'null-toggle', - 'name' => "$name"."[Null_$ns.$directive]", - 'id' => "$name:Null_$ns.$directive", - 'onclick' => "toggleWriteability('$name:$ns.$directive',checked)" // INLINE JAVASCRIPT!!!! - ); - if ($this->obj instanceof HTMLPurifier_Printer_ConfigForm_bool) { - // modify inline javascript slightly - $attr['onclick'] = "toggleWriteability('$name:Yes_$ns.$directive',checked);toggleWriteability('$name:No_$ns.$directive',checked)"; - } - if ($value === null) $attr['checked'] = 'checked'; - $ret .= $this->elementEmpty('input', $attr); - $ret .= $this->text(' or '); - $ret .= $this->elementEmpty('br'); - $ret .= $this->obj->render($ns, $directive, $value, $name, array($gen_config, $config)); - return $ret; - } -} - -/** - * Swiss-army knife configuration form field printer - */ -class HTMLPurifier_Printer_ConfigForm_default extends HTMLPurifier_Printer { - public $cols = 18; - public $rows = 5; - public function render($ns, $directive, $value, $name, $config) { - if (is_array($config) && isset($config[0])) { - $gen_config = $config[0]; - $config = $config[1]; - } else { - $gen_config = $config; - } - $this->prepareGenerator($gen_config); - // this should probably be split up a little - $ret = ''; - $def = $config->def->info["$ns.$directive"]; - if (is_int($def)) { - $type = abs($def); - } else { - $type = $def->type; - } - if (is_array($value)) { - switch ($type) { - case HTMLPurifier_VarParser::LOOKUP: - $array = $value; - $value = array(); - foreach ($array as $val => $b) { - $value[] = $val; - } - case HTMLPurifier_VarParser::ALIST: - $value = implode(PHP_EOL, $value); - break; - case HTMLPurifier_VarParser::HASH: - $nvalue = ''; - foreach ($value as $i => $v) { - $nvalue .= "$i:$v" . PHP_EOL; - } - $value = $nvalue; - break; - default: - $value = ''; - } - } - if ($type === HTMLPurifier_VarParser::MIXED) { - return 'Not supported'; - $value = serialize($value); - } - $attr = array( - 'name' => "$name"."[$ns.$directive]", - 'id' => "$name:$ns.$directive" - ); - if ($value === null) $attr['disabled'] = 'disabled'; - if (isset($def->allowed)) { - $ret .= $this->start('select', $attr); - foreach ($def->allowed as $val => $b) { - $attr = array(); - if ($value == $val) $attr['selected'] = 'selected'; - $ret .= $this->element('option', $val, $attr); - } - $ret .= $this->end('select'); - } elseif ( - $type === HTMLPurifier_VarParser::TEXT || - $type === HTMLPurifier_VarParser::ITEXT || - $type === HTMLPurifier_VarParser::ALIST || - $type === HTMLPurifier_VarParser::HASH || - $type === HTMLPurifier_VarParser::LOOKUP - ) { - $attr['cols'] = $this->cols; - $attr['rows'] = $this->rows; - $ret .= $this->start('textarea', $attr); - $ret .= $this->text($value); - $ret .= $this->end('textarea'); - } else { - $attr['value'] = $value; - $attr['type'] = 'text'; - $ret .= $this->elementEmpty('input', $attr); - } - return $ret; - } -} - -/** - * Bool form field printer - */ -class HTMLPurifier_Printer_ConfigForm_bool extends HTMLPurifier_Printer { - public function render($ns, $directive, $value, $name, $config) { - if (is_array($config) && isset($config[0])) { - $gen_config = $config[0]; - $config = $config[1]; - } else { - $gen_config = $config; - } - $this->prepareGenerator($gen_config); - $ret = ''; - $ret .= $this->start('div', array('id' => "$name:$ns.$directive")); - - $ret .= $this->start('label', array('for' => "$name:Yes_$ns.$directive")); - $ret .= $this->element('span', "$ns.$directive:", array('class' => 'verbose')); - $ret .= $this->text(' Yes'); - $ret .= $this->end('label'); - - $attr = array( - 'type' => 'radio', - 'name' => "$name"."[$ns.$directive]", - 'id' => "$name:Yes_$ns.$directive", - 'value' => '1' - ); - if ($value === true) $attr['checked'] = 'checked'; - if ($value === null) $attr['disabled'] = 'disabled'; - $ret .= $this->elementEmpty('input', $attr); - - $ret .= $this->start('label', array('for' => "$name:No_$ns.$directive")); - $ret .= $this->element('span', "$ns.$directive:", array('class' => 'verbose')); - $ret .= $this->text(' No'); - $ret .= $this->end('label'); - - $attr = array( - 'type' => 'radio', - 'name' => "$name"."[$ns.$directive]", - 'id' => "$name:No_$ns.$directive", - 'value' => '0' - ); - if ($value === false) $attr['checked'] = 'checked'; - if ($value === null) $attr['disabled'] = 'disabled'; - $ret .= $this->elementEmpty('input', $attr); - - $ret .= $this->end('div'); - - return $ret; - } -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Printer/HTMLDefinition.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Printer/HTMLDefinition.php deleted file mode 100644 index 556caf57..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Printer/HTMLDefinition.php +++ /dev/null @@ -1,272 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -class HTMLPurifier_Printer_HTMLDefinition extends HTMLPurifier_Printer -{ - - /** - * Instance of HTMLPurifier_HTMLDefinition, for easy access - */ - protected $def; - - public function render($config) { - $ret = ''; - $this->config =& $config; - - $this->def = $config->getHTMLDefinition(); - - $ret .= $this->start('div', array('class' => 'HTMLPurifier_Printer')); - - $ret .= $this->renderDoctype(); - $ret .= $this->renderEnvironment(); - $ret .= $this->renderContentSets(); - $ret .= $this->renderInfo(); - - $ret .= $this->end('div'); - - return $ret; - } - - /** - * Renders the Doctype table - */ - protected function renderDoctype() { - $doctype = $this->def->doctype; - $ret = ''; - $ret .= $this->start('table'); - $ret .= $this->element('caption', 'Doctype'); - $ret .= $this->row('Name', $doctype->name); - $ret .= $this->row('XML', $doctype->xml ? 'Yes' : 'No'); - $ret .= $this->row('Default Modules', implode($doctype->modules, ', ')); - $ret .= $this->row('Default Tidy Modules', implode($doctype->tidyModules, ', ')); - $ret .= $this->end('table'); - return $ret; - } - - - /** - * Renders environment table, which is miscellaneous info - */ - protected function renderEnvironment() { - $def = $this->def; - - $ret = ''; - - $ret .= $this->start('table'); - $ret .= $this->element('caption', 'Environment'); - - $ret .= $this->row('Parent of fragment', $def->info_parent); - $ret .= $this->renderChildren($def->info_parent_def->child); - $ret .= $this->row('Block wrap name', $def->info_block_wrapper); - - $ret .= $this->start('tr'); - $ret .= $this->element('th', 'Global attributes'); - $ret .= $this->element('td', $this->listifyAttr($def->info_global_attr),0,0); - $ret .= $this->end('tr'); - - $ret .= $this->start('tr'); - $ret .= $this->element('th', 'Tag transforms'); - $list = array(); - foreach ($def->info_tag_transform as $old => $new) { - $new = $this->getClass($new, 'TagTransform_'); - $list[] = "<$old> with $new"; - } - $ret .= $this->element('td', $this->listify($list)); - $ret .= $this->end('tr'); - - $ret .= $this->start('tr'); - $ret .= $this->element('th', 'Pre-AttrTransform'); - $ret .= $this->element('td', $this->listifyObjectList($def->info_attr_transform_pre)); - $ret .= $this->end('tr'); - - $ret .= $this->start('tr'); - $ret .= $this->element('th', 'Post-AttrTransform'); - $ret .= $this->element('td', $this->listifyObjectList($def->info_attr_transform_post)); - $ret .= $this->end('tr'); - - $ret .= $this->end('table'); - return $ret; - } - - /** - * Renders the Content Sets table - */ - protected function renderContentSets() { - $ret = ''; - $ret .= $this->start('table'); - $ret .= $this->element('caption', 'Content Sets'); - foreach ($this->def->info_content_sets as $name => $lookup) { - $ret .= $this->heavyHeader($name); - $ret .= $this->start('tr'); - $ret .= $this->element('td', $this->listifyTagLookup($lookup)); - $ret .= $this->end('tr'); - } - $ret .= $this->end('table'); - return $ret; - } - - /** - * Renders the Elements ($info) table - */ - protected function renderInfo() { - $ret = ''; - $ret .= $this->start('table'); - $ret .= $this->element('caption', 'Elements ($info)'); - ksort($this->def->info); - $ret .= $this->heavyHeader('Allowed tags', 2); - $ret .= $this->start('tr'); - $ret .= $this->element('td', $this->listifyTagLookup($this->def->info), array('colspan' => 2)); - $ret .= $this->end('tr'); - foreach ($this->def->info as $name => $def) { - $ret .= $this->start('tr'); - $ret .= $this->element('th', "<$name>", array('class'=>'heavy', 'colspan' => 2)); - $ret .= $this->end('tr'); - $ret .= $this->start('tr'); - $ret .= $this->element('th', 'Inline content'); - $ret .= $this->element('td', $def->descendants_are_inline ? 'Yes' : 'No'); - $ret .= $this->end('tr'); - if (!empty($def->excludes)) { - $ret .= $this->start('tr'); - $ret .= $this->element('th', 'Excludes'); - $ret .= $this->element('td', $this->listifyTagLookup($def->excludes)); - $ret .= $this->end('tr'); - } - if (!empty($def->attr_transform_pre)) { - $ret .= $this->start('tr'); - $ret .= $this->element('th', 'Pre-AttrTransform'); - $ret .= $this->element('td', $this->listifyObjectList($def->attr_transform_pre)); - $ret .= $this->end('tr'); - } - if (!empty($def->attr_transform_post)) { - $ret .= $this->start('tr'); - $ret .= $this->element('th', 'Post-AttrTransform'); - $ret .= $this->element('td', $this->listifyObjectList($def->attr_transform_post)); - $ret .= $this->end('tr'); - } - if (!empty($def->auto_close)) { - $ret .= $this->start('tr'); - $ret .= $this->element('th', 'Auto closed by'); - $ret .= $this->element('td', $this->listifyTagLookup($def->auto_close)); - $ret .= $this->end('tr'); - } - $ret .= $this->start('tr'); - $ret .= $this->element('th', 'Allowed attributes'); - $ret .= $this->element('td',$this->listifyAttr($def->attr), array(), 0); - $ret .= $this->end('tr'); - - if (!empty($def->required_attr)) { - $ret .= $this->row('Required attributes', $this->listify($def->required_attr)); - } - - $ret .= $this->renderChildren($def->child); - } - $ret .= $this->end('table'); - return $ret; - } - - /** - * Renders a row describing the allowed children of an element - * @param $def HTMLPurifier_ChildDef of pertinent element - */ - protected function renderChildren($def) { - $context = new HTMLPurifier_Context(); - $ret = ''; - $ret .= $this->start('tr'); - $elements = array(); - $attr = array(); - if (isset($def->elements)) { - if ($def->type == 'strictblockquote') { - $def->validateChildren(array(), $this->config, $context); - } - $elements = $def->elements; - } - if ($def->type == 'chameleon') { - $attr['rowspan'] = 2; - } elseif ($def->type == 'empty') { - $elements = array(); - } elseif ($def->type == 'table') { - $elements = array_flip(array('col', 'caption', 'colgroup', 'thead', - 'tfoot', 'tbody', 'tr')); - } - $ret .= $this->element('th', 'Allowed children', $attr); - - if ($def->type == 'chameleon') { - - $ret .= $this->element('td', - '<em>Block</em>: ' . - $this->escape($this->listifyTagLookup($def->block->elements)),0,0); - $ret .= $this->end('tr'); - $ret .= $this->start('tr'); - $ret .= $this->element('td', - '<em>Inline</em>: ' . - $this->escape($this->listifyTagLookup($def->inline->elements)),0,0); - - } elseif ($def->type == 'custom') { - - $ret .= $this->element('td', '<em>'.ucfirst($def->type).'</em>: ' . - $def->dtd_regex); - - } else { - $ret .= $this->element('td', - '<em>'.ucfirst($def->type).'</em>: ' . - $this->escape($this->listifyTagLookup($elements)),0,0); - } - $ret .= $this->end('tr'); - return $ret; - } - - /** - * Listifies a tag lookup table. - * @param $array Tag lookup array in form of array('tagname' => true) - */ - protected function listifyTagLookup($array) { - ksort($array); - $list = array(); - foreach ($array as $name => $discard) { - if ($name !== '#PCDATA' && !isset($this->def->info[$name])) continue; - $list[] = $name; - } - return $this->listify($list); - } - - /** - * Listifies a list of objects by retrieving class names and internal state - * @param $array List of objects - * @todo Also add information about internal state - */ - protected function listifyObjectList($array) { - ksort($array); - $list = array(); - foreach ($array as $discard => $obj) { - $list[] = $this->getClass($obj, 'AttrTransform_'); - } - return $this->listify($list); - } - - /** - * Listifies a hash of attributes to AttrDef classes - * @param $array Array hash in form of array('attrname' => HTMLPurifier_AttrDef) - */ - protected function listifyAttr($array) { - ksort($array); - $list = array(); - foreach ($array as $name => $obj) { - if ($obj === false) continue; - $list[] = "$name = <i>" . $this->getClass($obj, 'AttrDef_') . '</i>'; - } - return $this->listify($list); - } - - /** - * Creates a heavy header row - */ - protected function heavyHeader($text, $num = 1) { - $ret = ''; - $ret .= $this->start('tr'); - $ret .= $this->element('th', $text, array('colspan' => $num, 'class' => 'heavy')); - $ret .= $this->end('tr'); - return $ret; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/PropertyList.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/PropertyList.php deleted file mode 100644 index f3e2947c..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/PropertyList.php +++ /dev/null @@ -1,86 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Generic property list implementation - */ -class HTMLPurifier_PropertyList -{ - /** - * Internal data-structure for properties - */ - protected $data = array(); - - /** - * Parent plist - */ - protected $parent; - - protected $cache; - - public function __construct($parent = null) { - $this->parent = $parent; - } - - /** - * Recursively retrieves the value for a key - */ - public function get($name) { - if ($this->has($name)) return $this->data[$name]; - // possible performance bottleneck, convert to iterative if necessary - if ($this->parent) return $this->parent->get($name); - throw new HTMLPurifier_Exception("Key '$name' not found"); - } - - /** - * Sets the value of a key, for this plist - */ - public function set($name, $value) { - $this->data[$name] = $value; - } - - /** - * Returns true if a given key exists - */ - public function has($name) { - return array_key_exists($name, $this->data); - } - - /** - * Resets a value to the value of it's parent, usually the default. If - * no value is specified, the entire plist is reset. - */ - public function reset($name = null) { - if ($name == null) $this->data = array(); - else unset($this->data[$name]); - } - - /** - * Squashes this property list and all of its property lists into a single - * array, and returns the array. This value is cached by default. - * @param $force If true, ignores the cache and regenerates the array. - */ - public function squash($force = false) { - if ($this->cache !== null && !$force) return $this->cache; - if ($this->parent) { - return $this->cache = array_merge($this->parent->squash($force), $this->data); - } else { - return $this->cache = $this->data; - } - } - - /** - * Returns the parent plist. - */ - public function getParent() { - return $this->parent; - } - - /** - * Sets the parent plist. - */ - public function setParent($plist) { - $this->parent = $plist; - } -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/PropertyListIterator.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/PropertyListIterator.php deleted file mode 100644 index 7fa2088e..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/PropertyListIterator.php +++ /dev/null @@ -1,32 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Property list iterator. Do not instantiate this class directly. - */ -class HTMLPurifier_PropertyListIterator extends FilterIterator -{ - - protected $l; - protected $filter; - - /** - * @param $data Array of data to iterate over - * @param $filter Optional prefix to only allow values of - */ - public function __construct(Iterator $iterator, $filter = null) { - parent::__construct($iterator); - $this->l = strlen($filter); - $this->filter = $filter; - } - - public function accept() { - $key = $this->getInnerIterator()->key(); - if( strncmp($key, $this->filter, $this->l) !== 0 ) { - return false; - } - return true; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Strategy.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Strategy.php deleted file mode 100644 index e975e2c8..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Strategy.php +++ /dev/null @@ -1,26 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Supertype for classes that define a strategy for modifying/purifying tokens. - * - * While HTMLPurifier's core purpose is fixing HTML into something proper, - * strategies provide plug points for extra configuration or even extra - * features, such as custom tags, custom parsing of text, etc. - */ - - -abstract class HTMLPurifier_Strategy -{ - - /** - * Executes the strategy on the tokens. - * - * @param $tokens Array of HTMLPurifier_Token objects to be operated on. - * @param $config Configuration options - * @returns Processed array of token objects. - */ - abstract public function execute($tokens, $config, $context); - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Strategy/Composite.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Strategy/Composite.php deleted file mode 100644 index 590274dc..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Strategy/Composite.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Composite strategy that runs multiple strategies on tokens. - */ -abstract class HTMLPurifier_Strategy_Composite extends HTMLPurifier_Strategy -{ - - /** - * List of strategies to run tokens through. - */ - protected $strategies = array(); - - abstract public function __construct(); - - public function execute($tokens, $config, $context) { - foreach ($this->strategies as $strategy) { - $tokens = $strategy->execute($tokens, $config, $context); - } - return $tokens; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Strategy/Core.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Strategy/Core.php deleted file mode 100644 index c7d3c79c..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Strategy/Core.php +++ /dev/null @@ -1,18 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Core strategy composed of the big four strategies. - */ -class HTMLPurifier_Strategy_Core extends HTMLPurifier_Strategy_Composite -{ - - public function __construct() { - $this->strategies[] = new HTMLPurifier_Strategy_RemoveForeignElements(); - $this->strategies[] = new HTMLPurifier_Strategy_MakeWellFormed(); - $this->strategies[] = new HTMLPurifier_Strategy_FixNesting(); - $this->strategies[] = new HTMLPurifier_Strategy_ValidateAttributes(); - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Strategy/FixNesting.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Strategy/FixNesting.php deleted file mode 100644 index dc4ef88b..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Strategy/FixNesting.php +++ /dev/null @@ -1,328 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Takes a well formed list of tokens and fixes their nesting. - * - * HTML elements dictate which elements are allowed to be their children, - * for example, you can't have a p tag in a span tag. Other elements have - * much more rigorous definitions: tables, for instance, require a specific - * order for their elements. There are also constraints not expressible by - * document type definitions, such as the chameleon nature of ins/del - * tags and global child exclusions. - * - * The first major objective of this strategy is to iterate through all the - * nodes (not tokens) of the list of tokens and determine whether or not - * their children conform to the element's definition. If they do not, the - * child definition may optionally supply an amended list of elements that - * is valid or require that the entire node be deleted (and the previous - * node rescanned). - * - * The second objective is to ensure that explicitly excluded elements of - * an element do not appear in its children. Code that accomplishes this - * task is pervasive through the strategy, though the two are distinct tasks - * and could, theoretically, be seperated (although it's not recommended). - * - * @note Whether or not unrecognized children are silently dropped or - * translated into text depends on the child definitions. - * - * @todo Enable nodes to be bubbled out of the structure. - */ - -class HTMLPurifier_Strategy_FixNesting extends HTMLPurifier_Strategy -{ - - public function execute($tokens, $config, $context) { - //####################################################################// - // Pre-processing - - // get a copy of the HTML definition - $definition = $config->getHTMLDefinition(); - - // insert implicit "parent" node, will be removed at end. - // DEFINITION CALL - $parent_name = $definition->info_parent; - array_unshift($tokens, new HTMLPurifier_Token_Start($parent_name)); - $tokens[] = new HTMLPurifier_Token_End($parent_name); - - // setup the context variable 'IsInline', for chameleon processing - // is 'false' when we are not inline, 'true' when it must always - // be inline, and an integer when it is inline for a certain - // branch of the document tree - $is_inline = $definition->info_parent_def->descendants_are_inline; - $context->register('IsInline', $is_inline); - - // setup error collector - $e =& $context->get('ErrorCollector', true); - - //####################################################################// - // Loop initialization - - // stack that contains the indexes of all parents, - // $stack[count($stack)-1] being the current parent - $stack = array(); - - // stack that contains all elements that are excluded - // it is organized by parent elements, similar to $stack, - // but it is only populated when an element with exclusions is - // processed, i.e. there won't be empty exclusions. - $exclude_stack = array(); - - // variable that contains the start token while we are processing - // nodes. This enables error reporting to do its job - $start_token = false; - $context->register('CurrentToken', $start_token); - - //####################################################################// - // Loop - - // iterate through all start nodes. Determining the start node - // is complicated so it has been omitted from the loop construct - for ($i = 0, $size = count($tokens) ; $i < $size; ) { - - //################################################################// - // Gather information on children - - // child token accumulator - $child_tokens = array(); - - // scroll to the end of this node, report number, and collect - // all children - for ($j = $i, $depth = 0; ; $j++) { - if ($tokens[$j] instanceof HTMLPurifier_Token_Start) { - $depth++; - // skip token assignment on first iteration, this is the - // token we currently are on - if ($depth == 1) continue; - } elseif ($tokens[$j] instanceof HTMLPurifier_Token_End) { - $depth--; - // skip token assignment on last iteration, this is the - // end token of the token we're currently on - if ($depth == 0) break; - } - $child_tokens[] = $tokens[$j]; - } - - // $i is index of start token - // $j is index of end token - - $start_token = $tokens[$i]; // to make token available via CurrentToken - - //################################################################// - // Gather information on parent - - // calculate parent information - if ($count = count($stack)) { - $parent_index = $stack[$count-1]; - $parent_name = $tokens[$parent_index]->name; - if ($parent_index == 0) { - $parent_def = $definition->info_parent_def; - } else { - $parent_def = $definition->info[$parent_name]; - } - } else { - // processing as if the parent were the "root" node - // unknown info, it won't be used anyway, in the future, - // we may want to enforce one element only (this is - // necessary for HTML Purifier to clean entire documents - $parent_index = $parent_name = $parent_def = null; - } - - // calculate context - if ($is_inline === false) { - // check if conditions make it inline - if (!empty($parent_def) && $parent_def->descendants_are_inline) { - $is_inline = $count - 1; - } - } else { - // check if we're out of inline - if ($count === $is_inline) { - $is_inline = false; - } - } - - //################################################################// - // Determine whether element is explicitly excluded SGML-style - - // determine whether or not element is excluded by checking all - // parent exclusions. The array should not be very large, two - // elements at most. - $excluded = false; - if (!empty($exclude_stack)) { - foreach ($exclude_stack as $lookup) { - if (isset($lookup[$tokens[$i]->name])) { - $excluded = true; - // no need to continue processing - break; - } - } - } - - //################################################################// - // Perform child validation - - if ($excluded) { - // there is an exclusion, remove the entire node - $result = false; - $excludes = array(); // not used, but good to initialize anyway - } else { - // DEFINITION CALL - if ($i === 0) { - // special processing for the first node - $def = $definition->info_parent_def; - } else { - $def = $definition->info[$tokens[$i]->name]; - - } - - if (!empty($def->child)) { - // have DTD child def validate children - $result = $def->child->validateChildren( - $child_tokens, $config, $context); - } else { - // weird, no child definition, get rid of everything - $result = false; - } - - // determine whether or not this element has any exclusions - $excludes = $def->excludes; - } - - // $result is now a bool or array - - //################################################################// - // Process result by interpreting $result - - if ($result === true || $child_tokens === $result) { - // leave the node as is - - // register start token as a parental node start - $stack[] = $i; - - // register exclusions if there are any - if (!empty($excludes)) $exclude_stack[] = $excludes; - - // move cursor to next possible start node - $i++; - - } elseif($result === false) { - // remove entire node - - if ($e) { - if ($excluded) { - $e->send(E_ERROR, 'Strategy_FixNesting: Node excluded'); - } else { - $e->send(E_ERROR, 'Strategy_FixNesting: Node removed'); - } - } - - // calculate length of inner tokens and current tokens - $length = $j - $i + 1; - - // perform removal - array_splice($tokens, $i, $length); - - // update size - $size -= $length; - - // there is no start token to register, - // current node is now the next possible start node - // unless it turns out that we need to do a double-check - - // this is a rought heuristic that covers 100% of HTML's - // cases and 99% of all other cases. A child definition - // that would be tricked by this would be something like: - // ( | a b c) where it's all or nothing. Fortunately, - // our current implementation claims that that case would - // not allow empty, even if it did - if (!$parent_def->child->allow_empty) { - // we need to do a double-check - $i = $parent_index; - array_pop($stack); - } - - // PROJECTED OPTIMIZATION: Process all children elements before - // reprocessing parent node. - - } else { - // replace node with $result - - // calculate length of inner tokens - $length = $j - $i - 1; - - if ($e) { - if (empty($result) && $length) { - $e->send(E_ERROR, 'Strategy_FixNesting: Node contents removed'); - } else { - $e->send(E_WARNING, 'Strategy_FixNesting: Node reorganized'); - } - } - - // perform replacement - array_splice($tokens, $i + 1, $length, $result); - - // update size - $size -= $length; - $size += count($result); - - // register start token as a parental node start - $stack[] = $i; - - // register exclusions if there are any - if (!empty($excludes)) $exclude_stack[] = $excludes; - - // move cursor to next possible start node - $i++; - - } - - //################################################################// - // Scroll to next start node - - // We assume, at this point, that $i is the index of the token - // that is the first possible new start point for a node. - - // Test if the token indeed is a start tag, if not, move forward - // and test again. - $size = count($tokens); - while ($i < $size and !$tokens[$i] instanceof HTMLPurifier_Token_Start) { - if ($tokens[$i] instanceof HTMLPurifier_Token_End) { - // pop a token index off the stack if we ended a node - array_pop($stack); - // pop an exclusion lookup off exclusion stack if - // we ended node and that node had exclusions - if ($i == 0 || $i == $size - 1) { - // use specialized var if it's the super-parent - $s_excludes = $definition->info_parent_def->excludes; - } else { - $s_excludes = $definition->info[$tokens[$i]->name]->excludes; - } - if ($s_excludes) { - array_pop($exclude_stack); - } - } - $i++; - } - - } - - //####################################################################// - // Post-processing - - // remove implicit parent tokens at the beginning and end - array_shift($tokens); - array_pop($tokens); - - // remove context variables - $context->destroy('IsInline'); - $context->destroy('CurrentToken'); - - //####################################################################// - // Return - - return $tokens; - - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Strategy/MakeWellFormed.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Strategy/MakeWellFormed.php deleted file mode 100644 index c81b6b7b..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Strategy/MakeWellFormed.php +++ /dev/null @@ -1,457 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Takes tokens makes them well-formed (balance end tags, etc.) - */ -class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy -{ - - /** - * Array stream of tokens being processed. - */ - protected $tokens; - - /** - * Current index in $tokens. - */ - protected $t; - - /** - * Current nesting of elements. - */ - protected $stack; - - /** - * Injectors active in this stream processing. - */ - protected $injectors; - - /** - * Current instance of HTMLPurifier_Config. - */ - protected $config; - - /** - * Current instance of HTMLPurifier_Context. - */ - protected $context; - - public function execute($tokens, $config, $context) { - - $definition = $config->getHTMLDefinition(); - - // local variables - $generator = new HTMLPurifier_Generator($config, $context); - $escape_invalid_tags = $config->get('Core.EscapeInvalidTags'); - $e = $context->get('ErrorCollector', true); - $t = false; // token index - $i = false; // injector index - $token = false; // the current token - $reprocess = false; // whether or not to reprocess the same token - $stack = array(); - - // member variables - $this->stack =& $stack; - $this->t =& $t; - $this->tokens =& $tokens; - $this->config = $config; - $this->context = $context; - - // context variables - $context->register('CurrentNesting', $stack); - $context->register('InputIndex', $t); - $context->register('InputTokens', $tokens); - $context->register('CurrentToken', $token); - - // -- begin INJECTOR -- - - $this->injectors = array(); - - $injectors = $config->getBatch('AutoFormat'); - $def_injectors = $definition->info_injector; - $custom_injectors = $injectors['Custom']; - unset($injectors['Custom']); // special case - foreach ($injectors as $injector => $b) { - // XXX: Fix with a legitimate lookup table of enabled filters - if (strpos($injector, '.') !== false) continue; - $injector = "HTMLPurifier_Injector_$injector"; - if (!$b) continue; - $this->injectors[] = new $injector; - } - foreach ($def_injectors as $injector) { - // assumed to be objects - $this->injectors[] = $injector; - } - foreach ($custom_injectors as $injector) { - if (is_string($injector)) { - $injector = "HTMLPurifier_Injector_$injector"; - $injector = new $injector; - } - $this->injectors[] = $injector; - } - - // give the injectors references to the definition and context - // variables for performance reasons - foreach ($this->injectors as $ix => $injector) { - $error = $injector->prepare($config, $context); - if (!$error) continue; - array_splice($this->injectors, $ix, 1); // rm the injector - trigger_error("Cannot enable {$injector->name} injector because $error is not allowed", E_USER_WARNING); - } - - // -- end INJECTOR -- - - // a note on punting: - // In order to reduce code duplication, whenever some code needs - // to make HTML changes in order to make things "correct", the - // new HTML gets sent through the purifier, regardless of its - // status. This means that if we add a start token, because it - // was totally necessary, we don't have to update nesting; we just - // punt ($reprocess = true; continue;) and it does that for us. - - // isset is in loop because $tokens size changes during loop exec - for ( - $t = 0; - $t == 0 || isset($tokens[$t - 1]); - // only increment if we don't need to reprocess - $reprocess ? $reprocess = false : $t++ - ) { - - // check for a rewind - if (is_int($i) && $i >= 0) { - // possibility: disable rewinding if the current token has a - // rewind set on it already. This would offer protection from - // infinite loop, but might hinder some advanced rewinding. - $rewind_to = $this->injectors[$i]->getRewind(); - if (is_int($rewind_to) && $rewind_to < $t) { - if ($rewind_to < 0) $rewind_to = 0; - while ($t > $rewind_to) { - $t--; - $prev = $tokens[$t]; - // indicate that other injectors should not process this token, - // but we need to reprocess it - unset($prev->skip[$i]); - $prev->rewind = $i; - if ($prev instanceof HTMLPurifier_Token_Start) array_pop($this->stack); - elseif ($prev instanceof HTMLPurifier_Token_End) $this->stack[] = $prev->start; - } - } - $i = false; - } - - // handle case of document end - if (!isset($tokens[$t])) { - // kill processing if stack is empty - if (empty($this->stack)) break; - - // peek - $top_nesting = array_pop($this->stack); - $this->stack[] = $top_nesting; - - // send error - if ($e && !isset($top_nesting->armor['MakeWellFormed_TagClosedError'])) { - $e->send(E_NOTICE, 'Strategy_MakeWellFormed: Tag closed by document end', $top_nesting); - } - - // append, don't splice, since this is the end - $tokens[] = new HTMLPurifier_Token_End($top_nesting->name); - - // punt! - $reprocess = true; - continue; - } - - $token = $tokens[$t]; - - //echo '<br>'; printTokens($tokens, $t); printTokens($this->stack); - - // quick-check: if it's not a tag, no need to process - if (empty($token->is_tag)) { - if ($token instanceof HTMLPurifier_Token_Text) { - foreach ($this->injectors as $i => $injector) { - if (isset($token->skip[$i])) continue; - if ($token->rewind !== null && $token->rewind !== $i) continue; - $injector->handleText($token); - $this->processToken($token, $i); - $reprocess = true; - break; - } - } - // another possibility is a comment - continue; - } - - if (isset($definition->info[$token->name])) { - $type = $definition->info[$token->name]->child->type; - } else { - $type = false; // Type is unknown, treat accordingly - } - - // quick tag checks: anything that's *not* an end tag - $ok = false; - if ($type === 'empty' && $token instanceof HTMLPurifier_Token_Start) { - // claims to be a start tag but is empty - $token = new HTMLPurifier_Token_Empty($token->name, $token->attr); - $ok = true; - } elseif ($type && $type !== 'empty' && $token instanceof HTMLPurifier_Token_Empty) { - // claims to be empty but really is a start tag - $this->swap(new HTMLPurifier_Token_End($token->name)); - $this->insertBefore(new HTMLPurifier_Token_Start($token->name, $token->attr)); - // punt (since we had to modify the input stream in a non-trivial way) - $reprocess = true; - continue; - } elseif ($token instanceof HTMLPurifier_Token_Empty) { - // real empty token - $ok = true; - } elseif ($token instanceof HTMLPurifier_Token_Start) { - // start tag - - // ...unless they also have to close their parent - if (!empty($this->stack)) { - - $parent = array_pop($this->stack); - $this->stack[] = $parent; - - if (isset($definition->info[$parent->name])) { - $elements = $definition->info[$parent->name]->child->getAllowedElements($config); - $autoclose = !isset($elements[$token->name]); - } else { - $autoclose = false; - } - - $carryover = false; - if ($autoclose && $definition->info[$parent->name]->formatting) { - $carryover = true; - } - - if ($autoclose) { - // errors need to be updated - $new_token = new HTMLPurifier_Token_End($parent->name); - $new_token->start = $parent; - if ($carryover) { - $element = clone $parent; - $element->armor['MakeWellFormed_TagClosedError'] = true; - $element->carryover = true; - $this->processToken(array($new_token, $token, $element)); - } else { - $this->insertBefore($new_token); - } - if ($e && !isset($parent->armor['MakeWellFormed_TagClosedError'])) { - if (!$carryover) { - $e->send(E_NOTICE, 'Strategy_MakeWellFormed: Tag auto closed', $parent); - } else { - $e->send(E_NOTICE, 'Strategy_MakeWellFormed: Tag carryover', $parent); - } - } - $reprocess = true; - continue; - } - - } - $ok = true; - } - - if ($ok) { - foreach ($this->injectors as $i => $injector) { - if (isset($token->skip[$i])) continue; - if ($token->rewind !== null && $token->rewind !== $i) continue; - $injector->handleElement($token); - $this->processToken($token, $i); - $reprocess = true; - break; - } - if (!$reprocess) { - // ah, nothing interesting happened; do normal processing - $this->swap($token); - if ($token instanceof HTMLPurifier_Token_Start) { - $this->stack[] = $token; - } elseif ($token instanceof HTMLPurifier_Token_End) { - throw new HTMLPurifier_Exception('Improper handling of end tag in start code; possible error in MakeWellFormed'); - } - } - continue; - } - - // sanity check: we should be dealing with a closing tag - if (!$token instanceof HTMLPurifier_Token_End) { - throw new HTMLPurifier_Exception('Unaccounted for tag token in input stream, bug in HTML Purifier'); - } - - // make sure that we have something open - if (empty($this->stack)) { - if ($escape_invalid_tags) { - if ($e) $e->send(E_WARNING, 'Strategy_MakeWellFormed: Unnecessary end tag to text'); - $this->swap(new HTMLPurifier_Token_Text( - $generator->generateFromToken($token) - )); - } else { - $this->remove(); - if ($e) $e->send(E_WARNING, 'Strategy_MakeWellFormed: Unnecessary end tag removed'); - } - $reprocess = true; - continue; - } - - // first, check for the simplest case: everything closes neatly. - // Eventually, everything passes through here; if there are problems - // we modify the input stream accordingly and then punt, so that - // the tokens get processed again. - $current_parent = array_pop($this->stack); - if ($current_parent->name == $token->name) { - $token->start = $current_parent; - foreach ($this->injectors as $i => $injector) { - if (isset($token->skip[$i])) continue; - if ($token->rewind !== null && $token->rewind !== $i) continue; - $injector->handleEnd($token); - $this->processToken($token, $i); - $this->stack[] = $current_parent; - $reprocess = true; - break; - } - continue; - } - - // okay, so we're trying to close the wrong tag - - // undo the pop previous pop - $this->stack[] = $current_parent; - - // scroll back the entire nest, trying to find our tag. - // (feature could be to specify how far you'd like to go) - $size = count($this->stack); - // -2 because -1 is the last element, but we already checked that - $skipped_tags = false; - for ($j = $size - 2; $j >= 0; $j--) { - if ($this->stack[$j]->name == $token->name) { - $skipped_tags = array_slice($this->stack, $j); - break; - } - } - - // we didn't find the tag, so remove - if ($skipped_tags === false) { - if ($escape_invalid_tags) { - $this->swap(new HTMLPurifier_Token_Text( - $generator->generateFromToken($token) - )); - if ($e) $e->send(E_WARNING, 'Strategy_MakeWellFormed: Stray end tag to text'); - } else { - $this->remove(); - if ($e) $e->send(E_WARNING, 'Strategy_MakeWellFormed: Stray end tag removed'); - } - $reprocess = true; - continue; - } - - // do errors, in REVERSE $j order: a,b,c with </a></b></c> - $c = count($skipped_tags); - if ($e) { - for ($j = $c - 1; $j > 0; $j--) { - // notice we exclude $j == 0, i.e. the current ending tag, from - // the errors... - if (!isset($skipped_tags[$j]->armor['MakeWellFormed_TagClosedError'])) { - $e->send(E_NOTICE, 'Strategy_MakeWellFormed: Tag closed by element end', $skipped_tags[$j]); - } - } - } - - // insert tags, in FORWARD $j order: c,b,a with </a></b></c> - $replace = array($token); - for ($j = 1; $j < $c; $j++) { - // ...as well as from the insertions - $new_token = new HTMLPurifier_Token_End($skipped_tags[$j]->name); - $new_token->start = $skipped_tags[$j]; - array_unshift($replace, $new_token); - if (isset($definition->info[$new_token->name]) && $definition->info[$new_token->name]->formatting) { - $element = clone $skipped_tags[$j]; - $element->carryover = true; - $element->armor['MakeWellFormed_TagClosedError'] = true; - $replace[] = $element; - } - } - $this->processToken($replace); - $reprocess = true; - continue; - } - - $context->destroy('CurrentNesting'); - $context->destroy('InputTokens'); - $context->destroy('InputIndex'); - $context->destroy('CurrentToken'); - - unset($this->injectors, $this->stack, $this->tokens, $this->t); - return $tokens; - } - - /** - * Processes arbitrary token values for complicated substitution patterns. - * In general: - * - * If $token is an array, it is a list of tokens to substitute for the - * current token. These tokens then get individually processed. If there - * is a leading integer in the list, that integer determines how many - * tokens from the stream should be removed. - * - * If $token is a regular token, it is swapped with the current token. - * - * If $token is false, the current token is deleted. - * - * If $token is an integer, that number of tokens (with the first token - * being the current one) will be deleted. - * - * @param $token Token substitution value - * @param $injector Injector that performed the substitution; default is if - * this is not an injector related operation. - */ - protected function processToken($token, $injector = -1) { - - // normalize forms of token - if (is_object($token)) $token = array(1, $token); - if (is_int($token)) $token = array($token); - if ($token === false) $token = array(1); - if (!is_array($token)) throw new HTMLPurifier_Exception('Invalid token type from injector'); - if (!is_int($token[0])) array_unshift($token, 1); - if ($token[0] === 0) throw new HTMLPurifier_Exception('Deleting zero tokens is not valid'); - - // $token is now an array with the following form: - // array(number nodes to delete, new node 1, new node 2, ...) - - $delete = array_shift($token); - $old = array_splice($this->tokens, $this->t, $delete, $token); - - if ($injector > -1) { - // determine appropriate skips - $oldskip = isset($old[0]) ? $old[0]->skip : array(); - foreach ($token as $object) { - $object->skip = $oldskip; - $object->skip[$injector] = true; - } - } - - } - - /** - * Inserts a token before the current token. Cursor now points to this token - */ - private function insertBefore($token) { - array_splice($this->tokens, $this->t, 0, array($token)); - } - - /** - * Removes current token. Cursor now points to new token occupying previously - * occupied space. - */ - private function remove() { - array_splice($this->tokens, $this->t, 1); - } - - /** - * Swap current token with new token. Cursor points to new token (no change). - */ - private function swap($token) { - $this->tokens[$this->t] = $token; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Strategy/RemoveForeignElements.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Strategy/RemoveForeignElements.php deleted file mode 100644 index 9792a0f5..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Strategy/RemoveForeignElements.php +++ /dev/null @@ -1,171 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Removes all unrecognized tags from the list of tokens. - * - * This strategy iterates through all the tokens and removes unrecognized - * tokens. If a token is not recognized but a TagTransform is defined for - * that element, the element will be transformed accordingly. - */ - -class HTMLPurifier_Strategy_RemoveForeignElements extends HTMLPurifier_Strategy -{ - - public function execute($tokens, $config, $context) { - $definition = $config->getHTMLDefinition(); - $generator = new HTMLPurifier_Generator($config, $context); - $result = array(); - - $escape_invalid_tags = $config->get('Core.EscapeInvalidTags'); - $remove_invalid_img = $config->get('Core.RemoveInvalidImg'); - - // currently only used to determine if comments should be kept - $trusted = $config->get('HTML.Trusted'); - - $remove_script_contents = $config->get('Core.RemoveScriptContents'); - $hidden_elements = $config->get('Core.HiddenElements'); - - // remove script contents compatibility - if ($remove_script_contents === true) { - $hidden_elements['script'] = true; - } elseif ($remove_script_contents === false && isset($hidden_elements['script'])) { - unset($hidden_elements['script']); - } - - $attr_validator = new HTMLPurifier_AttrValidator(); - - // removes tokens until it reaches a closing tag with its value - $remove_until = false; - - // converts comments into text tokens when this is equal to a tag name - $textify_comments = false; - - $token = false; - $context->register('CurrentToken', $token); - - $e = false; - if ($config->get('Core.CollectErrors')) { - $e =& $context->get('ErrorCollector'); - } - - foreach($tokens as $token) { - if ($remove_until) { - if (empty($token->is_tag) || $token->name !== $remove_until) { - continue; - } - } - if (!empty( $token->is_tag )) { - // DEFINITION CALL - - // before any processing, try to transform the element - if ( - isset($definition->info_tag_transform[$token->name]) - ) { - $original_name = $token->name; - // there is a transformation for this tag - // DEFINITION CALL - $token = $definition-> - info_tag_transform[$token->name]-> - transform($token, $config, $context); - if ($e) $e->send(E_NOTICE, 'Strategy_RemoveForeignElements: Tag transform', $original_name); - } - - if (isset($definition->info[$token->name])) { - - // mostly everything's good, but - // we need to make sure required attributes are in order - if ( - ($token instanceof HTMLPurifier_Token_Start || $token instanceof HTMLPurifier_Token_Empty) && - $definition->info[$token->name]->required_attr && - ($token->name != 'img' || $remove_invalid_img) // ensure config option still works - ) { - $attr_validator->validateToken($token, $config, $context); - $ok = true; - foreach ($definition->info[$token->name]->required_attr as $name) { - if (!isset($token->attr[$name])) { - $ok = false; - break; - } - } - if (!$ok) { - if ($e) $e->send(E_ERROR, 'Strategy_RemoveForeignElements: Missing required attribute', $name); - continue; - } - $token->armor['ValidateAttributes'] = true; - } - - if (isset($hidden_elements[$token->name]) && $token instanceof HTMLPurifier_Token_Start) { - $textify_comments = $token->name; - } elseif ($token->name === $textify_comments && $token instanceof HTMLPurifier_Token_End) { - $textify_comments = false; - } - - } elseif ($escape_invalid_tags) { - // invalid tag, generate HTML representation and insert in - if ($e) $e->send(E_WARNING, 'Strategy_RemoveForeignElements: Foreign element to text'); - $token = new HTMLPurifier_Token_Text( - $generator->generateFromToken($token) - ); - } else { - // check if we need to destroy all of the tag's children - // CAN BE GENERICIZED - if (isset($hidden_elements[$token->name])) { - if ($token instanceof HTMLPurifier_Token_Start) { - $remove_until = $token->name; - } elseif ($token instanceof HTMLPurifier_Token_Empty) { - // do nothing: we're still looking - } else { - $remove_until = false; - } - if ($e) $e->send(E_ERROR, 'Strategy_RemoveForeignElements: Foreign meta element removed'); - } else { - if ($e) $e->send(E_ERROR, 'Strategy_RemoveForeignElements: Foreign element removed'); - } - continue; - } - } elseif ($token instanceof HTMLPurifier_Token_Comment) { - // textify comments in script tags when they are allowed - if ($textify_comments !== false) { - $data = $token->data; - $token = new HTMLPurifier_Token_Text($data); - } elseif ($trusted) { - // keep, but perform comment cleaning - if ($e) { - // perform check whether or not there's a trailing hyphen - if (substr($token->data, -1) == '-') { - $e->send(E_NOTICE, 'Strategy_RemoveForeignElements: Trailing hyphen in comment removed'); - } - } - $token->data = rtrim($token->data, '-'); - $found_double_hyphen = false; - while (strpos($token->data, '--') !== false) { - if ($e && !$found_double_hyphen) { - $e->send(E_NOTICE, 'Strategy_RemoveForeignElements: Hyphens in comment collapsed'); - } - $found_double_hyphen = true; // prevent double-erroring - $token->data = str_replace('--', '-', $token->data); - } - } else { - // strip comments - if ($e) $e->send(E_NOTICE, 'Strategy_RemoveForeignElements: Comment removed'); - continue; - } - } elseif ($token instanceof HTMLPurifier_Token_Text) { - } else { - continue; - } - $result[] = $token; - } - if ($remove_until && $e) { - // we removed tokens until the end, throw error - $e->send(E_ERROR, 'Strategy_RemoveForeignElements: Token removed to end', $remove_until); - } - - $context->destroy('CurrentToken'); - - return $result; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Strategy/ValidateAttributes.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Strategy/ValidateAttributes.php deleted file mode 100644 index d5e03b7b..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Strategy/ValidateAttributes.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Validate all attributes in the tokens. - */ - -class HTMLPurifier_Strategy_ValidateAttributes extends HTMLPurifier_Strategy -{ - - public function execute($tokens, $config, $context) { - - // setup validator - $validator = new HTMLPurifier_AttrValidator(); - - $token = false; - $context->register('CurrentToken', $token); - - foreach ($tokens as $key => $token) { - - // only process tokens that have attributes, - // namely start and empty tags - if (!$token instanceof HTMLPurifier_Token_Start && !$token instanceof HTMLPurifier_Token_Empty) continue; - - // skip tokens that are armored - if (!empty($token->armor['ValidateAttributes'])) continue; - - // note that we have no facilities here for removing tokens - $validator->validateToken($token, $config, $context); - - $tokens[$key] = $token; // for PHP 4 - } - $context->destroy('CurrentToken'); - - return $tokens; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/StringHash.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/StringHash.php deleted file mode 100644 index 2161685e..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/StringHash.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * This is in almost every respect equivalent to an array except - * that it keeps track of which keys were accessed. - * - * @warning For the sake of backwards compatibility with early versions - * of PHP 5, you must not use the $hash[$key] syntax; if you do - * our version of offsetGet is never called. - */ -class HTMLPurifier_StringHash extends ArrayObject -{ - protected $accessed = array(); - - /** - * Retrieves a value, and logs the access. - */ - public function offsetGet($index) { - $this->accessed[$index] = true; - return parent::offsetGet($index); - } - - /** - * Returns a lookup array of all array indexes that have been accessed. - * @return Array in form array($index => true). - */ - public function getAccessed() { - return $this->accessed; - } - - /** - * Resets the access array. - */ - public function resetAccessed() { - $this->accessed = array(); - } -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/StringHashParser.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/StringHashParser.php deleted file mode 100644 index 03deefce..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/StringHashParser.php +++ /dev/null @@ -1,110 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Parses string hash files. File format is as such: - * - * DefaultKeyValue - * KEY: Value - * KEY2: Value2 - * --MULTILINE-KEY-- - * Multiline - * value. - * - * Which would output something similar to: - * - * array( - * 'ID' => 'DefaultKeyValue', - * 'KEY' => 'Value', - * 'KEY2' => 'Value2', - * 'MULTILINE-KEY' => "Multiline\nvalue.\n", - * ) - * - * We use this as an easy to use file-format for configuration schema - * files, but the class itself is usage agnostic. - * - * You can use ---- to forcibly terminate parsing of a single string-hash; - * this marker is used in multi string-hashes to delimit boundaries. - */ -class HTMLPurifier_StringHashParser -{ - - public $default = 'ID'; - - /** - * Parses a file that contains a single string-hash. - */ - public function parseFile($file) { - if (!file_exists($file)) return false; - $fh = fopen($file, 'r'); - if (!$fh) return false; - $ret = $this->parseHandle($fh); - fclose($fh); - return $ret; - } - - /** - * Parses a file that contains multiple string-hashes delimited by '----' - */ - public function parseMultiFile($file) { - if (!file_exists($file)) return false; - $ret = array(); - $fh = fopen($file, 'r'); - if (!$fh) return false; - while (!feof($fh)) { - $ret[] = $this->parseHandle($fh); - } - fclose($fh); - return $ret; - } - - /** - * Internal parser that acepts a file handle. - * @note While it's possible to simulate in-memory parsing by using - * custom stream wrappers, if such a use-case arises we should - * factor out the file handle into its own class. - * @param $fh File handle with pointer at start of valid string-hash - * block. - */ - protected function parseHandle($fh) { - $state = false; - $single = false; - $ret = array(); - do { - $line = fgets($fh); - if ($line === false) break; - $line = rtrim($line, "\n\r"); - if (!$state && $line === '') continue; - if ($line === '----') break; - if (strncmp('--#', $line, 3) === 0) { - // Comment - continue; - } elseif (strncmp('--', $line, 2) === 0) { - // Multiline declaration - $state = trim($line, '- '); - if (!isset($ret[$state])) $ret[$state] = ''; - continue; - } elseif (!$state) { - $single = true; - if (strpos($line, ':') !== false) { - // Single-line declaration - list($state, $line) = explode(':', $line, 2); - $line = trim($line); - } else { - // Use default declaration - $state = $this->default; - } - } - if ($single) { - $ret[$state] = $line; - $single = false; - $state = false; - } else { - $ret[$state] .= "$line\n"; - } - } while (!feof($fh)); - return $ret; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/TagTransform.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/TagTransform.php deleted file mode 100644 index a8a1f45d..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/TagTransform.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Defines a mutation of an obsolete tag into a valid tag. - */ -abstract class HTMLPurifier_TagTransform -{ - - /** - * Tag name to transform the tag to. - */ - public $transform_to; - - /** - * Transforms the obsolete tag into the valid tag. - * @param $tag Tag to be transformed. - * @param $config Mandatory HTMLPurifier_Config object - * @param $context Mandatory HTMLPurifier_Context object - */ - abstract public function transform($tag, $config, $context); - - /** - * Prepends CSS properties to the style attribute, creating the - * attribute if it doesn't exist. - * @warning Copied over from AttrTransform, be sure to keep in sync - * @param $attr Attribute array to process (passed by reference) - * @param $css CSS to prepend - */ - protected function prependCSS(&$attr, $css) { - $attr['style'] = isset($attr['style']) ? $attr['style'] : ''; - $attr['style'] = $css . $attr['style']; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/TagTransform/Font.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/TagTransform/Font.php deleted file mode 100644 index 57823fa9..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/TagTransform/Font.php +++ /dev/null @@ -1,96 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Transforms FONT tags to the proper form (SPAN with CSS styling) - * - * This transformation takes the three proprietary attributes of FONT and - * transforms them into their corresponding CSS attributes. These are color, - * face, and size. - * - * @note Size is an interesting case because it doesn't map cleanly to CSS. - * Thanks to - * http://style.cleverchimp.com/font_size_intervals/altintervals.html - * for reasonable mappings. - * @warning This doesn't work completely correctly; specifically, this - * TagTransform operates before well-formedness is enforced, so - * the "active formatting elements" algorithm doesn't get applied. - */ -class HTMLPurifier_TagTransform_Font extends HTMLPurifier_TagTransform -{ - - public $transform_to = 'span'; - - protected $_size_lookup = array( - '0' => 'xx-small', - '1' => 'xx-small', - '2' => 'small', - '3' => 'medium', - '4' => 'large', - '5' => 'x-large', - '6' => 'xx-large', - '7' => '300%', - '-1' => 'smaller', - '-2' => '60%', - '+1' => 'larger', - '+2' => '150%', - '+3' => '200%', - '+4' => '300%' - ); - - public function transform($tag, $config, $context) { - - if ($tag instanceof HTMLPurifier_Token_End) { - $new_tag = clone $tag; - $new_tag->name = $this->transform_to; - return $new_tag; - } - - $attr = $tag->attr; - $prepend_style = ''; - - // handle color transform - if (isset($attr['color'])) { - $prepend_style .= 'color:' . $attr['color'] . ';'; - unset($attr['color']); - } - - // handle face transform - if (isset($attr['face'])) { - $prepend_style .= 'font-family:' . $attr['face'] . ';'; - unset($attr['face']); - } - - // handle size transform - if (isset($attr['size'])) { - // normalize large numbers - if ($attr['size']{0} == '+' || $attr['size']{0} == '-') { - $size = (int) $attr['size']; - if ($size < -2) $attr['size'] = '-2'; - if ($size > 4) $attr['size'] = '+4'; - } else { - $size = (int) $attr['size']; - if ($size > 7) $attr['size'] = '7'; - } - if (isset($this->_size_lookup[$attr['size']])) { - $prepend_style .= 'font-size:' . - $this->_size_lookup[$attr['size']] . ';'; - } - unset($attr['size']); - } - - if ($prepend_style) { - $attr['style'] = isset($attr['style']) ? - $prepend_style . $attr['style'] : - $prepend_style; - } - - $new_tag = clone $tag; - $new_tag->name = $this->transform_to; - $new_tag->attr = $attr; - - return $new_tag; - - } -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/TagTransform/Simple.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/TagTransform/Simple.php deleted file mode 100644 index ced91503..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/TagTransform/Simple.php +++ /dev/null @@ -1,35 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Simple transformation, just change tag name to something else, - * and possibly add some styling. This will cover most of the deprecated - * tag cases. - */ -class HTMLPurifier_TagTransform_Simple extends HTMLPurifier_TagTransform -{ - - protected $style; - - /** - * @param $transform_to Tag name to transform to. - * @param $style CSS style to add to the tag - */ - public function __construct($transform_to, $style = null) { - $this->transform_to = $transform_to; - $this->style = $style; - } - - public function transform($tag, $config, $context) { - $new_tag = clone $tag; - $new_tag->name = $this->transform_to; - if (!is_null($this->style) && - ($new_tag instanceof HTMLPurifier_Token_Start || $new_tag instanceof HTMLPurifier_Token_Empty) - ) { - $this->prependCSS($new_tag->attr, $this->style); - } - return $new_tag; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Token.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Token.php deleted file mode 100644 index 22bebcf7..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Token.php +++ /dev/null @@ -1,57 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Abstract base token class that all others inherit from. - */ -class HTMLPurifier_Token { - public $line; /**< Line number node was on in source document. Null if unknown. */ - public $col; /**< Column of line node was on in source document. Null if unknown. */ - - /** - * Lookup array of processing that this token is exempt from. - * Currently, valid values are "ValidateAttributes" and - * "MakeWellFormed_TagClosedError" - */ - public $armor = array(); - - /** - * Used during MakeWellFormed. - */ - public $skip; - public $rewind; - public $carryover; - - public function __get($n) { - if ($n === 'type') { - trigger_error('Deprecated type property called; use instanceof', E_USER_NOTICE); - switch (get_class($this)) { - case 'HTMLPurifier_Token_Start': return 'start'; - case 'HTMLPurifier_Token_Empty': return 'empty'; - case 'HTMLPurifier_Token_End': return 'end'; - case 'HTMLPurifier_Token_Text': return 'text'; - case 'HTMLPurifier_Token_Comment': return 'comment'; - default: return null; - } - } - } - - /** - * Sets the position of the token in the source document. - */ - public function position($l = null, $c = null) { - $this->line = $l; - $this->col = $c; - } - - /** - * Convenience function for DirectLex settings line/col position. - */ - public function rawPosition($l, $c) { - if ($c === -1) $l++; - $this->line = $l; - $this->col = $c; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Token/Comment.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Token/Comment.php deleted file mode 100644 index 592f2eea..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Token/Comment.php +++ /dev/null @@ -1,22 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Concrete comment token class. Generally will be ignored. - */ -class HTMLPurifier_Token_Comment extends HTMLPurifier_Token -{ - public $data; /**< Character data within comment. */ - public $is_whitespace = true; - /** - * Transparent constructor. - * - * @param $data String comment data. - */ - public function __construct($data, $line = null, $col = null) { - $this->data = $data; - $this->line = $line; - $this->col = $col; - } -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Token/Empty.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Token/Empty.php deleted file mode 100644 index 842c54da..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Token/Empty.php +++ /dev/null @@ -1,11 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Concrete empty token class. - */ -class HTMLPurifier_Token_Empty extends HTMLPurifier_Token_Tag -{ - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Token/End.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Token/End.php deleted file mode 100644 index e2fe995c..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Token/End.php +++ /dev/null @@ -1,19 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Concrete end token class. - * - * @warning This class accepts attributes even though end tags cannot. This - * is for optimization reasons, as under normal circumstances, the Lexers - * do not pass attributes. - */ -class HTMLPurifier_Token_End extends HTMLPurifier_Token_Tag -{ - /** - * Token that started this node. Added by MakeWellFormed. Please - * do not edit this! - */ - public $start; -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Token/Start.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Token/Start.php deleted file mode 100644 index a68cd9b5..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Token/Start.php +++ /dev/null @@ -1,11 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Concrete start token class. - */ -class HTMLPurifier_Token_Start extends HTMLPurifier_Token_Tag -{ - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Token/Tag.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Token/Tag.php deleted file mode 100644 index e09f123e..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Token/Tag.php +++ /dev/null @@ -1,56 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Abstract class of a tag token (start, end or empty), and its behavior. - */ -class HTMLPurifier_Token_Tag extends HTMLPurifier_Token -{ - /** - * Static bool marker that indicates the class is a tag. - * - * This allows us to check objects with <tt>!empty($obj->is_tag)</tt> - * without having to use a function call <tt>is_a()</tt>. - */ - public $is_tag = true; - - /** - * The lower-case name of the tag, like 'a', 'b' or 'blockquote'. - * - * @note Strictly speaking, XML tags are case sensitive, so we shouldn't - * be lower-casing them, but these tokens cater to HTML tags, which are - * insensitive. - */ - public $name; - - /** - * Associative array of the tag's attributes. - */ - public $attr = array(); - - /** - * Non-overloaded constructor, which lower-cases passed tag name. - * - * @param $name String name. - * @param $attr Associative array of attributes. - */ - public function __construct($name, $attr = array(), $line = null, $col = null) { - $this->name = ctype_lower($name) ? $name : strtolower($name); - foreach ($attr as $key => $value) { - // normalization only necessary when key is not lowercase - if (!ctype_lower($key)) { - $new_key = strtolower($key); - if (!isset($attr[$new_key])) { - $attr[$new_key] = $attr[$key]; - } - if ($new_key !== $key) { - unset($attr[$key]); - } - } - } - $this->attr = $attr; - $this->line = $line; - $this->col = $col; - } -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Token/Text.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Token/Text.php deleted file mode 100644 index 0d82f75a..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/Token/Text.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Concrete text token class. - * - * Text tokens comprise of regular parsed character data (PCDATA) and raw - * character data (from the CDATA sections). Internally, their - * data is parsed with all entities expanded. Surprisingly, the text token - * does have a "tag name" called #PCDATA, which is how the DTD represents it - * in permissible child nodes. - */ -class HTMLPurifier_Token_Text extends HTMLPurifier_Token -{ - - public $name = '#PCDATA'; /**< PCDATA tag name compatible with DTD. */ - public $data; /**< Parsed character data of text. */ - public $is_whitespace; /**< Bool indicating if node is whitespace. */ - - /** - * Constructor, accepts data and determines if it is whitespace. - * - * @param $data String parsed character data. - */ - public function __construct($data, $line = null, $col = null) { - $this->data = $data; - $this->is_whitespace = ctype_space($data); - $this->line = $line; - $this->col = $col; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/TokenFactory.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/TokenFactory.php deleted file mode 100644 index 16c969cf..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/TokenFactory.php +++ /dev/null @@ -1,94 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Factory for token generation. - * - * @note Doing some benchmarking indicates that the new operator is much - * slower than the clone operator (even discounting the cost of the - * constructor). This class is for that optimization. - * Other then that, there's not much point as we don't - * maintain parallel HTMLPurifier_Token hierarchies (the main reason why - * you'd want to use an abstract factory). - * @todo Port DirectLex to use this - */ -class HTMLPurifier_TokenFactory -{ - - /** - * Prototypes that will be cloned. - * @private - */ - // p stands for prototype - private $p_start, $p_end, $p_empty, $p_text, $p_comment; - - /** - * Generates blank prototypes for cloning. - */ - public function __construct() { - $this->p_start = new HTMLPurifier_Token_Start('', array()); - $this->p_end = new HTMLPurifier_Token_End(''); - $this->p_empty = new HTMLPurifier_Token_Empty('', array()); - $this->p_text = new HTMLPurifier_Token_Text(''); - $this->p_comment= new HTMLPurifier_Token_Comment(''); - } - - /** - * Creates a HTMLPurifier_Token_Start. - * @param $name Tag name - * @param $attr Associative array of attributes - * @return Generated HTMLPurifier_Token_Start - */ - public function createStart($name, $attr = array()) { - $p = clone $this->p_start; - $p->__construct($name, $attr); - return $p; - } - - /** - * Creates a HTMLPurifier_Token_End. - * @param $name Tag name - * @return Generated HTMLPurifier_Token_End - */ - public function createEnd($name) { - $p = clone $this->p_end; - $p->__construct($name); - return $p; - } - - /** - * Creates a HTMLPurifier_Token_Empty. - * @param $name Tag name - * @param $attr Associative array of attributes - * @return Generated HTMLPurifier_Token_Empty - */ - public function createEmpty($name, $attr = array()) { - $p = clone $this->p_empty; - $p->__construct($name, $attr); - return $p; - } - - /** - * Creates a HTMLPurifier_Token_Text. - * @param $data Data of text token - * @return Generated HTMLPurifier_Token_Text - */ - public function createText($data) { - $p = clone $this->p_text; - $p->__construct($data); - return $p; - } - - /** - * Creates a HTMLPurifier_Token_Comment. - * @param $data Data of comment token - * @return Generated HTMLPurifier_Token_Comment - */ - public function createComment($data) { - $p = clone $this->p_comment; - $p->__construct($data); - return $p; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URI.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URI.php deleted file mode 100644 index ac983b86..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URI.php +++ /dev/null @@ -1,173 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * HTML Purifier's internal representation of a URI. - * @note - * Internal data-structures are completely escaped. If the data needs - * to be used in a non-URI context (which is very unlikely), be sure - * to decode it first. The URI may not necessarily be well-formed until - * validate() is called. - */ -class HTMLPurifier_URI -{ - - public $scheme, $userinfo, $host, $port, $path, $query, $fragment; - - /** - * @note Automatically normalizes scheme and port - */ - public function __construct($scheme, $userinfo, $host, $port, $path, $query, $fragment) { - $this->scheme = is_null($scheme) || ctype_lower($scheme) ? $scheme : strtolower($scheme); - $this->userinfo = $userinfo; - $this->host = $host; - $this->port = is_null($port) ? $port : (int) $port; - $this->path = $path; - $this->query = $query; - $this->fragment = $fragment; - } - - /** - * Retrieves a scheme object corresponding to the URI's scheme/default - * @param $config Instance of HTMLPurifier_Config - * @param $context Instance of HTMLPurifier_Context - * @return Scheme object appropriate for validating this URI - */ - public function getSchemeObj($config, $context) { - $registry = HTMLPurifier_URISchemeRegistry::instance(); - if ($this->scheme !== null) { - $scheme_obj = $registry->getScheme($this->scheme, $config, $context); - if (!$scheme_obj) return false; // invalid scheme, clean it out - } else { - // no scheme: retrieve the default one - $def = $config->getDefinition('URI'); - $scheme_obj = $registry->getScheme($def->defaultScheme, $config, $context); - if (!$scheme_obj) { - // something funky happened to the default scheme object - trigger_error( - 'Default scheme object "' . $def->defaultScheme . '" was not readable', - E_USER_WARNING - ); - return false; - } - } - return $scheme_obj; - } - - /** - * Generic validation method applicable for all schemes. May modify - * this URI in order to get it into a compliant form. - * @param $config Instance of HTMLPurifier_Config - * @param $context Instance of HTMLPurifier_Context - * @return True if validation/filtering succeeds, false if failure - */ - public function validate($config, $context) { - - // ABNF definitions from RFC 3986 - $chars_sub_delims = '!$&\'()*+,;='; - $chars_gen_delims = ':/?#[]@'; - $chars_pchar = $chars_sub_delims . ':@'; - - // validate scheme (MUST BE FIRST!) - if (!is_null($this->scheme) && is_null($this->host)) { - $def = $config->getDefinition('URI'); - if ($def->defaultScheme === $this->scheme) { - $this->scheme = null; - } - } - - // validate host - if (!is_null($this->host)) { - $host_def = new HTMLPurifier_AttrDef_URI_Host(); - $this->host = $host_def->validate($this->host, $config, $context); - if ($this->host === false) $this->host = null; - } - - // validate username - if (!is_null($this->userinfo)) { - $encoder = new HTMLPurifier_PercentEncoder($chars_sub_delims . ':'); - $this->userinfo = $encoder->encode($this->userinfo); - } - - // validate port - if (!is_null($this->port)) { - if ($this->port < 1 || $this->port > 65535) $this->port = null; - } - - // validate path - $path_parts = array(); - $segments_encoder = new HTMLPurifier_PercentEncoder($chars_pchar . '/'); - if (!is_null($this->host)) { - // path-abempty (hier and relative) - $this->path = $segments_encoder->encode($this->path); - } elseif ($this->path !== '' && $this->path[0] === '/') { - // path-absolute (hier and relative) - if (strlen($this->path) >= 2 && $this->path[1] === '/') { - // This shouldn't ever happen! - $this->path = ''; - } else { - $this->path = $segments_encoder->encode($this->path); - } - } elseif (!is_null($this->scheme) && $this->path !== '') { - // path-rootless (hier) - // Short circuit evaluation means we don't need to check nz - $this->path = $segments_encoder->encode($this->path); - } elseif (is_null($this->scheme) && $this->path !== '') { - // path-noscheme (relative) - // (once again, not checking nz) - $segment_nc_encoder = new HTMLPurifier_PercentEncoder($chars_sub_delims . '@'); - $c = strpos($this->path, '/'); - if ($c !== false) { - $this->path = - $segment_nc_encoder->encode(substr($this->path, 0, $c)) . - $segments_encoder->encode(substr($this->path, $c)); - } else { - $this->path = $segment_nc_encoder->encode($this->path); - } - } else { - // path-empty (hier and relative) - $this->path = ''; // just to be safe - } - - // qf = query and fragment - $qf_encoder = new HTMLPurifier_PercentEncoder($chars_pchar . '/?'); - - if (!is_null($this->query)) { - $this->query = $qf_encoder->encode($this->query); - } - - if (!is_null($this->fragment)) { - $this->fragment = $qf_encoder->encode($this->fragment); - } - - return true; - - } - - /** - * Convert URI back to string - * @return String URI appropriate for output - */ - public function toString() { - // reconstruct authority - $authority = null; - if (!is_null($this->host)) { - $authority = ''; - if(!is_null($this->userinfo)) $authority .= $this->userinfo . '@'; - $authority .= $this->host; - if(!is_null($this->port)) $authority .= ':' . $this->port; - } - - // reconstruct the result - $result = ''; - if (!is_null($this->scheme)) $result .= $this->scheme . ':'; - if (!is_null($authority)) $result .= '//' . $authority; - $result .= $this->path; - if (!is_null($this->query)) $result .= '?' . $this->query; - if (!is_null($this->fragment)) $result .= '#' . $this->fragment; - - return $result; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URIDefinition.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URIDefinition.php deleted file mode 100644 index 86ac169c..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URIDefinition.php +++ /dev/null @@ -1,93 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -class HTMLPurifier_URIDefinition extends HTMLPurifier_Definition -{ - - public $type = 'URI'; - protected $filters = array(); - protected $postFilters = array(); - protected $registeredFilters = array(); - - /** - * HTMLPurifier_URI object of the base specified at %URI.Base - */ - public $base; - - /** - * String host to consider "home" base, derived off of $base - */ - public $host; - - /** - * Name of default scheme based on %URI.DefaultScheme and %URI.Base - */ - public $defaultScheme; - - public function __construct() { - $this->registerFilter(new HTMLPurifier_URIFilter_DisableExternal()); - $this->registerFilter(new HTMLPurifier_URIFilter_DisableExternalResources()); - $this->registerFilter(new HTMLPurifier_URIFilter_HostBlacklist()); - $this->registerFilter(new HTMLPurifier_URIFilter_MakeAbsolute()); - $this->registerFilter(new HTMLPurifier_URIFilter_Munge()); - } - - public function registerFilter($filter) { - $this->registeredFilters[$filter->name] = $filter; - } - - public function addFilter($filter, $config) { - $r = $filter->prepare($config); - if ($r === false) return; // null is ok, for backwards compat - if ($filter->post) { - $this->postFilters[$filter->name] = $filter; - } else { - $this->filters[$filter->name] = $filter; - } - } - - protected function doSetup($config) { - $this->setupMemberVariables($config); - $this->setupFilters($config); - } - - protected function setupFilters($config) { - foreach ($this->registeredFilters as $name => $filter) { - $conf = $config->get('URI.' . $name); - if ($conf !== false && $conf !== null) { - $this->addFilter($filter, $config); - } - } - unset($this->registeredFilters); - } - - protected function setupMemberVariables($config) { - $this->host = $config->get('URI.Host'); - $base_uri = $config->get('URI.Base'); - if (!is_null($base_uri)) { - $parser = new HTMLPurifier_URIParser(); - $this->base = $parser->parse($base_uri); - $this->defaultScheme = $this->base->scheme; - if (is_null($this->host)) $this->host = $this->base->host; - } - if (is_null($this->defaultScheme)) $this->defaultScheme = $config->get('URI.DefaultScheme'); - } - - public function filter(&$uri, $config, $context) { - foreach ($this->filters as $name => $f) { - $result = $f->filter($uri, $config, $context); - if (!$result) return false; - } - return true; - } - - public function postFilter(&$uri, $config, $context) { - foreach ($this->postFilters as $name => $f) { - $result = $f->filter($uri, $config, $context); - if (!$result) return false; - } - return true; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URIFilter.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URIFilter.php deleted file mode 100644 index 8c73051e..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URIFilter.php +++ /dev/null @@ -1,45 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Chainable filters for custom URI processing. - * - * These filters can perform custom actions on a URI filter object, - * including transformation or blacklisting. - * - * @warning This filter is called before scheme object validation occurs. - * Make sure, if you require a specific scheme object, you - * you check that it exists. This allows filters to convert - * proprietary URI schemes into regular ones. - */ -abstract class HTMLPurifier_URIFilter -{ - - /** - * Unique identifier of filter - */ - public $name; - - /** - * True if this filter should be run after scheme validation. - */ - public $post = false; - - /** - * Performs initialization for the filter - */ - public function prepare($config) {return true;} - - /** - * Filter a URI object - * @param $uri Reference to URI object variable - * @param $config Instance of HTMLPurifier_Config - * @param $context Instance of HTMLPurifier_Context - * @return bool Whether or not to continue processing: false indicates - * URL is no good, true indicates continue processing. Note that - * all changes are committed directly on the URI object - */ - abstract public function filter(&$uri, $config, $context); - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URIFilter/DisableExternal.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URIFilter/DisableExternal.php deleted file mode 100644 index 1e929eef..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URIFilter/DisableExternal.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -class HTMLPurifier_URIFilter_DisableExternal extends HTMLPurifier_URIFilter -{ - public $name = 'DisableExternal'; - protected $ourHostParts = false; - public function prepare($config) { - $our_host = $config->getDefinition('URI')->host; - if ($our_host !== null) $this->ourHostParts = array_reverse(explode('.', $our_host)); - } - public function filter(&$uri, $config, $context) { - if (is_null($uri->host)) return true; - if ($this->ourHostParts === false) return false; - $host_parts = array_reverse(explode('.', $uri->host)); - foreach ($this->ourHostParts as $i => $x) { - if (!isset($host_parts[$i])) return false; - if ($host_parts[$i] != $this->ourHostParts[$i]) return false; - } - return true; - } -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URIFilter/DisableExternalResources.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URIFilter/DisableExternalResources.php deleted file mode 100644 index b10370c9..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URIFilter/DisableExternalResources.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -class HTMLPurifier_URIFilter_DisableExternalResources extends HTMLPurifier_URIFilter_DisableExternal -{ - public $name = 'DisableExternalResources'; - public function filter(&$uri, $config, $context) { - if (!$context->get('EmbeddedURI', true)) return true; - return parent::filter($uri, $config, $context); - } -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URIFilter/HostBlacklist.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URIFilter/HostBlacklist.php deleted file mode 100644 index 11463f8f..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URIFilter/HostBlacklist.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -class HTMLPurifier_URIFilter_HostBlacklist extends HTMLPurifier_URIFilter -{ - public $name = 'HostBlacklist'; - protected $blacklist = array(); - public function prepare($config) { - $this->blacklist = $config->get('URI.HostBlacklist'); - return true; - } - public function filter(&$uri, $config, $context) { - foreach($this->blacklist as $blacklisted_host_fragment) { - if (strpos($uri->host, $blacklisted_host_fragment) !== false) { - return false; - } - } - return true; - } -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URIFilter/MakeAbsolute.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URIFilter/MakeAbsolute.php deleted file mode 100644 index 5f3c5ad3..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URIFilter/MakeAbsolute.php +++ /dev/null @@ -1,114 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -// does not support network paths - -class HTMLPurifier_URIFilter_MakeAbsolute extends HTMLPurifier_URIFilter -{ - public $name = 'MakeAbsolute'; - protected $base; - protected $basePathStack = array(); - public function prepare($config) { - $def = $config->getDefinition('URI'); - $this->base = $def->base; - if (is_null($this->base)) { - trigger_error('URI.MakeAbsolute is being ignored due to lack of value for URI.Base configuration', E_USER_WARNING); - return false; - } - $this->base->fragment = null; // fragment is invalid for base URI - $stack = explode('/', $this->base->path); - array_pop($stack); // discard last segment - $stack = $this->_collapseStack($stack); // do pre-parsing - $this->basePathStack = $stack; - return true; - } - public function filter(&$uri, $config, $context) { - if (is_null($this->base)) return true; // abort early - if ( - $uri->path === '' && is_null($uri->scheme) && - is_null($uri->host) && is_null($uri->query) && is_null($uri->fragment) - ) { - // reference to current document - $uri = clone $this->base; - return true; - } - if (!is_null($uri->scheme)) { - // absolute URI already: don't change - if (!is_null($uri->host)) return true; - $scheme_obj = $uri->getSchemeObj($config, $context); - if (!$scheme_obj) { - // scheme not recognized - return false; - } - if (!$scheme_obj->hierarchical) { - // non-hierarchal URI with explicit scheme, don't change - return true; - } - // special case: had a scheme but always is hierarchical and had no authority - } - if (!is_null($uri->host)) { - // network path, don't bother - return true; - } - if ($uri->path === '') { - $uri->path = $this->base->path; - } elseif ($uri->path[0] !== '/') { - // relative path, needs more complicated processing - $stack = explode('/', $uri->path); - $new_stack = array_merge($this->basePathStack, $stack); - if ($new_stack[0] !== '' && !is_null($this->base->host)) { - array_unshift($new_stack, ''); - } - $new_stack = $this->_collapseStack($new_stack); - $uri->path = implode('/', $new_stack); - } else { - // absolute path, but still we should collapse - $uri->path = implode('/', $this->_collapseStack(explode('/', $uri->path))); - } - // re-combine - $uri->scheme = $this->base->scheme; - if (is_null($uri->userinfo)) $uri->userinfo = $this->base->userinfo; - if (is_null($uri->host)) $uri->host = $this->base->host; - if (is_null($uri->port)) $uri->port = $this->base->port; - return true; - } - - /** - * Resolve dots and double-dots in a path stack - */ - private function _collapseStack($stack) { - $result = array(); - $is_folder = false; - for ($i = 0; isset($stack[$i]); $i++) { - $is_folder = false; - // absorb an internally duplicated slash - if ($stack[$i] == '' && $i && isset($stack[$i+1])) continue; - if ($stack[$i] == '..') { - if (!empty($result)) { - $segment = array_pop($result); - if ($segment === '' && empty($result)) { - // error case: attempted to back out too far: - // restore the leading slash - $result[] = ''; - } elseif ($segment === '..') { - $result[] = '..'; // cannot remove .. with .. - } - } else { - // relative path, preserve the double-dots - $result[] = '..'; - } - $is_folder = true; - continue; - } - if ($stack[$i] == '.') { - // silently absorb - $is_folder = true; - continue; - } - $result[] = $stack[$i]; - } - if ($is_folder) $result[] = ''; - return $result; - } -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URIFilter/Munge.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URIFilter/Munge.php deleted file mode 100644 index 16969bed..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URIFilter/Munge.php +++ /dev/null @@ -1,58 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -class HTMLPurifier_URIFilter_Munge extends HTMLPurifier_URIFilter -{ - public $name = 'Munge'; - public $post = true; - private $target, $parser, $doEmbed, $secretKey; - - protected $replace = array(); - - public function prepare($config) { - $this->target = $config->get('URI.' . $this->name); - $this->parser = new HTMLPurifier_URIParser(); - $this->doEmbed = $config->get('URI.MungeResources'); - $this->secretKey = $config->get('URI.MungeSecretKey'); - return true; - } - public function filter(&$uri, $config, $context) { - if ($context->get('EmbeddedURI', true) && !$this->doEmbed) return true; - - $scheme_obj = $uri->getSchemeObj($config, $context); - if (!$scheme_obj) return true; // ignore unknown schemes, maybe another postfilter did it - if (is_null($uri->host) || empty($scheme_obj->browsable)) { - return true; - } - // don't redirect if target host is our host - if ($uri->host === $config->getDefinition('URI')->host) { - return true; - } - - $this->makeReplace($uri, $config, $context); - $this->replace = array_map('rawurlencode', $this->replace); - - $new_uri = strtr($this->target, $this->replace); - $new_uri = $this->parser->parse($new_uri); - // don't redirect if the target host is the same as the - // starting host - if ($uri->host === $new_uri->host) return true; - $uri = $new_uri; // overwrite - return true; - } - - protected function makeReplace($uri, $config, $context) { - $string = $uri->toString(); - // always available - $this->replace['%s'] = $string; - $this->replace['%r'] = $context->get('EmbeddedURI', true); - $token = $context->get('CurrentToken', true); - $this->replace['%n'] = $token ? $token->name : null; - $this->replace['%m'] = $context->get('CurrentAttr', true); - $this->replace['%p'] = $context->get('CurrentCSSProperty', true); - // not always available - if ($this->secretKey) $this->replace['%t'] = sha1($this->secretKey . ':' . $string); - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URIParser.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URIParser.php deleted file mode 100644 index 902f5270..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URIParser.php +++ /dev/null @@ -1,70 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Parses a URI into the components and fragment identifier as specified - * by RFC 3986. - */ -class HTMLPurifier_URIParser -{ - - /** - * Instance of HTMLPurifier_PercentEncoder to do normalization with. - */ - protected $percentEncoder; - - public function __construct() { - $this->percentEncoder = new HTMLPurifier_PercentEncoder(); - } - - /** - * Parses a URI. - * @param $uri string URI to parse - * @return HTMLPurifier_URI representation of URI. This representation has - * not been validated yet and may not conform to RFC. - */ - public function parse($uri) { - - $uri = $this->percentEncoder->normalize($uri); - - // Regexp is as per Appendix B. - // Note that ["<>] are an addition to the RFC's recommended - // characters, because they represent external delimeters. - $r_URI = '!'. - '(([^:/?#"<>]+):)?'. // 2. Scheme - '(//([^/?#"<>]*))?'. // 4. Authority - '([^?#"<>]*)'. // 5. Path - '(\?([^#"<>]*))?'. // 7. Query - '(#([^"<>]*))?'. // 8. Fragment - '!'; - - $matches = array(); - $result = preg_match($r_URI, $uri, $matches); - - if (!$result) return false; // *really* invalid URI - - // seperate out parts - $scheme = !empty($matches[1]) ? $matches[2] : null; - $authority = !empty($matches[3]) ? $matches[4] : null; - $path = $matches[5]; // always present, can be empty - $query = !empty($matches[6]) ? $matches[7] : null; - $fragment = !empty($matches[8]) ? $matches[9] : null; - - // further parse authority - if ($authority !== null) { - $r_authority = "/^((.+?)@)?(\[[^\]]+\]|[^:]*)(:(\d*))?/"; - $matches = array(); - preg_match($r_authority, $authority, $matches); - $userinfo = !empty($matches[1]) ? $matches[2] : null; - $host = !empty($matches[3]) ? $matches[3] : ''; - $port = !empty($matches[4]) ? (int) $matches[5] : null; - } else { - $port = $host = $userinfo = null; - } - - return new HTMLPurifier_URI( - $scheme, $userinfo, $host, $port, $path, $query, $fragment); - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URIScheme.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URIScheme.php deleted file mode 100644 index 2ef2ae55..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URIScheme.php +++ /dev/null @@ -1,42 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Validator for the components of a URI for a specific scheme - */ -class HTMLPurifier_URIScheme -{ - - /** - * Scheme's default port (integer) - */ - public $default_port = null; - - /** - * Whether or not URIs of this schem are locatable by a browser - * http and ftp are accessible, while mailto and news are not. - */ - public $browsable = false; - - /** - * Whether or not the URI always uses <hier_part>, resolves edge cases - * with making relative URIs absolute - */ - public $hierarchical = false; - - /** - * Validates the components of a URI - * @note This implementation should be called by children if they define - * a default port, as it does port processing. - * @param $uri Instance of HTMLPurifier_URI - * @param $config HTMLPurifier_Config object - * @param $context HTMLPurifier_Context object - * @return Bool success or failure - */ - public function validate(&$uri, $config, $context) { - if ($this->default_port == $uri->port) $uri->port = null; - return true; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URIScheme/ftp.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URIScheme/ftp.php deleted file mode 100644 index f86f5f27..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URIScheme/ftp.php +++ /dev/null @@ -1,43 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Validates ftp (File Transfer Protocol) URIs as defined by generic RFC 1738. - */ -class HTMLPurifier_URIScheme_ftp extends HTMLPurifier_URIScheme { - - public $default_port = 21; - public $browsable = true; // usually - public $hierarchical = true; - - public function validate(&$uri, $config, $context) { - parent::validate($uri, $config, $context); - $uri->query = null; - - // typecode check - $semicolon_pos = strrpos($uri->path, ';'); // reverse - if ($semicolon_pos !== false) { - $type = substr($uri->path, $semicolon_pos + 1); // no semicolon - $uri->path = substr($uri->path, 0, $semicolon_pos); - $type_ret = ''; - if (strpos($type, '=') !== false) { - // figure out whether or not the declaration is correct - list($key, $typecode) = explode('=', $type, 2); - if ($key !== 'type') { - // invalid key, tack it back on encoded - $uri->path .= '%3B' . $type; - } elseif ($typecode === 'a' || $typecode === 'i' || $typecode === 'd') { - $type_ret = ";type=$typecode"; - } - } else { - $uri->path .= '%3B' . $type; - } - $uri->path = str_replace(';', '%3B', $uri->path); - $uri->path .= $type_ret; - } - - return true; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URIScheme/http.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URIScheme/http.php deleted file mode 100644 index 1a5ccbe9..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URIScheme/http.php +++ /dev/null @@ -1,20 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Validates http (HyperText Transfer Protocol) as defined by RFC 2616 - */ -class HTMLPurifier_URIScheme_http extends HTMLPurifier_URIScheme { - - public $default_port = 80; - public $browsable = true; - public $hierarchical = true; - - public function validate(&$uri, $config, $context) { - parent::validate($uri, $config, $context); - $uri->userinfo = null; - return true; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URIScheme/https.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URIScheme/https.php deleted file mode 100644 index ec1597bd..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URIScheme/https.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Validates https (Secure HTTP) according to http scheme. - */ -class HTMLPurifier_URIScheme_https extends HTMLPurifier_URIScheme_http { - - public $default_port = 443; - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URIScheme/mailto.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URIScheme/mailto.php deleted file mode 100644 index f3efb2ce..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URIScheme/mailto.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -// VERY RELAXED! Shouldn't cause problems, not even Firefox checks if the -// email is valid, but be careful! - -/** - * Validates mailto (for E-mail) according to RFC 2368 - * @todo Validate the email address - * @todo Filter allowed query parameters - */ - -class HTMLPurifier_URIScheme_mailto extends HTMLPurifier_URIScheme { - - public $browsable = false; - - public function validate(&$uri, $config, $context) { - parent::validate($uri, $config, $context); - $uri->userinfo = null; - $uri->host = null; - $uri->port = null; - // we need to validate path against RFC 2368's addr-spec - return true; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URIScheme/news.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URIScheme/news.php deleted file mode 100644 index 11a8f229..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URIScheme/news.php +++ /dev/null @@ -1,22 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Validates news (Usenet) as defined by generic RFC 1738 - */ -class HTMLPurifier_URIScheme_news extends HTMLPurifier_URIScheme { - - public $browsable = false; - - public function validate(&$uri, $config, $context) { - parent::validate($uri, $config, $context); - $uri->userinfo = null; - $uri->host = null; - $uri->port = null; - $uri->query = null; - // typecode check needed on path - return true; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URIScheme/nntp.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URIScheme/nntp.php deleted file mode 100644 index 57a05451..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URIScheme/nntp.php +++ /dev/null @@ -1,20 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Validates nntp (Network News Transfer Protocol) as defined by generic RFC 1738 - */ -class HTMLPurifier_URIScheme_nntp extends HTMLPurifier_URIScheme { - - public $default_port = 119; - public $browsable = false; - - public function validate(&$uri, $config, $context) { - parent::validate($uri, $config, $context); - $uri->userinfo = null; - $uri->query = null; - return true; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URISchemeRegistry.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URISchemeRegistry.php deleted file mode 100644 index ad227a43..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/URISchemeRegistry.php +++ /dev/null @@ -1,68 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Registry for retrieving specific URI scheme validator objects. - */ -class HTMLPurifier_URISchemeRegistry -{ - - /** - * Retrieve sole instance of the registry. - * @param $prototype Optional prototype to overload sole instance with, - * or bool true to reset to default registry. - * @note Pass a registry object $prototype with a compatible interface and - * the function will copy it and return it all further times. - */ - public static function instance($prototype = null) { - static $instance = null; - if ($prototype !== null) { - $instance = $prototype; - } elseif ($instance === null || $prototype == true) { - $instance = new HTMLPurifier_URISchemeRegistry(); - } - return $instance; - } - - /** - * Cache of retrieved schemes. - */ - protected $schemes = array(); - - /** - * Retrieves a scheme validator object - * @param $scheme String scheme name like http or mailto - * @param $config HTMLPurifier_Config object - * @param $config HTMLPurifier_Context object - */ - public function getScheme($scheme, $config, $context) { - if (!$config) $config = HTMLPurifier_Config::createDefault(); - - // important, otherwise attacker could include arbitrary file - $allowed_schemes = $config->get('URI.AllowedSchemes'); - if (!$config->get('URI.OverrideAllowedSchemes') && - !isset($allowed_schemes[$scheme]) - ) { - return; - } - - if (isset($this->schemes[$scheme])) return $this->schemes[$scheme]; - if (!isset($allowed_schemes[$scheme])) return; - - $class = 'HTMLPurifier_URIScheme_' . $scheme; - if (!class_exists($class)) return; - $this->schemes[$scheme] = new $class(); - return $this->schemes[$scheme]; - } - - /** - * Registers a custom scheme to the cache, bypassing reflection. - * @param $scheme Scheme name - * @param $scheme_obj HTMLPurifier_URIScheme object - */ - public function register($scheme, $scheme_obj) { - $this->schemes[$scheme] = $scheme_obj; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/UnitConverter.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/UnitConverter.php deleted file mode 100644 index 1944fad9..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/UnitConverter.php +++ /dev/null @@ -1,254 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Class for converting between different unit-lengths as specified by - * CSS. - */ -class HTMLPurifier_UnitConverter -{ - - const ENGLISH = 1; - const METRIC = 2; - const DIGITAL = 3; - - /** - * Units information array. Units are grouped into measuring systems - * (English, Metric), and are assigned an integer representing - * the conversion factor between that unit and the smallest unit in - * the system. Numeric indexes are actually magical constants that - * encode conversion data from one system to the next, with a O(n^2) - * constraint on memory (this is generally not a problem, since - * the number of measuring systems is small.) - */ - protected static $units = array( - self::ENGLISH => array( - 'px' => 3, // This is as per CSS 2.1 and Firefox. Your mileage may vary - 'pt' => 4, - 'pc' => 48, - 'in' => 288, - self::METRIC => array('pt', '0.352777778', 'mm'), - ), - self::METRIC => array( - 'mm' => 1, - 'cm' => 10, - self::ENGLISH => array('mm', '2.83464567', 'pt'), - ), - ); - - /** - * Minimum bcmath precision for output. - */ - protected $outputPrecision; - - /** - * Bcmath precision for internal calculations. - */ - protected $internalPrecision; - - /** - * Whether or not BCMath is available - */ - private $bcmath; - - public function __construct($output_precision = 4, $internal_precision = 10, $force_no_bcmath = false) { - $this->outputPrecision = $output_precision; - $this->internalPrecision = $internal_precision; - $this->bcmath = !$force_no_bcmath && function_exists('bcmul'); - } - - /** - * Converts a length object of one unit into another unit. - * @param HTMLPurifier_Length $length - * Instance of HTMLPurifier_Length to convert. You must validate() - * it before passing it here! - * @param string $to_unit - * Unit to convert to. - * @note - * About precision: This conversion function pays very special - * attention to the incoming precision of values and attempts - * to maintain a number of significant figure. Results are - * fairly accurate up to nine digits. Some caveats: - * - If a number is zero-padded as a result of this significant - * figure tracking, the zeroes will be eliminated. - * - If a number contains less than four sigfigs ($outputPrecision) - * and this causes some decimals to be excluded, those - * decimals will be added on. - */ - public function convert($length, $to_unit) { - - if (!$length->isValid()) return false; - - $n = $length->getN(); - $unit = $length->getUnit(); - - if ($n === '0' || $unit === false) { - return new HTMLPurifier_Length('0', false); - } - - $state = $dest_state = false; - foreach (self::$units as $k => $x) { - if (isset($x[$unit])) $state = $k; - if (isset($x[$to_unit])) $dest_state = $k; - } - if (!$state || !$dest_state) return false; - - // Some calculations about the initial precision of the number; - // this will be useful when we need to do final rounding. - $sigfigs = $this->getSigFigs($n); - if ($sigfigs < $this->outputPrecision) $sigfigs = $this->outputPrecision; - - // BCMath's internal precision deals only with decimals. Use - // our default if the initial number has no decimals, or increase - // it by how ever many decimals, thus, the number of guard digits - // will always be greater than or equal to internalPrecision. - $log = (int) floor(log(abs($n), 10)); - $cp = ($log < 0) ? $this->internalPrecision - $log : $this->internalPrecision; // internal precision - - for ($i = 0; $i < 2; $i++) { - - // Determine what unit IN THIS SYSTEM we need to convert to - if ($dest_state === $state) { - // Simple conversion - $dest_unit = $to_unit; - } else { - // Convert to the smallest unit, pending a system shift - $dest_unit = self::$units[$state][$dest_state][0]; - } - - // Do the conversion if necessary - if ($dest_unit !== $unit) { - $factor = $this->div(self::$units[$state][$unit], self::$units[$state][$dest_unit], $cp); - $n = $this->mul($n, $factor, $cp); - $unit = $dest_unit; - } - - // Output was zero, so bail out early. Shouldn't ever happen. - if ($n === '') { - $n = '0'; - $unit = $to_unit; - break; - } - - // It was a simple conversion, so bail out - if ($dest_state === $state) { - break; - } - - if ($i !== 0) { - // Conversion failed! Apparently, the system we forwarded - // to didn't have this unit. This should never happen! - return false; - } - - // Pre-condition: $i == 0 - - // Perform conversion to next system of units - $n = $this->mul($n, self::$units[$state][$dest_state][1], $cp); - $unit = self::$units[$state][$dest_state][2]; - $state = $dest_state; - - // One more loop around to convert the unit in the new system. - - } - - // Post-condition: $unit == $to_unit - if ($unit !== $to_unit) return false; - - // Useful for debugging: - //echo "<pre>n"; - //echo "$n\nsigfigs = $sigfigs\nnew_log = $new_log\nlog = $log\nrp = $rp\n</pre>\n"; - - $n = $this->round($n, $sigfigs); - if (strpos($n, '.') !== false) $n = rtrim($n, '0'); - $n = rtrim($n, '.'); - - return new HTMLPurifier_Length($n, $unit); - } - - /** - * Returns the number of significant figures in a string number. - * @param string $n Decimal number - * @return int number of sigfigs - */ - public function getSigFigs($n) { - $n = ltrim($n, '0+-'); - $dp = strpos($n, '.'); // decimal position - if ($dp === false) { - $sigfigs = strlen(rtrim($n, '0')); - } else { - $sigfigs = strlen(ltrim($n, '0.')); // eliminate extra decimal character - if ($dp !== 0) $sigfigs--; - } - return $sigfigs; - } - - /** - * Adds two numbers, using arbitrary precision when available. - */ - private function add($s1, $s2, $scale) { - if ($this->bcmath) return bcadd($s1, $s2, $scale); - else return $this->scale($s1 + $s2, $scale); - } - - /** - * Multiples two numbers, using arbitrary precision when available. - */ - private function mul($s1, $s2, $scale) { - if ($this->bcmath) return bcmul($s1, $s2, $scale); - else return $this->scale($s1 * $s2, $scale); - } - - /** - * Divides two numbers, using arbitrary precision when available. - */ - private function div($s1, $s2, $scale) { - if ($this->bcmath) return bcdiv($s1, $s2, $scale); - else return $this->scale($s1 / $s2, $scale); - } - - /** - * Rounds a number according to the number of sigfigs it should have, - * using arbitrary precision when available. - */ - private function round($n, $sigfigs) { - $new_log = (int) floor(log(abs($n), 10)); // Number of digits left of decimal - 1 - $rp = $sigfigs - $new_log - 1; // Number of decimal places needed - $neg = $n < 0 ? '-' : ''; // Negative sign - if ($this->bcmath) { - if ($rp >= 0) { - $n = bcadd($n, $neg . '0.' . str_repeat('0', $rp) . '5', $rp + 1); - $n = bcdiv($n, '1', $rp); - } else { - // This algorithm partially depends on the standardized - // form of numbers that comes out of bcmath. - $n = bcadd($n, $neg . '5' . str_repeat('0', $new_log - $sigfigs), 0); - $n = substr($n, 0, $sigfigs + strlen($neg)) . str_repeat('0', $new_log - $sigfigs + 1); - } - return $n; - } else { - return $this->scale(round($n, $sigfigs - $new_log - 1), $rp + 1); - } - } - - /** - * Scales a float to $scale digits right of decimal point, like BCMath. - */ - private function scale($r, $scale) { - if ($scale < 0) { - // The f sprintf type doesn't support negative numbers, so we - // need to cludge things manually. First get the string. - $r = sprintf('%.0f', (float) $r); - // Due to floating point precision loss, $r will more than likely - // look something like 4652999999999.9234. We grab one more digit - // than we need to precise from $r and then use that to round - // appropriately. - $precise = (string) round(substr($r, 0, strlen($r) + $scale), -1); - // Now we return it, truncating the zero that was rounded off. - return substr($precise, 0, -1) . str_repeat('0', -$scale + 1); - } - return sprintf('%.' . $scale . 'f', (float) $r); - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/VarParser.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/VarParser.php deleted file mode 100644 index f5dbb536..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/VarParser.php +++ /dev/null @@ -1,154 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Parses string representations into their corresponding native PHP - * variable type. The base implementation does a simple type-check. - */ -class HTMLPurifier_VarParser -{ - - const STRING = 1; - const ISTRING = 2; - const TEXT = 3; - const ITEXT = 4; - const INT = 5; - const FLOAT = 6; - const BOOL = 7; - const LOOKUP = 8; - const ALIST = 9; - const HASH = 10; - const MIXED = 11; - - /** - * Lookup table of allowed types. Mainly for backwards compatibility, but - * also convenient for transforming string type names to the integer constants. - */ - static public $types = array( - 'string' => self::STRING, - 'istring' => self::ISTRING, - 'text' => self::TEXT, - 'itext' => self::ITEXT, - 'int' => self::INT, - 'float' => self::FLOAT, - 'bool' => self::BOOL, - 'lookup' => self::LOOKUP, - 'list' => self::ALIST, - 'hash' => self::HASH, - 'mixed' => self::MIXED - ); - - /** - * Lookup table of types that are string, and can have aliases or - * allowed value lists. - */ - static public $stringTypes = array( - self::STRING => true, - self::ISTRING => true, - self::TEXT => true, - self::ITEXT => true, - ); - - /** - * Validate a variable according to type. Throws - * HTMLPurifier_VarParserException if invalid. - * It may return NULL as a valid type if $allow_null is true. - * - * @param $var Variable to validate - * @param $type Type of variable, see HTMLPurifier_VarParser->types - * @param $allow_null Whether or not to permit null as a value - * @return Validated and type-coerced variable - */ - final public function parse($var, $type, $allow_null = false) { - if (is_string($type)) { - if (!isset(HTMLPurifier_VarParser::$types[$type])) { - throw new HTMLPurifier_VarParserException("Invalid type '$type'"); - } else { - $type = HTMLPurifier_VarParser::$types[$type]; - } - } - $var = $this->parseImplementation($var, $type, $allow_null); - if ($allow_null && $var === null) return null; - // These are basic checks, to make sure nothing horribly wrong - // happened in our implementations. - switch ($type) { - case (self::STRING): - case (self::ISTRING): - case (self::TEXT): - case (self::ITEXT): - if (!is_string($var)) break; - if ($type == self::ISTRING || $type == self::ITEXT) $var = strtolower($var); - return $var; - case (self::INT): - if (!is_int($var)) break; - return $var; - case (self::FLOAT): - if (!is_float($var)) break; - return $var; - case (self::BOOL): - if (!is_bool($var)) break; - return $var; - case (self::LOOKUP): - case (self::ALIST): - case (self::HASH): - if (!is_array($var)) break; - if ($type === self::LOOKUP) { - foreach ($var as $k) if ($k !== true) $this->error('Lookup table contains value other than true'); - } elseif ($type === self::ALIST) { - $keys = array_keys($var); - if (array_keys($keys) !== $keys) $this->error('Indices for list are not uniform'); - } - return $var; - case (self::MIXED): - return $var; - default: - $this->errorInconsistent(get_class($this), $type); - } - $this->errorGeneric($var, $type); - } - - /** - * Actually implements the parsing. Base implementation is to not - * do anything to $var. Subclasses should overload this! - */ - protected function parseImplementation($var, $type, $allow_null) { - return $var; - } - - /** - * Throws an exception. - */ - protected function error($msg) { - throw new HTMLPurifier_VarParserException($msg); - } - - /** - * Throws an inconsistency exception. - * @note This should not ever be called. It would be called if we - * extend the allowed values of HTMLPurifier_VarParser without - * updating subclasses. - */ - protected function errorInconsistent($class, $type) { - throw new HTMLPurifier_Exception("Inconsistency in $class: ".HTMLPurifier_VarParser::getTypeName($type)." not implemented"); - } - - /** - * Generic error for if a type didn't work. - */ - protected function errorGeneric($var, $type) { - $vtype = gettype($var); - $this->error("Expected type ".HTMLPurifier_VarParser::getTypeName($type).", got $vtype"); - } - - static public function getTypeName($type) { - static $lookup; - if (!$lookup) { - // Lazy load the alternative lookup table - $lookup = array_flip(HTMLPurifier_VarParser::$types); - } - if (!isset($lookup[$type])) return 'unknown'; - return $lookup[$type]; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/VarParser/Flexible.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/VarParser/Flexible.php deleted file mode 100644 index e5998e5e..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/VarParser/Flexible.php +++ /dev/null @@ -1,96 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Performs safe variable parsing based on types which can be used by - * users. This may not be able to represent all possible data inputs, - * however. - */ -class HTMLPurifier_VarParser_Flexible extends HTMLPurifier_VarParser -{ - - protected function parseImplementation($var, $type, $allow_null) { - if ($allow_null && $var === null) return null; - switch ($type) { - // Note: if code "breaks" from the switch, it triggers a generic - // exception to be thrown. Specific errors can be specifically - // done here. - case self::MIXED : - case self::ISTRING : - case self::STRING : - case self::TEXT : - case self::ITEXT : - return $var; - case self::INT : - if (is_string($var) && ctype_digit($var)) $var = (int) $var; - return $var; - case self::FLOAT : - if ((is_string($var) && is_numeric($var)) || is_int($var)) $var = (float) $var; - return $var; - case self::BOOL : - if (is_int($var) && ($var === 0 || $var === 1)) { - $var = (bool) $var; - } elseif (is_string($var)) { - if ($var == 'on' || $var == 'true' || $var == '1') { - $var = true; - } elseif ($var == 'off' || $var == 'false' || $var == '0') { - $var = false; - } else { - throw new HTMLPurifier_VarParserException("Unrecognized value '$var' for $type"); - } - } - return $var; - case self::ALIST : - case self::HASH : - case self::LOOKUP : - if (is_string($var)) { - // special case: technically, this is an array with - // a single empty string item, but having an empty - // array is more intuitive - if ($var == '') return array(); - if (strpos($var, "\n") === false && strpos($var, "\r") === false) { - // simplistic string to array method that only works - // for simple lists of tag names or alphanumeric characters - $var = explode(',',$var); - } else { - $var = preg_split('/(,|[\n\r]+)/', $var); - } - // remove spaces - foreach ($var as $i => $j) $var[$i] = trim($j); - if ($type === self::HASH) { - // key:value,key2:value2 - $nvar = array(); - foreach ($var as $keypair) { - $c = explode(':', $keypair, 2); - if (!isset($c[1])) continue; - $nvar[$c[0]] = $c[1]; - } - $var = $nvar; - } - } - if (!is_array($var)) break; - $keys = array_keys($var); - if ($keys === array_keys($keys)) { - if ($type == self::ALIST) return $var; - elseif ($type == self::LOOKUP) { - $new = array(); - foreach ($var as $key) { - $new[$key] = true; - } - return $new; - } else break; - } - if ($type === self::LOOKUP) { - foreach ($var as $key => $value) { - $var[$key] = true; - } - } - return $var; - default: - $this->errorInconsistent(__CLASS__, $type); - } - $this->errorGeneric($var, $type); - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/VarParser/Native.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/VarParser/Native.php deleted file mode 100644 index cdd342fa..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/VarParser/Native.php +++ /dev/null @@ -1,26 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * This variable parser uses PHP's internal code engine. Because it does - * this, it can represent all inputs; however, it is dangerous and cannot - * be used by users. - */ -class HTMLPurifier_VarParser_Native extends HTMLPurifier_VarParser -{ - - protected function parseImplementation($var, $type, $allow_null) { - return $this->evalExpression($var); - } - - protected function evalExpression($expr) { - $var = null; - $result = eval("\$var = $expr;"); - if ($result === false) { - throw new HTMLPurifier_VarParserException("Fatal error in evaluated code"); - } - return $var; - } - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/VarParserException.php b/modules/gallery/lib/HTMLPurifier/HTMLPurifier/VarParserException.php deleted file mode 100644 index fe30cc79..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifier/VarParserException.php +++ /dev/null @@ -1,11 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); - -/** - * Exception type for HTMLPurifier_VarParser - */ -class HTMLPurifier_VarParserException extends HTMLPurifier_Exception -{ - -} - -// vim: et sw=4 sts=4 diff --git a/modules/gallery/lib/HTMLPurifier/HTMLPurifierLicense b/modules/gallery/lib/HTMLPurifier/HTMLPurifierLicense deleted file mode 100644 index 8c88a20d..00000000 --- a/modules/gallery/lib/HTMLPurifier/HTMLPurifierLicense +++ /dev/null @@ -1,504 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - <one line to give the library's name and a brief idea of what it does.> - Copyright (C) <year> <name of author> - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - <signature of Ty Coon>, 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! - - vim: et sw=4 sts=4 diff --git a/modules/gallery/libraries/Admin_View.php b/modules/gallery/libraries/Admin_View.php index 47770a90..21b70df6 100644 --- a/modules/gallery/libraries/Admin_View.php +++ b/modules/gallery/libraries/Admin_View.php @@ -46,20 +46,10 @@ class Admin_View_Core extends Gallery_View { public function admin_menu() { $menu = Menu::factory("root"); - gallery_menu::admin($menu, $this); - - foreach (module::active() as $module) { - if ($module->name == "gallery") { - continue; - } - $class = "{$module->name}_menu"; - if (method_exists($class, "admin")) { - call_user_func_array(array($class, "admin"), array(&$menu, $this)); - } - } - + gallery::admin_menu($menu, $this); + module::event("admin_menu", $menu, $this); $menu->compact(); - print $menu; + return $menu; } /** @@ -88,6 +78,7 @@ class Admin_View_Core extends Gallery_View { case "admin_page_bottom": case "admin_page_top": case "admin_head": + case "body_attributes": $blocks = array(); foreach (module::active() as $module) { $helper_class = "{$module->name}_theme"; diff --git a/modules/gallery/libraries/Form_Script.php b/modules/gallery/libraries/Form_Script.php new file mode 100644 index 00000000..e841408d --- /dev/null +++ b/modules/gallery/libraries/Form_Script.php @@ -0,0 +1,66 @@ +<?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 Form_Script_Core extends Forge { + protected $data = array( + "name" => false, + "type" => "script", + "url" => "", + "text" => ""); + + public function __construct($name) { + // Set dummy data so we don"t get errors + $this->attr["action"] = ""; + $this->attr["method"] = "post"; + $this->data["name"] = $name; + } + + public function __get($key) { + return isset($this->data[$key]) ? $this->data[$key] : null; + } + + /** + * Sets url attribute + */ + public function url($url) { + $this->data["url"] = $url; + + return $this; + } + + public function text($script_text) { + $this->data["text"] = $script_text; + + return $this; + } + + public function render() { + $script = array(); + if (!empty($this->data["url"])) { + $script[] = html::script($this->data["url"]); + } + + if (!empty($this->data["text"])) { + $script[] = "<script type=\"text/javascript\">\n{$this->data['text']}\n</script>\n"; + } + + return implode("\n", $script); + } + +} // End Form Script
\ No newline at end of file diff --git a/modules/gallery/libraries/Gallery_View.php b/modules/gallery/libraries/Gallery_View.php index 133066d7..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,40 +49,34 @@ 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($paths)) { + return; + } + // Include the url in the cache key so that if the Gallery moves, we don't use old cached // 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)); @@ -95,16 +85,21 @@ 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"; } } $cache->set($key, $contents, array($type), 30 * 84600); - if (function_exists("gzencode")) { + + $use_gzip = function_exists("gzencode") && + (int) ini_get("zlib.output_compression") === 0; + if ($use_gzip) { $cache->set("{$key}_gz", gzencode($contents, 9, FORCE_GZIP), array($type, "gzip"), 30 * 84600); } diff --git a/modules/gallery/libraries/I18n.php b/modules/gallery/libraries/I18n.php index 03a6d8f6..c3336052 100644 --- a/modules/gallery/libraries/I18n.php +++ b/modules/gallery/libraries/I18n.php @@ -77,13 +77,24 @@ class I18n_Core { // TODO: See G2 for better fallack code. $locale_prefs = array($locale); $locale_prefs[] = 'en_US'; - setlocale(LC_ALL, $locale_prefs); + $new_locale = setlocale(LC_ALL, $locale_prefs); + if (is_string($new_locale) && strpos($new_locale, 'tr') === 0) { + // Make PHP 5 work with Turkish (the localization results are mixed though). + // Hack for http://bugs.php.net/18556 + setlocale(LC_CTYPE, 'C'); + } } return $this->_config['default_locale']; } /** * Translates a localizable message. + * + * Security: + * The returned string is safe for use in HTML (it contains a safe subset of HTML and + * interpolation parameters are converted to HTML entities). + * For use in JavaScript, please call ->for_js() on it. + * * @param $message String|array The message to be translated. E.g. "Hello world" * or array("one" => "One album", "other" => "%count albums") * @param $options array (optional) Options array for key value pairs which are used @@ -110,7 +121,7 @@ class I18n_Core { $entry = $this->interpolate($locale, $entry, $values); - return $entry; + return SafeString::of_safe_html($entry); } private function lookup($locale, $message) { @@ -178,18 +189,20 @@ class I18n_Core { static function is_plural_message($message) { return is_array($message); } - - private function interpolate($locale, $string, $values) { + + private function interpolate($locale, $string, $key_values) { // TODO: Handle locale specific number formatting. // Replace x_y before replacing x. - krsort($values, SORT_STRING); + krsort($key_values, SORT_STRING); $keys = array(); - foreach (array_keys($values) as $key) { + $values = array(); + foreach ($key_values as $key => $value) { $keys[] = "%$key"; + $values[] = new SafeString($value); } - return str_replace($keys, array_values($values), $string); + return str_replace($keys, $values, $string); } private function pluralize($locale, $entry, $count) { @@ -414,4 +427,4 @@ class I18n_Core { return $count == 1 ? 'one' : 'other'; } } -}
\ No newline at end of file +} diff --git a/modules/gallery/libraries/MY_ORM.php b/modules/gallery/libraries/MY_ORM.php index 2bd9b4eb..2c9ad1d7 100644 --- a/modules/gallery/libraries/MY_ORM.php +++ b/modules/gallery/libraries/MY_ORM.php @@ -18,6 +18,9 @@ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ class ORM extends ORM_Core { + // Track the original value of this ORM so that we can look it up in ORM::original() + protected $original = null; + public function open_paren() { $this->db->open_paren(); return $this; @@ -29,8 +32,34 @@ class ORM extends ORM_Core { } public function save() { - model_cache::clear($this->object_name, $this->{$this->primary_key}, $this->primary_key); - return parent::save(); + model_cache::clear(); + $result = parent::save(); + $this->original = clone $this; + return $result; + } + + public function __set($column, $value) { + if (!isset($this->original)) { + $this->original = clone $this; + } + + if ($value instanceof SafeString) { + $value = $value->unescaped(); + } + + return parent::__set($column, $value); + } + + public function __unset($column) { + if (!isset($this->original)) { + $this->original = clone $this; + } + + return parent::__unset($column); + } + + public function original() { + return $this->original; } } diff --git a/modules/gallery/libraries/MY_View.php b/modules/gallery/libraries/MY_View.php index 96dcc71b..eb55aca6 100644 --- a/modules/gallery/libraries/MY_View.php +++ b/modules/gallery/libraries/MY_View.php @@ -38,16 +38,8 @@ class View extends View_Core { try { return parent::render($print, $renderer); } catch (Exception $e) { - Kohana::Log('error', $e->getTraceAsString()); - Kohana::Log('debug', $e->getMessage()); + Kohana::Log("error", $e->getMessage() . "\n" . $e->getTraceAsString()); return ""; } } - - public function body_attributes() { - if (locale::is_rtl()) { - return 'class="rtl"'; - } - return ''; - } } diff --git a/modules/gallery/libraries/Menu.php b/modules/gallery/libraries/Menu.php index a39b59a5..07b2b2b8 100644 --- a/modules/gallery/libraries/Menu.php +++ b/modules/gallery/libraries/Menu.php @@ -91,12 +91,43 @@ class Menu_Element_Link extends Menu_Element { } else { $css_class = ""; } - return "<li><a$css_id class=\"gMenuElement$css_class\" href=\"$this->url\" " . + return "<li><a$css_id class=\"gMenuLink $css_class\" href=\"$this->url\" " . "title=\"$this->label\">$this->label</a></li>"; } } /** + * Menu element that provides an AJAX link. + */ +class Menu_Element_Ajax_Link extends Menu_Element { + public $ajax_handler; + + /** + * Set the AJAX handler + * @chainable + */ + public function ajax_handler($ajax_handler) { + $this->ajax_handler = $ajax_handler; + return $this; + } + + public function __toString() { + if (isset($this->css_id) && !empty($this->css_id)) { + $css_id = " id=\"$this->css_id\""; + } else { + $css_id = ""; + } + if (isset($this->css_class) && !empty($this->css_class)) { + $css_class = " $this->css_class"; + } else { + $css_class = ""; + } + return "<li><a$css_id class=\"gAjaxLink $css_class\" href=\"$this->url\" " . + "title=\"$this->label\" ajax_handler=\"$this->ajax_handler\">$this->label</a></li>"; + } +} + +/** * Menu element that provides a pop-up dialog */ class Menu_Element_Dialog extends Menu_Element { @@ -111,7 +142,7 @@ class Menu_Element_Dialog extends Menu_Element { } else { $css_class = ""; } - return "<li><a$css_id class=\"gMenuLink$css_class\" href=\"$this->url\" " . + return "<li><a$css_id class=\"gDialogLink $css_class\" href=\"$this->url\" " . "title=\"$this->label\">$this->label</a></li>"; } } @@ -132,6 +163,9 @@ class Menu_Core extends Menu_Element { case "link": return new Menu_Element_Link($type); + case "ajax_link": + return new Menu_Element_Ajax_Link($type); + case "dialog": return new Menu_Element_Dialog($type); diff --git a/modules/gallery/libraries/ORM_MPTT.php b/modules/gallery/libraries/ORM_MPTT.php index 46280d95..83d2445c 100644 --- a/modules/gallery/libraries/ORM_MPTT.php +++ b/modules/gallery/libraries/ORM_MPTT.php @@ -52,14 +52,14 @@ class ORM_MPTT_Core extends ORM { try { // Make a hole in the parent for this new item $this->db->query( - "UPDATE {{$this->table_name}} SET `left` = `left` + 2 WHERE `left` >= {$parent->right}"); + "UPDATE {{$this->table_name}} SET `left_ptr` = `left_ptr` + 2 WHERE `left_ptr` >= {$parent->right_ptr}"); $this->db->query( - "UPDATE {{$this->table_name}} SET `right` = `right` + 2 WHERE `right` >= {$parent->right}"); - $parent->right += 2; + "UPDATE {{$this->table_name}} SET `right_ptr` = `right_ptr` + 2 WHERE `right_ptr` >= {$parent->right_ptr}"); + $parent->right_ptr += 2; // Insert this item into the hole - $this->left = $parent->right - 2; - $this->right = $parent->right - 1; + $this->left_ptr = $parent->right_ptr - 2; + $this->right_ptr = $parent->right_ptr - 1; $this->parent_id = $parent->id; $this->level = $parent->level + 1; $this->save(); @@ -81,7 +81,7 @@ class ORM_MPTT_Core extends ORM { if ($children) { foreach ($this->children() as $item) { // Deleting children affects the MPTT tree, so we have to reload each child before we - // delete it so that we have current left/right pointers. This is inefficient. + // delete it so that we have current left_ptr/right_ptr pointers. This is inefficient. // @todo load each child once, not twice. $item->reload()->delete(); } @@ -93,9 +93,9 @@ class ORM_MPTT_Core extends ORM { $this->lock(); try { $this->db->query( - "UPDATE {{$this->table_name}} SET `left` = `left` - 2 WHERE `left` > {$this->right}"); + "UPDATE {{$this->table_name}} SET `left_ptr` = `left_ptr` - 2 WHERE `left_ptr` > {$this->right_ptr}"); $this->db->query( - "UPDATE {{$this->table_name}} SET `right` = `right` - 2 WHERE `right` > {$this->right}"); + "UPDATE {{$this->table_name}} SET `right_ptr` = `right_ptr` - 2 WHERE `right_ptr` > {$this->right_ptr}"); } catch (Exception $e) { $this->unlock(); throw $e; @@ -110,8 +110,8 @@ class ORM_MPTT_Core extends ORM { * @param ORM $target * @return boolean */ - function is_descendant($target) { - return ($this->left <= $target->left && $this->right >= $target->right); + function contains($target) { + return ($this->left_ptr <= $target->left_ptr && $this->right_ptr >= $target->right_ptr); } /** @@ -133,10 +133,10 @@ class ORM_MPTT_Core extends ORM { */ function parents() { return $this - ->where("`left` <= {$this->left}") - ->where("`right` >= {$this->right}") + ->where("`left_ptr` <= {$this->left_ptr}") + ->where("`right_ptr` >= {$this->right_ptr}") ->where("id <> {$this->id}") - ->orderby("left", "ASC") + ->orderby("left_ptr", "ASC") ->find_all(); } @@ -146,69 +146,62 @@ class ORM_MPTT_Core extends ORM { * @chainable * @param integer SQL limit * @param integer SQL offset + * @param array additional where clauses * @param array orderby * @return array ORM */ - function children($limit=null, $offset=0, $orderby=null) { - $this->where("parent_id", $this->id); - if (empty($orderby)) { - $this->orderby("id", "ASC"); - } else { - $this->orderby($orderby); - } - return $this->find_all($limit, $offset); + function children($limit=null, $offset=0, $where=array(), $orderby=array("id" => "ASC")) { + return $this + ->where("parent_id", $this->id) + ->where($where) + ->orderby($orderby) + ->find_all($limit, $offset); } /** * Return all of the children of this node, ordered by id. * * @chainable - * @param integer SQL limit - * @param integer SQL offset + * @param array additional where clauses * @return array ORM */ - function children_count() { - return $this->where("parent_id", $this->id)->count_all(); + function children_count($where=array()) { + return $this + ->where($where) + ->where("parent_id", $this->id) + ->count_all(); } /** - * Return all of the children of the specified type, ordered by id. + * Return all of the decendents of the specified type, ordered by id. * * @param integer SQL limit * @param integer SQL offset - * @param string type to return + * @param array additional where clauses * @param array orderby * @return object ORM_Iterator */ - function descendants($limit=null, $offset=0, $type=null, $orderby=null) { - $this->where("left >", $this->left) - ->where("right <=", $this->right); - if ($type) { - $this->where("type", $type); - } - - if (empty($orderby)) { - $this->orderby("id", "ASC"); - } else { - $this->orderby($orderby); - } - - return $this->find_all($limit, $offset); + function descendants($limit=null, $offset=0, $where=array(), $orderby=array("id" => "ASC")) { + return $this + ->where("left_ptr >", $this->left_ptr) + ->where("right_ptr <=", $this->right_ptr) + ->where($where) + ->orderby($orderby) + ->find_all($limit, $offset); } /** * Return the count of all the children of the specified type. * - * @param string type to count + * @param array additional where clauses * @return integer child count */ - function descendants_count($type=null) { - $this->where("left >", $this->left) - ->where("right <=", $this->right); - if ($type) { - $this->where("type", $type); - } - return $this->count_all(); + function descendants_count($where=array()) { + return $this + ->where("left_ptr >", $this->left_ptr) + ->where("right_ptr <=", $this->right_ptr) + ->where($where) + ->count_all(); } /** @@ -219,16 +212,15 @@ class ORM_MPTT_Core extends ORM { * @return ORM_MTPP */ function move_to($target) { - if ($this->left <= $target->left && - $this->right >= $target->right) { + if ($this->contains($target)) { throw new Exception("@todo INVALID_TARGET can't move item inside itself"); } - $number_to_move = (int)(($this->right - $this->left) / 2 + 1); + $number_to_move = (int)(($this->right_ptr - $this->left_ptr) / 2 + 1); $size_of_hole = $number_to_move * 2; - $original_left = $this->left; - $original_right = $this->right; - $target_right = $target->right; + $original_left_ptr = $this->left_ptr; + $original_right_ptr = $this->right_ptr; + $target_right_ptr = $target->right_ptr; $level_delta = ($target->level + 1) - $this->level; $this->lock(); @@ -237,45 +229,45 @@ class ORM_MPTT_Core extends ORM { // Update the levels for the to-be-moved items $this->db->query( "UPDATE {{$this->table_name}} SET `level` = `level` + $level_delta" . - " WHERE `left` >= $original_left AND `right` <= $original_right"); + " WHERE `left_ptr` >= $original_left_ptr AND `right_ptr` <= $original_right_ptr"); } // Make a hole in the target for the move $target->db->query( - "UPDATE {{$this->table_name}} SET `left` = `left` + $size_of_hole" . - " WHERE `left` >= $target_right"); + "UPDATE {{$this->table_name}} SET `left_ptr` = `left_ptr` + $size_of_hole" . + " WHERE `left_ptr` >= $target_right_ptr"); $target->db->query( - "UPDATE {{$this->table_name}} SET `right` = `right` + $size_of_hole" . - " WHERE `right` >= $target_right"); + "UPDATE {{$this->table_name}} SET `right_ptr` = `right_ptr` + $size_of_hole" . + " WHERE `right_ptr` >= $target_right_ptr"); // Change the parent. $this->db->query( "UPDATE {{$this->table_name}} SET `parent_id` = {$target->id}" . " WHERE `id` = {$this->id}"); - // If the source is to the right of the target then we just adjusted its left and right above. - $left = $original_left; - $right = $original_right; - if ($original_left > $target_right) { - $left += $size_of_hole; - $right += $size_of_hole; + // If the source is to the right of the target then we just adjusted its left_ptr and right_ptr above. + $left_ptr = $original_left_ptr; + $right_ptr = $original_right_ptr; + if ($original_left_ptr > $target_right_ptr) { + $left_ptr += $size_of_hole; + $right_ptr += $size_of_hole; } - $new_offset = $target->right - $left; + $new_offset = $target->right_ptr - $left_ptr; $this->db->query( "UPDATE {{$this->table_name}}" . - " SET `left` = `left` + $new_offset," . - " `right` = `right` + $new_offset" . - " WHERE `left` >= $left" . - " AND `right` <= $right"); + " SET `left_ptr` = `left_ptr` + $new_offset," . + " `right_ptr` = `right_ptr` + $new_offset" . + " WHERE `left_ptr` >= $left_ptr" . + " AND `right_ptr` <= $right_ptr"); // Close the hole in the source's parent after the move $this->db->query( - "UPDATE {{$this->table_name}} SET `left` = `left` - $size_of_hole" . - " WHERE `left` > $right"); + "UPDATE {{$this->table_name}} SET `left_ptr` = `left_ptr` - $size_of_hole" . + " WHERE `left_ptr` > $right_ptr"); $this->db->query( - "UPDATE {{$this->table_name}} SET `right` = `right` - $size_of_hole" . - " WHERE `right` > $right"); + "UPDATE {{$this->table_name}} SET `right_ptr` = `right_ptr` - $size_of_hole" . + " WHERE `right_ptr` > $right_ptr"); } catch (Exception $e) { $this->unlock(); throw $e; @@ -285,6 +277,7 @@ class ORM_MPTT_Core extends ORM { // Lets reload to get the changes. $this->reload(); + $target->reload(); return $this; } diff --git a/modules/gallery/libraries/SafeString.php b/modules/gallery/libraries/SafeString.php new file mode 100644 index 00000000..ba3a8ffd --- /dev/null +++ b/modules/gallery/libraries/SafeString.php @@ -0,0 +1,162 @@ +<?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. + */ + +/** + * Safe string representation (regarding security - cross site scripting). + */ +class SafeString_Core { + private $_raw_string; + protected $_is_safe_html = false; + + /** Constructor */ + function __construct($string) { + if ($string instanceof SafeString) { + $this->_is_safe_html = $string->_is_safe_html; + $string = $string->unescaped(); + } + $this->_raw_string = (string) $string; + } + + /** + * Factory method returning a new SafeString instance for the given string. + */ + static function of($string) { + return new SafeString($string); + } + + /** + * Factory method returning a new SafeString instance after HTML purifying + * the given string. + */ + static function purify($string) { + if ($string instanceof SafeString) { + if ($string->_is_safe_html) { + return $string; + } else { + $string = $string->unescaped(); + } + } + $safe_string = self::of_safe_html(self::_purify_for_html($string)); + return $safe_string; + } + + /** + * Factory method returning a new SafeString instance which won't HTML escape. + */ + static function of_safe_html($string) { + $safe_string = new SafeString($string); + $safe_string->_is_safe_html = true; + return $safe_string; + } + + /** + * Safe for use in HTML. + * @see #for_html() + */ + function __toString() { + if ($this->_is_safe_html) { + return $this->_raw_string; + } else { + return self::_escape_for_html($this->_raw_string); + } + } + + /** + * Safe for use in HTML. + * + * Example:<pre> + * <div><?= $php_var ?> + * </pre> + * @return the string escaped for use in HTML. + */ + function for_html() { + return $this; + } + + /** + * Safe for use as JavaScript string. + * + * Example:<pre> + * <script type="text/javascript>" + * var some_js_var = <?= $php_var->for_js() ?>; + * </script> + * </pre> + * @return the string escaped for use in JavaScript. + */ + function for_js() { + return json_encode((string) $this->_raw_string); + } + + /** + * Safe for use in HTML element attributes. + * + * Assumes that the HTML element attribute is already + * delimited by single or double quotes + * + * Example:<pre> + * <a title="<?= $php_var->for_html_attr() ?>">; + * </script> + * </pre> + * @return the string escaped for use in HTML attributes. + */ + function for_html_attr() { + $string = (string) $this->for_html(); + return strtr($string, + array("'"=>"'", + '"'=>'"')); + } + + /** + * Safe for use HTML (purified HTML) + * + * Example:<pre> + * <div><?= $php_var->purified_html() ?> + * </pre> + * @return the string escaped for use in HTML. + */ + function purified_html() { + return self::purify($this); + } + + /** + * Returns the raw, unsafe string. Do not use lightly. + */ + function unescaped() { + return $this->_raw_string; + } + + /** + * Escape special HTML chars ("<", ">", "&", etc.) to HTML entities. + */ + private static function _escape_for_html($dirty_html) { + return html::specialchars($dirty_html); + } + + /** + * Purify the string, removing any potentially malicious or unsafe HTML / JavaScript. + */ + private static function _purify_for_html($dirty_html) { + if (method_exists("purifier", "purify")) { + return purifier::purify($dirty_html); + } else { + return self::_escape_for_html($dirty_html); + } + } +} diff --git a/modules/gallery/libraries/Sendmail.php b/modules/gallery/libraries/Sendmail.php index 90998457..7bc21a67 100644 --- a/modules/gallery/libraries/Sendmail.php +++ b/modules/gallery/libraries/Sendmail.php @@ -52,6 +52,7 @@ class Sendmail_Core { break; case "header": if (count($value) != 2) { + Kohana::log("error", wordwrap("Invalid header parameters\n" . Kohana::debug($value))); throw new Exception("@todo INVALID_HEADER_PARAMETERS"); } $this->headers[$value[0]] = $value[1]; @@ -70,6 +71,7 @@ class Sendmail_Core { public function send() { if (empty($this->to)) { + Kohana::log("error", wordwrap("Sending mail failed:\nNo to address specified")); throw new Exception("@todo TO_IS_REQUIRED_FOR_MAIL"); } $to = implode(", ", $this->to); @@ -84,8 +86,6 @@ class Sendmail_Core { $headers = implode($this->header_separator, $headers); $message = wordwrap($this->message, $this->line_length, "\n"); if (!$this->mail($to, $this->subject, $message, $headers)) { - Kohana::log("error", wordwrap("Sending mail failed:\nTo: $to\n $this->subject\n" . - "Headers: $headers\n $this->message")); throw new Exception("@todo SEND_MAIL_FAILED"); } return $this; diff --git a/modules/gallery/libraries/Theme_View.php b/modules/gallery/libraries/Theme_View.php index fa45ec89..541bce88 100644 --- a/modules/gallery/libraries/Theme_View.php +++ b/modules/gallery/libraries/Theme_View.php @@ -80,53 +80,46 @@ class Theme_View_Core extends Gallery_View { public function site_menu() { $menu = Menu::factory("root"); - if ($this->page_type != "login") { - gallery_menu::site($menu, $this); - - foreach (module::active() as $module) { - if ($module->name == "gallery") { - continue; - } - $class = "{$module->name}_menu"; - if (method_exists($class, "site")) { - call_user_func_array(array($class, "site"), array(&$menu, $this)); - } - } - } - - $menu->compact(); - print $menu; + gallery::site_menu($menu, $this); + module::event("site_menu", $menu, $this); + return $menu->compact(); } public function album_menu() { - print $this->_menu("album"); + $menu = Menu::factory("root"); + module::event("album_menu", $menu, $this); + return $menu->compact(); } public function tag_menu() { - print $this->_menu("tag"); + $menu = Menu::factory("root"); + module::event("tag_menu", $menu, $this); + return $menu->compact(); } public function photo_menu() { - print $this->_menu("photo"); - } + $menu = Menu::factory("root"); + if (access::can("view_full", $this->item())) { + $menu->append(Menu::factory("link") + ->id("fullsize") + ->label(t("View full size")) + ->url($this->item()->file_url()) + ->css_class("gFullSizeLink")); + } - public function thumb_menu($item) { - print $this->_menu("thumb", $item)->css_class("gThumbMenu"); + module::event("photo_menu", $menu, $this); + return $menu->compact(); } - private function _menu($type, $item=null) { - $menu = Menu::factory("root"); - call_user_func_array(array("gallery_menu", $type), array(&$menu, $this, $item)); - foreach (module::active() as $module) { - if ($module->name == "gallery") { - continue; - } - $class = "{$module->name}_menu"; - if (method_exists($class, $type)) { - call_user_func_array(array($class, $type), array(&$menu, $this, $item)); - } - } + public function context_menu($item, $thumbnail_css_selector) { + $menu = Menu::factory("root") + ->append(Menu::factory("submenu") + ->id("context_menu") + ->label(t("Options"))) + ->css_class("gContextMenu"); + gallery::context_menu($menu, $this, $item, $thumbnail_css_selector); + module::event("context_menu", $menu, $this, $item, $thumbnail_css_selector); return $menu->compact(); } @@ -164,6 +157,7 @@ class Theme_View_Core extends Gallery_View { case "album_blocks": case "album_bottom": case "album_top": + case "body_attributes": case "credits"; case "dynamic_bottom": case "dynamic_top": diff --git a/modules/gallery/models/item.php b/modules/gallery/models/item.php index 51037073..a87997c6 100644 --- a/modules/gallery/models/item.php +++ b/modules/gallery/models/item.php @@ -19,7 +19,6 @@ */ class Item_Model extends ORM_MPTT { protected $children = 'items'; - private $view_restrictions = null; protected $sorting = array(); var $rules = array( @@ -34,38 +33,7 @@ class Item_Model extends ORM_MPTT { * @chainable */ public function viewable() { - if (is_null($this->view_restrictions)) { - if (user::active()->admin) { - $this->view_restrictions = array(); - } else { - foreach (user::group_ids() as $id) { - // Separate the first restriction from the rest to make it easier for us to formulate - // our where clause below - if (empty($this->view_restrictions)) { - $this->view_restrictions[0] = "view_$id"; - } else { - $this->view_restrictions[1]["view_$id"] = access::ALLOW; - } - } - } - } - switch (count($this->view_restrictions)) { - case 0: - break; - - case 1: - $this->where($this->view_restrictions[0], access::ALLOW); - break; - - default: - $this->open_paren(); - $this->where($this->view_restrictions[0], access::ALLOW); - $this->orwhere($this->view_restrictions[1]); - $this->close_paren(); - break; - } - - return $this; + return item::viewable($this); } /** @@ -93,6 +61,7 @@ class Item_Model extends ORM_MPTT { } public function delete() { + $old = clone $this; module::event("item_before_delete", $this); $parent = $this->parent(); @@ -114,13 +83,15 @@ class Item_Model extends ORM_MPTT { @unlink($resize_path); @unlink($thumb_path); } + + module::event("item_deleted", $old); } /** * Move this item to the specified target. * @chainable - * @param Item_Model $target Target item (must be an album - * @return ORM_MTPP + * @param Item_Model $target Target item (must be an album) + * @return ORM_MPTT */ function move_to($target) { if (!$target->is_album()) { @@ -134,8 +105,10 @@ class Item_Model extends ORM_MPTT { $original_path = $this->file_path(); $original_resize_path = $this->resize_path(); $original_thumb_path = $this->thumb_path(); + $original_parent = $this->parent(); parent::move_to($target, true); + model_cache::clear(); $this->relative_path_cache = null; rename($original_path, $this->file_path()); @@ -144,13 +117,15 @@ class Item_Model extends ORM_MPTT { @rename(dirname($original_thumb_path), dirname($this->thumb_path())); Database::instance() ->update("items", - array("relative_path_cache" => null), - array("left >" => $this->left, "right <" => $this->right)); + array("relative_path_cache" => null, + "relative_url_cache" => null), + array("left_ptr >" => $this->left_ptr, "right_ptr <" => $this->right_ptr)); } else { @rename($original_resize_path, $this->resize_path()); @rename($original_thumb_path, $this->thumb_path()); } + module::event("item_moved", $this, $original_parent); return $this; } @@ -169,7 +144,7 @@ class Item_Model extends ORM_MPTT { throw new Exception("@todo NAME_CANNOT_CONTAIN_SLASH"); } - $old_relative_path = $this->relative_path(); + $old_relative_path = urldecode($this->relative_path()); $new_relative_path = dirname($old_relative_path) . "/" . $new_name; @rename(VARPATH . "albums/$old_relative_path", VARPATH . "albums/$new_relative_path"); @rename(VARPATH . "resizes/$old_relative_path", VARPATH . "resizes/$new_relative_path"); @@ -179,22 +154,38 @@ class Item_Model extends ORM_MPTT { if ($this->is_album()) { Database::instance() ->update("items", - array("relative_path_cache" => null), - array("left >" => $this->left, "right <" => $this->right)); + array("relative_path_cache" => null, + "relative_url_cache" => null), + array("left_ptr >" => $this->left_ptr, "right_ptr <" => $this->right_ptr)); } return $this; } /** - * album: url::site("albums/2") - * photo: url::site("photos/3") + * Return the server-relative url to this item, eg: + * /gallery3/index.php/BobsWedding?page=2 + * /gallery3/index.php/BobsWedding/Eating-Cake.jpg + * + * @param string $query the query string (eg "show=3") + */ + public function url($query=null) { + $url = url::site($this->relative_url()); + if ($query) { + $url .= "?$query"; + } + return $url; + } + + /** + * Return the full url to this item, eg: + * http://example.com/gallery3/index.php/BobsWedding?page=2 + * http://example.com/gallery3/index.php/BobsWedding/Eating-Cake.jpg * * @param string $query the query string (eg "show=3") */ - public function url($query=array(), $full_uri=false) { - $url = ($full_uri ? url::abs_site("{$this->type}s/$this->id") - : url::site("{$this->type}s/$this->id")); + public function abs_url($query=null) { + $url = url::abs_site($this->relative_url()); if ($query) { $url .= "?$query"; } @@ -206,7 +197,7 @@ class Item_Model extends ORM_MPTT { * photo: /var/albums/album1/album2/photo.jpg */ public function file_path() { - return VARPATH . "albums/" . $this->relative_path(); + return VARPATH . "albums/" . urldecode($this->relative_path()); } /** @@ -214,9 +205,8 @@ class Item_Model extends ORM_MPTT { * photo: http://example.com/gallery3/var/albums/album1/photo.jpg */ public function file_url($full_uri=false) { - return $full_uri ? - url::abs_file("var/albums/" . $this->relative_path()) : - url::file("var/albums/" . $this->relative_path()); + $relative_path = "var/albums/" . $this->relative_path(); + return $full_uri ? url::abs_file($relative_path) : url::file($relative_path); } /** @@ -224,7 +214,7 @@ class Item_Model extends ORM_MPTT { * photo: /var/albums/album1/photo.thumb.jpg */ public function thumb_path() { - $base = VARPATH . "thumbs/" . $this->relative_path(); + $base = VARPATH . "thumbs/" . urldecode($this->relative_path()); if ($this->is_photo()) { return $base; } else if ($this->is_album()) { @@ -248,9 +238,8 @@ class Item_Model extends ORM_MPTT { */ public function thumb_url($full_uri=false) { $cache_buster = "?m=" . $this->updated; - $base = ($full_uri ? - url::abs_file("var/thumbs/" . $this->relative_path()) : - url::file("var/thumbs/" . $this->relative_path())); + $relative_path = "var/thumbs/" . $this->relative_path(); + $base = ($full_uri ? url::abs_file($relative_path) : url::file($relative_path)); if ($this->is_photo()) { return $base . $cache_buster; } else if ($this->is_album()) { @@ -267,7 +256,7 @@ class Item_Model extends ORM_MPTT { * photo: /var/albums/album1/photo.resize.jpg */ public function resize_path() { - return VARPATH . "resizes/" . $this->relative_path() . + return VARPATH . "resizes/" . urldecode($this->relative_path()) . ($this->is_album() ? "/.album.jpg" : ""); } @@ -276,14 +265,37 @@ class Item_Model extends ORM_MPTT { * photo: http://example.com/gallery3/var/albums/album1/photo.resize.jpg */ public function resize_url($full_uri=false) { - return ($full_uri ? - url::abs_file("var/resizes/" . $this->relative_path()) : - url::file("var/resizes/" . $this->relative_path())) . + $relative_path = "var/resizes/" . $this->relative_path(); + return ($full_uri ? url::abs_file($relative_path) : url::file($relative_path)) . ($this->is_album() ? "/.album.jpg" : ""); } /** - * Return the relative path to this item's file. + * Rebuild the relative_path_cache and relative_url_cache. + */ + private function _build_relative_caches() { + $names = array(); + $slugs = array(); + foreach (Database::instance() + ->select(array("name", "slug")) + ->from("items") + ->where("left_ptr <=", $this->left_ptr) + ->where("right_ptr >=", $this->right_ptr) + ->where("id <>", 1) + ->orderby("left_ptr", "ASC") + ->get() as $row) { + $names[] = rawurlencode($row->name); + $slugs[] = rawurlencode($row->slug); + } + $this->relative_path_cache = implode($names, "/"); + $this->relative_url_cache = implode($slugs, "/"); + $this->save(); + } + + /** + * Return the relative path to this item's file. Note that the components of the path are + * urlencoded so if you want to use this as a filesystem path, you need to call urldecode + * on it. * @return string */ public function relative_path() { @@ -292,24 +304,27 @@ class Item_Model extends ORM_MPTT { } if (!isset($this->relative_path_cache)) { - $paths = array(); - foreach (Database::instance() - ->select("name") - ->from("items") - ->where("left <=", $this->left) - ->where("right >=", $this->right) - ->where("id <>", 1) - ->orderby("left", "ASC") - ->get() as $row) { - $paths[] = $row->name; - } - $this->relative_path_cache = implode($paths, "/"); - $this->save(); + $this->_build_relative_caches(); } return $this->relative_path_cache; } /** + * Return the relative url to this item's file. + * @return string + */ + public function relative_url() { + if (!$this->loaded) { + return; + } + + if (!isset($this->relative_url_cache)) { + $this->_build_relative_caches(); + } + return $this->relative_url_cache; + } + + /** * @see ORM::__get() */ public function __get($column) { @@ -331,8 +346,18 @@ class Item_Model extends ORM_MPTT { */ public function __set($column, $value) { if ($column == "name") { - // Clear the relative path as it is no longer valid. $this->relative_path_cache = null; + } else if ($column == "slug") { + if ($this->slug != $value) { + // Clear the relative url cache for this item and all children + $this->relative_url_cache = null; + if ($this->is_album()) { + Database::instance() + ->update("items", + array("relative_url_cache" => null), + array("left_ptr >" => $this->left_ptr, "right_ptr <" => $this->right_ptr)); + } + } } parent::__set($column, $value); } @@ -341,15 +366,25 @@ class Item_Model extends ORM_MPTT { * @see ORM::save() */ public function save() { - if (!empty($this->changed) && $this->changed != array("view_count" => "view_count")) { + $significant_changes = $this->changed; + unset($significant_changes["view_count"]); + unset($significant_changes["relative_url_cache"]); + unset($significant_changes["relative_path_cache"]); + + if (!empty($this->changed) && $significant_changes) { $this->updated = time(); if (!$this->loaded) { $this->created = $this->updated; - $r = ORM::factory("item")->select("MAX(weight) as max_weight")->find(); - $this->weight = $r->max_weight + 1; + $this->weight = item::get_max_weight(); + } else { + $send_event = 1; } } - return parent::save(); + parent::save(); + if (isset($send_event)) { + module::event("item_updated", $this->original(), $this); + } + return $this; } /** @@ -387,10 +422,10 @@ class Item_Model extends ORM_MPTT { $db = Database::instance(); $position = $db->query(" SELECT COUNT(*) AS position FROM {items} - WHERE parent_id = {$this->id} + WHERE `parent_id` = {$this->id} AND `{$this->sort_column}` $comp (SELECT `{$this->sort_column}` - FROM {items} WHERE id = $child_id) - ORDER BY `{$this->sort_column}` {$this->sort_order}")->current()->position; + FROM {items} WHERE `id` = $child_id)") + ->current()->position; // We stopped short of our target value in the sort (notice that we're using a < comparator // above) because it's possible that we have duplicate values in the sort column. An @@ -402,9 +437,10 @@ class Item_Model extends ORM_MPTT { // our base value. $result = $db->query(" SELECT id FROM {items} - WHERE parent_id = {$this->id} + WHERE `parent_id` = {$this->id} AND `{$this->sort_column}` = (SELECT `{$this->sort_column}` - FROM {items} WHERE id = $child_id)"); + FROM {items} WHERE `id` = $child_id) + ORDER BY `id` ASC"); foreach ($result as $row) { $position++; if ($row->id == $child_id) { @@ -502,26 +538,38 @@ class Item_Model extends ORM_MPTT { } /** - * Return all of the children of this node, ordered by the defined sort order. + * Return all of the children of this album. Unless you specify a specific sort order, the + * results will be ordered by this album's sort order. * * @chainable * @param integer SQL limit * @param integer SQL offset + * @param array additional where clauses + * @param array orderby * @return array ORM */ - function children($limit=null, $offset=0) { - return parent::children($limit, $offset, array($this->sort_column => $this->sort_order)); + function children($limit=null, $offset=0, $where=array(), $orderby=null) { + if (empty($orderby)) { + $orderby = array($this->sort_column => $this->sort_order); + } + return parent::children($limit, $offset, $where, $orderby); } /** - * Return all of the children of the specified type, ordered by the defined sort order. + * Return the children of this album, and all of it's sub-albums. Unless you specify a specific + * sort order, the results will be ordered by this album's sort order. Note that this + * album's sort order is imposed on all sub-albums, regardless of their sort order. + * + * @chainable * @param integer SQL limit * @param integer SQL offset - * @param string type to return + * @param array additional where clauses * @return object ORM_Iterator */ - function descendants($limit=null, $offset=0, $type=null) { - return parent::descendants($limit, $offset, $type, - array($this->sort_column => $this->sort_order)); + function descendants($limit=null, $offset=0, $where=array(), $orderby=null) { + if (empty($orderby)) { + $orderby = array($this->sort_column => $this->sort_order); + } + return parent::descendants($limit, $offset, $where, $orderby); } } diff --git a/modules/gallery/module.info b/modules/gallery/module.info index cefcaa08..70bd91e2 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 = 12 diff --git a/modules/gallery/tests/Access_Helper_Test.php b/modules/gallery/tests/Access_Helper_Test.php index d71bf971..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"); @@ -324,4 +361,40 @@ class Access_Helper_Test extends Unit_Test_Case { $this->assert_false(file_exists($album->resize_path() . "/.htaccess")); $this->assert_false(file_exists($album->thumb_path() . "/.htaccess")); } + + public function moved_items_inherit_new_permissions_test() { + user::set_active(user::lookup_by_name("admin")); + + $root = ORM::factory("item", 1); + $public_album = album::create($root, rand(), "public album"); + $public_photo = photo::create($public_album, MODPATH . "gallery/images/gallery.png", "", ""); + access::allow(group::everybody(), "view", $public_album); + + $root->reload(); // Account for MPTT changes + + $private_album = album::create($root, rand(), "private album"); + access::deny(group::everybody(), "view", $private_album); + $private_photo = photo::create($private_album, MODPATH . "gallery/images/gallery.png", "", ""); + + // Make sure that we now have a public photo and private photo. + $this->assert_true(access::group_can(group::everybody(), "view", $public_photo)); + $this->assert_false(access::group_can(group::everybody(), "view", $private_photo)); + + // Swap the photos + item::move($public_photo, $private_album); + $private_album->reload(); // Reload to get new MPTT pointers and cached perms. + $public_album->reload(); + $private_photo->reload(); + $public_photo->reload(); + + item::move($private_photo, $public_album); + $private_album->reload(); // Reload to get new MPTT pointers and cached perms. + $public_album->reload(); + $private_photo->reload(); + $public_photo->reload(); + + // Make sure that the public_photo is now private, and the private_photo is now public. + $this->assert_false(access::group_can(group::everybody(), "view", $public_photo)); + $this->assert_true(access::group_can(group::everybody(), "view", $private_photo)); + } } diff --git a/modules/gallery/tests/Albums_Controller_Test.php b/modules/gallery/tests/Albums_Controller_Test.php index 7674e85f..d65946c7 100644 --- a/modules/gallery/tests/Albums_Controller_Test.php +++ b/modules/gallery/tests/Albums_Controller_Test.php @@ -52,7 +52,7 @@ class Albums_Controller_Test extends Unit_Test_Case { ob_end_clean(); $this->assert_equal( - json_encode(array("result" => "success", "location" => "http://./index.php/test")), + json_encode(array("result" => "success")), $results); $this->assert_equal("new title", $this->_album->title); $this->assert_equal("new description", $this->_album->description); diff --git a/modules/gallery/tests/Database_Test.php b/modules/gallery/tests/Database_Test.php index bd3d2f53..d83212ad 100644 --- a/modules/gallery/tests/Database_Test.php +++ b/modules/gallery/tests/Database_Test.php @@ -103,15 +103,15 @@ class Database_Test extends Unit_Test_Case { $sql = "UPDATE {test_tables} SET `name` = '{test string}' " . "WHERE `item_id` IN " . " (SELECT `id` FROM {items} " . - " WHERE `left` >= 1 " . - " AND `right` <= 6)"; + " WHERE `left_ptr` >= 1 " . + " AND `right_ptr` <= 6)"; $sql = $db->add_table_prefixes($sql); $expected = "UPDATE g3test_test_tables SET `name` = '{test string}' " . "WHERE `item_id` IN " . " (SELECT `id` FROM g3test_items " . - " WHERE `left` >= 1 " . - " AND `right` <= 6)"; + " WHERE `left_ptr` >= 1 " . + " AND `right_ptr` <= 6)"; $this->assert_same($expected, $sql); } diff --git a/modules/gallery/tests/DrawForm_Test.php b/modules/gallery/tests/DrawForm_Test.php index 2c5aaba4..dde54257 100644 --- a/modules/gallery/tests/DrawForm_Test.php +++ b/modules/gallery/tests/DrawForm_Test.php @@ -80,5 +80,44 @@ class DrawForm_Test extends Unit_Test_Case { $this->assert_same($expected, $rendered); } + function form_script_test() { + $form = new Forge("test/controller", "", "post", array("id" => "gTestGroupForm")); + $group = $form->group("test_group")->label(t("Test Group")); + $group->input("title")->label(t("Title")); + $group->textarea("description")->label(t("Text Area")); + $form->script("") + ->url(url::file("test.js")) + ->text("alert('Test Javascript');"); + $group->submit("")->value(t("Submit")); + $rendered = $form->__toString(); + + $expected = "<form action=\"http://./index.php/test/controller\" method=\"post\" " . + "id=\"gTestGroupForm\">\n" . + "<input type=\"hidden\" name=\"csrf\" value=\"" . access::csrf_token() . "\" />\n" . + " <fieldset>\n" . + " <legend>Test Group</legend>\n" . + " <ul>\n" . + " <li>\n" . + " <label for=\"title\" >Title</label>\n" . + " <input type=\"text\" id=\"title\" name=\"title\" value=\"\" " . + "class=\"textbox\" />\n" . + " </li>\n" . + " <li>\n" . + " <label for=\"description\" >Text Area</label>\n" . + " <textarea id=\"description\" name=\"description\" " . + "class=\"textarea\" ></textarea>\n" . + " </li>\n" . + " <li>\n" . + " <input type=\"submit\" value=\"Submit\" class=\"submit\" />\n" . + " </li>\n" . + " </ul>\n" . + " </fieldset>\n" . + "<script type=\"text/javascript\" src=\"http://./test.js\"></script>\n\n" . + "<script type=\"text/javascript\">\n" . + "alert('Test Javascript');\n" . + "</script>\n" . + "</form>\n"; + $this->assert_same($expected, $rendered); + } } diff --git a/modules/gallery/tests/File_Structure_Test.php b/modules/gallery/tests/File_Structure_Test.php index 8a97e00b..9018f4c6 100644 --- a/modules/gallery/tests/File_Structure_Test.php +++ b/modules/gallery/tests/File_Structure_Test.php @@ -177,10 +177,20 @@ class File_Structure_Test extends Unit_Test_Case { new GalleryCodeFilterIterator( new RecursiveIteratorIterator( new RecursiveDirectoryIterator(DOCROOT)))); + $errors = array(); foreach ($dir as $file) { - $this->assert_false( - preg_match('/\t/', file_get_contents($file)), - "{$file->getPathname()} has tabs in it"); + $file_as_string = file_get_contents($file); + if (preg_match('/\t/', $file_as_string)) { + foreach (split("\n", $file_as_string) as $l => $line) { + if (preg_match('/\t/', $line)) { + $errors[] = "$file:$l has tab(s) ($line)"; + } + } + } + $file_as_string = null; + } + if ($errors) { + $this->assert_false(true, "tab(s) found:\n" . join("\n", $errors)); } } diff --git a/modules/gallery/tests/Gallery_Installer_Test.php b/modules/gallery/tests/Gallery_Installer_Test.php index 27157d6e..36ced2bb 100644 --- a/modules/gallery/tests/Gallery_Installer_Test.php +++ b/modules/gallery/tests/Gallery_Installer_Test.php @@ -34,13 +34,13 @@ class Gallery_Installer_Test extends Unit_Test_Case { } public function install_creates_root_item_test() { - $max_right = ORM::factory("item") - ->select("MAX(`right`) AS `right`") - ->find()->right; + $max_right_ptr = ORM::factory("item") + ->select("MAX(`right_ptr`) AS `right_ptr`") + ->find()->right_ptr; $root = ORM::factory('item')->find(1); $this->assert_equal("Gallery", $root->title); - $this->assert_equal(1, $root->left); - $this->assert_equal($max_right, $root->right); + $this->assert_equal(1, $root->left_ptr); + $this->assert_equal($max_right_ptr, $root->right_ptr); $this->assert_equal(null, $root->parent_id); $this->assert_equal(1, $root->level); } diff --git a/modules/gallery/tests/Html_Helper_Test.php b/modules/gallery/tests/Html_Helper_Test.php new file mode 100644 index 00000000..1662b866 --- /dev/null +++ b/modules/gallery/tests/Html_Helper_Test.php @@ -0,0 +1,57 @@ +<?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 Html_Helper_Test extends Unit_Test_Case { + public function clean_test() { + $safe_string = html::clean("hello <p >world</p>"); + $this->assert_equal("hello <p >world</p>", + $safe_string); + $this->assert_true($safe_string instanceof SafeString); + } + + public function purify_test() { + $safe_string = html::purify("hello <p >world</p>"); + $expected = method_exists("purifier", "purify") + ? "hello <p>world</p>" + : "hello <p >world</p>"; + $this->assert_equal($expected, $safe_string->unescaped()); + $this->assert_true($safe_string instanceof SafeString); + } + + public function mark_clean_test() { + $safe_string = html::mark_clean("hello <p >world</p>"); + $this->assert_true($safe_string instanceof SafeString); + $safe_string_2 = html::clean($safe_string); + $this->assert_equal("hello <p >world</p>", + $safe_string_2); + } + + public function js_string_test() { + $string = html::js_string("hello's <p >world</p>"); + $this->assert_equal('"hello\'s <p >world<\\/p>"', + $string); + } + + public function clean_attribute_test() { + $safe_string = SafeString::of_safe_html("hello's <p >world</p>"); + $safe_string = html::clean_attribute($safe_string); + $this->assert_equal("hello's <p >world</p>", + $safe_string); + } +}
\ No newline at end of file diff --git a/modules/gallery/tests/Item_Helper_Test.php b/modules/gallery/tests/Item_Helper_Test.php new file mode 100644 index 00000000..33fcdb73 --- /dev/null +++ b/modules/gallery/tests/Item_Helper_Test.php @@ -0,0 +1,70 @@ +<?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 Item_Helper_Test extends Unit_Test_Case { + + public function viewable_test() { + $root = ORM::factory("item", 1); + $album = album::create($root, rand(), rand(), rand()); + $item = self::_create_random_item($album); + user::set_active(user::guest()); + + // We can see the item when permissions are granted + access::allow(group::everybody(), "view", $album); + $this->assert_equal( + 1, + ORM::factory("item")->viewable()->where("id", $item->id)->count_all()); + + // We can't see the item when permissions are denied + access::deny(group::everybody(), "view", $album); + $this->assert_equal( + 0, + ORM::factory("item")->viewable()->where("id", $item->id)->count_all()); + } + + public function validate_url_safe_test() { + $input = new MockInput(); + $input->value = "Ab_cd-ef-d9"; + item::validate_url_safe($input); + $this->assert_true(!isset($input->not_url_safe)); + + $input->value = "ab&cd"; + item::validate_url_safe($input); + $this->assert_equal(1, $input->not_url_safe); + } + + public function convert_filename_to_slug_test() { + $this->assert_equal("foo", item::convert_filename_to_slug("{[foo]}")); + $this->assert_equal("foo-bar", item::convert_filename_to_slug("{[foo!@#!$@#^$@($!(@bar]}")); + } + + private static function _create_random_item($album) { + // Set all required fields (values are irrelevant) + $item = ORM::factory("item"); + $item->name = rand(); + $item->type = "photo"; + return $item->add_to_parent($album); + } +} + +class MockInput { + function add_error($error, $value) { + $this->$error = $value; + } +}
\ No newline at end of file diff --git a/modules/gallery/tests/Item_Model_Test.php b/modules/gallery/tests/Item_Model_Test.php index 615b8997..84210e4c 100644 --- a/modules/gallery/tests/Item_Model_Test.php +++ b/modules/gallery/tests/Item_Model_Test.php @@ -19,12 +19,12 @@ */ class Item_Model_Test extends Unit_Test_Case { public function saving_sets_created_and_updated_dates_test() { - $item = self::create_random_item(); + $item = self::_create_random_item(); $this->assert_true(!empty($item->created)); $this->assert_true(!empty($item->updated)); } - private function create_random_item() { + private static function _create_random_item() { $item = ORM::factory("item"); /* Set all required fields (values are irrelevant) */ $item->name = rand(); @@ -33,7 +33,7 @@ class Item_Model_Test extends Unit_Test_Case { } public function updating_doesnt_change_created_date_test() { - $item = self::create_random_item(); + $item = self::_create_random_item(); // Force the creation date to something well known $db = Database::instance(); @@ -47,7 +47,7 @@ class Item_Model_Test extends Unit_Test_Case { } public function updating_view_count_only_doesnt_change_updated_date_test() { - $item = self::create_random_item(); + $item = self::_create_random_item(); $item->reload(); $this->assert_same(0, $item->view_count); @@ -64,7 +64,7 @@ class Item_Model_Test extends Unit_Test_Case { public function move_photo_test() { // Create a test photo - $item = self::create_random_item(); + $item = self::_create_random_item(); file_put_contents($item->thumb_path(), "thumb"); file_put_contents($item->resize_path(), "resize"); @@ -128,7 +128,7 @@ class Item_Model_Test extends Unit_Test_Case { public function item_rename_wont_accept_slash_test() { // Create a test photo - $item = self::create_random_item(); + $item = self::_create_random_item(); $new_name = rand() . "/"; @@ -140,4 +140,24 @@ class Item_Model_Test extends Unit_Test_Case { } $this->assert_false(true, "Item_Model::rename should not accept / characters"); } + + public function save_original_values_test() { + $item = self::_create_random_item(); + $item->title = "ORIGINAL_VALUE"; + $item->save(); + $item->title = "NEW_VALUE"; + + $this->assert_same("ORIGINAL_VALUE", $item->original()->title); + $this->assert_same("NEW_VALUE", $item->title); + } + + public function urls_are_rawurlencoded_test() { + $item = self::_create_random_item(); + $item->slug = "foo bar"; + $item->name = "foo bar.jpg"; + $item->save(); + + $this->assert_equal("foo%20bar", $item->relative_url()); + $this->assert_equal("foo%20bar.jpg", $item->relative_path()); + } } diff --git a/modules/gallery/tests/Locales_Helper_Test.php b/modules/gallery/tests/Locales_Helper_Test.php new file mode 100644 index 00000000..85b8e206 --- /dev/null +++ b/modules/gallery/tests/Locales_Helper_Test.php @@ -0,0 +1,86 @@ +<?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 Locales_Helper_Test extends Unit_Test_Case { + static $installed_locales; + static $default_locale; + + public function setup() { + self::$installed_locales = locales::installed(); + self::$default_locale = module::get_var("gallery", "default_locale"); + locales::update_installed(array_keys(locales::available())); + module::set_var("gallery", "default_locale", "no_NO"); + } + + public function teardown() { + locales::update_installed(array_keys(self::$installed_locales)); + module::set_var("gallery", "default_locale", self::$default_locale); + } + + public function locale_from_http_request_test() { + $_SERVER["HTTP_ACCEPT_LANGUAGE"] = "de-de"; + $locale = locales::locale_from_http_request(); + $this->assert_equal("de_DE", $locale); + } + + public function locale_from_http_request_fallback_test() { + $_SERVER["HTTP_ACCEPT_LANGUAGE"] = "de"; + $locale = locales::locale_from_http_request(); + $this->assert_equal("de_DE", $locale); + } + + public function locale_from_http_request_by_qvalue_test() { + $_SERVER["HTTP_ACCEPT_LANGUAGE"] = "de-de;q=0.8,fr-fr;q=0.9"; + $locale = locales::locale_from_http_request(); + $this->assert_equal("fr_FR", $locale); + } + + public function locale_from_http_request_default_qvalue_test() { + $_SERVER["HTTP_ACCEPT_LANGUAGE"] = "de-de;q=0.8,it-it,fr-fr;q=0.9"; + $locale = locales::locale_from_http_request(); + $this->assert_equal("it_IT", $locale); + } + + public function locale_from_http_request_lang_fallback_qvalue_adjustment_test() { + $_SERVER["HTTP_ACCEPT_LANGUAGE"] = ",fr-fr;q=0.4,de-ch;q=0.8"; + $locale = locales::locale_from_http_request(); + $this->assert_equal("de_DE", $locale); + } + + public function locale_from_http_request_best_match_vs_installed_test() { + locales::update_installed(array("no_NO", "pt_PT", "ja_JP")); + $_SERVER["HTTP_ACCEPT_LANGUAGE"] = "en,en-us,ja_JP;q=0.7,no-fr;q=0.9"; + $locale = locales::locale_from_http_request(); + $this->assert_equal("ja_JP", $locale); + } + + public function locale_from_http_request_best_match_vs_installed_2_test() { + locales::update_installed(array("no_NO", "pt_PT", "ja_JP")); + $_SERVER["HTTP_ACCEPT_LANGUAGE"] = "en,en-us,ja_JP;q=0.5,no-fr;q=0.9"; + $locale = locales::locale_from_http_request(); + $this->assert_equal("no_NO", $locale); + } + + public function locale_from_http_request_no_match_vs_installed_test() { + locales::update_installed(array("no_NO", "pt_PT", "ja_JP")); + $_SERVER["HTTP_ACCEPT_LANGUAGE"] = "en,en-us,de"; + $locale = locales::locale_from_http_request(); + $this->assert_equal(null, $locale); + } +}
\ No newline at end of file diff --git a/modules/gallery/tests/Movie_Helper_Test.php b/modules/gallery/tests/Movie_Helper_Test.php index 627651bb..23544934 100644 --- a/modules/gallery/tests/Movie_Helper_Test.php +++ b/modules/gallery/tests/Movie_Helper_Test.php @@ -22,7 +22,7 @@ class Movie_Helper_Test extends Unit_Test_Case { $rand = rand(); $root = ORM::factory("item", 1); try { - $movie = movie::create($root, MODPATH . "gallery/tests/test.jpg", "$rand/.jpg", $rand, $rand); + $movie = movie::create($root, MODPATH . "gallery/tests/test.flv", "$rand/.flv", $rand, $rand); } catch (Exception $e) { // pass return; @@ -35,7 +35,7 @@ class Movie_Helper_Test extends Unit_Test_Case { $rand = rand(); $root = ORM::factory("item", 1); try { - $movie = movie::create($root, MODPATH . "gallery/tests/test.jpg", "$rand.jpg.", $rand, $rand); + $movie = movie::create($root, MODPATH . "gallery/tests/test.flv", "$rand.flv.", $rand, $rand); } catch (Exception $e) { $this->assert_equal("@todo NAME_CANNOT_END_IN_PERIOD", $e->getMessage()); return; @@ -43,4 +43,14 @@ class Movie_Helper_Test extends Unit_Test_Case { $this->assert_true(false, "Shouldn't create a movie with trailing . in the name"); } + + public function create_movie_creates_reasonable_slug_test() { + $rand = rand(); + $root = ORM::factory("item", 1); + $album = album::create($root, $rand, $rand, $rand); + $movie = movie::create( + $album, MODPATH . "gallery/tests/test.flv", "This (is) my file%name.flv", $rand, $rand); + + $this->assert_equal("This-is-my-file-name", $movie->slug); + } } diff --git a/modules/gallery/tests/ORM_MPTT_Test.php b/modules/gallery/tests/ORM_MPTT_Test.php index 200c8a74..a749542b 100644 --- a/modules/gallery/tests/ORM_MPTT_Test.php +++ b/modules/gallery/tests/ORM_MPTT_Test.php @@ -33,8 +33,8 @@ class ORM_MPTT_Test extends Unit_Test_Case { $album->sort_order = "ASC"; $album->add_to_parent($root); - $this->assert_equal($album->parent()->right - 2, $album->left); - $this->assert_equal($album->parent()->right - 1, $album->right); + $this->assert_equal($album->parent()->right_ptr - 2, $album->left_ptr); + $this->assert_equal($album->parent()->right_ptr - 1, $album->right_ptr); $this->assert_equal($album->parent()->level + 1, $album->level); $this->assert_equal($album->parent()->id, $album->parent_id); } @@ -48,10 +48,10 @@ class ORM_MPTT_Test extends Unit_Test_Case { $album1_1_2 = self::create_item_and_add_to_parent($album1_1); $album1->reload(); - $this->assert_equal(9, $album1->right - $album1->left); + $this->assert_equal(9, $album1->right_ptr - $album1->left_ptr); $album1_1->reload(); - $this->assert_equal(5, $album1_1->right - $album1_1->left); + $this->assert_equal(5, $album1_1->right_ptr - $album1_1->left_ptr); } public function delete_hierarchy_test() { @@ -66,7 +66,7 @@ class ORM_MPTT_Test extends Unit_Test_Case { $album1->reload(); // Now album1 contains only album1_2 - $this->assert_equal(3, $album1->right - $album1->left); + $this->assert_equal(3, $album1->right_ptr - $album1->left_ptr); } public function move_to_test() { @@ -85,8 +85,8 @@ class ORM_MPTT_Test extends Unit_Test_Case { $album1_1->reload(); $album1_2->reload(); - $this->assert_equal(3, $album1_1->right - $album1_1->left); - $this->assert_equal(3, $album1_2->right - $album1_2->left); + $this->assert_equal(3, $album1_1->right_ptr - $album1_1->left_ptr); + $this->assert_equal(3, $album1_2->right_ptr - $album1_2->left_ptr); $this->assert_equal( array($album1_1_2->id => "move_to_test_1_1_2"), @@ -97,6 +97,19 @@ class ORM_MPTT_Test extends Unit_Test_Case { $album1_2->children()->select_list()); } + public function cant_move_parent_into_own_subtree_test() { + $album1 = album::create(item::root(), "move_to_test", "move_to_test"); + $album2 = album::create($album1, "move_to_test", "move_to_test"); + $album3 = album::create($album2, "move_to_test", "move_to_test"); + + try { + $album1->move_to($album3); + $self->assert_true(false, "We should be unable to move an item inside its own hierarchy"); + } catch (Exception $e) { + // pass + } + } + public function parent_test() { $root = ORM::factory("item", 1); $album = self::create_item_and_add_to_parent($root); @@ -177,8 +190,8 @@ class ORM_MPTT_Test extends Unit_Test_Case { $parent->reload(); $this->assert_equal(3, $parent->descendants()->count()); - $this->assert_equal(2, $parent->descendants(null, 0, "photo")->count()); - $this->assert_equal(1, $parent->descendants(null, 0, "album")->count()); + $this->assert_equal(2, $parent->descendants(null, 0, array("type" => "photo"))->count()); + $this->assert_equal(1, $parent->descendants(null, 0, array("type" => "album"))->count()); } public function descendant_limit_test() { @@ -215,7 +228,7 @@ class ORM_MPTT_Test extends Unit_Test_Case { $parent->reload(); $this->assert_equal(3, $parent->descendants_count()); - $this->assert_equal(2, $parent->descendants_count("photo")); - $this->assert_equal(1, $parent->descendants_count("album")); + $this->assert_equal(2, $parent->descendants_count(array("type" => "photo"))); + $this->assert_equal(1, $parent->descendants_count(array("type" => "album"))); } } diff --git a/modules/gallery/tests/Photo_Helper_Test.php b/modules/gallery/tests/Photo_Helper_Test.php index cc1f20da..da455bf8 100644 --- a/modules/gallery/tests/Photo_Helper_Test.php +++ b/modules/gallery/tests/Photo_Helper_Test.php @@ -43,8 +43,8 @@ class Photo_Helper_Test extends Unit_Test_Case { $this->assert_equal($image_info[0], $photo->width); $this->assert_equal($image_info[1], $photo->height); - $this->assert_equal($photo->parent()->right - 2, $photo->left); - $this->assert_equal($photo->parent()->right - 1, $photo->right); + $this->assert_equal($photo->parent()->right_ptr - 2, $photo->left_ptr); + $this->assert_equal($photo->parent()->right_ptr - 1, $photo->right_ptr); } public function create_conflicting_photo_test() { @@ -81,6 +81,16 @@ class Photo_Helper_Test extends Unit_Test_Case { $this->assert_equal("http://./var/resizes/{$rand}/{$rand}.jpg", $photo->resize_url()); } + public function create_photo_creates_reasonable_slug_test() { + $rand = rand(); + $root = ORM::factory("item", 1); + $album = album::create($root, $rand, $rand, $rand); + $photo = photo::create( + $album, MODPATH . "gallery/tests/test.jpg", "This (is) my file%name.jpg", $rand, $rand); + + $this->assert_equal("This-is-my-file-name", $photo->slug); + } + public function create_photo_shouldnt_allow_names_with_slash_test() { $rand = rand(); $root = ORM::factory("item", 1); diff --git a/modules/gallery/tests/Photos_Controller_Test.php b/modules/gallery/tests/Photos_Controller_Test.php index f7d3f72f..0159b420 100644 --- a/modules/gallery/tests/Photos_Controller_Test.php +++ b/modules/gallery/tests/Photos_Controller_Test.php @@ -20,57 +20,54 @@ class Photos_Controller_Test extends Unit_Test_Case { public function setup() { $this->_post = $_POST; - $this->_photo = null; } public function teardown() { $_POST = $this->_post; - if ($this->_photo) { - $this->_photo->delete(); - } } public function change_photo_test() { $controller = new Photos_Controller(); $root = ORM::factory("item", 1); - $this->_photo = photo::create($root, MODPATH . "gallery/tests/test.jpg", "test.jpeg", "test", - "test"); - $orig_name = $this->_photo->name; + $photo = photo::create( + $root, MODPATH . "gallery/tests/test.jpg", "test.jpeg", + "test", "test", user::active(), "slug"); + $orig_name = $photo->name; $_POST["filename"] = "test.jpeg"; $_POST["name"] = "new name"; $_POST["title"] = "new title"; $_POST["description"] = "new description"; + $_POST["slug"] = "new-slug"; $_POST["csrf"] = access::csrf_token(); access::allow(group::everybody(), "edit", $root); ob_start(); - $controller->_update($this->_photo); + $controller->_update($photo); $results = ob_get_contents(); ob_end_clean(); - $this->assert_equal( - json_encode(array("result" => "success", - "location" => "http://./index.php/test.jpeg")), - $results); - $this->assert_equal("new title", $this->_photo->title); - $this->assert_equal("new description", $this->_photo->description); + $this->assert_equal(json_encode(array("result" => "success")), $results); + $this->assert_equal("new-slug", $photo->slug); + $this->assert_equal("new title", $photo->title); + $this->assert_equal("new description", $photo->description); // We don't change the name, yet. - $this->assert_equal($orig_name, $this->_photo->name); + $this->assert_equal($orig_name, $photo->name); } public function change_photo_no_csrf_fails_test() { $controller = new Photos_Controller(); $root = ORM::factory("item", 1); - $this->_photo = photo::create($root, MODPATH . "gallery/tests/test.jpg", "test", "test", "test"); + $photo = photo::create( + $root, MODPATH . "gallery/tests/test.jpg", "test.jpg", "test", "test"); $_POST["name"] = "new name"; $_POST["title"] = "new title"; $_POST["description"] = "new description"; access::allow(group::everybody(), "edit", $root); try { - $controller->_update($this->_photo); + $controller->_update($photo); $this->assert_true(false, "This should fail"); } catch (Exception $e) { // pass diff --git a/modules/gallery/tests/SafeString_Test.php b/modules/gallery/tests/SafeString_Test.php new file mode 100644 index 00000000..2c07d934 --- /dev/null +++ b/modules/gallery/tests/SafeString_Test.php @@ -0,0 +1,139 @@ +<?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 SafeString_Test extends Unit_Test_Case { + public function toString_escapes_for_html_test() { + $safe_string = new SafeString("hello <p>world</p>"); + $this->assert_equal("hello <p>world</p>", + $safe_string); + } + + public function toString_for_safe_string_test() { + $safe_string = SafeString::of_safe_html("hello <p>world</p>"); + $this->assert_equal("hello <p>world</p>", + $safe_string); + } + + public function for_html_test() { + $safe_string = new SafeString("hello <p>world</p>"); + $this->assert_equal("hello <p>world</p>", + $safe_string->for_html()); + } + + public function safestring_of_safestring_test() { + $safe_string = new SafeString("hello <p>world</p>"); + $safe_string_2 = new SafeString($safe_string); + $this->assert_true($safe_string_2 instanceof SafeString); + $raw_string = $safe_string_2->unescaped(); + $this->assert_false(is_object($raw_string)); + $this->assert_equal("hello <p>world</p>", $raw_string); + $this->assert_equal("hello <p>world</p>", $safe_string_2); + } + + public function for_js_test() { + $safe_string = new SafeString('"<em>Foo</em>\'s bar"'); + $js_string = $safe_string->for_js(); + $this->assert_equal('"\\"<em>Foo<\\/em>\'s bar\\""', + $js_string); + } + + public function for_html_attr_test() { + $safe_string = new SafeString('"<em>Foo</em>\'s bar"'); + $attr_string = $safe_string->for_html_attr(); + $this->assert_equal('"<em>Foo</em>'s bar"', + $attr_string); + } + + public function for_html_attr_with_safe_html_test() { + $safe_string = SafeString::of_safe_html('"<em>Foo</em>\'s bar"'); + $attr_string = $safe_string->for_html_attr(); + $this->assert_equal('"<em>Foo</em>'s bar"', + $attr_string); + } + + public function string_safestring_equality_test() { + $safe_string = new SafeString("hello <p>world</p>"); + $this->assert_equal("hello <p>world</p>", + $safe_string->unescaped()); + $escaped_string = "hello <p>world</p>"; + $this->assert_equal($escaped_string, $safe_string); + + $this->assert_true($escaped_string == $safe_string); + $this->assert_false($escaped_string === $safe_string); + $this->assert_false("meow" == $safe_string); + } + + public function of_test() { + $safe_string = SafeString::of("hello <p>world</p>"); + $this->assert_equal("hello <p>world</p>", $safe_string->unescaped()); + } + + public function of_safe_html_test() { + $safe_string = SafeString::of_safe_html("hello <p>world</p>"); + $this->assert_equal("hello <p>world</p>", $safe_string->for_html()); + } + + public function purify_test() { + $safe_string = SafeString::purify("hello <p >world</p>"); + $expected = method_exists("purifier", "purify") + ? "hello <p>world</p>" + : "hello <p >world</p>"; + $this->assert_equal($expected, $safe_string); + } + + public function purify_twice_test() { + $safe_string = SafeString::purify("hello <p >world</p>"); + $safe_string_2 = SafeString::purify($safe_string); + $expected = method_exists("purifier", "purify") + ? "hello <p>world</p>" + : "hello <p >world</p>"; + $this->assert_equal($expected, $safe_string_2); + } + + public function purify_safe_html_test() { + $safe_string = SafeString::of_safe_html("hello <p >world</p>"); + $actual = SafeString::purify($safe_string); + $this->assert_equal("hello <p >world</p>", $actual); + } + + public function of_fluid_api_test() { + $escaped_string = SafeString::of("Foo's bar")->for_js(); + $this->assert_equal('"Foo\'s bar"', $escaped_string); + } + + public function safestring_of_safestring_preserves_safe_status_test() { + $safe_string = SafeString::of_safe_html("hello's <p>world</p>"); + $safe_string_2 = new SafeString($safe_string); + $this->assert_equal("hello's <p>world</p>", $safe_string_2); + $this->assert_equal('"hello\'s <p>world<\\/p>"', $safe_string_2->for_js()); + } + + public function safestring_of_safestring_preserves_html_safe_status_test() { + $safe_string = SafeString::of_safe_html("hello's <p>world</p>"); + $safe_string_2 = new SafeString($safe_string); + $this->assert_equal("hello's <p>world</p>", $safe_string_2); + $this->assert_equal('"hello\'s <p>world<\\/p>"', $safe_string_2->for_js()); + } + + public function safestring_of_safestring_safe_status_override_test() { + $safe_string = new SafeString("hello <p>world</p>"); + $safe_string_2 = SafeString::of_safe_html($safe_string); + $this->assert_equal("hello <p>world</p>", $safe_string_2); + } +} diff --git a/modules/gallery/tests/Xss_Security_Test.php b/modules/gallery/tests/Xss_Security_Test.php index e179482c..85624517 100644 --- a/modules/gallery/tests/Xss_Security_Test.php +++ b/modules/gallery/tests/Xss_Security_Test.php @@ -19,87 +19,447 @@ */ class Xss_Security_Test extends Unit_Test_Case { public function find_unescaped_variables_in_views_test() { + $found = array(); foreach (glob("*/*/views/*.php") as $view) { - $expr = null; - $level = 0; - $php = 0; - $str = null; - $in_p_clean = 0; + // List of all tokens without whitespace, simplifying parsing. + $tokens = array(); foreach (token_get_all(file_get_contents($view)) as $token) { - if (false /* useful for debugging */) { - if (is_array($token)) { - printf("[$str] [$in_p_clean] %-15s %s\n", token_name($token[0]), $token[1]); - } else { - printf("[$str] [$in_p_clean] %-15s %s\n", "<char>", $token); - } + if (!is_array($token) || ($token[0] != T_WHITESPACE)) { + $tokens[] = $token; } + } + + $frame = null; + $script_block = 0; + $in_script_block = false; + $inline_html = ""; + $in_attribute_js_context = false; + $in_attribute = false; + $href_attribute_start = false; + $preceded_by_quote = false; + + for ($token_number = 0; $token_number < count($tokens); $token_number++) { + $token = $tokens[$token_number]; + + // Are we in a <script> ... </script> block? + if (is_array($token) && $token[0] == T_INLINE_HTML) { + $inline_html = $token[1]; + // T_INLINE_HTML blocks can be split. Need to handle the case + // where one token has "<scr" and the next has "ipt" + while (self::_token_matches(array(T_INLINE_HTML), $tokens, $token_number + 1)) { + $token_number++; + $token = $tokens[$token_number]; + $inline_html .= $token[1]; + } - // If we find a "(" after a "p::clean" then start counting levels of parens and assume - // that we're inside a p::clean() call until we find the matching close paren. - if ($token[0] == "(" && $str == "p::clean") { - $in_p_clean = 1; - } else if ($token[0] == "(" && $in_p_clean) { - $in_p_clean++; - } else if ($token[0] == ")" && $in_p_clean) { - $in_p_clean--; + $inline_html = str_replace("\n", " ", $inline_html); + + if ($frame) { + $frame->expr_append($inline_html); + } + + // Note: This approach won't catch <script src="..."> blocks if the src + // URL is generated via < ? = url::site() ? > or some other PHP. + // Assume that all such script blocks with a src URL have an + // empty element body. + // But we'll catch closing tags for such blocks, so don't keep track + // of opening / closing tag count since it would be meaningless. + + // Handle multiple start / end blocks on the same line? + $opening_script_pos = $closing_script_pos = -1; + if (preg_match_all('{</script>}i', $inline_html, $matches, PREG_OFFSET_CAPTURE)) { + $last_match = array_pop($matches[0]); + if (is_array($last_match)) { + $closing_script_pos = $last_match[1]; + } else { + $closing_script_pos = $last_match; + } + } + if (preg_match_all('{<script\b[^>]*>}i', $inline_html, $matches, PREG_OFFSET_CAPTURE)) { + $last_match = array_pop($matches[0]); + if (is_array($last_match)) { + $opening_script_pos = $last_match[1]; + } else { + $opening_script_pos = $last_match; + } + } + if ($opening_script_pos != $closing_script_pos) { + $in_script_block = $opening_script_pos > $closing_script_pos; + } } - // Concatenate runs of strings for convenience, which we use above to figure out if we're - // inside a p::clean() call or not - if ($token[0] == T_STRING || $token[0] == T_DOUBLE_COLON) { - $str .= $token[1]; - } else { - $str = null; + $preceded_by_quote = preg_match('{[\'"]\s*$}i', $inline_html); + + $pos = false; + if (($in_attribute || $in_attribute_js_context) && + ($pos = strpos($inline_html, $delimiter)) !== false) { + $in_attribute_js_context = false; + $in_attribute = false; + $href_attribute_start = false; + } + if (!$in_attribute_js_context || !$in_attribute) { + $pos = ($pos === false) ? 0 : $pos; + if (preg_match('{\bhref\s*=\s*(")javascript:[^"]*$}i', $inline_html, $matches, 0, $pos) || + preg_match("{\bhref\s*=\s*(')javascript:[^']*$}i", $inline_html, $matches, 0, $pos) || + preg_match("{\bon[a-z]+\s*=\s*(')[^']*$}i", $inline_html, $matches, 0, $pos) || + preg_match('{\bon[a-z]+\s*=\s*(")[^"]*$}i', $inline_html, $matches, 0, $pos)) { + $in_attribute_js_context = true; + $in_attribute = true; + $delimiter = $matches[1]; + $inline_html = ""; + } else if (preg_match('{\b([a-z]+)\s*=\s*(")([^"]*)$}i', $inline_html, $matches, 0, $pos) || + preg_match("{\b([a-z]+)\s*=\s*(')([^']*)$}i", $inline_html, $matches, 0, $pos)) { + $in_attribute = true; + $delimiter = $matches[2]; + $inline_html = ""; + $href_attribute_start = strtolower($matches[1]) == "href" && empty($matches[3]); + } } - // Scan for any occurrences of < ? = $variable ? > and store it in $expr - if ($token[0] == T_OPEN_TAG_WITH_ECHO) { - $php++; - } else if ($php && $token[0] == T_CLOSE_TAG) { - $php--; - } else if ($php && $token[0] == T_VARIABLE) { - if (!$expr) { - $entry = array($token[2], $in_p_clean); + // Look and report each instance of < ? = ... ? > + if (!is_array($token)) { + // A single char token, e.g: ; ( ) + if ($frame) { + $frame->expr_append($token); } - $expr .= $token[1]; - } else if ($expr) { - if ($token[0] == T_OBJECT_OPERATOR) { - $expr .= $token[1]; - } else if ($token[0] == T_STRING) { - $expr .= $token[1]; - } else if ($token == "(") { - $expr .= $token; - $level++; - } else if ($level > 0 && $token == ")") { - $expr .= $token; - $level--; - } else if ($level > 0) { - $expr .= is_array($token) ? $token[1] : $token; - } else { - $entry[] = $expr; - $found[$view][] = $entry; - $expr = null; - $entry = null; + } else if ($token[0] == T_OPEN_TAG_WITH_ECHO) { + // No need for a stack here - assume < ? = cannot be nested. + $frame = self::_create_frame($token, $in_script_block, + $href_attribute_start, $in_attribute_js_context, + $in_attribute, $preceded_by_quote); + $href_attribute_start = false; + } else if ($frame && $token[0] == T_CLOSE_TAG) { + // Store the < ? = ... ? > block that just ended here. + $found[$view][] = $frame; + $frame = null; + } else if ($frame && $token[0] == T_VARIABLE) { + $frame->expr_append($token[1]); + if ($token[1] == '$theme') { + if (self::_token_matches(array(T_OBJECT_OPERATOR, "->"), $tokens, $token_number + 1) && + self::_token_matches(array(T_STRING), $tokens, $token_number + 2) && + in_array($tokens[$token_number + 2][1], + array("thumb_proportion", "site_menu", "album_menu", "tag_menu", "photo_menu", + "context_menu", "pager", "site_status", "messages", "album_blocks", + "album_bottom", "album_top", "body_attributes", "credits", + "dynamic_bottom", "dynamic_top", "footer", "head", "header_bottom", + "header_top", "page_bottom", "page_top", "photo_blocks", "photo_bottom", + "photo_top", "resize_bottom", "resize_top", "sidebar_blocks", "sidebar_bottom", + "sidebar_top", "thumb_bottom", "thumb_info", "thumb_top")) && + self::_token_matches("(", $tokens, $token_number + 3)) { + + $method = $tokens[$token_number + 2][1]; + $frame->expr_append("->$method("); + + $token_number += 3; + $token = $tokens[$token_number]; + + $frame->is_safe_html(true); + } else if (self::_token_matches(array(T_OBJECT_OPERATOR, "->"), $tokens, $token_number + 1) && + self::_token_matches(array(T_STRING), $tokens, $token_number + 2) && + in_array($tokens[$token_number + 2][1], + array("css", "script", "url")) && + self::_token_matches("(", $tokens, $token_number + 3) && + // Only allow constant strings here + self::_token_matches(array(T_CONSTANT_ENCAPSED_STRING), $tokens, $token_number + 4)) { + + $method = $tokens[$token_number + 2][1]; + $frame->expr_append("->$method("); + + $token_number += 4; + $token = $tokens[$token_number]; + + $frame->is_safe_html(true); + } } + } else if ($frame && $token[0] == T_STRING) { + $frame->expr_append($token[1]); + // t() and t2() are special in that they're guaranteed to return a SafeString(). + if (in_array($token[1], array("t", "t2"))) { + if (self::_token_matches("(", $tokens, $token_number + 1)) { + $frame->is_safe_html(true); + $frame->expr_append("("); + + $token_number++; + $token = $tokens[$token_number]; + } + } else if ($token[1] == "SafeString") { + // Looking for SafeString::of(... + if (self::_token_matches(array(T_DOUBLE_COLON, "::"), $tokens, $token_number + 1) && + self::_token_matches(array(T_STRING), $tokens, $token_number + 2) && + in_array($tokens[$token_number + 2][1], array("of", "purify")) && + self::_token_matches("(", $tokens, $token_number + 3)) { + // Not checking for of_safe_html(). We want such calls to be marked dirty (thus reviewed). + + $frame->is_safe_html(true); + + $method = $tokens[$token_number + 2][1]; + $frame->expr_append("::$method("); + + $token_number += 3; + $token = $tokens[$token_number]; + } + } else if ($token[1] == "json_encode") { + if (self::_token_matches("(", $tokens, $token_number + 1)) { + $frame->is_safe_js(true); + $frame->expr_append("("); + + $token_number++; + $token = $tokens[$token_number]; + } + } else if ($token[1] == "url") { + // url methods return safe HTML + if (self::_token_matches(array(T_DOUBLE_COLON, "::"), $tokens, $token_number + 1) && + self::_token_matches(array(T_STRING), $tokens, $token_number + 2) && + in_array($tokens[$token_number + 2][1], + array("site", "current", "base", "file", "abs_site", "abs_current", + "abs_file", "merge")) && + self::_token_matches("(", $tokens, $token_number + 3)) { + $frame->is_safe_html(true); + $frame->is_safe_href_attr(true); + $frame->is_safe_attr(true); + + $method = $tokens[$token_number + 2][1]; + $frame->expr_append("::$method("); + + $token_number += 3; + $token = $tokens[$token_number]; + } + } else if ($token[1] == "html") { + if (self::_token_matches(array(T_DOUBLE_COLON, "::"), $tokens, $token_number + 1) && + self::_token_matches(array(T_STRING), $tokens, $token_number + 2) && + in_array($tokens[$token_number + 2][1], + array("clean", "purify", "js_string", "clean_attribute")) && + self::_token_matches("(", $tokens, $token_number + 3)) { + // Not checking for mark_clean(). We want such calls to be marked dirty (thus reviewed). + + $method = $tokens[$token_number + 2][1]; + $frame->expr_append("::$method("); + + $token_number += 3; + $token = $tokens[$token_number]; + + if ("js_string" == $method) { + $frame->is_safe_js(true); + } else { + $frame->is_safe_html(true); + } + if ("clean_attribute" == $method) { + $frame->is_safe_attr(true); + } + } + } + } else if ($frame && $token[0] == T_OBJECT_OPERATOR) { + $frame->expr_append($token[1]); + + if (self::_token_matches(array(T_STRING), $tokens, $token_number + 1) && + in_array($tokens[$token_number + 1][1], + array("for_js", "for_html", "purified_html", "for_html_attr")) && + self::_token_matches("(", $tokens, $token_number + 2)) { + $method = $tokens[$token_number + 1][1]; + $frame->expr_append("$method("); + + $token_number += 2; + $token = $tokens[$token_number]; + + if ("for_js" == $method) { + $frame->is_safe_js(true); + } else { + $frame->is_safe_html(true); + } + if ("for_html_attr" == $method) { + $frame->is_safe_attr(true); + } + } + } else if ($frame) { + $frame->expr_append($token[1]); } } } - $canonical = MODPATH . "gallery/tests/xss_data.txt"; + /* + * Generate the report + * + * States for uses of < ? = X ? >: + * DIRTY_JS: + * In <script> block + * X can be anything without calling ->for_js() + * At the start of a href= attribute + * X = anything but a url method + * In href="javascript: or onclick="...": + * X = anything (manual review required) + * DIRTY: + * Outside <script> block: + * X can be anything without a call to ->for_html() or ->purified_html() + * CLEAN: + * Outside <script> block: + * X = is SafeString (t(), t2(), url::site()) + * X = * and for_html() or purified_html() is called + * Inside <script> block: + * X = * with ->for_js() or json_encode(...) + * Start of href attribute: + * X = url method + */ $new = TMPPATH . "xss_data.txt"; $fd = fopen($new, "wb"); ksort($found); - foreach ($found as $view => $entries) { - foreach ($entries as $entry) { - fwrite($fd, - sprintf("%-60s %-3s %-5s %s\n", - $view, $entry[0], $entry[1] ? "" : "DIRTY", $entry[2])); + foreach ($found as $view => $frames) { + foreach ($frames as $frame) { + $state = "DIRTY"; + if ($frame->in_script_block() && $frame->in_href_attribute()) { + // This parser assumes this state does not occur. + $state = "ILLEGAL"; + } else if ($frame->in_script_block()) { + $state = "DIRTY_JS"; + if ($frame->is_safe_js() && !$frame->preceded_by_quote()) { + $state = "CLEAN"; + } + } else if ($frame->in_attribute_js_context()) { + // Manual review required + $state = "DIRTY_JS"; + } else if ($frame->in_href_attribute()) { + $state = "DIRTY_JS"; + if ($frame->is_safe_href_attr()) { + $state = "CLEAN"; + } + } else if ($frame->in_attribute()) { + $state = "DIRTY_ATTR"; + if ($frame->is_safe_attr()) { + $state = "CLEAN"; + } + } else { + if ($frame->is_safe_html()) { + $state = "CLEAN"; + } + } + + if ("CLEAN" == $state) { + // Don't print CLEAN instances - No need to update the golden + // file when adding / moving clean instances. + continue; + } + + fprintf($fd, "%-60s %-3s %-8s %s\n", + $view, $frame->line(), $state, $frame->expr()); } } fclose($fd); + // Compare with the expected report from our golden file. + $canonical = MODPATH . "gallery/tests/xss_data.txt"; exec("diff $canonical $new", $output, $return_value); $this->assert_false( - $return_value, "XSS golden file mismatch. Output:\n" . implode("\n", $output) ); + $return_value, "XSS golden file mismatch. Output:\n" . implode("\n", $output) ); + } + + private static function _create_frame($token, $in_script_block, + $href_attribute_start, $in_attribute_js_context, + $in_attribute, $preceded_by_quote) { + return new Xss_Security_Test_Frame($token[2], $in_script_block, + $href_attribute_start, $in_attribute_js_context, + $in_attribute, $preceded_by_quote); + } + + private static function _token_matches($expected_token, &$tokens, $token_number) { + if (!isset($tokens[$token_number])) { + return false; + } + + $token = $tokens[$token_number]; + + if (is_array($expected_token)) { + for ($i = 0; $i < count($expected_token); $i++) { + if ($expected_token[$i] != $token[$i]) { + return false; + } + } + return true; + } else { + return $expected_token == $token; + } + } +} + +class Xss_Security_Test_Frame { + private $_expr = ""; + private $_in_script_block = false; + private $_is_safe_html = false; + private $_is_safe_js = false; + private $_in_href_attribute = false; + private $_is_safe_href_attr = false; + private $_in_attribute_js_context = false; + private $_in_attribute = false; + private $_preceded_by_quote = false; + private $_is_safe_attr = false; + private $_line; + + function __construct($line_number, $in_script_block, + $href_attribute_start, $in_attribute_js_context, + $in_attribute, $preceded_by_quote) { + $this->_line = $line_number; + $this->_in_script_block = $in_script_block; + $this->_in_href_attribute = $href_attribute_start; + $this->_in_attribute_js_context = $in_attribute_js_context; + $this->_in_attribute = $in_attribute; + $this->_preceded_by_quote = $preceded_by_quote; + } + + function expr() { + return $this->_expr; + } + + function expr_append($append_value) { + return $this->_expr .= $append_value; + } + + function in_script_block() { + return $this->_in_script_block; + } + + function in_href_attribute() { + return $this->_in_href_attribute; + } + + function in_attribute() { + return $this->_in_attribute; + } + + function in_attribute_js_context() { + return $this->_in_attribute_js_context; + } + + function is_safe_html($new_val=NULL) { + if ($new_val !== NULL) { + $this->_is_safe_html = (bool) $new_val; + } + return $this->_is_safe_html; + } + + function is_safe_href_attr($new_val=NULL) { + if ($new_val !== NULL) { + $this->_is_safe_href_attr = (bool) $new_val; + } + return $this->_is_safe_href_attr; + } + + function is_safe_attr($new_val=NULL) { + if ($new_val !== NULL) { + $this->_is_safe_attr = (bool) $new_val; + } + return $this->_is_safe_attr; + } + + function is_safe_js($new_val=NULL) { + if ($new_val !== NULL) { + $this->_is_safe_js = (bool) $new_val; + } + return $this->_is_safe_js; + } + + function preceded_by_quote() { + return $this->_preceded_by_quote; + } + + function line() { + return $this->_line; } } diff --git a/modules/gallery/tests/test.flv b/modules/gallery/tests/test.flv Binary files differnew file mode 100644 index 00000000..799d137e --- /dev/null +++ b/modules/gallery/tests/test.flv diff --git a/modules/gallery/tests/xss_data.txt b/modules/gallery/tests/xss_data.txt index 982343f6..193d2ca1 100644 --- a/modules/gallery/tests/xss_data.txt +++ b/modules/gallery/tests/xss_data.txt @@ -1,642 +1,346 @@ -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 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() -modules/comment/views/admin_block_recent_comments.html.php 13 $comment->text -modules/comment/views/admin_comments.html.php 4 DIRTY $csrf -modules/comment/views/admin_comments.html.php 15 DIRTY $csrf -modules/comment/views/admin_comments.html.php 42 DIRTY $menu -modules/comment/views/admin_comments.html.php 65 DIRTY $spam_caught -modules/comment/views/admin_comments.html.php 72 DIRTY $counts->spam -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 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() -modules/comment/views/admin_comments.html.php 116 $comment->author_name() -modules/comment/views/admin_comments.html.php 122 DIRTY $item->url() -modules/comment/views/admin_comments.html.php 124 DIRTY $item->thumb_url() -modules/comment/views/admin_comments.html.php 125 $item->title -modules/comment/views/admin_comments.html.php 126 DIRTY $item->thumb_width -modules/comment/views/admin_comments.html.php 126 DIRTY $item->thumb_height -modules/comment/views/admin_comments.html.php 134 DIRTY $comment->created -modules/comment/views/admin_comments.html.php 135 $comment->text -modules/comment/views/admin_comments.html.php 141 DIRTY $comment->id -modules/comment/views/admin_comments.html.php 150 DIRTY $comment->id -modules/comment/views/admin_comments.html.php 159 DIRTY $comment->id -modules/comment/views/admin_comments.html.php 168 DIRTY $comment->id -modules/comment/views/admin_comments.html.php 175 DIRTY $comment->id -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 7 $comment->author_name() -modules/comment/views/comment.html.php 12 DIRTY $comment->created -modules/comment/views/comment.html.php 13 $comment->author_name() -modules/comment/views/comment.html.php 16 $comment->text -modules/comment/views/comment.mrss.php 9 $feed->title -modules/comment/views/comment.mrss.php 10 DIRTY $feed->uri -modules/comment/views/comment.mrss.php 11 $feed->description -modules/comment/views/comment.mrss.php 13 DIRTY $feed->uri -modules/comment/views/comment.mrss.php 16 DIRTY $feed->previous_page_uri -modules/comment/views/comment.mrss.php 19 DIRTY $feed->next_page_uri -modules/comment/views/comment.mrss.php 21 DIRTY $pub_date -modules/comment/views/comment.mrss.php 22 DIRTY $pub_date -modules/comment/views/comment.mrss.php 25 $child->title -modules/comment/views/comment.mrss.php 26 $child->item_uri -modules/comment/views/comment.mrss.php 27 $child->author -modules/comment/views/comment.mrss.php 28 DIRTY $child->item_uri -modules/comment/views/comment.mrss.php 29 DIRTY $child->pub_date -modules/comment/views/comment.mrss.php 32 $child->text -modules/comment/views/comment.mrss.php 34 DIRTY $child->thumb_url -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 15 $comment->author_name() -modules/comment/views/comments.html.php 20 DIRTY $comment->created -modules/comment/views/comments.html.php 21 $comment->author_name() -modules/comment/views/comments.html.php 24 $comment->text -modules/digibug/views/digibug_form.html.php 5 DIRTY $order_parms -modules/exif/views/exif_dialog.html.php 14 DIRTY $details -modules/exif/views/exif_dialog.html.php 14 DIRTY $i -modules/exif/views/exif_dialog.html.php 17 $details -modules/exif/views/exif_dialog.html.php 17 $i -modules/exif/views/exif_dialog.html.php 21 DIRTY $details -modules/exif/views/exif_dialog.html.php 21 DIRTY $i -modules/exif/views/exif_dialog.html.php 24 $details -modules/exif/views/exif_dialog.html.php 24 $i -modules/exif/views/exif_sidebar.html.php 2 DIRTY $item->id -modules/g2_import/views/admin_g2_import.html.php 28 DIRTY $form -modules/g2_import/views/admin_g2_import.html.php 40 DIRTY $g2_sizes -modules/g2_import/views/admin_g2_import.html.php 41 DIRTY $thumb_size -modules/g2_import/views/admin_g2_import.html.php 49 DIRTY $g2_sizes -modules/g2_import/views/admin_g2_import.html.php 50 DIRTY $resize_size -modules/g2_import/views/admin_g2_import.html.php 62 DIRTY $g2_stats -modules/g2_import/views/admin_g2_import.html.php 65 DIRTY $g2_stats -modules/g2_import/views/admin_g2_import.html.php 68 DIRTY $g2_stats -modules/g2_import/views/admin_g2_import.html.php 71 DIRTY $g2_stats -modules/g2_import/views/admin_g2_import.html.php 74 DIRTY $g2_stats -modules/g2_import/views/admin_g2_import.html.php 77 DIRTY $g2_stats -modules/g2_import/views/admin_g2_import.html.php 81 DIRTY $g2_stats -modules/g2_import/views/admin_g2_import.html.php 88 DIRTY $csrf -modules/gallery/views/admin_advanced_settings.html.php 22 DIRTY $var->module_name -modules/gallery/views/admin_advanced_settings.html.php 23 $var->name -modules/gallery/views/admin_advanced_settings.html.php 25 DIRTY $var->module_name -modules/gallery/views/admin_advanced_settings.html.php 25 $var->name -modules/gallery/views/admin_advanced_settings.html.php 27 $var->name -modules/gallery/views/admin_advanced_settings.html.php 27 DIRTY $var->module_name -modules/gallery/views/admin_advanced_settings.html.php 29 $var->value -modules/gallery/views/admin_block_log_entries.html.php 4 DIRTY $entry->severity -modules/gallery/views/admin_block_log_entries.html.php 5 DIRTY $entry->user_id -modules/gallery/views/admin_block_log_entries.html.php 5 $entry->user->name -modules/gallery/views/admin_block_log_entries.html.php 6 DIRTY $entry->timestamp -modules/gallery/views/admin_block_log_entries.html.php 7 DIRTY $entry->message -modules/gallery/views/admin_block_log_entries.html.php 8 DIRTY $entry->html -modules/gallery/views/admin_block_news.html.php 5 DIRTY $entry -modules/gallery/views/admin_block_news.html.php 5 DIRTY $entry -modules/gallery/views/admin_block_news.html.php 7 DIRTY $entry -modules/gallery/views/admin_block_photo_stream.html.php 5 DIRTY $photo->id -modules/gallery/views/admin_block_photo_stream.html.php 5 $photo->title -modules/gallery/views/admin_block_photo_stream.html.php 6 DIRTY $photo->width -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_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 -modules/gallery/views/admin_dashboard.html.php 35 DIRTY $blocks -modules/gallery/views/admin_graphics.html.php 6 DIRTY $csrf -modules/gallery/views/admin_graphics.html.php 21 DIRTY $active -modules/gallery/views/admin_graphics.html.php 25 DIRTY $available -modules/gallery/views/admin_graphics_gd.html.php 2 DIRTY $is_active -modules/gallery/views/admin_graphics_gd.html.php 2 DIRTY $tk->gd -modules/gallery/views/admin_graphics_gd.html.php 11 DIRTY $tk->gd -modules/gallery/views/admin_graphics_gd.html.php 19 DIRTY $tk->gd -modules/gallery/views/admin_graphics_graphicsmagick.html.php 2 DIRTY $is_active -modules/gallery/views/admin_graphics_graphicsmagick.html.php 2 DIRTY $tk->graphicsmagick -modules/gallery/views/admin_graphics_graphicsmagick.html.php 11 DIRTY $tk->graphicsmagick -modules/gallery/views/admin_graphics_imagemagick.html.php 2 DIRTY $is_active -modules/gallery/views/admin_graphics_imagemagick.html.php 2 DIRTY $tk->imagemagick -modules/gallery/views/admin_graphics_imagemagick.html.php 11 DIRTY $tk->imagemagick -modules/gallery/views/admin_languages.html.php 5 DIRTY $settings_form -modules/gallery/views/admin_languages.html.php 8 DIRTY $csrf -modules/gallery/views/admin_languages.html.php 14 DIRTY $share_translations_form -modules/gallery/views/admin_maintenance.html.php 23 DIRTY $task->severity -modules/gallery/views/admin_maintenance.html.php 25 DIRTY $task->name -modules/gallery/views/admin_maintenance.html.php 28 DIRTY $task->description -modules/gallery/views/admin_maintenance.html.php 31 DIRTY $task->callback -modules/gallery/views/admin_maintenance.html.php 31 DIRTY $csrf -modules/gallery/views/admin_maintenance.html.php 44 DIRTY $csrf -modules/gallery/views/admin_maintenance.html.php 70 DIRTY $task->state -modules/gallery/views/admin_maintenance.html.php 72 DIRTY $task->updated -modules/gallery/views/admin_maintenance.html.php 75 DIRTY $task->name -modules/gallery/views/admin_maintenance.html.php 86 DIRTY $task->percent_complete -modules/gallery/views/admin_maintenance.html.php 90 DIRTY $task->status -modules/gallery/views/admin_maintenance.html.php 93 $task->owner()->name -modules/gallery/views/admin_maintenance.html.php 97 DIRTY $task->id -modules/gallery/views/admin_maintenance.html.php 97 DIRTY $csrf -modules/gallery/views/admin_maintenance.html.php 101 DIRTY $task->id -modules/gallery/views/admin_maintenance.html.php 101 DIRTY $csrf -modules/gallery/views/admin_maintenance.html.php 113 DIRTY $csrf -modules/gallery/views/admin_maintenance.html.php 140 DIRTY $task->state -modules/gallery/views/admin_maintenance.html.php 142 DIRTY $task->updated -modules/gallery/views/admin_maintenance.html.php 145 DIRTY $task->name -modules/gallery/views/admin_maintenance.html.php 157 DIRTY $task->status -modules/gallery/views/admin_maintenance.html.php 160 DIRTY $task->owner()->name -modules/gallery/views/admin_maintenance.html.php 164 DIRTY $task->id -modules/gallery/views/admin_maintenance.html.php 164 DIRTY $csrf -modules/gallery/views/admin_maintenance.html.php 168 DIRTY $task->id -modules/gallery/views/admin_maintenance.html.php 168 DIRTY $csrf -modules/gallery/views/admin_maintenance.html.php 171 DIRTY $task->id -modules/gallery/views/admin_maintenance.html.php 171 DIRTY $csrf -modules/gallery/views/admin_maintenance_task.html.php 5 DIRTY $task->id -modules/gallery/views/admin_maintenance_task.html.php 5 DIRTY $csrf -modules/gallery/views/admin_maintenance_task.html.php 26 DIRTY $task->name -modules/gallery/views/admin_modules.html.php 19 DIRTY $i -modules/gallery/views/admin_modules.html.php 22 DIRTY $data -modules/gallery/views/admin_modules.html.php 22 DIRTY $module_name -modules/gallery/views/admin_modules.html.php 23 DIRTY $module_info->name -modules/gallery/views/admin_modules.html.php 24 DIRTY $module_info->version -modules/gallery/views/admin_modules.html.php 25 DIRTY $module_info->description -modules/gallery/views/admin_theme_options.html.php 5 DIRTY $form -modules/gallery/views/admin_themes.html.php 5 DIRTY $csrf -modules/gallery/views/admin_themes.html.php 18 DIRTY $site -modules/gallery/views/admin_themes.html.php 19 DIRTY $themes -modules/gallery/views/admin_themes.html.php 19 DIRTY $site -modules/gallery/views/admin_themes.html.php 20 DIRTY $themes -modules/gallery/views/admin_themes.html.php 20 DIRTY $site -modules/gallery/views/admin_themes.html.php 22 DIRTY $themes -modules/gallery/views/admin_themes.html.php 22 DIRTY $site -modules/gallery/views/admin_themes.html.php 33 DIRTY $id -modules/gallery/views/admin_themes.html.php 33 DIRTY $info->name -modules/gallery/views/admin_themes.html.php 34 DIRTY $id -modules/gallery/views/admin_themes.html.php 35 DIRTY $info->name -modules/gallery/views/admin_themes.html.php 36 DIRTY $info->name -modules/gallery/views/admin_themes.html.php 38 DIRTY $info->description -modules/gallery/views/admin_themes.html.php 56 DIRTY $admin -modules/gallery/views/admin_themes.html.php 57 DIRTY $themes -modules/gallery/views/admin_themes.html.php 57 DIRTY $admin -modules/gallery/views/admin_themes.html.php 58 DIRTY $themes -modules/gallery/views/admin_themes.html.php 58 DIRTY $admin -modules/gallery/views/admin_themes.html.php 60 DIRTY $themes -modules/gallery/views/admin_themes.html.php 60 DIRTY $admin -modules/gallery/views/admin_themes.html.php 71 DIRTY $id -modules/gallery/views/admin_themes.html.php 71 DIRTY $info->name -modules/gallery/views/admin_themes.html.php 72 DIRTY $id -modules/gallery/views/admin_themes.html.php 73 DIRTY $info->name -modules/gallery/views/admin_themes.html.php 74 DIRTY $info->name -modules/gallery/views/admin_themes.html.php 76 DIRTY $info->description -modules/gallery/views/admin_themes_preview.html.php 3 DIRTY $type -modules/gallery/views/admin_themes_preview.html.php 3 DIRTY $theme_name -modules/gallery/views/admin_themes_preview.html.php 3 DIRTY $csrf -modules/gallery/views/admin_themes_preview.html.php 4 DIRTY $info->name -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/kohana_error_page.php 98 DIRTY $message -modules/gallery/views/kohana_error_page.php 100 DIRTY $file -modules/gallery/views/kohana_error_page.php 100 DIRTY $line -modules/gallery/views/kohana_error_page.php 112 DIRTY $trace -modules/gallery/views/kohana_profiler.php 32 DIRTY $profile->render() -modules/gallery/views/kohana_profiler.php 34 DIRTY $execution_time -modules/gallery/views/l10n_client.html.php 17 DIRTY $string -modules/gallery/views/l10n_client.html.php 19 DIRTY $string -modules/gallery/views/l10n_client.html.php 20 DIRTY $string -modules/gallery/views/l10n_client.html.php 22 DIRTY $string -modules/gallery/views/l10n_client.html.php 28 DIRTY $l10n_search_form -modules/gallery/views/l10n_client.html.php 72 DIRTY $string_list -modules/gallery/views/l10n_client.html.php 73 DIRTY $plural_forms -modules/gallery/views/move_browse.html.php 4 DIRTY $source->id -modules/gallery/views/move_browse.html.php 39 DIRTY $tree -modules/gallery/views/move_browse.html.php 42 DIRTY $source->id -modules/gallery/views/move_tree.html.php 2 DIRTY $parent->thumb_img(array(), 25) -modules/gallery/views/move_tree.html.php 4 DIRTY $parent->id -modules/gallery/views/move_tree.html.php 4 $parent->title -modules/gallery/views/move_tree.html.php 6 DIRTY $parent->id -modules/gallery/views/move_tree.html.php 6 $parent->title -modules/gallery/views/move_tree.html.php 8 DIRTY $parent->id -modules/gallery/views/move_tree.html.php 10 DIRTY $child->id -modules/gallery/views/move_tree.html.php 11 DIRTY $child->thumb_img(array(), 25) -modules/gallery/views/move_tree.html.php 13 DIRTY $child->id -modules/gallery/views/move_tree.html.php 13 $child->title -modules/gallery/views/move_tree.html.php 15 DIRTY $child->id -modules/gallery/views/move_tree.html.php 15 $child->title -modules/gallery/views/movieplayer.html.php 2 DIRTY $item->file_url(true) -modules/gallery/views/movieplayer.html.php 2 DIRTY $attrs -modules/gallery/views/movieplayer.html.php 4 DIRTY $attrs -modules/gallery/views/permissions_browse.html.php 15 DIRTY $csrf -modules/gallery/views/permissions_browse.html.php 37 DIRTY $parent->id -modules/gallery/views/permissions_browse.html.php 38 $parent->title -modules/gallery/views/permissions_browse.html.php 40 DIRTY $parent->id -modules/gallery/views/permissions_browse.html.php 44 DIRTY $item->id -modules/gallery/views/permissions_browse.html.php 45 $item->title -modules/gallery/views/permissions_browse.html.php 47 DIRTY $item->id -modules/gallery/views/permissions_browse.html.php 48 DIRTY $form -modules/gallery/views/permissions_form.html.php 9 $group->name -modules/gallery/views/permissions_form.html.php 15 DIRTY $permission->display_name -modules/gallery/views/permissions_form.html.php 24 DIRTY $lock->id -modules/gallery/views/permissions_form.html.php 32 DIRTY $group->id -modules/gallery/views/permissions_form.html.php 32 DIRTY $permission->id -modules/gallery/views/permissions_form.html.php 32 DIRTY $item->id -modules/gallery/views/permissions_form.html.php 36 DIRTY $group->id -modules/gallery/views/permissions_form.html.php 36 DIRTY $permission->id -modules/gallery/views/permissions_form.html.php 36 DIRTY $item->id -modules/gallery/views/permissions_form.html.php 43 DIRTY $group->id -modules/gallery/views/permissions_form.html.php 43 DIRTY $permission->id -modules/gallery/views/permissions_form.html.php 43 DIRTY $item->id -modules/gallery/views/permissions_form.html.php 47 DIRTY $group->id -modules/gallery/views/permissions_form.html.php 47 DIRTY $permission->id -modules/gallery/views/permissions_form.html.php 47 DIRTY $item->id -modules/gallery/views/permissions_form.html.php 56 DIRTY $group->id -modules/gallery/views/permissions_form.html.php 56 DIRTY $permission->id -modules/gallery/views/permissions_form.html.php 56 DIRTY $item->id -modules/gallery/views/permissions_form.html.php 63 DIRTY $group->id -modules/gallery/views/permissions_form.html.php 63 DIRTY $permission->id -modules/gallery/views/permissions_form.html.php 63 DIRTY $item->id -modules/gallery/views/permissions_form.html.php 74 DIRTY $group->id -modules/gallery/views/permissions_form.html.php 74 DIRTY $permission->id -modules/gallery/views/permissions_form.html.php 74 DIRTY $item->id -modules/gallery/views/permissions_form.html.php 79 DIRTY $group->id -modules/gallery/views/permissions_form.html.php 79 DIRTY $permission->id -modules/gallery/views/permissions_form.html.php 79 DIRTY $item->id -modules/gallery/views/quick_pane.html.php 3 DIRTY $button->class -modules/gallery/views/quick_pane.html.php 3 DIRTY $button->href -modules/gallery/views/quick_pane.html.php 4 DIRTY $button->title -modules/gallery/views/quick_pane.html.php 5 DIRTY $button->icon -modules/gallery/views/quick_pane.html.php 6 DIRTY $button->title -modules/gallery/views/quick_pane.html.php 20 DIRTY $button->class -modules/gallery/views/quick_pane.html.php 20 DIRTY $button->href -modules/gallery/views/quick_pane.html.php 21 DIRTY $button->title -modules/gallery/views/quick_pane.html.php 22 DIRTY $button->title -modules/gallery/views/simple_uploader.html.php 7 DIRTY $csrf -modules/gallery/views/simple_uploader.html.php 9 $item->title -modules/gallery/views/simple_uploader.html.php 29 $parent->title -modules/gallery/views/simple_uploader.html.php 31 $item->title -modules/gallery/views/simple_uploader.html.php 85 DIRTY $item->id -modules/gallery/views/simple_uploader.html.php 89 DIRTY $csrf -modules/gallery/views/upgrader.html.php 44 DIRTY $module->version -modules/gallery/views/upgrader.html.php 44 DIRTY $module->code_version -modules/gallery/views/upgrader.html.php 45 DIRTY $id -modules/gallery/views/upgrader.html.php 46 DIRTY $module->name -modules/gallery/views/upgrader.html.php 49 DIRTY $module->version -modules/gallery/views/upgrader.html.php 52 DIRTY $module->code_version -modules/gallery/views/upgrader.html.php 75 DIRTY $module->name -modules/gallery/views/upgrader.html.php 84 DIRTY $upgrade_token -modules/image_block/views/image_block_block.html.php 3 DIRTY $item->url() -modules/image_block/views/image_block_block.html.php 4 DIRTY $item->thumb_img(array("class" => "gThumbnail")) -modules/info/views/info_block.html.php 5 $item->title -modules/info/views/info_block.html.php 10 $item->description -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/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 -modules/notification/views/comment_published.html.php 15 $comment->author_name() -modules/notification/views/comment_published.html.php 19 $comment->author_email() -modules/notification/views/comment_published.html.php 23 $comment->author_url() -modules/notification/views/comment_published.html.php 28 DIRTY $comment->item()->url(array(), true) -modules/notification/views/comment_published.html.php 29 DIRTY $comment->item()->url(array(), true) -modules/notification/views/item_added.html.php 4 $subject -modules/notification/views/item_added.html.php 7 $subject -modules/notification/views/item_added.html.php 11 $item->title -modules/notification/views/item_added.html.php 16 DIRTY $item->url(array(), true) -modules/notification/views/item_added.html.php 17 DIRTY $item->url(array(), true) -modules/notification/views/item_added.html.php 24 $item->description -modules/notification/views/item_deleted.html.php 4 $subject -modules/notification/views/item_deleted.html.php 7 $subject -modules/notification/views/item_deleted.html.php 12 $item->parent()->title -modules/notification/views/item_deleted.html.php 18 DIRTY $item->parent()->url(array(), true) -modules/notification/views/item_deleted.html.php 19 DIRTY $item->parent()->url(array(), true) -modules/notification/views/item_updated.html.php 4 $subject -modules/notification/views/item_updated.html.php 7 $subject -modules/notification/views/item_updated.html.php 12 $new->title -modules/notification/views/item_updated.html.php 15 $new->title -modules/notification/views/item_updated.html.php 20 DIRTY $new->url(array(), true) -modules/notification/views/item_updated.html.php 20 DIRTY $new->url(array(), true) -modules/notification/views/item_updated.html.php 25 $new->description -modules/notification/views/item_updated.html.php 30 $new->description -modules/organize/views/organize.html.php 10 DIRTY $item->id -modules/organize/views/organize.html.php 12 DIRTY $csrf -modules/organize/views/organize.html.php 13 DIRTY $csrf -modules/organize/views/organize.html.php 19 $item->title -modules/organize/views/organize.html.php 33 DIRTY $album_tree -modules/organize/views/organize.html.php 48 DIRTY $button_pane -modules/organize/views/organize_album.html.php 3 DIRTY $album->id -modules/organize/views/organize_album.html.php 4 DIRTY $album->id -modules/organize/views/organize_album.html.php 4 DIRTY $album->id -modules/organize/views/organize_album.html.php 5 DIRTY $album_icon -modules/organize/views/organize_album.html.php 5 DIRTY $album_icon -modules/organize/views/organize_album.html.php 8 DIRTY $album->id -modules/organize/views/organize_album.html.php 8 DIRTY $album->id -modules/organize/views/organize_album.html.php 9 DIRTY $selected -modules/organize/views/organize_album.html.php 10 $album->title -modules/organize/views/organize_album.html.php 12 DIRTY $album->id -modules/organize/views/organize_album.html.php 13 DIRTY $album_icon -modules/organize/views/organize_album.html.php 14 DIRTY $children -modules/organize/views/organize_edit.html.php 4 DIRTY $idx -modules/organize/views/organize_edit.html.php 4 DIRTY $pane -modules/organize/views/organize_edit.html.php 10 DIRTY $idx -modules/organize/views/organize_edit.html.php 10 DIRTY $pane -modules/organize/views/organize_thumb_grid.html.php 7 DIRTY $child->id -modules/organize/views/organize_thumb_grid.html.php 7 DIRTY $child->id -modules/organize/views/organize_thumb_grid.html.php 8 DIRTY $child->id -modules/organize/views/organize_thumb_grid.html.php 8 DIRTY $item_class -modules/organize/views/organize_thumb_grid.html.php 9 DIRTY $child->thumb_img(array("class" => "gThumbnail"), $thumbsize, true) -modules/recaptcha/views/admin_recaptcha.html.php 6 DIRTY $form->get_key_url -modules/recaptcha/views/admin_recaptcha.html.php 10 DIRTY $form -modules/recaptcha/views/admin_recaptcha.html.php 23 DIRTY $public_key -modules/recaptcha/views/form_recaptcha.html.php 7 DIRTY $public_key -modules/rss/views/feed.mrss.php 9 $feed->title -modules/rss/views/feed.mrss.php 10 DIRTY $feed->uri -modules/rss/views/feed.mrss.php 11 $feed->description -modules/rss/views/feed.mrss.php 13 DIRTY $feed->uri -modules/rss/views/feed.mrss.php 16 DIRTY $feed->previous_page_uri -modules/rss/views/feed.mrss.php 19 DIRTY $feed->next_page_uri -modules/rss/views/feed.mrss.php 21 DIRTY $pub_date -modules/rss/views/feed.mrss.php 22 DIRTY $pub_date -modules/rss/views/feed.mrss.php 25 $child->title -modules/rss/views/feed.mrss.php 26 DIRTY $child->type -modules/rss/views/feed.mrss.php 26 DIRTY $child->id -modules/rss/views/feed.mrss.php 27 DIRTY $child->type -modules/rss/views/feed.mrss.php 27 DIRTY $child->id -modules/rss/views/feed.mrss.php 28 DIRTY $child->created -modules/rss/views/feed.mrss.php 31 $child->description -modules/rss/views/feed.mrss.php 34 DIRTY $child->resize_url(true) -modules/rss/views/feed.mrss.php 35 $child->title -modules/rss/views/feed.mrss.php 36 DIRTY $child->resize_height -modules/rss/views/feed.mrss.php 36 DIRTY $child->resize_width -modules/rss/views/feed.mrss.php 38 DIRTY $child->type -modules/rss/views/feed.mrss.php 38 DIRTY $child->id -modules/rss/views/feed.mrss.php 39 DIRTY $child->thumb_url(true) -modules/rss/views/feed.mrss.php 40 $child->title -modules/rss/views/feed.mrss.php 41 DIRTY $child->thumb_height -modules/rss/views/feed.mrss.php 41 DIRTY $child->thumb_width -modules/rss/views/feed.mrss.php 43 $child->description -modules/rss/views/feed.mrss.php 47 DIRTY $child->thumb_url(true) -modules/rss/views/feed.mrss.php 48 DIRTY $child->thumb_path() -modules/rss/views/feed.mrss.php 49 DIRTY $child->thumb_height -modules/rss/views/feed.mrss.php 50 DIRTY $child->thumb_width -modules/rss/views/feed.mrss.php 54 DIRTY $child->resize_url(true) -modules/rss/views/feed.mrss.php 55 DIRTY $child->resize_path() -modules/rss/views/feed.mrss.php 56 DIRTY $child->mime_type -modules/rss/views/feed.mrss.php 57 DIRTY $child->resize_height -modules/rss/views/feed.mrss.php 58 DIRTY $child->resize_width -modules/rss/views/feed.mrss.php 62 DIRTY $child->file_url(true) -modules/rss/views/feed.mrss.php 63 DIRTY $child->file_path() -modules/rss/views/feed.mrss.php 64 DIRTY $child->mime_type -modules/rss/views/feed.mrss.php 65 DIRTY $child->height -modules/rss/views/feed.mrss.php 66 DIRTY $child->width -modules/rss/views/feed.mrss.php 70 DIRTY $child->file_url(true) -modules/rss/views/feed.mrss.php 71 DIRTY $child->file_path() -modules/rss/views/feed.mrss.php 72 DIRTY $child->height -modules/rss/views/feed.mrss.php 73 DIRTY $child->width -modules/rss/views/feed.mrss.php 74 DIRTY $child->mime_type -modules/rss/views/rss_block.html.php 6 DIRTY $url -modules/rss/views/rss_block.html.php 8 DIRTY $title -modules/search/views/search.html.php 11 $q -modules/search/views/search.html.php 30 DIRTY $item_class -modules/search/views/search.html.php 31 DIRTY $item->id -modules/search/views/search.html.php 32 DIRTY $item->thumb_img() -modules/search/views/search.html.php 34 $item->title -modules/search/views/search.html.php 37 $item->description -modules/search/views/search.html.php 43 DIRTY $theme->pager() -modules/search/views/search.html.php 47 $q -modules/server_add/views/admin_server_add.html.php 14 DIRTY $path -modules/server_add/views/admin_server_add.html.php 14 DIRTY $csrf -modules/server_add/views/admin_server_add.html.php 15 DIRTY $id -modules/server_add/views/admin_server_add.html.php 19 DIRTY $path -modules/server_add/views/admin_server_add.html.php 24 DIRTY $form -modules/server_add/views/server_add_tree.html.php 4 DIRTY $tree_id -modules/server_add/views/server_add_tree.html.php 6 DIRTY $file_info -modules/server_add/views/server_add_tree.html.php 10 $file_info -modules/server_add/views/server_add_tree.html.php 10 DIRTY $checked -modules/server_add/views/server_add_tree.html.php 10 $file -modules/server_add/views/server_add_tree_dialog.html.php 10 $album_title -modules/server_add/views/server_add_tree_dialog.html.php 15 $parent->title -modules/server_add/views/server_add_tree_dialog.html.php 17 $album_title -modules/server_add/views/server_add_tree_dialog.html.php 20 DIRTY $action -modules/server_add/views/server_add_tree_dialog.html.php 22 DIRTY $tree -modules/tag/views/admin_tags.html.php 13 DIRTY $csrf -modules/tag/views/admin_tags.html.php 27 DIRTY $tags->count() -modules/tag/views/admin_tags.html.php 35 DIRTY $current_letter -modules/tag/views/admin_tags.html.php 45 DIRTY $current_letter -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_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 -modules/tag/views/tag_cloud.html.php 6 DIRTY $tag->id -modules/tag/views/tag_cloud.html.php 6 $tag->name -modules/user/views/admin_users.html.php 3 DIRTY $csrf -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 71 $user->name -modules/user/views/admin_users.html.php 74 $user->name -modules/user/views/admin_users.html.php 77 $user->full_name -modules/user/views/admin_users.html.php 80 $user->email -modules/user/views/admin_users.html.php 83 DIRTY $user->last_login -modules/user/views/admin_users.html.php 83 DIRTY $user->last_login -modules/user/views/admin_users.html.php 86 DIRTY $user->id -modules/user/views/admin_users.html.php 91 DIRTY $user->id -modules/user/views/admin_users.html.php 121 DIRTY $group->id -modules/user/views/admin_users.html.php 121 DIRTY $group->special -modules/user/views/admin_users.html.php 123 DIRTY $v -modules/user/views/admin_users_group.html.php 3 $group->name -modules/user/views/admin_users_group.html.php 5 DIRTY $group->id -modules/user/views/admin_users_group.html.php 6 $group->name -modules/user/views/admin_users_group.html.php 20 $user->name -modules/user/views/admin_users_group.html.php 22 DIRTY $user->id -modules/user/views/admin_users_group.html.php 22 DIRTY $group->id -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 18 DIRTY $csrf -modules/user/views/login_ajax.html.php 37 DIRTY $form -modules/user/views/reset_password.html.php 9 $user->full_name -modules/user/views/reset_password.html.php 9 $user->full_name -modules/user/views/reset_password.html.php 9 $user->name -modules/user/views/reset_password.html.php 12 DIRTY $confirm_url -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 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() -themes/admin_default/views/admin.html.php 43 DIRTY $theme->site_status() -themes/admin_default/views/admin.html.php 45 DIRTY $theme->admin_header_top() -themes/admin_default/views/admin.html.php 48 DIRTY $csrf -themes/admin_default/views/admin.html.php 52 DIRTY $theme->admin_menu() -themes/admin_default/views/admin.html.php 54 DIRTY $theme->admin_header_bottom() -themes/admin_default/views/admin.html.php 60 DIRTY $theme->messages() -themes/admin_default/views/admin.html.php 61 DIRTY $content -themes/admin_default/views/admin.html.php 67 DIRTY $sidebar -themes/admin_default/views/admin.html.php 72 DIRTY $theme->admin_footer() -themes/admin_default/views/admin.html.php 74 DIRTY $theme->admin_credits() -themes/admin_default/views/admin.html.php 78 DIRTY $theme->admin_page_bottom() -themes/admin_default/views/block.html.php 2 DIRTY $id -themes/admin_default/views/block.html.php 2 DIRTY $css_id -themes/admin_default/views/block.html.php 5 DIRTY $id -themes/admin_default/views/block.html.php 5 DIRTY $csrf -themes/admin_default/views/block.html.php 10 DIRTY $title -themes/admin_default/views/block.html.php 13 DIRTY $content -themes/admin_default/views/pager.html.php 13 DIRTY $url -themes/admin_default/views/pager.html.php 20 DIRTY $previous_page -themes/admin_default/views/pager.html.php 20 DIRTY $url -themes/admin_default/views/pager.html.php 27 DIRTY $from_to_msg -themes/admin_default/views/pager.html.php 30 DIRTY $next_page -themes/admin_default/views/pager.html.php 30 DIRTY $url -themes/admin_default/views/pager.html.php 37 DIRTY $last_page -themes/admin_default/views/pager.html.php 37 DIRTY $url -themes/default/views/album.html.php 4 DIRTY $theme->album_top() -themes/default/views/album.html.php 5 $item->title -themes/default/views/album.html.php 6 $item->description -themes/default/views/album.html.php 16 DIRTY $child->id -themes/default/views/album.html.php 16 DIRTY $item_class -themes/default/views/album.html.php 17 DIRTY $theme->thumb_top($child) -themes/default/views/album.html.php 18 DIRTY $child->url() -themes/default/views/album.html.php 19 DIRTY $child->thumb_img(array("class" => "gThumbnail")) -themes/default/views/album.html.php 21 DIRTY $theme->thumb_bottom($child) -themes/default/views/album.html.php 22 DIRTY $theme->thumb_menu($child) -themes/default/views/album.html.php 23 DIRTY $child->url() -themes/default/views/album.html.php 23 $child->title -themes/default/views/album.html.php 25 DIRTY $theme->thumb_info($child) -themes/default/views/album.html.php 33 DIRTY $addurl -themes/default/views/album.html.php 39 DIRTY $theme->album_bottom() -themes/default/views/album.html.php 41 DIRTY $theme->pager() -themes/default/views/block.html.php 2 DIRTY $anchor -themes/default/views/block.html.php 3 DIRTY $css_id -themes/default/views/block.html.php 4 DIRTY $title -themes/default/views/block.html.php 6 DIRTY $content -themes/default/views/dynamic.html.php 4 DIRTY $theme->dynamic_top() -themes/default/views/dynamic.html.php 6 $tag->name -themes/default/views/dynamic.html.php 11 DIRTY $child->is_album() -themes/default/views/dynamic.html.php 12 DIRTY $theme->thumb_top($child) -themes/default/views/dynamic.html.php 13 DIRTY $child->url() -themes/default/views/dynamic.html.php 14 DIRTY $child->id -themes/default/views/dynamic.html.php 15 DIRTY $child->thumb_url() -themes/default/views/dynamic.html.php 16 DIRTY $child->thumb_width -themes/default/views/dynamic.html.php 17 DIRTY $child->thumb_height -themes/default/views/dynamic.html.php 19 $child->title -themes/default/views/dynamic.html.php 20 DIRTY $theme->thumb_bottom($child) -themes/default/views/dynamic.html.php 22 DIRTY $theme->thumb_info($child) -themes/default/views/dynamic.html.php 27 DIRTY $theme->dynamic_bottom() -themes/default/views/dynamic.html.php 29 DIRTY $theme->pager() -themes/default/views/footer.html.php 2 DIRTY $theme->footer() -themes/default/views/footer.html.php 4 DIRTY $footer_text -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 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 -themes/default/views/header.html.php 21 DIRTY $item->id -themes/default/views/header.html.php 22 $parent->title -themes/default/views/header.html.php 26 $item->title -themes/default/views/movie.html.php 3 DIRTY $theme->photo_top() -themes/default/views/movie.html.php 6 DIRTY $position -themes/default/views/movie.html.php 6 DIRTY $sibling_count -themes/default/views/movie.html.php 8 DIRTY $previous_item->url() -themes/default/views/movie.html.php 11 DIRTY $next_item->url() -themes/default/views/movie.html.php 15 DIRTY $item->movie_img(array("class" => "gMovie", "id" => "gMovieId-{$item->id}")) -themes/default/views/movie.html.php 18 $item->title -themes/default/views/movie.html.php 19 $item->description -themes/default/views/movie.html.php 25 DIRTY $theme->photo_bottom() -themes/default/views/page.html.php 9 DIRTY $page_title -themes/default/views/page.html.php 13 $theme->item()->title -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 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 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() -themes/default/views/page.html.php 76 DIRTY $theme->site_status() -themes/default/views/page.html.php 84 DIRTY $theme->messages() -themes/default/views/page.html.php 85 DIRTY $content -themes/default/views/page.html.php 99 DIRTY $theme->page_bottom() -themes/default/views/pager.html.php 13 DIRTY $url -themes/default/views/pager.html.php 20 DIRTY $previous_page -themes/default/views/pager.html.php 20 DIRTY $url -themes/default/views/pager.html.php 27 DIRTY $from_to_msg -themes/default/views/pager.html.php 30 DIRTY $next_page -themes/default/views/pager.html.php 30 DIRTY $url -themes/default/views/pager.html.php 37 DIRTY $last_page -themes/default/views/pager.html.php 37 DIRTY $url -themes/default/views/photo.html.php 8 DIRTY $theme->item()->file_url() -themes/default/views/photo.html.php 8 DIRTY $theme->item()->width -themes/default/views/photo.html.php 8 DIRTY $theme->item()->height -themes/default/views/photo.html.php 16 DIRTY $theme->photo_top() -themes/default/views/photo.html.php 21 DIRTY $previous_item->url() -themes/default/views/photo.html.php 28 DIRTY $position -themes/default/views/photo.html.php 28 DIRTY $sibling_count -themes/default/views/photo.html.php 31 DIRTY $next_item->url() -themes/default/views/photo.html.php 41 DIRTY $theme->resize_top($item) -themes/default/views/photo.html.php 43 DIRTY $item->file_url() -themes/default/views/photo.html.php 45 DIRTY $item->resize_img(array("id" => "gPhotoId-{$item->id}", "class" => "gResize")) -themes/default/views/photo.html.php 49 DIRTY $theme->resize_bottom($item) -themes/default/views/photo.html.php 53 $item->title -themes/default/views/photo.html.php 54 $item->description -themes/default/views/photo.html.php 60 DIRTY $theme->photo_bottom() -themes/default/views/sidebar.html.php 2 DIRTY $theme->sidebar_top() -themes/default/views/sidebar.html.php 6 DIRTY $theme->album_menu() -themes/default/views/sidebar.html.php 8 DIRTY $theme->photo_menu() -themes/default/views/sidebar.html.php 10 DIRTY $theme->tag_menu() -themes/default/views/sidebar.html.php 15 DIRTY $theme->sidebar_blocks() -themes/default/views/sidebar.html.php 16 DIRTY $theme->sidebar_bottom() +modules/akismet/views/admin_akismet.html.php 16 DIRTY $form +modules/akismet/views/admin_akismet_stats.html.php 9 DIRTY_ATTR $api_key +modules/akismet/views/admin_akismet_stats.html.php 9 DIRTY_ATTR urlencode($blog_url) +modules/comment/views/admin_block_recent_comments.html.php 4 DIRTY_ATTR ($i%2==0)?"gEvenRow":"gOddRow" +modules/comment/views/admin_block_recent_comments.html.php 5 DIRTY_ATTR $comment->author()->avatar_url(32,$theme->url(,true)) +modules/comment/views/admin_block_recent_comments.html.php 10 DIRTY gallery::date_time($comment->created) +modules/comment/views/admin_comments.html.php 42 DIRTY $menu +modules/comment/views/admin_comments.html.php 106 DIRTY_ATTR $comment->id +modules/comment/views/admin_comments.html.php 106 DIRTY_ATTR ($i%2==0)?"gOddRow":"gEvenRow" +modules/comment/views/admin_comments.html.php 109 DIRTY_ATTR $comment->author()->avatar_url(40,$theme->url(,true)) +modules/comment/views/admin_comments.html.php 122 DIRTY_JS $item->url() +modules/comment/views/admin_comments.html.php 124 DIRTY_ATTR $item->thumb_url() +modules/comment/views/admin_comments.html.php 126 DIRTY photo::img_dimensions($item->thumb_width,$item->thumb_height,75) +modules/comment/views/admin_comments.html.php 134 DIRTY gallery::date($comment->created) +modules/comment/views/admin_comments.html.php 141 DIRTY_JS $comment->id +modules/comment/views/admin_comments.html.php 150 DIRTY_JS $comment->id +modules/comment/views/admin_comments.html.php 159 DIRTY_JS $comment->id +modules/comment/views/admin_comments.html.php 168 DIRTY_JS $comment->id +modules/comment/views/admin_comments.html.php 175 DIRTY_JS $comment->id +modules/comment/views/admin_comments.html.php 183 DIRTY_JS $comment->id +modules/comment/views/admin_comments.html.php 196 DIRTY $pager +modules/comment/views/comment.html.php 2 DIRTY_ATTR $comment->id; +modules/comment/views/comment.html.php 5 DIRTY_ATTR $comment->author()->avatar_url(40,$theme->url(,true)) +modules/comment/views/comment.mrss.php 10 DIRTY $feed->uri +modules/comment/views/comment.mrss.php 13 DIRTY_JS $feed->uri +modules/comment/views/comment.mrss.php 16 DIRTY_JS $feed->previous_page_uri +modules/comment/views/comment.mrss.php 19 DIRTY_JS $feed->next_page_uri +modules/comment/views/comment.mrss.php 21 DIRTY $pub_date +modules/comment/views/comment.mrss.php 22 DIRTY $pub_date +modules/comment/views/comment.mrss.php 28 DIRTY $child->item_uri +modules/comment/views/comment.mrss.php 29 DIRTY $child->pub_date +modules/comment/views/comment.mrss.php 34 DIRTY_ATTR $child->thumb_url +modules/comment/views/comment.mrss.php 35 DIRTY_ATTR $child->thumb_height +modules/comment/views/comment.mrss.php 35 DIRTY_ATTR $child->thumb_width +modules/comment/views/comments.html.php 16 DIRTY_ATTR $comment->id +modules/comment/views/comments.html.php 19 DIRTY_ATTR $comment->author()->avatar_url(40,$theme->url(,true)) +modules/digibug/views/digibug_form.html.php 4 DIRTY form::open("http://www.digibug.com/dapi/order.php") +modules/digibug/views/digibug_form.html.php 5 DIRTY form::hidden($order_parms) +modules/digibug/views/digibug_form.html.php 6 DIRTY form::close() +modules/exif/views/exif_dialog.html.php 14 DIRTY $details[$i]["caption"] +modules/exif/views/exif_dialog.html.php 21 DIRTY $details[$i]["caption"] +modules/g2_import/views/admin_g2_import.html.php 28 DIRTY $form +modules/gallery/views/admin_advanced_settings.html.php 22 DIRTY $var->module_name +modules/gallery/views/admin_block_log_entries.html.php 4 DIRTY_ATTR log::severity_class($entry->severity) +modules/gallery/views/admin_block_log_entries.html.php 6 DIRTY gallery::date_time($entry->timestamp) +modules/gallery/views/admin_block_log_entries.html.php 7 DIRTY $entry->message +modules/gallery/views/admin_block_log_entries.html.php 8 DIRTY $entry->html +modules/gallery/views/admin_block_news.html.php 5 DIRTY_JS $entry["link"] +modules/gallery/views/admin_block_news.html.php 5 DIRTY $entry["title"] +modules/gallery/views/admin_block_news.html.php 7 DIRTY text::limit_words(strip_tags($entry["description"]),25); +modules/gallery/views/admin_block_photo_stream.html.php 5 DIRTY_JS $photo->url() +modules/gallery/views/admin_block_photo_stream.html.php 6 DIRTY photo::img_dimensions($photo->width,$photo->height,72) +modules/gallery/views/admin_block_photo_stream.html.php 7 DIRTY_ATTR $photo->thumb_url() +modules/gallery/views/admin_dashboard.html.php 5 DIRTY_JS $csrf +modules/gallery/views/admin_dashboard.html.php 35 DIRTY $blocks +modules/gallery/views/admin_graphics.html.php 22 DIRTY newView("admin_graphics_none.html") +modules/gallery/views/admin_graphics.html.php 24 DIRTY newView("admin_graphics_$active.html",array("tk"=>$tk->$active,"is_active"=>true)) +modules/gallery/views/admin_graphics.html.php 31 DIRTY newView("admin_graphics_$id.html",array("tk"=>$tk->$id,"is_active"=>false)) +modules/gallery/views/admin_graphics_gd.html.php 2 DIRTY_ATTR $is_active?" gSelected":"" +modules/gallery/views/admin_graphics_gd.html.php 2 DIRTY_ATTR $tk->installed?" gInstalledToolkit":" gUnavailable" +modules/gallery/views/admin_graphics_gd.html.php 19 DIRTY $tk->error +modules/gallery/views/admin_graphics_graphicsmagick.html.php 2 DIRTY_ATTR $is_active?" gSelected":"" +modules/gallery/views/admin_graphics_graphicsmagick.html.php 2 DIRTY_ATTR $tk->installed?" gInstalledToolkit":" gUnavailable" +modules/gallery/views/admin_graphics_graphicsmagick.html.php 18 DIRTY $tk->error +modules/gallery/views/admin_graphics_imagemagick.html.php 2 DIRTY_ATTR $is_active?" gSelected":"" +modules/gallery/views/admin_graphics_imagemagick.html.php 2 DIRTY_ATTR $tk->installed?" gInstalledToolkit":" gUnavailable" +modules/gallery/views/admin_graphics_imagemagick.html.php 18 DIRTY $tk->error +modules/gallery/views/admin_languages.html.php 9 DIRTY access::csrf_form_field() +modules/gallery/views/admin_languages.html.php 27 DIRTY_ATTR (isset($installed_locales[$code]))?"installed":"" +modules/gallery/views/admin_languages.html.php 27 DIRTY_ATTR ($default_locale==$code)?" default":"" +modules/gallery/views/admin_languages.html.php 28 DIRTY form::checkbox("installed_locales[]",$code,isset($installed_locales[$code])) +modules/gallery/views/admin_languages.html.php 29 DIRTY $display_name +modules/gallery/views/admin_languages.html.php 31 DIRTY form::radio("default_locale",$code,($default_locale==$code),((isset($installed_locales[$code]))?'':'disabled="disabled"')) +modules/gallery/views/admin_languages.html.php 102 DIRTY $share_translations_form +modules/gallery/views/admin_maintenance.html.php 24 DIRTY_ATTR ($i%2==0)?"gOddRow":"gEvenRow" +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 72 DIRTY_ATTR ($i%2==0)?"gOddRow":"gEvenRow" +modules/gallery/views/admin_maintenance.html.php 72 DIRTY_ATTR $task->state=="stalled"?"gWarning":"" +modules/gallery/views/admin_maintenance.html.php 73 DIRTY_ATTR $task->state=="stalled"?"gWarning":"" +modules/gallery/views/admin_maintenance.html.php 74 DIRTY gallery::date_time($task->updated) +modules/gallery/views/admin_maintenance.html.php 77 DIRTY $task->name +modules/gallery/views/admin_maintenance.html.php 92 DIRTY $task->status +modules/gallery/views/admin_maintenance.html.php 145 DIRTY_ATTR ($i%2==0)?"gOddRow":"gEvenRow" +modules/gallery/views/admin_maintenance.html.php 145 DIRTY_ATTR $task->state=="success"?"gSuccess":"gError" +modules/gallery/views/admin_maintenance.html.php 146 DIRTY_ATTR $task->state=="success"?"gSuccess":"gError" +modules/gallery/views/admin_maintenance.html.php 147 DIRTY gallery::date_time($task->updated) +modules/gallery/views/admin_maintenance.html.php 150 DIRTY $task->name +modules/gallery/views/admin_maintenance.html.php 162 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 +modules/gallery/views/admin_modules.html.php 9 DIRTY access::csrf_form_field() +modules/gallery/views/admin_modules.html.php 19 DIRTY_ATTR ($i%2==0)?"gOddRow":"gEvenRow" +modules/gallery/views/admin_modules.html.php 22 DIRTY form::checkbox($data,'1',module::is_active($module_name)) +modules/gallery/views/admin_modules.html.php 24 DIRTY $module_info->version +modules/gallery/views/admin_theme_options.html.php 5 DIRTY $form +modules/gallery/views/admin_themes.html.php 3 DIRTY_JS url::site("admin/themes/choose") +modules/gallery/views/admin_themes.html.php 5 DIRTY_JS $csrf +modules/gallery/views/admin_themes.html.php 20 DIRTY $themes[$site]->name +modules/gallery/views/admin_themes.html.php 22 DIRTY $themes[$site]->description +modules/gallery/views/admin_themes.html.php 36 DIRTY $info->name +modules/gallery/views/admin_themes.html.php 38 DIRTY $info->description +modules/gallery/views/admin_themes.html.php 58 DIRTY $themes[$admin]->name +modules/gallery/views/admin_themes.html.php 60 DIRTY $themes[$admin]->description +modules/gallery/views/admin_themes.html.php 74 DIRTY $info->name +modules/gallery/views/admin_themes.html.php 76 DIRTY $info->description +modules/gallery/views/admin_themes_preview.html.php 7 DIRTY_ATTR $url +modules/gallery/views/kohana_error_page.php 102 DIRTY $message +modules/gallery/views/kohana_error_page.php 116 DIRTY $trace +modules/gallery/views/kohana_profiler.php 32 DIRTY $profile->render(); +modules/gallery/views/l10n_client.html.php 21 DIRTY_ATTR $string["translation"]===""?"untranslated":"translated" +modules/gallery/views/l10n_client.html.php 23 DIRTY $string["source"]["one"] +modules/gallery/views/l10n_client.html.php 24 DIRTY $string["source"]["other"] +modules/gallery/views/l10n_client.html.php 26 DIRTY $string["source"] +modules/gallery/views/l10n_client.html.php 32 DIRTY $l10n_search_form +modules/gallery/views/l10n_client.html.php 41 DIRTY access::csrf_form_field() +modules/gallery/views/l10n_client.html.php 42 DIRTY form::hidden("l10n-message-key") +modules/gallery/views/l10n_client.html.php 43 DIRTY form::textarea("l10n-edit-translation","",' rows="5" class="translationField"') +modules/gallery/views/l10n_client.html.php 46 DIRTY form::textarea("l10n-edit-plural-translation-zero","",' rows="2"') +modules/gallery/views/l10n_client.html.php 50 DIRTY form::textarea("l10n-edit-plural-translation-one","",' rows="2"') +modules/gallery/views/l10n_client.html.php 54 DIRTY form::textarea("l10n-edit-plural-translation-two","",' rows="2"') +modules/gallery/views/l10n_client.html.php 58 DIRTY form::textarea("l10n-edit-plural-translation-few","",' rows="2"') +modules/gallery/views/l10n_client.html.php 62 DIRTY form::textarea("l10n-edit-plural-translation-many","",' rows="2"') +modules/gallery/views/l10n_client.html.php 67 DIRTY form::textarea("l10n-edit-plural-translation-other","",' rows="2"') +modules/gallery/views/maintenance.html.php 46 DIRTY user::get_login_form("login/auth_html") +modules/gallery/views/move_browse.html.php 4 DIRTY_JS url::site("move/show_sub_tree/{$source->id}/__TARGETID__") +modules/gallery/views/move_browse.html.php 39 DIRTY $tree +modules/gallery/views/move_browse.html.php 43 DIRTY access::csrf_form_field() +modules/gallery/views/move_tree.html.php 2 DIRTY $parent->thumb_img(array(),25); +modules/gallery/views/move_tree.html.php 4 DIRTY_JS $parent->id +modules/gallery/views/move_tree.html.php 6 DIRTY_JS $parent->id +modules/gallery/views/move_tree.html.php 8 DIRTY_ATTR $parent->id +modules/gallery/views/move_tree.html.php 10 DIRTY_ATTR $child->id +modules/gallery/views/move_tree.html.php 11 DIRTY $child->thumb_img(array(),25); +modules/gallery/views/move_tree.html.php 13 DIRTY_JS $child->id +modules/gallery/views/move_tree.html.php 15 DIRTY_JS $child->id +modules/gallery/views/movieplayer.html.php 2 DIRTY html::anchor($item->file_url(true),"",$attrs) +modules/gallery/views/movieplayer.html.php 5 DIRTY_JS $attrs["id"] +modules/gallery/views/movieplayer.html.php 7 DIRTY_JS url::abs_file("lib/flowplayer.swf") +modules/gallery/views/movieplayer.html.php 13 DIRTY_JS url::abs_file("lib/flowplayer.h264streaming.swf") +modules/gallery/views/permissions_browse.html.php 3 DIRTY_JS url::site("permissions/form/__ITEM__") +modules/gallery/views/permissions_browse.html.php 16 DIRTY_JS url::site("permissions/change/__CMD__/__GROUP__/__PERM__/__ITEM__?csrf=$csrf") +modules/gallery/views/permissions_browse.html.php 42 DIRTY_ATTR $parent->id +modules/gallery/views/permissions_browse.html.php 44 DIRTY_JS $parent->id +modules/gallery/views/permissions_browse.html.php 52 DIRTY_ATTR $item->id +modules/gallery/views/permissions_browse.html.php 53 DIRTY_JS $item->id +modules/gallery/views/permissions_browse.html.php 60 DIRTY $form +modules/gallery/views/permissions_form.html.php 24 DIRTY_JS $lock->id +modules/gallery/views/permissions_form.html.php 32 DIRTY_JS $group->id +modules/gallery/views/permissions_form.html.php 32 DIRTY_JS $permission->id +modules/gallery/views/permissions_form.html.php 32 DIRTY_JS $item->id +modules/gallery/views/permissions_form.html.php 36 DIRTY_JS $group->id +modules/gallery/views/permissions_form.html.php 36 DIRTY_JS $permission->id +modules/gallery/views/permissions_form.html.php 36 DIRTY_JS $item->id +modules/gallery/views/permissions_form.html.php 43 DIRTY_JS $group->id +modules/gallery/views/permissions_form.html.php 43 DIRTY_JS $permission->id +modules/gallery/views/permissions_form.html.php 43 DIRTY_JS $item->id +modules/gallery/views/permissions_form.html.php 47 DIRTY_JS $group->id +modules/gallery/views/permissions_form.html.php 47 DIRTY_JS $permission->id +modules/gallery/views/permissions_form.html.php 47 DIRTY_JS $item->id +modules/gallery/views/permissions_form.html.php 56 DIRTY_JS $group->id +modules/gallery/views/permissions_form.html.php 56 DIRTY_JS $permission->id +modules/gallery/views/permissions_form.html.php 56 DIRTY_JS $item->id +modules/gallery/views/permissions_form.html.php 63 DIRTY_JS $group->id +modules/gallery/views/permissions_form.html.php 63 DIRTY_JS $permission->id +modules/gallery/views/permissions_form.html.php 63 DIRTY_JS $item->id +modules/gallery/views/permissions_form.html.php 74 DIRTY_JS $group->id +modules/gallery/views/permissions_form.html.php 74 DIRTY_JS $permission->id +modules/gallery/views/permissions_form.html.php 74 DIRTY_JS $item->id +modules/gallery/views/permissions_form.html.php 79 DIRTY_JS $group->id +modules/gallery/views/permissions_form.html.php 79 DIRTY_JS $permission->id +modules/gallery/views/permissions_form.html.php 79 DIRTY_JS $item->id +modules/gallery/views/upgrader.html.php 44 DIRTY_ATTR $module->version==$module->code_version?"current":"upgradeable" +modules/gallery/views/upgrader.html.php 45 DIRTY_ATTR $id +modules/gallery/views/upgrader.html.php 49 DIRTY $module->version +modules/gallery/views/upgrader.html.php 52 DIRTY $module->code_version +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"=>"gThumbnail")) +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 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() +modules/notification/views/item_added.html.php 16 DIRTY_JS $item->abs_url() +modules/notification/views/item_added.html.php 17 DIRTY $item->abs_url() +modules/notification/views/item_deleted.html.php 18 DIRTY_JS $item->parent()->abs_url() +modules/notification/views/item_deleted.html.php 19 DIRTY $item->parent()->abs_url() +modules/notification/views/item_updated.html.php 20 DIRTY_JS $item->abs_url() +modules/notification/views/item_updated.html.php 20 DIRTY $item->abs_url() +modules/organize/views/organize_dialog.html.php 3 DIRTY_JS url::site("organize/move_to/__ALBUM_ID__?csrf=$csrf") +modules/organize/views/organize_dialog.html.php 4 DIRTY_JS url::site("organize/rearrange/__TARGET_ID__/__BEFORE__?csrf=$csrf") +modules/organize/views/organize_dialog.html.php 5 DIRTY_JS url::site("organize/sort_order/__ALBUM_ID__/__COL__/__DIR__?csrf=$csrf") +modules/organize/views/organize_dialog.html.php 6 DIRTY_JS url::site("organize/tree/__ALBUM_ID__") +modules/organize/views/organize_dialog.html.php 22 DIRTY $album_tree +modules/organize/views/organize_dialog.html.php 29 DIRTY $micro_thumb_grid +modules/organize/views/organize_dialog.html.php 37 DIRTY form::dropdown(array("id"=>"gOrganizeSortColumn"),album::get_sort_order_options(),$album->sort_column) +modules/organize/views/organize_dialog.html.php 38 DIRTY form::dropdown(array("id"=>"gOrganizeSortOrder"),array("ASC"=>"Ascending","DESC"=>"Descending"),$album->sort_order) +modules/organize/views/organize_thumb_grid.html.php 3 DIRTY_ATTR $child->id +modules/organize/views/organize_thumb_grid.html.php 4 DIRTY_ATTR $child->id +modules/organize/views/organize_thumb_grid.html.php 5 DIRTY_ATTR $child->is_album()?"gAlbum":"gPhoto" +modules/organize/views/organize_thumb_grid.html.php 6 DIRTY $child->thumb_img(array("class"=>"gThumbnail","ref"=>$child->id),90,true) +modules/organize/views/organize_thumb_grid.html.php 14 DIRTY_JS url::site("organize/album/$album->id/".($offset+25)) +modules/organize/views/organize_tree.html.php 2 DIRTY_ATTR access::can("edit",$album)?"":"gViewOnly" +modules/organize/views/organize_tree.html.php 3 DIRTY_ATTR $album->id +modules/organize/views/organize_tree.html.php 6 DIRTY_ATTR $selected&&$album->id==$selected->id?"selected":"" +modules/organize/views/organize_tree.html.php 7 DIRTY_ATTR $album->id +modules/organize/views/organize_tree.html.php 13 DIRTY View::factory("organize_tree.html",array("selected"=>$selected,"album"=>$child)); +modules/organize/views/organize_tree.html.php 15 DIRTY_ATTR access::can("edit",$child)?"":"gViewOnly" +modules/organize/views/organize_tree.html.php 16 DIRTY_ATTR $child->id +modules/organize/views/organize_tree.html.php 19 DIRTY_ATTR $child->id +modules/recaptcha/views/admin_recaptcha.html.php 10 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/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 +modules/rss/views/feed.mrss.php 19 DIRTY_JS $feed->next_page_uri +modules/rss/views/feed.mrss.php 21 DIRTY $pub_date +modules/rss/views/feed.mrss.php 22 DIRTY $pub_date +modules/rss/views/feed.mrss.php 28 DIRTY date("D, d M Y H:i:s T",$child->created); +modules/rss/views/feed.mrss.php 34 DIRTY_ATTR $child->resize_url(true) +modules/rss/views/feed.mrss.php 36 DIRTY_ATTR $child->resize_height +modules/rss/views/feed.mrss.php 36 DIRTY_ATTR $child->resize_width +modules/rss/views/feed.mrss.php 39 DIRTY_ATTR $child->thumb_url(true) +modules/rss/views/feed.mrss.php 41 DIRTY_ATTR $child->thumb_height +modules/rss/views/feed.mrss.php 41 DIRTY_ATTR $child->thumb_width +modules/rss/views/feed.mrss.php 47 DIRTY_ATTR $child->thumb_url(true) +modules/rss/views/feed.mrss.php 48 DIRTY_ATTR @filesize($child->thumb_path()) +modules/rss/views/feed.mrss.php 49 DIRTY_ATTR $child->thumb_height +modules/rss/views/feed.mrss.php 50 DIRTY_ATTR $child->thumb_width +modules/rss/views/feed.mrss.php 54 DIRTY_ATTR $child->resize_url(true) +modules/rss/views/feed.mrss.php 55 DIRTY_ATTR @filesize($child->resize_path()) +modules/rss/views/feed.mrss.php 56 DIRTY_ATTR $child->mime_type +modules/rss/views/feed.mrss.php 57 DIRTY_ATTR $child->resize_height +modules/rss/views/feed.mrss.php 58 DIRTY_ATTR $child->resize_width +modules/rss/views/feed.mrss.php 62 DIRTY_ATTR $child->file_url(true) +modules/rss/views/feed.mrss.php 63 DIRTY_ATTR @filesize($child->file_path()) +modules/rss/views/feed.mrss.php 64 DIRTY_ATTR $child->mime_type +modules/rss/views/feed.mrss.php 65 DIRTY_ATTR $child->height +modules/rss/views/feed.mrss.php 66 DIRTY_ATTR $child->width +modules/rss/views/feed.mrss.php 70 DIRTY_ATTR $child->file_url(true) +modules/rss/views/feed.mrss.php 71 DIRTY_ATTR @filesize($child->file_path()) +modules/rss/views/feed.mrss.php 72 DIRTY_ATTR $child->height +modules/rss/views/feed.mrss.php 73 DIRTY_ATTR $child->width +modules/rss/views/feed.mrss.php 74 DIRTY_ATTR $child->mime_type +modules/rss/views/rss_block.html.php 6 DIRTY_JS rss::url($url) +modules/search/views/search.html.php 30 DIRTY_ATTR $item_class +modules/search/views/search.html.php 31 DIRTY_JS $item->url() +modules/search/views/search.html.php 32 DIRTY $item->thumb_img() +modules/server_add/views/admin_server_add.html.php 15 DIRTY_ATTR $id +modules/server_add/views/admin_server_add.html.php 24 DIRTY $form +modules/server_add/views/server_add_tree.html.php 12 DIRTY_JS html::js_string($dir) +modules/server_add/views/server_add_tree.html.php 20 DIRTY_ATTR is_dir($file)?"ui-icon-folder-collapsed":"ui-icon-document" +modules/server_add/views/server_add_tree_dialog.html.php 3 DIRTY_JS url::site("server_add/children?path=__PATH__") +modules/server_add/views/server_add_tree_dialog.html.php 4 DIRTY_JS url::site("server_add/start?item_id={$item->id}&csrf=$csrf") +modules/server_add/views/server_add_tree_dialog.html.php 23 DIRTY $tree +modules/tag/views/admin_tags.html.php 13 DIRTY_JS $csrf +modules/tag/views/admin_tags.html.php 50 DIRTY_ATTR $tag->id +modules/tag/views/admin_tags.html.php 51 DIRTY $tag->count +modules/tag/views/tag_block.html.php 15 DIRTY $cloud +modules/tag/views/tag_block.html.php 17 DIRTY $form +modules/tag/views/tag_cloud.html.php 4 DIRTY_ATTR (int)(($tag->count/$max_count)*7) +modules/tag/views/tag_cloud.html.php 5 DIRTY $tag->count +modules/user/views/admin_users.html.php 3 DIRTY_JS url::site("admin/users/add_user_to_group/__USERID__/__GROUPID__?csrf=$csrf") +modules/user/views/admin_users.html.php 26 DIRTY_JS url::site("admin/users/group/__GROUPID__") +modules/user/views/admin_users.html.php 36 DIRTY_JS url::site("admin/users/remove_user_from_group/__USERID__/__GROUPID__?csrf=$csrf") +modules/user/views/admin_users.html.php 67 DIRTY_ATTR $user->id +modules/user/views/admin_users.html.php 67 DIRTY_ATTR text::alternate("gOddRow","gEvenRow") +modules/user/views/admin_users.html.php 67 DIRTY_ATTR $user->admin?"admin":"" +modules/user/views/admin_users.html.php 68 DIRTY_ATTR $user->id +modules/user/views/admin_users.html.php 69 DIRTY_ATTR $user->avatar_url(20,$theme->url(,true)) +modules/user/views/admin_users.html.php 83 DIRTY ($user->last_login==0)?"":gallery::date($user->last_login) +modules/user/views/admin_users.html.php 121 DIRTY_ATTR $group->id +modules/user/views/admin_users.html.php 121 DIRTY_ATTR ($group->special?"gDefaultGroup":"") +modules/user/views/admin_users.html.php 123 DIRTY $v +modules/user/views/admin_users_group.html.php 22 DIRTY_JS $user->id +modules/user/views/admin_users_group.html.php 22 DIRTY_JS $group->id +modules/user/views/login_ajax.html.php 6 DIRTY_JS url::site("password/reset") +modules/user/views/login_ajax.html.php 37 DIRTY $form +modules/user/views/user_languages_block.html.php 2 DIRTY form::dropdown("gSelectSessionLocale",$installed_locales,$selected) +modules/watermark/views/admin_watermarks.html.php 19 DIRTY_ATTR $width +modules/watermark/views/admin_watermarks.html.php 19 DIRTY_ATTR $height +modules/watermark/views/admin_watermarks.html.php 19 DIRTY_ATTR $url +themes/admin_default/views/admin.html.php 15 DIRTY_JS $theme->url() +themes/admin_default/views/admin.html.php 32 DIRTY $theme->admin_head() +themes/admin_default/views/admin.html.php 36 DIRTY $theme->admin_page_top() +themes/admin_default/views/admin.html.php 44 DIRTY $theme->admin_header_top() +themes/admin_default/views/admin.html.php 49 DIRTY_JS item::root()->url() +themes/admin_default/views/admin.html.php 53 DIRTY $theme->admin_menu() +themes/admin_default/views/admin.html.php 55 DIRTY $theme->admin_header_bottom() +themes/admin_default/views/admin.html.php 62 DIRTY $content +themes/admin_default/views/admin.html.php 68 DIRTY $sidebar +themes/admin_default/views/admin.html.php 73 DIRTY $theme->admin_footer() +themes/admin_default/views/admin.html.php 75 DIRTY $theme->admin_credits() +themes/admin_default/views/admin.html.php 79 DIRTY $theme->admin_page_bottom() +themes/admin_default/views/block.html.php 2 DIRTY $id +themes/admin_default/views/block.html.php 2 DIRTY_ATTR $css_id +themes/admin_default/views/block.html.php 10 DIRTY $title +themes/admin_default/views/block.html.php 13 DIRTY $content +themes/admin_default/views/pager.html.php 13 DIRTY_JS str_replace('{page}',1,$url) +themes/admin_default/views/pager.html.php 20 DIRTY_JS str_replace('{page}',$previous_page,$url) +themes/admin_default/views/pager.html.php 27 DIRTY $from_to_msg +themes/admin_default/views/pager.html.php 30 DIRTY_JS str_replace('{page}',$next_page,$url) +themes/admin_default/views/pager.html.php 37 DIRTY_JS str_replace('{page}',$last_page,$url) +themes/default/views/album.html.php 16 DIRTY_ATTR $child->id +themes/default/views/album.html.php 16 DIRTY_ATTR $item_class +themes/default/views/album.html.php 18 DIRTY_JS $child->url() +themes/default/views/album.html.php 19 DIRTY $child->thumb_img(array("class"=>"gThumbnail")) +themes/default/views/album.html.php 23 DIRTY_JS $child->url() +themes/default/views/block.html.php 2 DIRTY_ATTR $anchor +themes/default/views/block.html.php 3 DIRTY_ATTR $css_id +themes/default/views/block.html.php 4 DIRTY $title +themes/default/views/block.html.php 6 DIRTY $content +themes/default/views/dynamic.html.php 11 DIRTY_ATTR $child->is_album()?"gAlbum":"" +themes/default/views/dynamic.html.php 13 DIRTY_JS $child->url() +themes/default/views/dynamic.html.php 14 DIRTY_ATTR $child->id +themes/default/views/dynamic.html.php 15 DIRTY_ATTR $child->thumb_url() +themes/default/views/dynamic.html.php 16 DIRTY_ATTR $child->thumb_width +themes/default/views/dynamic.html.php 17 DIRTY_ATTR $child->thumb_height +themes/default/views/movie.html.php 8 DIRTY_JS $previous_item->url() +themes/default/views/movie.html.php 18 DIRTY_JS $next_item->url() +themes/default/views/movie.html.php 28 DIRTY $item->movie_img(array("class"=>"gMovie","id"=>"gMovieId-{$item->id}")) +themes/default/views/page.html.php 9 DIRTY $page_title +themes/default/views/page.html.php 32 DIRTY_JS $theme->url() +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 82 DIRTY $header_text +themes/default/views/page.html.php 84 DIRTY_JS item::root()->url() +themes/default/views/page.html.php 98 DIRTY_JS $parent->url("show={$theme->item()->id}") +themes/default/views/page.html.php 112 DIRTY $content +themes/default/views/page.html.php 118 DIRTY newView("sidebar.html") +themes/default/views/page.html.php 125 DIRTY $footer_text +themes/default/views/pager.html.php 13 DIRTY_JS str_replace('{page}',1,$url) +themes/default/views/pager.html.php 20 DIRTY_JS str_replace('{page}',$previous_page,$url) +themes/default/views/pager.html.php 27 DIRTY $from_to_msg +themes/default/views/pager.html.php 30 DIRTY_JS str_replace('{page}',$next_page,$url) +themes/default/views/pager.html.php 37 DIRTY_JS str_replace('{page}',$last_page,$url) +themes/default/views/photo.html.php 8 DIRTY_JS $theme->item()->width +themes/default/views/photo.html.php 8 DIRTY_JS $theme->item()->height +themes/default/views/photo.html.php 21 DIRTY_JS $previous_item->url() +themes/default/views/photo.html.php 31 DIRTY_JS $next_item->url() +themes/default/views/photo.html.php 43 DIRTY_JS $item->file_url() +themes/default/views/photo.html.php 45 DIRTY $item->resize_img(array("id"=>"gPhotoId-{$item->id}","class"=>"gResize")) diff --git a/modules/gallery/views/admin_advanced_settings.html.php b/modules/gallery/views/admin_advanced_settings.html.php index b37c1c73..c3595da5 100644 --- a/modules/gallery/views/admin_advanced_settings.html.php +++ b/modules/gallery/views/admin_advanced_settings.html.php @@ -20,13 +20,13 @@ <? if ($var->module_name == "gallery" && $var->name == "_cache") continue ?> <tr class="setting"> <td> <?= $var->module_name ?> </td> - <td> <?= p::clean($var->name) ?> </td> + <td> <?= html::clean($var->name) ?> </td> <td> - <a href="<?= url::site("admin/advanced_settings/edit/$var->module_name/" . p::clean($var->name)) ?>" + <a href="<?= url::site("admin/advanced_settings/edit/$var->module_name/" . html::clean($var->name)) ?>" class="gDialogLink" - title="<?= t("Edit %var (%module_name)", array("var" => p::clean($var->name), "module_name" => $var->module_name)) ?>"> + title="<?= t("Edit %var (%module_name)", array("var" => $var->name, "module_name" => $var->module_name))->for_html_attr() ?>"> <? if ($var->value): ?> - <?= p::clean($var->value) ?> + <?= html::clean($var->value) ?> <? else: ?> <i> <?= t("empty") ?> </i> <? endif ?> diff --git a/modules/gallery/views/admin_block_log_entries.html.php b/modules/gallery/views/admin_block_log_entries.html.php index 44c1657f..780ff2d0 100644 --- a/modules/gallery/views/admin_block_log_entries.html.php +++ b/modules/gallery/views/admin_block_log_entries.html.php @@ -2,7 +2,7 @@ <ul> <? foreach ($entries as $entry): ?> <li class="<?= log::severity_class($entry->severity) ?>" style="direction: ltr"> - <a href="<?= url::site("user/$entry->user_id") ?>"><?= p::clean($entry->user->name) ?></a> + <a href="<?= url::site("user/$entry->user_id") ?>"><?= html::clean($entry->user->name) ?></a> <?= gallery::date_time($entry->timestamp) ?> <?= $entry->message ?> <?= $entry->html ?> diff --git a/modules/gallery/views/admin_block_photo_stream.html.php b/modules/gallery/views/admin_block_photo_stream.html.php index 1e1329d1..4968c39b 100644 --- a/modules/gallery/views/admin_block_photo_stream.html.php +++ b/modules/gallery/views/admin_block_photo_stream.html.php @@ -2,9 +2,9 @@ <ul> <? foreach ($photos as $photo): ?> <li class="gItem gPhoto"> - <a href="<?= url::site("photos/$photo->id") ?>" title="<?= p::clean($photo->title) ?>"> + <a href="<?= $photo->url() ?>" title="<?= html::purify($photo->title)->for_html_attr() ?>"> <img <?= photo::img_dimensions($photo->width, $photo->height, 72) ?> - src="<?= $photo->thumb_url() ?>" alt="<?= p::clean($photo->title) ?>" /> + src="<?= $photo->thumb_url() ?>" alt="<?= html::purify($photo->title)->for_html_attr() ?>" /> </a> </li> <? endforeach ?> diff --git a/modules/gallery/views/admin_block_platform.html.php b/modules/gallery/views/admin_block_platform.html.php index 6b79f047..f27b9e7a 100644 --- a/modules/gallery/views/admin_block_platform.html.php +++ b/modules/gallery/views/admin_block_platform.html.php @@ -1,7 +1,10 @@ <?php defined("SYSPATH") or die("No direct script access.") ?> <ul> <li> - <?= t("Operating System: %operating_system", array("operating_system" => PHP_OS)) ?> + <?= t("Host name: %host_name", array("host_name" => php_uname("n"))) ?> + </li> + <li> + <?= t("Operating System: %os %version", array("os" => php_uname("s"), "version" => php_uname("r"))) ?> </li> <li> <?= t("Apache: %apache_version", array("apache_version" => function_exists("apache_get_version") ? apache_get_version() : t("Unknown"))) ?> diff --git a/modules/gallery/views/admin_block_welcome.html.php b/modules/gallery/views/admin_block_welcome.html.php index 38d2bd56..d8c96187 100644 --- a/modules/gallery/views/admin_block_welcome.html.php +++ b/modules/gallery/views/admin_block_welcome.html.php @@ -5,16 +5,16 @@ <ul> <li> <?= t("General Settings - choose your <a href=\"%graphics_url\">graphics</a> and <a href=\"%language_url\">language</a> settings.", - array("graphics_url" => url::site("admin/graphics"), - "language_url" => url::site("admin/languages"))) ?> + array("graphics_url" => html::mark_clean(url::site("admin/graphics")), + "language_url" => html::mark_clean(url::site("admin/languages")))) ?> </li> <li> <?= t("Appearance - <a href=\"%theme_url\">choose a theme</a>, or <a href=\"%theme_options_url\">customize the way it looks</a>.", - array("theme_url" => url::site("admin/themes"), - "theme_options_url" => url::site("admin/theme_options"))) ?> + array("theme_url" => html::mark_clean(url::site("admin/themes")), + "theme_options_url" => html::mark_clean(url::site("admin/theme_options")))) ?> </li> <li> <?= t("Customize - <a href=\"%modules_url\">install modules</a> to add cool features!", - array("modules_url" => url::site("admin/modules"))) ?> + array("modules_url" => html::mark_clean(url::site("admin/modules")))) ?> </li> </ul> diff --git a/modules/gallery/views/admin_dashboard.html.php b/modules/gallery/views/admin_dashboard.html.php index a2d22ab6..148de65f 100644 --- a/modules/gallery/views/admin_dashboard.html.php +++ b/modules/gallery/views/admin_dashboard.html.php @@ -1,7 +1,7 @@ <?php defined("SYSPATH") or die("No direct script access.") ?> <script type="text/javascript"> update_blocks = function() { - $.get("<?= url::site("admin/dashboard/reorder") ?>", + $.get(<?= html::js_string(url::site("admin/dashboard/reorder")) ?>, {"csrf": "<?= $csrf ?>", "dashboard_center[]": $("#gAdminDashboard").sortable( "toArray", {attribute: "block_id"}), diff --git a/modules/gallery/views/admin_graphics.html.php b/modules/gallery/views/admin_graphics.html.php index 08374471..f64c7f80 100644 --- a/modules/gallery/views/admin_graphics.html.php +++ b/modules/gallery/views/admin_graphics.html.php @@ -3,14 +3,14 @@ $(document).ready(function() { select_toolkit = function(el) { if (!$(this).hasClass("gUnavailable")) { - window.location = '<?= url::site("admin/graphics/choose/__TK__?csrf=$csrf") ?>' + window.location = <?= html::js_string(url::site("admin/graphics/choose/__TK__?csrf=$csrf")) ?> .replace("__TK__", $(this).attr("id")); } }; $("#gAdminGraphics div.gAvailable .gBlock").click(select_toolkit); }); - </script> + <div id="gAdminGraphics"> <h1> <?= t("Graphics Settings") ?> </h1> <p> @@ -18,11 +18,19 @@ </p> <h2> <?= t("Active Toolkit") ?> </h2> - <?= $active ?> + <? if ($active == "none"): ?> + <?= new View("admin_graphics_none.html") ?> + <? else: ?> + <?= new View("admin_graphics_$active.html", array("tk" => $tk->$active, "is_active" => true)) ?> + <? endif ?> <div class="gAvailable"> <h2> <?= t("Available Toolkits") ?> </h2> - <?= $available ?> + <? foreach (array_keys((array)$tk) as $id): ?> + <? if ($id != $active): ?> + <?= new View("admin_graphics_$id.html", array("tk" => $tk->$id, "is_active" => false)) ?> + <? endif ?> + <? endforeach ?> </div> </div> diff --git a/modules/gallery/views/admin_graphics_gd.html.php b/modules/gallery/views/admin_graphics_gd.html.php index b77da8e3..010a31b4 100644 --- a/modules/gallery/views/admin_graphics_gd.html.php +++ b/modules/gallery/views/admin_graphics_gd.html.php @@ -1,29 +1,30 @@ <?php defined("SYSPATH") or die("No direct script access.") ?> -<div id="gd" class="gBlock<?= $is_active ? " gSelected" : "" ?><?= $tk->gd["GD Version"] ? " gInstalledToolkit" : " gUnavailable" ?>"> +<div id="gd" class="gBlock<?= $is_active ? " gSelected" : "" ?><?= $tk->installed ? " gInstalledToolkit" : " gUnavailable" ?>"> <img class="logo" width="170" height="110" src="<?= url::file("modules/gallery/images/gd.png"); ?>" alt="<? t("Visit the GD lib project site") ?>" /> <h3> <?= t("GD") ?> </h3> <p> <?= t("The GD graphics library is an extension to PHP commonly installed most webservers. Please refer to the <a href=\"%url\">GD website</a> for more information.", array("url" => "http://www.boutell.com/gd")) ?> </p> - <? if ($tk->gd["GD Version"] && function_exists('imagerotate')): ?> - <p class="gSuccess"> - <?= t("You have GD version %version.", array("version" => $tk->gd["GD Version"])) ?> - </p> + <? if ($tk->installed && $tk->rotate): ?> + <div class="gModuleStatus gInfo"> + <?= t("You have GD version %version.", array("version" => $tk->version)) ?> + </div> <p> <a class="gButtonLink ui-state-default ui-corner-all"><?= t("Activate GD") ?></a> </p> - <? elseif ($tk->gd["GD Version"]): ?> - <p class="gWarning"> - <?= t("You have GD version %version, but it lacks image rotation.", - array("version" => $tk->gd["GD Version"])) ?> + <? elseif ($tk->installed): ?> + <? if ($tk->error): ?> + <p class="gModuleStatus gWarning"> + <?= $tk->error ?> </p> + <? endif ?> <p> <a class="gButtonLink ui-state-default ui-corner-all"><?= t("Activate GD") ?></a> </p> <? else: ?> - <p class="gInfo"> + <div class="gModuleStatus gInfo"> <?= t("You do not have GD installed.") ?> - </p> + </div> <? endif ?> </div> diff --git a/modules/gallery/views/admin_graphics_graphicsmagick.html.php b/modules/gallery/views/admin_graphics_graphicsmagick.html.php index e2cd0777..97624850 100644 --- a/modules/gallery/views/admin_graphics_graphicsmagick.html.php +++ b/modules/gallery/views/admin_graphics_graphicsmagick.html.php @@ -1,21 +1,21 @@ <?php defined("SYSPATH") or die("No direct script access.") ?> -<div id="graphicsmagick" class="gBlock<?= $is_active ? " gSelected" : "" ?><?= $tk->graphicsmagick ? " gInstalledToolkit" : " gUnavailable" ?>"> - <h3> <?= t("GraphicsMagick") ?> </h3> +<div id="graphicsmagick" class="gBlock<?= $is_active ? " gSelected" : "" ?><?= $tk->installed ? " gInstalledToolkit" : " gUnavailable" ?>"> <img class="logo" width="107" height="76" src="<?= url::file("modules/gallery/images/graphicsmagick.png"); ?>" alt="<? t("Visit the GraphicsMagick project site") ?>" /> + <h3> <?= t("GraphicsMagick") ?> </h3> <p> <?= t("GraphicsMagick is a standalone graphics program available on most Linux systems. Please refer to the <a href=\"%url\">GraphicsMagick website</a> for more information.", array("url" => "http://www.graphicsmagick.org")) ?> </p> - <? if ($tk->graphicsmagick): ?> - <p class="gSuccess"> - <?= t("GraphicsMagick is available in %path", array("path" => $tk->graphicsmagick)) ?> - </p> + <? if ($tk->installed): ?> + <div class="gModuleStatus gInfo"> + <?= t("GraphicsMagick version %version is available in %dir", array("version" => $tk->version, "dir" => $tk->dir)) ?> + </div> <p> <a class="gButtonLink ui-state-default ui-corner-all"><?= t("Activate Graphics Magic") ?></a> </p> <? else: ?> - <p class="gInfo"> - <?= t("GraphicsMagick is not available on your system.") ?> - </p> + <div class="gModuleStatus gWarning"> + <?= $tk->error ?> + </div> <? endif ?> </div> diff --git a/modules/gallery/views/admin_graphics_imagemagick.html.php b/modules/gallery/views/admin_graphics_imagemagick.html.php index 081ddc15..cdff7c2c 100644 --- a/modules/gallery/views/admin_graphics_imagemagick.html.php +++ b/modules/gallery/views/admin_graphics_imagemagick.html.php @@ -1,21 +1,21 @@ <?php defined("SYSPATH") or die("No direct script access.") ?> -<div id="imagemagick" class="gBlock<?= $is_active ? " gSelected" : "" ?><?= $tk->imagemagick ? " gInstalledToolkit" : " gUnavailable" ?>"> - <h3> <?= t("ImageMagick") ?> </h3> +<div id="imagemagick" class="gBlock<?= $is_active ? " gSelected" : "" ?><?= $tk->installed ? " gInstalledToolkit" : " gUnavailable" ?>"> <img class="logo" width="114" height="118" src="<?= url::file("modules/gallery/images/imagemagick.jpg"); ?>" alt="<? t("Visit the ImageMagick project site") ?>" /> + <h3> <?= t("ImageMagick") ?> </h3> <p> <?= t("ImageMagick is a standalone graphics program available on most Linux systems. Please refer to the <a href=\"%url\">ImageMagick website</a> for more information.", array("url" => "http://www.imagemagick.org")) ?> </p> - <? if ($tk->imagemagick): ?> - <p class="gSuccess"> - <?= t("ImageMagick is available in %path", array("path" => $tk->imagemagick)) ?> - </p> + <? if ($tk->installed): ?> + <div class="gModuleStatus gInfo"> + <?= t("ImageMagick version %version is available in %dir", array("version" => $tk->version, "dir" => $tk->dir)) ?> + </div> <p> <a class="gButtonLink ui-state-default ui-corner-all"><?= t("Activate ImageMagick") ?></a> </p> - <? else: ?> - <p class="gInfo"> - <?= t("ImageMagick is not available on your system.") ?> - </p> + <? elseif ($tk->error): ?> + <div class="gModuleStatus gWarning"> + <?= $tk->error ?> + </div> <? endif ?> </div> diff --git a/modules/gallery/views/admin_graphics_none.html.php b/modules/gallery/views/admin_graphics_none.html.php index 5306a70d..e6923a5a 100644 --- a/modules/gallery/views/admin_graphics_none.html.php +++ b/modules/gallery/views/admin_graphics_none.html.php @@ -1,7 +1,8 @@ <?php defined("SYSPATH") or die("No direct script access.") ?> -<div id="none" class="gBlock"> - <h3 class="gWarning"> <?= t("No Active Toolkit") ?> </h3> + +<div id="none" class="gModuleStatus gWarning gBlock"> + <h3> <?= t("No Active Toolkit") ?> </h3> <p> - <?= t("We were unable to detect a graphics program. You must install one of the toolkits below in order to many Gallery features.") ?> + <?= t("We were unable to detect a graphics program. You must install one of the toolkits below in order to use many Gallery features.") ?> </p> </div> diff --git a/modules/gallery/views/admin_languages.html.php b/modules/gallery/views/admin_languages.html.php index f41694b4..fa97d299 100644 --- a/modules/gallery/views/admin_languages.html.php +++ b/modules/gallery/views/admin_languages.html.php @@ -1,15 +1,103 @@ <?php defined("SYSPATH") or die("No direct script access.") ?> <div id="gLanguages"> - <h2> <?= t("Languages") ?> </h2> + <h1> <?= t("Languages") ?> </h1> + <p> + <?= t("Install new languages, update installed ones and set the default language for your Gallery.") ?> + </p> - <?= $settings_form ?> + <form id="gLanguagesForm" method="post" action="<?= url::site("admin/languages/save") ?>"> + <?= access::csrf_form_field() ?> + <table> + <tr> + <th> <?= t("Installed") ?> </th> + <th> <?= t("Language") ?> </th> + <th> <?= t("Default language") ?> </th> + </tr> + <? $i = 0 ?> + <? foreach ($available_locales as $code => $display_name): ?> + <? if ($i == (count($available_locales)/2)): ?> + <table> + <tr> + <th> <?= t("Installed") ?> </th> + <th> <?= t("Language") ?> </th> + <th> <?= t("Default language") ?> </th> + </tr> + <? endif ?> - <h2> <?= t("Download translations") ?> </h2> - <a href="<?= url::site("admin/maintenance/start/gallery_task::update_l10n?csrf=$csrf") ?>" - class="gDialogLink"> - <?= t("Get updates") ?> - </a> + <tr class="<?= (isset($installed_locales[$code])) ? "installed" : "" ?><?= ($default_locale == $code) ? " default" : "" ?>"> + <td> <?= form::checkbox("installed_locales[]", $code, isset($installed_locales[$code])) ?> </td> + <td> <?= $display_name ?> </td> + <td> + <?= form::radio("default_locale", $code, ($default_locale == $code), ((isset($installed_locales[$code]))?'':'disabled="disabled"') ) ?> + </td> + </tr> + <? $i++ ?> - <h2> <?= t("Your Own Translations") ?> </h2> + <? endforeach ?> + </table> + <input type="submit" value="<?= t("Update languages")->for_html_attr() ?>" /> + </form> + + <script type="text/javascript"> + var old_default_locale = <?= html::js_string($default_locale) ?>; + + $("input[name='installed_locales[]']").change(function (event) { + if (this.checked) { + $("input[type='radio'][value='" + this.value + "']").enable(); + } else { + if ($("input[type='radio'][value='" + this.value + "']").selected()) { // if you deselect your default language, switch to some other installed language + $("input[type='radio'][value='" + old_default_locale + "']").attr("checked", "checked"); + } + $("input[type='radio'][value='" + this.value + "']").attr("disabled", "disabled"); + } + }); + + $("#gLanguagesForm").ajaxForm({ + dataType: "json", + success: function(data) { + if (data.result == "success") { + el = $('<a href="' + <?= html::js_string(url::site("admin/maintenance/start/gallery_task::update_l10n?csrf=$csrf")) ?> + '"></a>'); // this is a little hack to trigger the update_l10n task in a dialog + el.gallery_dialog(); + el.trigger('click'); + } + } + }); + </script> +</div> + +<div id="gTranslations"> + <h1> <?= t("Translations") ?> </h1> + <p> + <?= t("Create your own translations and share them with the rest of the Gallery community.") ?> + </p> + + <h3><?= t("Translating Gallery") ?></h3> + + <div class="gBlock"> + <a href="http://codex.gallery2.org/Gallery3:Localization" target="_blank" + class="gDocLink ui-state-default ui-corner-all ui-icon ui-icon-help" + title="<?= t("Localization documentation")->for_html_attr() ?>"> + <?= t("Localization documentation") ?> + </a> + + <p><?= t("<strong>Step 1:</strong> Make sure the target language is installed and up to date (check above).") ?></p> + + <p><?= t("<strong>Step 2:</strong> Make sure you have selected the right target language (currently %default_locale).", + array("default_locale" => locales::display_name())) ?></p> + + <p><?= t("<strong>Step 3:</strong> Start the translation mode and the translation interface will appear at the bottom of each Gallery page.") ?></p> + + <a href="<?= url::site("l10n_client/toggle_l10n_mode?csrf=".access::csrf_token()) ?>" + class="gButtonLink ui-state-default ui-corner-all ui-icon-left"> + <span class="ui-icon ui-icon-power"></span> + <? if (Session::instance()->get("l10n_mode", false)): ?> + <?= t("Stop translation mode") ?> + <? else: ?> + <?= t("Start translation mode") ?> + <? endif ?> + </a> +</div> + +<h3>Sharing your translations</h3> <?= $share_translations_form ?> </div> diff --git a/modules/gallery/views/admin_maintenance.html.php b/modules/gallery/views/admin_maintenance.html.php index 450eb754..ce693d73 100644 --- a/modules/gallery/views/admin_maintenance.html.php +++ b/modules/gallery/views/admin_maintenance.html.php @@ -19,9 +19,10 @@ <?= t("Action") ?> </th> </tr> + <? $i = 0; ?> <? foreach ($task_definitions as $task): ?> - <tr class="<?= log::severity_class($task->severity) ?>"> - <td> + <tr class="<?= ($i % 2 == 0) ? "gOddRow" : "gEvenRow" ?> <?= log::severity_class($task->severity) ?>"> + <td class="<?= log::severity_class($task->severity) ?>"> <?= $task->name ?> </td> <td> @@ -34,6 +35,7 @@ </a> </td> </tr> + <? $i++ ?> <? endforeach ?> </table> </div> @@ -41,10 +43,6 @@ <? if ($running_tasks->count()): ?> <div id="gRunningTasks"> <h2> <?= t("Running Tasks") ?> </h2> - <a href="<?= url::site("admin/maintenance/cancel_running_tasks?csrf=$csrf") ?>" - class="gButtonLink ui-icon-left ui-state-default ui-corner-all right"> - <?= t("cancel all") ?></a> - <table> <tr> <th> @@ -64,11 +62,15 @@ </th> <th> <?= t("Action") ?> + <a href="<?= url::site("admin/maintenance/cancel_running_tasks?csrf=$csrf") ?>" + class="gButtonLink ui-icon-left ui-state-default ui-corner-all right"> + <?= t("cancel all") ?></a> </th> </tr> + <? $i = 0; ?> <? foreach ($running_tasks as $task): ?> - <tr class="<?= $task->state == "stalled" ? "gWarning" : "" ?>"> - <td> + <tr class="<?= ($i % 2 == 0) ? "gOddRow" : "gEvenRow" ?> <?= $task->state == "stalled" ? "gWarning" : "" ?>"> + <td class="<?= $task->state == "stalled" ? "gWarning" : "" ?>"> <?= gallery::date_time($task->updated) ?> </td> <td> @@ -90,7 +92,7 @@ <?= $task->status ?> </td> <td> - <?= p::clean($task->owner()->name) ?> + <?= html::clean($task->owner()->name) ?> </td> <td> <? if ($task->state == "stalled"): ?> @@ -105,6 +107,7 @@ </a> </td> </tr> + <? $i++ ?> <? endforeach ?> </table> </div> @@ -112,10 +115,6 @@ <? if ($finished_tasks->count()): ?> <div id="gFinishedTasks"> - <a href="<?= url::site("admin/maintenance/remove_finished_tasks?csrf=$csrf") ?>" - class="gButtonLink ui-icon-left ui-state-default ui-corner-all right"> - <span class="ui-icon ui-icon-trash"></span><?= t("remove all finished") ?></a> - <h2> <?= t("Finished Tasks") ?> </h2> <table> <tr> @@ -136,11 +135,15 @@ </th> <th> <?= t("Action") ?> + <a href="<?= url::site("admin/maintenance/remove_finished_tasks?csrf=$csrf") ?>" + class="gButtonLink ui-icon-left ui-state-default ui-corner-all right"> + <span class="ui-icon ui-icon-trash"></span><?= t("remove all finished") ?></a> </th> </tr> + <? $i = 0; ?> <? foreach ($finished_tasks as $task): ?> - <tr class="<?= $task->state == "success" ? "gSuccess" : "gError" ?>"> - <td> + <tr class="<?= ($i % 2 == 0) ? "gOddRow" : "gEvenRow" ?> <?= $task->state == "success" ? "gSuccess" : "gError" ?>"> + <td class="<?= $task->state == "success" ? "gSuccess" : "gError" ?>"> <?= gallery::date_time($task->updated) ?> </td> <td> @@ -159,7 +162,7 @@ <?= $task->status ?> </td> <td> - <?= $task->owner()->name ?> + <?= html::clean($task->owner()->name) ?> </td> <td> <? if ($task->done): ?> @@ -183,6 +186,7 @@ </td> </tr> <? endforeach ?> + <? $i++ ?> </table> </div> <? endif ?> diff --git a/modules/gallery/views/admin_maintenance_show_log.html.php b/modules/gallery/views/admin_maintenance_show_log.html.php index 9d850986..8ea1beb6 100644 --- a/modules/gallery/views/admin_maintenance_show_log.html.php +++ b/modules/gallery/views/admin_maintenance_show_log.html.php @@ -12,7 +12,7 @@ appendTo('body').submit().remove(); <div id="gTaskLogDialog"> <h1> <?= $task->name ?> </h1> <div class="gTaskLog"> - <pre><?= p::purify($task->get_log()) ?></pre> + <pre><?= html::purify($task->get_log()) ?></pre> </div> <button id="gCloseButton" class="ui-state-default ui-corner-all" onclick="dismiss()"><?= t("Close") ?></button> <button id="gSaveButton" class="ui-state-default ui-corner-all" onclick="download()"><?= t("Save") ?></button> diff --git a/modules/gallery/views/admin_maintenance_task.html.php b/modules/gallery/views/admin_maintenance_task.html.php index 5c2c03a1..ddd5bd17 100644 --- a/modules/gallery/views/admin_maintenance_task.html.php +++ b/modules/gallery/views/admin_maintenance_task.html.php @@ -1,11 +1,40 @@ <?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 = parseInt($(".gProgressBar div").css("width").replace("%", "")); + if (target_value > current_value) { + // speed up + delta = Math.min(delta + 0.04, 3); + } else { + // slow down + delta = Math.max(delta - 0.05, 1); + } + + if (target_value == 100) { + $(".gProgressBar").progressbar("value", 100); + } else if (current_value != target_value || delta != 1) { + var new_value = Math.min(current_value + delta, target_value); + $(".gProgressBar").progressbar("value", new_value); + animation = setTimeout(function() { animate_progress_bar(target_value); }, 100); + } else { + animation = null; + delta = 1; + } + $.fn.gallery_hover_init(); + } + update = function() { $.ajax({ - url: "<?= url::site("admin/maintenance/run/$task->id?csrf=$csrf") ?>", + url: <?= html::js_string(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(); @@ -28,7 +57,7 @@ <div id="gStatus"> <?= t("Starting up...") ?> </div> - <div> + <div class="txtright"> <button id="gPauseButton" class="ui-state-default ui-corner-all" onclick="dismiss()"><?= t("Pause") ?></button> <button id="gDoneButton" class="ui-state-default ui-corner-all" style="display: none" onclick="dismiss()"><?= t("Close") ?></button> </div> diff --git a/modules/gallery/views/admin_modules.html.php b/modules/gallery/views/admin_modules.html.php index 3fddd6cd..9cf03cb3 100644 --- a/modules/gallery/views/admin_modules.html.php +++ b/modules/gallery/views/admin_modules.html.php @@ -16,7 +16,7 @@ </tr> <? $i = 0 ?> <? foreach ($available as $module_name => $module_info): ?> - <tr class="<?= ($i % 2 == 0) ? "gEvenRow" : "gOddRow" ?>"> + <tr class="<?= ($i % 2 == 0) ? "gOddRow" : "gEvenRow" ?>"> <? $data = array("name" => $module_name); ?> <? if ($module_info->locked) $data["disabled"] = 1; ?> <td> <?= form::checkbox($data, '1', module::is_active($module_name)) ?> </td> @@ -27,6 +27,6 @@ <? $i++ ?> <? endforeach ?> </table> - <input type="submit" value="<?= t("Update") ?>"/> + <input type="submit" value="<?= t("Update")->for_html_attr() ?>"/> </form> </div> diff --git a/modules/gallery/views/admin_themes.html.php b/modules/gallery/views/admin_themes.html.php index dc13a6a0..0aac4717 100644 --- a/modules/gallery/views/admin_themes.html.php +++ b/modules/gallery/views/admin_themes.html.php @@ -16,7 +16,7 @@ <h2> <?= t("Gallery theme") ?> </h2> <div class="gBlock gSelected"> <img src="<?= url::file("themes/{$site}/thumbnail.png") ?>" - alt="<?= $themes[$site]->name ?>" /> + alt="<?= html::clean_attribute($themes[$site]->name) ?>" /> <h3> <?= $themes[$site]->name ?> </h3> <p> <?= $themes[$site]->description ?> @@ -30,9 +30,9 @@ <? if (!$info->site) continue ?> <? if ($id == $site) continue ?> <div class="gBlock"> - <a href="<?= url::site("admin/themes/preview/site/$id") ?>" class="gDialogLink" title="<?= t("Theme Preview: %theme_name", array("theme_name" => $info->name)) ?>"> + <a href="<?= url::site("admin/themes/preview/site/$id") ?>" class="gDialogLink" title="<?= t("Theme Preview: %theme_name", array("theme_name" => $info->name))->for_html_attr() ?>"> <img src="<?= url::file("themes/{$id}/thumbnail.png") ?>" - alt="<?= $info->name ?>" /> + alt="<?= html::clean_attribute($info->name) ?>" /> <h3> <?= $info->name ?> </h3> <p> <?= $info->description ?> @@ -54,7 +54,7 @@ <h2> <?= t("Admin theme") ?> </h2> <div class="gBlock gSelected"> <img src="<?= url::file("themes/{$admin}/thumbnail.png") ?>" - alt="<?= $themes[$admin]->name ?>" /> + alt="<?= html::clean_attribute($themes[$admin]->name) ?>" /> <h3> <?= $themes[$admin]->name ?> </h3> <p> <?= $themes[$admin]->description ?> @@ -68,9 +68,9 @@ <? if (!$info->admin) continue ?> <? if ($id == $admin) continue ?> <div class="gBlock"> - <a href="<?= url::site("admin/themes/preview/admin/$id") ?>" class="gDialogLink" title="<?= t("Theme Preview: %theme_name", array("theme_name" => $info->name)) ?>"> + <a href="<?= url::site("admin/themes/preview/admin/$id") ?>" class="gDialogLink" title="<?= t("Theme Preview: %theme_name", array("theme_name" => $info->name))->for_html_attr() ?>"> <img src="<?= url::file("themes/{$id}/thumbnail.png") ?>" - alt="<?= $info->name ?>" /> + alt="<?= html::clean_attribute($info->name) ?>" /> <h3> <?= $info->name ?> </h3> <p> <?= $info->description ?> diff --git a/modules/gallery/views/after_install.html.php b/modules/gallery/views/after_install.html.php deleted file mode 100644 index d6ba8e7c..00000000 --- a/modules/gallery/views/after_install.html.php +++ /dev/null @@ -1,29 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access.") ?> -<h1 style="display: none"> - <?= t("Welcome to Gallery 3!") ?> -</h1> - -<p> - <?= t("Congratulations on choosing Gallery to host your photos. We're confident that you're going to have a great experience.") ?> -</p> - -<p> - <?= t("You're logged in to the <b>%user_name</b> account. The very first thing you should do is to change your password to something that you'll remember.", array("user_name" => p::clean($user->name))) ?> -</p> - -<p> - <a href="<?= url::site("form/edit/users/{$user->id}") ?>" - title="<?= t("Edit Your Profile") ?>" - id="gAfterInstallChangePasswordLink" class="gButtonLink ui-state-default ui-corners-all"><?= t("Change Password Now") ?></a> - <script> - $("#gAfterInstallChangePasswordLink").bind("click", handleDialogEvent); - </script> -</p> - -<p> - <?= t("Want to learn more? The <a href=\"%url\">Gallery website</a> has news and information about Gallery Project and community.", array("url" => "http://gallery.menalto.com")) ?> -</p> - -<p> - <?= t("Having problems? There's lots of information in our <a href=\"%codex_url\">documentation site</a> or you can <a href=\"%forum_url\">ask for help in the forums!</a>", array("codex_url" => "http://codex.gallery2.org/Main_Page", "forum_url" => "http://gallery.menalto.com/forum")) ?> -</ul> diff --git a/modules/gallery/views/after_install_loader.html.php b/modules/gallery/views/after_install_loader.html.php deleted file mode 100644 index baf91eed..00000000 --- a/modules/gallery/views/after_install_loader.html.php +++ /dev/null @@ -1,7 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access.") ?> -<span id="gAfterInstall" - title="<?= t("Welcome to Gallery 3") ?>" - href="<?= url::site("after_install") ?>"/> -<script type="text/javascript"> - $(document).ready(function(){openDialog($("#gAfterInstall"));}); -</script> diff --git a/modules/gallery/views/form.html.php b/modules/gallery/views/form.html.php index ec2a56a9..730d77cb 100644 --- a/modules/gallery/views/form.html.php +++ b/modules/gallery/views/form.html.php @@ -40,6 +40,8 @@ if (!function_exists("DrawForm")) { print "$prefix {$hidden->render()}\n"; } print "$prefix</fieldset>\n"; + } else if ($input->type == 'script') { + print $input->render(); } else { if ($input->error_messages()) { print "$prefix<li class=\"gError\">\n"; diff --git a/modules/gallery/views/l10n_client.html.php b/modules/gallery/views/l10n_client.html.php index c0cbbfa2..b0f424be 100644 --- a/modules/gallery/views/l10n_client.html.php +++ b/modules/gallery/views/l10n_client.html.php @@ -1,7 +1,11 @@ <?php defined("SYSPATH") or die("No direct script access.") ?> <div id="l10n-client" class="hidden"> <div class="labels"> - <span id="l10n-client-toggler">X</span> + <span id="l10n-client-toggler"> + <a id="gMinimizeL10n">_</a> + <a id="gCloseL10n" title="<?= t("Stop the translation mode")->for_html_attr() ?>" + href="<?= html::clean_attribute(url::site("l10n_client/toggle_l10n_mode?csrf=".access::csrf_token())) ?>">X</a> + </span> <div class="label strings"><h2><?= t("Page Text") ?> <? if (!Input::instance()->get('show_all_l10n_messages')): ?> <a style="background-color:#fff" href="<?= url::site("admin/languages?show_all_l10n_messages=1") ?>"><?= t("(Show All)") ?></a> @@ -9,7 +13,7 @@ </h2></div> <div class="label source"><h2><?= t("Source") ?></div> <div class="label translation"><h2><?= t("Translation to %language", - array("language" => locale::display_name())) ?></h2></div> + array("language" => locales::display_name())) ?></h2></div> </div> <div id="l10n-client-string-select"> <ul class="string-list"> @@ -62,16 +66,17 @@ (<a href="http://www.unicode.org/cldr/data/charts/supplemental/language_plural_rules.html"><?= t("learn more about plural forms") ?></a>) <?= form::textarea("l10n-edit-plural-translation-other", "", ' rows="2"') ?> </div> - <input type="submit" name="l10n-edit-save" value="<?= t("Save translation") ?>"/> + <input type="submit" name="l10n-edit-save" value="<?= t("Save translation")->for_html_attr() ?>"/> <a href="javascript: Gallery.l10nClient.copySourceText()" class="gButtonLink ui-state-default ui-corner-all"><?= t("Copy source text") ?></a> </form> </div> </div> <script type="text/javascript"> - var MSG_TRANSLATE_TEXT = "<?= t("Translate Text") ?>"; - var MSG_CLOSE_X = "<?= t("X") ?>"; + var MSG_TRANSLATE_TEXT = <?= t("Translate Text")->for_js() ?>; var l10n_client_data = <?= json_encode($string_list) ?>; var plural_forms = <?= json_encode($plural_forms) ?>; + var toggle_l10n_mode_url = <?= html::js_string(url::site("l10n_client/toggle_l10n_mode")) ?>; + var csrf = <?= html::js_string(access::csrf_token()) ?>; </script> </div> diff --git a/modules/gallery/views/move_browse.html.php b/modules/gallery/views/move_browse.html.php index 4f69c0e9..99728ecc 100644 --- a/modules/gallery/views/move_browse.html.php +++ b/modules/gallery/views/move_browse.html.php @@ -42,6 +42,6 @@ <form method="post" action="<?= url::site("move/save/$source->id") ?>"> <?= access::csrf_form_field() ?> <input type="hidden" name="target_id" value="" /> - <input type="submit" id="gMoveButton" value="<?= t("Move") ?>" disabled="disabled"/> + <input type="submit" id="gMoveButton" value="<?= t("Move")->for_html_attr() ?>" disabled="disabled"/> </form> </div> diff --git a/modules/gallery/views/move_tree.html.php b/modules/gallery/views/move_tree.html.php index 5f70cf67..e629e1bb 100644 --- a/modules/gallery/views/move_tree.html.php +++ b/modules/gallery/views/move_tree.html.php @@ -1,18 +1,18 @@ <?php defined("SYSPATH") or die("No direct script access.") ?> <?= $parent->thumb_img(array(), 25); ?> -<? if (!access::can("edit", $parent) || $source->is_descendant($parent)): ?> -<a href="javascript:load_tree('<?= $parent->id ?>',1)"> <?= p::clean($parent->title) ?> <?= t("(locked)") ?> </a> +<? if (!access::can("edit", $parent) || $source->contains($parent)): ?> +<a href="javascript:load_tree('<?= $parent->id ?>',1)"> <?= html::clean($parent->title) ?> <?= t("(locked)") ?> </a> <? else: ?> -<a href="javascript:load_tree('<?= $parent->id ?>',0)"> <?= p::clean($parent->title) ?></a> +<a href="javascript:load_tree('<?= $parent->id ?>',0)"> <?= html::clean($parent->title) ?></a> <? endif ?> <ul id="tree_<?= $parent->id ?>"> <? foreach ($children as $child): ?> <li id="node_<?= $child->id ?>" class="node"> <?= $child->thumb_img(array(), 25); ?> - <? if (!access::can("edit", $child) || $source->is_descendant($child)): ?> - <a href="javascript:load_tree('<?= $child->id ?>',1)"> <?= p::clean($child->title) ?> <?= t("(locked)") ?></a> + <? if (!access::can("edit", $child) || $source->contains($child)): ?> + <a href="javascript:load_tree('<?= $child->id ?>',1)"> <?= html::clean($child->title) ?> <?= t("(locked)") ?></a> <? else: ?> - <a href="javascript:load_tree('<?= $child->id ?>',0)"> <?= p::clean($child->title) ?> </a> + <a href="javascript:load_tree('<?= $child->id ?>',0)"> <?= html::clean($child->title) ?> </a> <? endif ?> </li> <? endforeach ?> diff --git a/modules/gallery/views/movieplayer.html.php b/modules/gallery/views/movieplayer.html.php index e8cabd31..e9783eb8 100644 --- a/modules/gallery/views/movieplayer.html.php +++ b/modules/gallery/views/movieplayer.html.php @@ -1,15 +1,22 @@ <?php defined("SYSPATH") or die("No direct script access.") ?> <?= html::anchor($item->file_url(true), "", $attrs) ?> <script> - flowplayer("<?= $attrs["id"] ?>", "<?= url::abs_file("lib/flowplayer.swf") ?>", { - plugins: { - h264streaming: { - url: "<?= url::abs_file("lib/flowplayer.h264streaming.swf") ?>" - }, - controls: { - autoHide: 'always', - hideDelay: 2000 + flowplayer( + "<?= $attrs["id"] ?>", + { + src: "<?= url::abs_file("lib/flowplayer.swf") ?>", + wmode: "transparent" + }, + { + plugins: { + h264streaming: { + url: "<?= url::abs_file("lib/flowplayer.h264streaming.swf") ?>" + }, + controls: { + autoHide: 'always', + hideDelay: 2000 + } } } - }) + ) </script> diff --git a/modules/gallery/views/permissions_browse.html.php b/modules/gallery/views/permissions_browse.html.php index 888a27f7..519734d6 100644 --- a/modules/gallery/views/permissions_browse.html.php +++ b/modules/gallery/views/permissions_browse.html.php @@ -5,8 +5,9 @@ $.ajax({ url: form_url.replace("__ITEM__", id), success: function(data) { - $("div.form").slideUp(); - $("div#edit-" + id).html(data).slideDown(); + $("#gEditPermissionForm").html(data); + $(".active").removeClass("active"); + $("#item-" + id).addClass("active"); } }); } @@ -18,7 +19,7 @@ url: action_url.replace("__CMD__", cmd).replace("__GROUP__", group_id). replace("__PERM__", perm_id).replace("__ITEM__", item_id), success: function(data) { - $("div#edit-" + item_id).load(form_url.replace("__ITEM__", item_id)); + $("#gEditPermissionForm").load(form_url.replace("__ITEM__", item_id)); } }); } @@ -27,30 +28,35 @@ <? if (!$htaccess_works): ?> <ul id="gMessage"> <li class="gError"> - <?= t("Oh no! Your server needs a configuration change in order for you to hide photos! Ask your server administrator to enable <a %mod_rewrite_attrs>mod_rewrite</a> and set <a %apache_attrs><i>AllowOverride FileInfo Options</i></a> to fix this.", array("mod_rewrite_attrs" => "href=\"http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html\" target=\"_blank\"", "apache_attrs" => "href=\"http://httpd.apache.org/docs/2.0/mod/core.html#allowoverride\" target=\"_blank\"")) ?> + <?= t("Oh no! Your server needs a configuration change in order for you to hide photos! Ask your server administrator to enable <a %mod_rewrite_attrs>mod_rewrite</a> and set <a %apache_attrs><i>AllowOverride FileInfo Options</i></a> to fix this.", + array("mod_rewrite_attrs" => html::mark_clean('href="http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html" target="_blank"'), + "apache_attrs" => html::mark_clean('href="http://httpd.apache.org/docs/2.0/mod/core.html#allowoverride" target="_blank"'))) ?> </li> </ul> <? endif ?> - <ul> + + <p><?= t("Edit permissions for album:") ?></p> + + <ul class="gBreadcrumbs"> <? foreach ($parents as $parent): ?> - <li> + <li id="item-<?= $parent->id ?>"> + <? if (access::can("edit", $parent)): ?> <a href="javascript:show(<?= $parent->id ?>)"> - <?= p::clean($parent->title) ?> + <?= html::purify($parent->title) ?> + </a> + <? else: ?> + <?= html::purify($parent->title) ?> + <? endif ?> + </li> + <? endforeach ?> + <li class="active" id="item-<?= $item->id ?>"> + <a href="javascript:show(<?= $item->id ?>)"> + <?= html::purify($item->title) ?> </a> - <div class="form" id="edit-<?= $parent->id ?>"></div> - <ul> - <? endforeach ?> - <li> - <a href="javascript:show(<?= $item->id ?>)"> - <?= p::purify($item->title) ?> - </a> - <div class="form" id="edit-<?= $item->id ?>"> - <?= $form ?> - </div> - </li> - <? foreach ($parents as $parent): ?> - </ul> </li> </ul> - <? endforeach ?> + + <div id="gEditPermissionForm"> + <?= $form ?> + </div> </div> diff --git a/modules/gallery/views/permissions_form.html.php b/modules/gallery/views/permissions_form.html.php index 0f60070a..a0bb35f2 100644 --- a/modules/gallery/views/permissions_form.html.php +++ b/modules/gallery/views/permissions_form.html.php @@ -6,7 +6,7 @@ <tr> <th> </th> <? foreach ($groups as $group): ?> - <th> <?= p::clean($group->name) ?> </th> + <th> <?= html::clean($group->name) ?> </th> <? endforeach ?> </tr> @@ -20,33 +20,33 @@ <? if ($lock): ?> <td class="gDenied"> - <img src="<?= url::file('themes/default/images/ico-denied.png') ?>" title="<?= t('denied and locked through parent album') ?>" alt="<?= t('denied icon') ?>" /> - <a href="javascript:show(<?= $lock->id ?>)" title="<?= t('click to go to parent album') ?>"> - <img src="<?= url::file('themes/default/images/ico-lock.png') ?>" alt="<?= t('locked icon') ?>" /> + <img src="<?= url::file('themes/default/images/ico-denied.png') ?>" title="<?= t('denied and locked through parent album')->for_html_attr() ?>" alt="<?= t('denied icon')->for_html_attr() ?>" /> + <a href="javascript:show(<?= $lock->id ?>)" title="<?= t('click to go to parent album')->for_html_attr() ?>"> + <img src="<?= url::file('themes/default/images/ico-lock.png') ?>" alt="<?= t('locked icon')->for_html_attr() ?>" /> </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 ?>)" - title="<?= t('allowed through parent album, click to allow explicitly') ?>"> - <img src="<?= url::file('themes/default/images/ico-success-pale.png') ?>" alt="<?= t('passive allowed icon') ?>" /> + title="<?= t('allowed through parent album, click to allow explicitly')->for_html_attr() ?>"> + <img src="<?= url::file('themes/default/images/ico-success-pale.png') ?>" alt="<?= t('passive allowed icon')->for_html_attr() ?>" /> </a> <a href="javascript:set('deny',<?= $group->id ?>,<?= $permission->id ?>,<?= $item->id ?>)" - title="<?= t('click to deny') ?>"> - <img src="<?= url::file('themes/default/images/ico-denied-gray.png') ?>" alt="<?= t('inactive denied icon') ?>" /> + title="<?= t('click to deny')->for_html_attr() ?>"> + <img src="<?= url::file('themes/default/images/ico-denied-gray.png') ?>" alt="<?= t('inactive denied icon')->for_html_attr() ?>" /> </a> </td> <? else: ?> <td class="gDenied"> <a href="javascript:set('allow',<?= $group->id ?>,<?= $permission->id ?>,<?= $item->id ?>)" - title="<?= t('click to allow') ?>"> - <img src="<?= url::file('themes/default/images/ico-success-gray.png') ?>" alt="<?= t('inactive allowed icon') ?>" /> + title="<?= t('click to allow')->for_html_attr() ?>"> + <img src="<?= url::file('themes/default/images/ico-success-gray.png') ?>" alt="<?= t('inactive allowed icon')->for_html_attr() ?>" /> </a> <a href="javascript:set('deny',<?= $group->id ?>,<?= $permission->id ?>,<?= $item->id ?>)" - title="<?= t('denied through parent album, click to deny explicitly') ?>"> - <img src="<?= url::file('themes/default/images/ico-denied-pale.png') ?>" alt="<?= t('passive denied icon') ?>" /> + title="<?= t('denied through parent album, click to deny explicitly')->for_html_attr() ?>"> + <img src="<?= url::file('themes/default/images/ico-denied-pale.png') ?>" alt="<?= t('passive denied icon')->for_html_attr() ?>" /> </a> </td> <? endif ?> @@ -54,31 +54,31 @@ <? elseif ($intent === access::DENY): ?> <td class="gDenied"> <a href="javascript:set('allow',<?= $group->id ?>,<?= $permission->id ?>,<?= $item->id ?>)" - title="<?= t('click to allow') ?>"> - <img src="<?= url::file('themes/default/images/ico-success-gray.png') ?>" alt="<?= t('inactive allowed icon') ?>" /> + title="<?= t('click to allow')->for_html_attr() ?>"> + <img src="<?= url::file('themes/default/images/ico-success-gray.png') ?>" alt="<?= t('inactive allowed icon')->for_html_attr() ?>" /> </a> <? if ($item->id == 1): ?> - <img src="<?= url::file('themes/default/images/ico-denied.png') ?>" alt="<?= t('denied icon') ?>" title="<?= t('denied') ?>"/> + <img src="<?= url::file('themes/default/images/ico-denied.png') ?>" alt="<?= t('denied icon')->for_html_attr() ?>" title="<?= t('denied')->for_html_attr() ?>"/> <? else: ?> <a href="javascript:set('reset',<?= $group->id ?>,<?= $permission->id ?>,<?= $item->id ?>)" - title="<?= t('denied, click to reset') ?>"> - <img src="<?= url::file('themes/default/images/ico-denied.png') ?>" alt="<?= t('denied icon') ?>" /> + title="<?= t('denied, click to reset')->for_html_attr() ?>"> + <img src="<?= url::file('themes/default/images/ico-denied.png') ?>" alt="<?= t('denied icon')->for_html_attr() ?>" /> </a> <? endif ?> </td> <? elseif ($intent === access::ALLOW): ?> <td class="gAllowed"> <? if ($item->id == 1): ?> - <img src="<?= url::file('themes/default/images/ico-success.png') ?>" title="<?= t("allowed") ?>" alt="<?= t('allowed icon') ?>" /> + <img src="<?= url::file('themes/default/images/ico-success.png') ?>" title="<?= t("allowed")->for_html_attr() ?>" alt="<?= t('allowed icon')->for_html_attr() ?>" /> <? else: ?> <a href="javascript:set('reset',<?= $group->id ?>,<?= $permission->id ?>,<?= $item->id ?>)" - title="<?= t('allowed, click to reset') ?>"> - <img src="<?= url::file('themes/default/images/ico-success.png') ?>" alt="<?= t('allowed icon') ?>" /> + title="<?= t('allowed, click to reset')->for_html_attr() ?>"> + <img src="<?= url::file('themes/default/images/ico-success.png') ?>" alt="<?= t('allowed icon')->for_html_attr() ?>" /> </a> <? endif ?> <a href="javascript:set('deny',<?= $group->id ?>,<?= $permission->id ?>,<?= $item->id ?>)" - title="<?= t('click to deny') ?>"> - <img src="<?= url::file('themes/default/images/ico-denied-gray.png') ?>" alt="<?= t('inactive denied icon') ?>" /> + title="<?= t('click to deny')->for_html_attr() ?>"> + <img src="<?= url::file('themes/default/images/ico-denied-gray.png') ?>" alt="<?= t('inactive denied icon')->for_html_attr() ?>" /> </a> </td> <? endif ?> diff --git a/modules/gallery/views/quick_pane.html.php b/modules/gallery/views/quick_pane.html.php deleted file mode 100644 index eabf4a67..00000000 --- a/modules/gallery/views/quick_pane.html.php +++ /dev/null @@ -1,26 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access.") ?> -<? foreach ($button_list->main as $button): ?> -<a class="<?= $button->class ?> ui-corner-all ui-state-default" href="<?= $button->href ?>" - title="<?= $button->title ?>"> - <span class="ui-icon <?= $button->icon ?>"> - <?= $button->title ?> - </span> -</a> -<? endforeach ?> - -<? if (!empty($button_list->additional)): ?> -<a class="gButtonLink ui-corner-all ui-state-default options" href="#" title="<?= t("additional options") ?>"> - <span class="ui-icon ui-icon-triangle-1-s"> - <?= t("Additional options") ?> - </span> -</a> - -<ul id="gQuickPaneOptions" style="display: none"> - <? foreach ($button_list->additional as $button): ?> - <li><a class="<?= $button->class ?>" href="<?= $button->href ?>" - title="<?= $button->title ?>"> - <?= $button->title ?> - </a></li> - <? endforeach ?> -</ul> -<? endif ?> diff --git a/modules/gallery/views/simple_uploader.html.php b/modules/gallery/views/simple_uploader.html.php index 38ac518c..7f8a96df 100644 --- a/modules/gallery/views/simple_uploader.html.php +++ b/modules/gallery/views/simple_uploader.html.php @@ -6,7 +6,7 @@ <!-- hack to set the title for the dialog --> <form id="gAddPhotosForm" action="<?= url::site("simple_uploader/finish?csrf=$csrf") ?>"> <fieldset> - <legend> <?= t("Add photos to %album_title", array("album_title" => p::purify($item->title))) ?> </legend> + <legend> <?= t("Add photos to %album_title", array("album_title" => html::purify($item->title))) ?> </legend> </fieldset> </form> @@ -26,16 +26,16 @@ </p> <ul class="gBreadcrumbs"> <? foreach ($item->parents() as $parent): ?> - <li> <?= p::clean($parent->title) ?> </li> + <li> <?= html::clean($parent->title) ?> </li> <? endforeach ?> - <li class="active"> <?= p::purify($item->title) ?> </li> + <li class="active"> <?= html::purify($item->title) ?> </li> </ul> <p> <span id="gUploadQueueInfo"> <?= t("Upload Queue") ?> </span> - <a id="gUploadCancel" title="<?= t("Cancel all the pending uploads") ?>" onclick="swfu.cancelQueue();"><?= t("cancel") ?></a> + <a id="gUploadCancel" title="<?= t("Cancel all the pending uploads")->for_html_attr() ?>" onclick="swfu.cancelQueue();"><?= t("cancel") ?></a> </p> <div id="gAddPhotosCanvas" style="text-align: center;"> <div id="gAddPhotosQueue"></div> @@ -82,27 +82,26 @@ <script type="text/javascript"> var swfu = new SWFUpload({ - flash_url: "<?= url::file("lib/swfupload/swfupload.swf") ?>", - upload_url: "<?= url::site("simple_uploader/add_photo/$item->id") ?>", - post_params: { - "g3sid": "<?= Session::instance()->id() ?>", - "user_agent": "<?= Input::instance()->server("HTTP_USER_AGENT") ?>", - "csrf": "<?= $csrf ?>" - }, - file_size_limit: "<?= ini_get("upload_max_filesize") ? num::convert_to_bytes(ini_get("upload_max_filesize"))."B" : "100MB" ?>", + flash_url: <?= html::js_string(url::file("lib/swfupload/swfupload.swf")) ?>, + upload_url: <?= html::js_string(url::site("simple_uploader/add_photo/$item->id")) ?>, + post_params: <?= json_encode(array( + "g3sid" => Session::instance()->id(), + "user_agent" => Input::instance()->server("HTTP_USER_AGENT"), + "csrf" => $csrf)) ?>, + file_size_limit: <?= html::js_string(ini_get("upload_max_filesize") ? num::convert_to_bytes(ini_get("upload_max_filesize"))."B" : "100MB") ?>, file_types: "*.gif;*.jpg;*.jpeg;*.png;*.flv;*.mp4;*.GIF;*.JPG;*.JPEG;*.PNG;*.FLV;*.MP4", - file_types_description: "<?= t("Photos and Movies") ?>", + file_types_description: <?= t("Photos and Movies")->for_js() ?>, file_upload_limit: 1000, file_queue_limit: 0, custom_settings: { }, debug: false, // Button settings - button_image_url: "<?= url::file("themes/default/images/select-photos-backg.png") ?>", + button_image_url: <?= html::js_string(url::file("themes/default/images/select-photos-backg.png")) ?>, button_width: "202", button_height: "45", button_placeholder_id: "gChooseFilesButtonPlaceholder", - button_text: '<span class="swfUploadFont"><?= t("Select photos...") ?></span>', + button_text: <?= json_encode('<span class="swfUploadFont">' . t("Select photos...") . '</span>') ?>, button_text_style: ".swfUploadFont { color: #2E6E9E; font-size: 16px; font-family: Lucida Grande,Lucida Sans,Arial,sans-serif; font-weight: bold; }", button_text_left_padding: 30, button_text_top_padding: 10, @@ -146,13 +145,13 @@ function file_queued(file) { var fp = new File_Progress(file); fp.title.html(file.name); - fp.set_status("pending", "<?= t("Pending...") ?>"); + fp.set_status("pending", <?= t("Pending...")->for_js() ?>); // @todo add cancel button to call this.cancelUpload(file.id) } function file_queue_error(file, error_code, message) { if (error_code === SWFUpload.QUEUE_ERROR.QUEUE_LIMIT_EXCEEDED) { - alert("<?= t("You have attempted to queue too many files.") ?>"); + alert(<?= t("You have attempted to queue too many files.")->for_js() ?>); return; } @@ -160,20 +159,20 @@ switch (error_code) { case SWFUpload.QUEUE_ERROR.FILE_EXCEEDS_SIZE_LIMIT: fp.title.html(file.name); - fp.set_status("error", "<?= t("<strong>File is too big.</strong> A likely error source is a too low value for <em>upload_max_filesize</em> (%upload_max_filesize) in your <em>php.ini</em>.", array("upload_max_filesize" => ini_get("upload_max_filesize"))) ?>"); + fp.set_status("error", <?= t("<strong>File is too big.</strong> A likely error source is a too low value for <em>upload_max_filesize</em> (%upload_max_filesize) in your <em>php.ini</em>.", array("upload_max_filesize" => ini_get("upload_max_filesize")))->for_js() ?>); break; case SWFUpload.QUEUE_ERROR.ZERO_BYTE_FILE: fp.title.html(file.name); - fp.set_status("error", "<?= t("Cannot upload empty files.") ?>"); + fp.set_status("error", <?= t("Cannot upload empty files.")->for_js() ?>); break; case SWFUpload.QUEUE_ERROR.INVALID_FILETYPE: fp.title.html(file.name); - fp.set_status("error", "<?= t("Invalid file type.") ?>"); + fp.set_status("error", <?= t("Invalid file type.")->for_js() ?>); break; default: if (file !== null) { fp.title.html(file.name); - fp.set_status("error", "<?= t("Unknown error") ?>"); + fp.set_status("error", <?= t("Unknown error")->for_js() ?>); } break; } @@ -194,7 +193,7 @@ // no uploadProgress events are called (limitation in the Linux Flash VM). var fp = new File_Progress(file); fp.title.html(file.name); - fp.set_status("uploading", "<?= t("Uploading...") ?>"); + fp.set_status("uploading", <?= t("Uploading...")->for_js() ?>); $("#gAddPhotosCanvas").scrollTo(fp.box, 1000); return true; // @todo add cancel button to call this.cancelUpload(file.id) @@ -203,7 +202,7 @@ function upload_progress(file, bytes_loaded, bytes_total) { var percent = Math.ceil((bytes_loaded / bytes_total) * 100); var fp = new File_Progress(file); - fp.set_status("uploading", "<?= t("Uploading...") ?>"); + fp.set_status("uploading", <?= t("Uploading...")->for_js() ?>); fp.progress_bar.css("visibility", "visible"); fp.progress_bar.progressbar("value", percent); } @@ -211,42 +210,42 @@ function upload_success(file, serverData) { var fp = new File_Progress(file); fp.progress_bar.progressbar("value", 100); - fp.set_status("complete", "<?= t("Complete.") ?>"); + fp.set_status("complete", <?= t("Complete.")->for_js() ?>); } function upload_error(file, error_code, message) { var fp = new File_Progress(file); switch (error_code) { case SWFUpload.UPLOAD_ERROR.HTTP_ERROR: - fp.set_status("error", "<?= t("Upload error: ") ?>" + message); + fp.set_status("error", <?= t("Upload error: bad image file")->for_js() ?>); break; case SWFUpload.UPLOAD_ERROR.UPLOAD_FAILED: - fp.set_status("error", "<?= t("Upload failed") ?>"); + fp.set_status("error", <?= t("Upload failed")->for_js() ?>); break; case SWFUpload.UPLOAD_ERROR.IO_ERROR: - fp.set_status("error", "<?= t("Server error") ?>"); + fp.set_status("error", <?= t("Server error")->for_js() ?>); break; case SWFUpload.UPLOAD_ERROR.SECURITY_ERROR: - fp.set_status("error", "<?= t("Security error") ?>"); + fp.set_status("error", <?= t("Security error")->for_js() ?>); break; case SWFUpload.UPLOAD_ERROR.UPLOAD_LIMIT_EXCEEDED: - fp.set_status("error", "<?= t("Upload limit exceeded") ?>"); + fp.set_status("error", <?= t("Upload limit exceeded")->for_js() ?>); break; case SWFUpload.UPLOAD_ERROR.FILE_VALIDATION_FAILED: - fp.set_status("error", "<?= t("Failed validation. File skipped") ?>"); + fp.set_status("error", <?= t("Failed validation. File skipped")->for_js() ?>); break; case SWFUpload.UPLOAD_ERROR.FILE_CANCELLED: // If there aren't any files left (they were all cancelled) disable the cancel button if (this.getStats().files_queued === 0) { $("#gUploadCancel").hide(); } - fp.set_status("error", "<?= t("Cancelled") ?>"); + fp.set_status("error", <?= t("Cancelled")->for_js() ?>); break; case SWFUpload.UPLOAD_ERROR.UPLOAD_STOPPED: - fp.set_status("error", "<?= t("Stopped") ?>"); + fp.set_status("error", <?= t("Stopped")->for_js() ?>); break; default: - fp.set_status("error", "<?= t("Unknown error: ") ?>" + error_code); + fp.set_status("error", <?= t("Unknown error: ")->for_js() ?> + error_code); break; } } @@ -260,7 +259,7 @@ } function get_completed_status_msg(stats) { - var msg = "<?= t("Upload Queue (completed %completed of %total)", array("completed" => "__COMPLETED__", "total" => "__TOTAL__")) ?>"; + var msg = <?= t("Upload Queue (completed %completed of %total)", array("completed" => "__COMPLETED__", "total" => "__TOTAL__"))->for_js() ?>; msg = msg.replace("__COMPLETED__", stats.successful_uploads); msg = msg.replace("__TOTAL__", stats.files_queued + stats.successful_uploads + stats.upload_errors + stats.upload_cancelled + stats.queue_errors); @@ -269,7 +268,7 @@ // This event comes from the Queue Plugin function queue_complete(num_files_uploaded) { - var status_msg = "<?= t("Uploaded: __COUNT__") ?>"; + var status_msg = <?= t("Uploaded: __COUNT__")->for_js() ?>; $("#gUploadStatus").html(status_msg.replace("__COUNT__", num_files_uploaded)); } </script> diff --git a/modules/gallery/views/upgrader.html.php b/modules/gallery/views/upgrader.html.php index 37578855..5f93c2d5 100644 --- a/modules/gallery/views/upgrader.html.php +++ b/modules/gallery/views/upgrader.html.php @@ -18,7 +18,7 @@ <h1> <?= t("That's it!") ?> </h1> <p> <?= t("Your <a href=\"%url\">Gallery</a> is up to date.", - array("url" => url::site("albums/1"))) ?> + array("url" => html::mark_clean(item::root()->url()))) ?> </p> </div> </div> diff --git a/modules/gallery/views/welcome_message.html.php b/modules/gallery/views/welcome_message.html.php new file mode 100644 index 00000000..5515c3dc --- /dev/null +++ b/modules/gallery/views/welcome_message.html.php @@ -0,0 +1,36 @@ +<?php defined("SYSPATH") or die("No direct script access.") ?> +<div id="gWelcomeMessage"> + <h1 style="display: none"> + <?= t("Welcome to Gallery 3!") ?> + </h1> + + <p> + <h2> + <?= t("Congratulations on choosing Gallery to host your photos. You're going to have a great experience!") ?> + </h2> + </p> + + <p> + <?= t("First things first. You're logged in to the <b>%user_name</b> account. You should change your password to something that you'll remember.", array("user_name" => $user->name)) ?> + </p> + + <p> + <a href="<?= url::site("form/edit/users/{$user->id}") ?>" + title="<?= t("Edit Your Profile")->for_html_attr() ?>" + id="gAfterInstallChangePasswordLink" + class="gButtonLink ui-state-default ui-corners-all"> + <?= t("Change Password Now") ?> + </a> + <script> + $("#gAfterInstallChangePasswordLink").gallery_dialog(); + </script> + </p> + + <p> + <?= t("Want to learn more? The <a href=\"%url\">Gallery website</a> has news and information about the Gallery project and community.", array("url" => "http://gallery.menalto.com")) ?> + </p> + + <p> + <?= t("Having problems? There's lots of information in our <a href=\"%codex_url\">documentation site</a> or you can <a href=\"%forum_url\">ask for help in the forums!</a>", array("codex_url" => "http://codex.gallery2.org/Main_Page", "forum_url" => "http://gallery.menalto.com/forum")) ?> + </p> +</div> diff --git a/modules/gallery/views/welcome_message_loader.html.php b/modules/gallery/views/welcome_message_loader.html.php new file mode 100644 index 00000000..2c6bffca --- /dev/null +++ b/modules/gallery/views/welcome_message_loader.html.php @@ -0,0 +1,7 @@ +<?php defined("SYSPATH") or die("No direct script access.") ?> +<span id="gWelcomeMessageLink" + title="<?= t("Welcome to Gallery 3")->for_html_attr() ?>" + href="<?= url::site("welcome_message") ?>"/> +<script type="text/javascript"> + $(document).ready(function(){$("#gWelcomeMessageLink").gallery_dialog({immediate: true});}); +</script> diff --git a/modules/gallery_unit_test/controllers/gallery_unit_test.php b/modules/gallery_unit_test/controllers/gallery_unit_test.php index 8f3353dc..a5dbcc1f 100644 --- a/modules/gallery_unit_test/controllers/gallery_unit_test.php +++ b/modules/gallery_unit_test/controllers/gallery_unit_test.php @@ -122,6 +122,9 @@ class Gallery_Unit_Test_Controller extends Controller { module::activate($module_name); } + // Trigger late-binding install actions (defined in gallery_event::user_login) + graphics::choose_default_toolkit(); + $filter = count($_SERVER["argv"]) > 2 ? $_SERVER["argv"][2] : null; print new Unit_Test($modules, $filter); } catch (Exception $e) { diff --git a/modules/image_block/helpers/image_block_installer.php b/modules/image_block/helpers/image_block_installer.php deleted file mode 100644 index 7ea6a229..00000000 --- a/modules/image_block/helpers/image_block_installer.php +++ /dev/null @@ -1,24 +0,0 @@ -<?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 image_block_installer { - static function install() { - module::set_version("image_block", 1); - } -} diff --git a/modules/info/helpers/info_installer.php b/modules/info/helpers/info_installer.php deleted file mode 100644 index e3e78b90..00000000 --- a/modules/info/helpers/info_installer.php +++ /dev/null @@ -1,24 +0,0 @@ -<?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 info_installer { - static function install() { - module::set_version("info", 1); - } -} diff --git a/modules/info/helpers/info_theme.php b/modules/info/helpers/info_theme.php index 51378e54..4bf894ad 100644 --- a/modules/info/helpers/info_theme.php +++ b/modules/info/helpers/info_theme.php @@ -38,9 +38,11 @@ class info_theme_Core { if ($item->owner) { $results .= "<li>"; if ($item->owner->url) { - $results .= t("By: %owner_name", array("owner_name" => "<a href=\"{$item->owner->url}\">{$item->owner->full_name}</a>")); + $results .= t("By: <a href=\"%owner_url\">%owner_name</a>", + array("owner_name" => $item->owner->display_name(), + "owner_url" => $item->owner->url)); } else { - $results .= t("By: %owner_name", array("owner_name" => "{$item->owner->full_name}")); + $results .= t("By: %owner_name", array("owner_name" => $item->owner->display_name())); } $results .= "</li>"; } diff --git a/modules/info/views/info_block.html.php b/modules/info/views/info_block.html.php index 9f544376..d8f36984 100644 --- a/modules/info/views/info_block.html.php +++ b/modules/info/views/info_block.html.php @@ -2,18 +2,18 @@ <ul class="gMetadata"> <li> <strong class="caption"><?= t("Title:") ?></strong> - <?= p::purify($item->title) ?> + <?= html::purify($item->title) ?> </li> <? if ($item->description): ?> <li> <strong class="caption"><?= t("Description:") ?></strong> - <?= nl2br(p::purify($item->description)) ?> + <?= nl2br(html::purify($item->description)) ?> </li> <? endif ?> - <? if ($item->id != 1): ?> + <? if (!$item->is_album()): ?> <li> - <strong class="caption"><?= t("Folder name:") ?></strong> - <?= p::clean($item->name) ?> + <strong class="caption"><?= t("File name:") ?></strong> + <?= html::clean($item->name) ?> </li> <? endif ?> <? if ($item->captured): ?> @@ -26,9 +26,9 @@ <li> <strong class="caption"><?= t("Owner:") ?></strong> <? if ($item->owner->url): ?> - <a href="<?= $item->owner->url ?>"><?= p::clean($item->owner->full_name) ?></a> + <a href="<?= $item->owner->url ?>"><?= html::clean($item->owner->display_name()) ?></a> <? else: ?> - <?= p::clean($item->owner->name) ?> + <?= html::clean($item->owner->display_name()) ?> <? endif ?> </li> <? endif ?> diff --git a/modules/notification/controllers/notification.php b/modules/notification/controllers/notification.php index ffb4b46a..d502b9fe 100644 --- a/modules/notification/controllers/notification.php +++ b/modules/notification/controllers/notification.php @@ -26,11 +26,11 @@ class Notification_Controller extends Controller { if (notification::is_watching($item)) { notification::remove_watch($item); - message::success(sprintf(t("You are no longer watching %s"), $item->title)); + message::success(sprintf(t("You are no longer watching %s"), html::purify($item->title))); } else { notification::add_watch($item); - message::success(sprintf(t("You are now watching %s"), $item->title)); + message::success(sprintf(t("You are now watching %s"), html::purify($item->title))); } - url::redirect($item->url(array(), true)); + url::redirect($item->abs_url()); } } diff --git a/modules/notification/helpers/notification.php b/modules/notification/helpers/notification.php index 8ee0c6ba..88d92b16 100644 --- a/modules/notification/helpers/notification.php +++ b/modules/notification/helpers/notification.php @@ -67,35 +67,48 @@ 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") ->where("email IS NOT", null) - ->where("items.left <=", $item->left) - ->where("items.right >", $item->right) + ->where("items.left_ptr <=", $item->left_ptr) + ->where("items.right_ptr >", $item->right_ptr) ->find_all(); $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($old, $new) { + static function send_item_updated($item) { + $subscribers = self::get_subscribers($item); + if (!$subscribers) { + return; + } + $v = new View("item_updated.html"); - $v->old = $old; - $v->new = $new; - $v->subject = $old->is_album() ? - t("Album %title updated", array("title" => $old->title)) : - ($old->is_photo() ? - t("Photo %title updated", array("title" => $old->title)) - : t("Movie %title updated", array("title" => $old->title))); - - self::_notify_subscribers($old, $v->render(), $v->subject); + $v->item = $item; + $v->subject = $item->is_album() ? + t("Album %title updated", array("title" => $item->original("title"))) : + ($item->is_photo() ? + t("Photo %title updated", array("title" => $item->original("title"))) + : t("Movie %title updated", array("title" => $item->original("title")))); + + self::_notify($subscribers, $item, $v->render(), $v->subject); } static function send_item_add($item) { + $subscribers = self::get_subscribers($item); + if (!$subscribers) { + return; + } + $parent = $item->parent(); $v = new View("item_added.html"); $v->item = $item; @@ -104,14 +117,19 @@ 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); + self::_notify($subscribers, $item, $v->render(), $v->subject); } static function send_item_deleted($item) { + $subscribers = self::get_subscribers($item); + if (!$subscribers) { + return; + } + $parent = $item->parent(); $v = new View("item_deleted.html"); $v->item = $item; @@ -124,11 +142,16 @@ class notification { : t("Movie %title removed from %parent_title", array("title" => $item->title, "parent_title" => $parent->title))); - self::_notify_subscribers($item, $v->render(), $v->subject); + self::_notify($subscribers, $item, $v->render(), $v->subject); } static function send_comment_published($comment) { $item = $comment->item(); + $subscribers = self::get_subscribers($item); + if (!$subscribers) { + return; + } + $v = new View("comment_published.html"); $v->comment = $comment; $v->subject = $item->is_album() ? @@ -137,7 +160,7 @@ class notification { t("A new comment was published for photo %title", array("title" => $item->title)) : t("A new comment was published for movie %title", array("title" => $item->title))); - self::_notify_subscribers($item, $v->render(), $v->subject); + self::_notify($subscribers, $item, $v->render(), $v->subject); } static function send_pending_notifications() { @@ -150,7 +173,7 @@ class notification { ->where("email", $email) ->find_all(); if ($result->count() == 1) { - $pending = $result->get(); + $pending = $result->current(); Sendmail::factory() ->to($email) ->subject($pending->subject) @@ -176,23 +199,22 @@ class notification { } } - private static function _notify_subscribers($item, $text, $subject) { - $users = self::get_subscribers($item); - if (!empty($users)) { + private static function _notify($subscribers, $item, $text, $subject) { + if (!empty($subscribers)) { if (!batch::in_progress()) { Sendmail::factory() - ->to($users) + ->to($subscribers) ->subject($subject) ->header("Mime-Version", "1.0") ->header("Content-type", "text/html; charset=utf-8") ->message($text) ->send(); } else { - foreach ($users as $user) { + foreach ($subscribers as $subscriber) { $pending = ORM::factory("pending_notification"); $pending->subject = $subject; $pending->text = $text; - $pending->email = $user; + $pending->email = $subscriber; $pending->save(); } } diff --git a/modules/notification/helpers/notification_event.php b/modules/notification/helpers/notification_event.php index 1cf9ff58..c50b04c4 100644 --- a/modules/notification/helpers/notification_event.php +++ b/modules/notification/helpers/notification_event.php @@ -18,41 +18,98 @@ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ class notification_event_Core { - static function item_updated($old, $new) { - notification::send_item_updated($old, $new); + // The assumption is that the exception was logged at a lower level, but we + // don't want to screw up the processing that was generating the notification + // so we don't pass the exception up the call stack + static function item_updated($original, $new) { + try { + notification::send_item_updated($new); + } catch (Exception $e) { + Kohana::log("error", "@todo notification_event::item_updated() failed"); + Kohana::Log("error", $e->getMessage() . "\n" . $e->getTraceAsString()); + } } static function item_created($item) { - notification::send_item_add($item); + try { + notification::send_item_add($item); + } catch (Exception $e) { + Kohana::log("error", "@todo notification_event::item_created() failed"); + Kohana::Log("error", $e->getMessage() . "\n" . $e->getTraceAsString()); + } } - static function item_before_delete($item) { - notification::send_item_deleted($item); + static function item_deleted($item) { + try { + notification::send_item_deleted($item); - if (notification::is_watching($item)) { - notification::remove_watch($item); + if (notification::is_watching($item)) { + notification::remove_watch($item); + } + } catch (Exception $e) { + Kohana::log("error", "@todo notification_event::item_deleted() failed"); + Kohana::Log("error", $e->getMessage() . "\n" . $e->getTraceAsString()); } } static function comment_created($comment) { - if ($comment->state == "published") { - notification::send_comment_published($comment); + try { + if ($comment->state == "published") { + notification::send_comment_published($comment); + } + } catch (Exception $e) { + Kohana::log("error", "@todo notification_event::comment_created() failed"); + Kohana::Log("error", $e->getMessage() . "\n" . $e->getTraceAsString()); } } - static function comment_updated($old, $new) { - if ($new->state == "published" && $old->state != "published") { - notification::send_comment_published($new); + static function comment_updated($original, $new) { + try { + if ($new->state == "published" && $original->state != "published") { + notification::send_comment_published($new); + } + } catch (Exception $e) { + Kohana::log("error", "@todo notification_event::comment_updated() failed"); + Kohana::Log("error", $e->getMessage() . "\n" . $e->getTraceAsString()); } } static function user_before_delete($user) { - ORM::factory("subscription") - ->where("user_id", $user->id) - ->delete_all(); + try { + ORM::factory("subscription") + ->where("user_id", $user->id) + ->delete_all(); + } catch (Exception $e) { + Kohana::log("error", "@todo notification_event::user_before_delete() failed"); + Kohana::Log("error", $e->getMessage() . "\n" . $e->getTraceAsString()); + } } static function batch_complete() { - notification::send_pending_notifications(); + try { + notification::send_pending_notifications(); + } catch (Exception $e) { + Kohana::log("error", "@todo notification_event::batch_complete() failed"); + Kohana::Log("error", $e->getMessage() . "\n" . $e->getTraceAsString()); + } + } + + static function site_menu($menu, $theme) { + if (!user::active()->guest) { + $item = $theme->item(); + + if ($item && $item->is_album() && access::can("view", $item)) { + $watching = notification::is_watching($item); + + $label = $watching ? t("Remove notifications") : t("Enable notifications"); + + $menu->get("options_menu") + ->append(Menu::factory("link") + ->id("watch") + ->label($label) + ->css_id("gNotifyLink") + ->url(url::site("notification/watch/$item->id?csrf=" . access::csrf_token()))); + } + } } }
\ No newline at end of file diff --git a/modules/notification/helpers/notification_installer.php b/modules/notification/helpers/notification_installer.php index 3d450258..aa2e09f7 100644 --- a/modules/notification/helpers/notification_installer.php +++ b/modules/notification/helpers/notification_installer.php @@ -27,14 +27,14 @@ class notification_installer { PRIMARY KEY (`id`), UNIQUE KEY (`item_id`, `user_id`), UNIQUE KEY (`user_id`, `item_id`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); $db->query("CREATE TABLE IF NOT EXISTS {pending_notifications} ( `id` int(9) NOT NULL auto_increment, `email` varchar(128) NOT NULL, `subject` varchar(255) NOT NULL, `text` text, PRIMARY KEY (`id`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); module::set_version("notification", 1); } diff --git a/modules/notification/helpers/notification_menu.php b/modules/notification/helpers/notification_menu.php deleted file mode 100644 index 696aad62..00000000 --- a/modules/notification/helpers/notification_menu.php +++ /dev/null @@ -1,39 +0,0 @@ -<?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 notification_menu_Core { - static function site($menu, $theme) { - if (!user::active()->guest) { - $item = $theme->item(); - - if ($item && $item->is_album()) { - $watching = notification::is_watching($item); - - $watching ? $label = t("Remove notifications") : $label = t("Enable notifications"); - - $menu->get("options_menu") - ->append(Menu::factory("link") - ->id("watch") - ->label($label) - ->css_id("gNotifyLink") - ->url(url::site("notification/watch/$item->id?csrf=" . access::csrf_token()))); - } - } - } -} diff --git a/modules/notification/views/comment_published.html.php b/modules/notification/views/comment_published.html.php index 4a56cdad..a8ca1899 100644 --- a/modules/notification/views/comment_published.html.php +++ b/modules/notification/views/comment_published.html.php @@ -1,32 +1,32 @@ <?php defined("SYSPATH") or die("No direct script access.") ?> <html> <head> - <title><?= p::clean($subject) ?> </title> + <title><?= html::clean($subject) ?> </title> </head> <body> - <h2><?= p::clean($subject) ?></h2> + <h2><?= html::clean($subject) ?></h2> <table> <tr> <td><?= t("Comment:") ?></td> - <td><?= nl2br(p::purify($comment->text)) ?></td> + <td><?= nl2br(html::purify($comment->text)) ?></td> </tr> <tr> <td><?= t("Author Name:") ?></td> - <td><?= p::clean($comment->author_name()) ?></td> + <td><?= html::clean($comment->author_name()) ?></td> </tr> <tr> <td><?= t("Author Email:") ?></td> - <td><?= p::clean($comment->author_email()) ?></td> + <td><?= html::clean($comment->author_email()) ?></td> </tr> <tr> <td><?= t("Author URL:") ?></td> - <td><?= p::clean($comment->author_url()) ?></td> + <td><?= html::clean($comment->author_url()) ?></td> </tr> <tr> <td><?= t("Url:") ?></td> <td> - <a href="<?= $comment->item()->url(array(), true) ?>#comments"> - <?= $comment->item()->url(array(), true) ?>#comments + <a href="<?= $comment->item()->abs_url() ?>#comments"> + <?= $comment->item()->abs_url() ?>#comments </a> </td> </tr> diff --git a/modules/notification/views/item_added.html.php b/modules/notification/views/item_added.html.php index 86724927..1ea3720d 100644 --- a/modules/notification/views/item_added.html.php +++ b/modules/notification/views/item_added.html.php @@ -1,27 +1,27 @@ <?php defined("SYSPATH") or die("No direct script access.") ?> <html> <head> - <title><?= p::clean($subject) ?> </title> + <title><?= html::clean($subject) ?> </title> </head> <body> - <h2><?= p::clean($subject) ?></h2> + <h2><?= html::clean($subject) ?></h2> <table> <tr> <td><?= t("Title:") ?></td> - <td><?= p::purify($item->title) ?></td> + <td><?= html::purify($item->title) ?></td> </tr> <tr> <td><?= t("Url:") ?></td> <td> - <a href="<?= $item->url(array(), true) ?>"> - <?= $item->url(array(), true) ?> + <a href="<?= $item->abs_url() ?>"> + <?= $item->abs_url() ?> </a> </td> </tr> <? if ($item->description): ?> <tr> <td><?= t("Description:") ?></td> - <td><?= nl2br(p::purify($item->description)) ?></td> + <td><?= nl2br(html::purify($item->description)) ?></td> </tr> <? endif ?> </table> diff --git a/modules/notification/views/item_deleted.html.php b/modules/notification/views/item_deleted.html.php index 92215211..a95cdd89 100644 --- a/modules/notification/views/item_deleted.html.php +++ b/modules/notification/views/item_deleted.html.php @@ -1,22 +1,22 @@ <?php defined("SYSPATH") or die("No direct script access.") ?> <html> <head> - <title><?= p::clean($subject) ?> </title> + <title><?= html::clean($subject) ?> </title> </head> <body> - <h2><?= p::clean($subject) ?></h2> + <h2><?= html::clean($subject) ?></h2> <table> <tr> <td colspan="2"> <?= t("To view the changed album %title use the link below.", - array("title" => p::purify($item->parent()->title))) ?> + array("title" => html::purify($item->parent()->title))) ?> </td> </tr> <tr> <td><?= t("Url:") ?></td> <td> - <a href="<?= $item->parent()->url(array(), true) ?>"> - <?= $item->parent()->url(array(), true) ?> + <a href="<?= $item->parent()->abs_url() ?>"> + <?= $item->parent()->abs_url() ?> </a> </td> </tr> diff --git a/modules/notification/views/item_updated.html.php b/modules/notification/views/item_updated.html.php index 0620c50c..9c200964 100644 --- a/modules/notification/views/item_updated.html.php +++ b/modules/notification/views/item_updated.html.php @@ -1,33 +1,33 @@ <?php defined("SYSPATH") or die("No direct script access.") ?> <html> <head> - <title><?= p::clean($subject) ?> </title> + <title><?= html::clean($subject) ?> </title> </head> <body> - <h2> <?= p::clean($subject) ?> </h2> + <h2> <?= html::clean($subject) ?> </h2> <table> <tr> - <? if ($old->title != $new->title): ?> + <? if ($item->original("title") != $item->title): ?> <td><?= t("New Title:") ?></td> - <td><?= p::clean($new->title) ?></td> + <td><?= html::clean($item->title) ?></td> <? else: ?> <td><?= t("Title:") ?></td> - <td><?= p::clean($new->title) ?></td> + <td><?= html::clean($item->title) ?></td> <? endif ?> </tr> <tr> <td><?= t("Url:") ?></td> - <td><a href="<?= $new->url(array(), true) ?>"><?= $new->url(array(), true) ?></a></td> + <td><a href="<?= $item->abs_url() ?>"><?= $item->abs_url() ?></a></td> </tr> - <? if ($old->description != $new->description): ?> + <? if ($item->original("description") != $item->description): ?> <tr> <td><?= t("New Description:") ?></td> - <td><?= p::clean($new->description) ?></td> + <td><?= html::clean($item->description) ?></td> </tr> - <? elseif (!empty($new->description)): ?> + <? elseif (!empty($item->description)): ?> <tr> <td><?= t("Description:") ?></td> - <td><?= p::clean($new->description) ?></td> + <td><?= html::clean($item->description) ?></td> </tr> <? endif ?> </table> diff --git a/modules/organize/controllers/organize.php b/modules/organize/controllers/organize.php index 6792573d..4639777c 100644 --- a/modules/organize/controllers/organize.php +++ b/modules/organize/controllers/organize.php @@ -18,527 +18,139 @@ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ class Organize_Controller extends Controller { - private static $_MICRO_THUMB_SIZE = 90; - private static $_MICRO_THUMB_PADDING = 5; - - function index($item_id=1) { - $item = ORM::factory("item", $item_id); - $root = ($item->id == 1) ? $item : ORM::factory("item", 1); - access::required("view", $item); - access::required("edit", $item); - - $v = new View("organize.html"); - $v->root = $root; - $v->item = $item; - $v->album_tree = $this->tree($item, $root); - $v->button_pane = new View("organize_button_pane.html"); + function dialog($album_id) { + $album = ORM::factory("item", $album_id); + access::required("view", $album); + access::required("edit", $album); + + $v = new View("organize_dialog.html"); + $v->album = $album; + $v->album_tree = self::_expanded_tree(ORM::factory("item", 1), $album); + $v->micro_thumb_grid = self::_get_micro_thumb_grid($album, 0); print $v; } - function content($item_id) { - $item = ORM::factory("item", $item_id); - access::required("view", $item); - access::required("edit", $item); - - $width = $this->input->get("width"); - $height = $this->input->get("height"); - $offset = $this->input->get("offset", 0); - $thumbsize = self::$_MICRO_THUMB_SIZE + 2 * self::$_MICRO_THUMB_PADDING; - $page_size = ceil($width / $thumbsize) * ceil($height / $thumbsize); - - $v = new View("organize_thumb_grid.html"); - $v->children = $item->children($page_size, $offset); - $v->thumbsize = self::$_MICRO_THUMB_SIZE; - $v->padding = self::$_MICRO_THUMB_PADDING; - $v->offset = $offset; - - print json_encode(array("count" => $v->children->count(), - "data" => $v->__toString())); - } - - function header($item_id) { - $item = ORM::factory("item", $item_id); - access::required("view", $item); - access::required("edit", $item); - - print json_encode( - array("title" => p::purify($item->title), - "description" => empty($item->description) ? "" : p::purify($item->description))); - } - - function tree($item, $parent) { - access::required("view", $item); - access::required("edit", $item); - - $albums = ORM::factory("item") - ->where(array("parent_id" => $parent->id, "type" => "album")) - ->orderby(array("title" => "ASC")) - ->find_all(); - - $v = new View("organize_album.html"); - $v->album = $parent; - $v->selected = $parent->id == $item->id; - - if ($albums->count()) { - $v->album_icon = $parent->id == 1 || $v->selected ? "ui-icon-minus" : "ui-icon-plus"; - } else { - $v->album_icon = ""; - } - - $v->children = ""; - foreach ($albums as $album) { - $v->children .= $this->tree($item, $album); - } - return $v->__toString(); - } - - function startTask($operation, $id) { - access::verify_csrf(); - $items = $this->input->post("item"); - - $item = ORM::factory("item", $id); - access::required("view", $item); - access::required("edit", $item); + function album($album_id, $offset) { + $album = ORM::factory("item", $album_id); + access::required("view", $album); + access::required("edit", $album); - $definition = $this->_getOperationDefinition($item, $operation); - - $task_def = Task_Definition::factory() - ->callback("organize_task::run") - ->description($definition["description"]) - ->name($definition["name"]); - $task = task::create($task_def, array("items" => $items, "position" => 0, "target" => $id, - "type" => $definition["type"], - "batch" => ceil(count($items) * .1))); - // @todo If there is only one item then call task_run($task->id); Maybe even change js so - // we can call finish as well. - batch::start(); print json_encode( - array("result" => "started", - "runningMsg" => $definition["runningMsg"], - "pauseMsg" => "<div class=\"gWarning\">{$definition['pauseMsg']}</div>", - "resumeMsg" => "<div class=\"gWarning\">{$definition['resumeMsg']}</div>", - "task" => array("id" => $task->id, - "percent_complete" => $task->percent_complete, - "type" => $task->get("type"), - "status" => $task->status, - "state" => $task->state, - "done" => $task->done))); - } - - function runTask($task_id) { - access::verify_csrf(); - - $task = task::run($task_id); - if (!$task->loaded || $task->owner_id != user::active()->id) { - access::forbidden(); - } - - print json_encode(array("result" => $task->done ? $task->state : "in_progress", - "task" => array("id" => $task->id, - "percent_complete" => $task->percent_complete, - "type" => $task->get("type"), - "post_process" => $task->get("post_process"), - "status" => $task->status, - "state" => $task->state, - "done" => $task->done))); + array("grid" => self::_get_micro_thumb_grid($album, $offset)->__toString(), + "sort_column" => $album->sort_column, + "sort_order" => $album->sort_order)); } - function finishTask($task_id) { + function move_to($target_album_id) { access::verify_csrf(); - $task = ORM::factory("task", $task_id); - if (!$task->loaded || $task->owner_id != user::active()->id) { - access::forbidden(); - } - - if ($task->done) { - $item = ORM::factory("item", (int)$task->get("target")); - $type = $task->get("type"); - switch ($type) { - case "albumCover": - $task->status = t("Album cover set for '%album'", array("album" => $item->title)); - break; - case "delete": - $task->status = t("Selection deleted"); - break; - case "move": - $task->status = t("Move to '%album' completed", array("album" => $item->title)); - break; - case "rearrange": - try { - $item->sort_column = "weight"; - $item->save(); - $task->status = t("Rearrange for '%album' completed", array("album" => $item->title)); - } catch (Exception $e) { - $task->state = "error"; - $task->status = $e->getMessage(); - } - break; - case "rotateCcw": - case "rotateCw": - $task->status = t("Rotation completed"); - break; + $target_album = ORM::factory("item", $target_album_id); + foreach ($this->input->post("source_ids") as $source_id) { + $source = ORM::factory("item", $source_id); + if (!$source->contains($target_album)) { + item::move($source, $target_album); } - $task->save(); - } - - batch::stop(); - print json_encode(array("result" => "success", - "task" => array( - "id" => $task->id, - "percent_complete" => $task->percent_complete, - "status" => $task->status, - "state" => $task->state, - "done" => $task->done))); - } - - function cancelTask($task_id) { - access::verify_csrf(); - - $task = ORM::factory("task", $task_id); - if (!$task->loaded || $task->owner_id != user::active()->id) { - access::forbidden(); - } - - if (!$task->done) { - $task->done = 1; - $task->state = "cancelled"; - $type = $task->get("type"); - switch ($type) { - case "move": - $task->status = t("Move to album was cancelled prior to completion"); - break; - case "rearrange": - $task->status = t("Rearrange album was cancelled prior to completion"); - case "rotateCcw": - case "rotateCw": - $task->status = t("Rotation was cancelled prior to completion"); - break; - } - $task->save(); } - batch::stop(); - print json_encode(array("result" => "success", - "task" => array( - "id" => $task->id, - "percent_complete" => $task->percent_complete, - "status" => $task->status, - "state" => $task->state, - "done" => $task->done))); - } - - function editForm() { - $event_parms = new stdClass(); - $event_parms->panes = array(); - $event_parms->itemids = $this->input->get("item"); - - // The following code should be done more dynamically i.e. use the event mechanism - if (count($event_parms->itemids) == 1) { - $item = ORM::factory("item") - ->in("id", $event_parms->itemids[0]) - ->find(); - - access::required("view", $item); - access::required("edit", $item); - - $event_parms->panes[] = array( - "label" => $item->is_album() ? t("Edit Album") : t("Edit Photo"), - "content" => organize::get_general_edit_form($item)); - - if ($item->is_album()) { - $event_parms->panes[] = array("label" => t("Sort Order"), - "content" => organize::get_sort_edit_form($item)); - } - } - - $event_parms->panes[] = array("label" => t("Manage Tags"), - "content" => organize::get_tag_form($event_parms->itemids)); - - $v = new View("organize_edit.html"); - $v->panes = $event_parms->panes; - print $v->render(); + print json_encode( + array("tree" => self::_expanded_tree(ORM::factory("item", 1), $album)->__toString(), + "grid" => self::_get_micro_thumb_grid($album, 0)->__toString())); } - // Handlers for the album/photo edit. Probably should be in modules/gallery - public function general() { + function rearrange($target_id, $before_or_after) { access::verify_csrf(); - $itemids = $this->input->post("item"); - $item = ORM::factory("item") - ->in("id", $itemids[0]) - ->find(); - access::required("view", $item); - access::required("edit", $item); - - $form = organize::get_general_edit_form($item); - if ($form->validate()) { - $orig = clone $item; - $item->title = $form->title->value; - $item->description = $form->description->value; - $item->rename($form->dirname->value); - $item->save(); + $target = ORM::factory("item", $target_id); + $album = $target->parent(); + access::required("view", $album); + access::required("edit", $album); - module::event("item_updated", $orig, $item); + $source_ids = $this->input->post("source_ids", array()); - if ($item->is_album()) { - log::success("content", "Updated album", "<a href=\"albums/$item->id\">view</a>"); - $message = t("Saved album %album_title", array("album_title" => p::purify($item->title))); - } else { - log::success("content", "Updated photo", "<a href=\"photos/$item->id\">view</a>"); - $message = t("Saved photo %photo_title", array("photo_title" => p::purify($item->title))); + if ($album->sort_column != "weight") { + $i = 0; + foreach ($album->children() as $child) { + // Do this directly in the database to avoid sending notifications + Database::Instance()->update("items", array("weight" => ++$i), array("id" => $child->id)); } - print json_encode(array("form" => $form->__toString(), "message" => $message)); - } else { - print json_encode(array("form" => $form->__toString())); + $album->sort_column = "weight"; + $album->sort_order = "ASC"; + $album->save(); + $target->reload(); } - } - - public function reset_general() { - $itemids = Input::instance()->get("item"); - $item = ORM::factory("item") - ->in("id", $itemids[0]) - ->find(); - access::required("view", $item); - access::required("edit", $item); - - print organize::get_general_edit_form($item); - } - - public function sort() { - access::verify_csrf(); - $itemids = $this->input->post("item"); - $item = ORM::factory("item") - ->in("id", $itemids[0]) - ->find(); - access::required("view", $item); - access::required("edit", $item); - - $form = organize::get_sort_edit_form($item); - if ($form->validate()) { - $orig = clone $item; - $item->sort_column = $form->column->value; - $item->sort_order = $form->direction->value; - $item->save(); + // Find the insertion point + $target_weight = $target->weight; + if ($before_or_after == "after") { + $target_weight++; + } - module::event("item_updated", $orig, $item); + // Make a hole + $count = count($source_ids); + Database::Instance()->query( + "UPDATE {items} " . + "SET `weight` = `weight` + $count " . + "WHERE `weight` >= $target_weight AND `parent_id` = {$album->id}"); - log::success("content", "Updated album", "<a href=\"albums/$item->id\">view</a>"); - $message = t("Saved album %album_title", array("album_title" => p::purify($item->title))); - print json_encode(array("form" => $form->__toString(), "message" => $message)); - } else { - print json_encode(array("form" => $form->__toString())); + // Insert source items into the hole + foreach ($source_ids as $source_id) { + Database::Instance()->update( + "items", array("weight" => $target_weight++), array("id" => $source_id)); } - } - public function reset_sort() { - $itemids = Input::instance()->get("item"); - $item = ORM::factory("item") - ->in("id", $itemids[0]) - ->find(); - access::required("view", $item); - access::required("edit", $item); + module::event("album_rearrange", $album); - print organize::get_sort_edit_form($item); + print json_encode( + array("grid" => self::_get_micro_thumb_grid($album, 0)->__toString(), + "sort_column" => $album->sort_column, + "sort_order" => $album->sort_order)); } - public function edit_tags() { + function sort_order($album_id, $col, $dir) { access::verify_csrf(); - $itemids = explode("|", $this->input->post("item")); - $form = organize::get_tag_form($itemids); - $old_tags = $form->tags->value; - if ($form->validate()) { - - $old_tags = preg_split("/[;,\s]+/", $old_tags); - sort($old_tags); - $new_tags = preg_split("/[;,\s]+/", $form->tags->value); - sort($new_tags); + $album = ORM::factory("item", $album_id); + access::required("view", $album); + access::required("edit", $album); - $HIGH_VALUE_STRING = "\256"; - for ($old_index = $new_index = 0;;) { - $old_tag = $old_index >= count($old_tags) ? $HIGH_VALUE_STRING : $old_tags[$old_index]; - $new_tag = $new_index >= count($new_tags) ? $HIGH_VALUE_STRING : $new_tags[$new_index]; - if ($old_tag == $HIGH_VALUE_STRING && $new_tag == $HIGH_VALUE_STRING) { - break; - } - $matches = array(); - $old_star = false; - if (preg_match("/(.*)(\*)$/", $old_tag, $matches)) { - $old_star = true; - $old_tag = $matches[1]; - } - $new_star = false; - if (preg_match("/(.*)(\*)$/", $new_tag, $matches)) { - $new_star = true; - $new_tag = $matches[1]; - } - if ($old_tag > $new_tag) { - // Its missing in the old list so add it - $this->_add_tag($new_tag, $itemids); - $new_index++; - } else if ($old_tag < $new_tag) { - // Its missing in the new list so its been removed - $this->_delete_tag($old_tag, $itemids); - $old_index++; - } else { - if ($old_star && !$new_star) { - // User wants tag to apply to all items, originally only on some of selected - $this->_update_tag($old_tag, $itemids); - } // Not changed ignore - $old_index++; - $new_index++; - } - } + $options = album::get_sort_order_options(); + if (!isset($options[$col])) { + return; } - print json_encode(array("form" => $form->__toString(), "message" => t("Tags updated"))); - } - - public function reset_edit_tags() { - $itemids = $this->input->get("item"); - print organize::get_tag_form($itemids); - } - - private function _add_tag($new_tag, $itemids) { - // Super lame security stopgap. This code is going to get rewritten anyway. - foreach ($itemids as $item_id) { - $item = ORM::factory("item", $item_id); - access::required("view", $item); - access::required("edit", $item); - } + $album->sort_column = $col; + $album->sort_order = $dir; + $album->save(); - $tag = ORM::factory("tag") - ->where("name", $new_tag) - ->find(); - if ($tag->loaded) { - $tag->count += count($itemids); - } else { - $tag->name = $new_tag; - $tag->count = count($itemids); - } - $tag->save(); - - $db = Database::instance(); - foreach ($itemids as $item_id) { - $db->query("INSERT INTO {items_tags} SET item_id = $item_id, tag_id = {$tag->id};"); - } + print json_encode( + array("grid" => self::_get_micro_thumb_grid($album, 0)->__toString(), + "sort_column" => $album->sort_column, + "sort_order" => $album->sort_order)); } - private function _delete_tag($new_tag, $itemids) { - // Super lame security stopgap. This code is going to get rewritten anyway. - foreach ($itemids as $item_id) { - $item = ORM::factory("item", $item_id); - access::required("view", $item); - access::required("edit", $item); - } - - $tag = ORM::factory("tag") - ->where("name", $new_tag) - ->find(); - $tag->count -= count($itemids); - if ($tag->count > 0) { - $tag->save(); - } else { - $tag->delete(); - } - - $ids = implode(", ", $itemids); - Database::instance()->query( - "DELETE FROM {items_tags} WHERE tag_id = {$tag->id} AND item_id IN ($ids);"); + private static function _get_micro_thumb_grid($album, $offset) { + $v = new View("organize_thumb_grid.html"); + $v->album = $album; + $v->offset = $offset; + return $v; } - private function _update_tag($new_tag, $itemids) { - // Super lame security stopgap. This code is going to get rewritten anyway. - foreach ($itemids as $item_id) { - $item = ORM::factory("item", $item_id); - access::required("view", $item); - access::required("edit", $item); - } - - $tag = ORM::factory("tag") - ->where("name", $new_tag) - ->find(); - - $db = Database::instance(); - $ids = implode(", ", $itemids); - $result = $db->query( - "SELECT item_id FROM {items_tags} - WHERE tag_id = {$tag->id} - AND item_id IN ($ids)"); + public function tree($album_id) { + $album = ORM::factory("item", $album_id); + access::required("view", $album); - $add_items = array_fill_keys($itemids, 1); - foreach($result as $row) { - unset($add_items[$row->item_id]); - } - $add_items = array_keys($add_items); - $tag->count += count($add_items); - $tag->save(); - foreach ($add_items as $item_id) { - $db->query("INSERT INTO {items_tags} SET item_id = $item_id, tag_id = {$tag->id};"); - } + print self::_expanded_tree($album); } - private function _getOperationDefinition($item, $operation) { - switch ($operation) { - case "move": - return array("description" => - t("Move albums and photos to '%name'", array("name" => $item->title)), - "name" => t("Move to '%name'", array("name" => $item->title)), - "type" => "move", - "runningMsg" => t("Move in progress"), - "pauseMsg" => t("The move operation was paused"), - "resumeMsg" => t("The move operation was resumed")); - break; - - case "rearrange": - return array("description" => t("Rearrange the order of albums and photos"), - "name" => t("Rearrange: %name", array("name" => $item->title)), - "type" => "rearrange", - "runningMsg" => t("Rearrange in progress"), - "pauseMsg" => t("The rearrange operation was paused"), - "resumeMsg" => t("The rearrange operation was resumed")); - break; - - case "rotateCcw": - return array("description" => t("Rotate the selected photos counter clockwise"), - "name" => t("Rotate images in %name", array("name" => $item->title)), - "type" => "rotateCcw", - "runningMsg" => t("Rotate Counter Clockwise in progress"), - "pauseMsg" => t("The rotate operation was paused"), - "resumeMsg" => t("The rotate operation was resumed")); - break; - - case "rotateCw": - return array("description" => t("Rotate the selected photos clockwise"), - "name" => t("Rotate images in %name", array("name" => $item->title)), - "type" => "rotateCw", - "runningMsg" => t("Rotate Clockwise in progress"), - "pauseMsg" => t("The rotate operation was paused"), - "resumeMsg" => t("The rotate operation was resumed")); - break; - - case "delete": - return array("description" => t("Delete selected photos and albums"), - "name" => t("Delete images in %name", array("name" => $item->title)), - "type" => "delete", - "runningMsg" => t("Delete images in progress"), - "pauseMsg" => t("The delete operation was paused"), - "resumeMsg" => t("The delete operation was resumed")); - break; - - case "albumCover": - return array("description" => t("Reset Album Cover"), - "name" => t("Reset Album cover for %name", array("name" => $item->title)), - "type" => "albumCover", - "runningMsg" => t("Reset Album Cover in progress"), - "pauseMsg" => t("Reset album cover was paused"), - "resumeMsg" => t("Reset album cover was resumed")); - break; - - default: - throw new Exception("Operation '$operation' is not implmented"); - } + /** + * Create an HTML representation of the tree from the root down to the selected album. We only + * include albums along the descendant hierarchy that includes the selected album, and the + * immediate child albums. + */ + private static function _expanded_tree($root, $selected_album=null) { + $v = new View("organize_tree.html"); + $v->album = $root; + $v->selected = $selected_album; + return $v; } -}
\ No newline at end of file +} diff --git a/modules/organize/css/organize.css b/modules/organize/css/organize.css index e58cd5a5..b1cef33c 100644 --- a/modules/organize/css/organize.css +++ b/modules/organize/css/organize.css @@ -1,282 +1,148 @@ -/* @todo move to theme css */ + /******************************************************************* - * Dialog wide stylings + * Dialog wide styles */ -#gMessage { - margin-bottom: .4em; +#gOrganize { + overflow: hidden; } -#gMessage .gInfo { - background-color: transparent; - background-image: none; - padding-left: .4em; +#gOrganize #bd { + height: 100%; } -#gOrganizeProgressDialog { - text-align: left; +#gOrganize .yui-u { + width: 75%; } -#gDialog .yui-gf div.first { - width: 20%; +#gOrganize .yui-gf .first { + width: 25%; } -#gDialog .yui-gf .yui-u { - width: 80%; +#gMessage { + margin-bottom: .4em; + width: 75%; + white-space: nowrap; +} + +#gOrganizeDetail { + height: 100%; +} + +#gMessage .gInfo { + font-weight: bold; + padding-left: 2em; } /******************************************************************* - * Album Tree styling + * Album Tree styles */ #gOrganizeTreeContainer { - overflow-y: auto; + height: 100%; + overflow: auto; margin: 0 !important; padding: 0 !important; } -#gOrganizeAlbumDescription { - height: 2em; - overflow-y: auto; +#gOrganizeAlbumTree .selected { + background-color: #cfdeff; + border-bottom: 1px solid #999; + margin-right: 0px; } -.gBranchSelected { - background-color: #cfdeff !important; - border-bottom: 1px solid #999 !important; - display: block; - padding: .3em 0; +#gOrganizeAlbumTree ul li { + padding-left: 1.2em; } -.gBranchDroppable { - border: 1px dotted; +.gOrganizeAlbum span { + cursor: pointer; } -.gBranchText { +.gOrganizeAlbumText { cursor: pointer; width: auto; + margin: 2px 0px 1px 2px; + display: block; } -.gBranchCollapsed { - display: none; -} - -.gBranchEmpty { - visibility: hidden; -} - -#gOrganizeTreeContainer ul ul li { - padding-left: 1.2em; +.gOrganizeAlbumText:hover { + background: #eee; } /******************************************************************* - * Album Panel Styles + * Album panel styles */ - -#gMicroThumbUnselectAll, -#gMicroThumbSelectAll { - font-size: 1em; - font-weight: bold; -} - -#gMicroThumbPanel { +#gOrganizeMicroThumbPanel { margin: 0 !important; padding: 0 !important; background-color: #cfdeff; - border: 1px solid #999 !important; + border: 1px solid #999; border-top: none !important; border-left: none !important; - margin-left: -1em !important; overflow-x: hidden; overflow-y: auto; } -#gMicroThumbGrid { - padding: .5em; +#gOrganizeMicroThumbGrid { + padding: 1em; } -.gMicroThumbContainer { - display: block; +.gOrganizeMicroThumbGridCell { float: left; - font-size: .7em; - height: 9em; - margin-bottom: 1em; - margin-left: 1em; - opacity: .4; - padding: 0 .5em; + font-size: 0.8em; + padding: .5em !important; + border-left: 1px hidden #13A; + border-right: 1px hidden #13A; + margin: 4px; } -.gMicroThumb { - height: 9em; - width: 9em; - background-color: #fff; +.gOrganizeMicroThumb { display: block; - float: left; + height: 9em; text-align: center; + width: 9em; } -#gMicroThumbPanel #gMicroThumbGrid .gAlbum { - background-color: #e8e8e8; -} - -#gMicroThumbPanel #gMicroThumbGrid :hover { - opacity: 1; +.gOrganizeMicroThumbGridCell.ui-selecting, +.gOrganizeMicroThumbGridCell.ui-selected { + margin: 2px; + border: 2px solid #13A; } -.gMicroThumbContainer.ui-selected { - opacity: 1; +.ui-selectable-helper { + z-index: 2000 !important; + border: 1px dashed #00F; + opacity: 0.25; + background: #13A; } -#gDragHelper .gMicroThumbGrid { - background-color: transparent; - padding: 0; - overflow: visible; +.gThumbnail { + padding: .5em; } -#gDragHelper .gMicroThumbContainer { - display: block; - margin: 0; - padding: 0; +#gOrganizeMicroThumbGrid .gAlbum { + background-color: #e8e8e8; } -#gDragHelper .gMicroThumb { - background-color: transparent; - height: auto; - width: auto; +.gOrganizeMicroThumbGridCell:hover { + margin: 2px; + border: 2px solid #13A; } - /**************************************************************** - * Organize Edit Drawer styling + * Controls styles */ -#gOrganizeEditDrawer { +#gOrganizeControls { + padding-left: 8px; background-color: #13A; - width: 90%; -} - -#gOrganizeEditDrawerPanel { - background-color: #fff; - border: 1px solid #13A; - display: none; - height: 195px; -} - -#gOrganizeEditDrawerHandle { - height: 30px; + color: #ccc; + width: 100% !important; } -#gOrganizeEditHandleLeft { - background-color: #FFF; - float: left; - height: 30px; - width: 15px; -} - -#gOrganizeEditHandleButtonsMiddle, -#gOrganizeEditHandleButtonsLeft { - float: left; - height: 20px; - padding: 2px 10px; -} - -#gOrganizeEditHandleButtonsMiddle { - margin-left: 20px; -} - -#gOrganizeEditHandleButtonsMiddle a, -#gOrganizeEditHandleButtonsLeft a { - float: left; - margin: 0 2.5px; -} - -#gOrganizeEditHandleButtonsRight { - float: right; - height: 20px; - padding: 2px 10px; -} - -#gOrganizeEditHandleButtonsRight a { - float: left; - margin: 0 2.5px; -} - -#gOrganizeEditHandleRight { - background-color: #FFF; - background-position: -15px 0; - float: right; - height: 30px; - width: 15px; -} - -#gOrganizeFormButtons { - bottom: 0.5em; -} - -#gOrganizeFormButtons .submit { +#gOrganizeControls select { display: inline; - float: none; - left: 0.5em; - position: relative; } -/* yui-u gives 80% width, but then we wrap so do it ourselves */ -#gOrganizeEditForm { +#gOrganizeClose { float: right; - width: 79%; - // height: 100px; -} - -#gOrganizeFormThumbs { - overflow: hidden; -} - -#gOrganizeFormThumbs div { - margin: 0; - text-align: center; - background: transparent none repeat scroll 0 0; -} - -#gOrganizeFormThumbs .gMicroThumbContainer { - display: block; - float: left; - opacity: 1; - position: absolute; -} - -/**************************************************************** - * Organize Edit From tabs styling - */ -#gOrganizeEditForm.ui-tabs .ui-tabs-hide { - display: block !important; - left: -10000px; - position: absolute; -} - -#gOrganizeEditForm.ui-widget { - font-size: .75em; -} - -.gOrganizeEditPane { - height: 135px; - overflow-y: auto; -} - -.textbox, -.textarea { - border: 1px solid #e8e8e8; - border-top-color: #ccc; - border-left-color: #ccc; - color: #333; - width: 100%; -} - -.textarea { - height: 6em; -} - -.textbox { - height: 1.3em; - width: 50% -} - -.gTagGroup { - float:left; - margin: .5em; + margin-right: 12px; } diff --git a/modules/organize/helpers/organize.php b/modules/organize/helpers/organize.php deleted file mode 100644 index 25284771..00000000 --- a/modules/organize/helpers/organize.php +++ /dev/null @@ -1,94 +0,0 @@ -<?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 organize_Core { - static function get_general_edit_form($item) { - $generalPane = new Forge("organize/__FUNCTION__", "", "post", - array("id" => "gEditGeneral", "ref" => "general")); - // In this case we know there is only 1 item, but in general we should loop - // and create multiple hidden items. - $generalPane->hidden("item[]")->value($item->id); - $generalPane->input("title")->label(t("Title"))->value($item->title); - $generalPane->textarea("description")->label(t("Description"))->value($item->description); - $generalPane->input("dirname")->label(t("Path Name"))->value($item->name) - ->callback("item::validate_no_slashes") - ->error_messages("no_slashes", t("The directory name can't contain a \"/\"")) - ->callback("item::validate_no_trailing_period") - ->error_messages("no_trailing_period", t("The directory name can't end in \".\"")) - ->callback("item::validate_no_name_conflict") - ->error_messages("conflict", t("The path name is not unique")); - - return $generalPane; - } - - static function get_sort_edit_form($item) { - $sortPane = new Forge("organize/__FUNCTION__", "", "post", - array("id" => "gEditSort", "ref" => "sort")); - $sortPane->hidden("item[]")->value($item->id); - $sortPane->dropdown("column", array("id" => "gAlbumSortColumn")) - ->label(t("Sort by")) - ->options(array("weight" => t("Order Added"), - "captured" => t("Capture Date"), - "created" => t("Creation Date"), - "title" => t("Title"), - "updated" => t("Updated Date"), - "view_count" => t("Number of views"), - "rand_key" => t("Random"))) - ->selected($item->sort_column); - $sortPane->dropdown("direction", array("id" => "gAlbumSortDirection")) - ->label(t("Order")) - ->options(array("ASC" => t("Ascending"), - "DESC" => t("Descending"))) - ->selected($item->sort_order); - - return $sortPane; - } - - static function get_tag_form($itemids) { - $tagPane = new Forge("organize/__FUNCTION__", "", "post", - array("id" => "gEditTags", "ref" => "edit_tags")); - $tagPane->hidden("item")->value(implode("|", $itemids)); - $item_count = count($itemids); - $ids = implode(", ", $itemids); - - // Lame stopgap security check. This code is going to get rewritten anyway. - foreach ($itemids as $id) { - $item = ORM::factory("item", $id); - access::required("view", $item); - access::required("edit", $item); - } - - $tags = Database::instance()->query( - "SELECT t.name, COUNT(it.item_id) as count - FROM {items_tags} it, {tags} t - WHERE it.tag_id = t.id - AND it.item_id in($ids) - GROUP BY it.tag_id - ORDER BY t.name ASC"); - $taglist = array(); - foreach ($tags as $tag) { - $taglist[] = $tag->name . ($item_count > $tag->count ? "*" : ""); - } - $taglist = implode("; ", $taglist); - $tagPane->textarea("tags")->label(t("Tags"))->value($taglist); - - return $tagPane; - } - -}
\ No newline at end of file diff --git a/modules/organize/helpers/organize_menu.php b/modules/organize/helpers/organize_event.php index 850c1eab..d6043116 100644 --- a/modules/organize/helpers/organize_menu.php +++ b/modules/organize/helpers/organize_event.php @@ -17,17 +17,30 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ -class organize_menu { - static function site($menu, $theme) { +class organize_event_Core { + static function site_menu($menu, $theme) { $item = $theme->item(); - if ($item && access::can("edit", $item) && $item->is_album()) { + if ($item && $item->is_album() && access::can("edit", $item)) { $menu->get("options_menu") - ->append(Menu::factory("link") - ->id("organize") - ->label(t("Organize Album")) - ->css_id("gOrganizeLink") - ->url(url::site("organize/index/{$item->id}"))); + ->append(Menu::factory("dialog") + ->id("organize") + ->label(t("Organize Album")) + ->css_id("gOrganizeLink") + ->url(url::site("organize/dialog/{$item->id}"))); } } + + static function context_menu($menu, $theme, $item) { + if ($item->is_album() && access::can("edit", $item)) { + $menu->get("options_menu") + ->append(Menu::factory("dialog") + ->id("organize") + ->label(t("Organize album")) + ->css_id("gOrganizeLink") + ->css_class("ui-icon-folder-open") + ->url(url::site("organize/dialog/{$item->id}"))); + } + } + } diff --git a/modules/organize/helpers/organize_installer.php b/modules/organize/helpers/organize_installer.php deleted file mode 100644 index 22ca1793..00000000 --- a/modules/organize/helpers/organize_installer.php +++ /dev/null @@ -1,24 +0,0 @@ -<?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 organize_installer { - static function install() { - module::set_version("organize", 1); - } -} diff --git a/modules/organize/helpers/organize_task.php b/modules/organize/helpers/organize_task.php deleted file mode 100644 index dc474818..00000000 --- a/modules/organize/helpers/organize_task.php +++ /dev/null @@ -1,131 +0,0 @@ -<?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 organize_task_Core { - static function available_tasks() { - // Return empty array so nothing appears in the maintenance screen - return array(); - } - - static function run($task) { - $context = unserialize($task->context); - $taskType = $context["type"]; - - try { - $target = ORM::factory("item", $context["target"]); - $total = count($context["items"]); - $stop = min($total - $context["position"], $context["batch"]); - $context["post_process"] = array(); - for ($offset = 0; $offset < $stop; $offset++) { - $current_id = $context["position"] + $offset; - $id = $context["items"][$current_id]; - switch ($taskType) { - case "move": - $source = ORM::factory("item", $id); - access::required("view", $source); - access::required("view", $target); - access::required("edit", $source); - access::required("edit", $target); - - item::move($source, $target); - break; - - case "rearrange": - $item = ORM::factory("item", $id); - access::required("view", $item); - access::required("edit", $item); - - Database::instance() - ->query("Update {items} set weight = {$context["position"]} where id=$id;"); - break; - - case "rotateCcw": - case "rotateCw": - $item = ORM::factory("item", $id); - access::required("view", $item); - access::required("edit", $item); - - if ($item->is_photo()) { - $context["post_process"]["reload"][] = - self::_do_rotation($item, $taskType == "rotateCcw" ? -90 : 90); - } - break; - - case "albumCover": - $item = ORM::factory("item", $id); - access::required("view", $item); - access::required("view", $item->parent()); - access::required("edit", $item->parent()); - - item::make_album_cover($item); - break; - - case "delete": - $item = ORM::factory("item", $id); - access::required("view", $item); - access::required("edit", $item); - - $item->delete(); - $context["post_process"]["remove"][] = array("id" => $id); - break; - - default: - throw new Exception("Task '$taskType' is not implemented"); - } - } - $context["position"] += $stop; - $task->state = "success"; - } catch(Exception $e) { - $task->status = $e->getMessage(); - $task->state = "error"; - $task->save(); - throw $e; - } - $task->context = serialize($context); - $total = count($context["items"]); - $task->percent_complete = $context["position"] / (float)$total * 100; - $task->done = $context["position"] == $total || $task->state == "error"; - } - - private static function _do_rotation($item, $degrees) { - // This code is copied from Quick_Controller::rotate - 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; - $item->save(); - - graphics::generate($item); - - $parent = $item->parent(); - if ($parent->album_cover_item_id == $item->id) { - copy($item->thumb_path(), $parent->thumb_path()); - $parent->thumb_width = $item->thumb_width; - $parent->thumb_height = $item->thumb_height; - $parent->save(); - } - list ($height, $width) = $item->scale_dimensions(90); - $margin_top = (90 - $height) / 20; - - return array("src" => $item->thumb_url() . "?rnd=" . rand(), - "id" => $item->id, - "marginTop" => "{$margin_top}em", "width" => $width, "height" => $height); - } -}
\ No newline at end of file diff --git a/modules/organize/helpers/organize_theme.php b/modules/organize/helpers/organize_theme.php index 02f1f589..61b6fe7d 100644 --- a/modules/organize/helpers/organize_theme.php +++ b/modules/organize/helpers/organize_theme.php @@ -19,9 +19,14 @@ */ 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"); + $item = $theme->item(); + if ($item && access::can("edit", $item) && $item->is_album()) { + // @todo: Defer loading js/css until we're loading the organize dialog as <script> and + // <link> elements so that we're not forcing them to be downloaded on every page view (which + // is expensive in terms of browser latency). When we do that, we'll have to figure out an + // approach that lets us continue to use the Kohana cascading filesystem. + $theme->script("organize.js"); + $theme->css("organize.css"); + } } } diff --git a/modules/organize/js/organize.js b/modules/organize/js/organize.js index f10cbcc9..7d204708 100644 --- a/modules/organize/js/organize.js +++ b/modules/organize/js/organize.js @@ -1,621 +1,247 @@ -/* - * @todo Trap resize of dialog and resize the child areas (tree, grid and edit form) - */ -var url; -var paused = false; -var task = null; -var transitItems = []; -var heightMicroThumbPanel; - -// ************************************************************************** -// JQuery UI Widgets -// Draggable -var draggable = { - handle: ".gMicroThumbContainer.ui-selected", - revert: true, - zindex: 2000, - distance: 10, - helper: function(event, ui) { - if (!$(event.currentTarget).hasClass("ui-selected")) { - $(event.currentTarget).addClass("ui-selected"); - setDrawerButtonState(); - } - $("#gMicroThumbPanel").append("<div id=\"gDragHelper\"><ul></ul></div>"); - var beginTop = event.pageY; - var beginLeft = event.pageX; - var zindex = $(".gMicroThumbContainer").draggable("option", "zindex"); - $("#gDragHelper").css('top', event.pageY - 22.5); - $("#gDragHelper").css('left', event.pageX + 22.5); - var placeHolder = $(this).clone(); - $(placeHolder).attr("id", "gPlaceHolder"); - $(placeHolder).css("visibility", "hidden"); - $(placeHolder).removeClass("ui-selected"); - $(placeHolder).removeClass("ui-draggable"); - $(this).after(placeHolder); +(function($) { + $.organize = { + micro_thumb_draggable: { + handle: ".ui-selected", + distance: 10, + cursorAt: { left: -10, top: -10}, + appendTo: "#gOrganizeMicroThumbPanel", + helper: function(event, ui) { + var selected = $(".ui-draggable.ui-selected img"); + if (selected.length) { + var set = $('<div class="gDragHelper"></div>') + .css({ + zIndex: 2000, + width: 80, + height: Math.ceil(selected.length / 5) * 16 + }); + var offset = $(this).offset(); + var click = {left: event.pageX - offset.left, top: event.pageY - offset.top}; + + selected.each(function(i) { + var row = parseInt(i / 5); + var j = i - (row * 5); + var o = $(this).offset(); + var copy = $(this).clone() + .css({ + width: $(this).width(), height: $(this).height(), display: "block", + margin: 0, position: 'absolute', outline: '5px solid #fff', + left: o.left - event.pageX, top: o.top - event.pageY + }) + .appendTo(set) + .animate({ width: 10, height: 10, outlineWidth: 1, margin: 1, + left: (20 * j), top: (row * 20) }, 500); + }); + return set; + } + return null; + }, - $("li.ui-selected").each(function(i) { - var clone = $(this).clone(); - $(clone).attr("id", "drag_clone_" + $(this).attr("ref")); - $("#gDragHelper ul").append(clone); - $(clone).css("position", "absolute"); - $(clone).css("top", beginTop); - $(clone).css("left", beginLeft); - $(clone).css("z-index", zindex--); - $(this).hide(); + start: function(event, ui) { + $("#gOrganizeMicroThumbPanel .ui-selected").hide(); + }, - var children = $(clone).find(".gMicroThumb .gThumbnail"); - var width = new String(children.css("width")).replace(/[^0-9]/g,"") * .5; - var height = new String(children.css("height")).replace(/[^0-9]/g,"") * .5; - var marginTop = new String(children.css("margin-top")).replace(/[^\.0-9]/g,"") * .5; - children.attr("width", width); - children.attr("height", height); - children.css("margin-top", marginTop); - if (i < 9) { - beginTop -= 5; - beginLeft += 5; + drag: function(event, ui) { + var top = $("#gOrganizeMicroThumbPanel").offset().top; + var height = $("#gOrganizeMicroThumbPanel").height(); + if (ui.offset.top > height + top - 20) { + $("#gOrganizeMicroThumbPanel").get(0).scrollTop += 100; + } else if (ui.offset.top < top + 20) { + $("#gOrganizeMicroThumbPanel").get(0).scrollTop = Math.max(0, $("#gOrganizeMicroThumbPanel").get(0).scrollTop - 100); + } } - }); - return $("#gDragHelper"); - }, - stop: function(event, ui) { - $("#gDragHelper li").each(function(i) { - $("#thumb_" + $(this).attr("ref")).show(); - }); - $(".gMicroThumbContainer.ui-selected").css("z-index", null); - $("#gDragHelper").remove(); - $("#gPlaceHolder").remove(); - } -}; - -// Thumbnail Grid Droppable -var thumbDroppable = { - tolerance: "pointer", - over: function(event, ui) { - $("#gPlaceHolder").show(); - }, - out: function(event, ui) { - $("#gPlaceHolder").hide(); - }, - drop: function(event, ui) { - $("#gDragHelper").hide(); - $("#gPlaceHolder").hide(); - var newOrder = ""; - $("#gMicroThumbGrid .gMicroThumbContainer").each(function(i) { - if ($(this).attr("id") == "gPlaceHolder") { - $("#gDragHelper li").each(function(i) { - newOrder += "&item[]=" + $(this).attr("ref"); + }, + + content_droppable: { + accept: "*", + tolerance: "pointer", + greedy: true, + drop: function(event, ui) { + var before_or_after = null; + var target_id = null; + if ($(".currentDropTarget").length) { + before_or_after = $(".currentDropTarget").css("borderLeftStyle") == "solid" ? "before" : "after"; + target_id = $(".currentDropTarget").attr("ref"); + } else { + before_or_after = "after"; + target_id = $("#gOrganizeMicroThumbGrid li:last").attr("ref"); + } + $.organize.do_drop({ + url: rearrange_url + .replace("__TARGET_ID__", target_id) + .replace("__BEFORE__", before_or_after), + source: $(ui.helper).children("img") }); - } else if ($(this).css("display") != "none") { - newOrder += "&item[]=" + $(this).attr("ref"); - } else { - // If its not displayed then its one of the ones being moved so ignore. - } - }); - $("#gDragHelper li").each(function(i) { - $("#gPlaceHolder").before($("#thumb_" + $(this).attr("ref")).show()); - }); - $.ajax({ - data: newOrder, - dataType: "json", - success: operationCallback, - type: "POST", - url: get_organize_url("organize/startTask/rearrange", {item_id: item_id}) - }); - } -}; - -// Album Tree Droppable -var treeDroppable = { - tolerance: "pointer", - greedy: true, - hoverClass: "gBranchDroppable", - drop: function(event, ui) { - $("#gDragHelper").hide(); - var targetItemId = $(this).attr("ref"); - if ($(this).hasClass("gBranchSelected")) { - $("#gMessage").empty().append(INVALID_DROP_TARGET); - ui.draggable.trigger("stop", event); - return false; - } - var postData = serializeItemIds("#gDragHelper li"); - var okToMove = true; - $("#gDragHelper li").each(function(i) { - okToMove &= targetItemId != $(this).attr("ref"); - }); - if (!okToMove) { - $("#gMessage").empty().append(INVALID_DROP_TARGET); - ui.draggable.trigger("stop", event); - return false; - } - $("#gDragHelper li").each(function(i) { - $("#thumb_" + $(this).attr("ref")).remove(); - }); - $.ajax({ - data: postData, - dataType: "json", - success: operationCallback, - type: "POST", - url: get_organize_url("organize/startTask/move", {item_id: targetItemId}) - }); - return true; - } -}; - -// Selectable -var selectable = { - filter: ".gMicroThumbContainer", - selected: function(event, ui) { - setDrawerButtonState(); - }, - unselected: function(event, ui) { - setDrawerButtonState(); - }, - stop: function(event, ui) { - getEditForm(); - } -}; - -// ************************************************************************** -// Event Handlers -// MicroThumbContainer mouseup -var onMicroThumbContainerMouseup = function(event) { - // For simplicity always remove the ui-selected class. If it was unselected - // it will get added back - $(this).toggleClass("ui-selected"); - - setDrawerButtonState(); - if ($("#gMicroThumbGrid li.ui-selected").length > 0) { - getEditForm(); - } -}; - -// MicroThumbContainer mousemove -var onMicroThumbContainerMousemove = function(event) { - if ($("#gDragHelper").length > 0 && $(this).attr("id") != "gPlaceHolder") { - if (event.pageX < $(this).offset().left + $(this).width() / 2) { - $(this).before($("#gPlaceHolder")); - } else { - $(this).after($("#gPlaceHolder")); - } - var container = $("#gMicroThumbPanel").get(0); - var scrollHeight = container.scrollHeight; - var scrollTop = container.scrollTop; - var height = $(container).height(); - if (event.pageY > height + scrollTop) { - container.scrollTop = this.offsetTop; - } else if (event.pageY < scrollTop) { - container.scrollTop -= height; - } - } -}; - -// Handle click events on the buttons on the drawer handle -function drawerHandleButtonsClick(event) { - event.preventDefault(); - if (!$(this).attr("disabled")) { - var operation = $(this).attr("ref"); - switch (operation) { - case "edit": - case "close": - $("#gOrganizeEditDrawerPanel").animate( - {"height": "toggle", "display": "block"}, - {duration: "fast", - complete: function() { - setSelectedThumbs(); - if (operation == "close") { - $("#gOrganizeEditHandleButtonsLeft a[ref='edit']").css("display", "inline-block"); - $("#gOrganizeEditHandleButtonsLeft a[ref='close']").css("display", "none"); - $("#gOrganizeEditHandleButtonsMiddle a").css("display", "none"); - } else { - $("#gOrganizeEditHandleButtonsLeft a[ref='edit']").css("display", "none"); - $("#gOrganizeEditHandleButtonsLeft a[ref='close']").css("display", "inline-block"); - $("#gOrganizeEditHandleButtonsMiddle a").css("display", "inline-block"); - } - }, - step: function() { - $("#gMicroThumbPanel").height(heightMicroThumbPanel - $(this).height()); - } - }); - break; - case "select-all": - $("#gMicroThumbGrid li").addClass("ui-selected"); - $("#gMicroThumbSelectAll").hide(); - $("#gMicroThumbUnselectAll").show(); - setDrawerButtonState(); - getEditForm(); - break; - case "unselect-all": - $("#gMicroThumbGrid li").removeClass("ui-selected"); - $("#gMicroThumbSelectAll").show(); - $("#gMicroThumbUnselectAll").hide(); - setDrawerButtonState(); - break; - case "done": - $("#gDialog").dialog("close"); - break; - case "submit": - var currentTab = $("#gOrganizeEditForm").tabs("option", "selected"); - var form = $("#pane-"+currentTab+" form"); - var url = $(form).attr("action") - .replace("__FUNCTION__", $(form).attr("ref")); - $.ajax({ - data: $(form).serialize(), - dataType: "json", - success: function (data, textStatus) { - $("#pane-"+currentTab).children("form").replaceWith(data.form); - if (data.message) { - $("#gMessage").empty().append("<div class='gSuccess'>" + data.message + "</div>"); - } - }, - type: "POST", - url: url - }); - break; - case "reset": - currentTab = $("#gOrganizeEditForm").tabs("option", "selected"); - form = $("#pane-"+currentTab+" form"); - $.ajax({ - data: serializeItemIds("#gMicroThumbPanel li.ui-selected"), - dataType: "html", - success: function (data, textStatus) { - $("#pane-"+currentTab + " form").replaceWith(data); - }, - type: "GET", - url: $(form).attr("action").replace("__FUNCTION__", "reset_" + $(form).attr("ref")) - }); - break; - case "delete": - if (!confirm(CONFIRM_DELETE)) { - break; } - default: - $.ajax({ - data: serializeItemIds("#gMicroThumbPanel li.ui-selected"), - dataType: "json", - success: operationCallback, - type: "POST", - url: get_organize_url("organize/startTask/" + operation, {item_id: item_id}) - }); - break; - } - } -}; - -// ************************************************************************** -// AJAX Callbacks -// MicroThumbContainer click -var getMicroThumbsCallback = function(json, textStatus) { - if (json.count > 0) { - $("#gMicroThumbGrid").append(json.data); - retrieveMicroThumbs(); - $(".gMicroThumbContainer").mouseup(onMicroThumbContainerMouseup); - $(".gMicroThumbContainer").mousemove(onMicroThumbContainerMousemove); - $(".gMicroThumbContainer").draggable(draggable); - } -}; - -var operationCallback = function (data, textStatus) { - var done = false; - if (!paused) { - createProgressDialog(data.runningMsg); - task = data.task; - task.pauseMsg = data.pauseMsg; - task.resumeMsg = data.resumeMsg; - done = data.task.done; - } - $(".gMicroThumbContainer").draggable("disable"); - paused = false; - while (!done && !paused) { - $.ajax({async: false, - success: function(data, textStatus) { - $(".gProgressBar").progressbar("value", data.task.percent_complete); - done = data.task.done; - if (data.task.post_process.reload) { - $.each(data.task.post_process.reload, function() { - var selector = "#gMicroThumb-" + this.id + " img"; - $(selector).attr("height", this.height); - $(selector).attr("width", this.width); - $(selector).attr("src", this.src); - $(selector).css("margin-top", this.marginTop); + }, + + branch_droppable: { + accept: "*", + tolerance: "pointer", + greedy: true, + drop: function(event, ui) { + if ($(event.target).hasClass("gViewOnly")) { + $(".ui-selected").show(); + $(".gOrganizeMicroThumbGridCell").css("borderStyle", "none"); + } else { + $.organize.do_drop({ + url: move_url.replace("__ALBUM_ID__", $(event.target).attr("ref")), + source: $(ui.helper).children("img") }); } - if (data.task.post_process.remove) { - $.each(data.task.post_process.remove, function() { - $("#thumb_" + this.id).remove(); - }); - } - }, - error: function(XMLHttpRequest, textStatus, errorThrown) { - paused = true; - displayAjaxError(XMLHttpRequest.responseText); - }, - dataType: "json", - type: "POST", - url: get_organize_url("organize/runTask", {task_id: task.id}) - }); - } - if (!paused) { - $("#gOrganizeProgressDialog").dialog("destroy").remove(); - $.ajax({async: false, - success: function(data, textStatus) { - setDrawerButtonState(); - task = null; - $("#gMessage").empty().append("<div class='gSuccess'>" + data.task.status + "</div>"); - }, - dataType: "json", - type: "POST", - url: get_organize_url("organize/finishTask", {task_id: task.id}) - }); - } - $(".gMicroThumbContainer").draggable("enable"); -}; - -// ************************************************************************** - -/** - * Dynamically initialize the organize dialog when it is displayed - */ -function organize_dialog_init() { - var size = getViewportSize(); - heightMicroThumbPanel = size.height() - 100; - var width = size.width() - 100; - - // Deal with ui.jquery bug: http://dev.jqueryui.com/ticket/4475 - $(".sf-menu li.sfHover ul").css("z-index", 70); - - $("#gDialog").dialog("option", "width", width); - $("#gDialog").dialog("option", "height", heightMicroThumbPanel); - - $("#gDialog").dialog("open"); - if ($("#gDialog h1").length) { - $("#gDialog").dialog('option', 'title', $("#gDialog h1:eq(0)").html()); - } else if ($("#gDialog fieldset legend").length) { - $("#gDialog").dialog('option', 'title', $("#gDialog fieldset legend:eq(0)").html()); - } - - $("#gDialog").bind("organize_close", function(target) { - document.location.reload(); - }); - - heightMicroThumbPanel -= 2 * parseFloat($("#gDialog").css("padding-top")); - heightMicroThumbPanel -= 2 * parseFloat($("#gDialog").css("padding-bottom")); - heightMicroThumbPanel -= $("#gMicroThumbPanel").position().top; - heightMicroThumbPanel -= $("#gDialog #ft").height(); - heightMicroThumbPanel -= $("#gOrganizeEditDrawerHandle").height(); - heightMicroThumbPanel = Math.round(heightMicroThumbPanel); - - $("#gMicroThumbPanel").height(heightMicroThumbPanel); - $("#gOrganizeTreeContainer").height(heightMicroThumbPanel); - - $(".gOrganizeBranch .ui-icon").click(organizeToggleChildren); - $(".gBranchText").droppable(treeDroppable); - $(".gBranchText").click(organizeOpenFolder); - retrieveMicroThumbs(item_id); - //showLoading("#gDialog"); - - $("#gMicroThumbPanel").droppable(thumbDroppable); - $("#gMicroThumbPanel").selectable(selectable); - $("#gOrganizeEditDrawerHandle a").click(drawerHandleButtonsClick); -} - -function retrieveMicroThumbs() { - var offset = $("#gMicroThumbGrid li").length; - if (url == null) { - var grid_width = $("#gMicroThumbPanel").width(); - url = $("#gMicroThumbPanel").attr("ref"); - url = url.replace("__WIDTH__", grid_width); - url = url.replace("__HEIGHT__", heightMicroThumbPanel); - } - var url_data = url.replace("__OFFSET__", offset); - url_data = url_data.replace("__ITEM_ID__", item_id); - $.getJSON(url_data, getMicroThumbsCallback); -} - -function organizeToggleChildren(event) { - var id = $(this).attr("ref"); - var span_children = $("#gOrganizeChildren-" + id); - if ($(this).hasClass("ui-icon-plus")) { - $(this).removeClass("ui-icon-plus"); - $(this).addClass("ui-icon-minus"); - $("#gOrganizeChildren-" + id).removeClass("gBranchCollapsed"); - } else { - $(this).removeClass("ui-icon-minus"); - $(this).addClass("ui-icon-plus"); - $("#gOrganizeChildren-" + id).addClass("gBranchCollapsed"); - } - event.preventDefault(); -} + } + }, -function organizeOpenFolder(event) { - var selected = $(".gBranchSelected"); - if ($(selected).attr("id") != $(this).attr("id")) { - $(selected).removeClass("gBranchSelected"); - $(this).addClass("gBranchSelected"); - item_id = $(this).attr("ref"); - $("#gMicroThumbGrid").empty(); - retrieveMicroThumbs(); - } - event.preventDefault(); -} + do_drop: function(options) { + $("#gOrganizeMicroThumbPanel").selectable("destroy"); + var source_ids = []; + $(options.source).each(function(i) { + source_ids.push($(this).attr("ref")); + }); -function get_organize_url(uri, parms) { - var url = rearrangeUrl; - url = url.replace("__URI__", uri); - url = url.replace("__ITEM_ID__", !parms.item_id ? "" : parms.item_id); - url += (parms.item_id && parms.task_id) ? "/" : ""; - url = url.replace("__TASK_ID__", !parms.task_id ? "" : parms.task_id); - return url; -} + if (source_ids.length) { + $.post(options.url, + { "source_ids[]": source_ids }, + function(data) { + $.organize._refresh(data); + }, + "json"); + } + }, -/** - * Set the enabled/disabled state of the buttons. The album cover is only enabled if - * there is only 1 image selected - */ -function setDrawerButtonState() { - $("#gOrganizeFormThumbStack").empty(); - $("#gOrganizeEditForm").empty(); - var selectedCount = $("#gMicroThumbGrid li.ui-selected").length; - if (selectedCount) { - $("#gOrganizeEditHandleButtonsLeft a").removeAttr("disabled"); - $("#gOrganizeEditHandleButtonsLeft a").removeClass("ui-state-disabled"); + _refresh: function(data) { + if (data.tree) { + $("#gOrganizeAlbumTree").html(data.tree); + } + if (data.grid) { + $("#gOrganizeMicroThumbGrid").html(data.grid); + $("#gOrganizeSortColumn").attr("value", data.sort_column); + $("#gOrganizeSortOrder").attr("value", data.sort_order); + } + $.organize.set_handlers(); + }, + + mouse_move_handler: function(event) { + if ($(".gDragHelper").length) { + $(".gOrganizeMicroThumbGridCell").css({borderStyle: "hidden", margin: "4px"}); + $(".currentDropTarget").removeClass("currentDropTarget"); + var borderStyle = event.pageX < $(this).offset().left + $(this).width() / 2 ? + {borderLeftStyle: "solid", marginLeft: "2px"} : {borderRightStyle: "solid", marginRight: "2px"}; + $(this).addClass("currentDropTarget") + .css(borderStyle); + } + }, + + /** + * Dynamically initialize the organize dialog when it is displayed + */ + init: function(data) { + var self = this; + // Deal with ui.jquery bug: http://dev.jqueryui.com/ticket/4475 (target 1.8?) + $(".sf-menu li.sfHover ul").css("z-index", 68); + $("#gDialog").dialog("option", "zIndex", 70); + $("#gDialog").bind("dialogopen", function(event, ui) { + $("#gOrganize").height($("#gDialog").innerHeight() - 20); + $("#gOrganizeMicroThumbPanel").height($("#gDialog").innerHeight() - 90); + $("#gOrganizeAlbumTree").height($("#gDialog").innerHeight() - 59); + }); - if (selectedCount > 1) { - $("#gOrganizeEditHandleButtonsLeft a[ref='albumCover']").attr("disabled", true); - $("#gOrganizeEditHandleButtonsLeft a[ref='albumCover']").addClass("ui-state-disabled"); - } - setSelectedThumbs(); - } else { - if ($("#gOrganizeEditDrawerPanel::visible").length) { - $("#gOrganizeEditHandleButtonsLeft a[ref='close']").trigger("click"); - } - $("#gOrganizeEditHandleButtonsLeft a").attr("disabled", true); - $("#gOrganizeEditHandleButtonsLeft a").addClass("ui-state-disabled"); - } -} + $("#gDialog").bind("dialogclose", function(event, ui) { + window.location.reload(); + }); -function setSelectedThumbs() { - if (!$("#gOrganizeEditDrawerPanel::visible").length) { - return; - } - var position = $("#gOrganizeFormThumbStack").position(); - var beginLeft = position.left; - var beginTop = 50; - var zindex = 2000; - $("li.ui-selected").each(function(i) { - var clone = $(this).clone(); - $(clone).attr("id", "edit_clone_" + $(this).attr("ref")); - $("#gOrganizeFormThumbStack").append(clone); - $(clone).removeClass("ui-draggable"); - $(clone).removeClass("ui-selected"); - $(clone).css("margin-top", beginTop); - $(clone).css("left", beginLeft); - $(clone).css("z-index", zindex--); + $("#gDialog #gOrganizeClose").click(function(event) { + $("#gDialog").dialog("close"); + }); - if (i < 9) { - beginTop -= 5; - beginLeft += 5; - } - }); -} + $("#gOrganizeSortColumn,#gOrganizeSortOrder").change(function(event) { + $.organize.resort($("#gOrganizeSortColumn").attr("value"), $("#gOrganizeSortOrder").attr("value")); + }); -function getEditForm() { - if ($("#gMicroThumbGrid li.ui-selected").length > 0) { - var postData = serializeItemIds("li.ui-selected"); - var url_data = get_organize_url("organize/editForm", {}) + postData; - $.get(url_data, function(data, textStatus) { - $("#gOrganizeEditForm").tabs("destroy"); - $("#gOrganizeEditForm").html(data); - if ($("#gOrganizeEditForm ul li").length) { - $("#gOrganizeEditForm").tabs(); - $("#gOrganizeEditHandleButtonsMiddle a").removeAttr("disabled"); - $("#gOrganizeEditHandleButtonsMiddle a").removeClass("ui-state-disabled"); + $.organize.set_handlers(); + }, + + set_handlers: function() { + $("#gOrganizeMicroThumbPanel") + .selectable({filter: ".gOrganizeMicroThumbGridCell"}) + .droppable($.organize.content_droppable); + $(".gOrganizeMicroThumbGridCell") + .draggable($.organize.micro_thumb_draggable) + .mouseleave($.organize.mouse_leave_handler) + .mousemove($.organize.mouse_move_handler); + $(".gOrganizeAlbum").droppable($.organize.branch_droppable); + $(".gOrganizeAlbumText").click($.organize.show_album); + $("#gOrganizeAlbumTree .ui-icon-plus,#gOrganizeAlbumTree .ui-icon-minus").click($.organize.toggle_branch); + }, + + toggle_branch: function(event) { + event.preventDefault(); + var target = $(event.currentTarget); + var branch = $(target).parent(); + var id = $(event.currentTarget).parent().attr("ref"); + + if ($(target).hasClass("ui-icon-plus")) { + // Expanding + if (!branch.find("ul").length) { + $.get(tree_url.replace("__ALBUM_ID__", id), { }, + function(data) { + branch.replaceWith(data); + $.organize.set_handlers(); + } + ); + } else { + branch.find("ul:eq(0)").slideDown(); + } } else { - $("#gOrganizeEditHandleButtonsMiddle a").attr("disabled", true); - $("#gOrganizeEditHandleButtonsMiddle a").addClass("ui-state-disabled"); + // Contracting + branch.find("ul:eq(0)").slideUp(); } - }); - } else { - $("#gOrganizeEditForm").tabs("destroy"); - $("#gOrganizeEditForm").empty(); - } -} - -function serializeItemIds(selector) { - var postData = ""; - $(selector).each(function(i) { - postData += "&item[]=" + $(this).attr("ref"); - }); - - return postData; -} - -function submitCurrentForm(event) { - console.log("submitCurrentForm"); - return false; -} - -function resetCurrentForm(event) { - console.log("resetCurrentForm"); - return false; -} - -function createProgressDialog(title) { - $("body").append("<div id='gOrganizeProgressDialog'>" + - "<div class='gProgressBar'></div>" + - "<button id='gOrganizeTaskPause' class='ui-state-default ui-corner-all'>" + PAUSE_BUTTON + "</button>" + - "<button id='gOrganizeTaskResume' class='ui-state-default ui-corner-all' style='display: none'>" + RESUME_BUTTON + "</button>" + - "<button id='gOrganizeTaskCancel' class='ui-state-default ui-corner-all' style='display: none'>" + CANCEL_BUTTON + "</button>" + - "</div>"); - $("#gOrganizeProgressDialog").dialog({ - autoOpen: true, - autoResize: false, - modal: true, - resizable: false, - title: title - }); - - $(".gProgressBar").progressbar(); - $("#gOrganizeTaskPause").click(function(event) { - paused = true; - $("#gOrganizeTaskPause").hide(); - $("#gOrganizeTaskResume").show(); - $("#gOrganizeTaskCancel").show(); - $("#gMessage").empty().append(task.pauseMsg); - }); - $("#gOrganizeTaskResume").click(function(event) { - $("#gOrganizeTaskPause").show(); - $("#gOrganizeTaskResume").hide(); - $("#gOrganizeTaskCancel").hide(); - $("#gMessage").empty().append(task.resumeMsg); - operationCallback(); - //startRearrangeCallback(); - }); - $("#gOrganizeTaskCancel").click(function(event) { - $("#gOrganizeTaskPause").show(); - $("#gOrganizeTaskResume").hide(); - $("#gOrganizeTaskCancel").hide(); - - $.ajax({async: false, - success: function(data, textStatus) { - task = null; - paused = false; - transitItems = []; - $("#gMessage").empty().append("<div class='gWarning'>" + data.task.status + "</div>"); - $("#gOrganizeProgressDialog").dialog("destroy").remove(); - }, - dataType: "json", - type: "POST", - url: get_organize_url("organize/cancelTask", {task_id: task.id}) - }); - }); -} - -// ************************************************************************** -// Functions that should probably be in a gallery namespace -function getViewportSize() { - return { - width : function() { - return window.innerWidth - || document.documentElement && document.documentElement.clientWidth - || document.body.clientWidth; - }, - height : function() { - return window.innerHeight - || document.documentElement && document.documentElement.clientHeight - || document.body.clientHeight; + $(target).toggleClass("ui-icon-plus"); + $(target).toggleClass("ui-icon-minus"); + }, + + /** + * When the text of a selection is clicked, then show that albums contents + */ + show_album: function(event) { + event.preventDefault(); + if ($(event.currentTarget).hasClass("selected")) { + return; } + var parent = $(event.currentTarget).parents(".gOrganizeBranch"); + if ($(parent).hasClass("gViewOnly")) { + return; + } + $("#gOrganizeMicroThumbPanel").selectable("destroy"); + var id = $(event.currentTarget).attr("ref"); + $("#gOrganizeAlbumTree .selected").removeClass("selected"); + $(".gOrganizeAlbumText[ref=" + id + "]").addClass("selected"); + var url = $("#gOrganizeMicroThumbPanel").attr("ref").replace("__ITEM_ID__", id).replace("__OFFSET__", 0); + $.get(url, {}, + function(data) { + $("#gOrganizeMicroThumbGrid").html(data.grid); + $("#gOrganizeSortColumn").attr("value", data.sort_column); + $("#gOrganizeSortOrder").attr("value", data.sort_order); + $.organize.set_handlers(); + }, + "json"); + }, + + /** + * Change the sort order. + */ + resort: function(column, dir) { + var url = sort_order_url + .replace("__ALBUM_ID__", $("#gOrganizeAlbumTree .selected").attr("ref")) + .replace("__COL__", column) + .replace("__DIR__", dir); + $.get(url, {}, + function(data) { + $("#gOrganizeMicroThumbGrid").html(data.grid); + $("#gOrganizeSortColumn").attr("value", data.sort_column); + $("#gOrganizeSortOrder").attr("value", data.sort_order); + $.organize.set_handlers(); + }, + "json"); + } }; -} - -function displayAjaxError(error) { - $("body").append("<div id=\"gAjaxError\" title=\"" + FATAL_ERROR + "\">" + error + "</div>"); - - $("#gAjaxError").dialog({ - autoOpen: true, - autoResize: false, - modal: true, - resizable: true, - width: 610, - height: $("#gDialog").height() - }); -} +})(jQuery); diff --git a/modules/organize/js/organize_init.js b/modules/organize/js/organize_init.js deleted file mode 100644 index ed036fdb..00000000 --- a/modules/organize/js/organize_init.js +++ /dev/null @@ -1,29 +0,0 @@ -$("document").ready(function() { - $("#gOrganizeLink").click(function(event) { - event.preventDefault(); - var href = event.target.href; - - $("body").append('<div id="gDialog"></div>'); - - $("#gDialog").dialog({ - autoOpen: false, - autoResize: false, - modal: true, - resizable: false, - close: function () { - $("#gDialog").trigger("organize_close"); - $("#gDialog").dialog("destroy").remove(); - }, - zIndex: 75 - }); - - //showLoading("#gDialog"); - - $.get(href, function(data) { - $("#gDialog").html(data); - }); - return false; - }); -}); - - diff --git a/modules/organize/views/organize.html.php b/modules/organize/views/organize.html.php deleted file mode 100644 index 65d67d04..00000000 --- a/modules/organize/views/organize.html.php +++ /dev/null @@ -1,53 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access.") ?> -<!-- ?= html::script("modules/organize/js/organize.js") ? --> -<script> - var FATAL_ERROR = "<?= t("Fatal Error") ?>"; - var PAUSE_BUTTON = "<?= t("Pause") ?>"; - var RESUME_BUTTON = "<?= t("Resume") ?>"; - var CANCEL_BUTTON = "<?= t("Cancel") ?>"; - var INVALID_DROP_TARGET = "<div class=\"gError\"><?= t("Drop cancelled as it would result in a recursive move") ?></div>"; -var CONFIRM_DELETE = "<?= t("Do you really want to delete the selected albums and/or photos") ?>" - var item_id = <?= $item->id ?>; - - var csrf = "<?= $csrf ?>"; - var rearrangeUrl = "<?= url::site("__URI__/__ITEM_ID____TASK_ID__?csrf=$csrf") ?>"; - $("#doc3").ready(function() { - organize_dialog_init(); - }); -</script> -<fieldset style="display: none"> - <legend><?= t("Organize %name", array("name" => p::purify($item->title))) ?></legend> -</fieldset> -<div id="doc3" class="yui-t7"> - <div id="bd"> - <div class="yui-gf"> - <div class="yui-u first"> - <h3><?= t("Albums") ?></h3> - </div> - <div id="gMessage" class="yui-u"> - <div class="gInfo"><?= t("Select one or more items to edit; drag and drop items to re-order or move between albums") ?></div> - </div> - </div> - <div class="yui-gf"> - <div id="gOrganizeTreeContainer" class="yui-u first"> - <?= $album_tree ?> - </div> - <div id="gMicroThumbPanel" class="yui-u" - ref="<?= url::site("organize/content/__ITEM_ID__?width=__WIDTH__&height=__HEIGHT__&offset=__OFFSET__") ?>"> - <ul id="gMicroThumbGrid"></ul> - </div> - <div id="gOrganizeEditDrawer" class="yui-u"> - <div id="gOrganizeEditDrawerPanel" class="yui-gf"> - <div id="gOrganizeFormThumbs" class="yui-u first"> - <ul id="gOrganizeFormThumbStack" /> - </div> - <div id="gOrganizeEditForm"> - </div> - </div> - <div id="gOrganizeEditDrawerHandle"> - <?= $button_pane ?> - </div> - </div> - </div> - </div> -</div> diff --git a/modules/organize/views/organize_album.html.php b/modules/organize/views/organize_album.html.php deleted file mode 100644 index ae2d5d51..00000000 --- a/modules/organize/views/organize_album.html.php +++ /dev/null @@ -1,17 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access.") ?> -<ul> - <li class="gOrganizeBranch ui-icon-left" ref="<?= $album->id ?>"> - <span id="gOrganizeIcon-<?= $album->id ?>" ref="<?= $album->id ?>" - class="ui-icon <?= $album_icon ?> <?= $album_icon ? "" : "gBranchEmpty" ?>"> - </span> - - <div id="gOrganizeBranch-<?= $album->id ?>" ref="<?= $album->id ?>" - class="<?= $selected ? "gBranchSelected" : "" ?> gBranchText"> - <?= p::clean($album->title) ?> - </div> - <div id="gOrganizeChildren-<?= $album->id ?>" - class="<?= $album_icon == "ui-icon-plus" ? "gBranchCollapsed" : "" ?>"> - <?= $children ?> - <div> - </li> -</ul> diff --git a/modules/organize/views/organize_button_pane.html.php b/modules/organize/views/organize_button_pane.html.php deleted file mode 100644 index c5839a44..00000000 --- a/modules/organize/views/organize_button_pane.html.php +++ /dev/null @@ -1,50 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access.") ?> -<div id="gOrganizeEditHandleButtonsLeft"> - <a class="gButtonLink ui-corner-all ui-state-default ui-state-disabled" href="#" ref="edit" - disabled="1" title="<?= t("Open Drawer") ?>"> - <span class="ui-icon ui-icon-arrowthickstop-1-n"><?= t("Open Drawer") ?></span> - </a> - - <a class="gButtonLink ui-corner-all ui-state-default ui-state-disabled" href="#" ref="close" - disabled="1" title="<?= t("Close Drawer") ?>" style="display: none"> - <span class="ui-icon ui-icon-arrowthickstop-1-s"><?= t("Close Drawer") ?></span> - </a> - - <? if (graphics::can("rotate")): ?> - <a class="gButtonLink ui-corner-all ui-state-default ui-state-disabled" href="#" ref="rotateCcw" - disabled="1" title="<?= t("Rotate 90 degrees counter clockwise") ?>"> - <span class="ui-icon ui-icon-rotate-ccw"><?= t("Rotate 90 degrees counter clockwise") ?></span> - </a> - - <a class="gButtonLink ui-corner-all ui-state-default ui-state-disabled" href="#" ref="rotateCw" - disabled="1" title="<?= t("Rotate 90 degrees clockwise") ?>"> - <span class="ui-icon ui-icon-rotate-cw"> <?= t("Rotate 90 degrees clockwise") ?></span> - </a> - <? endif ?> - - <a class="gButtonLink ui-corner-all ui-state-default ui-state-disabled" href="#" ref="albumCover" - disabled="1" title="<?= t("Choose this photo as the album cover") ?>"> - <span class="ui-icon ui-icon-star"><?= t("Choose this photo as the album cover") ?></span> - </a> - - <a class="gButtonLink ui-corner-all ui-state-default ui-state-disabled" href="#" ref="delete" - disabled="1" title="<?= t("Delete selection") ?>"> - <span class="ui-icon ui-icon-trash"><?= t("Delete selection") ?></span> - </a> -</div> -<div id="gOrganizeEditHandleButtonsMiddle"> - <a class="gButtonLink ui-corner-all ui-state-default" href="#" ref="submit" - title="<?= t("Apply Changes") ?>" style="display: none" > - <span class="ui-icon ui-icon-check"><?= t("Apply Changes") ?></span> - </a> - - <a class="gButtonLink ui-corner-all ui-state-default" href="#" ref="reset" - title="<?= t("Reset Form") ?>" style="display: none" > - <span class="ui-icon ui-icon-closethick"><?= t("Reset Form") ?></span> - </a> -</div> -<div id="gOrganizeEditHandleButtonsRight"> - <a id="gMicroThumbSelectAll" href="#" ref="select-all" class="gButtonLink ui-corner-all ui-state-default"><?= t("Select all") ?></a> - <a id="gMicroThumbUnselectAll" href="#" ref="unselect-all" style="display: none" class="gButtonLink ui-corner-all ui-state-default"><?= t("Deselect all") ?></a> - <a id="gMicroThumbDone" href="#" ref="done" class="gButtonLink ui-corner-all ui-state-default"><?= t("Close") ?></a> -</div> diff --git a/modules/organize/views/organize_dialog.html.php b/modules/organize/views/organize_dialog.html.php new file mode 100644 index 00000000..cbc2e4f9 --- /dev/null +++ b/modules/organize/views/organize_dialog.html.php @@ -0,0 +1,48 @@ +<?php defined("SYSPATH") or die("No direct script access.") ?> +<script type="text/javascript"> + var move_url = "<?= url::site("organize/move_to/__ALBUM_ID__?csrf=$csrf") ?>"; + var rearrange_url = "<?= url::site("organize/rearrange/__TARGET_ID__/__BEFORE__?csrf=$csrf") ?>"; + var sort_order_url = "<?= url::site("organize/sort_order/__ALBUM_ID__/__COL__/__DIR__?csrf=$csrf") ?>"; + var tree_url = "<?= url::site("organize/tree/__ALBUM_ID__") ?>"; +</script> +<div id="gOrganize" class="gDialogPanel"> + <h1 style="display:none"><?= t("Organize %name", array("name" => html::purify($album->title))) ?></h1> + <div id="bd"> + <div class="yui-gf"> + <div class="yui-u first"> + <h3><?= t("Albums") ?></h3> + </div> + <div id="gMessage" class="yui-u"> + <div class="gInfo"><?= t("Drag and drop photos to re-order or move between albums") ?></div> + </div> + </div> + <div id="gOrganizeContentPane" class="yui-gf"> + <div id="gOrganizeTreeContainer" class="yui-u first"> + <ul id="gOrganizeAlbumTree"> + <?= $album_tree ?> + </ul> + </div> + <div id="gOrganizeDetail" class="yui-u"> + <div id="gOrganizeMicroThumbPanel" + ref="<?= url::site("organize/album/__ITEM_ID__/__OFFSET__") ?>"> + <ul id="gOrganizeMicroThumbGrid"> + <?= $micro_thumb_grid ?> + </ul> + </div> + <div id="gOrganizeControls"> + <a id="gOrganizeClose" href="#" ref="done" + class="gButtonLink ui-corner-all ui-state-default"><?= t("Close") ?></a> + <form> + <?= t("Sort order") ?> + <?= form::dropdown(array("id" => "gOrganizeSortColumn"), album::get_sort_order_options(), $album->sort_column) ?> + <?= form::dropdown(array("id" => "gOrganizeSortOrder"), array("ASC" => "Ascending", "DESC" => "Descending"), $album->sort_order) ?> + </form> + </div> + </div> + </div> + </div> +</div> + +<script type="text/javascript"> + $("#gOrganize").ready($.organize.init); +</script> diff --git a/modules/organize/views/organize_edit.html.php b/modules/organize/views/organize_edit.html.php deleted file mode 100644 index 1adf290f..00000000 --- a/modules/organize/views/organize_edit.html.php +++ /dev/null @@ -1,14 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access.") ?> -<ul> -<? foreach ($panes as $idx => $pane): ?> - <li><a href="#pane-<?= $idx ?>"><?= $pane["label"] ?></a></li> -<? endforeach?> -</ul> - -<? if (count($panes) > 0): ?> - <? foreach ($panes as $idx => $pane): ?> - <div id="pane-<?= $idx ?>" class="gOrganizeEditPane ui-tabs-hide"><?= $pane["content"] ?></div> - <? endforeach?> -<? else: ?> -<div class="gWarning"><?= t("No Edit pages apply to the selected items") ?></div> -<? endif ?>
\ No newline at end of file diff --git a/modules/organize/views/organize_thumb_grid.html.php b/modules/organize/views/organize_thumb_grid.html.php index c80696ad..af7136fc 100644 --- a/modules/organize/views/organize_thumb_grid.html.php +++ b/modules/organize/views/organize_thumb_grid.html.php @@ -1,12 +1,23 @@ <?php defined("SYSPATH") or die("No direct script access.") ?> -<? foreach ($children as $i => $child): ?> -<? $item_class = "gPhoto"; ?> -<? if ($child->is_album()): ?> - <? $item_class = "gAlbum"; ?> -<? endif ?> -<li id="thumb_<?= $child->id ?>" class="gMicroThumbContainer" ref="<?= $child->id ?>"> - <div id="gMicroThumb-<?= $child->id ?>" class="gMicroThumb <?= $item_class ?>"> - <?= $child->thumb_img(array("class" => "gThumbnail"), $thumbsize, true) ?> +<? foreach ($album->children(25, $offset) as $child): ?> +<li class="gOrganizeMicroThumbGridCell" ref="<?= $child->id ?>"> + <div id="gOrganizeMicroThumb_<?= $child->id ?>" + class="gOrganizeMicroThumb <?= $child->is_album() ? "gAlbum" : "gPhoto" ?>"> + <?= $child->thumb_img(array("class" => "gThumbnail", "ref" => $child->id), 90, true) ?> </div> </li> <? endforeach ?> + +<? if ($album->children_count() > $offset): ?> +<script> + setTimeout(function() { + $.get("<?= url::site("organize/album/$album->id/" . ($offset + 25)) ?>", + {}, + function(data) { + $("#gOrganizeMicroThumbGrid").append(data.grid); + $.organize.set_handlers(); + }, + "json"); + }, 50); +</script> +<? endif ?> diff --git a/modules/organize/views/organize_tree.html.php b/modules/organize/views/organize_tree.html.php index d2cdd957..e5d91c04 100644 --- a/modules/organize/views/organize_tree.html.php +++ b/modules/organize/views/organize_tree.html.php @@ -1,4 +1,27 @@ <?php defined("SYSPATH") or die("No direct script access.") ?> -<? foreach ($children as $i => $child): ?> -<? endforeach ?> +<li class="gOrganizeAlbum ui-icon-left <?= access::can("edit", $album) ? "" : "gViewOnly" ?>" + ref="<?= $album->id ?>"> + <span class="ui-icon ui-icon-minus"> + </span> + <span class="gOrganizeAlbumText <?= $selected && $album->id == $selected->id ? "selected" : "" ?>" + ref="<?= $album->id ?>"> + <?= html::clean($album->title) ?> + </span> + <ul> + <? foreach ($album->children(null, 0, array("type" => "album")) as $child): ?> + <? if ($selected && $child->contains($selected)): ?> + <?= View::factory("organize_tree.html", array("selected" => $selected, "album" => $child)); ?> + <? else: ?> + <li class="gOrganizeAlbum ui-icon-left <?= access::can("edit", $child) ? "" : "gViewOnly" ?>" + ref="<?= $child->id ?>"> + <span class="ui-icon ui-icon-plus"> + </span> + <span class="gOrganizeAlbumText" ref="<?= $child->id ?>"> + <?= html::clean($child->title) ?> + </span> + </li> + <? endif ?> + <? endforeach ?> + </ul> +</li> diff --git a/modules/recaptcha/helpers/recaptcha.php b/modules/recaptcha/helpers/recaptcha.php index 501dd972..bead6156 100644 --- a/modules/recaptcha/helpers/recaptcha.php +++ b/modules/recaptcha/helpers/recaptcha.php @@ -43,7 +43,7 @@ class recaptcha_Core { if (empty($public_key) || empty($private_key)) { site_status::warning( t("reCAPTCHA is not quite ready! Please configure the <a href=\"%url\">reCAPTCHA Keys</a>", - array("url" => url::site("admin/recaptcha"))), + array("url" => html::mark_clean(url::site("admin/recaptcha")))), "recaptcha_config"); } else { site_status::clear("recaptcha_config"); diff --git a/modules/recaptcha/helpers/recaptcha_event.php b/modules/recaptcha/helpers/recaptcha_event.php index 932ddee6..d23a0c74 100644 --- a/modules/recaptcha/helpers/recaptcha_event.php +++ b/modules/recaptcha/helpers/recaptcha_event.php @@ -23,4 +23,12 @@ class recaptcha_event_Core { $form->add_comment->recaptcha("recaptcha")->label("")->id("gRecaptcha"); } } + + static function admin_menu($menu, $theme) { + $menu->get("settings_menu") + ->append(Menu::factory("link") + ->id("recaptcha") + ->label(t("reCAPTCHA")) + ->url(url::site("admin/recaptcha"))); + } } diff --git a/modules/recaptcha/helpers/recaptcha_installer.php b/modules/recaptcha/helpers/recaptcha_installer.php index 12044a1b..e04822ea 100644 --- a/modules/recaptcha/helpers/recaptcha_installer.php +++ b/modules/recaptcha/helpers/recaptcha_installer.php @@ -18,10 +18,6 @@ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ class recaptcha_installer { - static function install() { - module::set_version("recaptcha", 1); - } - static function activate() { recaptcha::check_config(); } diff --git a/modules/recaptcha/helpers/recaptcha_menu.php b/modules/recaptcha/helpers/recaptcha_menu.php deleted file mode 100644 index 047abf8f..00000000 --- a/modules/recaptcha/helpers/recaptcha_menu.php +++ /dev/null @@ -1,28 +0,0 @@ -<?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 recaptcha_menu_Core { - static function admin($menu, $theme) { - $menu->get("settings_menu") - ->append(Menu::factory("link") - ->id("recaptcha") - ->label(t("reCAPTCHA")) - ->url(url::site("admin/recaptcha"))); - } -} diff --git a/modules/recaptcha/views/admin_recaptcha.html.php b/modules/recaptcha/views/admin_recaptcha.html.php index 43b4da8a..0a4b1f8f 100644 --- a/modules/recaptcha/views/admin_recaptcha.html.php +++ b/modules/recaptcha/views/admin_recaptcha.html.php @@ -4,7 +4,7 @@ <p> <?= t("reCAPTCHA is a free CAPTCHA service that helps to digitize books, newspapers and old time radio shows. In order to use it, you need to sign up for a <a href=\"%domain_url\">reCAPTCHA Public/Private Key pair</a>, which is also free. Once registered, the challenge and response strings are evaluated at <a href=\"%recaptcha_url\">recaptcha.net</a> to determine if the form content has been entered by a bot.", array("domain_url" => $form->get_key_url, - "recaptcha_url" => "http://recaptcha.net")) ?> + "recaptcha_url" => html::mark_clean("http://recaptcha.net"))) ?> </p> <?= $form ?> @@ -23,7 +23,7 @@ Recaptcha.create("<?= $public_key ?>", "gRecaptcha", { callback: Recaptcha.focus_response_field, lang: "en", - custom_translations : { instructions_visual : "<?= t("Type words to check:") ?>"}, + custom_translations : { instructions_visual : <?= t("Type words to check:")->for_js() ?>}, theme: "white" }); </script> diff --git a/modules/recaptcha/views/form_recaptcha.html.php b/modules/recaptcha/views/form_recaptcha.html.php index d4031586..4ec04c49 100644 --- a/modules/recaptcha/views/form_recaptcha.html.php +++ b/modules/recaptcha/views/form_recaptcha.html.php @@ -8,7 +8,7 @@ "gRecaptcha", { theme: "white", - custom_translations : { instructions_visual : "<?= t("Type words to check:") ?>"}, + custom_translations : { instructions_visual : <?= t("Type words to check:")->for_js() ?>}, callback: Recaptcha.focus_response_field } ); diff --git a/modules/rss/controllers/rss.php b/modules/rss/controllers/rss.php index e9dd9fff..b89bed40 100644 --- a/modules/rss/controllers/rss.php +++ b/modules/rss/controllers/rss.php @@ -26,13 +26,16 @@ class Rss_Controller extends Controller { url::redirect(url::merge(array("page" => 1))); } + // Configurable page size between 1 and 100, default 20 + $page_size = max(1, min(100, $this->input->get("page_size", self::$page_size))); + // Run the appropriate feed callback if (module::is_active($module_id)) { $class_name = "{$module_id}_rss"; if (method_exists($class_name, "feed")) { $feed = call_user_func( array($class_name, "feed"), $feed_id, - ($page - 1) * self::$page_size, self::$page_size, $id); + ($page - 1) * $page_size, $page_size, $id); } } if (empty($feed)) { diff --git a/modules/rss/helpers/rss_installer.php b/modules/rss/helpers/rss_installer.php deleted file mode 100644 index 7766fdfa..00000000 --- a/modules/rss/helpers/rss_installer.php +++ /dev/null @@ -1,24 +0,0 @@ -<?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 rss_installer { - static function install() { - module::set_version("rss", 1); - } -} diff --git a/modules/rss/module.info b/modules/rss/module.info index 81ee7848..48375da1 100644 --- a/modules/rss/module.info +++ b/modules/rss/module.info @@ -1,3 +1,3 @@ name = "RSS" -description = "Provide a RSS feeds" +description = "Provides RSS feeds" version = 1 diff --git a/modules/rss/views/feed.mrss.php b/modules/rss/views/feed.mrss.php index 447179a5..3612cbc0 100644 --- a/modules/rss/views/feed.mrss.php +++ b/modules/rss/views/feed.mrss.php @@ -6,9 +6,9 @@ xmlns:fh="http://purl.org/syndication/history/1.0"> <channel> <generator>gallery3</generator> - <title><?= p::clean($feed->title) ?></title> + <title><?= html::clean($feed->title) ?></title> <link><?= $feed->uri ?></link> - <description><?= p::clean($feed->description) ?></description> + <description><?= html::clean($feed->description) ?></description> <language>en-us</language> <atom:link rel="self" href="<?= $feed->uri ?>" type="application/rss+xml" /> <fh:complete/> @@ -22,25 +22,25 @@ <lastBuildDate><?= $pub_date ?></lastBuildDate> <? foreach ($feed->children as $child): ?> <item> - <title><?= p::clean($child->title) ?></title> + <title><?= html::purify($child->title) ?></title> <link><?= url::abs_site("{$child->type}s/{$child->id}") ?></link> <guid isPermaLink="true"><?= url::abs_site("{$child->type}s/{$child->id}") ?></guid> <pubDate><?= date("D, d M Y H:i:s T", $child->created); ?></pubDate> <content:encoded> <![CDATA[ - <span><?= p::clean($child->description) ?></span> + <span><?= html::purify($child->description) ?></span> <p> <? if ($child->type == "photo" || $child->type == "album"): ?> <img alt="" src="<?= $child->resize_url(true) ?>" - title="<?= p::clean($child->title) ?>" + title="<?= html::purify($child->title)->for_html_attr() ?>" height="<?= $child->resize_height ?>" width="<?= $child->resize_width ?>" /><br /> <? else: ?> <a href="<?= url::abs_site("{$child->type}s/{$child->id}") ?>"> <img alt="" src="<?= $child->thumb_url(true) ?>" - title="<?= p::clean($child->title) ?>" + title="<?= html::purify($child->title)->for_html_attr() ?>" height="<?= $child->thumb_height ?>" width="<?= $child->thumb_width ?>" /></a><br /> <? endif ?> - <?= p::clean($child->description) ?> + <?= html::purify($child->description) ?> </p> ]]> </content:encoded> diff --git a/modules/rss/views/rss_block.html.php b/modules/rss/views/rss_block.html.php index 39921d7d..737731b6 100644 --- a/modules/rss/views/rss_block.html.php +++ b/modules/rss/views/rss_block.html.php @@ -5,7 +5,7 @@ <span class="ui-icon-left"> <a href="<?= rss::url($url) ?>"> <span class="ui-icon ui-icon-signal-diag"></span> - <?= $title ?> + <?= html::purify($title) ?> </a> </span> </li> diff --git a/modules/search/helpers/search.php b/modules/search/helpers/search.php index 34eaecbd..0080b4ce 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 { @@ -58,28 +58,22 @@ class search_Core { if ($remaining) { site_status::warning( t('Your search index needs to be updated. <a href="%url" class="gDialogLink">Fix this now</a>', - array("url" => url::site("admin/maintenance/start/search_task::update_index?csrf=__CSRF__"))), + array("url" => html::mark_clean(url::site("admin/maintenance/start/search_task::update_index?csrf=__CSRF__")))), "search_index_out_of_date"); } } static function update($item) { - $data = array(); + $data = new ArrayObject(); $record = ORM::factory("search_record")->where("item_id", $item->id)->find(); if (!$record->loaded) { $record->item_id = $item->id; } - foreach (module::active() as $module) { - $class_name = "{$module->name}_search"; - if (method_exists($class_name, "item_index_data")) { - $data[] = call_user_func(array($class_name, "item_index_data"), $record->item()); - } - } - $record->data = join(" ", $data); + module::event("item_index_data", $record->item(), $data); + $record->data = join(" ", (array)$data); $record->dirty = 0; $record->save(); - return t("Search index updated for '%title'", array("title" => p::purify($item->title))); } static function stats() { diff --git a/modules/search/helpers/search_event.php b/modules/search/helpers/search_event.php index b9657395..836bbe15 100644 --- a/modules/search/helpers/search_event.php +++ b/modules/search/helpers/search_event.php @@ -22,11 +22,11 @@ class search_event_Core { search::update($item); } - static function item_updated($old_item, $new_item) { - search::update($new_item); + static function item_updated($original, $new) { + search::update($new); } - static function item_before_delete($item) { + static function item_deleted($item) { ORM::factory("search_record") ->where("item_id", $item->id) ->delete_all(); @@ -35,9 +35,4 @@ class search_event_Core { static function item_related_update($item) { search::update($item); } - - static function item_related_update_batch($sql) { - $db = Database::instance(); - $db->query("UPDATE {search_records} SET `dirty` = 1 WHERE item_id IN ($sql)"); - } } diff --git a/modules/search/helpers/search_installer.php b/modules/search/helpers/search_installer.php index cd253be4..10d8211f 100644 --- a/modules/search/helpers/search_installer.php +++ b/modules/search/helpers/search_installer.php @@ -28,7 +28,7 @@ class search_installer { PRIMARY KEY (`id`), KEY(`item_id`), FULLTEXT INDEX (`data`)) - ENGINE=MyISAM DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); module::set_version("search", 1); } diff --git a/modules/search/helpers/search_task.php b/modules/search/helpers/search_task.php index df1dfe16..9508f420 100644 --- a/modules/search/helpers/search_task.php +++ b/modules/search/helpers/search_task.php @@ -48,12 +48,18 @@ class search_task_Core { ->where("search_records.item_id", null) ->orwhere("search_records.dirty", 1) ->find_all() as $item) { - if (microtime(true) - $start > 1.5) { - break; + // The query above can take a long time, so start the timer after its done + // to give ourselves a little time to actually process rows. + if (!isset($start)) { + $start = microtime(true); } - $message[] = search::update($item); + search::update($item); $completed++; + + if (microtime(true) - $start > 1.5) { + break; + } } list ($remaining, $total, $percent) = search::stats(); @@ -69,13 +75,10 @@ class search_task_Core { $task->status = t2("one record updated, index is %percent% up-to-date", "%count records updated, index is %percent% up-to-date", $completed, array("percent" => $percent)); - $message[] = $task->status; } catch (Exception $e) { $task->done = true; $task->state = "error"; $task->status = $e->getMessage(); - $message[] = $e->__toString(); } - $task->log($message); } } diff --git a/modules/search/views/search.html.php b/modules/search/views/search.html.php index 6a222ef1..91d9eec8 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="<?= p::clean($q) ?>"/> + <input name="q" id="q" type="text" value="<?= html::clean_attribute($q) ?>"/> </li> <li> - <input type="submit" value="<?= t("Search") ?>" /> + <input type="submit" value="<?= t("Search")->for_html_attr() ?>" /> </li> </ul> </fieldset> @@ -28,13 +28,13 @@ <? $item_class = "gAlbum"; ?> <? endif ?> <li class="gItem <?= $item_class ?>"> - <a href="<?= url::site("items/$item->id") ?>"> + <a href="<?= $item->url() ?>"> <?= $item->thumb_img() ?> <p> - <?= p::purify($item->title) ?> + <?= html::purify($item->title) ?> </p> <div> - <?= nl2br(p::purify($item->description)) ?> + <?= nl2br(html::purify($item->description)) ?> </div> </a> </li> @@ -44,7 +44,7 @@ <? else: ?> <p> - <?= t("No results found for <b>%term</b>", array("term" => p::clean($q))) ?> + <?= t("No results found for <b>%term</b>", array("term" => $q)) ?> </p> <? endif; ?> diff --git a/modules/search/views/search_link.html.php b/modules/search/views/search_link.html.php index 3f1bca91..51bb4e14 100644 --- a/modules/search/views/search_link.html.php +++ b/modules/search/views/search_link.html.php @@ -6,7 +6,7 @@ <input type="text" name="q" id="gSearch"/> </li> <li> - <input type="submit" value="<?= t("Go") ?>" /> + <input type="submit" value="<?= t("Go")->for_html_attr() ?>" /> </li> </ul> </form> diff --git a/modules/server_add/controllers/admin_server_add.php b/modules/server_add/controllers/admin_server_add.php index 30109f42..fac2aa44 100644 --- a/modules/server_add/controllers/admin_server_add.php +++ b/modules/server_add/controllers/admin_server_add.php @@ -38,7 +38,7 @@ class Admin_Server_Add_Controller extends Admin_Controller { $path = $form->add_path->path->value; $paths[$path] = 1; module::set_var("server_add", "authorized_paths", serialize($paths)); - message::success(t("Added path %path", array("path" => p::clean($path)))); + message::success(t("Added path %path", array("path" => $path))); server_add::check_config($paths); url::redirect("admin/server_add"); } else { @@ -60,7 +60,7 @@ class Admin_Server_Add_Controller extends Admin_Controller { $paths = unserialize(module::get_var("server_add", "authorized_paths")); if (isset($paths[$path])) { unset($paths[$path]); - message::success(t("Removed path %path", array("path" => p::clean($path)))); + message::success(t("Removed path %path", array("path" => $path))); module::set_var("server_add", "authorized_paths", serialize($paths)); server_add::check_config($paths); } diff --git a/modules/server_add/controllers/server_add.php b/modules/server_add/controllers/server_add.php index 6056d7cd..26b3bd08 100644 --- a/modules/server_add/controllers/server_add.php +++ b/modules/server_add/controllers/server_add.php @@ -150,7 +150,8 @@ class Server_Add_Controller extends Admin_Controller { $queue[] = array($child, $entry->id); } else { $ext = strtolower(pathinfo($child, PATHINFO_EXTENSION)); - if (in_array($ext, array("gif", "jpeg", "jpg", "png", "flv", "mp4"))) { + if (in_array($ext, array("gif", "jpeg", "jpg", "png", "flv", "mp4")) && + filesize($child) > 0) { $child_entry = ORM::factory("server_add_file"); $child_entry->task_id = $task->id; $child_entry->file = $child; @@ -219,19 +220,25 @@ class Server_Add_Controller extends Admin_Controller { $album = album::create($parent, $name, $title, null, $owner_id); $entry->item_id = $album->id; } else { - $extension = strtolower(pathinfo($name, PATHINFO_EXTENSION)); - if (in_array($extension, array("gif", "png", "jpg", "jpeg"))) { - $photo = photo::create($parent, $entry->file, $name, $title, null, $owner_id); - $entry->item_id = $photo->id; - } else if (in_array($extension, array("flv", "mp4"))) { - $movie = movie::create($parent, $entry->file, $name, $title, null, $owner_id); - $entry->item_id = $movie->id; - } else { - // This should never happen, because we don't add stuff to the list that we can't - // process. But just in, case.. set this to a non-null value so that we skip this - // entry. + try { + $extension = strtolower(pathinfo($name, PATHINFO_EXTENSION)); + if (in_array($extension, array("gif", "png", "jpg", "jpeg"))) { + $photo = photo::create($parent, $entry->file, $name, $title, null, $owner_id); + $entry->item_id = $photo->id; + } else if (in_array($extension, array("flv", "mp4"))) { + $movie = movie::create($parent, $entry->file, $name, $title, null, $owner_id); + $entry->item_id = $movie->id; + } else { + // This should never happen, because we don't add stuff to the list that we can't + // process. But just in, case.. set this to a non-null value so that we skip this + // entry. + $entry->item_id = 0; + $task->log("Skipping unknown file type: $entry->file"); + } + } catch (Exception $e) { + // This can happen if a photo file is invalid, like a BMP masquerading as a .jpg $entry->item_id = 0; - $task->log("Skipping unknown file type: $entry->file"); + $task->log("Skipping invalid file: $entry->file"); } } @@ -239,7 +246,7 @@ class Server_Add_Controller extends Admin_Controller { $entry->save(); } $task->set("completed_files", $completed_files); - $task->status = t("Adding photos and albums (%completed of %total)", + $task->status = t("Adding photos / albums (%completed of %total)", array("completed" => $completed_files, "total" => $total_files)); $task->percent_complete = 10 + 100 * ($completed_files / $total_files); @@ -251,8 +258,8 @@ class Server_Add_Controller extends Admin_Controller { $task->state = "success"; $task->percent_complete = 100; ORM::factory("server_add_file")->where("task_id", $task->id)->delete_all(); - message::info(t2("Successfully added one photo", - "Successfully added %count photos and albums", + message::info(t2("Successfully added one photo / album", + "Successfully added %count photos / albums", $task->get("completed_files"))); } } diff --git a/modules/server_add/helpers/server_add.php b/modules/server_add/helpers/server_add.php index 74f51ad9..27794855 100644 --- a/modules/server_add/helpers/server_add.php +++ b/modules/server_add/helpers/server_add.php @@ -25,7 +25,7 @@ class server_add_Core { if (empty($paths)) { site_status::warning( t("Server Add needs configuration. <a href=\"%url\">Configure it now!</a>", - array("url" => url::site("admin/server_add"))), + array("url" => html::mark_clean(url::site("admin/server_add")))), "server_add_configuration"); } else { site_status::clear("server_add_configuration"); diff --git a/modules/akismet/helpers/akismet_menu.php b/modules/server_add/helpers/server_add_event.php index ebd948d6..b9dd8c28 100644 --- a/modules/akismet/helpers/akismet_menu.php +++ b/modules/server_add/helpers/server_add_event.php @@ -17,20 +17,25 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ -class akismet_menu_Core { - static function admin($menu, $theme) { +class server_add_event_Core { + static function admin_menu($menu, $theme) { $menu->get("settings_menu") ->append(Menu::factory("link") - ->id("akismet") - ->label(t("Akismet")) - ->url(url::site("admin/akismet"))); + ->id("server_add") + ->label(t("Server Add")) + ->url(url::site("admin/server_add"))); + } + + static function site_menu($menu, $theme) { + $item = $theme->item(); + $paths = unserialize(module::get_var("server_add", "authorized_paths")); - if (module::get_var("akismet", "api_key")) { - $menu->get("statistics_menu") - ->append(Menu::factory("link") - ->id("akismet") - ->label(t("Akismet")) - ->url(url::site("admin/akismet/stats"))); + if ($item && user::active()->admin && $item->is_album() && !empty($paths)) { + $menu->get("add_menu") + ->append(Menu::factory("dialog") + ->id("server_add") + ->label(t("Server add")) + ->url(url::site("server_add/browse/$item->id"))); } } } diff --git a/modules/server_add/helpers/server_add_installer.php b/modules/server_add/helpers/server_add_installer.php index cd278eb7..c3c1572d 100644 --- a/modules/server_add/helpers/server_add_installer.php +++ b/modules/server_add/helpers/server_add_installer.php @@ -27,7 +27,7 @@ class server_add_installer { `parent_id` int(9), `task_id` int(9) NOT NULL, PRIMARY KEY (`id`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); module::set_version("server_add", 3); server_add::check_config(); } @@ -40,7 +40,7 @@ class server_add_installer { `task_id` int(9) NOT NULL, `file` varchar(255) NOT NULL, PRIMARY KEY (`id`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); module::set_version("server_add", $version = 2); } diff --git a/modules/server_add/helpers/server_add_menu.php b/modules/server_add/helpers/server_add_menu.php deleted file mode 100644 index 0f01eb64..00000000 --- a/modules/server_add/helpers/server_add_menu.php +++ /dev/null @@ -1,64 +0,0 @@ -<?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 server_add_menu_Core { - static function admin($menu, $theme) { - $menu->get("settings_menu") - ->append(Menu::factory("link") - ->id("server_add") - ->label(t("Server Add")) - ->url(url::site("admin/server_add"))); - } - - static function site($menu, $theme) { - $item = $theme->item(); - $paths = unserialize(module::get_var("server_add", "authorized_paths")); - - if ($item && user::active()->admin && $item->is_album() && !empty($paths)) { - // This is a little tricky. Normally there's an "Add Photo" menu option, but we want to - // turn that into a dropdown if there are two different ways to add things. Do that in a - // portable way for now. If we find ourselves duplicating this pattern, we should make an - // API method for this. - $server_add = Menu::factory("dialog") - ->id("server_add") - ->label(t("Add from server")) - ->url(url::site("server_add/browse/$item->id")); - $add_photos_item = $menu->get("add_photos_item"); - $add_photos_menu = $menu->get("add_photos_menu"); - - if ($add_photos_item && !$add_photos_menu) { - // Assuming that $add_menu is unset, create add_menu and add our item - $menu->add_after( - "add_photos_item", - Menu::factory("submenu") - ->id("add_photos_menu") - ->label($add_photos_item->label) - ->append(Menu::factory("dialog") - ->id("add_photos_submenu_item") - ->label(t("Simple Uploader")) - ->url($add_photos_item->url)) - ->append($server_add)); - $menu->remove("add_photos_item"); - } else if ($add_photos_menu) { - // Append to the existing sub-menu - $add_photos_menu->append($server_add); - } - } - } -} 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/js/server_add.js b/modules/server_add/js/server_add.js index 989555cc..51ef41a7 100644 --- a/modules/server_add/js/server_add.js +++ b/modules/server_add/js/server_add.js @@ -4,11 +4,9 @@ function select_file(li) { $(li).toggleClass("selected"); if ($("#gServerAdd span.selected").length) { - $("#gServerAddAddButton").enable(true); - $("#gServerAddAddButton").removeClass("ui-state-disabled"); + $("#gServerAddAddButton").enable(true).removeClass("ui-state-disabled"); } else { - $("#gServerAddAddButton").enable(false); - $("#gServerAddAddButton").addClass("ui-state-disabled"); + $("#gServerAddAddButton").enable(false).addClass("ui-state-disabled"); } } @@ -26,9 +24,11 @@ function open_dir(path) { function start_add() { var paths = []; - $.each($("#gServerAdd span.selected"), function () { - paths.push($(this).attr("file")); - }); + $.each($("#gServerAdd span.selected"), + function () { + paths.push($(this).attr("file")); + } + ); $.ajax({ url: START_URL, @@ -54,7 +54,7 @@ function run_add(url) { $("#gStatus").html(data.status); $("#gServerAdd .gProgressBar").progressbar("value", data.percent_complete); if (data.done) { - $("#gProgress").slideUp(); + $("#gServerAddProgress").slideUp(); } else { setTimeout(function() { run_add(url); }, 0); } diff --git a/modules/server_add/views/admin_server_add.html.php b/modules/server_add/views/admin_server_add.html.php index 588a9fca..b48a19da 100644 --- a/modules/server_add/views/admin_server_add.html.php +++ b/modules/server_add/views/admin_server_add.html.php @@ -11,12 +11,12 @@ <ul id="gPathList"> <? foreach ($paths as $id => $path): ?> <li class="ui-icon-left"> - <a href="<?= url::site("admin/server_add/remove_path?path=$path&csrf=$csrf") ?>" + <a href="<?= url::site("admin/server_add/remove_path?path=" . urlencode($path) . "&csrf=$csrf") ?>" id="icon_<?= $id?>" class="gRemoveDir ui-icon ui-icon-trash"> X </a> - <?= $path ?> + <?= html::clean($path) ?> </li> <? endforeach ?> </ul> diff --git a/modules/server_add/views/server_add_tree.html.php b/modules/server_add/views/server_add_tree.html.php index 254a9da0..918fbdc7 100644 --- a/modules/server_add/views/server_add_tree.html.php +++ b/modules/server_add/views/server_add_tree.html.php @@ -9,8 +9,8 @@ <? foreach ($parents as $dir): ?> <li class="ui-icon-left"> <span class="ui-icon ui-icon-folder-open"></span> - <span ondblclick="open_dir('<?= $dir ?>')"> - <?= basename($dir) ?> + <span ondblclick='open_dir(<?= html::js_string($dir) ?>)'> + <?= html::clean(basename($dir)) ?> </span> <ul> <? endforeach ?> @@ -22,9 +22,9 @@ <? if (is_dir($file)): ?> ondblclick="open_dir($(this).attr('file'))" <? endif ?> - file="<?= $file ?>" + file="<?= html::clean_attribute($file) ?>" > - <?= p::clean(basename($file)) ?> + <?= html::clean(basename($file)) ?> </span> </li> <? endforeach ?> 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 21952849..8eb6e4df 100644 --- a/modules/server_add/views/server_add_tree_dialog.html.php +++ b/modules/server_add/views/server_add_tree_dialog.html.php @@ -5,17 +5,17 @@ </script> <div id="gServerAdd"> - <h1 style="display: none;"><?= t("Add Photos to '%title'", array("title" => p::purify($item->title))) ?></h1> + <h1 style="display: none;"><?= t("Add Photos to '%title'", array("title" => html::purify($item->title))) ?></h1> <p id="gDescription"><?= t("Photos will be added to album:") ?></p> <ul class="gBreadcrumbs"> <? foreach ($item->parents() as $parent): ?> <li> - <?= p::purify($parent->title) ?> + <?= html::purify($parent->title) ?> </li> <? endforeach ?> <li class="active"> - <?= p::purify($item->title) ?> + <?= html::purify($item->title) ?> </li> </ul> @@ -23,7 +23,7 @@ <?= $tree ?> </ul> - <div id="gProgress" style="display: none"> + <div id="gServerAddProgress" style="display: none"> <div class="gProgressBar"></div> <div id="gStatus"></div> </div> @@ -34,7 +34,7 @@ <?= t("Add") ?> </button> - <button class="ui-state-default ui-corner-all" onclick="closeDialog(); window.location.reload();"> + <button id="gServerCloseButton" class="ui-state-default ui-corner-all"> <?= t("Close") ?> </button> </span> @@ -46,7 +46,10 @@ $("#gServerAdd .gProgressBar"). progressbar(). progressbar("value", 0); - $("#gProgress").slideDown("fast", function() { start_add() }); + $("#gServerAddProgress").slideDown("fast", function() { start_add() }); + }); + $("#gServerCloseButton").click(function(event) { + $("#gDialog").dialog("close"); }); }); </script> diff --git a/modules/slideshow/helpers/slideshow_event.php b/modules/slideshow/helpers/slideshow_event.php index c6cd7dc7..ce26b189 100644 --- a/modules/slideshow/helpers/slideshow_event.php +++ b/modules/slideshow/helpers/slideshow_event.php @@ -23,10 +23,52 @@ class slideshow_event_Core { site_status::warning( t("The Slideshow module requires the RSS module. " . "<a href=\"%url\">Activate the RSS module now</a>", - array("url" => url::site("admin/modules"))), + array("url" => html::mark_clean(url::site("admin/modules")))), "slideshow_needs_rss"); } else { site_status::clear("slideshow_needs_rss"); } } + + static function album_menu($menu, $theme) { + $descendants_count = ORM::factory("item", $theme->item()->id) + ->descendants_count(array("type" => "photo")); + if ($descendants_count > 1) { + $menu->append(Menu::factory("link") + ->id("slideshow") + ->label(t("View slideshow")) + ->url("javascript:PicLensLite.start(" . + "{maxScale:0,feedUrl:'" . self::_feed_url($theme) . "'})") + ->css_id("gSlideshowLink")); + } + } + + static function photo_menu($menu, $theme) { + $menu->append(Menu::factory("link") + ->id("slideshow") + ->label(t("View slideshow")) + ->url("javascript:PicLensLite.start(" . + "{maxScale:0,feedUrl:'" . self::_feed_url($theme) . "'})") + ->css_id("gSlideshowLink")); + } + + static function tag_menu($menu, $theme) { + $menu->append(Menu::factory("link") + ->id("slideshow") + ->label(t("View slideshow")) + ->url("javascript:PicLensLite.start(" . + "{maxScale:0,feedUrl:'" . self::_feed_url($theme) . "'})") + ->css_id("gSlideshowLink")); + } + + private static function _feed_url($theme) { + if ($item = $theme->item()) { + if (!$item->is_album()) { + $item = $item->parent(); + } + return rss::url("gallery/album/{$item->id}?page_size=100"); + } else { + return rss::url("tag/tag/{$theme->tag()->id}?page_size=100"); + } + } } diff --git a/modules/slideshow/helpers/slideshow_installer.php b/modules/slideshow/helpers/slideshow_installer.php index cd1c6e05..56874a6a 100644 --- a/modules/slideshow/helpers/slideshow_installer.php +++ b/modules/slideshow/helpers/slideshow_installer.php @@ -18,10 +18,6 @@ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ class slideshow_installer { - static function install() { - module::set_version("slideshow", 1); - } - static function deactivate() { site_status::clear("slideshow_needs_rss"); } diff --git a/modules/slideshow/helpers/slideshow_menu.php b/modules/slideshow/helpers/slideshow_menu.php deleted file mode 100644 index ee975d88..00000000 --- a/modules/slideshow/helpers/slideshow_menu.php +++ /dev/null @@ -1,51 +0,0 @@ -<?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 slideshow_menu_Core { - static function album($menu, $theme) { - $menu - ->append(Menu::factory("link") - ->id("slideshow") - ->label(t("View slideshow")) - ->url("javascript:PicLensLite.start(" . - "{maxScale:0,feedUrl:PicLensLite.indexFeeds()[0].url})") - ->css_id("gSlideshowLink")); - } - - static function photo($menu, $theme) { - $menu - ->append(Menu::factory("link") - ->id("slideshow") - ->label(t("View slideshow")) - ->url("javascript:PicLensLite.start(" . - "{maxScale:0,feedUrl:PicLensLite.indexFeeds()[0].url})") - ->css_id("gSlideshowLink")); - } - - static function tag($menu, $theme) { - $menu - ->append(Menu::factory("link") - ->id("slideshow") - ->label(t("View slideshow")) - ->url("javascript:PicLensLite.start(" . - "{maxScale:0,feedUrl:PicLensLite.indexFeeds()[0].url})") - ->css_id("gSlideshowLink")); - } - -} diff --git a/modules/slideshow/helpers/slideshow_theme.php b/modules/slideshow/helpers/slideshow_theme.php index 125d175c..269a93ce 100644 --- a/modules/slideshow/helpers/slideshow_theme.php +++ b/modules/slideshow/helpers/slideshow_theme.php @@ -20,7 +20,7 @@ class slideshow_theme_Core { static function head($theme) { $proto = (empty($_SERVER["HTTPS"]) || $_SERVER["HTTPS"] === "off") ? "http" : "https"; - return "<script src=\"$proto://lite.piclens.com/current/piclens_optimized.js\"" . + return "<script src=\"$proto://lite.piclens.com/current/piclens_optimized.js\" " . "type=\"text/javascript\"></script>"; } } diff --git a/modules/tag/controllers/admin_tags.php b/modules/tag/controllers/admin_tags.php index dcdc16b9..8b8dde21 100644 --- a/modules/tag/controllers/admin_tags.php +++ b/modules/tag/controllers/admin_tags.php @@ -53,8 +53,8 @@ class Admin_Tags_Controller extends Admin_Controller { $name = $tag->name; Database::instance()->delete("items_tags", array("tag_id" => "$tag->id")); $tag->delete(); - message::success(t("Deleted tag %tag_name", array("tag_name" => p::clean($name)))); - log::success("tags", t("Deleted tag %tag_name", array("tag_name" => p::clean($name)))); + message::success(t("Deleted tag %tag_name", array("tag_name" => $name))); + log::success("tags", t("Deleted tag %tag_name", array("tag_name" => $name))); print json_encode( array("result" => "success", @@ -98,7 +98,7 @@ class Admin_Tags_Controller extends Admin_Controller { $tag->save(); $message = t("Renamed tag %old_name to %new_name", - array("old_name" => p::clean($old_name), "new_name" => p::clean($tag->name))); + array("old_name" => $old_name, "new_name" => $tag->name)); message::success($message); log::success("tags", $message); @@ -106,7 +106,7 @@ class Admin_Tags_Controller extends Admin_Controller { array("result" => "success", "location" => url::site("admin/tags"), "tag_id" => $tag->id, - "new_tagname" => p::clean($tag->name))); + "new_tagname" => html::clean($tag->name))); } else { print json_encode( array("result" => "error", diff --git a/modules/tag/controllers/tags.php b/modules/tag/controllers/tags.php index 85f6d16e..c993e374 100644 --- a/modules/tag/controllers/tags.php +++ b/modules/tag/controllers/tags.php @@ -53,7 +53,7 @@ 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); @@ -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("#,#", $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 7c4b56ba..be5461a4 100644 --- a/modules/tag/helpers/tag.php +++ b/modules/tag/helpers/tag.php @@ -79,6 +79,24 @@ class tag_Core { } } + + /** + * Return all the tags for a given item. + * @return array + */ + static function item_tags($item) { + $tags = array(); + foreach (Database::instance() + ->select("name") + ->from("tags") + ->join("items_tags", "tags.id", "items_tags.tag_id", "left") + ->where("items_tags.item_id", $item->id) + ->get() as $row) { + $tags[] = $row->name; + } + return $tags; + } + static function get_add_form($item) { $form = new Forge("tags", "", "post", array("id" => "gAddTagForm")); $label = $item->is_album() ? @@ -86,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; @@ -108,4 +126,24 @@ class tag_Core { $group->submit("")->value(t("Delete Tag")); return $form; } + + /** + * Delete all tags associated with an item + */ + static function clear_all($item) { + $db = Database::instance(); + $db->query("UPDATE {tags} SET `count` = `count` - 1 WHERE `count` > 0 " . + "AND `id` IN (SELECT `tag_id` from {items_tags} WHERE `item_id` = $item->id)"); + $db->delete("items_tags", array("item_id" => "$item->id")); + } + + /** + * Get rid of any tags that have no associated items. + */ + static function compact() { + // @todo There's a potential race condition here which we can solve by adding a lock around + // this and all the cases where we create/update tags. I'm loathe to do that since it's an + // extremely rare case. + Database::instance() ->delete("tags", array("count" => 0)); + } }
\ No newline at end of file diff --git a/modules/tag/helpers/tag_event.php b/modules/tag/helpers/tag_event.php index 7a170bf8..57986e40 100644 --- a/modules/tag/helpers/tag_event.php +++ b/modules/tag/helpers/tag_event.php @@ -34,8 +34,8 @@ class tag_event_Core { if (!empty($iptc["2#025"])) { foreach($iptc["2#025"] as $tag) { $tag = str_replace("\0", "", $tag); - foreach (preg_split("/[,;]/", $tag) as $word) { - $word = preg_replace('/\s+/', '.', trim($word)); + foreach (preg_split("/,/", $tag) as $word) { + $word = trim($word); if (function_exists("mb_detect_encoding") && mb_detect_encoding($word) != "UTF-8") { $word = utf8_encode($word); } @@ -59,12 +59,42 @@ class tag_event_Core { return; } - static function item_before_delete($item) { - $db = Database::instance(); - $db->query("UPDATE {tags} SET `count` = `count` - 1 WHERE `count` > 0 " . - "AND `id` IN (SELECT `tag_id` from {items_tags} WHERE `item_id` = $item->id)"); - $db->query("DELETE FROM {tags} WHERE `count` = 0 AND `id` IN (" . - "SELECT `tag_id` from {items_tags} WHERE `item_id` = $item->id)"); - $db->delete("items_tags", array("item_id" => "$item->id")); + static function item_deleted($item) { + tag::clear_all($item); + tag::compact(); + } + + static function item_edit_form($item, $form) { + $url = url::site("tags/autocomplete"); + $form->script("") + ->text("$('form input[id=tags]').ready(function() { + $('form input[id=tags]').autocomplete( + '$url', {max: 30, multiple: true, multipleSeparator: ',', cacheLength: 1}); + });"); + $tag_value = implode(", ", tag::item_tags($item)); + $form->edit_item->input("tags")->label(t("Tags (comma separated)")) + ->value($tag_value); + } + + static function item_edit_form_completed($item, $form) { + tag::clear_all($item); + foreach (preg_split("/,/", $form->edit_item->tags->value) as $tag_name) { + if ($tag_name) { + tag::add($item, trim($tag_name)); + } + } + tag::compact(); + } + + static function admin_menu($menu, $theme) { + $menu->get("content_menu") + ->append(Menu::factory("link") + ->id("tags") + ->label(t("Tags")) + ->url(url::site("admin/tags"))); + } + + static function item_index_data($item, $data) { + $data[] = join(" ", tag::item_tags($item)); } } diff --git a/modules/tag/helpers/tag_installer.php b/modules/tag/helpers/tag_installer.php index 3c16e3f3..bcb830e4 100644 --- a/modules/tag/helpers/tag_installer.php +++ b/modules/tag/helpers/tag_installer.php @@ -26,7 +26,7 @@ class tag_installer { `count` int(10) unsigned NOT NULL DEFAULT 0, PRIMARY KEY (`id`), UNIQUE KEY(`name`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); $db->query("CREATE TABLE IF NOT EXISTS {items_tags} ( `id` int(9) NOT NULL auto_increment, @@ -35,7 +35,7 @@ class tag_installer { PRIMARY KEY (`id`), KEY(`tag_id`, `id`), KEY(`item_id`, `id`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); module::set_version("tag", 1); } diff --git a/modules/tag/helpers/tag_menu.php b/modules/tag/helpers/tag_menu.php deleted file mode 100644 index e1b61a93..00000000 --- a/modules/tag/helpers/tag_menu.php +++ /dev/null @@ -1,28 +0,0 @@ -<?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 tag_menu_Core { - static function admin($menu, $theme) { - $menu->get("content_menu") - ->append(Menu::factory("link") - ->id("tags") - ->label(t("Tags")) - ->url(url::site("admin/tags"))); - } -} diff --git a/modules/tag/helpers/tag_rss.php b/modules/tag/helpers/tag_rss.php index f94508cf..de5d6c72 100644 --- a/modules/tag/helpers/tag_rss.php +++ b/modules/tag/helpers/tag_rss.php @@ -22,7 +22,7 @@ class tag_rss_Core { static function available_feeds($item, $tag) { if ($tag) { $feeds["tag/tag/{$tag->id}"] = - t("Tag feed for %tag_name", array("tag_name" => p::clean($tag->name))); + t("Tag feed for %tag_name", array("tag_name" => $tag->name)); return $feeds; } return array(); @@ -37,7 +37,6 @@ class tag_rss_Core { $feed->children = $tag->items($limit, $offset, "photo"); $feed->max_pages = ceil($tag->count / $limit); $feed->title = $tag->name; - $feed->link = url::abs_site("tags/{$tag->id}"); $feed->description = t("Photos related to %tag_name", array("tag_name" => $tag->name)); return $feed; 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..aaae9e72 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); }); } @@ -23,22 +23,28 @@ function closeEditInPlaceForms() { $("#gRenameTagForm").parent().html($("#gRenameTagForm").parent().data("revert")); li.height(""); $(".gEditable", li).bind("click", editInPlace); - $(".gDialogLink", li).bind("click", handleDialogEvent); + $(".gDialogLink", li).gallery_dialog(); } } +function str_replace(search_term, replacement, string) { + var temp = string.split(search_term); + return temp.join(replacement); +} + function editInPlace(element) { closeEditInPlaceForms(); // create edit form var tag_id = $(this).attr('id').substr(5); - var tag_name = $(this).text(); + var tag_name = $(this).html(); var tag_width = $(this).width(); $(this).parent().data("revert", $(this).parent().html()); var form = '<form id="gRenameTagForm" method="post" class="ui-helper-clearfix" '; form += 'action="' + TAG_RENAME_URL.replace('__ID__', tag_id) + '">'; form += '<input name="csrf" type="hidden" value="' + csrf_token + '" />'; - form += '<input id="name" name="name" type="text" class="textbox" value="' + tag_name + '" />'; + form += '<input id="name" name="name" type="text" class="textbox" value="' + + str_replace('"', """, tag_name) + '" />'; form += '<input type="submit" class="submit ui-state-default ui-corner-all" value="' + save_i18n + '" i/>'; form += '<a href="#">' + cancel_i18n + '</a>'; form += '</form>'; @@ -66,3 +72,4 @@ function editInPlace(element) { }; ajaxify_editInPlaceForm(); } + diff --git a/modules/tag/models/tag.php b/modules/tag/models/tag.php index 7a85dbab..d9488e1c 100644 --- a/modules/tag/models/tag.php +++ b/modules/tag/models/tag.php @@ -44,10 +44,62 @@ 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(); + } + + /** + * Overload ORM::save() to trigger an item_related_update event for all items that are related + * to this tag. Since items can be added or removed as part of the save, we need to trigger an + * event for the union of all related items before and after the save. + */ + public function save() { + $db = Database::instance(); + $related_item_ids = array(); + foreach ($db->getwhere("items_tags", array("tag_id" => $this->id)) as $row) { + $related_item_ids[$row->item_id] = 1; + } + + $result = parent::save(); + + foreach ($db->getwhere("items_tags", array("tag_id" => $this->id)) as $row) { + $related_item_ids[$row->item_id] = 1; + } + + if ($related_item_ids) { + foreach (ORM::factory("item")->in("id", array_keys($related_item_ids))->find_all() as $item) { + module::event("item_related_update", $item); + } + } + + return $result; + } + + /** + * Overload ORM::delete() to trigger an item_related_update event for all items that are + * related to this tag. + */ + public function delete() { + $related_item_ids = array(); + $db = Database::Instance(); + foreach ($db->getwhere("items_tags", array("tag_id" => $this->id)) as $row) { + $related_item_ids[$row->item_id] = 1; + } + + $result = parent::delete(); + + if ($related_item_ids) { + foreach (ORM::factory("item")->in("id", array_keys($related_item_ids))->find_all() as $item) { + module::event("item_related_update", $item); + } + } + return $result; } }
\ No newline at end of file diff --git a/modules/tag/views/admin_tags.html.php b/modules/tag/views/admin_tags.html.php index 7d201da7..8f3693aa 100644 --- a/modules/tag/views/admin_tags.html.php +++ b/modules/tag/views/admin_tags.html.php @@ -1,9 +1,9 @@ <?php defined("SYSPATH") or die("No direct script access.") ?> <script> - var TAG_RENAME_URL = "<?= url::site("admin/tags/rename/__ID__") ?>"; + var TAG_RENAME_URL = <?= html::js_string(url::site("admin/tags/rename/__ID__")) ?>; $("document").ready(function() { // using JS for adding link titles to avoid running t() for each tag - $("#gTagAdmin .tag-name").attr("title", "<?= t("Click to edit this tag") ?>"); + $("#gTagAdmin .tag-name").attr("title", <?= t("Click to edit this tag")->for_js() ?>); $("#gTagAdmin .delete-link").attr("title", $(".delete-link:first span").html()); // In-place editing for tag admin @@ -11,8 +11,8 @@ }); // make some values available within tag.js var csrf_token = "<?= $csrf ?>"; - var save_i18n = '<?= t("save") ?>'; - var cancel_i18n = '<?= t("cancel") ?>'; + var save_i18n = <?= html::js_string(t("save")->for_html_attr()) ?>; + var cancel_i18n = <?= html::js_string(t("cancel")->for_html_attr()) ?>; </script> <div class="gBlock"> <h2> @@ -32,7 +32,7 @@ <? $current_letter = strtoupper(mb_substr($tag->name, 0, 1)) ?> <? if ($i == 0): /* first letter */ ?> - <strong><?= $current_letter ?></strong> + <strong><?= html::clean($current_letter) ?></strong> <ul> <? elseif ($last_letter != $current_letter): /* new letter */ ?> <? if ($column_tag_count > $tags_per_column): /* new column */ ?> @@ -42,12 +42,12 @@ <? endif ?> </ul> - <strong><?= $current_letter ?></strong> + <strong><?= html::clean($current_letter) ?></strong> <ul> <? endif ?> <li> - <span id="gTag-<?= $tag->id ?>" class="gEditable tag-name"><?= p::clean($tag->name) ?></span> + <span id="gTag-<?= $tag->id ?>" class="gEditable tag-name"><?= html::clean($tag->name) ?></span> <span class="understate">(<?= $tag->count ?>)</span> <a href="<?= url::site("admin/tags/form_delete/$tag->id") ?>" class="gDialogLink delete-link gButtonLink"> diff --git a/modules/tag/views/tag_block.html.php b/modules/tag/views/tag_block.html.php index 9c8f3de5..59a4ef88 100644 --- a/modules/tag/views/tag_block.html.php +++ b/modules/tag/views/tag_block.html.php @@ -1,5 +1,17 @@ <?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, + multiple: true, + multipleSeparator: ',', + cacheLength: 1} + ); + }); +</script> +<div id="gTagCloud" title="<?= url::site("tags") ?>"> <?= $cloud ?> </div> <?= $form ?>
\ No newline at end of file diff --git a/modules/tag/views/tag_cloud.html.php b/modules/tag/views/tag_cloud.html.php index eba615fc..d6a0b5f8 100644 --- a/modules/tag/views/tag_cloud.html.php +++ b/modules/tag/views/tag_cloud.html.php @@ -3,7 +3,7 @@ <? foreach ($tags as $tag): ?> <li class="size<?=(int)(($tag->count / $max_count) * 7) ?>"> <span><?= $tag->count ?> photos are tagged with </span> - <a href="<?= url::site("tags/$tag->id") ?>"><?= p::clean($tag->name) ?></a> + <a href="<?= url::site("tags/$tag->id") ?>"><?= html::clean($tag->name) ?></a> </li> <? endforeach ?> </ul> diff --git a/modules/user/controllers/admin_users.php b/modules/user/controllers/admin_users.php index b5dc6cb5..521f82fa 100644 --- a/modules/user/controllers/admin_users.php +++ b/modules/user/controllers/admin_users.php @@ -48,9 +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(); - message::success(t("Created user %user_name", array("user_name" => p::clean($user->name)))); + module::event("user_add_form_admin_completed", $user, $form); + + message::success(t("Created user %user_name", array("user_name" => $user->name))); print json_encode(array("result" => "success")); } else { print json_encode(array("result" => "error", @@ -83,7 +84,7 @@ class Admin_Users_Controller extends Controller { "form" => $form->__toString())); } - $message = t("Deleted user %user_name", array("user_name" => p::clean($name))); + $message = t("Deleted user %user_name", array("user_name" => $name)); log::success("user", $message); message::success($message); print json_encode(array("result" => "success")); @@ -128,6 +129,7 @@ class Admin_Users_Controller extends Controller { $user->password = $form->edit_user->password->value; } $user->email = $form->edit_user->email->value; + $user->url = $form->edit_user->url->value; if ($form->edit_user->locale) { $desired_locale = $form->edit_user->locale->value; $user->locale = $desired_locale == "none" ? null : $desired_locale; @@ -138,8 +140,9 @@ class Admin_Users_Controller extends Controller { $user->admin = $form->edit_user->admin->checked; } $user->save(); + module::event("user_edit_form_admin_completed", $user, $form); - message::success(t("Changed user %user_name", array("user_name" => p::clean($user->name)))); + message::success(t("Changed user %user_name", array("user_name" => $user->name))); print json_encode(array("result" => "success")); } else { print json_encode(array("result" => "error", @@ -201,7 +204,7 @@ class Admin_Users_Controller extends Controller { $group = group::create($new_name); $group->save(); message::success( - t("Created group %group_name", array("group_name" => p::clean($group->name)))); + t("Created group %group_name", array("group_name" => $group->name))); print json_encode(array("result" => "success")); } else { print json_encode(array("result" => "error", @@ -230,7 +233,7 @@ class Admin_Users_Controller extends Controller { "form" => $form->__toString())); } - $message = t("Deleted group %group_name", array("group_name" => p::clean($name))); + $message = t("Deleted group %group_name", array("group_name" => $name)); log::success("group", $message); message::success($message); print json_encode(array("result" => "success")); @@ -268,11 +271,11 @@ class Admin_Users_Controller extends Controller { $group->name = $form->edit_group->inputs["name"]->value; $group->save(); message::success( - t("Changed group %group_name", array("group_name" => p::clean($group->name)))); + t("Changed group %group_name", array("group_name" => $group->name))); print json_encode(array("result" => "success")); } else { message::error( - t("Failed to change group %group_name", array("group_name" => p::clean($group->name)))); + t("Failed to change group %group_name", array("group_name" => $group->name))); print json_encode(array("result" => "error", "form" => $form->__toString())); } diff --git a/modules/user/controllers/login.php b/modules/user/controllers/login.php index 4d901051..8bee7db5 100644 --- a/modules/user/controllers/login.php +++ b/modules/user/controllers/login.php @@ -48,7 +48,7 @@ class Login_Controller extends Controller { list ($valid, $form) = $this->_auth("login/auth_html"); if ($valid) { - url::redirect("albums/1"); + url::redirect(item::root()->abs_url()); } else { print $form; } @@ -63,7 +63,7 @@ class Login_Controller extends Controller { log::warning( "user", t("Failed login for %name", - array("name" => p::clean($form->login->inputs["name"]->value)))); + array("name" => $form->login->inputs["name"]->value))); $form->login->inputs["name"]->add_error("invalid_login", 1); $valid = false; } @@ -71,7 +71,7 @@ class Login_Controller extends Controller { if ($valid) { user::login($user); - log::info("user", t("User %name logged in", array("name" => p::clean($user->name)))); + log::info("user", t("User %name logged in", array("name" => $user->name))); } // Either way, regenerate the session id to avoid session trapping diff --git a/modules/user/controllers/logout.php b/modules/user/controllers/logout.php index 63971789..45d397ad 100644 --- a/modules/user/controllers/logout.php +++ b/modules/user/controllers/logout.php @@ -19,18 +19,19 @@ */ class Logout_Controller extends Controller { public function index() { - access::verify_csrf(); + //access::verify_csrf(); $user = user::active(); user::logout(); - log::info("user", t("User %name logged out", array("name" => p::clean($user->name))), - html::anchor("user/$user->id", p::clean($user->name))); - if ($this->input->get("continue")) { - $item = url::get_item_from_uri($this->input->get("continue")); + log::info("user", t("User %name logged out", array("name" => $user->name)), + html::anchor("user/$user->id", html::clean($user->name))); + if ($continue_url = $this->input->get("continue")) { + $item = url::get_item_from_uri($continue_url); if (access::can("view", $item)) { - url::redirect($this->input->get("continue")); + // Don't use url::redirect() because it'll call url::site() and munge the continue url. + header("Location: $continue_url"); } else { - url::redirect(""); + url::redirect(item::root()->abs_url()); } } } diff --git a/modules/user/controllers/password.php b/modules/user/controllers/password.php index ed3b9736..92608dcd 100644 --- a/modules/user/controllers/password.php +++ b/modules/user/controllers/password.php @@ -29,8 +29,6 @@ class Password_Controller extends Controller { } public function do_reset() { - access::verify_csrf(); - if (request::method() == "post") { $this->_change_password(); } else { @@ -74,7 +72,7 @@ class Password_Controller extends Controller { log::success( "user", - t("Password reset email sent for user %name", array("name" => p::clean($user->name))); + t("Password reset email sent for user %name", array("name" => $user->name))); } else { // Don't include the username here until you're sure that it's XSS safe log::warning( @@ -132,7 +130,7 @@ class Password_Controller extends Controller { $user->hash = null; $user->save(); message::success(t("Password reset successfully")); - url::redirect("albums/1"); + url::redirect(item::root()->abs_url()); } else { print $view; } diff --git a/modules/user/controllers/users.php b/modules/user/controllers/users.php index 46f799c5..4ad704f0 100644 --- a/modules/user/controllers/users.php +++ b/modules/user/controllers/users.php @@ -36,9 +36,15 @@ class Users_Controller extends REST_Controller { $user->url = $form->edit_user->url->value; if ($form->edit_user->locale) { $desired_locale = $form->edit_user->locale->value; - $user->locale = $desired_locale == "none" ? null : $desired_locale; + $new_locale = $desired_locale == "none" ? null : $desired_locale; + if ($new_locale != $user->locale) { + // Delete the session based locale preference + setcookie("g_locale", "", time() - 24 * 3600, "/"); + } + $user->locale = $new_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/group.php b/modules/user/helpers/group.php index 1dace840..04e6efd6 100644 --- a/modules/user/helpers/group.php +++ b/modules/user/helpers/group.php @@ -39,7 +39,6 @@ class group_Core { $group->name = $name; $group->save(); - module::event("group_created", $group); return $group; } diff --git a/modules/user/helpers/user.php b/modules/user/helpers/user.php index a59588f8..b9162b92 100644 --- a/modules/user/helpers/user.php +++ b/modules/user/helpers/user.php @@ -34,13 +34,16 @@ class user_Core { ->matches($group->password); $group->input("email")->label(t("Email"))->id("gEmail")->value($user->email); $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, $form); + $group->submit("")->value(t("Save")); return $form; } static function get_edit_form_admin($user) { - $form = new Forge("admin/users/edit_user/$user->id", "", "post", array("id" => "gEditUserForm")); + $form = new Forge( + "admin/users/edit_user/$user->id", "", "post", array("id" => "gEditUserForm")); $group = $form->group("edit_user")->label(t("Edit User")); $group->input("name")->label(t("Username"))->id("gUsername")->value($user->name); $group->inputs["name"]->error_messages( @@ -53,9 +56,11 @@ class user_Core { $group->input("email")->label(t("Email"))->id("gEmail")->value($user->email); $group->input("url")->label(t("URL"))->id("gUrl")->value($user->url); $group->checkbox("admin")->label(t("Admin"))->id("gAdmin")->checked($user->admin); - $group->submit("")->value(t("Modify User")); $form->add_rules_from($user); $form->edit_user->password->rules("-required"); + + module::event("user_edit_form_admin", $user, $form); + $group->submit("")->value(t("Modify User")); return $form; } @@ -72,14 +77,19 @@ class user_Core { $group->input("url")->label(t("URL"))->id("gUrl"); self::_add_locale_dropdown($group); $group->checkbox("admin")->label(t("Admin"))->id("gAdmin"); - $group->submit("")->value(t("Add User")); $user = ORM::factory("user"); $form->add_rules_from($user); + + module::event("user_add_form_admin", $user, $form); + $group->submit("")->value(t("Add User")); return $form; } private static function _add_locale_dropdown(&$form, $user=null) { - $locales = locale::installed(); + $locales = locales::installed(); + foreach ($locales as $locale => $display_name) { + $locales[$locale] = SafeString::of_safe_html($display_name); + } if (count($locales) > 1) { // Put "none" at the first position in the array $locales = array_merge(array("" => t("« none »")), $locales); @@ -152,7 +162,12 @@ class user_Core { */ static function active() { // @todo (maybe) cache this object so we're not always doing session lookups. - $user = Session::instance()->get("user", self::guest()); + $user = Session::instance()->get("user", null); + if (!isset($user)) { + // Don't do this as a fallback in the Session::get() call because it can trigger unnecessary + // work. + $user = user::guest(); + } return $user; } @@ -202,7 +217,6 @@ class user_Core { $user->add(group::registered_users()); $user->save(); - module::event("user_created", $user); return $user; } @@ -325,4 +339,19 @@ class user_Core { } return $salt . md5($salt . $password); } + + static function cookie_locale() { + $cookie_data = Input::instance()->cookie("g_locale"); + $locale = null; + if ($cookie_data) { + if (preg_match("/^([a-z]{2,3}(?:_[A-Z]{2})?)$/", trim($cookie_data), $matches)) { + $requested_locale = $matches[1]; + $installed_locales = locales::installed(); + if (isset($installed_locales[$requested_locale])) { + $locale = $requested_locale; + } + } + } + return $locale; + } }
\ No newline at end of file diff --git a/modules/user/helpers/user_event.php b/modules/user/helpers/user_event.php index 6515fbfb..ede4e515 100644 --- a/modules/user/helpers/user_event.php +++ b/modules/user/helpers/user_event.php @@ -23,10 +23,30 @@ class user_event_Core { */ static function gallery_ready() { user::load_user(); + self::set_request_locale(); + } + + static function admin_menu($menu, $theme) { + $menu->add_after("appearance_menu", + Menu::factory("link") + ->id("users_groups") + ->label(t("Users/Groups")) + ->url(url::site("admin/users"))); + } - $locale = user::active()->locale; - if (!empty($locale)) { - // TODO(andy_st): Check session data as well. + static function set_request_locale() { + // 1. Check the session specific preference (cookie) + $locale = user::cookie_locale(); + // 2. Check the user's preference + if (!$locale) { + $locale = user::active()->locale; + } + // 3. Check the browser's / OS' preference + if (!$locale) { + $locale = locales::locale_from_http_request(); + } + // If we have any preference, override the site's default locale + if ($locale) { I18n::instance()->locale($locale); } } diff --git a/modules/user/helpers/user_installer.php b/modules/user/helpers/user_installer.php index 1959d038..8ef4f13d 100644 --- a/modules/user/helpers/user_installer.php +++ b/modules/user/helpers/user_installer.php @@ -36,7 +36,7 @@ class user_installer { PRIMARY KEY (`id`), UNIQUE KEY(`hash`), UNIQUE KEY(`name`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); $db->query("CREATE TABLE IF NOT EXISTS {groups} ( `id` int(9) NOT NULL auto_increment, @@ -44,14 +44,14 @@ class user_installer { `special` BOOLEAN default 0, PRIMARY KEY (`id`), UNIQUE KEY(`name`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); $db->query("CREATE TABLE IF NOT EXISTS {groups_users} ( `group_id` int(9) NOT NULL, `user_id` int(9) NOT NULL, PRIMARY KEY (`group_id`, `user_id`), UNIQUE KEY(`user_id`, `group_id`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); $everybody = group::create("Everybody"); $everybody->special = true; diff --git a/modules/user/helpers/user_menu.php b/modules/user/helpers/user_menu.php deleted file mode 100644 index 05e401f9..00000000 --- a/modules/user/helpers/user_menu.php +++ /dev/null @@ -1,28 +0,0 @@ -<?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 user_menu_Core { - static function admin($menu, $theme) { - $menu->add_after("appearance_menu", - Menu::factory("link") - ->id("users_groups") - ->label(t("Users/Groups")) - ->url(url::site("admin/users"))); - } -} diff --git a/modules/user/helpers/user_theme.php b/modules/user/helpers/user_theme.php index ad9d4c63..098d87fd 100644 --- a/modules/user/helpers/user_theme.php +++ b/modules/user/helpers/user_theme.php @@ -18,15 +18,36 @@ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ class user_theme_Core { + static function head($theme) { + if (count(locales::installed())) { + // Needed by the languages block + $theme->script("jquery.cookie.js"); + } + return ""; + } + static function header_top($theme) { - $view = new View("login.html"); - $view->user = user::active(); - return $view->render(); + if ($theme->page_type != "login") { + $view = new View("login.html"); + $view->user = user::active(); + return $view->render(); + } } - static function admin_head($theme) { - if (strpos(Router::$current_uri, "admin/users") !== false) { - $theme->script("lib/gallery.panel.js"); + static function sidebar_blocks($theme) { + $locales = locales::installed(); + foreach ($locales as $locale => $display_name) { + $locales[$locale] = SafeString::of_safe_html($display_name); + } + if (count($locales) > 1) { + $block = new Block(); + $block->css_id = "gUserLanguageBlock"; + $block->title = t("Language Preference"); + $block->content = new View("user_languages_block.html"); + $block->content->installed_locales = + array_merge(array("" => t("« none »")), $locales); + $block->content->selected = (string) user::cookie_locale(); + return $block; } } } diff --git a/modules/user/models/group.php b/modules/user/models/group.php index 45948887..8af78012 100644 --- a/modules/user/models/group.php +++ b/modules/user/models/group.php @@ -27,7 +27,22 @@ class Group_Model extends ORM { * @see ORM::delete() */ public function delete($id=null) { + $old = clone $this; module::event("group_before_delete", $this); parent::delete($id); + module::event("group_deleted", $old); + } + + public function save() { + if (!$this->loaded) { + $created = 1; + } + parent::save(); + if (isset($created)) { + module::event("group_created", $this); + } else { + module::event("group_updated", $this->original(), $this); + } + return $this; } }
\ No newline at end of file diff --git a/modules/user/models/user.php b/modules/user/models/user.php index b447892e..55562f34 100644 --- a/modules/user/models/user.php +++ b/modules/user/models/user.php @@ -25,6 +25,7 @@ class User_Model extends ORM { "full_name" => "length[0,255]", "email" => "valid_email|length[1,255]", "password" => "length[1,40]", + "url" => "valid_url", "locale" => "length[2,10]"); public function __set($column, $value) { @@ -44,8 +45,10 @@ class User_Model extends ORM { * @see ORM::delete() */ public function delete($id=null) { + $old = clone $this; module::event("user_before_delete", $this); parent::delete($id); + module::event("user_deleted", $old); } /** @@ -57,4 +60,26 @@ class User_Model extends ORM { return sprintf("http://www.gravatar.com/avatar/%s.jpg?s=%d&r=pg%s", md5($this->email), $size, $default ? "&d=" . urlencode($default) : ""); } + + public function save() { + if (!$this->loaded) { + $created = 1; + } + parent::save(); + if (isset($created)) { + module::event("user_created", $this); + } else { + module::event("user_updated", $this->original(), $this); + } + return $this; + } + + /** + * Return the best version of the user's name. Either their specified full name, or fall back + * to the user name. + * @return string + */ + public function display_name() { + return empty($this->full_name) ? $this->name : $this->full_name; + } }
\ No newline at end of file diff --git a/modules/user/views/admin_users.html.php b/modules/user/views/admin_users.html.php index b469f82d..c065e4b1 100644 --- a/modules/user/views/admin_users.html.php +++ b/modules/user/views/admin_users.html.php @@ -28,7 +28,7 @@ {}, function(data) { $("#group-" + group_id).html(data); - $("#group-" + group_id + " .gDialogLink").bind("click", handleDialogEvent); + $("#group-" + group_id + " .gDialogLink").gallery_dialog(); }); } @@ -44,7 +44,7 @@ <div class="gBlock"> <a href="<?= url::site("admin/users/add_user_form") ?>" class="gDialogLink gButtonLink right ui-icon-left ui-state-default ui-corner-all" - title="<?= t("Create a new user") ?>"> + title="<?= t("Create a new user")->for_html_attr() ?>"> <span class="ui-icon ui-icon-circle-plus"></span> <?= t("Add a new user") ?> </a> @@ -66,18 +66,18 @@ <? 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)) ?>" - title="<?= t("Drag user onto group below to add as a new member") ?>" - alt="<?= p::clean($user->name) ?>" + <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")->for_html_attr() ?>" + alt="<?= html::clean_attribute($user->name) ?>" width="20" height="20" /> - <?= p::clean($user->name) ?> + <?= html::clean($user->name) ?> </td> <td> - <?= p::clean($user->full_name) ?> + <?= html::clean($user->full_name) ?> </td> <td> - <?= p::clean($user->email) ?> + <?= html::clean($user->email) ?> </td> <td> <?= ($user->last_login == 0) ? "" : gallery::date($user->last_login) ?> @@ -92,7 +92,7 @@ class="gDialogLink gButtonLink ui-state-default ui-corner-all ui-icon-left"> <span class="ui-icon ui-icon-trash"></span><?= t("delete") ?></a> <? else: ?> - <span title="<?= t("This user cannot be deleted") ?>" + <span title="<?= t("This user cannot be deleted")->for_html_attr() ?>" class="gButtonLink ui-state-disabled ui-corner-all ui-icon-left"> <span class="ui-icon ui-icon-trash"></span><?= t("delete") ?></span> <? endif ?> @@ -106,7 +106,7 @@ <div id="gGroupAdmin" class="gBlock"> <a href="<?= url::site("admin/users/add_group_form") ?>" class="gDialogLink gButtonLink right ui-icon-left ui-state-default ui-corner-all" - title="<?= t("Create a new group") ?>"> + title="<?= t("Create a new group")->for_html_attr() ?>"> <span class="ui-icon ui-icon-circle-plus"></span> <?= t("Add a new group") ?> </a> diff --git a/modules/user/views/admin_users_group.html.php b/modules/user/views/admin_users_group.html.php index bfd79dba..476e0817 100644 --- a/modules/user/views/admin_users_group.html.php +++ b/modules/user/views/admin_users_group.html.php @@ -1,13 +1,13 @@ <?php defined("SYSPATH") or die("No direct script access.") ?> <h4> - <?= p::clean($group->name) ?> + <?= html::clean($group->name) ?> <? if (!$group->special): ?> <a href="<?= url::site("admin/users/delete_group_form/$group->id") ?>" - title="<?= t("Delete the %name group", array("name" => p::clean($group->name))) ?>" + title="<?= t("Delete the %name group", array("name" => $group->name))->for_html_attr() ?>" class="gDialogLink gButtonLink ui-state-default ui-corner-all"> <span class="ui-icon ui-icon-trash"><?= t("delete") ?></span></a> <? else: ?> - <a title="<?= t("This default group cannot be deleted") ?>" + <a title="<?= t("This default group cannot be deleted")->for_html_attr() ?>" class="gDialogLink gButtonLink ui-state-disabled ui-corner-all ui-icon-left"> <span class="ui-icon ui-icon-trash"><?= t("delete") ?></span></a> <? endif ?> @@ -17,12 +17,12 @@ <ul> <? foreach ($group->users as $i => $user): ?> <li class="gUser"> - <?= p::clean($user->name) ?> + <?= html::clean($user->name) ?> <? if (!$group->special): ?> <a href="javascript:remove_user(<?= $user->id ?>, <?= $group->id ?>)" class="gButtonLink ui-state-default ui-corner-all ui-icon-left" title="<?= t("Remove %user from %group group", - array("user" => p::clean($user->name), "group" => p::clean($group->name))) ?>"> + array("user" => $user->name, "group" => $group->name))->for_html_attr() ?>"> <span class="ui-icon ui-icon-closethick"><?= t("remove") ?></span> </a> <? endif ?> diff --git a/modules/user/views/login.html.php b/modules/user/views/login.html.php index 7617d131..bb670d51 100644 --- a/modules/user/views/login.html.php +++ b/modules/user/views/login.html.php @@ -3,19 +3,19 @@ <? if ($user->guest): ?> <li class="first"> <a href="<?= url::site("login/ajax") ?>" - title="<?= t("Login to Gallery") ?>" + title="<?= t("Login to Gallery")->for_html_attr() ?>" id="gLoginLink"><?= t("Login") ?></a> </li> <? else: ?> <li class="first"> - <?= t('Logged in as %name', array('name' => - '<a href="' . url::site("form/edit/users/{$user->id}") . - '" title="' . t("Edit Your Profile") . + <?= t('Logged in as %name', array('name' => html::mark_clean( + '<a href="' . url::site("form/edit/users/{$user->id}") . + '" title="' . t("Edit Your Profile")->for_html_attr() . '" id="gUserProfileLink" class="gDialogLink">' . - p::clean(empty($user->full_name) ? $user->name : $user->full_name) . '</a>')) ?> + html::clean($user->display_name()) . '</a>'))) ?> </li> <li> - <a href="<?= url::site("logout?csrf=$csrf&continue=" . url::current(true)) ?>" + <a href="<?= url::site("logout?csrf=$csrf&continue=" . urlencode(url::current(true))) ?>" id="gLogoutLink"><?= t("Logout") ?></a> </li> <? endif ?> diff --git a/modules/user/views/login_ajax.html.php b/modules/user/views/login_ajax.html.php index 56a6f111..56bc1cbd 100644 --- a/modules/user/views/login_ajax.html.php +++ b/modules/user/views/login_ajax.html.php @@ -6,7 +6,7 @@ url: "<?= url::site("password/reset") ?>", success: function(data) { $("div#gLoginView").html(data); - $("#ui-dialog-title-gDialog").text("<?= t("Reset Password") ?>"); + $("#ui-dialog-title-gDialog").html(<?= t("Reset Password")->for_js() ?>); ajaxify_login_reset_form(); } }); @@ -38,7 +38,7 @@ </div> </li> <li> - <a href="#" id="gForgotPasswordLink"><?= t("Forgot your Password?") ?></a> + <a href="#" id="gForgotPasswordLink"><?= t("Forgot Your Password?") ?></a> </li> </ul> </div> diff --git a/modules/user/views/reset_password.html.php b/modules/user/views/reset_password.html.php index 4c4672ee..92ca4917 100644 --- a/modules/user/views/reset_password.html.php +++ b/modules/user/views/reset_password.html.php @@ -6,10 +6,12 @@ <body> <h2><?= t("Password Reset Request") ?> </h2> <p> - <?= t("Hello, %name,", array("name" => p::clean($user->full_name ? $user->full_name : $user->name))) ?> + <?= t("Hello, %name,", array("name" => $user->full_name ? $user->full_name : $user->name)) ?> </p> <p> - <?= t("We received a request to reset your password for <a href=\"%site_url\">%site_url</a>. If you made this request, you can confirm it by <a href=\"%confirm_url\">clicking this link</a>. If you didn't request this password reset, it's ok to ignore this mail.", array("site_url" => url::base(false, "http"), "confirm_url" => $confirm_url)) ?> + <?= t("We received a request to reset your password for <a href=\"%site_url\">%site_url</a>. If you made this request, you can confirm it by <a href=\"%confirm_url\">clicking this link</a>. If you didn't request this password reset, it's ok to ignore this mail.", + array("site_url" => html::mark_clean(url::base(false, "http")), + "confirm_url" => $confirm_url)) ?> </p> </body> </html> diff --git a/modules/user/views/user_languages_block.html.php b/modules/user/views/user_languages_block.html.php new file mode 100644 index 00000000..b5ae674c --- /dev/null +++ b/modules/user/views/user_languages_block.html.php @@ -0,0 +1,19 @@ +<?php defined("SYSPATH") or die("No direct script access.") ?> +<?= form::dropdown("gSelectSessionLocale", $installed_locales, $selected) ?> +<script type="text/javascript"> + $("#gSelectSessionLocale").change(function() { + var old_locale_preference = <?= html::js_string($selected) ?>; + var locale = $(this).val(); + if (old_locale_preference == locale) { + return; + } + + var expires = -1; + if (locale) { + expires = 365; + } + $.cookie("g_locale", locale, {"expires": expires, "path": "/"}); + window.location.reload(true); + }); +</script> + diff --git a/modules/watermark/helpers/watermark_menu.php b/modules/watermark/helpers/watermark_event.php index bc3a4fed..45b410f9 100644 --- a/modules/watermark/helpers/watermark_menu.php +++ b/modules/watermark/helpers/watermark_event.php @@ -17,8 +17,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ -class watermark_menu_Core { - static function admin($menu, $theme) { +class watermark_event_Core { + static function admin_menu($menu, $theme) { $menu->get("content_menu") ->append( Menu::factory("link") diff --git a/modules/watermark/helpers/watermark_installer.php b/modules/watermark/helpers/watermark_installer.php index 705b89d4..b3e91044 100644 --- a/modules/watermark/helpers/watermark_installer.php +++ b/modules/watermark/helpers/watermark_installer.php @@ -30,7 +30,7 @@ class watermark_installer { `mime_type` varchar(64) default NULL, PRIMARY KEY (`id`), UNIQUE KEY(`name`)) - ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + DEFAULT CHARSET=utf8;"); @mkdir(VARPATH . "modules/watermark"); module::set_version("watermark", 1); diff --git a/modules/watermark/views/admin_watermarks.html.php b/modules/watermark/views/admin_watermarks.html.php index e83a7efa..ac69d21d 100644 --- a/modules/watermark/views/admin_watermarks.html.php +++ b/modules/watermark/views/admin_watermarks.html.php @@ -7,7 +7,7 @@ <? if (empty($name)): ?> <a href="<?= url::site("admin/watermarks/form_add") ?>" - title="<?= t("Upload a watermark") ?>" + title="<?= t("Upload a watermark")->for_html_attr() ?>" class="gDialogLink gButtonLink ui-icon-left ui-state-default ui-corner-all"><span class="ui-icon ui-icon-document-b"></span><?= t("Upload a watermark") ?></a> <? else: ?> <h2> <?= t("Active Watermark") ?> </h2> @@ -26,10 +26,10 @@ </div> <div class="controls"> <a href="<?= url::site("admin/watermarks/form_edit") ?>" - title="<?= t("Edit Watermark") ?>" + title="<?= t("Edit Watermark")->for_html_attr() ?>" class="gDialogLink gButtonLink ui-icon-left ui-state-default ui-corner-all"><span class="ui-icon ui-icon-pencil"></span><?= t("edit") ?></a> <a href="<?= url::site("admin/watermarks/form_delete") ?>" - title="<?= t("Delete Watermark") ?>" + title="<?= t("Delete Watermark")->for_html_attr() ?>" class="gDialogLink gButtonLink ui-icon-left ui-state-default ui-corner-all"><span class="ui-icon ui-icon-trash"></span><?= t("delete") ?></a> </div> </div> |