summaryrefslogtreecommitdiff
path: root/modules/gallery/controllers
diff options
context:
space:
mode:
Diffstat (limited to 'modules/gallery/controllers')
-rw-r--r--modules/gallery/controllers/admin.php94
-rw-r--r--modules/gallery/controllers/admin_advanced_settings.php57
-rw-r--r--modules/gallery/controllers/admin_dashboard.php97
-rw-r--r--modules/gallery/controllers/admin_graphics.php50
-rw-r--r--modules/gallery/controllers/admin_languages.php135
-rw-r--r--modules/gallery/controllers/admin_maintenance.php243
-rw-r--r--modules/gallery/controllers/admin_modules.php119
-rw-r--r--modules/gallery/controllers/admin_movies.php72
-rw-r--r--modules/gallery/controllers/admin_sidebar.php69
-rw-r--r--modules/gallery/controllers/admin_theme_options.php120
-rw-r--r--modules/gallery/controllers/admin_themes.php80
-rw-r--r--modules/gallery/controllers/admin_upgrade_checker.php57
-rw-r--r--modules/gallery/controllers/albums.php207
-rw-r--r--modules/gallery/controllers/combined.php96
-rw-r--r--modules/gallery/controllers/file_proxy.php174
-rw-r--r--modules/gallery/controllers/items.php43
-rw-r--r--modules/gallery/controllers/l10n_client.php179
-rw-r--r--modules/gallery/controllers/login.php90
-rw-r--r--modules/gallery/controllers/logout.php29
-rw-r--r--modules/gallery/controllers/movies.php91
-rw-r--r--modules/gallery/controllers/packager.php191
-rw-r--r--modules/gallery/controllers/permissions.php91
-rw-r--r--modules/gallery/controllers/photos.php91
-rw-r--r--modules/gallery/controllers/quick.php144
-rw-r--r--modules/gallery/controllers/reauthenticate.php105
-rw-r--r--modules/gallery/controllers/upgrader.php118
-rw-r--r--modules/gallery/controllers/uploader.php133
-rw-r--r--modules/gallery/controllers/user_profile.php108
-rw-r--r--modules/gallery/controllers/welcome_message.php30
29 files changed, 3113 insertions, 0 deletions
diff --git a/modules/gallery/controllers/admin.php b/modules/gallery/controllers/admin.php
new file mode 100644
index 0000000..b35a929
--- /dev/null
+++ b/modules/gallery/controllers/admin.php
@@ -0,0 +1,94 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 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 Admin_Controller extends Controller {
+ private $theme;
+
+ public function __construct($theme=null) {
+ if (!identity::active_user()->admin) {
+ if (identity::active_user()->guest) {
+ Session::instance()->set("continue_url", url::abs_current(true));
+ url::redirect("login");
+ } else {
+ access::forbidden();
+ }
+ }
+
+ parent::__construct();
+ }
+
+ public function __call($controller_name, $args) {
+ if (Input::instance()->get("reauth_check")) {
+ return self::_reauth_check();
+ }
+ if (auth::must_reauth_for_admin_area()) {
+ return self::_prompt_for_reauth($controller_name, $args);
+ }
+
+ if (request::method() == "post") {
+ access::verify_csrf();
+ }
+
+ if ($controller_name == "index") {
+ $controller_name = "dashboard";
+ }
+ $controller_name = "Admin_{$controller_name}_Controller";
+ if ($args) {
+ $method = array_shift($args);
+ } else {
+ $method = "index";
+ }
+
+ if (!class_exists($controller_name) || !method_exists($controller_name, $method)) {
+ throw new Kohana_404_Exception();
+ }
+
+ call_user_func_array(array(new $controller_name, $method), $args);
+ }
+
+ private static function _reauth_check() {
+ $session = Session::instance();
+ $last_active_auth = $session->get("active_auth_timestamp", 0);
+ $last_admin_area_activity = $session->get("admin_area_activity_timestamp", 0);
+ $admin_area_timeout = module::get_var("gallery", "admin_area_timeout");
+
+ $time_remaining = max($last_active_auth, $last_admin_area_activity) +
+ $admin_area_timeout - time();
+
+ $result = new stdClass();
+ $result->result = "success";
+ if ($time_remaining < 30) {
+ message::success(t("Automatically logged out of the admin area for your security"));
+ $result->location = url::abs_site("");
+ }
+
+ json::reply($result);
+ }
+
+ private static function _prompt_for_reauth($controller_name, $args) {
+ if (request::method() == "get") {
+ // Avoid anti-phishing protection by passing the url as session variable.
+ Session::instance()->set("continue_url", url::abs_current(true));
+ }
+ // Save the is_ajax value as we lose it, if set, when we redirect
+ Session::instance()->set("is_ajax_request", request::is_ajax());
+ url::redirect("reauthenticate");
+ }
+}
+
diff --git a/modules/gallery/controllers/admin_advanced_settings.php b/modules/gallery/controllers/admin_advanced_settings.php
new file mode 100644
index 0000000..267ff14
--- /dev/null
+++ b/modules/gallery/controllers/admin_advanced_settings.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-2013 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 Admin_Advanced_Settings_Controller extends Admin_Controller {
+ public function index() {
+ $view = new Admin_View("admin.html");
+ $view->page_title = t("Advanced settings");
+ $view->content = new View("admin_advanced_settings.html");
+ $view->content->vars = ORM::factory("var")
+ ->order_by("module_name")
+ ->order_by("name")
+ ->find_all();
+ print $view;
+ }
+
+ public function edit($module_name, $var_name) {
+ if (module::is_installed($module_name)) {
+ $value = module::get_var($module_name, $var_name);
+ $form = new Forge("admin/advanced_settings/save/$module_name/$var_name", "", "post");
+ $group = $form->group("edit_var")->label(t("Edit setting"));
+ $group->input("module_name")->label(t("Module"))->value($module_name)->disabled(1);
+ $group->input("var_name")->label(t("Setting"))->value($var_name)->disabled(1);
+ $group->textarea("value")->label(t("Value"))->value($value);
+ $group->submit("")->value(t("Save"));
+ print $form;
+ }
+ }
+
+ public function save($module_name, $var_name) {
+ access::verify_csrf();
+
+ if (module::is_installed($module_name)) {
+ module::set_var($module_name, $var_name, Input::instance()->post("value"));
+ message::success(
+ t("Saved value for %var (%module_name)",
+ array("var" => $var_name, "module_name" => $module_name)));
+
+ json::reply(array("result" => "success"));
+ }
+ }
+}
diff --git a/modules/gallery/controllers/admin_dashboard.php b/modules/gallery/controllers/admin_dashboard.php
new file mode 100644
index 0000000..5317210
--- /dev/null
+++ b/modules/gallery/controllers/admin_dashboard.php
@@ -0,0 +1,97 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 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 Admin_Dashboard_Controller extends Admin_Controller {
+ public function index() {
+ $view = new Admin_View("admin.html");
+ $view->page_title = t("Dashboard");
+ $view->content = new View("admin_dashboard.html");
+ $view->content->blocks = block_manager::get_html("dashboard_center");
+ $view->sidebar = "<div id=\"g-admin-dashboard-sidebar\">" .
+ block_manager::get_html("dashboard_sidebar") .
+ "</div>";
+ $view->content->obsolete_modules_message = module::get_obsolete_modules_message();
+ print $view;
+ }
+
+ public function add_block() {
+ access::verify_csrf();
+
+ $form = gallery_block::get_add_block_form();
+ if ($form->validate()) {
+ list ($module_name, $id) = explode(":", $form->add_block->id->value);
+ $available = block_manager::get_available_admin_blocks();
+
+ if ($form->add_block->center->value) {
+ block_manager::add("dashboard_center", $module_name, $id);
+ message::success(
+ t("Added <b>%title</b> block to the dashboard center",
+ array("title" => $available["$module_name:$id"])));
+ } else {
+ block_manager::add("dashboard_sidebar", $module_name, $id);
+ message::success(
+ t("Added <b>%title</b> to the dashboard sidebar",
+ array("title" => $available["$module_name:$id"])));
+ }
+ }
+ url::redirect("admin/dashboard");
+ }
+
+ public function remove_block($id) {
+ access::verify_csrf();
+
+ $blocks_center = block_manager::get_active("dashboard_center");
+ $blocks_sidebar = block_manager::get_active("dashboard_sidebar");
+
+ if (array_key_exists($id, $blocks_sidebar)) {
+ $deleted = $blocks_sidebar[$id];
+ block_manager::remove("dashboard_sidebar", $id);
+ } else if (array_key_exists($id, $blocks_center)) {
+ $deleted = $blocks_center[$id];
+ block_manager::remove("dashboard_center", $id);
+ }
+
+ if (!empty($deleted)) {
+ $available = block_manager::get_available_admin_blocks();
+ $title = $available[join(":", $deleted)];
+ message::success(t("Removed <b>%title</b> block", array("title" => $title)));
+ }
+
+ url::redirect("admin");
+ }
+
+ public function reorder() {
+ access::verify_csrf();
+
+ $active_set = array();
+ foreach (array("dashboard_sidebar", "dashboard_center") as $location) {
+ foreach (block_manager::get_active($location) as $id => $info) {
+ $active_set[$id] = $info;
+ }
+ }
+
+ foreach (array("dashboard_sidebar", "dashboard_center") as $location) {
+ $new_blocks = array();
+ foreach (Input::instance()->get($location, array()) as $id) {
+ $new_blocks[$id] = $active_set[$id];
+ }
+ block_manager::set_active($location, $new_blocks);
+ }
+ }
+}
diff --git a/modules/gallery/controllers/admin_graphics.php b/modules/gallery/controllers/admin_graphics.php
new file mode 100644
index 0000000..a24486f
--- /dev/null
+++ b/modules/gallery/controllers/admin_graphics.php
@@ -0,0 +1,50 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 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 Admin_Graphics_Controller extends Admin_Controller {
+ public function index() {
+ $view = new Admin_View("admin.html");
+ $view->page_title = t("Graphics settings");
+ $view->content = new View("admin_graphics.html");
+ $view->content->tk = graphics::detect_toolkits();
+ $view->content->active = module::get_var("gallery", "graphics_toolkit", "none");
+ print $view;
+ }
+
+ public function choose($toolkit_id) {
+ access::verify_csrf();
+
+ 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");
+
+ $msg = t("Changed graphics toolkit to: %toolkit", array("toolkit" => $tk->$toolkit_id->name));
+ message::success($msg);
+ log::success("graphics", $msg);
+
+ module::event("graphics_toolkit_change", $toolkit_id);
+ }
+
+ url::redirect("admin/graphics");
+ }
+}
+
diff --git a/modules/gallery/controllers/admin_languages.php b/modules/gallery/controllers/admin_languages.php
new file mode 100644
index 0000000..50ddc67
--- /dev/null
+++ b/modules/gallery/controllers/admin_languages.php
@@ -0,0 +1,135 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 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 Admin_Languages_Controller extends Admin_Controller {
+ public function index($share_translations_form=null) {
+ $v = new Admin_View("admin.html");
+ $v->page_title = t("Languages and translations");
+ $v->content = new View("admin_languages.html");
+ $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();
+ }
+ $v->content->share_translations_form = $share_translations_form;
+ $this->_outgoing_translations_count();
+ print $v;
+ }
+
+ public function save() {
+ access::verify_csrf();
+
+ $input = Input::instance();
+ locales::update_installed($input->post("installed_locales"));
+
+ $installed_locales = array_keys(locales::installed());
+ $new_default_locale = $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);
+
+ json::reply(array("result" => "success"));
+ }
+
+ public function share() {
+ access::verify_csrf();
+
+ $form = $this->_share_translations_form();
+ if (!$form->validate()) {
+ // Show the page with form errors
+ return $this->index($form);
+ }
+
+ if (Input::instance()->post("share")) {
+ l10n_client::submit_translations();
+ message::success(t("Translations submitted"));
+ } else {
+ return $this->_save_api_key($form);
+ }
+ url::redirect("admin/languages");
+ }
+
+ private function _save_api_key($form) {
+ $new_key = $form->sharing->api_key->value;
+ if ($new_key) {
+ list($connected, $valid) = l10n_client::validate_api_key($new_key);
+ if (!$valid) {
+ $form->sharing->api_key->add_error($connected ? "invalid" : "no_connection", 1);
+ }
+ } else {
+ $valid = true;
+ }
+
+ if ($valid) {
+ $old_key = l10n_client::api_key();
+ l10n_client::api_key($new_key);
+ if ($old_key && !$new_key) {
+ message::success(t("Your API key has been cleared."));
+ } else if ($old_key && $new_key && $old_key != $new_key) {
+ message::success(t("Your API key has been changed."));
+ } else if (!$old_key && $new_key) {
+ message::success(t("Your API key has been saved."));
+ } else if ($old_key && $new_key && $old_key == $new_key) {
+ message::info(t("Your API key was not changed."));
+ }
+
+ log::success(t("gallery"), t("l10n_client API key changed."));
+ url::redirect("admin/languages");
+ } else {
+ // Show the page with form errors
+ $this->index($form);
+ }
+ }
+
+ private function _outgoing_translations_count() {
+ return ORM::factory("outgoing_translation")->count_all();
+ }
+
+ private function _share_translations_form() {
+ $form = new Forge("admin/languages/share", "", "post", array("id" => "g-share-translations-form"));
+ $group = $form->group("sharing")
+ ->label("Translations API Key");
+ $api_key = l10n_client::api_key();
+ $server_link = l10n_client::server_api_key_url();
+ $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::mark_clean(html::anchor($server_link))))
+ : t("API key"))
+ ->value($api_key)
+ ->error_messages("invalid", t("The API key you provided is invalid."))
+ ->error_messages(
+ "no_connection", t("Could not connect to remote server to validate the API key."));
+ $group->submit("save")->value(t("Save settings"));
+ if ($api_key && $this->_outgoing_translations_count()) {
+ // TODO: UI improvement: hide API key / save button when API key is set.
+ $group->submit("share")->value(t("Submit translations"));
+ }
+ return $form;
+ }
+}
+
diff --git a/modules/gallery/controllers/admin_maintenance.php b/modules/gallery/controllers/admin_maintenance.php
new file mode 100644
index 0000000..32f2078
--- /dev/null
+++ b/modules/gallery/controllers/admin_maintenance.php
@@ -0,0 +1,243 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 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 Admin_Maintenance_Controller extends Admin_Controller {
+ /**
+ * Show a list of all available, running and finished tasks.
+ */
+ public function index() {
+ $query = db::build()
+ ->update("tasks")
+ ->set("state", "stalled")
+ ->where("done", "=", 0)
+ ->where("state", "<>", "stalled")
+ ->where(db::expr("UNIX_TIMESTAMP(NOW()) - `updated` > 15"))
+ ->execute();
+ $stalled_count = $query->count();
+ if ($stalled_count) {
+ log::warning("tasks",
+ t2("One task is stalled",
+ "%count tasks are stalled",
+ $stalled_count),
+ t('<a href="%url">view</a>',
+ array("url" => html::mark_clean(url::site("admin/maintenance")))));
+ }
+
+ $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")
+ ->where("done", "=", 0)->order_by("updated", "DESC")->find_all();
+ $view->content->finished_tasks = ORM::factory("task")
+ ->where("done", "=", 1)->order_by("updated", "DESC")->find_all();
+ print $view;
+
+ // Do some maintenance while we're in here
+ db::build()
+ ->delete("caches")
+ ->where("expiration", "<>", 0)
+ ->where("expiration", "<=", time())
+ ->execute();
+ module::deactivate_missing_modules();
+ }
+
+ /**
+ * Start a new task
+ * @param string $task_callback
+ */
+ public function start($task_callback) {
+ access::verify_csrf();
+
+ $task = task::start($task_callback);
+ $view = new View("admin_maintenance_task.html");
+ $view->task = $task;
+
+ log::info("tasks", t("Task %task_name started (task id %task_id)",
+ array("task_name" => $task->name, "task_id" => $task->id)),
+ html::anchor("admin/maintenance", t("maintenance")));
+ print $view;
+ }
+
+ /**
+ * Resume a stalled task
+ * @param string $task_id
+ */
+ public function resume($task_id) {
+ access::verify_csrf();
+
+ $task = ORM::factory("task", $task_id);
+ if (!$task->loaded()) {
+ throw new Exception("@todo MISSING_TASK");
+ }
+ $view = new View("admin_maintenance_task.html");
+ $view->task = $task;
+
+ $task->log(t("Task %task_name resumed (task id %task_id)",
+ array("task_name" => $task->name, "task_id" => $task->id)));
+ log::info("tasks", t("Task %task_name resumed (task id %task_id)",
+ array("task_name" => $task->name, "task_id" => $task->id)),
+ html::anchor("admin/maintenance", t("maintenance")));
+ print $view;
+ }
+
+ /**
+ * Show the task log
+ * @param string $task_id
+ */
+ public function show_log($task_id) {
+ access::verify_csrf();
+
+ $task = ORM::factory("task", $task_id);
+ if (!$task->loaded()) {
+ throw new Exception("@todo MISSING_TASK");
+ }
+ $view = new View("admin_maintenance_show_log.html");
+ $view->task = $task;
+
+ print $view;
+ }
+
+ /**
+ * Save the task log
+ * @param string $task_id
+ */
+ public function save_log($task_id) {
+ access::verify_csrf();
+
+ $task = ORM::factory("task", $task_id);
+ if (!$task->loaded()) {
+ throw new Exception("@todo MISSING_TASK");
+ }
+
+ header("Content-Type: application/text");
+ header("Content-Disposition: filename=gallery3_task_log.txt");
+ print $task->get_log();
+ }
+
+ /**
+ * Cancel a task.
+ * @param string $task_id
+ */
+ public function cancel($task_id) {
+ access::verify_csrf();
+
+ task::cancel($task_id);
+
+ message::success(t("Task cancelled"));
+ url::redirect("admin/maintenance");
+ }
+
+ public function cancel_running_tasks() {
+ access::verify_csrf();
+ db::build()
+ ->update("tasks")
+ ->set("done", 1)
+ ->set("state", "cancelled")
+ ->where("done", "=", 0)
+ ->execute();
+ message::success(t("All running tasks cancelled"));
+ url::redirect("admin/maintenance");
+ }
+
+ /**
+ * Remove a task.
+ * @param string $task_id
+ */
+ public function remove($task_id) {
+ access::verify_csrf();
+
+ task::remove($task_id);
+
+ message::success(t("Task removed"));
+ url::redirect("admin/maintenance");
+ }
+
+ public function remove_finished_tasks() {
+ access::verify_csrf();
+
+ // Do it the long way so we can call delete and remove the cache.
+ $finished = ORM::factory("task")
+ ->where("done", "=", 1)
+ ->find_all();
+ foreach ($finished as $task) {
+ task::remove($task->id);
+ }
+ message::success(t("All finished tasks removed"));
+ url::redirect("admin/maintenance");
+ }
+
+ /**
+ * Run a task. This will trigger the task to do a small amount of work, then it will report
+ * back with status on the task.
+ * @param string $task_id
+ */
+ public function run($task_id) {
+ access::verify_csrf();
+
+ try {
+ $task = task::run($task_id);
+ } catch (Exception $e) {
+ Kohana_Log::add(
+ "error",
+ sprintf(
+ "%s in %s at line %s:\n%s", $e->getMessage(), $e->getFile(),
+ $e->getLine(), $e->getTraceAsString()));
+ throw $e;
+ }
+
+ if ($task->done) {
+ switch ($task->state) {
+ case "success":
+ log::success("tasks", t("Task %task_name completed (task id %task_id)",
+ array("task_name" => $task->name, "task_id" => $task->id)),
+ html::anchor("admin/maintenance", t("maintenance")));
+ message::success(t("Task completed successfully"));
+ break;
+
+ case "error":
+ log::error("tasks", t("Task %task_name failed (task id %task_id)",
+ array("task_name" => $task->name, "task_id" => $task->id)),
+ html::anchor("admin/maintenance", t("maintenance")));
+ message::success(t("Task failed"));
+ break;
+ }
+ // Using sprintf("%F") to avoid comma as decimal separator.
+ json::reply(array("result" => "success",
+ "task" => array(
+ "percent_complete" => sprintf("%F", $task->percent_complete),
+ "status" => (string) $task->status,
+ "done" => (bool) $task->done),
+ "location" => url::site("admin/maintenance")));
+
+ } else {
+ json::reply(array("result" => "in_progress",
+ "task" => array(
+ "percent_complete" => sprintf("%F", $task->percent_complete),
+ "status" => (string) $task->status,
+ "done" => (bool) $task->done)));
+ }
+ }
+
+ public function maintenance_mode($value) {
+ access::verify_csrf();
+ module::set_var("gallery", "maintenance_mode", $value);
+ url::redirect("admin/maintenance");
+ }
+}
diff --git a/modules/gallery/controllers/admin_modules.php b/modules/gallery/controllers/admin_modules.php
new file mode 100644
index 0000000..177a925
--- /dev/null
+++ b/modules/gallery/controllers/admin_modules.php
@@ -0,0 +1,119 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 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 Admin_Modules_Controller extends Admin_Controller {
+ public function index() {
+ // If modules need upgrading, this will get recreated in module::available()
+ site_status::clear("upgrade_now");
+
+ $view = new Admin_View("admin.html");
+ $view->page_title = t("Modules");
+ $view->content = new View("admin_modules.html");
+ $view->content->available = module::available();
+ $view->content->obsolete_modules_message = module::get_obsolete_modules_message();
+ print $view;
+ }
+
+
+ public function confirm() {
+ access::verify_csrf();
+
+ $messages = array("error" => array(), "warn" => array());
+ $desired_list = array();
+ foreach (module::available() as $module_name => $info) {
+ if ($info->locked) {
+ continue;
+ }
+
+ if ($desired = Input::instance()->post($module_name) == 1) {
+ $desired_list[] = $module_name;
+ }
+ if ($info->active && !$desired && module::is_active($module_name)) {
+ $messages = array_merge($messages, module::can_deactivate($module_name));
+ } else if (!$info->active && $desired && !module::is_active($module_name)) {
+ $messages = array_merge($messages, module::can_activate($module_name));
+ }
+ }
+
+ if (empty($messages["error"]) && empty($messages["warn"])) {
+ $this->_do_save();
+ $result["reload"] = 1;
+ } else {
+ $v = new View("admin_modules_confirm.html");
+ $v->messages = $messages;
+ $v->modules = $desired_list;
+ $result["dialog"] = (string)$v;
+ $result["allow_continue"] = empty($messages["error"]);
+ }
+ json::reply($result);
+ }
+
+ public function save() {
+ access::verify_csrf();
+
+ $this->_do_save();
+ url::redirect("admin/modules");
+ }
+
+ private function _do_save() {
+ $changes = new stdClass();
+ $changes->activate = array();
+ $changes->deactivate = array();
+ $activated_names = array();
+ $deactivated_names = array();
+ foreach (module::available() as $module_name => $info) {
+ if ($info->locked) {
+ continue;
+ }
+
+ try {
+ $desired = Input::instance()->post($module_name) == 1;
+ if ($info->active && !$desired && module::is_active($module_name)) {
+ module::deactivate($module_name);
+ $changes->deactivate[] = $module_name;
+ $deactivated_names[] = t($info->name);
+ } else if (!$info->active && $desired && !module::is_active($module_name)) {
+ if (module::is_installed($module_name)) {
+ module::upgrade($module_name);
+ } else {
+ module::install($module_name);
+ }
+ module::activate($module_name);
+ $changes->activate[] = $module_name;
+ $activated_names[] = t($info->name);
+ }
+ } catch (Exception $e) {
+ message::warning(t("An error occurred while installing the <b>%module_name</b> module",
+ array("module_name" => $info->name)));
+ Kohana_Log::add("error", (string)$e);
+ }
+ }
+
+ module::event("module_change", $changes);
+
+ // @todo this type of collation is questionable from an i18n perspective
+ if ($activated_names) {
+ message::success(t("Activated: %names", array("names" => join(", ", $activated_names))));
+ }
+ if ($deactivated_names) {
+ message::success(t("Deactivated: %names", array("names" => join(", ", $deactivated_names))));
+ }
+ }
+}
+
diff --git a/modules/gallery/controllers/admin_movies.php b/modules/gallery/controllers/admin_movies.php
new file mode 100644
index 0000000..38fa44a
--- /dev/null
+++ b/modules/gallery/controllers/admin_movies.php
@@ -0,0 +1,72 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 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 Admin_Movies_Controller extends Admin_Controller {
+ public function index() {
+ // Print screen from new form.
+ $form = $this->_get_admin_form();
+ $this->_print_view($form);
+ }
+
+ public function save() {
+ access::verify_csrf();
+ $form = $this->_get_admin_form();
+ if ($form->validate()) {
+ module::set_var("gallery", "movie_allow_uploads", $form->settings->allow_uploads->value);
+ if ($form->settings->rebuild_thumbs->value) {
+ graphics::mark_dirty(true, false, "movie");
+ }
+ // All done - redirect with message.
+ message::success(t("Movies settings updated successfully"));
+ url::redirect("admin/movies");
+ }
+ // Something went wrong - print view from existing form.
+ $this->_print_view($form);
+ }
+
+ private function _print_view($form) {
+ list ($ffmpeg_version, $ffmpeg_date) = movie::get_ffmpeg_version();
+ $ffmpeg_version = $ffmpeg_date ? "{$ffmpeg_version} ({$ffmpeg_date})" : $ffmpeg_version;
+ $ffmpeg_path = movie::find_ffmpeg();
+ $ffmpeg_dir = substr($ffmpeg_path, 0, strrpos($ffmpeg_path, "/"));
+
+ $view = new Admin_View("admin.html");
+ $view->page_title = t("Movies settings");
+ $view->content = new View("admin_movies.html");
+ $view->content->form = $form;
+ $view->content->ffmpeg_dir = $ffmpeg_dir;
+ $view->content->ffmpeg_version = $ffmpeg_version;
+ print $view;
+ }
+
+ private function _get_admin_form() {
+ $form = new Forge("admin/movies/save", "", "post", array("id" => "g-movies-admin-form"));
+ $group = $form->group("settings")->label(t("Settings"));
+ $group->dropdown("allow_uploads")
+ ->label(t("Allow movie uploads into Gallery (does not affect existing movies)"))
+ ->options(array("autodetect"=>t("only if FFmpeg is detected (default)"),
+ "always"=>t("always"), "never"=>t("never")))
+ ->selected(module::get_var("gallery", "movie_allow_uploads", "autodetect"));
+ $group->checkbox("rebuild_thumbs")
+ ->label(t("Rebuild all movie thumbnails (once FFmpeg is installed, use this to update existing movie thumbnails)"))
+ ->checked(false); // always set as false
+ $form->submit("save")->value(t("Save"));
+ return $form;
+ }
+}
diff --git a/modules/gallery/controllers/admin_sidebar.php b/modules/gallery/controllers/admin_sidebar.php
new file mode 100644
index 0000000..f150f85
--- /dev/null
+++ b/modules/gallery/controllers/admin_sidebar.php
@@ -0,0 +1,69 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 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 Admin_Sidebar_Controller extends Admin_Controller {
+ public function index() {
+ $view = new Admin_View("admin.html");
+ $view->page_title = t("Manage sidebar");
+ $view->content = new View("admin_sidebar.html");
+ $view->content->csrf = access::csrf_token();
+ $view->content->available = new View("admin_sidebar_blocks.html");
+ $view->content->active = new View("admin_sidebar_blocks.html");
+ list($view->content->available->blocks, $view->content->active->blocks) = $this->_get_blocks();
+ print $view;
+ }
+
+ public function update() {
+ access::verify_csrf();
+
+ $available_blocks = block_manager::get_available_site_blocks();
+
+ $active_blocks = array();
+ foreach (Input::instance()->get("block", array()) as $block_id) {
+ $active_blocks[md5($block_id)] = explode(":", (string) $block_id);
+ }
+ block_manager::set_active("site_sidebar", $active_blocks);
+
+ $result = array("result" => "success");
+ list($available, $active) = $this->_get_blocks();
+ $v = new View("admin_sidebar_blocks.html");
+ $v->blocks = $available;
+ $result["available"] = $v->render();
+ $v = new View("admin_sidebar_blocks.html");
+ $v->blocks = $active;
+ $result["active"] = $v->render();
+ $message = t("Updated sidebar blocks");
+ $result["message"] = (string) $message;
+ json::reply($result);
+ }
+
+ private function _get_blocks() {
+ $active_blocks = array();
+ $available_blocks = block_manager::get_available_site_blocks();
+ foreach (block_manager::get_active("site_sidebar") as $block) {
+ $id = "{$block[0]}:{$block[1]}";
+ if (!empty($available_blocks[$id])) {
+ $active_blocks[$id] = $available_blocks[$id];
+ unset($available_blocks[$id]);
+ }
+ }
+ return array($available_blocks, $active_blocks);
+ }
+}
+
diff --git a/modules/gallery/controllers/admin_theme_options.php b/modules/gallery/controllers/admin_theme_options.php
new file mode 100644
index 0000000..38d2b0a
--- /dev/null
+++ b/modules/gallery/controllers/admin_theme_options.php
@@ -0,0 +1,120 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 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 Admin_Theme_Options_Controller extends Admin_Controller {
+ public function index() {
+ $view = new Admin_View("admin.html");
+ $view->page_title = t("Theme options");
+ $view->content = new View("admin_theme_options.html");
+ $view->content->form = $this->_get_edit_form_admin();
+ print $view;
+ }
+
+ public function save() {
+ access::verify_csrf();
+
+ $form = $this->_get_edit_form_admin();
+ if ($form->validate()) {
+ module::set_var("gallery", "page_size", $form->edit_theme->page_size->value);
+
+ $thumb_size = $form->edit_theme->thumb_size->value;
+ if (module::get_var("gallery", "thumb_size") != $thumb_size) {
+ graphics::remove_rule("gallery", "thumb", "gallery_graphics::resize");
+ graphics::add_rule(
+ "gallery", "thumb", "gallery_graphics::resize",
+ array("width" => $thumb_size, "height" => $thumb_size, "master" => Image::AUTO),
+ 100);
+ module::set_var("gallery", "thumb_size", $thumb_size);
+ }
+
+ $resize_size = $form->edit_theme->resize_size->value;
+ if (module::get_var("gallery", "resize_size") != $resize_size) {
+ graphics::remove_rule("gallery", "resize", "gallery_graphics::resize");
+ graphics::add_rule(
+ "gallery", "resize", "gallery_graphics::resize",
+ array("width" => $resize_size, "height" => $resize_size, "master" => Image::AUTO),
+ 100);
+ module::set_var("gallery", "resize_size", $resize_size);
+ }
+
+ module::set_var("gallery", "header_text", $form->edit_theme->header_text->value);
+ module::set_var("gallery", "footer_text", $form->edit_theme->footer_text->value);
+ module::set_var("gallery", "show_credits", $form->edit_theme->show_credits->value);
+ module::set_var("gallery", "favicon_url", $form->edit_theme->favicon_url->value);
+ module::set_var("gallery", "apple_touch_icon_url", $form->edit_theme->apple_touch_icon_url->value);
+
+ module::event("theme_edit_form_completed", $form);
+
+ message::success(t("Updated theme details"));
+ url::redirect("admin/theme_options");
+ } else {
+ $view = new Admin_View("admin.html");
+ $view->content = new View("admin_theme_options.html");
+ $view->content->form = $form;
+ print $view;
+ }
+ }
+
+ private function _get_edit_form_admin() {
+ $form = new Forge("admin/theme_options/save/", "", null, array("id" =>"g-theme-options-form"));
+ $group = $form->group("edit_theme")->label(t("Theme layout"));
+ $group->input("page_size")->label(t("Items per page"))->id("g-page-size")
+ ->rules("required|valid_digit")
+ ->callback(array($this, "_valididate_page_size"))
+ ->error_messages("required", t("You must enter a number"))
+ ->error_messages("valid_digit", t("You must enter a number"))
+ ->error_messages("valid_min_value", t("The value must be greater than zero"))
+ ->value(module::get_var("gallery", "page_size"));
+ $group->input("thumb_size")->label(t("Thumbnail size (in pixels)"))->id("g-thumb-size")
+ ->rules("required|valid_digit")
+ ->error_messages("required", t("You must enter a number"))
+ ->error_messages("valid_digit", t("You must enter a number"))
+ ->value(module::get_var("gallery", "thumb_size"));
+ $group->input("resize_size")->label(t("Resized image size (in pixels)"))->id("g-resize-size")
+ ->rules("required|valid_digit")
+ ->error_messages("required", t("You must enter a number"))
+ ->error_messages("valid_digit", t("You must enter a number"))
+ ->value(module::get_var("gallery", "resize_size"));
+ $group->input("favicon_url")->label(t("URL (or relative path) to your favicon.ico"))
+ ->id("g-favicon")
+ ->value(module::get_var("gallery", "favicon_url"));
+ $group->input("apple_touch_icon_url")->label(t("URL (or relative path) to your Apple Touch icon"))
+ ->id("g-apple-touch")
+ ->value(module::get_var("gallery", "apple_touch_icon_url"));
+ $group->textarea("header_text")->label(t("Header text"))->id("g-header-text")
+ ->value(module::get_var("gallery", "header_text"));
+ $group->textarea("footer_text")->label(t("Footer text"))->id("g-footer-text")
+ ->value(module::get_var("gallery", "footer_text"));
+ $group->checkbox("show_credits")->label(t("Show site credits"))->id("g-footer-text")
+ ->checked(module::get_var("gallery", "show_credits"));
+
+ module::event("theme_edit_form", $form);
+
+ $group->submit("")->value(t("Save"));
+ return $form;
+ }
+
+ function _valididate_page_size($input) {
+ if ($input->value < 1) {
+ $input->add_error("valid_min_value", true);
+ }
+
+ }
+}
+
diff --git a/modules/gallery/controllers/admin_themes.php b/modules/gallery/controllers/admin_themes.php
new file mode 100644
index 0000000..4ab994f
--- /dev/null
+++ b/modules/gallery/controllers/admin_themes.php
@@ -0,0 +1,80 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 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 Admin_Themes_Controller extends Admin_Controller {
+ public function index() {
+ $view = new Admin_View("admin.html");
+ $view->page_title = t("Theme choice");
+ $view->content = new View("admin_themes.html");
+ $view->content->admin = module::get_var("gallery", "active_admin_theme");
+ $view->content->site = module::get_var("gallery", "active_site_theme");
+ $view->content->themes = $this->_get_themes();
+
+ site_status::clear("missing_site_theme");
+ site_status::clear("missing_admin_theme");
+ print $view;
+ }
+
+ private function _get_themes() {
+ $themes = array();
+ foreach (scandir(THEMEPATH) as $theme_name) {
+ if ($theme_name[0] == ".") {
+ continue;
+ }
+ $theme_name = preg_replace("/[^a-zA-Z0-9\._-]/", "", $theme_name);
+ if (file_exists(THEMEPATH . "$theme_name/theme.info")) {
+
+ $themes[$theme_name] = theme::get_info($theme_name);
+ }
+ }
+ return $themes;
+ }
+
+ public function preview($type, $theme_name) {
+ $view = new View("admin_themes_preview.html");
+ $view->info = theme::get_info($theme_name);
+ $view->theme_name = t($theme_name);
+ $view->type = $type;
+ if ($type == "admin") {
+ $view->url = url::site("admin?theme=$theme_name");
+ } else {
+ $view->url = item::root()->url("theme=$theme_name");
+ }
+ print $view;
+ }
+
+ public function choose($type, $theme_name) {
+ access::verify_csrf();
+
+ $info = theme::get_info($theme_name);
+
+ if ($type == "admin" && $info->admin) {
+ module::set_var("gallery", "active_admin_theme", $theme_name);
+ message::success(t("Successfully changed your admin theme to <b>%theme_name</b>",
+ array("theme_name" => $info->name)));
+ } else if ($type == "site" && $info->site) {
+ module::set_var("gallery", "active_site_theme", $theme_name);
+ message::success(t("Successfully changed your Gallery theme to <b>%theme_name</b>",
+ array("theme_name" => $info->name)));
+ }
+
+ url::redirect("admin/themes");
+ }
+}
+
diff --git a/modules/gallery/controllers/admin_upgrade_checker.php b/modules/gallery/controllers/admin_upgrade_checker.php
new file mode 100644
index 0000000..3f0bdac
--- /dev/null
+++ b/modules/gallery/controllers/admin_upgrade_checker.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-2013 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 Admin_Upgrade_Checker_Controller extends Admin_Controller {
+ function check_now() {
+ access::verify_csrf();
+ upgrade_checker::fetch_version_info();
+ $message = upgrade_checker::get_upgrade_message();
+ if ($message) {
+ $message .= t(
+ " <a href=\"%hide-url\"><i>(remind me later)</i></a>",
+ array("hide-url" => url::site("admin/upgrade_checker/remind_me_later?csrf=__CSRF__")));
+ site_status::info($message, "upgrade_checker");
+ } else {
+ site_status::clear("upgrade_checker");
+ }
+ url::redirect("admin/dashboard");
+ }
+
+ function remind_me_later() {
+ access::verify_csrf();
+ site_status::clear("upgrade_checker");
+ if ($referer = Input::instance()->server("HTTP_REFERER")) {
+ url::redirect($referer);
+ } else {
+ url::redirect(item::root()->abs_url());
+ }
+ }
+
+ function set_auto($val) {
+ access::verify_csrf();
+ module::set_var("gallery", "upgrade_checker_auto_enabled", (bool)$val);
+
+ if ((bool)$val) {
+ message::success(t("Automatic upgrade checking is enabled."));
+ } else {
+ message::success(t("Automatic upgrade checking is disabled."));
+ }
+ url::redirect("admin/dashboard");
+ }
+}
diff --git a/modules/gallery/controllers/albums.php b/modules/gallery/controllers/albums.php
new file mode 100644
index 0000000..0fb033a
--- /dev/null
+++ b/modules/gallery/controllers/albums.php
@@ -0,0 +1,207 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 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 Albums_Controller extends Items_Controller {
+ public function index() {
+ $this->show(ORM::factory("item", 1));
+ }
+
+ public function show($album) {
+ if (!is_object($album)) {
+ // show() must be public because we route to it in url::parse_url(), so make
+ // sure that we're actually receiving an object
+ throw new Kohana_404_Exception();
+ }
+
+ access::required("view", $album);
+
+ $page_size = module::get_var("gallery", "page_size", 9);
+ $input = Input::instance();
+ $show = $input->get("show");
+
+ if ($show) {
+ $child = ORM::factory("item", $show);
+ $index = item::get_position($child);
+ if ($index) {
+ $page = ceil($index / $page_size);
+ if ($page == 1) {
+ url::redirect($album->abs_url());
+ } else {
+ url::redirect($album->abs_url("page=$page"));
+ }
+ }
+ }
+
+ $page = $input->get("page", "1");
+ $children_count = $album->viewable()->children_count();
+ $offset = ($page - 1) * $page_size;
+ $max_pages = max(ceil($children_count / $page_size), 1);
+
+ // Make sure that the page references a valid offset
+ if ($page < 1) {
+ url::redirect($album->abs_url());
+ } else if ($page > $max_pages) {
+ url::redirect($album->abs_url("page=$max_pages"));
+ }
+
+ $template = new Theme_View("page.html", "collection", "album");
+ $template->set_global(
+ array("page" => $page,
+ "page_title" => null,
+ "max_pages" => $max_pages,
+ "page_size" => $page_size,
+ "item" => $album,
+ "children" => $album->viewable()->children($page_size, $offset),
+ "parents" => $album->parents()->as_array(), // view calls empty() on this
+ "breadcrumbs" => Breadcrumb::array_from_item_parents($album),
+ "children_count" => $children_count));
+ $template->content = new View("album.html");
+ $album->increment_view_count();
+
+ print $template;
+ item::set_display_context_callback("Albums_Controller::get_display_context");
+ }
+
+ static function get_display_context($item) {
+ $where = array(array("type", "!=", "album"));
+ $position = item::get_position($item, $where);
+ if ($position > 1) {
+ list ($previous_item, $ignore, $next_item) =
+ $item->parent()->viewable()->children(3, $position - 2, $where);
+ } else {
+ $previous_item = null;
+ list ($next_item) = $item->parent()->viewable()->children(1, $position, $where);
+ }
+
+ return array("position" => $position,
+ "previous_item" => $previous_item,
+ "next_item" => $next_item,
+ "sibling_count" => $item->parent()->viewable()->children_count($where),
+ "siblings_callback" => array("Albums_Controller::get_siblings", array($item)),
+ "parents" => $item->parents()->as_array(),
+ "breadcrumbs" => Breadcrumb::array_from_item_parents($item));
+ }
+
+ static function get_siblings($item, $limit=null, $offset=null) {
+ // @todo consider creating Item_Model::siblings() if we use this more broadly.
+ return $item->parent()->viewable()->children($limit, $offset);
+ }
+
+ public function create($parent_id) {
+ access::verify_csrf();
+ $album = ORM::factory("item", $parent_id);
+ access::required("view", $album);
+ access::required("add", $album);
+
+ $form = album::get_add_form($album);
+ try {
+ $valid = $form->validate();
+ $album = ORM::factory("item");
+ $album->type = "album";
+ $album->parent_id = $parent_id;
+ $album->name = $form->add_album->inputs["name"]->value;
+ $album->title = $form->add_album->title->value ?
+ $form->add_album->title->value : $form->add_album->inputs["name"]->value;
+ $album->description = $form->add_album->description->value;
+ $album->slug = $form->add_album->slug->value;
+ $album->validate();
+ } catch (ORM_Validation_Exception $e) {
+ // Translate ORM validation errors into form error messages
+ foreach ($e->validation->errors() as $key => $error) {
+ $form->add_album->inputs[$key]->add_error($error, 1);
+ }
+ $valid = false;
+ }
+
+ if ($valid) {
+ $album->save();
+ module::event("album_add_form_completed", $album, $form);
+ log::success("content", "Created an album",
+ html::anchor("albums/$album->id", "view album"));
+ message::success(t("Created album %album_title",
+ array("album_title" => html::purify($album->title))));
+
+ json::reply(array("result" => "success", "location" => $album->url()));
+ } else {
+ json::reply(array("result" => "error", "html" => (string)$form));
+ }
+ }
+
+ public function update($album_id) {
+ access::verify_csrf();
+ $album = ORM::factory("item", $album_id);
+ access::required("view", $album);
+ access::required("edit", $album);
+
+ $form = album::get_edit_form($album);
+ try {
+ $valid = $form->validate();
+ $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 (array_key_exists("name", $form->edit_item->inputs)) {
+ $album->name = $form->edit_item->inputs["name"]->value;
+ }
+ $album->slug = $form->edit_item->slug->value;
+ $album->validate();
+ } catch (ORM_Validation_Exception $e) {
+ // Translate ORM validation errors into form error messages
+ foreach ($e->validation->errors() as $key => $error) {
+ $form->edit_item->inputs[$key]->add_error($error, 1);
+ }
+ $valid = false;
+ }
+
+ if ($valid) {
+ $album->save();
+ 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" => html::purify($album->title))));
+
+ if ($form->from_id->value == $album->id) {
+ // Use the new url; it might have changed.
+ json::reply(array("result" => "success", "location" => $album->url()));
+ } else {
+ // Stay on the same page
+ json::reply(array("result" => "success"));
+ }
+ } else {
+ json::reply(array("result" => "error", "html" => (string)$form));
+ }
+ }
+
+ public function form_add($album_id) {
+ $album = ORM::factory("item", $album_id);
+ access::required("view", $album);
+ access::required("add", $album);
+
+ print album::get_add_form($album);
+ }
+
+ public function form_edit($album_id) {
+ $album = ORM::factory("item", $album_id);
+ access::required("view", $album);
+ access::required("edit", $album);
+
+ print album::get_edit_form($album);
+ }
+}
diff --git a/modules/gallery/controllers/combined.php b/modules/gallery/controllers/combined.php
new file mode 100644
index 0000000..3cf7f87
--- /dev/null
+++ b/modules/gallery/controllers/combined.php
@@ -0,0 +1,96 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 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 Combined_Controller extends Controller {
+ const ALLOW_MAINTENANCE_MODE = true;
+ const ALLOW_PRIVATE_GALLERY = true;
+
+ /**
+ * Return the combined Javascript bundle associated with the given key.
+ */
+ public function javascript($key) {
+ return $this->_emit("javascript", $key);
+ }
+
+ /**
+ * Return the combined CSS bundle associated with the given key.
+ */
+ public function css($key) {
+ return $this->_emit("css", $key);
+ }
+
+ /**
+ * Print out a cached entry.
+ * @param string the combined entry type (either "javascript" or "css")
+ * @param string the key (typically an md5 sum)
+ */
+ private function _emit($type, $key) {
+ $input = Input::instance();
+
+ // We don't need to save the session for this request
+ Session::instance()->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: public,max-age=2678400");
+ header('Pragma: public');
+ Kohana::close_buffers(false);
+ return "";
+ }
+
+ if (empty($key)) {
+ throw new Kohana_404_Exception();
+ }
+
+ $cache = Cache::instance();
+ $use_gzip = function_exists("gzencode") &&
+ 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");
+ header("Vary: Accept-Encoding");
+ } else {
+ // Fall back to non-gzipped if we have to
+ $content = $cache->get($key);
+ }
+ if (empty($content)) {
+ throw new Kohana_404_Exception();
+ }
+
+ // $type is either 'javascript' or 'css'
+ if ($type == "javascript") {
+ header("Content-Type: application/javascript; charset=UTF-8");
+ } else {
+ header("Content-Type: text/css; charset=UTF-8");
+ }
+ header("Expires: Tue, 19 Jan 2038 00:00:00 GMT");
+ header("Cache-Control: public,max-age=2678400");
+ header("Pragma: public");
+ header("Last-Modified: " . gmdate("D, d M Y H:i:s T", time()));
+ header("Content-Length: " . strlen($content));
+
+ Kohana::close_buffers(false);
+ print $content;
+ }
+
+}
+
diff --git a/modules/gallery/controllers/file_proxy.php b/modules/gallery/controllers/file_proxy.php
new file mode 100644
index 0000000..34f6b8c
--- /dev/null
+++ b/modules/gallery/controllers/file_proxy.php
@@ -0,0 +1,174 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 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.
+ */
+/**
+ * Proxy access to files in var/albums and var/resizes, making sure that the session user has
+ * access to view these files.
+ *
+ * Security Philosophy: we do not use the information provided to find if the file exists on
+ * disk. We use this information only to locate the correct item in the database and then we
+ * *only* use information from the database to find and proxy the correct file. This way all user
+ * input is sanitized against the database before we perform any file I/O.
+ */
+class File_Proxy_Controller extends Controller {
+ const ALLOW_PRIVATE_GALLERY = true;
+ public function __call($function, $args) {
+
+ // Force zlib compression off. Image and movie files are already compressed and
+ // recompressing them is CPU intensive.
+ if (ini_get("zlib.output_compression")) {
+ ini_set("zlib.output_compression", "Off");
+ }
+
+ // request_uri: gallery3/var/albums/foo/bar.jpg?m=1234
+ $request_uri = rawurldecode(Input::instance()->server("REQUEST_URI"));
+
+ // get rid of query parameters
+ // request_uri: gallery3/var/albums/foo/bar.jpg
+ $request_uri = preg_replace("/\?.*/", "", $request_uri);
+
+ // var_uri: gallery3/var/
+ $var_uri = url::file("var/");
+
+ // Make sure that the request is for a file inside var
+ $offset = strpos(rawurldecode($request_uri), $var_uri);
+ if ($offset !== 0) {
+ $e = new Kohana_404_Exception();
+ $e->test_fail_code = 1;
+ throw $e;
+ }
+
+ // file_uri: albums/foo/bar.jpg
+ $file_uri = substr($request_uri, strlen($var_uri));
+
+ // type: albums
+ // path: foo/bar.jpg
+ list ($type, $path) = explode("/", $file_uri, 2);
+ if ($type != "resizes" && $type != "albums" && $type != "thumbs") {
+ $e = new Kohana_404_Exception();
+ $e->test_fail_code = 2;
+ throw $e;
+ }
+
+ // If the last element is .album.jpg, pop that off since it's not a real item
+ $path = preg_replace("|/.album.jpg$|", "", $path);
+
+ $item = item::find_by_path($path);
+ if (!$item->loaded()) {
+ // We didn't turn it up. 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 movie file would
+ // have been converted to a .jpg. So try some alternate types:
+ if (preg_match('/.jpg$/', $path)) {
+ foreach (legal_file::get_movie_extensions() as $ext) {
+ $movie_path = preg_replace('/.jpg$/', ".$ext", $path);
+ $item = item::find_by_path($movie_path);
+ if ($item->loaded()) {
+ break;
+ }
+ }
+ }
+ }
+
+ if (!$item->loaded()) {
+ $e = new Kohana_404_Exception();
+ $e->test_fail_code = 3;
+ throw $e;
+ }
+
+ // Make sure we have access to the item
+ if (!access::can("view", $item)) {
+ $e = new Kohana_404_Exception();
+ $e->test_fail_code = 4;
+ throw $e;
+ }
+
+ // Make sure we have view_full access to the original
+ if ($type == "albums" && !access::can("view_full", $item)) {
+ $e = new Kohana_404_Exception();
+ $e->test_fail_code = 5;
+ throw $e;
+ }
+
+ // Don't try to load a directory
+ if ($type == "albums" && $item->is_album()) {
+ $e = new Kohana_404_Exception();
+ $e->test_fail_code = 6;
+ throw $e;
+ }
+
+ // Note: this code is roughly duplicated in data_rest, so if you modify this, please look to
+ // see if you should make the same change there as well.
+
+ if ($type == "albums") {
+ $file = $item->file_path();
+ } else if ($type == "resizes") {
+ $file = $item->resize_path();
+ } else {
+ $file = $item->thumb_path();
+ }
+
+ if (!file_exists($file)) {
+ $e = new Kohana_404_Exception();
+ $e->test_fail_code = 7;
+ throw $e;
+ }
+
+ if (gallery::show_profiler()) {
+ Profiler::enable();
+ $profiler = new Profiler();
+ $profiler->render();
+ exit;
+ }
+
+ header("Content-Length: " . filesize($file));
+
+ header("Pragma:");
+ // Check that the content hasn't expired or it wasn't changed since cached
+ expires::check(2592000, $item->updated);
+
+ // We don't need to save the session for this request
+ Session::instance()->abort_save();
+
+ expires::set(2592000, $item->updated); // 30 days
+
+ // Dump out the image. If the item is a movie or album, then its thumbnail will be a JPG.
+ if (($item->is_movie() || $item->is_album()) && $type == "thumbs") {
+ header("Content-Type: image/jpeg");
+ } else {
+ header("Content-Type: $item->mime_type");
+ }
+
+ if (TEST_MODE) {
+ return $file;
+ } else {
+ // Don't use Kohana::close_buffers(false) here because that only closes all the buffers
+ // that Kohana started. We want to close *all* buffers at this point because otherwise we're
+ // going to buffer up whatever file we're proxying (and it may be very large). This may
+ // affect embedding or systems with PHP's output_buffering enabled.
+ while (ob_get_level()) {
+ if (!@ob_end_clean()) {
+ // ob_end_clean() can return false if the buffer can't be removed for some reason
+ // (zlib output compression buffers sometimes cause problems).
+ break;
+ }
+ }
+ readfile($file);
+ }
+ }
+}
diff --git a/modules/gallery/controllers/items.php b/modules/gallery/controllers/items.php
new file mode 100644
index 0000000..845df76
--- /dev/null
+++ b/modules/gallery/controllers/items.php
@@ -0,0 +1,43 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 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 Items_Controller extends Controller {
+ public function __call($function, $args) {
+ $item = ORM::factory("item", (int)$function);
+ if (!$item->loaded()) {
+ throw new Kohana_404_Exception();
+ }
+
+ // Redirect to the more specific resource type, since it will render differently. We can't
+ // delegate here because we may have gotten to this page via /items/<id> which means that we
+ // don't have a type-specific controller. Also, we want to drive a single canonical resource
+ // mapping where possible.
+ access::required("view", $item);
+ url::redirect($item->abs_url());
+ }
+
+ // Return the width/height dimensions for the given item
+ public function dimensions($id) {
+ $item = ORM::factory("item", $id);
+ access::required("view", $item);
+ json::reply(array("thumb" => array((int)$item->thumb_width, (int)$item->thumb_height),
+ "resize" => array((int)$item->resize_width, (int)$item->resize_height),
+ "full" => array((int)$item->width, (int)$item->height)));
+ }
+}
diff --git a/modules/gallery/controllers/l10n_client.php b/modules/gallery/controllers/l10n_client.php
new file mode 100644
index 0000000..993dfb3
--- /dev/null
+++ b/modules/gallery/controllers/l10n_client.php
@@ -0,0 +1,179 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 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 L10n_Client_Controller extends Controller {
+ public function save() {
+ access::verify_csrf();
+ if (!identity::active_user()->admin) {
+ access::forbidden();
+ }
+
+ $locale = Gallery_I18n::instance()->locale();
+ $input = Input::instance();
+ $key = $input->post("l10n-message-key");
+
+ $root_message = ORM::factory("incoming_translation")
+ ->where("key", "=", $key)
+ ->where("locale", "=", "root")
+ ->find();
+
+ if (!$root_message->loaded()) {
+ throw new Exception("@todo bad request data / illegal state");
+ }
+ $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();
+ foreach($plural_forms as $plural_form) {
+ $value = $input->post("l10n-edit-plural-translation-$plural_form");
+ if (null === $value || !is_string($value)) {
+ 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");
+ }
+ }
+
+ $entry = ORM::factory("outgoing_translation")
+ ->where("key", "=", $key)
+ ->where("locale", "=", $locale)
+ ->find();
+
+ 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_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;
+ }
+
+ $entry->save();
+ }
+
+ Gallery_I18n::clear_cache($locale);
+
+ json::reply(new stdClass());
+ }
+
+ public function toggle_l10n_mode() {
+ access::verify_csrf();
+ if (!identity::active_user()->admin) {
+ access::forbidden();
+ }
+
+ $session = Session::instance();
+ $l10n_mode = $session->get("l10n_mode", false);
+ $session->set("l10n_mode", !$l10n_mode);
+
+ $redirect_url = "admin/languages";
+ if (!$l10n_mode) {
+ $redirect_url .= "#l10n-client";
+ }
+
+ url::redirect($redirect_url);
+ }
+
+ private static function _l10n_client_search_form() {
+ $form = new Forge("#", "", "post", array("id" => "g-l10n-search-form"));
+ $group = $form->group("l10n_search");
+ $group->input("l10n-search")->id("g-l10n-search");
+
+ return $form;
+ }
+
+ public static function l10n_form() {
+ if (Input::instance()->get("show_all_l10n_messages")) {
+ $calls = array();
+ foreach (db::build()
+ ->select("key", "message")
+ ->from("incoming_translations")
+ ->where("locale", "=", "root")
+ ->execute() as $row) {
+ $calls[$row->key] = array(unserialize($row->message), array());
+ }
+ } else {
+ $calls = Gallery_I18n::instance()->call_log();
+ }
+ $locale = Gallery_I18n::instance()->locale();
+
+ if ($calls) {
+ $translations = array();
+ foreach (db::build()
+ ->select("key", "translation")
+ ->from("incoming_translations")
+ ->where("locale", "=", $locale)
+ ->execute() as $row) {
+ $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) {
+ $translations[$row->key] = unserialize($row->translation);
+ }
+
+ $string_list = array();
+ $cache = array();
+ foreach ($calls as $key => $call) {
+ list ($message, $options) = $call;
+ // Ensure that the message is in the DB
+ l10n_scanner::process_message($message, $cache);
+ // Note: Not interpolating placeholders for the actual translation input field.
+ // TODO: Might show a preview w/ interpolations (using $options)
+ $translation = isset($translations[$key]) ? $translations[$key] : '';
+ $string_list[] = array('source' => $message,
+ 'key' => $key,
+ 'translation' => $translation);
+ }
+
+ $v = new View('l10n_client.html');
+ $v->string_list = $string_list;
+ $v->l10n_search_form = self::_l10n_client_search_form();
+ $v->plural_forms = l10n_client::plural_forms($locale);
+ return $v;
+ }
+
+ return '';
+ }
+}
diff --git a/modules/gallery/controllers/login.php b/modules/gallery/controllers/login.php
new file mode 100644
index 0000000..9da575b
--- /dev/null
+++ b/modules/gallery/controllers/login.php
@@ -0,0 +1,90 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 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 Login_Controller extends Controller {
+ const ALLOW_MAINTENANCE_MODE = true;
+ const ALLOW_PRIVATE_GALLERY = true;
+
+ public function ajax() {
+ $view = new View("login_ajax.html");
+ $view->form = auth::get_login_form("login/auth_ajax");
+ print $view;
+ }
+
+ public function auth_ajax() {
+ access::verify_csrf();
+
+ list ($valid, $form) = $this->_auth("login/auth_ajax");
+ if ($valid) {
+ json::reply(array("result" => "success"));
+ } else {
+ $view = new View("login_ajax.html");
+ $view->form = $form;
+ json::reply(array("result" => "error", "html" => (string)$view));
+ }
+ }
+
+ public function html() {
+ $view = new Theme_View("page.html", "other", "login");
+ $view->page_title = t("Log in to Gallery");
+ $view->content = new View("login_ajax.html");
+ $view->content->form = auth::get_login_form("login/auth_html");
+ print $view;
+ }
+
+ public function auth_html() {
+ access::verify_csrf();
+
+ list ($valid, $form) = $this->_auth("login/auth_html");
+ if ($valid) {
+ $continue_url = $form->continue_url->value;
+ url::redirect($continue_url ? $continue_url : item::root()->abs_url());
+ } else {
+ $view = new Theme_View("page.html", "other", "login");
+ $view->page_title = t("Log in to Gallery");
+ $view->content = new View("login_ajax.html");
+ $view->content->form = $form;
+ print $view;
+ }
+ }
+
+ private function _auth($url) {
+ $form = auth::get_login_form($url);
+ $valid = $form->validate();
+ if ($valid) {
+ $user = identity::lookup_user_by_name($form->login->inputs["name"]->value);
+ if (empty($user) || !identity::is_correct_password($user, $form->login->password->value)) {
+ $form->login->inputs["name"]->add_error("invalid_login", 1);
+ $name = $form->login->inputs["name"]->value;
+ log::warning("user", t("Failed login for %name", array("name" => $name)));
+ module::event("user_auth_failed", $name);
+ $valid = false;
+ }
+ }
+
+ if ($valid) {
+ auth::login($user);
+ }
+
+ // Either way, regenerate the session id to avoid session trapping
+ Session::instance()->regenerate();
+
+ return array($valid, $form);
+ }
+} \ No newline at end of file
diff --git a/modules/gallery/controllers/logout.php b/modules/gallery/controllers/logout.php
new file mode 100644
index 0000000..9a24d1b
--- /dev/null
+++ b/modules/gallery/controllers/logout.php
@@ -0,0 +1,29 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 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 Logout_Controller extends Controller {
+ public function index() {
+ access::verify_csrf();
+ auth::logout();
+ if ($continue_url = Input::instance()->get("continue_url")) {
+ url::redirect($continue_url);
+ }
+ url::redirect(item::root()->abs_url());
+ }
+} \ No newline at end of file
diff --git a/modules/gallery/controllers/movies.php b/modules/gallery/controllers/movies.php
new file mode 100644
index 0000000..5607571
--- /dev/null
+++ b/modules/gallery/controllers/movies.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-2013 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 Movies_Controller extends Items_Controller {
+ public function show($movie) {
+ if (!is_object($movie)) {
+ // show() must be public because we route to it in url::parse_url(), so make
+ // sure that we're actually receiving an object
+ throw new Kohana_404_Exception();
+ }
+
+ access::required("view", $movie);
+
+ $template = new Theme_View("page.html", "item", "movie");
+ $template->set_global(array("item" => $movie,
+ "children" => array(),
+ "children_count" => 0));
+ $template->set_global(item::get_display_context($movie));
+ $template->content = new View("movie.html");
+
+ $movie->increment_view_count();
+
+ print $template;
+ }
+
+ public function update($movie_id) {
+ access::verify_csrf();
+ $movie = ORM::factory("item", $movie_id);
+ access::required("view", $movie);
+ access::required("edit", $movie);
+
+ $form = movie::get_edit_form($movie);
+ try {
+ $valid = $form->validate();
+ $movie->title = $form->edit_item->title->value;
+ $movie->description = $form->edit_item->description->value;
+ $movie->slug = $form->edit_item->slug->value;
+ $movie->name = $form->edit_item->inputs["name"]->value;
+ $movie->validate();
+ } catch (ORM_Validation_Exception $e) {
+ // Translate ORM validation errors into form error messages
+ foreach ($e->validation->errors() as $key => $error) {
+ $form->edit_item->inputs[$key]->add_error($error, 1);
+ }
+ $valid = false;
+ }
+
+ if ($valid) {
+ $movie->save();
+ module::event("item_edit_form_completed", $movie, $form);
+
+ log::success("content", "Updated movie", "<a href=\"{$movie->url()}\">view</a>");
+ message::success(
+ t("Saved movie %movie_title", array("movie_title" => html::purify($movie->title))));
+
+ if ($form->from_id->value == $movie->id) {
+ // Use the new url; it might have changed.
+ json::reply(array("result" => "success", "location" => $movie->url()));
+ } else {
+ // Stay on the same page
+ json::reply(array("result" => "success"));
+ }
+ } else {
+ json::reply(array("result" => "error", "html" => (string) $form));
+ }
+ }
+
+ public function form_edit($movie_id) {
+ $movie = ORM::factory("item", $movie_id);
+ access::required("view", $movie);
+ access::required("edit", $movie);
+
+ print movie::get_edit_form($movie);
+ }
+}
diff --git a/modules/gallery/controllers/packager.php b/modules/gallery/controllers/packager.php
new file mode 100644
index 0000000..d7e3cf4
--- /dev/null
+++ b/modules/gallery/controllers/packager.php
@@ -0,0 +1,191 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 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 Packager_Controller extends Controller {
+ function package() {
+ if (PHP_SAPI != "cli") {
+ access::forbidden();
+ }
+
+ $_SERVER["HTTP_HOST"] = "example.com";
+
+ try {
+ $this->_reset(); // empty and reinstall the standard modules
+ $this->_dump_database(); // Dump the database
+ $this->_dump_var(); // Dump the var directory
+ } catch (Exception $e) {
+ print $e->getMessage() . "\n" . $e->getTraceAsString();
+ return;
+ }
+
+ print "Successfully wrote install.sql and init_var.php\n";
+ }
+
+ private function _reset() {
+ // Drop all tables
+ foreach (Database::instance()->list_tables() as $table) {
+ Database::instance()->query("DROP TABLE IF EXISTS {{$table}}");
+ }
+
+ // Clean out data
+ dir::unlink(VARPATH . "uploads");
+ dir::unlink(VARPATH . "albums");
+ dir::unlink(VARPATH . "resizes");
+ dir::unlink(VARPATH . "thumbs");
+ dir::unlink(VARPATH . "modules");
+ dir::unlink(VARPATH . "tmp");
+
+ Database::instance()->clear_cache();
+ module::$modules = array();
+ module::$active = array();
+
+ // Use a known random seed so that subsequent packaging runs will reuse the same random
+ // numbers, keeping our install.sql file more stable.
+ srand(0);
+
+ foreach (array("gallery", "user", "comment", "organize", "info",
+ "rss", "search", "slideshow", "tag") as $module_name) {
+ module::install($module_name);
+ module::activate($module_name);
+ }
+ }
+
+ private function _dump_database() {
+ // We now have a clean install with just the packages that we want. Make sure that the
+ // database is clean too.
+ $i = 1;
+ foreach (array("dashboard_sidebar", "dashboard_center", "site_sidebar") as $key) {
+ $blocks = array();
+ foreach (unserialize(module::get_var("gallery", "blocks_{$key}")) as $rnd => $value) {
+ $blocks[++$i] = $value;
+ }
+ module::set_var("gallery", "blocks_{$key}", serialize($blocks));
+ }
+
+ Database::instance()->query("TRUNCATE {caches}");
+ Database::instance()->query("TRUNCATE {sessions}");
+ Database::instance()->query("TRUNCATE {logs}");
+ db::build()->update("users")
+ ->set(array("password" => ""))
+ ->where("id", "in", array(1, 2))
+ ->execute();
+
+ $dbconfig = Kohana::config('database.default');
+ $conn = $dbconfig["connection"];
+ $sql_file = DOCROOT . "installer/install.sql";
+ if (!is_writable($sql_file)) {
+ print "$sql_file is not writeable";
+ return;
+ }
+ $command = sprintf(
+ "mysqldump --compact --skip-extended-insert --add-drop-table %s %s %s %s > $sql_file",
+ escapeshellarg("-h{$conn['host']}"),
+ escapeshellarg("-u{$conn['user']}"),
+ $conn['pass'] ? escapeshellarg("-p{$conn['pass']}") : "",
+ escapeshellarg($conn['database']));
+ exec($command, $output, $status);
+ if ($status) {
+ print "<pre>";
+ print "$command\n";
+ print "Failed to dump database\n";
+ print implode("\n", $output);
+ return;
+ }
+
+ // Post-process the sql file
+ $buf = "";
+ $root = ORM::factory("item", 1);
+ $root_created_timestamp = $root->created;
+ $root_updated_timestamp = $root->updated;
+ $table_name = "";
+ foreach (file($sql_file) as $line) {
+ // Prefix tables
+ $line = preg_replace(
+ "/(CREATE TABLE|IF EXISTS|INSERT INTO) `{$dbconfig['table_prefix']}(\w+)`/", "\\1 {\\2}",
+ $line);
+
+ if (preg_match("/CREATE TABLE {(\w+)}/", $line, $matches)) {
+ $table_name = $matches[1];
+ }
+ // Normalize dates
+ $line = preg_replace("/,$root_created_timestamp,/", ",UNIX_TIMESTAMP(),", $line);
+ $line = preg_replace("/,$root_updated_timestamp,/", ",UNIX_TIMESTAMP(),", $line);
+
+ // Remove ENGINE= specifications execpt for search records, it always needs to be MyISAM
+ if ($table_name != "search_records") {
+ $line = preg_replace("/ENGINE=\S+ /", "", $line);
+ }
+
+ // Null out ids in the vars table since it's an auto_increment table and this will result in
+ // more stable values so we'll have less churn in install.sql.
+ $line = preg_replace(
+ "/^INSERT INTO {vars} VALUES \(\d+/", "INSERT INTO {vars} VALUES (NULL", $line);
+
+ $buf .= $line;
+ }
+ $fd = fopen($sql_file, "wb");
+ fwrite($fd, $buf);
+ fclose($fd);
+ }
+
+ private function _dump_var() {
+ $objects = new RecursiveIteratorIterator(
+ new RecursiveDirectoryIterator(VARPATH),
+ RecursiveIteratorIterator::SELF_FIRST);
+
+ $var_file = DOCROOT . "installer/init_var.php";
+ if (!is_writable($var_file)) {
+ print "$var_file is not writeable";
+ return;
+ }
+
+ $paths = array();
+ foreach($objects as $name => $file){
+ $path = $file->getPath();
+ $basename = $file->getBasename();
+ if ($basename == "database.php" || $basename == "." || $basename == "..") {
+ continue;
+ } else if (basename($path) == "logs" && $basename != ".htaccess") {
+ continue;
+ }
+
+ if ($file->isDir()) {
+ $paths[] = "VARPATH . \"" . substr($name, strlen(VARPATH)) . "\"";
+ } else {
+ // @todo: serialize non-directories
+ $files["VARPATH . \"" . substr($name, strlen(VARPATH)) . "\""] =
+ base64_encode(file_get_contents($name));
+ }
+ }
+ // Sort the paths so that the var file is stable
+ sort($paths);
+
+ $fd = fopen($var_file, "w");
+ fwrite($fd, "<?php defined(\"SYSPATH\") or die(\"No direct script access.\") ?>\n");
+ fwrite($fd, "<?php\n");
+ foreach ($paths as $path) {
+ fwrite($fd, "!file_exists($path) && mkdir($path);\n");
+ }
+ ksort($files);
+ foreach ($files as $file => $contents) {
+ fwrite($fd, "file_put_contents($file, base64_decode(\"$contents\"));\n");
+ }
+ fclose($fd);
+ }
+} \ No newline at end of file
diff --git a/modules/gallery/controllers/permissions.php b/modules/gallery/controllers/permissions.php
new file mode 100644
index 0000000..2513f86
--- /dev/null
+++ b/modules/gallery/controllers/permissions.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-2013 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 Permissions_Controller extends Controller {
+ function browse($id) {
+ $item = ORM::factory("item", $id);
+ access::required("view", $item);
+ access::required("edit", $item);
+
+ if (!$item->is_album()) {
+ access::forbidden();
+ }
+
+ $view = new View("permissions_browse.html");
+ $view->htaccess_works = access::htaccess_works();
+ $view->item = $item;
+ $view->parents = $item->parents();
+ $view->form = $this->_get_form($item);
+
+ print $view;
+ }
+
+ function form($id) {
+ $item = ORM::factory("item", $id);
+ access::required("view", $item);
+ access::required("edit", $item);
+
+ if (!$item->is_album()) {
+ access::forbidden();
+ }
+
+ print $this->_get_form($item);
+ }
+
+ function change($command, $group_id, $perm_id, $item_id) {
+ access::verify_csrf();
+
+ $group = identity::lookup_group($group_id);
+ $perm = ORM::factory("permission", $perm_id);
+ $item = ORM::factory("item", $item_id);
+ access::required("view", $item);
+ access::required("edit", $item);
+
+ if (!empty($group) && $perm->loaded() && $item->loaded()) {
+ switch($command) {
+ case "allow":
+ access::allow($group, $perm->name, $item);
+ break;
+
+ case "deny":
+ access::deny($group, $perm->name, $item);
+ break;
+
+ case "reset":
+ 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(identity::active_user(), "edit", $item)) {
+ access::allow($group, $perm->name, $item);
+ }
+ }
+ }
+ }
+
+ private function _get_form($item) {
+ $view = new View("permissions_form.html");
+ $view->item = $item;
+ $view->groups = identity::groups();
+ $view->permissions = ORM::factory("permission")->find_all();
+ return $view;
+ }
+}
diff --git a/modules/gallery/controllers/photos.php b/modules/gallery/controllers/photos.php
new file mode 100644
index 0000000..96a22c5
--- /dev/null
+++ b/modules/gallery/controllers/photos.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-2013 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 Photos_Controller extends Items_Controller {
+ public function show($photo) {
+ if (!is_object($photo)) {
+ // show() must be public because we route to it in url::parse_url(), so make
+ // sure that we're actually receiving an object
+ throw new Kohana_404_Exception();
+ }
+
+ access::required("view", $photo);
+
+ $template = new Theme_View("page.html", "item", "photo");
+ $template->set_global(array("item" => $photo,
+ "children" => array(),
+ "children_count" => 0));
+ $template->set_global(item::get_display_context($photo));
+ $template->content = new View("photo.html");
+
+ $photo->increment_view_count();
+
+ print $template;
+ }
+
+ public function update($photo_id) {
+ access::verify_csrf();
+ $photo = ORM::factory("item", $photo_id);
+ access::required("view", $photo);
+ access::required("edit", $photo);
+
+ $form = photo::get_edit_form($photo);
+ try {
+ $valid = $form->validate();
+ $photo->title = $form->edit_item->title->value;
+ $photo->description = $form->edit_item->description->value;
+ $photo->slug = $form->edit_item->slug->value;
+ $photo->name = $form->edit_item->inputs["name"]->value;
+ $photo->validate();
+ } catch (ORM_Validation_Exception $e) {
+ // Translate ORM validation errors into form error messages
+ foreach ($e->validation->errors() as $key => $error) {
+ $form->edit_item->inputs[$key]->add_error($error, 1);
+ }
+ $valid = false;
+ }
+
+ if ($valid) {
+ $photo->save();
+ module::event("item_edit_form_completed", $photo, $form);
+
+ log::success("content", "Updated photo", "<a href=\"{$photo->url()}\">view</a>");
+ message::success(
+ t("Saved photo %photo_title", array("photo_title" => html::purify($photo->title))));
+
+ if ($form->from_id->value == $photo->id) {
+ // Use the new url; it might have changed.
+ json::reply(array("result" => "success", "location" => $photo->url()));
+ } else {
+ // Stay on the same page
+ json::reply(array("result" => "success"));
+ }
+ } else {
+ json::reply(array("result" => "error", "html" => (string)$form));
+ }
+ }
+
+ public function form_edit($photo_id) {
+ $photo = ORM::factory("item", $photo_id);
+ access::required("view", $photo);
+ access::required("edit", $photo);
+
+ print photo::get_edit_form($photo);
+ }
+}
diff --git a/modules/gallery/controllers/quick.php b/modules/gallery/controllers/quick.php
new file mode 100644
index 0000000..4b21d9e
--- /dev/null
+++ b/modules/gallery/controllers/quick.php
@@ -0,0 +1,144 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 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 Quick_Controller extends Controller {
+ public function rotate($id, $dir) {
+ access::verify_csrf();
+ $item = model_cache::get("item", $id);
+ access::required("view", $item);
+ access::required("edit", $item);
+
+ $degrees = 0;
+ switch($dir) {
+ case "ccw":
+ $degrees = -90;
+ break;
+
+ case "cw":
+ $degrees = 90;
+ break;
+ }
+
+ if ($degrees) {
+ $tmpfile = system::temp_filename("rotate",
+ pathinfo($item->file_path(), PATHINFO_EXTENSION));
+ gallery_graphics::rotate($item->file_path(), $tmpfile, array("degrees" => $degrees), $item);
+ $item->set_data_file($tmpfile);
+ $item->save();
+ }
+
+ if (Input::instance()->get("page_type") == "collection") {
+ json::reply(
+ array("src" => $item->thumb_url(),
+ "width" => $item->thumb_width,
+ "height" => $item->thumb_height));
+ } else {
+ json::reply(
+ array("src" => $item->resize_url(),
+ "width" => $item->resize_width,
+ "height" => $item->resize_height));
+ }
+ }
+
+ public function make_album_cover($id) {
+ access::verify_csrf();
+
+ $item = model_cache::get("item", $id);
+ access::required("view", $item);
+ access::required("view", $item->parent());
+ access::required("edit", $item->parent());
+
+ $msg = t("Made <b>%title</b> this album's cover", array("title" => html::purify($item->title)));
+
+ item::make_album_cover($item);
+ message::success($msg);
+
+ json::reply(array("result" => "success", "reload" => 1));
+ }
+
+ public function form_delete($id) {
+ $item = model_cache::get("item", $id);
+ access::required("view", $item);
+ access::required("edit", $item);
+
+ $v = new View("quick_delete_confirm.html");
+ $v->item = $item;
+ $v->form = item::get_delete_form($item);
+ print $v;
+ }
+
+ public function delete($id) {
+ access::verify_csrf();
+ $item = model_cache::get("item", $id);
+ access::required("view", $item);
+ access::required("edit", $item);
+
+ if ($item->is_album()) {
+ $msg = t("Deleted album <b>%title</b>", array("title" => html::purify($item->title)));
+ } else {
+ $msg = t("Deleted photo <b>%title</b>", array("title" => html::purify($item->title)));
+ }
+
+ $parent = $item->parent();
+
+ if ($item->is_album()) {
+ // Album delete will trigger deletes for all children. Do this in a batch so that we can be
+ // smart about notifications, album cover updates, etc.
+ batch::start();
+ $item->delete();
+ batch::stop();
+ } else {
+ $item->delete();
+ }
+ message::success($msg);
+
+ $from_id = Input::instance()->get("from_id");
+ if (Input::instance()->get("page_type") == "collection" &&
+ $from_id != $id /* deleted the item we were viewing */) {
+ json::reply(array("result" => "success", "reload" => 1));
+ } else {
+ json::reply(array("result" => "success", "location" => $parent->url()));
+ }
+ }
+
+ public function form_edit($id) {
+ $item = model_cache::get("item", $id);
+ access::required("view", $item);
+ access::required("edit", $item);
+
+ switch ($item->type) {
+ case "album":
+ $form = album::get_edit_form($item);
+ break;
+
+ case "photo":
+ $form = photo::get_edit_form($item);
+ break;
+
+ case "movie":
+ $form = movie::get_edit_form($item);
+ break;
+ }
+
+ // Pass on the source item where this form was generated, so we have an idea where to return to.
+ $form->hidden("from_id")->value((int)Input::instance()->get("from_id", 0));
+
+ print $form;
+ }
+}
diff --git a/modules/gallery/controllers/reauthenticate.php b/modules/gallery/controllers/reauthenticate.php
new file mode 100644
index 0000000..c79b76e
--- /dev/null
+++ b/modules/gallery/controllers/reauthenticate.php
@@ -0,0 +1,105 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 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 Reauthenticate_Controller extends Controller {
+ public function index() {
+ $is_ajax = Session::instance()->get_once("is_ajax_request", request::is_ajax());
+ if (!identity::active_user()->admin) {
+ if ($is_ajax) {
+ // We should never be able to get here since Admin_Controller::_reauth_check() won't work
+ // for non-admins.
+ access::forbidden();
+ } else {
+ url::redirect(item::root()->abs_url());
+ }
+ }
+
+ // On redirects from the admin controller, the ajax request indicator is lost,
+ // so we store it in the session.
+ if ($is_ajax) {
+ $v = new View("reauthenticate.html");
+ $v->form = self::_form();
+ $v->user_name = identity::active_user()->name;
+ print $v;
+ } else {
+ self::_show_form(self::_form());
+ }
+ }
+
+ public function auth() {
+ if (!identity::active_user()->admin) {
+ access::forbidden();
+ }
+ access::verify_csrf();
+
+ $form = self::_form();
+ $valid = $form->validate();
+ $user = identity::active_user();
+ if ($valid) {
+ module::event("user_auth", $user);
+ if (!request::is_ajax()) {
+ message::success(t("Successfully re-authenticated!"));
+ }
+ url::redirect(Session::instance()->get_once("continue_url"));
+ } else {
+ $name = $user->name;
+ log::warning("user", t("Failed re-authentication for %name", array("name" => $name)));
+ module::event("user_auth_failed", $name);
+ if (request::is_ajax()) {
+ $v = new View("reauthenticate.html");
+ $v->form = $form;
+ $v->user_name = identity::active_user()->name;
+ json::reply(array("html" => (string)$v));
+ } else {
+ self::_show_form($form);
+ }
+ }
+ }
+
+ private static function _show_form($form) {
+ $view = new Theme_View("page.html", "other", "reauthenticate");
+ $view->page_title = t("Re-authenticate");
+ $view->content = new View("reauthenticate.html");
+ $view->content->form = $form;
+ $view->content->user_name = identity::active_user()->name;
+
+ print $view;
+ }
+
+ private static function _form() {
+ $form = new Forge("reauthenticate/auth", "", "post", array("id" => "g-reauthenticate-form"));
+ $form->set_attr("class", "g-narrow");
+ $group = $form->group("reauthenticate")->label(t("Re-authenticate"));
+ $group->password("password")->label(t("Password"))->id("g-password")->class(null)
+ ->callback("auth::validate_too_many_failed_auth_attempts")
+ ->callback("Reauthenticate_Controller::valid_password")
+ ->error_messages("invalid_password", t("Incorrect password"))
+ ->error_messages(
+ "too_many_failed_auth_attempts",
+ t("Too many incorrect passwords. Try again later"));
+ $group->submit("")->value(t("Submit"));
+ return $form;
+ }
+
+ static function valid_password($password_input) {
+ if (!identity::is_correct_password(identity::active_user(), $password_input->value)) {
+ $password_input->add_error("invalid_password", 1);
+ }
+ }
+}
diff --git a/modules/gallery/controllers/upgrader.php b/modules/gallery/controllers/upgrader.php
new file mode 100644
index 0000000..6b3a9ef
--- /dev/null
+++ b/modules/gallery/controllers/upgrader.php
@@ -0,0 +1,118 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 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 Upgrader_Controller extends Controller {
+ public function index() {
+ $session = Session::instance();
+
+ // Make sure we have an upgrade token
+ if (!($upgrade_token = $session->get("upgrade_token", null))) {
+ $session->set("upgrade_token", $upgrade_token = random::hash());
+ }
+
+ // If the upgrade token exists, then bless this session
+ if (file_exists(TMPPATH . $upgrade_token)) {
+ $session->set("can_upgrade", true);
+ @unlink(TMPPATH . $upgrade_token);
+ }
+
+ $available_upgrades = 0;
+ foreach (module::available() as $module) {
+ if ($module->version && $module->version != $module->code_version) {
+ $available_upgrades++;
+ }
+ }
+
+ $failed = Input::instance()->get("failed");
+ $view = new View("upgrader.html");
+ $view->can_upgrade = identity::active_user()->admin || $session->get("can_upgrade");
+ $view->upgrade_token = $upgrade_token;
+ $view->available = module::available();
+ $view->failed = $failed ? explode(",", $failed) : array();
+ $view->done = $available_upgrades == 0;
+ $view->obsolete_modules_message = module::get_obsolete_modules_message();
+ print $view;
+ }
+
+ public function upgrade() {
+ if (php_sapi_name() == "cli") {
+ // @todo this may screw up some module installers, but we don't have a better answer at
+ // this time.
+ $_SERVER["HTTP_HOST"] = "example.com";
+ } else {
+ if (!identity::active_user()->admin && !Session::instance()->get("can_upgrade", false)) {
+ access::forbidden();
+ }
+
+ try {
+ access::verify_csrf();
+ } catch (Exception $e) {
+ url::redirect("upgrader");
+ }
+ }
+
+ $available = module::available();
+ // Upgrade gallery first
+ $gallery = $available["gallery"];
+ if ($gallery->code_version != $gallery->version) {
+ module::upgrade("gallery");
+ module::activate("gallery");
+ }
+
+ // Then upgrade the rest
+ $failed = array();
+ foreach (module::available() as $id => $module) {
+ if ($id == "gallery") {
+ continue;
+ }
+
+ if ($module->active && $module->code_version != $module->version) {
+ try {
+ module::upgrade($id);
+ } catch (Exception $e) {
+ // @todo assume it's MODULE_FAILED_TO_UPGRADE for now
+ $failed[] = $id;
+ }
+ }
+ }
+
+ // If the upgrade failed, this will get recreated
+ site_status::clear("upgrade_now");
+
+ // Clear any upgrade check strings, we are probably up to date.
+ site_status::clear("upgrade_checker");
+
+ if (php_sapi_name() == "cli") {
+ if ($failed) {
+ print "Upgrade completed ** WITH FAILURES **\n";
+ print "The following modules were not successfully upgraded:\n";
+ print " " . implode($failed, "\n ") . "\n";
+ print "Try getting newer versions or deactivating those modules\n";
+ } else {
+ print "Upgrade complete\n";
+ }
+ } else {
+ if ($failed) {
+ url::redirect("upgrader?failed=" . join(",", $failed));
+ } else {
+ url::redirect("upgrader");
+ }
+ }
+ }
+}
diff --git a/modules/gallery/controllers/uploader.php b/modules/gallery/controllers/uploader.php
new file mode 100644
index 0000000..8e09dbe
--- /dev/null
+++ b/modules/gallery/controllers/uploader.php
@@ -0,0 +1,133 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 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 Uploader_Controller extends Controller {
+ public function index($id) {
+ $item = ORM::factory("item", $id);
+ access::required("view", $item);
+ access::required("add", $item);
+ if (!$item->is_album()) {
+ $item = $item->parent();
+ }
+
+ print $this->_get_add_form($item);
+ }
+
+ public function start() {
+ access::verify_csrf();
+ batch::start();
+ }
+
+ public function add_photo($id) {
+ $album = ORM::factory("item", $id);
+ access::required("view", $album);
+ access::required("add", $album);
+ access::verify_csrf();
+
+ // The Flash uploader not call /start directly, so simulate it here for now.
+ if (!batch::in_progress()) {
+ batch::start();
+ }
+
+ $form = $this->_get_add_form($album);
+
+ // Uploadify adds its own field to the form, so validate that separately.
+ $file_validation = new Validation($_FILES);
+ $file_validation->add_rules(
+ "Filedata", "upload::valid", "upload::required",
+ "upload::type[" . implode(",", legal_file::get_extensions()) . "]");
+
+ if ($form->validate() && $file_validation->validate()) {
+ $temp_filename = upload::save("Filedata");
+ system::delete_later($temp_filename);
+ try {
+ $item = ORM::factory("item");
+ $item->name = substr(basename($temp_filename), 10); // Skip unique identifier Kohana adds
+ $item->title = item::convert_filename_to_title($item->name);
+ $item->parent_id = $album->id;
+ $item->set_data_file($temp_filename);
+
+ $path_info = @pathinfo($temp_filename);
+ if (array_key_exists("extension", $path_info) &&
+ legal_file::get_movie_extensions($path_info["extension"])) {
+ $item->type = "movie";
+ $item->save();
+ log::success("content", t("Added a movie"),
+ html::anchor("movies/$item->id", t("view movie")));
+ } else {
+ $item->type = "photo";
+ $item->save();
+ log::success("content", t("Added a photo"),
+ html::anchor("photos/$item->id", t("view photo")));
+ }
+
+ module::event("add_photos_form_completed", $item, $form);
+ } catch (Exception $e) {
+ // The Flash uploader has no good way of reporting complex errors, so just keep it simple.
+ Kohana_Log::add("error", $e->getMessage() . "\n" . $e->getTraceAsString());
+
+ // Ugh. I hate to use instanceof, But this beats catching the exception separately since
+ // we mostly want to treat it the same way as all other exceptions
+ if ($e instanceof ORM_Validation_Exception) {
+ Kohana_Log::add("error", "Validation errors: " . print_r($e->validation->errors(), 1));
+ }
+
+ header("HTTP/1.1 500 Internal Server Error");
+ print "ERROR: " . $e->getMessage();
+ return;
+ }
+ print "FILEID: $item->id";
+ } else {
+ header("HTTP/1.1 400 Bad Request");
+ print "ERROR: " . t("Invalid upload");
+ }
+ }
+
+ public function status($success_count, $error_count) {
+ if ($error_count) {
+ // The "errors" won't be properly pluralized :-/
+ print t2("Uploaded %count photo (%error errors)",
+ "Uploaded %count photos (%error errors)",
+ (int)$success_count,
+ array("error" => (int)$error_count));
+ } else {
+ print t2("Uploaded %count photo", "Uploaded %count photos", $success_count);}
+ }
+
+ public function finish() {
+ access::verify_csrf();
+
+ batch::stop();
+ json::reply(array("result" => "success"));
+ }
+
+ private function _get_add_form($album) {
+ $form = new Forge("uploader/finish", "", "post", array("id" => "g-add-photos-form"));
+ $group = $form->group("add_photos")
+ ->label(t("Add photos to %album_title", array("album_title" => html::purify($album->title))));
+ $group->uploadify("uploadify")->album($album);
+
+ $group = $form->group("actions");
+ $group->uploadify_buttons("");
+
+ module::event("add_photos_form", $album, $form);
+
+ return $form;
+ }
+}
diff --git a/modules/gallery/controllers/user_profile.php b/modules/gallery/controllers/user_profile.php
new file mode 100644
index 0000000..cf589da
--- /dev/null
+++ b/modules/gallery/controllers/user_profile.php
@@ -0,0 +1,108 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 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_Profile_Controller extends Controller {
+
+ public function show($id) {
+ // If we get here, then we should have a user id other than guest.
+ $user = identity::lookup_user($id);
+ if (!$user) {
+ throw new Kohana_404_Exception();
+ }
+
+ if (!$this->_can_view_profile_pages($user)) {
+ throw new Kohana_404_Exception();
+ }
+
+ $v = new Theme_View("page.html", "other", "profile");
+ $v->page_title = t("%name Profile", array("name" => $user->display_name()));
+ $v->content = new View("user_profile.html");
+
+ $v->content->user = $user;
+ $v->content->contactable =
+ !$user->guest && $user->id != identity::active_user()->id && $user->email;
+ $v->content->editable =
+ identity::is_writable() && !$user->guest && $user->id == identity::active_user()->id;
+
+ $event_data = (object)array("user" => $user, "content" => array());
+ module::event("show_user_profile", $event_data);
+ $v->content->info_parts = $event_data->content;
+
+ print $v;
+ }
+
+ public function contact($id) {
+ $user = identity::lookup_user($id);
+ if (!$this->_can_view_profile_pages($user)) {
+ throw new Kohana_404_Exception();
+ }
+
+ print user_profile::get_contact_form($user);
+ }
+
+ public function send($id) {
+ access::verify_csrf();
+ $user = identity::lookup_user($id);
+ if (!$this->_can_view_profile_pages($user)) {
+ throw new Kohana_404_Exception();
+ }
+
+ $form = user_profile::get_contact_form($user);
+ if ($form->validate()) {
+ Sendmail::factory()
+ ->to($user->email)
+ ->subject(html::clean($form->message->subject->value))
+ ->header("Mime-Version", "1.0")
+ ->header("Content-type", "text/html; charset=UTF-8")
+ ->reply_to($form->message->reply_to->value)
+ ->message(html::purify($form->message->message->value))
+ ->send();
+ message::success(t("Sent message to %user_name", array("user_name" => $user->display_name())));
+ json::reply(array("result" => "success"));
+ } else {
+ json::reply(array("result" => "error", "html" => (string)$form));
+ }
+ }
+
+ private function _can_view_profile_pages($user) {
+ if (!$user->loaded()) {
+ return false;
+ }
+
+ if ($user->id == identity::active_user()->id) {
+ // You can always view your own profile
+ return true;
+ }
+
+ switch (module::get_var("gallery", "show_user_profiles_to")) {
+ case "admin_users":
+ return identity::active_user()->admin;
+
+ case "registered_users":
+ return !identity::active_user()->guest;
+
+ case "everybody":
+ return true;
+
+ default:
+ // Fail in private mode on an invalid setting
+ return false;
+ }
+ }
+}
diff --git a/modules/gallery/controllers/welcome_message.php b/modules/gallery/controllers/welcome_message.php
new file mode 100644
index 0000000..bde5e94
--- /dev/null
+++ b/modules/gallery/controllers/welcome_message.php
@@ -0,0 +1,30 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 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 Welcome_Message_Controller extends Controller {
+ public function index() {
+ if (!identity::active_user()->admin) {
+ url::redirect(item::root()->abs_url());
+ }
+
+ $v = new View("welcome_message.html");
+ $v->user = identity::active_user();
+ print $v;
+ }
+}