summaryrefslogtreecommitdiff
path: root/modules/gallery/libraries
diff options
context:
space:
mode:
Diffstat (limited to 'modules/gallery/libraries')
-rw-r--r--modules/gallery/libraries/Gallery_I18n.php72
-rw-r--r--modules/gallery/libraries/IdentityProvider.php5
-rw-r--r--modules/gallery/libraries/MY_Kohana_Exception.php116
-rw-r--r--modules/gallery/libraries/Menu.php30
-rw-r--r--modules/gallery/libraries/drivers/Cache/Database.php14
-rw-r--r--modules/gallery/libraries/drivers/IdentityProvider.php2
6 files changed, 211 insertions, 28 deletions
diff --git a/modules/gallery/libraries/Gallery_I18n.php b/modules/gallery/libraries/Gallery_I18n.php
index cfed046a..f1e77744 100644
--- a/modules/gallery/libraries/Gallery_I18n.php
+++ b/modules/gallery/libraries/Gallery_I18n.php
@@ -73,12 +73,26 @@ class Gallery_I18n_Core {
public function locale($locale=null) {
if ($locale) {
$this->_config['default_locale'] = $locale;
- // Attempt to set PHP's locale as well (for number formatting, collation, etc.)
- // TODO: See G2 for better fallack code.
- $locale_prefs = array($locale);
- $locale_prefs[] = 'en_US';
- $new_locale = setlocale(LC_ALL, $locale_prefs);
- if (is_string($new_locale) && strpos($new_locale, 'tr') === 0) {
+ $php_locale = setlocale(LC_ALL, 0);
+ list ($php_locale, $unused) = explode('.', $php_locale . '.');
+ if ($php_locale != $locale) {
+ // Attempt to set PHP's locale as well (for number formatting, collation, etc.)
+ $locale_prefs = array($locale);
+ // Try appending some character set names; some systems (like FreeBSD) need this.
+ // Some systems require a format with hyphen (eg. Gentoo) and others without (eg. FreeBSD).
+ $charsets = array('utf8', 'UTF-8', 'UTF8', 'ISO8859-1', 'ISO-8859-1');
+ if (substr($locale, 0, 2) != 'en') {
+ $charsets = array_merge($charsets, array(
+ 'EUC', 'Big5', 'euc', 'ISO8859-2', 'ISO8859-5', 'ISO8859-7',
+ 'ISO8859-9', 'ISO-8859-2', 'ISO-8859-5', 'ISO-8859-7', 'ISO-8859-9'));
+ }
+ foreach ($charsets as $charset) {
+ $locale_prefs[] = $locale . '.' . $charset;
+ }
+ $locale_prefs[] = 'en_US';
+ $php_locale = setlocale(LC_ALL, $locale_prefs);
+ }
+ if (is_string($php_locale) && substr($php_locale, 0, 2) == 'tr') {
// Make PHP 5 work with Turkish (the localization results are mixed though).
// Hack for http://bugs.php.net/18556
setlocale(LC_CTYPE, 'C');
@@ -136,33 +150,44 @@ class Gallery_I18n_Core {
private function lookup($locale, $message) {
if (!isset($this->_cache[$locale])) {
- $this->_cache[$locale] = array();
- // TODO: Load data from locale file instead of the DB.
+ $this->_cache[$locale] = self::load_translations($locale);
+ }
+
+ $key = self::get_message_key($message);
+
+ if (isset($this->_cache[$locale][$key])) {
+ return $this->_cache[$locale][$key];
+ } else {
+ return null;
+ }
+ }
+
+ private static function load_translations($locale) {
+ $cache_key = "translation|" . $locale;
+ $cache = Cache::instance();
+ $translations = $cache->get($cache_key);
+ if (!isset($translations) || !is_array($translations)) {
+ $translations = array();
foreach (db::build()
->select("key", "translation")
->from("incoming_translations")
->where("locale", "=", $locale)
->execute() as $row) {
- $this->_cache[$locale][$row->key] = unserialize($row->translation);
+ $translations[$row->key] = unserialize($row->translation);
}
-
+
// Override incoming with outgoing...
foreach (db::build()
->select("key", "translation")
->from("outgoing_translations")
->where("locale", "=", $locale)
->execute() as $row) {
- $this->_cache[$locale][$row->key] = unserialize($row->translation);
+ $translations[$row->key] = unserialize($row->translation);
}
+
+ $cache->set($cache_key, $translations, array("translation"), 0);
}
-
- $key = self::get_message_key($message);
-
- if (isset($this->_cache[$locale][$key])) {
- return $this->_cache[$locale][$key];
- } else {
- return null;
- }
+ return $translations;
}
public function has_translation($message, $options=null) {
@@ -242,6 +267,15 @@ class Gallery_I18n_Core {
return $this->_call_log;
}
+ public static function clear_cache($locale=null) {
+ $cache = Cache::instance();
+ if ($locale) {
+ $cache->delete("translation|" . $locale);
+ } else {
+ $cache->delete_tag("translation");
+ }
+ }
+
private static function get_plural_key($locale, $count) {
$parts = explode('_', $locale);
$language = $parts[0];
diff --git a/modules/gallery/libraries/IdentityProvider.php b/modules/gallery/libraries/IdentityProvider.php
index 3f1666eb..01ea9ad7 100644
--- a/modules/gallery/libraries/IdentityProvider.php
+++ b/modules/gallery/libraries/IdentityProvider.php
@@ -66,6 +66,11 @@ class IdentityProvider_Core {
}
static function change_provider($new_provider) {
+ if (!identity::active_user()->admin && PHP_SAPI != "cli") {
+ // Below, the active user is set to the primary admin.
+ access::forbidden();
+ }
+
$current_provider = module::get_var("gallery", "identity_provider");
if (!empty($current_provider)) {
module::uninstall($current_provider);
diff --git a/modules/gallery/libraries/MY_Kohana_Exception.php b/modules/gallery/libraries/MY_Kohana_Exception.php
index 1c40091a..1712d895 100644
--- a/modules/gallery/libraries/MY_Kohana_Exception.php
+++ b/modules/gallery/libraries/MY_Kohana_Exception.php
@@ -33,6 +33,120 @@ class Kohana_Exception extends Kohana_Exception_Core {
if ($e instanceof ORM_Validation_Exception) {
Kohana_Log::add("error", "Validation errors: " . print_r($e->validation->errors(), 1));
}
- return parent::handle($e);
+ try {
+ $user = identity::active_user();
+ $try_themed_view = $user && !$user->admin;
+ } catch (Exception $e2) {
+ $try_themed_view = false;
+ }
+
+ if ($try_themed_view) {
+ try {
+ return self::_show_themed_error_page($e);
+ } catch (Exception $e3) {
+ Kohana_Log::add("error", "Exception in exception handling code: " . self::text($e3));
+ return parent::handle($e);
+ }
+ } else {
+ return parent::handle($e);
+ }
+ }
+
+ /**
+ * Shows a themed error page.
+ * @see Kohana_Exception::handle
+ */
+ private static function _show_themed_error_page(Exception $e) {
+ // Create a text version of the exception
+ $error = Kohana_Exception::text($e);
+
+ // Add this exception to the log
+ Kohana_Log::add('error', $error);
+
+ // Manually save logs after exceptions
+ Kohana_Log::save();
+
+ if (!headers_sent()) {
+ if ($e instanceof Kohana_Exception) {
+ $e->sendHeaders();
+ } else {
+ header("HTTP/1.1 500 Internal Server Error");
+ }
+ }
+
+ $view = new Theme_View("page.html", "other", "error");
+ if ($e instanceof Kohana_404_Exception) {
+ $view->page_title = t("Dang... Page not found!");
+ $view->content = new View("error_404.html");
+ $user = identity::active_user();
+ $view->content->is_guest = $user && $user->guest;
+ if ($view->content->is_guest) {
+ $view->content->login_form = new View("login_ajax.html");
+ $view->content->login_form->form = auth::get_login_form("login/auth_html");
+ // Avoid anti-phishing protection by passing the url as session variable.
+ Session::instance()->set("continue_url", url::current(true));
+ }
+ } else {
+ $view->page_title = t("Dang... Something went wrong!");
+ $view->content = new View("error.html");
+ }
+ 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/libraries/Menu.php b/modules/gallery/libraries/Menu.php
index e2b68d1a..fef07916 100644
--- a/modules/gallery/libraries/Menu.php
+++ b/modules/gallery/libraries/Menu.php
@@ -184,7 +184,7 @@ class Menu_Core extends Menu_Element {
}
/**
- * Add a new element to this menu
+ * Add a new element to this menu, after the specific element
*/
public function add_after($target_id, $new_menu_element) {
$copy = array();
@@ -199,6 +199,21 @@ class Menu_Core extends Menu_Element {
}
/**
+ * Add a new element to this menu, before the specific element
+ */
+ public function add_before($target_id, $new_menu_element) {
+ $copy = array();
+ foreach ($this->elements as $id => $menu_element) {
+ if ($id == $target_id) {
+ $copy[$new_menu_element->id] = $new_menu_element;
+ }
+ $copy[$id] = $menu_element;
+ }
+ $this->elements = $copy;
+ return $this;
+ }
+
+ /**
* Remove an element from the menu
*/
public function remove($target_id) {
@@ -216,6 +231,19 @@ class Menu_Core extends Menu_Element {
return null;
}
+ public function is_empty() {
+ foreach ($this->elements as $element) {
+ if ($element instanceof Menu) {
+ if (!$element->is_empty()) {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+ return true;
+ }
+
public function render() {
$view = new View(isset($this->view) ? $this->view : "menu.html");
$view->menu = $this;
diff --git a/modules/gallery/libraries/drivers/Cache/Database.php b/modules/gallery/libraries/drivers/Cache/Database.php
index 82a09ab9..ff982396 100644
--- a/modules/gallery/libraries/drivers/Cache/Database.php
+++ b/modules/gallery/libraries/drivers/Cache/Database.php
@@ -130,7 +130,7 @@ class Cache_Database_Driver extends Cache_Driver {
// Make sure the expiration is valid and that the hash matches
if ($cache->expiration != 0 && $cache->expiration <= time()) {
// Cache is not valid, delete it now
- $this->delete($cache->id);
+ $this->delete(array($cache->id));
} else {
// Disable notices for unserializing
$ER = error_reporting(~E_NOTICE);
@@ -153,15 +153,17 @@ class Cache_Database_Driver extends Cache_Driver {
* @param bool delete a tag
* @return bool
*/
- public function delete($id, $tag=false) {
+ public function delete($keys, $is_tag=false) {
$db = db::build()
->delete("caches");
- if ($id === true) {
+ if ($keys === true) {
// Delete all caches
- } else if ($tag === true) {
- $db->where("tags", "LIKE", "%<$id>%");
+ } else if ($is_tag === true) {
+ foreach ($keys as $tag) {
+ $db->where("tags", "LIKE", "%<$tag>%");
+ }
} else {
- $db->where("key", "=", $id);
+ $db->where("key", "IN", $keys);
}
$status = $db->execute();
diff --git a/modules/gallery/libraries/drivers/IdentityProvider.php b/modules/gallery/libraries/drivers/IdentityProvider.php
index b7b1fbe8..09cdd093 100644
--- a/modules/gallery/libraries/drivers/IdentityProvider.php
+++ b/modules/gallery/libraries/drivers/IdentityProvider.php
@@ -26,7 +26,7 @@ interface IdentityProvider_Driver {
public function guest();
/**
- * Return the admins user.
+ * Return the primary admin user.
*
* @return User_Definition the user object
*/