diff options
Diffstat (limited to 'modules/gallery/controllers')
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; + } +} |
