summaryrefslogtreecommitdiff
path: root/modules/gallery/libraries
diff options
context:
space:
mode:
Diffstat (limited to 'modules/gallery/libraries')
-rw-r--r--modules/gallery/libraries/Admin_View.php17
-rw-r--r--modules/gallery/libraries/Form_Script.php66
-rw-r--r--modules/gallery/libraries/Gallery_View.php73
-rw-r--r--modules/gallery/libraries/HtmlPurifier.php38
-rw-r--r--modules/gallery/libraries/I18n.php29
-rw-r--r--modules/gallery/libraries/MY_ORM.php33
-rw-r--r--modules/gallery/libraries/MY_View.php10
-rw-r--r--modules/gallery/libraries/Menu.php38
-rw-r--r--modules/gallery/libraries/ORM_MPTT.php143
-rw-r--r--modules/gallery/libraries/SafeString.php162
-rw-r--r--modules/gallery/libraries/Sendmail.php4
-rw-r--r--modules/gallery/libraries/Theme_View.php62
12 files changed, 453 insertions, 222 deletions
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/HtmlPurifier.php b/modules/gallery/libraries/HtmlPurifier.php
deleted file mode 100644
index daa5896e..00000000
--- a/modules/gallery/libraries/HtmlPurifier.php
+++ /dev/null
@@ -1,38 +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 HtmlPurifier_Core {
- private static $_instance;
-
- 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);
- }
-
- return self::$_instance;
- }
-}
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("'"=>"&#039;",
+ '"'=>'&quot;'));
+ }
+
+ /**
+ * 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":