summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorTim Almdal <tnalmdal@shaw.ca>2010-02-28 15:38:39 -0800
committerTim Almdal <tnalmdal@shaw.ca>2010-02-28 15:38:39 -0800
commite3e72ca4da0375d88b86ba69b6596b10be164e23 (patch)
treef32855f9416252b474ab8d598a345fdcf1455b7d /modules
parentf28b80fcf43e02ca65f419eb6774321dc30a2a37 (diff)
parentfd94f4bec21a7deaa86d468da704a048d2be751e (diff)
Merge branch 'master' into talmdal_dev
Diffstat (limited to 'modules')
-rw-r--r--modules/gallery/controllers/admin_maintenance.php1
-rw-r--r--modules/gallery/controllers/l10n_client.php39
-rw-r--r--modules/gallery/helpers/access.php18
-rw-r--r--modules/gallery/helpers/gallery_block.php2
-rw-r--r--modules/gallery/helpers/gallery_theme.php2
-rw-r--r--modules/gallery/js/l10n_client.js20
-rw-r--r--modules/gallery/libraries/Admin_View.php1
-rw-r--r--modules/gallery/libraries/MY_Kohana_Exception.php57
-rw-r--r--modules/gallery/tests/Kohana_Exception_Test.php170
-rw-r--r--modules/gallery/views/kohana/error.php4
-rw-r--r--modules/user/controllers/password.php2
-rw-r--r--modules/user/controllers/users.php7
12 files changed, 295 insertions, 28 deletions
diff --git a/modules/gallery/controllers/admin_maintenance.php b/modules/gallery/controllers/admin_maintenance.php
index c16c5c41..6ef21d41 100644
--- a/modules/gallery/controllers/admin_maintenance.php
+++ b/modules/gallery/controllers/admin_maintenance.php
@@ -40,6 +40,7 @@ class Admin_Maintenance_Controller extends Admin_Controller {
}
$view = new Admin_View("admin.html");
+ $view->page_title = t("Maintenance tasks");
$view->content = new View("admin_maintenance.html");
$view->content->task_definitions = task::get_definitions();
$view->content->running_tasks = ORM::factory("task")
diff --git a/modules/gallery/controllers/l10n_client.php b/modules/gallery/controllers/l10n_client.php
index be0aaa11..084f88af 100644
--- a/modules/gallery/controllers/l10n_client.php
+++ b/modules/gallery/controllers/l10n_client.php
@@ -38,6 +38,7 @@ class L10n_Client_Controller extends Controller {
}
$is_plural = Gallery_I18n::is_plural_message(unserialize($root_message->message));
+ $is_empty = true;
if ($is_plural) {
$plural_forms = l10n_client::plural_forms($locale);
$translation = array();
@@ -47,9 +48,11 @@ class L10n_Client_Controller extends Controller {
throw new Exception("@todo bad request data");
}
$translation[$plural_form] = $value;
+ $is_empty = $is_empty && empty($value);
}
} else {
$translation = $input->post("l10n-edit-translation");
+ $is_empty = empty($translation);
if (null === $translation || !is_string($translation)) {
throw new Exception("@todo bad request data");
}
@@ -60,25 +63,31 @@ class L10n_Client_Controller extends Controller {
->where("locale", "=", $locale)
->find();
- if (!$entry->loaded()) {
- $entry->key = $key;
- $entry->locale = $locale;
- $entry->message = $root_message->message;
- $entry->base_revision = null;
- }
+ if ($is_empty) {
+ if ($entry->loaded()) {
+ $entry->delete();
+ }
+ } else {
+ if (!$entry->loaded()) {
+ $entry->key = $key;
+ $entry->locale = $locale;
+ $entry->message = $root_message->message;
+ $entry->base_revision = null;
+ }
- $entry->translation = serialize($translation);
+ $entry->translation = serialize($translation);
- $entry_from_incoming = ORM::factory("incoming_translation")
- ->where("key", "=", $key)
- ->where("locale", "=", $locale)
- ->find();
+ $entry_from_incoming = ORM::factory("incoming_translation")
+ ->where("key", "=", $key)
+ ->where("locale", "=", $locale)
+ ->find();
- if (!$entry_from_incoming->loaded()) {
- $entry->base_revision = $entry_from_incoming->revision;
- }
+ if (!$entry_from_incoming->loaded()) {
+ $entry->base_revision = $entry_from_incoming->revision;
+ }
- $entry->save();
+ $entry->save();
+ }
Gallery_I18n::clear_cache($locale);
diff --git a/modules/gallery/helpers/access.php b/modules/gallery/helpers/access.php
index 7e8b079a..af336798 100644
--- a/modules/gallery/helpers/access.php
+++ b/modules/gallery/helpers/access.php
@@ -637,8 +637,22 @@ class access_Core {
$dirs[] = dirname($album->thumb_path());
}
- $base_url = url::site("?kohana_uri=/file_proxy");
- $base_url = str_replace("/?", "?", $base_url);
+ $base_url = url::base(true);
+ $sep = "?";
+ if (strpos($base_url, "?") !== false) {
+ $sep = "&";
+ }
+ $base_url .= $sep . "kohana_uri=/file_proxy";
+ // Replace "/index.php/?kohana..." with "/index.php?koahan..."
+ // Doesn't apply to "/?kohana..." or "/foo/?kohana..."
+ // Can't check for "index.php" since the file might be renamed, and
+ // there might be more Apache aliases / rewrites at work.
+ $url_path = parse_url($base_url, PHP_URL_PATH);
+ // Does the URL path have a file component?
+ if (preg_match("#[^/]+\.php#i", $url_path)) {
+ $base_url = str_replace("/?", "?", $base_url);
+ }
+
foreach ($dirs as $dir) {
if ($value === self::DENY) {
$fp = fopen("$dir/.htaccess", "w+");
diff --git a/modules/gallery/helpers/gallery_block.php b/modules/gallery/helpers/gallery_block.php
index 46742743..eabdcebc 100644
--- a/modules/gallery/helpers/gallery_block.php
+++ b/modules/gallery/helpers/gallery_block.php
@@ -93,7 +93,7 @@ class gallery_block_Core {
case "language":
$locales = locales::installed();
- if (count($locales)) {
+ if (count($locales) > 1) {
foreach ($locales as $locale => $display_name) {
$locales[$locale] = SafeString::of_safe_html($display_name);
}
diff --git a/modules/gallery/helpers/gallery_theme.php b/modules/gallery/helpers/gallery_theme.php
index d6944323..7f2d4ec7 100644
--- a/modules/gallery/helpers/gallery_theme.php
+++ b/modules/gallery/helpers/gallery_theme.php
@@ -71,6 +71,7 @@ class gallery_theme_Core {
static function page_bottom($theme) {
$session = Session::instance();
if ($session->get("profiler", false)) {
+ Profiler::enable();
$profiler = new Profiler();
$profiler->render();
}
@@ -87,6 +88,7 @@ class gallery_theme_Core {
static function admin_page_bottom($theme) {
$session = Session::instance();
if ($session->get("profiler", false)) {
+ Profiler::enable();
$profiler = new Profiler();
$profiler->render();
}
diff --git a/modules/gallery/js/l10n_client.js b/modules/gallery/js/l10n_client.js
index d0d6f619..a1170e2d 100644
--- a/modules/gallery/js/l10n_client.js
+++ b/modules/gallery/js/l10n_client.js
@@ -124,7 +124,7 @@ jQuery.extend(Gallery, {
if (translation[form] == undefined) {
translation[form] = '';
}
- $('#l10n-edit-plural-translation-' + form)
+ $("#plural-" + form + " textarea[name='l10n-edit-plural-translation-" + form + "']")
.attr('value', translation[form]);
$('#plural-' + form).removeClass('hidden');
}
@@ -166,7 +166,7 @@ jQuery.extend(Gallery, {
if (form == 'one') {
text = source['one'];
}
- $('#l10n-edit-plural-translation-' + form)
+ $("#plural-" + form + " textarea[name='l10n-edit-plural-translation-" + form + "']")
.attr('value', text);
}
} else {
@@ -260,18 +260,26 @@ Gallery.behaviors.l10nClient = function(context) {
// Store translation in local js
var translation = {};
+ var is_non_empty = false;
if (is_plural) {
for (var i = 0; i < num_plural_forms; i++) {
var form = plural_forms[i];
- translation[form] = $('#g-l10n-client-save-form #l10n-edit-plural-translation-' + form).attr('value');
+ translation[form] = $("#plural-" + form + " textarea[name='l10n-edit-plural-translation-" + form + "']").attr('value');
+ is_non_empty = is_non_empty || translation[form];
}
} else {
translation = $('#l10n-edit-translation').attr('value');
+ is_non_empty = translation;
}
Gallery.l10nClient.setString(Gallery.l10nClient.selected, translation);
- // Mark message as translated.
- $('#l10n-client-string-select li').eq(Gallery.l10nClient.selected).removeClass('untranslated').removeClass('active').addClass('translated');
+ // Mark message as translated / untranslated.
+ var source_element = $('#l10n-client-string-select li').eq(Gallery.l10nClient.selected);
+ if (is_non_empty) {
+ source_element.removeClass('untranslated').removeClass('active').addClass('translated');
+ } else {
+ source_element.removeClass('active').removeClass('translated').addClass('untranslated');
+ }
// Clear the translation form fields
Gallery.l10nClient.showSourceMessage('', false);
@@ -279,7 +287,7 @@ Gallery.behaviors.l10nClient = function(context) {
for (var i = 0; i < num_plural_forms; i++) {
var form = plural_forms[i];
- $('#g-l10n-client-save-form #l10n-edit-plural-translation-' + form).val('');
+ $("#plural-" + form + " textarea[name='l10n-edit-plural-translation-" + form + "']").val('');
}
$("#g-l10n-client-save-form input[name='l10n-message-key']").val('');
},
diff --git a/modules/gallery/libraries/Admin_View.php b/modules/gallery/libraries/Admin_View.php
index e3f9dff0..f07bebf4 100644
--- a/modules/gallery/libraries/Admin_View.php
+++ b/modules/gallery/libraries/Admin_View.php
@@ -38,6 +38,7 @@ class Admin_View_Core extends Gallery_View {
$this->set_global("user", identity::active_user());
$this->set_global("page_type", "admin");
$this->set_global("page_subtype", $name);
+ $this->set_global("page_title", null);
}
public function admin_menu() {
diff --git a/modules/gallery/libraries/MY_Kohana_Exception.php b/modules/gallery/libraries/MY_Kohana_Exception.php
index d6f1f467..1712d895 100644
--- a/modules/gallery/libraries/MY_Kohana_Exception.php
+++ b/modules/gallery/libraries/MY_Kohana_Exception.php
@@ -92,4 +92,61 @@ class Kohana_Exception extends Kohana_Exception_Core {
}
print $view;
}
+
+ /**
+ * @see Kohana_Exception::dump()
+ */
+ public static function dump($value, $length=128, $max_level=5) {
+ return self::safe_dump($value, null, $length, $max_level);
+ }
+
+ /**
+ * A safer version of dump(), eliding sensitive information in the dumped
+ * data, such as session ids and passwords / hashes.
+ */
+ public static function safe_dump($value, $key, $length=128, $max_level=5) {
+ return parent::dump(self::_sanitize_for_dump($value, $key), $length, $max_level);
+ }
+
+ /**
+ * Elides sensitive data which shouldn't be echoed to the client,
+ * such as passwords, and other secrets.
+ */
+ /* Visible for testing*/ static function _sanitize_for_dump($value, $key=null) {
+ // Better elide too much than letting something through.
+ // Note: unanchored match is intended.
+ $sensitive_info_pattern =
+ '/(password|pass|email|hash|private_key|session_id|session|g3sid|csrf|secret)/i';
+ if (preg_match($sensitive_info_pattern, $key) ||
+ (is_string($value) && preg_match('/[a-f0-9]{20,}/i', $value))) {
+ return 'removed for display';
+ } else if (is_object($value)) {
+ if ($value instanceof Database) {
+ // Elide database password, host, name, user, etc.
+ return get_class($value) . ' object - details omitted for display';
+ } else if ($value instanceof User_Model) {
+ return get_class($value) . ' object for "' . $value->name . '" - details omitted for display';
+ }
+ return self::_sanitize_for_dump((array) $value, $key);
+ } else if (is_array($value)) {
+ $result = array();
+ foreach ($value as $k => $v) {
+ $actual_key = $k;
+ $key_for_display = $k;
+ if ($k[0] === "\x00") {
+ // Remove the access level from the variable name
+ $actual_key = substr($k, strrpos($k, "\x00") + 1);
+ $access = $k[1] === '*' ? 'protected' : 'private';
+ $key_for_display = "$access: $actual_key";
+ }
+ if (is_object($v)) {
+ $key_for_display .= ' (type: ' . get_class($v) . ')';
+ }
+ $result[$key_for_display] = self::_sanitize_for_dump($v, $actual_key);
+ }
+ } else {
+ $result = $value;
+ }
+ return $result;
+ }
} \ No newline at end of file
diff --git a/modules/gallery/tests/Kohana_Exception_Test.php b/modules/gallery/tests/Kohana_Exception_Test.php
new file mode 100644
index 00000000..d2dbb4dc
--- /dev/null
+++ b/modules/gallery/tests/Kohana_Exception_Test.php
@@ -0,0 +1,170 @@
+<?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 Kohana_Exception_Test extends Gallery_Unit_Test_Case {
+
+ public function dump_test() {
+ // Verify the override.
+ $this->assert_equal('<small>string</small><span>(19)</span> "removed for display"',
+ Kohana_Exception::dump("1a62761b836138c6198313911"));
+ $this->assert_equal('<small>string</small><span>(14)</span> "original value"',
+ Kohana_Exception::dump("original value"));
+ }
+
+ public function safe_dump_test() {
+ // Verify the delegation.
+ $this->assert_equal('<small>string</small><span>(19)</span> "removed for display"',
+ Kohana_Exception::safe_dump("original value", "password"));
+ $this->assert_equal('<small>string</small><span>(14)</span> "original value"',
+ Kohana_Exception::safe_dump("original value", "meow"));
+ }
+
+ public function sanitize_for_dump_match_key_test() {
+ $this->assert_equal("removed for display",
+ Kohana_Exception::_sanitize_for_dump("original value", "password"));
+ $this->assert_equal("original value",
+ Kohana_Exception::_sanitize_for_dump("original value", "meow"));
+ }
+
+ public function sanitize_for_dump_match_key_loosely_test() {
+ $this->assert_equal("removed for display",
+ Kohana_Exception::_sanitize_for_dump("original value", "this secret key"));
+ }
+
+ public function sanitize_for_dump_match_value_test() {
+ // Looks like a hash / secret value.
+ $this->assert_equal("removed for display",
+ Kohana_Exception::_sanitize_for_dump("p$2a178b841c6391d6368f131", "meow"));
+ $this->assert_equal("original value",
+ Kohana_Exception::_sanitize_for_dump("original value", "meow"));
+ }
+
+ public function sanitize_for_dump_array_test() {
+ $var = array("safe" => "original value 1",
+ "some hash" => "original value 2",
+ "three" => "2a3728788982938293b9292");
+ $expected = array("safe" => "original value 1",
+ "some hash" => "removed for display",
+ "three" => "removed for display");
+
+ $this->assert_equal($expected,
+ Kohana_Exception::_sanitize_for_dump($var, "ignored"));
+ }
+
+ public function sanitize_for_dump_nested_array_test() {
+ $var = array("safe" => "original value 1",
+ "safe 2" => array("some hash" => "original value 2"));
+ $expected = array("safe" => "original value 1",
+ "safe 2" => array("some hash" => "removed for display"));
+ $this->assert_equal($expected,
+ Kohana_Exception::_sanitize_for_dump($var, "ignored"));
+ }
+
+ public function sanitize_for_dump_user_test() {
+ $user = new User_Model();
+ $user->name = "john";
+ $user->hash = "value 1";
+ $user->email = "value 2";
+ $user->full_name = "value 3";
+ $this->assert_equal('User_Model object for "john" - details omitted for display',
+ Kohana_Exception::_sanitize_for_dump($user, "ignored"));
+ }
+
+ public function sanitize_for_dump_database_test() {
+ $db = new Kohana_Exception_Test_Database(
+ array("connection" => array("user" => "john", "name" => "gallery_3"),
+ "cache" => array()));
+ $this->assert_equal("Kohana_Exception_Test_Database object - details omitted for display",
+ Kohana_Exception::_sanitize_for_dump($db, "ignored"));
+ }
+
+ public function sanitize_for_dump_nested_database_test() {
+ $db = new Kohana_Exception_Test_Database(
+ array("connection" => array("user" => "john", "name" => "gallery_3"),
+ "cache" => array()));
+ $var = array("some" => "foo",
+ "bar" => $db);
+ $this->assert_equal(
+ array("some" => "foo",
+ "bar (type: Kohana_Exception_Test_Database)" =>
+ "Kohana_Exception_Test_Database object - details omitted for display"),
+ Kohana_Exception::_sanitize_for_dump($var, "ignored"));
+ }
+
+ public function sanitize_for_dump_object_test() {
+ $obj = new Kohana_Exception_Test_Class();
+ $obj->password = "original value";
+ $expected = array("var_1" => "val 1",
+ "protected: var_2" => "val 2",
+ "private: var_3" => "val 3",
+ "protected: hash" => "removed for display",
+ "private: email_address" => "removed for display",
+ "password" => "removed for display");
+ $this->assert_equal($expected,
+ Kohana_Exception::_sanitize_for_dump($obj, "ignored"));
+ }
+
+ public function sanitize_for_dump_nested_object_test() {
+ $user = new User_Model();
+ $user->name = "john";
+ $obj = new Kohana_Exception_Test_Class();
+ $obj->meow = new Kohana_Exception_Test_Class();
+ $obj->woof = "original value";
+ $obj->foo = array("bar" => $user);
+ $expected = array("var_1" => "val 1",
+ "protected: var_2" => "val 2",
+ "private: var_3" => "val 3",
+ "protected: hash" => "removed for display",
+ "private: email_address" => "removed for display",
+ "meow (type: Kohana_Exception_Test_Class)" =>
+ array("var_1" => "val 1",
+ "protected: var_2" => "val 2",
+ "private: var_3" => "val 3",
+ "protected: hash" => "removed for display",
+ "private: email_address" => "removed for display"),
+ "woof" => "original value",
+ "foo" => array("bar (type: User_Model)" =>
+ 'User_Model object for "john" - details omitted for display'));
+ $this->assert_equal($expected,
+ Kohana_Exception::_sanitize_for_dump($obj, "ignored"));
+ }
+}
+
+class Kohana_Exception_Test_Database extends Database {
+ function __construct($config) { parent::__construct($config); }
+ public function connect() {}
+ public function disconnect() {}
+ public function set_charset($charset) {}
+ public function query_execute($sql) {}
+ public function escape($value) {}
+ public function list_constraints($table) {}
+ public function list_fields($table) {}
+ public function list_tables() {}
+}
+
+class Kohana_Exception_Test_Class {
+ public $var_1 = "val 1";
+ protected $var_2 = "val 2";
+ private $var_3 = "val 3";
+ protected $hash = "val 4";
+ private $email_address = "val 5";
+ function __set($name, $val) {
+ $this->$name = $val;
+ }
+} \ No newline at end of file
diff --git a/modules/gallery/views/kohana/error.php b/modules/gallery/views/kohana/error.php
index 26628cf2..d55105a0 100644
--- a/modules/gallery/views/kohana/error.php
+++ b/modules/gallery/views/kohana/error.php
@@ -204,7 +204,7 @@
<pre><?= $name?></pre>
</td>
<td class="value">
- <pre><?= Kohana_Exception::dump($arg) ?></pre>
+ <pre><?= Kohana_Exception::safe_dump($arg, $name) ?></pre>
</td>
</tr>
<? endforeach?>
@@ -265,7 +265,7 @@
</code>
</td>
<td class="value">
- <pre><?= Kohana_Exception::dump($value) ?></pre>
+ <pre><?= Kohana_Exception::safe_dump($value, $key) ?></pre>
</td>
</tr>
<? endforeach?>
diff --git a/modules/user/controllers/password.php b/modules/user/controllers/password.php
index f5190974..38fa66be 100644
--- a/modules/user/controllers/password.php
+++ b/modules/user/controllers/password.php
@@ -52,7 +52,7 @@ class Password_Controller extends Controller {
$user_name = $form->reset->inputs["name"]->value;
$user = user::lookup_by_name($user_name);
if ($user && !empty($user->email)) {
- $user->hash = md5(rand());
+ $user->hash = md5(uniqid(mt_rand(), true));
$user->save();
$message = new View("reset_password.html");
$message->confirm_url = url::abs_site("password/do_reset?key=$user->hash");
diff --git a/modules/user/controllers/users.php b/modules/user/controllers/users.php
index cd7d271f..a5fdd994 100644
--- a/modules/user/controllers/users.php
+++ b/modules/user/controllers/users.php
@@ -30,7 +30,8 @@ class Users_Controller extends Controller {
$user->full_name = $form->edit_user->full_name->value;
$user->url = $form->edit_user->url->value;
- if ($user->locale != $form->edit_user->locale->value) {
+ if (count(locales::installed()) > 1 &&
+ $user->locale != $form->edit_user->locale->value) {
$user->locale = $form->edit_user->locale->value;
$flush_locale_cookie = true;
}
@@ -221,6 +222,10 @@ class Users_Controller extends Controller {
/** @todo combine with Admin_Users_Controller::_add_locale_dropdown */
private function _add_locale_dropdown(&$form, $user=null) {
$locales = locales::installed();
+ if (count($locales) <= 1) {
+ return;
+ }
+
foreach ($locales as $locale => $display_name) {
$locales[$locale] = SafeString::of_safe_html($display_name);
}