summaryrefslogtreecommitdiff
path: root/modules/gallery/helpers
diff options
context:
space:
mode:
Diffstat (limited to 'modules/gallery/helpers')
-rw-r--r--modules/gallery/helpers/album.php9
-rw-r--r--modules/gallery/helpers/block_manager.php10
-rw-r--r--modules/gallery/helpers/gallery_event.php39
-rw-r--r--modules/gallery/helpers/gallery_installer.php32
-rw-r--r--modules/gallery/helpers/gallery_task.php6
-rw-r--r--modules/gallery/helpers/gallery_theme.php4
-rw-r--r--modules/gallery/helpers/graphics.php6
-rw-r--r--modules/gallery/helpers/item.php81
-rw-r--r--modules/gallery/helpers/legal_file.php32
-rw-r--r--modules/gallery/helpers/module.php72
-rw-r--r--modules/gallery/helpers/movie.php36
-rw-r--r--modules/gallery/helpers/photo.php7
-rw-r--r--modules/gallery/helpers/system.php33
-rw-r--r--modules/gallery/helpers/task.php2
14 files changed, 318 insertions, 51 deletions
diff --git a/modules/gallery/helpers/album.php b/modules/gallery/helpers/album.php
index 23aed8ac..fe6b03fc 100644
--- a/modules/gallery/helpers/album.php
+++ b/modules/gallery/helpers/album.php
@@ -34,12 +34,16 @@ class album_Core {
->error_messages("length", t("Your title is too long"));
$group->textarea("description")->label(t("Description"));
$group->input("name")->label(t("Directory name"))
- ->error_messages("no_slashes", t("The directory name can't contain the \"/\" character"))
+ ->error_messages("no_slashes", t("The directory name can't contain a \"/\""))
+ ->error_messages("no_backslashes", t("The directory name can't contain a \"\\\""))
+ ->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"))
->error_messages("conflict", t("There is already a movie, photo or album with this name"));
$group->input("slug")->label(t("Internet Address"))
->error_messages(
+ "conflict", t("There is already a movie, photo or album with this internet address"))
+ ->error_messages(
"reserved", t("This address is reserved and can't be used."))
->error_messages(
"not_url_safe",
@@ -64,13 +68,14 @@ class album_Core {
$group = $form->group("edit_item")->label(t("Edit Album"));
$group->input("title")->label(t("Title"))->value($parent->title)
- ->error_messages("required", t("You must provide a 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("name")->label(t("Directory Name"))->value($parent->name)
->error_messages("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 \"/\""))
+ ->error_messages("no_backslashes", t("The directory name can't contain a \"\\\""))
->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"));
diff --git a/modules/gallery/helpers/block_manager.php b/modules/gallery/helpers/block_manager.php
index bd6ca1c8..a2279468 100644
--- a/modules/gallery/helpers/block_manager.php
+++ b/modules/gallery/helpers/block_manager.php
@@ -35,7 +35,7 @@ class block_manager_Core {
static function activate_blocks($module_name) {
$block_class = "{$module_name}_block";
- if (method_exists($block_class, "get_site_list")) {
+ if (class_exists($block_class) && method_exists($block_class, "get_site_list")) {
$blocks = call_user_func(array($block_class, "get_site_list"));
foreach (array_keys($blocks) as $block_id) {
block_manager::add("site_sidebar", $module_name, $block_id);
@@ -61,14 +61,14 @@ class block_manager_Core {
static function deactivate_blocks($module_name) {
$block_class = "{$module_name}_block";
- if (method_exists($block_class, "get_site_list")) {
+ if (class_exists($block_class) && method_exists($block_class, "get_site_list")) {
$blocks = call_user_func(array($block_class, "get_site_list"));
foreach (array_keys($blocks) as $block_id) {
block_manager::remove_blocks_for_module("site_sidebar", $module_name);
}
}
- if (method_exists($block_class, "get_admin_list")) {
+ if (class_exists($block_class) && method_exists($block_class, "get_admin_list")) {
$blocks = call_user_func(array($block_class, "get_admin_list"));
foreach (array("dashboard_sidebar", "dashboard_center") as $location) {
block_manager::remove_blocks_for_module($location, $module_name);
@@ -89,7 +89,7 @@ class block_manager_Core {
foreach (module::active() as $module) {
$class_name = "{$module->name}_block";
- if (method_exists($class_name, $function)) {
+ if (class_exists($class_name) && method_exists($class_name, $function)) {
foreach (call_user_func(array($class_name, $function)) as $id => $title) {
$blocks["{$module->name}:$id"] = $title;
}
@@ -102,7 +102,7 @@ class block_manager_Core {
$active = block_manager::get_active($location);
$result = "";
foreach ($active as $id => $desc) {
- if (method_exists("$desc[0]_block", "get")) {
+ if (class_exists("$desc[0]_block") && method_exists("$desc[0]_block", "get")) {
$block = call_user_func(array("$desc[0]_block", "get"), $desc[1], $theme);
if (!empty($block)) {
$block->id = $id;
diff --git a/modules/gallery/helpers/gallery_event.php b/modules/gallery/helpers/gallery_event.php
index aeb1c7eb..a319b9c6 100644
--- a/modules/gallery/helpers/gallery_event.php
+++ b/modules/gallery/helpers/gallery_event.php
@@ -36,6 +36,41 @@ class gallery_event_Core {
locales::set_request_locale();
}
+ static function gallery_shutdown() {
+ // Every 500th request, do a pass over var/logs and var/tmp and delete old files.
+ // Limit ourselves to deleting a single file so that we don't spend too much CPU
+ // time on it. As long as servers call this at least twice a day they'll eventually
+ // wind up with a clean var/logs directory because we only create 1 file a day there.
+ // var/tmp might be stickier because theoretically we could wind up spamming that
+ // dir with a lot of files. But let's start with this and refine as we go.
+ if (!(rand() % 500)) {
+ // Note that this code is roughly duplicated in gallery_task::file_cleanup
+ $threshold = time() - 1209600; // older than 2 weeks
+ foreach(array("logs", "tmp") as $dir) {
+ $dir = VARPATH . $dir;
+ if ($dh = opendir($dir)) {
+ while (($file = readdir($dh)) !== false) {
+ if ($file[0] == ".") {
+ continue;
+ }
+
+ // Ignore directories for now, but we should really address them in the long term.
+ if (is_dir("$dir/$file")) {
+ continue;
+ }
+
+ if (filemtime("$dir/$file") <= $threshold) {
+ unlink("$dir/$file");
+ break;
+ }
+ }
+ }
+ }
+ }
+ // Delete all files marked using system::delete_later.
+ system::delete_marked_files();
+ }
+
static function user_deleted($user) {
$admin = identity::admin_user();
if (!empty($admin)) { // could be empty if there is not identity provider
@@ -399,6 +434,10 @@ class gallery_event_Core {
->label(t("Graphics"))
->url(url::site("admin/graphics")))
->append(Menu::factory("link")
+ ->id("movies_settings")
+ ->label(t("Movies"))
+ ->url(url::site("admin/movies")))
+ ->append(Menu::factory("link")
->id("languages")
->label(t("Languages"))
->url(url::site("admin/languages")))
diff --git a/modules/gallery/helpers/gallery_installer.php b/modules/gallery/helpers/gallery_installer.php
index 051a66cf..f1604150 100644
--- a/modules/gallery/helpers/gallery_installer.php
+++ b/modules/gallery/helpers/gallery_installer.php
@@ -797,6 +797,38 @@ class gallery_installer {
module::set_var("gallery", "movie_allow_uploads", "autodetect");
module::set_version("gallery", $version = 56);
}
+
+ if ($version == 56) {
+ // Cleanup possible instances where resize_dirty of albums or movies was set to 0. This is
+ // unlikely to have occurred, and doesn't currently matter much since albums and movies don't
+ // have resize images anyway. However, it may be useful to be consistent here going forward.
+ db::build()
+ ->update("items")
+ ->set("resize_dirty", 1)
+ ->where("type", "<>", "photo")
+ ->execute();
+ module::set_version("gallery", $version = 57);
+ }
+
+ if ($version == 57) {
+ // In v58 we changed the Item_Model validation code to disallow files or directories with
+ // backslashes in them, and we need to fix any existing items that have them. This is
+ // pretty unlikely, as having backslashes would have probably already caused other issues for
+ // users, but we should check anyway. This might be slow, but if it times out it can just
+ // pick up where it left off.
+ foreach (db::build()
+ ->from("items")
+ ->select("id")
+ ->where(db::expr("`name` REGEXP '\\\\\\\\'"), "=", 1) // one \, 3x escaped
+ ->order_by("id", "asc")
+ ->execute() as $row) {
+ set_time_limit(30);
+ $item = ORM::factory("item", $row->id);
+ $item->name = str_replace("\\", "_", $item->name);
+ $item->save();
+ }
+ module::set_version("gallery", $version = 58);
+ }
}
static function uninstall() {
diff --git a/modules/gallery/helpers/gallery_task.php b/modules/gallery/helpers/gallery_task.php
index 856d2639..a79cb2d5 100644
--- a/modules/gallery/helpers/gallery_task.php
+++ b/modules/gallery/helpers/gallery_task.php
@@ -281,6 +281,7 @@ class gallery_task_Core {
switch ($task->get("mode", "init")) {
case "init":
$threshold = time() - 1209600; // older than 2 weeks
+ // Note that this code is roughly duplicated in gallery_event::gallery_shutdown
foreach(array("logs", "tmp") as $dir) {
$dir = VARPATH . $dir;
if ($dh = opendir($dir)) {
@@ -289,6 +290,11 @@ class gallery_task_Core {
continue;
}
+ // Ignore directories for now, but we should really address them in the long term.
+ if (is_dir("$dir/$file")) {
+ continue;
+ }
+
if (filemtime("$dir/$file") <= $threshold) {
$files[] = "$dir/$file";
}
diff --git a/modules/gallery/helpers/gallery_theme.php b/modules/gallery/helpers/gallery_theme.php
index 3c6d71e9..e5f6b0b4 100644
--- a/modules/gallery/helpers/gallery_theme.php
+++ b/modules/gallery/helpers/gallery_theme.php
@@ -49,6 +49,10 @@ class gallery_theme_Core {
. $theme->script("l10n_client.js");
}
+ // Add MediaElementJS library
+ $buf .= $theme->script("mediaelementjs/mediaelement.js");
+ $buf .= $theme->script("mediaelementjs/mediaelementplayer.js");
+ $buf .= $theme->css("mediaelementjs/mediaelementplayer.css");
$buf .= $theme->css("uploadify/uploadify.css");
return $buf;
}
diff --git a/modules/gallery/helpers/graphics.php b/modules/gallery/helpers/graphics.php
index e66908c4..459784c9 100644
--- a/modules/gallery/helpers/graphics.php
+++ b/modules/gallery/helpers/graphics.php
@@ -121,12 +121,6 @@ class graphics_Core {
if ($item->resize_dirty && $item->is_photo()) {
$ops["resize"] = $item->resize_path();
}
- if (empty($ops)) {
- $item->thumb_dirty = 0;
- $item->resize_dirty = 0;
- $item->save();
- return;
- }
try {
foreach ($ops as $target => $output_file) {
diff --git a/modules/gallery/helpers/item.php b/modules/gallery/helpers/item.php
index 9882a9c5..bbbc81d6 100644
--- a/modules/gallery/helpers/item.php
+++ b/modules/gallery/helpers/item.php
@@ -203,10 +203,18 @@ class item_Core {
/**
* Find an item by its path. If there's no match, return an empty Item_Model.
* NOTE: the caller is responsible for performing security checks on the resulting item.
+ *
+ * In addition to $path, $var_subdir can be specified ("albums", "resizes", or "thumbs"). This
+ * corresponds to the file's directory in var, which is what's used in file_proxy. By specifying
+ * this, we can be smarter about items whose formats get converted (e.g. movies that get jpg
+ * thumbs). If omitted, it defaults to "albums" which looks for identical matches between $path
+ * and the item name, just like pre-v3.1 behavior.
+ *
* @param string $path
+ * @param string $var_subdir
* @return object Item_Model
*/
- static function find_by_path($path) {
+ static function find_by_path($path, $var_subdir="albums") {
$path = trim($path, "/");
// The root path name is NULL not "", hence this workaround.
@@ -214,35 +222,80 @@ class item_Core {
return item::root();
}
+ $search_full_name = true;
+ $album_thumb = false;
+ if (($var_subdir == "thumbs") && preg_match("|^(.*)/\.album\.jpg$|", $path, $matches)) {
+ // It's an album thumb - remove "/.album.jpg" from the path.
+ $path = $matches[1];
+ $album_thumb = true;
+ } else if (($var_subdir != "albums") && preg_match("/^(.*)\.jpg$/", $path, $matches)) {
+ // Item itself could be non-jpg (e.g. movies) - remove .jpg from path, don't search full name.
+ $path = $matches[1];
+ $search_full_name = false;
+ }
+
// Check to see if there's an item in the database with a matching relative_path_cache value.
- // Since that field is urlencoded, we must urlencoded the components of the path.
+ // Since that field is urlencoded, we must urlencode the components of the path.
foreach (explode("/", $path) as $part) {
$encoded_array[] = rawurlencode($part);
}
$encoded_path = join("/", $encoded_array);
- $item = ORM::factory("item")
- ->where("relative_path_cache", "=", $encoded_path)
- ->find();
- if ($item->loaded()) {
- return $item;
+ if ($search_full_name) {
+ $item = ORM::factory("item")
+ ->where("relative_path_cache", "=", $encoded_path)
+ ->find();
+ // See if the item was found and if it should have been found.
+ if ($item->loaded() &&
+ (($var_subdir == "albums") || $item->is_photo() || $album_thumb)) {
+ return $item;
+ }
+ } else {
+ // Note that the below query uses LIKE with wildcard % at end, which is still sargable and
+ // therefore still takes advantage of the indexed relative_path_cache (i.e. still quick).
+ $item = ORM::factory("item")
+ ->where("relative_path_cache", "LIKE", Database::escape_for_like($encoded_path) . ".%")
+ ->find();
+ // See if the item was found and should be a jpg.
+ if ($item->loaded() &&
+ (($item->is_movie() && ($var_subdir == "thumbs")) ||
+ ($item->is_photo() && (preg_match("/^(.*)\.jpg$/", $item->name))))) {
+ return $item;
+ }
}
// Since the relative_path_cache field is a cache, it can be unavailable. If we don't find
// anything, fall back to checking the path the hard way.
$paths = explode("/", $path);
- foreach (ORM::factory("item")
- ->where("name", "=", end($paths))
- ->where("level", "=", count($paths) + 1)
- ->find_all() as $item) {
- if (urldecode($item->relative_path()) == $path) {
- return $item;
+ if ($search_full_name) {
+ foreach (ORM::factory("item")
+ ->where("name", "=", end($paths))
+ ->where("level", "=", count($paths) + 1)
+ ->find_all() as $item) {
+ // See if the item was found and if it should have been found.
+ if ((urldecode($item->relative_path()) == $path) &&
+ (($var_subdir == "albums") || $item->is_photo() || $album_thumb)) {
+ return $item;
+ }
+ }
+ } else {
+ foreach (ORM::factory("item")
+ ->where("name", "LIKE", Database::escape_for_like(end($paths)) . ".%")
+ ->where("level", "=", count($paths) + 1)
+ ->find_all() as $item) {
+ // Compare relative_path without extension (regexp same as legal_file::change_extension),
+ // see if it should be a jpg.
+ if ((preg_replace("/\.[^\.\/]*?$/", "", urldecode($item->relative_path())) == $path) &&
+ (($item->is_movie() && ($var_subdir == "thumbs")) ||
+ ($item->is_photo() && (preg_match("/^(.*)\.jpg$/", $item->name))))) {
+ return $item;
+ }
}
}
+ // Nothing found - return an empty item model.
return new Item_Model();
}
-
/**
* Locate an item using the URL. We assume that the url is in the form /a/b/c where each
* component matches up with an item slug. If there's no match, return an empty Item_Model
diff --git a/modules/gallery/helpers/legal_file.php b/modules/gallery/helpers/legal_file.php
index eb9c25de..9f02fe70 100644
--- a/modules/gallery/helpers/legal_file.php
+++ b/modules/gallery/helpers/legal_file.php
@@ -70,7 +70,8 @@ class legal_file_Core {
if (empty(self::$movie_types_by_extension)) {
$types_by_extension_wrapper = new stdClass();
$types_by_extension_wrapper->types_by_extension = array(
- "flv" => "video/x-flv", "mp4" => "video/mp4", "m4v" => "video/x-m4v");
+ "flv" => "video/x-flv", "mp4" => "video/mp4", "m4v" => "video/x-m4v",
+ "webm" => "video/webm", "ogv" => "video/ogg");
module::event("movie_types_by_extension", $types_by_extension_wrapper);
foreach (self::$blacklist as $key) {
unset($types_by_extension_wrapper->types_by_extension[$key]);
@@ -297,7 +298,7 @@ class legal_file_Core {
$filename = str_replace("/", "_", $filename);
$filename = str_replace("\\", "_", $filename);
- // Remove extra dots from the filename. This will also remove extraneous underscores.
+ // Remove extra dots from the filename. Also removes extraneous and leading/trailing underscores.
$filename = legal_file::smash_extensions($filename);
// It's possible that the filename has no base (e.g. ".jpg") - if so, give it a generic one.
@@ -307,4 +308,31 @@ class legal_file_Core {
return $filename;
}
+
+ /**
+ * Sanitize a directory name for an album. This returns a completely legal and valid
+ * directory name.
+ *
+ * @param string $dirname (with no parent directory)
+ * @return string sanitized dirname
+ */
+ static function sanitize_dirname($dirname) {
+ // It should be a dirname without a parent directory - remove all slashes (and backslashes).
+ $dirname = str_replace("/", "_", $dirname);
+ $dirname = str_replace("\\", "_", $dirname);
+
+ // Remove extraneous and leading/trailing underscores.
+ $dirname = preg_replace("/[_]+/", "_", $dirname);
+ $dirname = trim($dirname, "_");
+
+ // Remove any trailing dots.
+ $dirname = rtrim($dirname, ".");
+
+ // It's possible that the dirname is now empty - if so, give it a generic one.
+ if (empty($dirname)) {
+ $dirname = "album";
+ }
+
+ return $dirname;
+ }
}
diff --git a/modules/gallery/helpers/module.php b/modules/gallery/helpers/module.php
index df258e87..1b6c8d1a 100644
--- a/modules/gallery/helpers/module.php
+++ b/modules/gallery/helpers/module.php
@@ -141,7 +141,7 @@ class module_Core {
$messages = array();
$installer_class = "{$module_name}_installer";
- if (method_exists($installer_class, "can_activate")) {
+ if (class_exists($installer_class) && method_exists($installer_class, "can_activate")) {
$messages = call_user_func(array($installer_class, "can_activate"));
}
@@ -173,7 +173,7 @@ class module_Core {
module::_add_to_path($module_name);
$installer_class = "{$module_name}_installer";
- if (method_exists($installer_class, "install")) {
+ if (class_exists($installer_class) && method_exists($installer_class, "install")) {
call_user_func_array(array($installer_class, "install"), array());
}
module::set_version($module_name, module::available()->$module_name->code_version);
@@ -226,7 +226,7 @@ class module_Core {
$version_before = module::get_version($module_name);
$installer_class = "{$module_name}_installer";
$available = module::available();
- if (method_exists($installer_class, "upgrade")) {
+ if (class_exists($installer_class) && method_exists($installer_class, "upgrade")) {
call_user_func_array(array($installer_class, "upgrade"), array($version_before));
} else {
if (isset($available->$module_name->code_version)) {
@@ -261,7 +261,7 @@ class module_Core {
module::_add_to_path($module_name);
$installer_class = "{$module_name}_installer";
- if (method_exists($installer_class, "activate")) {
+ if (class_exists($installer_class) && method_exists($installer_class, "activate")) {
call_user_func_array(array($installer_class, "activate"), array());
}
@@ -288,7 +288,7 @@ class module_Core {
*/
static function deactivate($module_name) {
$installer_class = "{$module_name}_installer";
- if (method_exists($installer_class, "deactivate")) {
+ if (class_exists($installer_class) && method_exists($installer_class, "deactivate")) {
call_user_func_array(array($installer_class, "deactivate"), array());
}
@@ -303,8 +303,25 @@ class module_Core {
block_manager::deactivate_blocks($module_name);
- log::success(
- "module", t("Deactivated module %module_name", array("module_name" => $module_name)));
+ if (module::info($module_name)) {
+ log::success(
+ "module", t("Deactivated module %module_name", array("module_name" => $module_name)));
+ } else {
+ log::success(
+ "module", t("Deactivated missing module %module_name", array("module_name" => $module_name)));
+ }
+ }
+
+ /**
+ * Deactivate modules that are unavailable or missing, yet still active.
+ * This happens when a user deletes a module without deactivating it.
+ */
+ static function deactivate_missing_modules() {
+ foreach (self::$modules as $module_name => $module) {
+ if (module::is_active($module_name) && !module::info($module_name)) {
+ module::deactivate($module_name);
+ }
+ }
}
/**
@@ -314,7 +331,7 @@ class module_Core {
*/
static function uninstall($module_name) {
$installer_class = "{$module_name}_installer";
- if (method_exists($installer_class, "uninstall")) {
+ if (class_exists($installer_class) && method_exists($installer_class, "uninstall")) {
call_user_func(array($installer_class, "uninstall"));
}
@@ -403,7 +420,7 @@ class module_Core {
continue;
}
$class = "{$module->name}_event";
- if (method_exists($class, $function)) {
+ if (class_exists($class) && method_exists($class, $function)) {
call_user_func_array(array($class, $function), $args);
}
}
@@ -411,7 +428,7 @@ class module_Core {
// Give the admin theme a chance to respond, if we're in admin mode.
if (theme::$is_admin) {
$class = theme::$admin_theme_name . "_event";
- if (method_exists($class, $function)) {
+ if (class_exists($class) && method_exists($class, $function)) {
call_user_func_array(array($class, $function), $args);
}
}
@@ -419,7 +436,7 @@ class module_Core {
// Give the site theme a chance to respond as well. It gets a chance even in admin mode, as
// long as the theme has an admin subdir.
$class = theme::$site_theme_name . "_event";
- if (method_exists($class, $function)) {
+ if (class_exists($class) && method_exists($class, $function)) {
call_user_func_array(array($class, $function), $args);
}
}
@@ -541,4 +558,37 @@ class module_Core {
static function get_version($module_name) {
return module::get($module_name)->version;
}
+
+ /**
+ * Check if obsolete modules are active and, if so, return a warning message.
+ * If none are found, return null.
+ */
+ static function get_obsolete_modules_message() {
+ // This is the obsolete modules list. Any active module that's on the list
+ // with version number at or below the one given will be considered obsolete.
+ // It is hard-coded here, and may be updated with future releases of Gallery.
+ $obsolete_modules = array("videos" => 4, "noffmpeg" => 1, "videodimensions" => 1,
+ "digibug" => 2);
+
+ // Before we check the active modules, deactivate any that are missing.
+ module::deactivate_missing_modules();
+
+ $modules_found = array();
+ foreach ($obsolete_modules as $module => $version) {
+ if (module::is_active($module) && (module::get_version($module) <= $version)) {
+ $modules_found[] = $module;
+ }
+ }
+
+ if ($modules_found) {
+ // Need this to be on one super-long line or else the localization scanner may not work.
+ // (ref: http://sourceforge.net/apps/trac/gallery/ticket/1321)
+ return t("Recent upgrades to Gallery have made the following modules obsolete: %modules. We recommend that you <a href=\"%url_mod\">deactivate</a> the module(s). For more information, please see the <a href=\"%url_doc\">documentation page</a>.",
+ array("modules" => implode(", ", $modules_found),
+ "url_mod" => url::site("admin/modules"),
+ "url_doc" => "http://codex.galleryproject.org/Gallery3:User_guide:Obsolete_modules"));
+ }
+
+ return null;
+ }
}
diff --git a/modules/gallery/helpers/movie.php b/modules/gallery/helpers/movie.php
index eda478c7..4613df61 100644
--- a/modules/gallery/helpers/movie.php
+++ b/modules/gallery/helpers/movie.php
@@ -38,6 +38,7 @@ class movie_Core {
->error_messages(
"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 \"/\""))
+ ->error_messages("no_backslashes", t("The movie name can't contain a \"\\\""))
->error_messages("no_trailing_period", t("The movie name can't end in \".\""))
->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"))
@@ -138,7 +139,8 @@ class movie_Core {
* Return the path to the ffmpeg binary if one exists and is executable, or null.
*/
static function find_ffmpeg() {
- if (!($ffmpeg_path = module::get_var("gallery", "ffmpeg_path")) || !file_exists($ffmpeg_path)) {
+ if (!($ffmpeg_path = module::get_var("gallery", "ffmpeg_path")) ||
+ !@is_executable($ffmpeg_path)) {
$ffmpeg_path = system::find_binary(
"ffmpeg", module::get_var("gallery", "graphics_toolkit_path"));
module::set_var("gallery", "ffmpeg_path", $ffmpeg_path);
@@ -147,6 +149,34 @@ class movie_Core {
}
/**
+ * Return version number and build date of ffmpeg if found, empty string(s) if not. When using
+ * static builds that aren't official releases, the version numbers are strange, hence why the
+ * date can be useful.
+ */
+ static function get_ffmpeg_version() {
+ $ffmpeg = movie::find_ffmpeg();
+ if (empty($ffmpeg)) {
+ return array("", "");
+ }
+
+ // Find version using -h argument since -version wasn't available in early versions.
+ // To keep the preg_match searches quick, we'll trim the (otherwise long) result.
+ $cmd = escapeshellcmd($ffmpeg) . " -h 2>&1";
+ $result = substr(`$cmd`, 0, 1000);
+ if (preg_match("/ffmpeg version (\S+)/i", $result, $matches_version)) {
+ // Version number found - see if we can get the build date or copyright year as well.
+ if (preg_match("/built on (\S+\s\S+\s\S+)/i", $result, $matches_build_date)) {
+ return array(trim($matches_version[1], ","), trim($matches_build_date[1], ","));
+ } else if (preg_match("/copyright \S*\s?2000-(\d{4})/i", $result, $matches_copyright_date)) {
+ return array(trim($matches_version[1], ","), $matches_copyright_date[1]);
+ } else {
+ return array(trim($matches_version[1], ","), "");
+ }
+ }
+ return array("", "");
+ }
+
+ /**
* Return the width, height, mime_type, extension and duration of the given movie file.
* Metadata is first generated using ffmpeg (or set to defaults if it fails),
* then can be modified by other modules using movie_get_file_metadata events.
@@ -163,9 +193,7 @@ class movie_Core {
* -> return metadata from ffmpeg
* Input is *not* standard movie type that is *not* supported by ffmpeg but is legal
* -> return zero width, height, and duration; mime type and extension according to legal_file
- * Input is *not* standard movie type that is *not* supported by ffmpeg and is *not* legal
- * -> return zero width, height, and duration; null mime type and extension
- * Input is not readable or does not exist
+ * Input is illegal, unidentifiable, unreadable, or does not exist
* -> throw exception
* Note: movie_get_file_metadata events can change any of the above cases (except the last one).
*/
diff --git a/modules/gallery/helpers/photo.php b/modules/gallery/helpers/photo.php
index 2d32f0d3..ecf81e66 100644
--- a/modules/gallery/helpers/photo.php
+++ b/modules/gallery/helpers/photo.php
@@ -35,6 +35,7 @@ class photo_Core {
$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 \"/\""))
+ ->error_messages("no_backslashes", t("The photo name can't contain a \"\\\""))
->error_messages("no_trailing_period", t("The photo name can't end in \".\""))
->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"))
@@ -94,10 +95,8 @@ class photo_Core {
* Input is *not* standard photo type that is supported by getimagesize (e.g. tif, bmp...)
* -> return metadata from getimagesize()
* Input is *not* standard photo type that is *not* supported by getimagesize but is legal
- * -> return zero width and height, mime type and extension according to legal_file
- * Input is *not* standard photo type that is *not* supported by getimagesize and is *not* legal
- * -> return zero width and height, null mime type and extension
- * Input is not readable or does not exist
+ * -> return metadata if found by photo_get_file_metadata events
+ * Input is illegal, unidentifiable, unreadable, or does not exist
* -> throw exception
* Note: photo_get_file_metadata events can change any of the above cases (except the last one).
*/
diff --git a/modules/gallery/helpers/system.php b/modules/gallery/helpers/system.php
index e1398103..f0879d6a 100644
--- a/modules/gallery/helpers/system.php
+++ b/modules/gallery/helpers/system.php
@@ -18,6 +18,8 @@
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
class system_Core {
+ private static $files_marked_for_deletion = array();
+
/**
* Return the path to an executable version of the named binary, or null.
* The paths are traversed in the following order:
@@ -45,6 +47,7 @@ class system_Core {
explode(":", module::get_var("gallery", "extra_binary_paths")));
foreach ($paths as $path) {
+ $path = rtrim($path, "/");
$candidate = "$path/$binary";
// @suppress errors below to avoid open_basedir issues
if (@file_exists($candidate)) {
@@ -66,8 +69,10 @@ class system_Core {
* This helper is similar to the built-in tempnam.
* It allows the caller to specify a prefix and an extension.
* It always places the file in TMPPATH.
+ * Unless specified with the $delete_later argument, it will be marked
+ * for deletion at shutdown using system::delete_later.
*/
- static function temp_filename($prefix="", $extension="") {
+ static function temp_filename($prefix="", $extension="", $delete_later=true) {
do {
$basename = tempnam(TMPPATH, $prefix);
if (!$basename) {
@@ -79,6 +84,30 @@ class system_Core {
@unlink($basename);
}
} while (!$success);
+
+ if ($delete_later) {
+ system::delete_later($filename);
+ }
+
return $filename;
}
-} \ No newline at end of file
+
+ /**
+ * Mark a file for deletion at shutdown time. This is useful for temp files, where we can delay
+ * the deletion time until shutdown to keep page load time quick.
+ */
+ static function delete_later($filename) {
+ self::$files_marked_for_deletion[] = $filename;
+ }
+
+ /**
+ * Delete all files marked using system::delete_later. This is called at gallery shutdown.
+ */
+ static function delete_marked_files() {
+ foreach (self::$files_marked_for_deletion as $filename) {
+ // We want to suppress all errors, as it's possible that some of these
+ // files may have been deleted/moved before we got here.
+ @unlink($filename);
+ }
+ }
+}
diff --git a/modules/gallery/helpers/task.php b/modules/gallery/helpers/task.php
index 32fd9739..5638faf4 100644
--- a/modules/gallery/helpers/task.php
+++ b/modules/gallery/helpers/task.php
@@ -25,7 +25,7 @@ class task_Core {
$tasks = array();
foreach (module::active() as $module) {
$class_name = "{$module->name}_task";
- if (method_exists($class_name, "available_tasks")) {
+ if (class_exists($class_name) && method_exists($class_name, "available_tasks")) {
foreach (call_user_func(array($class_name, "available_tasks")) as $task) {
$tasks[$task->callback] = $task;
}