summaryrefslogtreecommitdiff
path: root/modules/gallery/helpers
diff options
context:
space:
mode:
Diffstat (limited to 'modules/gallery/helpers')
-rw-r--r--modules/gallery/helpers/MY_url.php4
-rw-r--r--modules/gallery/helpers/access.php37
-rw-r--r--modules/gallery/helpers/album.php106
-rw-r--r--modules/gallery/helpers/auth.php55
-rw-r--r--modules/gallery/helpers/gallery_block.php2
-rw-r--r--modules/gallery/helpers/gallery_event.php34
-rw-r--r--modules/gallery/helpers/gallery_installer.php97
-rw-r--r--modules/gallery/helpers/gallery_rest.php248
-rw-r--r--modules/gallery/helpers/gallery_rss.php1
-rw-r--r--modules/gallery/helpers/gallery_task.php28
-rw-r--r--modules/gallery/helpers/graphics.php3
-rw-r--r--modules/gallery/helpers/identity.php10
-rw-r--r--modules/gallery/helpers/item.php40
-rw-r--r--modules/gallery/helpers/item_rest.php176
-rw-r--r--modules/gallery/helpers/l10n_client.php1
-rw-r--r--modules/gallery/helpers/locales.php4
-rw-r--r--modules/gallery/helpers/module.php3
-rw-r--r--modules/gallery/helpers/movie.php128
-rw-r--r--modules/gallery/helpers/photo.php137
-rw-r--r--modules/gallery/helpers/task.php11
20 files changed, 470 insertions, 655 deletions
diff --git a/modules/gallery/helpers/MY_url.php b/modules/gallery/helpers/MY_url.php
index 8a7909b6..323cae37 100644
--- a/modules/gallery/helpers/MY_url.php
+++ b/modules/gallery/helpers/MY_url.php
@@ -93,8 +93,8 @@ class url extends url_Core {
/**
* Just like url::merge except that it escapes any XSS in the path.
*/
- static function merge($params) {
- return htmlspecialchars(parent::merge($params));
+ static function merge(array $arguments) {
+ return htmlspecialchars(parent::merge($arguments));
}
/**
diff --git a/modules/gallery/helpers/access.php b/modules/gallery/helpers/access.php
index e0a0e979..29b981e8 100644
--- a/modules/gallery/helpers/access.php
+++ b/modules/gallery/helpers/access.php
@@ -183,10 +183,10 @@ class access_Core {
}
/**
- * Terminate immediately with an HTTP 503 Forbidden response.
+ * Terminate immediately with an HTTP 403 Forbidden response.
*/
static function forbidden() {
- throw new Exception("@todo FORBIDDEN", 503);
+ throw new Kohana_Exception("@todo FORBIDDEN", null, 403);
}
/**
@@ -663,23 +663,28 @@ class access_Core {
* working and our permission system works.
*/
static function htaccess_works() {
- $success_url = url::file("var/tmp/security_test/success");
+ $success_url = url::file("var/security_test/success");
- @mkdir(VARPATH . "tmp/security_test");
- if ($fp = @fopen(VARPATH . "tmp/security_test/.htaccess", "w+")) {
- fwrite($fp, "RewriteEngine On\n");
- fwrite($fp, "RewriteRule verify $success_url [L]\n");
- fclose($fp);
- }
+ @mkdir(VARPATH . "security_test");
+ try {
+ if ($fp = @fopen(VARPATH . "security_test/.htaccess", "w+")) {
+ fwrite($fp, "RewriteEngine On\n");
+ fwrite($fp, "RewriteRule verify $success_url [L]\n");
+ fclose($fp);
+ }
- if ($fp = @fopen(VARPATH . "tmp/security_test/success", "w+")) {
- fwrite($fp, "success");
- fclose($fp);
- }
+ if ($fp = @fopen(VARPATH . "security_test/success", "w+")) {
+ fwrite($fp, "success");
+ fclose($fp);
+ }
- list ($response) = remote::do_request(url::abs_file("var/tmp/security_test/verify"));
- $works = $response == "HTTP/1.1 200 OK";
- @dir::unlink(VARPATH . "tmp/security_test");
+ list ($response) = remote::do_request(url::abs_file("var/security_test/verify"));
+ $works = $response == "HTTP/1.1 200 OK";
+ } catch (Exception $e) {
+ @dir::unlink(VARPATH . "security_test");
+ throw $e;
+ }
+ @dir::unlink(VARPATH . "security_test");
return $works;
}
diff --git a/modules/gallery/helpers/album.php b/modules/gallery/helpers/album.php
index feaf74cc..389f6e48 100644
--- a/modules/gallery/helpers/album.php
+++ b/modules/gallery/helpers/album.php
@@ -24,90 +24,27 @@
* Note: by design, this class does not do any permission checking.
*/
class album_Core {
- /**
- * Create a new album.
- * @param integer $parent_id id of parent album
- * @param string $name the name of this new album (it will become the directory name on disk)
- * @param integer $title the title of the new album
- * @param string $description (optional) the longer description of this album
- * @param string $slug (optional) the url component for this photo
- * @return Item_Model
- */
- static function create($parent, $name, $title, $description=null, $owner_id=null, $slug=null) {
- if (!$parent->loaded() || !$parent->is_album()) {
- throw new Exception("@todo INVALID_PARENT");
- }
-
- if (strpos($name, "/")) {
- throw new Exception("@todo NAME_CANNOT_CONTAIN_SLASH");
- }
-
- // We don't allow trailing periods as a security measure
- // ref: http://dev.kohanaphp.com/issues/684
- if (rtrim($name, ".") != $name) {
- throw new Exception("@todo NAME_CANNOT_END_IN_PERIOD");
- }
-
- if (empty($slug)) {
- $slug = item::convert_filename_to_slug($name);
- }
-
- $album = ORM::factory("item");
- $album->type = "album";
- $album->title = $title;
- $album->description = $description;
- $album->name = $name;
- $album->owner_id = $owner_id;
- $album->thumb_dirty = 1;
- $album->resize_dirty = 1;
- $album->slug = $slug;
- $album->rand_key = ((float)mt_rand()) / (float)mt_getrandmax();
- $album->sort_column = "created";
- $album->sort_order = "ASC";
-
- // Randomize the name or slug if there's a conflict
- // @todo Improve this. Random numbers are not user friendly
- while (ORM::factory("item")
- ->where("parent_id", "=", $parent->id)
- ->and_open()
- ->where("name", "=", $album->name)
- ->or_where("slug", "=", $album->slug)
- ->close()
- ->find()->id) {
- $rand = rand();
- $album->name = "{$name}-$rand";
- $album->slug = "{$slug}-$rand";
- }
-
- $album = $album->add_to_parent($parent);
- mkdir($album->file_path());
- mkdir(dirname($album->thumb_path()));
- mkdir(dirname($album->resize_path()));
-
- // @todo: publish this from inside Item_Model::save() when we refactor to the point where
- // there's only one save() happening here.
- module::event("item_created", $album);
-
- return $album;
- }
static function get_add_form($parent) {
$form = new Forge("albums/create/{$parent->id}", "", "post", array("id" => "g-add-album-form"));
$group = $form->group("add_album")
->label(t("Add an album to %album_title", array("album_title" => $parent->title)));
- $group->input("title")->label(t("Title"));
+ $group->input("title")->label(t("Title"))
+ ->error_messages("required", t("You must provide a title"))
+ ->error_messages("length", t("Your title is too long"));
$group->textarea("description")->label(t("Description"));
$group->input("name")->label(t("Directory name"))
- ->callback("item::validate_no_slashes")
- ->error_messages("no_slashes", t("The directory name can't contain the \"/\" character"));
+ ->error_messages("no_slashes", t("The directory name can't contain the \"/\" character"))
+ ->error_messages("required", t("You must provide a directory name"))
+ ->error_messages("length", t("Your directory name is too long"));
$group->input("slug")->label(t("Internet Address"))
- ->callback("item::validate_url_safe")
->error_messages(
"not_url_safe",
- t("The internet address should contain only letters, numbers, hyphens and underscores"));
+ t("The internet address should contain only letters, numbers, hyphens and underscores"))
+ ->error_messages("required", t("You must provide an internet address"))
+ ->error_messages("length", t("Your internet address is too long"));
$group->hidden("type")->value("album");
$group->submit("")->value(t("Create"));
- $form->add_rules_from(ORM::factory("item"));
$form->script("")
->url(url::abs_file("modules/gallery/js/albums_form_add.js"));
return $form;
@@ -118,26 +55,28 @@ class album_Core {
$form->hidden("from_id");
$group = $form->group("edit_item")->label(t("Edit Album"));
- $group->input("title")->label(t("Title"))->value($parent->title);
+ $group->input("title")->label(t("Title"))->value($parent->title)
+ ->error_messages("required", t("You must provide a title"))
+ ->error_messages("length", t("Your title is too long"));
$group->textarea("description")->label(t("Description"))->value($parent->description);
if ($parent->id != 1) {
- $group->input("dirname")->label(t("Directory Name"))->value($parent->name)
- ->rules("required")
+ $group->input("name")->label(t("Directory Name"))->value($parent->name)
->error_messages(
- "name_conflict", t("There is already a movie, photo or album with this name"))
- ->callback("item::validate_no_slashes")
+ "conflict", t("There is already a movie, photo or album with this name"))
->error_messages("no_slashes", t("The directory name can't contain a \"/\""))
- ->callback("item::validate_no_trailing_period")
- ->error_messages("no_trailing_period", t("The directory name can't end in \".\""));
+ ->error_messages("no_trailing_period", t("The directory name can't end in \".\""))
+ ->error_messages("required", t("You must provide a directory name"))
+ ->error_messages("length", t("Your directory name is too long"));
$group->input("slug")->label(t("Internet Address"))->value($parent->slug)
->error_messages(
- "slug_conflict", t("There is already a movie, photo or album with this internet address"))
- ->callback("item::validate_url_safe")
+ "conflict", t("There is already a movie, photo or album with this internet address"))
->error_messages(
"not_url_safe",
- t("The internet address should contain only letters, numbers, hyphens and underscores"));
+ t("The internet address should contain only letters, numbers, hyphens and underscores"))
+ ->error_messages("required", t("You must provide an internet address"))
+ ->error_messages("length", t("Your internet address is too long"));
} else {
- $group->hidden("dirname")->value($parent->name);
+ $group->hidden("name")->value($parent->name);
$group->hidden("slug")->value($parent->slug);
}
@@ -159,7 +98,6 @@ class album_Core {
$group = $form->group("buttons")->label("");
$group->hidden("type")->value("album");
$group->submit("")->value(t("Modify"));
- $form->add_rules_from(ORM::factory("item"));
return $form;
}
diff --git a/modules/gallery/helpers/auth.php b/modules/gallery/helpers/auth.php
index 21a39bfb..16f8915a 100644
--- a/modules/gallery/helpers/auth.php
+++ b/modules/gallery/helpers/auth.php
@@ -22,7 +22,10 @@ class auth_Core {
$form = new Forge($url, "", "post", array("id" => "g-login-form"));
$form->set_attr('class', "g-narrow");
$group = $form->group("login")->label(t("Login"));
- $group->input("name")->label(t("Username"))->id("g-username")->class(null);
+ $group->input("name")->label(t("Username"))->id("g-username")->class(null)
+ ->callback("auth::validate_too_many_failed_logins")
+ ->error_messages(
+ "too_many_failed_logins", t("Too many failed login attempts. Try again later"));
$group->password("password")->label(t("Password"))->id("g-password")->class(null);
$group->inputs["name"]->error_messages("invalid_login", t("Invalid name or password"));
$group->submit("")->value(t("Login"));
@@ -30,12 +33,12 @@ class auth_Core {
}
static function login($user) {
+ identity::set_active_user($user);
if (identity::is_writable()) {
$user->login_count += 1;
$user->last_login = time();
$user->save();
}
- identity::set_active_user($user);
log::info("user", t("User %name logged in", array("name" => $user->name)));
module::event("user_login", $user);
}
@@ -51,6 +54,52 @@ class auth_Core {
module::event("user_logout", $user);
}
log::info("user", t("User %name logged out", array("name" => $user->name)),
- html::anchor("user/$user->id", html::clean($user->name)));
+ t('<a href="%url">%user_name</a>',
+ array("url" => user_profile::url($user->id),
+ "user_name" => html::clean($user->name))));
+ }
+
+ /**
+ * After there have been 5 failed login attempts, any failure leads to getting locked out for a
+ * minute.
+ */
+ static function too_many_failed_logins($name) {
+ $failed_login = ORM::factory("failed_login")
+ ->where("name", "=", $name)
+ ->find();
+ return ($failed_login->loaded() &&
+ $failed_login->count > 5 &&
+ (time() - $failed_login->time < 60));
+ }
+
+ static function validate_too_many_failed_logins($name_input) {
+ if (self::too_many_failed_logins($name_input->value)) {
+ $name_input->add_error("too_many_failed_logins", 1);
+ }
+ }
+
+ /**
+ * Record a failed login for this user
+ */
+ static function record_failed_login($name) {
+ $failed_login = ORM::factory("failed_login")
+ ->where("name", "=", $name)
+ ->find();
+ if (!$failed_login->loaded()) {
+ $failed_login->name = $name;
+ }
+ $failed_login->time = time();
+ $failed_login->count++;
+ $failed_login->save();
+ }
+
+ /**
+ * Clear any failed logins for this user
+ */
+ static function record_successful_login($user) {
+ db::build()
+ ->delete("failed_logins")
+ ->where("name", "=", $user->name)
+ ->execute();
}
} \ No newline at end of file
diff --git a/modules/gallery/helpers/gallery_block.php b/modules/gallery/helpers/gallery_block.php
index 9d4e81b6..be0f11b8 100644
--- a/modules/gallery/helpers/gallery_block.php
+++ b/modules/gallery/helpers/gallery_block.php
@@ -72,7 +72,7 @@ class gallery_block_Core {
$block->content = new View("admin_block_platform.html");
if (is_readable("/proc/loadavg")) {
$block->content->load_average =
- join(" ", array_slice(explode(" ", array_shift(file("/proc/loadavg"))), 0, 3));
+ join(" ", array_slice(explode(" ", current(file("/proc/loadavg"))), 0, 3));
} else {
$block->content->load_average = t("Unavailable");
}
diff --git a/modules/gallery/helpers/gallery_event.php b/modules/gallery/helpers/gallery_event.php
index b35ae3c4..6479e2c3 100644
--- a/modules/gallery/helpers/gallery_event.php
+++ b/modules/gallery/helpers/gallery_event.php
@@ -75,6 +75,24 @@ class gallery_event_Core {
static function item_created($item) {
access::add_item($item);
+
+ if ($item->is_photo() || $item->is_movie()) {
+ // Build our thumbnail/resizes.
+ try {
+ graphics::generate($item);
+ } catch (Exception $e) {
+ log::error("graphics", t("Couldn't create a thumbnail or resize for %item_title",
+ array("item_title" => $item->title)),
+ html::anchor($item->abs_url(), t("details")));
+ Kohana_Log::add("error", $e->getMessage() . "\n" . $e->getTraceAsString());
+ }
+
+ // If the parent has no cover item, make this it.
+ $parent = $item->parent();
+ if (access::can("edit", $parent) && $parent->album_cover_item_id == null) {
+ item::make_album_cover($item);
+ }
+ }
}
static function item_deleted($item) {
@@ -92,6 +110,11 @@ class gallery_event_Core {
graphics::choose_default_toolkit();
module::clear_var("gallery", "choose_default_tookit");
}
+ auth::record_successful_login($user);
+ }
+
+ static function user_login_failed($name) {
+ auth::record_failed_login($name);
}
static function item_index_data($item, $data) {
@@ -268,6 +291,7 @@ class gallery_event_Core {
->label(t("Options"))
->css_class("ui-icon-carat-1-n"));
+ $page_type = $theme->page_type();
if (access::can("edit", $item)) {
switch ($item->type) {
case "movie":
@@ -306,7 +330,7 @@ class gallery_event_Core {
->css_class("ui-icon-rotate-ccw")
->ajax_handler("function(data) { " .
"\$.gallery_replace_image(data, \$('$thumb_css_selector')) }")
- ->url(url::site("quick/rotate/$item->id/ccw?csrf=$csrf&from_id=$theme_item->id")))
+ ->url(url::site("quick/rotate/$item->id/ccw?csrf=$csrf&from_id=$theme_item->id&page_type=$page_type")))
->append(
Menu::factory("ajax_link")
->id("rotate_cw")
@@ -314,7 +338,7 @@ class gallery_event_Core {
->css_class("ui-icon-rotate-cw")
->ajax_handler("function(data) { " .
"\$.gallery_replace_image(data, \$('$thumb_css_selector')) }")
- ->url(url::site("quick/rotate/$item->id/cw?csrf=$csrf&from_id=$theme_item->id")));
+ ->url(url::site("quick/rotate/$item->id/cw?csrf=$csrf&from_id=$theme_item->id&page_type=$page_type")));
}
// @todo Don't move photos from the photo page; we don't yet have a good way of redirecting
@@ -354,7 +378,7 @@ class gallery_event_Core {
->label($delete_title)
->css_class("ui-icon-trash")
->css_id("g-quick-delete")
- ->url(url::site("quick/form_delete/$item->id?csrf=$csrf&from_id=$theme_item->id")));
+ ->url(url::site("quick/form_delete/$item->id?csrf=$csrf&from_id=$theme_item->id&page_type=$page_type")));
}
if ($item->is_album()) {
@@ -386,14 +410,14 @@ class gallery_event_Core {
if (!$data->display_all) {
$fields = array("name" => t("Name"), "full_name" => t("Full name"), "url" => "Web site");
}
- $v->fields = array();
+ $v->user_profile_data = array();
foreach ($fields as $field => $label) {
if (!empty($data->user->$field)) {
$value = $data->user->$field;
if ($field == "locale") {
$value = locales::display_name($value);
}
- $v->fields[(string) $label] = html::clean($value);
+ $v->user_profile_data[(string) $label] = $value;
}
}
$data->content[] = (object) array("title" => t("User information"), "view" => $v);
diff --git a/modules/gallery/helpers/gallery_installer.php b/modules/gallery/helpers/gallery_installer.php
index 1e0ad28c..bffef8e6 100644
--- a/modules/gallery/helpers/gallery_installer.php
+++ b/modules/gallery/helpers/gallery_installer.php
@@ -42,6 +42,14 @@ class gallery_installer {
KEY (`tags`))
DEFAULT CHARSET=utf8;");
+ $db->query("CREATE TABLE {failed_logins} (
+ `id` int(9) NOT NULL auto_increment,
+ `count` int(9) NOT NULL,
+ `name` varchar(255) NOT NULL,
+ `time` int(9) NOT NULL,
+ PRIMARY KEY (`id`))
+ DEFAULT CHARSET=utf8;");
+
$db->query("CREATE TABLE {graphics_rules} (
`id` int(9) NOT NULL auto_increment,
`active` BOOLEAN default 0,
@@ -196,6 +204,9 @@ class gallery_installer {
foreach (array("albums", "logs", "modules", "resizes", "thumbs", "tmp", "uploads") as $dir) {
@mkdir(VARPATH . $dir);
+ if (in_array($dir, array("logs", "tmp", "uploads"))) {
+ self::_protect_directory(VARPATH . $dir);
+ }
}
access::register_permission("view", "View");
@@ -209,19 +220,26 @@ class gallery_installer {
t("Edit");
t("Add");
- $root = ORM::factory("item");
- $root->type = "album";
- $root->title = "Gallery";
- $root->description = "";
- $root->left_ptr = 1;
- $root->right_ptr = 2;
- $root->parent_id = 0;
- $root->level = 1;
- $root->thumb_dirty = 1;
- $root->resize_dirty = 1;
- $root->sort_column = "weight";
- $root->sort_order = "ASC";
- $root->save();
+ // Hardcode the first item to sidestep ORM validation rules
+ $now = time();
+ db::build()->insert(
+ "items",
+ array("created" => $now,
+ "description" => "",
+ "left_ptr" => 1,
+ "level" => 1,
+ "parent_id" => 0,
+ "resize_dirty" => 1,
+ "right_ptr" => 2,
+ "sort_column" => "weight",
+ "sort_order" => "ASC",
+ "thumb_dirty" => 1,
+ "title" => "Gallery",
+ "type" => "album",
+ "updated" => $now,
+ "weight" => 1))
+ ->execute();
+ $root = ORM::factory("item", 1);
access::add_item($root);
module::set_var("gallery", "active_site_theme", "wind");
@@ -269,7 +287,7 @@ class gallery_installer {
// @todo this string needs to be picked up by l10n_scanner
module::set_var("gallery", "credits", "Powered by <a href=\"%url\">Gallery %version</a>");
module::set_var("gallery", "simultaneous_upload_limit", 5);
- module::set_version("gallery", 21);
+ module::set_version("gallery", 25);
}
static function upgrade($version) {
@@ -443,7 +461,7 @@ class gallery_installer {
// Update the graphics rules table so that the maximum height for resizes is 640 not 480.
// Fixes ticket #671
- if ( $version == 21) {
+ if ($version == 21) {
$resize_rule = ORM::factory("graphics_rule")
->where("id", "=", "2")
->find();
@@ -456,6 +474,46 @@ class gallery_installer {
}
module::set_version("gallery", $version = 22);
}
+
+ // Update slug values to be legal. We should have done this in the 11->12 upgrader, but I was
+ // lazy. Mea culpa!
+ if ($version == 22) {
+ foreach (db::build()
+ ->from("items")
+ ->select("id", "slug")
+ ->where(new Database_Expression("`slug` REGEXP '[^_A-Za-z0-9-]'"), "=", 1)
+ ->execute() as $row) {
+ $new_slug = item::convert_filename_to_slug($row->slug);
+ if (empty($new_slug)) {
+ $new_slug = rand();
+ }
+ db::build()
+ ->update("items")
+ ->set("slug", $new_slug)
+ ->set("relative_url_cache", null)
+ ->where("id", "=", $row->id)
+ ->execute();
+ }
+ module::set_version("gallery", $version = 23);
+ }
+
+ if ($version == 23) {
+ $db->query("CREATE TABLE {failed_logins} (
+ `id` int(9) NOT NULL auto_increment,
+ `count` int(9) NOT NULL,
+ `name` varchar(255) NOT NULL,
+ `time` int(9) NOT NULL,
+ PRIMARY KEY (`id`))
+ DEFAULT CHARSET=utf8;");
+ module::set_version("gallery", $version = 24);
+ }
+
+ if ($version == 24) {
+ foreach (array("logs", "tmp", "uploads") as $dir) {
+ self::_protect_directory(VARPATH . $dir);
+ }
+ module::set_version("gallery", $version = 25);
+ }
}
static function uninstall() {
@@ -464,6 +522,7 @@ class gallery_installer {
$db->query("DROP TABLE IF EXISTS {access_intents}");
$db->query("DROP TABLE IF EXISTS {graphics_rules}");
$db->query("DROP TABLE IF EXISTS {incoming_translations}");
+ $db->query("DROP TABLE IF EXISTS {failed_logins}");
$db->query("DROP TABLE IF EXISTS {items}");
$db->query("DROP TABLE IF EXISTS {logs}");
$db->query("DROP TABLE IF EXISTS {modules}");
@@ -479,4 +538,12 @@ class gallery_installer {
system("/bin/rm -rf " . VARPATH . $entry);
}
}
+
+ static function _protect_directory($dir) {
+ $fp = @fopen("$dir/.htaccess", "w+");
+ fwrite($fp, "DirectoryIndex .htaccess\nSetHandler Gallery_Security_Do_Not_Remove\n" .
+ "Options None\n<IfModule mod_rewrite.c>\nRewriteEngine off\n</IfModule>\n" .
+ "Order allow,deny\nDeny from all\n");
+ fclose($fp);
+ }
}
diff --git a/modules/gallery/helpers/gallery_rest.php b/modules/gallery/helpers/gallery_rest.php
deleted file mode 100644
index a87ebb4e..00000000
--- a/modules/gallery/helpers/gallery_rest.php
+++ /dev/null
@@ -1,248 +0,0 @@
-<?php defined("SYSPATH") or die("No direct script access.");
-/**
- * Gallery - a web based photo album viewer and editor
- * Copyright (C) 2000-2009 Bharat Mediratta
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
- */
-class gallery_rest_Core {
- static function get($request) {
- $path = implode("/", $request->arguments);
-
- $item = gallery_rest::_get_item($path);
-
- $parent = $item->parent();
- $response_data = array("type" => $item->type,
- "name" => $item->name,
- "path" => $item->relative_url(),
- "parent_path" => empty($parent) ? null : $parent->relative_url(),
- "title" => $item->title,
- "thumb_url" => $item->thumb_url(true),
- "thumb_size" => array("height" => $item->thumb_height,
- "width" => $item->thumb_width),
- "resize_url" => $item->resize_url(true),
- "resize_size" => array("height" => (int)$item->resize_height,
- "width" => (int)$item->resize_width),
- "url" => $item->file_url(true),
- "size" => array("height" => $item->height,
- "width" => $item->width),
- "description" => $item->description,
- "slug" => $item->slug);
-
- $children = self::_get_children($item, $request);
- if (!empty($children) || $item->is_album()) {
- $response_data["children"] = $children;
- }
- return rest::success(array("resource" => $response_data));
- }
-
- static function put($request) {
- if (empty($request->arguments)) {
- throw new Rest_Exception(400, "Bad request");
- }
- $path = implode("/", $request->arguments);
- $item = gallery_rest::_get_item($path, "edit");
-
- // Validate the request data
- $new_values = gallery_rest::_validate($request, $item->parent_id, $item->id);
- $errors = $new_values->errors();
- if (empty($errors)) {
- $item->title = $new_values->title;
- $item->description = $new_values->description;
- if ($item->id != 1) {
- $item->rename($new_values->name);
- }
- $item->slug = $new_values->slug;
- $item->save();
-
- log::success("content", "Updated $item->type",
- "<a href=\"{$item->type}s/$item->id\">view</a>");
-
- return rest::success();
- } else {
- return rest::validation_error($errors);
- }
- }
-
- static function post($request) {
- if (empty($request->arguments)) {
- throw new Rest_Exception(400, "Bad request");
- }
-
- $components = $request->arguments;
- $name = urldecode(array_pop($components));
-
- $parent = gallery_rest::_get_item(implode("/", $components), "edit");
-
- // Validate the request data
- $request->name = $name;
- $new_values = gallery_rest::_validate($request, $parent->id);
- $errors = $new_values->errors();
- if (!empty($errors)) {
- return rest::validation_error($errors);
- }
-
- if (empty($new_values["image"])) {
- $new_item = album::create(
- $parent,
- $name,
- empty($new_values["title"]) ? $name : $new_values["title"],
- empty($new_values["description"]) ? null : $new_values["description"],
- identity::active_user()->id,
- empty($new_values["slug"]) ? $name : $new_values["slug"]);
- $log_message = t("Added an album");
- } else {
- $temp_filename = upload::save("image");
- $path_info = @pathinfo($temp_filename);
- if (array_key_exists("extension", $path_info) &&
- in_array(strtolower($path_info["extension"]), array("flv", "mp4"))) {
- $new_item =
- movie::create($parent, $temp_filename, $new_values["name"], $new_values["title"]);
- $log_message = t("Added a movie");
- } else {
- $new_item =
- photo::create($parent, $temp_filename, $new_values["name"], $new_values["title"]);
- $log_message = t("Added a photo");
- }
- }
-
- log::success("content", $log_message, "<a href=\"{$new_item->type}s/$new_item->id\">view</a>");
-
- return rest::success(array("path" => $new_item->relative_url()));
- }
-
- static function delete($request) {
- if (empty($request->arguments)) {
- throw new Rest_Exception(400, "Bad request");
- }
- $path = implode("/", $request->arguments);
-
- $item = gallery_rest::_get_item($path, "edit");
-
- if ($item->id == 1) {
- throw new Rest_Exception(400, "Bad request");
- }
-
- $parent = $item->parent();
- $item->delete();
-
- 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)));
- }
- log::success("content", $msg);
-
- return rest::success(array("resource" => array("parent_path" => $parent->relative_url())));
- }
-
- private static function _get_item($path, $permission="view") {
- $item = url::get_item_from_uri($path);
-
- if (!$item->loaded()) {
- throw new Kohana_404_Exception();
- }
-
- if (!access::can($permission, $item)) {
- throw new Kohana_404_Exception();
- }
-
- return $item;
- }
-
- private static function _get_children($item, $request) {
- $children = array();
- $limit = empty($request->limit) ? null : $request->limit;
- $offset = empty($request->offset) ? null : $request->offset;
- $where = empty($request->filter) ? array() : array("type" => $request->filter);
- foreach ($item->viewable()->children($limit, $offset, $where) as $child) {
- $children[] = array("type" => $child->type,
- "has_children" => $child->children_count() > 0,
- "path" => $child->relative_url(),
- "thumb_url" => $child->thumb_url(true),
- "thumb_dimensions" => array("width" => $child->thumb_width,
- "height" => $child->thumb_height),
- "has_thumb" => $child->has_thumb(),
- "title" => $child->title);
- }
-
- return $children;
- }
-
- private static function _validate($request, $parent_id, $item_id=0) {
- $item = ORM::factory("item", $item_id);
-
- // Normalize the inputs so all fields have a value
- $new_values = Validation::factory(array());
- foreach ($item->form_rules as $field => $rule_set) {
- if (isset($request->$field)) {
- $new_values[$field] = $request->$field;
- } else if (isset($item->$field)) {
- $new_values[$field] = $item->$field;
- }
- foreach (explode("|", $rule_set) as $rule) {
- $new_values->add_rules($field, $rule);
- }
- }
- $name = $new_values["name"];
- $new_values["title"] = empty($new_values["title"]) ? $name : $new_values["title"];
- $new_values["description"] =
- empty($new_values["description"]) ? null : $new_values["description"];
- $new_values["slug"] = empty($new_values["slug"]) ? $name : $new_values["slug"];
-
- if (!empty($request->image)) {
- $new_values["image"] = $request->image;
- $new_values->add_rules(
- "image", "upload::valid", "upload::required", "upload::type[gif,jpg,jpeg,png,flv,mp4]");
- }
-
- if ($new_values->validate() && $item_id != 1) {
- $errors = gallery_rest::_check_for_conflicts($parent_id, $item_id,
- $new_values["name"], $new_values["slug"]);
- if (!empty($errors)) {
- !empty($errors["name_conflict"]) OR $new_values->add_error("name", "Duplicate name");
- !empty($errors["slug_conflict"]) OR
- $new_values->add_error("slug", "Duplicate Internet address");
- }
- }
-
- return $new_values;
- }
-
- private static function _check_for_conflicts($parent_id, $item_id, $new_name, $new_slug) {
- $errors = array();
-
- if ($row = db::build()
- ->select(array("name", "slug"))
- ->from("items")
- ->where("parent_id", "=", $parent_id)
- ->where("id", "<>", $item_id)
- ->and_open()
- ->where("name", "=", $new_name)
- ->or_where("slug", "=", $new_slug)
- ->close()
- ->execute()
- ->current()) {
- if ($row->name == $new_name) {
- $errors["name_conflict"] = 1;
- }
- if ($row->slug == $new_slug) {
- $errors["slug_conflict"] = 1;
- }
- }
-
- return $errors;
- }
-}
diff --git a/modules/gallery/helpers/gallery_rss.php b/modules/gallery/helpers/gallery_rss.php
index d422636f..c1790d28 100644
--- a/modules/gallery/helpers/gallery_rss.php
+++ b/modules/gallery/helpers/gallery_rss.php
@@ -25,6 +25,7 @@ class gallery_rss_Core {
}
static function feed($feed_id, $offset, $limit, $id) {
+ $feed = new stdClass();
switch ($feed_id) {
case "latest":
$feed->children = ORM::factory("item")
diff --git a/modules/gallery/helpers/gallery_task.php b/modules/gallery/helpers/gallery_task.php
index 5402b5d1..3e6278e5 100644
--- a/modules/gallery/helpers/gallery_task.php
+++ b/modules/gallery/helpers/gallery_task.php
@@ -40,7 +40,7 @@ class gallery_task_Core {
$tasks[] = Task_Definition::factory()
->callback("gallery_task::file_cleanup")
->name(t("Remove old files"))
- ->description(t("Remove files from the logs and tmp directory"))
+ ->description(t("Remove expired files from the logs and tmp directory"))
->severity(log::SUCCESS);
return $tasks;
}
@@ -81,7 +81,7 @@ class gallery_task_Core {
} catch (Exception $e) {
$errors[] = t("Unable to rebuild images for '%title'",
array("title" => html::purify($item->title)));
- $errors[] = $e->__toString();
+ $errors[] = (string)$e;
$ignored[$item->id] = 1;
}
}
@@ -111,10 +111,11 @@ class gallery_task_Core {
site_status::clear("graphics_dirty");
}
} catch (Exception $e) {
+ Kohana_Log::add("error",(string)$e);
$task->done = true;
$task->state = "error";
$task->status = $e->getMessage();
- $errors[] = $e->__toString();
+ $errors[] = (string)$e;
}
if ($errors) {
$task->log($errors);
@@ -214,10 +215,11 @@ class gallery_task_Core {
Cache::instance()->delete("update_l10n_cache:{$task->id}");
}
} catch (Exception $e) {
+ Kohana_Log::add("error",(string)$e);
$task->done = true;
$task->state = "error";
$task->status = $e->getMessage();
- $errors[] = $e->__toString();
+ $errors[] = (string)$e;
}
if ($errors) {
$task->log($errors);
@@ -233,13 +235,13 @@ class gallery_task_Core {
try {
$start = microtime(true);
$data = Cache::instance()->get("file_cleanup_cache:{$task->id}");
- if ($data) {
- $files = unserialize($data);
- }
+ $files = $data ? unserialize($data) : array();
$i = 0;
+ $current = 0;
+ $total = 0;
switch ($task->get("mode", "init")) {
- case "init": // 0%
+ case "init":
$threshold = time() - 1209600; // older than 2 weeks
foreach(array("logs", "tmp") as $dir) {
$dir = VARPATH . $dir;
@@ -262,6 +264,7 @@ class gallery_task_Core {
if (count($files) == 0) {
break;
}
+
case "delete_files":
$current = $task->get("current");
$total = $task->get("total");
@@ -273,18 +276,21 @@ class gallery_task_Core {
$task->set("current", $current);
}
- $task->status = t("Removed: %count files. Total: %total_count.",
- array("count" => $current, "total_count" => $total));
+ $task->status = t2("Removed: 1 file. Total: %total_count.",
+ "Removed: %count files. Total: %total_count.",
+ $current, array("total_count" => $total));
if ($total == $current) {
$task->done = true;
$task->state = "success";
+ $task->percent_complete = 100;
}
} catch (Exception $e) {
+ Kohana_Log::add("error",(string)$e);
$task->done = true;
$task->state = "error";
$task->status = $e->getMessage();
- $errors[] = $e->__toString();
+ $errors[] = (string)$e;
}
if ($errors) {
$task->log($errors);
diff --git a/modules/gallery/helpers/graphics.php b/modules/gallery/helpers/graphics.php
index 5a290905..c85c7750 100644
--- a/modules/gallery/helpers/graphics.php
+++ b/modules/gallery/helpers/graphics.php
@@ -262,6 +262,9 @@ class graphics_Core {
*/
static function detect_toolkits() {
$toolkits = new stdClass();
+ $toolkits->gd = new stdClass();
+ $toolkits->imagemagick = new stdClass();
+ $toolkits->graphicsmagick = new stdClass();
// GD is special, it doesn't use exec()
$gd = function_exists("gd_info") ? gd_info() : array();
diff --git a/modules/gallery/helpers/identity.php b/modules/gallery/helpers/identity.php
index eae0ea3e..6df860d6 100644
--- a/modules/gallery/helpers/identity.php
+++ b/modules/gallery/helpers/identity.php
@@ -68,9 +68,7 @@ class identity_Core {
// upconvert into a user.
// @todo set the user name into the session instead of 2 and then use it to get the user object
if ($user === 2) {
- $user = IdentityProvider::instance()->admin_user();
- self::set_active_user($user);
- $session->set("user", $user);
+ auth::login(IdentityProvider::instance()->admin_user());
}
if (!$session->get("group_ids")) {
@@ -82,7 +80,7 @@ class identity_Core {
}
} catch (Exception $e) {
// Log it, so we at least have so notification that we swallowed the exception.
- Kohana_Log::add("error", "Load_user Exception: " .
+ Kohana_Log::add("error", "load_user Exception: " .
$e->getMessage() . "\n" . $e->getTraceAsString());
try {
Session::instance()->destroy();
@@ -155,8 +153,8 @@ class identity_Core {
/**
* @see IdentityProvider_Driver::create_user.
*/
- static function create_user($name, $full_name, $password) {
- return IdentityProvider::instance()->create_user($name, $full_name, $password);
+ static function create_user($name, $full_name, $password, $email) {
+ return IdentityProvider::instance()->create_user($name, $full_name, $password, $email);
}
/**
diff --git a/modules/gallery/helpers/item.php b/modules/gallery/helpers/item.php
index f6181f8a..41d49ce9 100644
--- a/modules/gallery/helpers/item.php
+++ b/modules/gallery/helpers/item.php
@@ -39,7 +39,8 @@ class item_Core {
}
}
- $source->move_to($target);
+ $source->parent_id = $target->id;
+ $source->save();
// If the target has no cover item, make this it.
if ($target->album_cover_item_id == null) {
@@ -59,7 +60,8 @@ class item_Core {
$parent->save();
graphics::generate($parent);
$grand_parent = $parent->parent();
- if ($grand_parent && $grand_parent->album_cover_item_id == null) {
+ if ($grand_parent && access::can("edit", $grand_parent) &&
+ $grand_parent->album_cover_item_id == null) {
item::make_album_cover($parent);
}
}
@@ -78,24 +80,6 @@ class item_Core {
graphics::generate($album);
}
- static function validate_no_slashes($input) {
- if (strpos($input->value, "/") !== false) {
- $input->add_error("no_slashes", 1);
- }
- }
-
- static function validate_no_trailing_period($input) {
- if (rtrim($input->value, ".") !== $input->value) {
- $input->add_error("no_trailing_period", 1);
- }
- }
-
- static function validate_url_safe($input) {
- if (preg_match("/[^A-Za-z0-9-_]/", $input->value)) {
- $input->add_error("not_url_safe", 1);
- }
- }
-
/**
* Sanitize a filename into something presentable as an item title
* @param string $filename
@@ -173,4 +157,20 @@ class item_Core {
static function root() {
return model_cache::get("item", 1);
}
+
+ /**
+ * Return a query to get a random Item_Model, with optional filters
+ *
+ * @param array (optional) where tuple
+ */
+ static function random_query($where=null) {
+ // Pick a random number and find the item that's got nearest smaller number.
+ // This approach works best when the random numbers in the system are roughly evenly
+ // distributed so this is going to be more efficient with larger data sets.
+ return ORM::factory("item")
+ ->viewable()
+ ->where("rand_key", "<", ((float)mt_rand()) / (float)mt_getrandmax())
+ ->merge_where($where)
+ ->order_by("rand_key", "DESC");
+ }
} \ No newline at end of file
diff --git a/modules/gallery/helpers/item_rest.php b/modules/gallery/helpers/item_rest.php
new file mode 100644
index 00000000..c0fc422a
--- /dev/null
+++ b/modules/gallery/helpers/item_rest.php
@@ -0,0 +1,176 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2009 Bharat Mediratta
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+class item_rest_Core {
+ /**
+ * For items that are collections, you can specify the following additional query parameters to
+ * query the collection. You can specify them in any combination.
+ *
+ * scope=direct
+ * only return items that are immediately under this one
+ * scope=all
+ * return items anywhere under this one
+ *
+ * name=<substring>
+ * only return items where the name contains this substring
+ *
+ * random=true
+ * return a single random item
+ *
+ * type=<comma separate list of photo, movie or album>
+ * limit the type to types in this list. eg, "type=photo,movie"
+ */
+ static function get($request) {
+ $item = rest::resolve($request->url);
+ access::required("view", $item);
+
+ $p = $request->params;
+ if (isset($p->random)) {
+ $orm = item::random_query()->offset(0)->limit(1);
+ } else {
+ $orm = ORM::factory("item")->viewable();
+ }
+
+ if (empty($p->scope)) {
+ $p->scope = "direct";
+ }
+
+ if (!in_array($p->scope, array("direct", "all"))) {
+ throw new Rest_Exception("Bad Request", 400);
+ }
+
+ if ($p->scope == "direct") {
+ $orm->where("parent_id", "=", $item->id);
+ } else {
+ $orm->where("left_ptr", ">", $item->left_ptr);
+ $orm->where("right_ptr", "<", $item->right_ptr);
+ }
+
+ if (isset($p->name)) {
+ $orm->where("name", "LIKE", "%{$p->name}%");
+ }
+
+ if (isset($p->type)) {
+ $orm->where("type", "IN", explode(",", $p->type));
+ }
+
+ $members = array();
+ foreach ($orm->find_all() as $child) {
+ $members[] = rest::url("item", $child);
+ }
+
+ return array(
+ "url" => $request->url,
+ "entity" => $item->as_restful_array(),
+ "members" => $members,
+ "relationships" => rest::relationships("item", $item));
+ }
+
+ static function put($request) {
+ $item = rest::resolve($request->url);
+ access::required("edit", $item);
+
+ $params = $request->params;
+
+ // Only change fields from a whitelist.
+ foreach (array("album_cover", "captured", "description",
+ "height", "mime_type", "name", "parent", "rand_key", "resize_dirty",
+ "resize_height", "resize_width", "slug", "sort_column", "sort_order",
+ "thumb_dirty", "thumb_height", "thumb_width", "title", "view_count",
+ "weight", "width") as $key) {
+ switch ($key) {
+ case "album_cover":
+ if (property_exists($request->params, "album_cover")) {
+ $album_cover_item = rest::resolve($request->params->album_cover);
+ access::required("view", $album_cover_item);
+ $item->album_cover_item_id = $album_cover_item->id;
+ }
+ break;
+
+ case "parent":
+ if (property_exists($request->params, "parent")) {
+ $parent = rest::resolve($request->params->parent);
+ access::required("edit", $parent);
+ $item->parent_id = $parent->id;
+ }
+ break;
+ default:
+ if (property_exists($request->params, $key)) {
+ $item->$key = $request->params->$key;
+ }
+ }
+ }
+ $item->save();
+ }
+
+ static function post($request) {
+ $parent = rest::resolve($request->url);
+ access::required("edit", $parent);
+
+ $params = $request->params;
+ $item = ORM::factory("item");
+ switch ($params->type) {
+ case "album":
+ $item->type = "album";
+ $item->parent_id = $parent->id;
+ $item->name = $params->name;
+ $item->title = isset($params->title) ? $params->title : $name;
+ $item->description = isset($params->description) ? $params->description : null;
+ $item->slug = isset($params->slug) ? $params->slug : null;
+ $item->save();
+ break;
+
+ case "photo":
+ case "movie":
+ $item->type = $params->type;
+ $item->parent_id = $parent->id;
+ $item->set_data_file($request->file);
+ $item->name = $params->name;
+ $item->title = isset($params->title) ? $params->title : $params->name;
+ $item->description = isset($params->description) ? $params->description : null;
+ $item->slug = isset($params->slug) ? $params->slug : null;
+ $item->save();
+ break;
+
+ default:
+ throw new Rest_Exception("Invalid type: $params->type", 400);
+ }
+
+ return array("url" => rest::url("item", $item));
+ }
+
+ static function delete($request) {
+ $item = rest::resolve($request->url);
+ access::required("edit", $item);
+
+ $item->delete();
+ }
+
+ static function resolve($id) {
+ $item = ORM::factory("item", $id);
+ if (!access::can("view", $item)) {
+ throw new Kohana_404_Exception();
+ }
+ return $item;
+ }
+
+ static function url($item) {
+ return url::abs_site("rest/item/{$item->id}");
+ }
+}
diff --git a/modules/gallery/helpers/l10n_client.php b/modules/gallery/helpers/l10n_client.php
index 086245e8..c27e4e5b 100644
--- a/modules/gallery/helpers/l10n_client.php
+++ b/modules/gallery/helpers/l10n_client.php
@@ -77,6 +77,7 @@ class l10n_client_Core {
* translations for.
*/
static function fetch_updates(&$num_fetched) {
+ $request = new stdClass();
$request->locales = array();
$request->messages = new stdClass();
diff --git a/modules/gallery/helpers/locales.php b/modules/gallery/helpers/locales.php
index 5c8c227a..dc32b12f 100644
--- a/modules/gallery/helpers/locales.php
+++ b/modules/gallery/helpers/locales.php
@@ -238,7 +238,9 @@ class locales_Core {
}
static function cookie_locale() {
- $cookie_data = Input::instance()->cookie("g_locale");
+ // Can't use Input framework for client side cookies since
+ // they're not signed.
+ $cookie_data = isset($_COOKIE["g_locale"]) ? $_COOKIE["g_locale"] : null;
$locale = null;
if ($cookie_data) {
if (preg_match("/^([a-z]{2,3}(?:_[A-Z]{2})?)$/", trim($cookie_data), $matches)) {
diff --git a/modules/gallery/helpers/module.php b/modules/gallery/helpers/module.php
index 95e426c4..9523d1d2 100644
--- a/modules/gallery/helpers/module.php
+++ b/modules/gallery/helpers/module.php
@@ -430,7 +430,8 @@ class module_Core {
// This could happen if there's a race condition
continue;
}
- self::$var_cache->{$row->module_name}->{$row->name} = $row->value;
+ // Mute the "Creating default object from empty value" warning below
+ @self::$var_cache->{$row->module_name}->{$row->name} = $row->value;
}
$cache = ORM::factory("var");
$cache->module_name = "gallery";
diff --git a/modules/gallery/helpers/movie.php b/modules/gallery/helpers/movie.php
index 01859924..7033b7da 100644
--- a/modules/gallery/helpers/movie.php
+++ b/modules/gallery/helpers/movie.php
@@ -24,138 +24,36 @@
* Note: by design, this class does not do any permission checking.
*/
class movie_Core {
- /**
- * Create a new movie.
- * @param integer $parent_id id of parent album
- * @param string $filename path to the photo file on disk
- * @param string $name the filename to use for this photo in the album
- * @param integer $title the title of the new photo
- * @param string $description (optional) the longer description of this photo
- * @param string $slug (optional) the url component for this photo
- * @return Item_Model
- */
- static function create($parent, $filename, $name, $title,
- $description=null, $owner_id=null, $slug=null) {
- if (!$parent->loaded() || !$parent->is_album()) {
- throw new Exception("@todo INVALID_PARENT");
- }
-
- if (!is_file($filename)) {
- throw new Exception("@todo MISSING_MOVIE_FILE");
- }
-
- if (strpos($name, "/")) {
- throw new Exception("@todo NAME_CANNOT_CONTAIN_SLASH");
- }
-
- // We don't allow trailing periods as a security measure
- // ref: http://dev.kohanaphp.com/issues/684
- if (rtrim($name, ".") != $name) {
- throw new Exception("@todo NAME_CANNOT_END_IN_PERIOD");
- }
-
- try {
- $movie_info = movie::getmoviesize($filename);
- } catch (Exception $e) {
- // Assuming this is MISSING_FFMPEG for now
- $movie_info = getimagesize(MODPATH . "gallery/images/missing_movie.png");
- }
-
- // Force an extension onto the name
- $pi = pathinfo($filename);
- if (empty($pi["extension"])) {
- $pi["extension"] = image_type_to_extension($movie_info[2], false);
- $name .= "." . $pi["extension"];
- }
-
- if (empty($slug)) {
- $slug = item::convert_filename_to_slug($name);
- }
-
- $movie = ORM::factory("item");
- $movie->type = "movie";
- $movie->title = $title;
- $movie->description = $description;
- $movie->name = $name;
- $movie->owner_id = $owner_id ? $owner_id : identity::active_user()->id;
- $movie->width = $movie_info[0];
- $movie->height = $movie_info[1];
- $movie->mime_type = strtolower($pi["extension"]) == "mp4" ? "video/mp4" : "video/x-flv";
- $movie->thumb_dirty = 1;
- $movie->resize_dirty = 1;
- $movie->sort_column = "weight";
- $movie->slug = $slug;
- $movie->rand_key = ((float)mt_rand()) / (float)mt_getrandmax();
-
- // Randomize the name if there's a conflict
- // @todo Improve this. Random numbers are not user friendly
- while (ORM::factory("item")
- ->where("parent_id", "=", $parent->id)
- ->and_open()
- ->where("name", "=", $movie->name)
- ->or_where("slug", "=", $movie->slug)
- ->close()
- ->find()->id) {
- $rand = rand();
- $movie->name = "{$name}.$rand.{$pi['extension']}";
- $movie->slug = "{$slug}-$rand";
- }
-
- // This saves the photo
- $movie->add_to_parent($parent);
-
- // If the thumb or resize already exists then rename it
- if (file_exists($movie->resize_path()) ||
- file_exists($movie->thumb_path())) {
- $movie->name = $pi["filename"] . "-" . rand() . "." . $pi["extension"];
- $movie->save();
- }
-
- copy($filename, $movie->file_path());
-
- // @todo: publish this from inside Item_Model::save() when we refactor to the point where
- // there's only one save() happening here.
- module::event("item_created", $movie);
-
- // Build our thumbnail
- graphics::generate($movie);
-
- // If the parent has no cover item, make this it.
- if (access::can("edit", $parent) && $parent->album_cover_item_id == null) {
- item::make_album_cover($movie);
- }
-
- return $movie;
- }
-
static function get_edit_form($movie) {
$form = new Forge("movies/update/$movie->id", "", "post", array("id" => "g-edit-movie-form"));
$form->hidden("from_id");
$group = $form->group("edit_item")->label(t("Edit Movie"));
- $group->input("title")->label(t("Title"))->value($movie->title);
+ $group->input("title")->label(t("Title"))->value($movie->title)
+ ->error_messages("required", t("You must provide a title"))
+ ->error_messages("length", t("Your title is too long"));
$group->textarea("description")->label(t("Description"))->value($movie->description);
- $group->input("filename")->label(t("Filename"))->value($movie->name)
- ->rules("required")
+ $group->input("name")->label(t("Filename"))->value($movie->name)
->error_messages(
- "name_conflict", t("There is already a movie, photo or album with this name"))
- ->callback("item::validate_no_slashes")
+ "conflict", t("There is already a movie, photo or album with this name"))
->error_messages("no_slashes", t("The movie name can't contain a \"/\""))
- ->callback("item::validate_no_trailing_period")
->error_messages("no_trailing_period", t("The movie name can't end in \".\""))
- ->error_messages("illegal_extension", t("You cannot change the filename extension"));
+ ->error_messages("illegal_data_file_extension", t("You cannot change the movie file extension"))
+ ->error_messages("required", t("You must provide a movie file name"))
+ ->error_messages("length", t("Your movie file name is too long"));
$group->input("slug")->label(t("Internet Address"))->value($movie->slug)
- ->callback("item::validate_url_safe")
->error_messages(
- "slug_conflict", t("There is already a movie, photo or album with this internet address"))
+ "conflict", t("There is already a movie, photo or album with this internet address"))
->error_messages(
"not_url_safe",
- t("The internet address should contain only letters, numbers, hyphens and underscores"));
+ t("The internet address should contain only letters, numbers, hyphens and underscores"))
+ ->error_messages("required", t("You must provide an internet address"))
+ ->error_messages("length", t("Your internet address is too long"));
module::event("item_edit_form", $movie, $form);
$group = $form->group("buttons")->label("");
$group->submit("")->value(t("Modify"));
- $form->add_rules_from(ORM::factory("item"));
+
return $form;
}
diff --git a/modules/gallery/helpers/photo.php b/modules/gallery/helpers/photo.php
index 4e20e610..bbdf2e3b 100644
--- a/modules/gallery/helpers/photo.php
+++ b/modules/gallery/helpers/photo.php
@@ -24,147 +24,34 @@
* Note: by design, this class does not do any permission checking.
*/
class photo_Core {
- /**
- * Create a new photo.
- * @param integer $parent parent album
- * @param string $filename path to the photo file on disk
- * @param string $name the filename to use for this photo in the album
- * @param integer $title the title of the new photo
- * @param string $description (optional) the longer description of this photo
- * @param string $slug (optional) the url component for this photo
- * @return Item_Model
- */
- static function create($parent, $filename, $name, $title,
- $description=null, $owner_id=null, $slug=null) {
- if (!$parent->loaded() || !$parent->is_album()) {
- throw new Exception("@todo INVALID_PARENT");
- }
-
- if (!is_file($filename)) {
- throw new Exception("@todo MISSING_IMAGE_FILE");
- }
-
- if (strpos($name, "/")) {
- throw new Exception("@todo NAME_CANNOT_CONTAIN_SLASH");
- }
-
- // We don't allow trailing periods as a security measure
- // ref: http://dev.kohanaphp.com/issues/684
- if (rtrim($name, ".") != $name) {
- throw new Exception("@todo NAME_CANNOT_END_IN_PERIOD");
- }
-
- if (filesize($filename) == 0) {
- throw new Exception("@todo EMPTY_INPUT_FILE");
- }
-
- $image_info = getimagesize($filename);
-
- // Force an extension onto the name
- $pi = pathinfo($filename);
- if (empty($pi["extension"])) {
- $pi["extension"] = image_type_to_extension($image_info[2], false);
- $name .= "." . $pi["extension"];
- }
-
- if (empty($slug)) {
- $slug = item::convert_filename_to_slug($name);
- }
-
- $photo = ORM::factory("item");
- $photo->type = "photo";
- $photo->title = $title;
- $photo->description = $description;
- $photo->name = $name;
- $photo->owner_id = $owner_id ? $owner_id : identity::active_user()->id;
- $photo->width = $image_info[0];
- $photo->height = $image_info[1];
- $photo->mime_type = empty($image_info['mime']) ? "application/unknown" : $image_info['mime'];
- $photo->thumb_dirty = 1;
- $photo->resize_dirty = 1;
- $photo->sort_column = "weight";
- $photo->slug = $slug;
- $photo->rand_key = ((float)mt_rand()) / (float)mt_getrandmax();
-
- // Randomize the name or slug if there's a conflict
- // @todo Improve this. Random numbers are not user friendly
- while (ORM::factory("item")
- ->where("parent_id", "=", $parent->id)
- ->and_open()
- ->where("name", "=", $photo->name)
- ->or_where("slug", "=", $photo->slug)
- ->close()
- ->find()->id) {
- $rand = rand();
- $photo->name = "{$name}.$rand.{$pi['extension']}";
- $photo->slug = "{$slug}-$rand";
- }
-
- // This saves the photo
- $photo->add_to_parent($parent);
-
- /*
- * If the thumb or resize already exists then rename it. We need to do this after the save
- * because the resize_path and thumb_path both call relative_path which caches the
- * path. Before add_to_parent the relative path will be incorrect.
- */
- if (file_exists($photo->resize_path()) ||
- file_exists($photo->thumb_path())) {
- $photo->name = $pi["filename"] . "-" . rand() . "." . $pi["extension"];
- $photo->save();
- }
-
- copy($filename, $photo->file_path());
-
- // @todo: publish this from inside Item_Model::save() when we refactor to the point where
- // there's only one save() happening here.
- module::event("item_created", $photo);
-
- // Build our thumbnail/resizes. If we fail to build thumbnail/resize we assume that the image
- // is bad in some way and discard it.
- try {
- graphics::generate($photo);
- } catch (Exception $e) {
- $photo->delete();
- throw $e;
- }
-
- // If the parent has no cover item, make this it.
- if (access::can("edit", $parent) && $parent->album_cover_item_id == null) {
- item::make_album_cover($photo);
- }
-
- return $photo;
- }
-
static function get_edit_form($photo) {
$form = new Forge("photos/update/$photo->id", "", "post", array("id" => "g-edit-photo-form"));
$form->hidden("from_id");
$group = $form->group("edit_item")->label(t("Edit Photo"));
- $group->input("title")->label(t("Title"))->value($photo->title);
+ $group->input("title")->label(t("Title"))->value($photo->title)
+ ->error_messages("required", t("You must provide a title"))
+ ->error_messages("length", t("Your title is too long"));
$group->textarea("description")->label(t("Description"))->value($photo->description);
- $group->input("filename")->label(t("Filename"))->value($photo->name)
- ->rules("required")
- ->error_messages(
- "name_conflict", t("There is already a movie, photo or album with this name"))
- ->callback("item::validate_no_slashes")
+ $group->input("name")->label(t("Filename"))->value($photo->name)
+ ->error_messages("conflict", t("There is already a movie, photo or album with this name"))
->error_messages("no_slashes", t("The photo name can't contain a \"/\""))
- ->callback("item::validate_no_trailing_period")
->error_messages("no_trailing_period", t("The photo name can't end in \".\""))
- ->error_messages("illegal_extension", t("You cannot change the filename extension"));
+ ->error_messages("illegal_data_file_extension", t("You cannot change the photo file extension"))
+ ->error_messages("required", t("You must provide a photo file name"))
+ ->error_messages("length", t("Your photo file name is too long"));
$group->input("slug")->label(t("Internet Address"))->value($photo->slug)
- ->callback("item::validate_url_safe")
->error_messages(
- "slug_conflict", t("There is already a movie, photo or album with this internet address"))
+ "conflict", t("There is already a movie, photo or album with this internet address"))
->error_messages(
"not_url_safe",
- t("The internet address should contain only letters, numbers, hyphens and underscores"));
+ t("The internet address should contain only letters, numbers, hyphens and underscores"))
+ ->error_messages("required", t("You must provide an internet address"))
+ ->error_messages("length", t("Your internet address is too long"));
module::event("item_edit_form", $photo, $form);
$group = $form->group("buttons")->label("");
$group->submit("")->value(t("Modify"));
- $form->add_rules_from(ORM::factory("item"));
return $form;
}
diff --git a/modules/gallery/helpers/task.php b/modules/gallery/helpers/task.php
index 4aa95f33..645850d1 100644
--- a/modules/gallery/helpers/task.php
+++ b/modules/gallery/helpers/task.php
@@ -84,8 +84,15 @@ class task_Core {
}
$task->save();
} catch (Exception $e) {
- Kohana_Log::add("error", $e->__toString());
- $task->log($e->__toString());
+ Kohana_Log::add("error", (string)$e);
+
+ // 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));
+ }
+
+ $task->log((string)$e);
$task->state = "error";
$task->done = true;
$task->status = substr($e->getMessage(), 0, 255);