summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.build_number2
-rw-r--r--index.php7
-rw-r--r--installer/install.sql5
-rw-r--r--installer/installer.php5
-rw-r--r--modules/digibug/config/digibug.php29
-rw-r--r--modules/digibug/controllers/admin_digibug.php27
-rw-r--r--modules/digibug/controllers/digibug.php121
-rw-r--r--modules/digibug/helpers/digibug_event.php52
-rw-r--r--modules/digibug/helpers/digibug_installer.php51
-rw-r--r--modules/digibug/helpers/digibug_theme.php24
-rw-r--r--modules/digibug/images/digibug_logo.pngbin17296 -> 0 bytes
-rw-r--r--modules/digibug/js/digibug.js43
-rw-r--r--modules/digibug/models/digibug_proxy.php22
-rw-r--r--modules/digibug/module.info7
-rw-r--r--modules/digibug/tests/Digibug_Controller_Test.php74
-rw-r--r--modules/digibug/views/admin_digibug.html.php20
-rw-r--r--modules/digibug/views/digibug_form.html.php13
-rw-r--r--modules/g2_import/controllers/g2.php2
-rw-r--r--modules/gallery/controllers/admin_movies.php72
-rw-r--r--modules/gallery/controllers/albums.php4
-rw-r--r--modules/gallery/controllers/upgrader.php6
-rw-r--r--modules/gallery/controllers/uploader.php4
-rw-r--r--modules/gallery/helpers/gallery_event.php4
-rw-r--r--modules/gallery/helpers/gallery_graphics.php5
-rw-r--r--modules/gallery/helpers/gallery_installer.php8
-rw-r--r--modules/gallery/helpers/graphics.php35
-rw-r--r--modules/gallery/helpers/legal_file.php79
-rw-r--r--modules/gallery/helpers/movie.php67
-rw-r--r--modules/gallery/helpers/photo.php15
-rw-r--r--modules/gallery/helpers/system.php36
-rw-r--r--modules/gallery/images/ffmpeg.pngbin0 -> 2888 bytes
-rw-r--r--modules/gallery/libraries/Form_Uploadify.php2
-rw-r--r--modules/gallery/libraries/Theme_View.php6
-rw-r--r--modules/gallery/models/item.php154
-rw-r--r--modules/gallery/module.info2
-rw-r--r--modules/gallery/tests/Item_Model_Test.php124
-rw-r--r--modules/gallery/tests/Legal_File_Helper_Test.php54
-rw-r--r--modules/gallery/tests/Movie_Helper_Test.php36
-rw-r--r--modules/gallery/tests/Photo_Helper_Test.php18
-rw-r--r--modules/gallery/tests/xss_data.txt1
-rw-r--r--modules/gallery/views/admin_movies.html.php44
-rw-r--r--modules/gallery/views/form_uploadify.html.php2
-rw-r--r--modules/search/controllers/search.php11
-rw-r--r--modules/search/helpers/search.php10
-rw-r--r--modules/watermark/controllers/admin_watermarks.php20
-rw-r--r--system/libraries/ORM.php1
46 files changed, 663 insertions, 661 deletions
diff --git a/.build_number b/.build_number
index 5f471925..6f2a9ebc 100644
--- a/.build_number
+++ b/.build_number
@@ -3,4 +3,4 @@
; process. You don't need to edit it. In fact..
;
; DO NOT EDIT THIS FILE BY HAND!
-build_number=324
+build_number=347
diff --git a/index.php b/index.php
index 5f6d231b..c39452ea 100644
--- a/index.php
+++ b/index.php
@@ -29,6 +29,13 @@ if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
exit("Gallery is not supported on Windows (PHP reports that you're using: " . PHP_OS . ")");
}
+// Gallery doesn't use Zend Guard code obfuscation, and Kohana 2.4 will not work if level is 3+.
+if (function_exists("zend_current_obfuscation_level") && (zend_current_obfuscation_level() >= 3)) {
+ exit("Gallery doesn't use Zend Guard code obfuscation, and is incompatible if it's running " .
+ "with a level of 3 or higher. For Gallery to run, please edit your main php.ini file and " .
+ "change/add the following line: 'zend_loader.obfuscation_level_support = 2'");
+}
+
// PHP 5.4 requires a timezone - if one isn't set date functions aren't going to work properly.
// We'll log this once the logging system is initialized (in the gallery_event::gallery_ready).
if (!ini_get("date.timezone")) {
diff --git a/installer/install.sql b/installer/install.sql
index 4097d51e..b89d6b9b 100644
--- a/installer/install.sql
+++ b/installer/install.sql
@@ -245,7 +245,7 @@ CREATE TABLE {modules} (
KEY `weight` (`weight`)
) AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
-INSERT INTO {modules} VALUES (1,1,'gallery',55,1);
+INSERT INTO {modules} VALUES (1,1,'gallery',56,1);
INSERT INTO {modules} VALUES (2,1,'user',4,2);
INSERT INTO {modules} VALUES (3,1,'comment',7,3);
INSERT INTO {modules} VALUES (4,1,'organize',4,4);
@@ -383,7 +383,7 @@ CREATE TABLE {vars} (
`value` text,
PRIMARY KEY (`id`),
UNIQUE KEY `module_name` (`module_name`,`name`)
-) AUTO_INCREMENT=46 DEFAULT CHARSET=utf8;
+) AUTO_INCREMENT=47 DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
INSERT INTO {vars} VALUES (NULL,'gallery','active_site_theme','wind');
INSERT INTO {vars} VALUES (NULL,'gallery','active_admin_theme','admin_wind');
@@ -417,6 +417,7 @@ INSERT INTO {vars} VALUES (NULL,'gallery','extra_binary_paths','/usr/local/bin:/
INSERT INTO {vars} VALUES (NULL,'gallery','timezone',NULL);
INSERT INTO {vars} VALUES (NULL,'gallery','lock_timeout','1');
INSERT INTO {vars} VALUES (NULL,'gallery','movie_extract_frame_time','3');
+INSERT INTO {vars} VALUES (NULL,'gallery','movie_allow_uploads','autodetect');
INSERT INTO {vars} VALUES (NULL,'gallery','blocks_site_sidebar','a:4:{i:10;a:2:{i:0;s:7:\"gallery\";i:1;s:8:\"language\";}i:11;a:2:{i:0;s:4:\"info\";i:1;s:8:\"metadata\";}i:12;a:2:{i:0;s:3:\"rss\";i:1;s:9:\"rss_feeds\";}i:13;a:2:{i:0;s:3:\"tag\";i:1;s:3:\"tag\";}}');
INSERT INTO {vars} VALUES (NULL,'gallery','identity_provider','user');
INSERT INTO {vars} VALUES (NULL,'user','minimum_password_length','5');
diff --git a/installer/installer.php b/installer/installer.php
index 4ce80ee7..2b0f1452 100644
--- a/installer/installer.php
+++ b/installer/installer.php
@@ -243,6 +243,11 @@ class installer {
$errors[] = "Gallery cannot function when PHP is in <a href=\"http://php.net/manual/en/features.safe-mode.php\">Safe Mode</a>. Please disable safe mode.";
}
+ if (function_exists("zend_current_obfuscation_level") && (zend_current_obfuscation_level() >= 3)) {
+ $errors[] = "Gallery doesn't use <a href=\"http://www.zend.com/en/products/guard\">Zend Guard code obfuscation</a>, and is incompatible if it's running " .
+ "with a level of 3 or higher. Please edit your main php.ini file and change/add the following line: 'zend_loader.obfuscation_level_support = 2'";
+ }
+
return @$errors;
}
diff --git a/modules/digibug/config/digibug.php b/modules/digibug/config/digibug.php
deleted file mode 100644
index 9412ca96..00000000
--- a/modules/digibug/config/digibug.php
+++ /dev/null
@@ -1,29 +0,0 @@
-<?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.
- */
-/**
- * PHP Mail Configuration parameters
- * from => email address that appears as the from address
- * line-length => word wrap length (PHP documentations suggest no larger tha 70 characters
- * reply-to => what goes into the reply to header
- */
-$config["ranges"] = array(
- "Digibug1" => array("low" => "65.249.152.0", "high" => "65.249.159.255"),
- "Digibug2" => array("low" => "208.122.55.0", "high" => "208.122.55.255")
-);
diff --git a/modules/digibug/controllers/admin_digibug.php b/modules/digibug/controllers/admin_digibug.php
deleted file mode 100644
index 50f6f832..00000000
--- a/modules/digibug/controllers/admin_digibug.php
+++ /dev/null
@@ -1,27 +0,0 @@
-<?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_Digibug_Controller extends Admin_Controller {
- public function index() {
- $v = new Admin_View("admin.html");
- $v->page_title = t("Digibug");
- $v->content = new View("admin_digibug.html");
- print $v;
- }
-} \ No newline at end of file
diff --git a/modules/digibug/controllers/digibug.php b/modules/digibug/controllers/digibug.php
deleted file mode 100644
index 19199188..00000000
--- a/modules/digibug/controllers/digibug.php
+++ /dev/null
@@ -1,121 +0,0 @@
-<?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 Digibug_Controller extends Controller {
- const ALLOW_PRIVATE_GALLERY = true;
-
- public function print_photo($id) {
- access::verify_csrf();
- $item = ORM::factory("item", $id);
- access::required("view", $item);
-
- if (access::group_can(identity::everybody(), "view_full", $item)) {
- $full_url = $item->file_url(true);
- $thumb_url = $item->thumb_url(true);
- } else {
- $proxy = ORM::factory("digibug_proxy");
- $proxy->uuid = random::hash();
- $proxy->item_id = $item->id;
- $proxy->save();
- $full_url = url::abs_site("digibug/print_proxy/full/$proxy->uuid/$item->id");
- $thumb_url = url::abs_site("digibug/print_proxy/thumb/$proxy->uuid/$item->id");
- }
-
- $v = new View("digibug_form.html");
- $v->order_params = array(
- "digibug_api_version" => "100",
- "company_id" => module::get_var("digibug", "company_id"),
- "event_id" => module::get_var("digibug", "event_id"),
- "cmd" => "addimg",
- "partner_code" => "69",
- "return_url" => url::abs_site("digibug/close_window"),
- "num_images" => "1",
- "image_1" => $full_url,
- "thumb_1" => $thumb_url,
- "image_height_1" => $item->height,
- "image_width_1" => $item->width,
- "thumb_height_1" => $item->thumb_height,
- "thumb_width_1" => $item->thumb_width,
- "title_1" => html::purify($item->title));
-
- print $v;
- }
-
- public function print_proxy($type, $uuid) {
- // If its a request for the full size then make sure we are coming from an
- // authorized address
- if ($type == "full") {
- $remote_addr = ip2long(Input::instance()->server("REMOTE_ADDR"));
- if ($remote_addr === false) {
- throw new Kohana_404_Exception();
- }
- $config = Kohana::config("digibug");
-
- $authorized = false;
- foreach ($config["ranges"] as $ip_range) {
- $low = ip2long($ip_range["low"]);
- $high = ip2long($ip_range["high"]);
- $authorized = $low !== false && $high !== false &&
- $low <= $remote_addr && $remote_addr <= $high;
- if ($authorized) {
- break;
- }
- }
- if (!$authorized) {
- throw new Kohana_404_Exception();
- }
- }
-
- $proxy = ORM::factory("digibug_proxy")->where("uuid", "=", $uuid)->find();
- if (!$proxy->loaded() || !$proxy->item->loaded()) {
- throw new Kohana_404_Exception();
- }
-
- $file = $type == "full" ? $proxy->item->file_path() : $proxy->item->thumb_path();
- if (!file_exists($file)) {
- throw new Kohana_404_Exception();
- }
-
- // We don't need to save the session for this request
- Session::instance()->abort_save();
-
- if (!TEST_MODE) {
- // Dump out the image
- header("Content-Type: {$proxy->item->mime_type}");
- Kohana::close_buffers(false);
- $fd = fopen($file, "rb");
- fpassthru($fd);
- fclose($fd);
- }
-
- $this->_clean_expired();
- }
-
- public function close_window() {
- print "<script type=\"text/javascript\">window.close();</script>";
- }
-
- private function _clean_expired() {
- db::build()
- ->delete("digibug_proxies")
- ->where("request_date", "<=", db::expr("(CURDATE() - INTERVAL 90 DAY)"))
- ->limit(20)
- ->execute();
- }
-} \ No newline at end of file
diff --git a/modules/digibug/helpers/digibug_event.php b/modules/digibug/helpers/digibug_event.php
deleted file mode 100644
index eaebc87b..00000000
--- a/modules/digibug/helpers/digibug_event.php
+++ /dev/null
@@ -1,52 +0,0 @@
-<?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 digibug_event_Core {
- static function admin_menu($menu, $theme) {
- $menu->get("settings_menu")
- ->append(Menu::factory("link")
- ->id("digibug_menu")
- ->label(t("Digibug"))
- ->url(url::site("admin/digibug")));
- }
-
- static function site_menu($menu, $theme) {
- $item = $theme->item();
- if ($item && $item->type == "photo") {
- $menu->get("options_menu")
- ->append(Menu::factory("link")
- ->id("digibug")
- ->label(t("Print with Digibug"))
- ->url(url::site("digibug/print_photo/$item->id?csrf=$theme->csrf"))
- ->css_id("g-print-digibug-link")
- ->css_class("g-print-digibug-link ui-icon-print"));
- }
- }
-
- static function context_menu($menu, $theme, $item) {
- if ($item->type == "photo") {
- $menu->get("options_menu")
- ->append(Menu::factory("link")
- ->id("digibug")
- ->label(t("Print with Digibug"))
- ->url(url::site("digibug/print_photo/$item->id?csrf=$theme->csrf"))
- ->css_class("g-print-digibug-link ui-icon-print"));
- }
- }
-}
diff --git a/modules/digibug/helpers/digibug_installer.php b/modules/digibug/helpers/digibug_installer.php
deleted file mode 100644
index be88b5ec..00000000
--- a/modules/digibug/helpers/digibug_installer.php
+++ /dev/null
@@ -1,51 +0,0 @@
-<?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 digibug_installer {
- static function install() {
- Database::instance()
- ->query("CREATE TABLE {digibug_proxies} (
- `id` int(9) NOT NULL AUTO_INCREMENT,
- `uuid` char(32) NOT NULL,
- `request_date` TIMESTAMP NOT NULL DEFAULT current_timestamp,
- `item_id` int(9) NOT NULL,
- PRIMARY KEY (`id`))
- DEFAULT CHARSET=utf8;");
-
- module::set_var("digibug", "company_id", "3153");
- module::set_var("digibug", "event_id", "8491");
- }
-
- static function upgrade($version) {
- if ($version == 1) {
- module::clear_var("digibug", "default_company_id");
- module::clear_var("digibug", "default_event_id");
- module::clear_var("digibug", "basic_default_company_id");
- module::clear_var("digibug", "basic_event_id");
- module::set_var("digibug", "company_id", "3153");
- module::set_var("digibug", "event_id", "8491");
- module::set_version("digibug", $version = 2);
- }
- }
-
- static function uninstall() {
- Database::instance()->query("DROP TABLE IF EXISTS {digibug_proxies}");
- module::delete("digibug");
- }
-}
diff --git a/modules/digibug/helpers/digibug_theme.php b/modules/digibug/helpers/digibug_theme.php
deleted file mode 100644
index e3795c3b..00000000
--- a/modules/digibug/helpers/digibug_theme.php
+++ /dev/null
@@ -1,24 +0,0 @@
-<?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 digibug_theme_Core {
- static function head($theme) {
- return $theme->script("digibug.js");
- }
-}
diff --git a/modules/digibug/images/digibug_logo.png b/modules/digibug/images/digibug_logo.png
deleted file mode 100644
index 5eac2c7d..00000000
--- a/modules/digibug/images/digibug_logo.png
+++ /dev/null
Binary files differ
diff --git a/modules/digibug/js/digibug.js b/modules/digibug/js/digibug.js
deleted file mode 100644
index 46ddac52..00000000
--- a/modules/digibug/js/digibug.js
+++ /dev/null
@@ -1,43 +0,0 @@
-$(document).ready(function() {
- $(".g-print-digibug-link").click(function(e) {
- e.preventDefault();
- return digibug_popup(e.currentTarget.href, { width: 800, height: 600 } );
- });
-});
-
-function digibug_popup(url, options) {
- options = $.extend({
- /* default options */
- width: '800',
- height: '600',
- target: 'dbPopWin',
- scrollbars: 'yes',
- resizable: 'no',
- menuBar: 'no',
- addressBar: 'yes'
- }, options);
-
- // center the window by default.
- if (!options.winY) {
- options.winY = screen.height / 2 - options.height / 2;
- };
- if (!options.winX) {
- options.winX = screen.width / 2 - options.width / 2;
- };
-
- open(
- url,
- options['target'],
- 'width= ' + options.width +
- ',height=' + options.height +
- ',top=' + options.winY +
- ',left=' + options.winX +
- ',scrollbars=' + options.scrollbars +
- ',resizable=' + options.resizable +
- ',menubar=' + options.menuBar +
- ',location=' + options.addressBar
- );
-
- return false;
-
-}
diff --git a/modules/digibug/models/digibug_proxy.php b/modules/digibug/models/digibug_proxy.php
deleted file mode 100644
index 18c77d49..00000000
--- a/modules/digibug/models/digibug_proxy.php
+++ /dev/null
@@ -1,22 +0,0 @@
-<?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 Digibug_Proxy_Model_Core extends ORM {
- protected $belongs_to = array("item");
-}
diff --git a/modules/digibug/module.info b/modules/digibug/module.info
deleted file mode 100644
index 5e5ca10f..00000000
--- a/modules/digibug/module.info
+++ /dev/null
@@ -1,7 +0,0 @@
-name = "Digibug"
-description = "Digibug Photo Printing Module"
-version = 2
-author_name = "Gallery Team"
-author_url = "http://codex.galleryproject.org/Gallery:Team"
-info_url = "http://codex.galleryproject.org/Gallery3:Modules:digibug"
-discuss_url = "http://galleryproject.org/forum_module_digibug"
diff --git a/modules/digibug/tests/Digibug_Controller_Test.php b/modules/digibug/tests/Digibug_Controller_Test.php
deleted file mode 100644
index 3b3ceba2..00000000
--- a/modules/digibug/tests/Digibug_Controller_Test.php
+++ /dev/null
@@ -1,74 +0,0 @@
-<?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 Digibug_Controller_Test extends Gallery_Unit_Test_Case {
- private $_server;
-
- public function setup() {
- $this->_server = $_SERVER;
- }
-
- public function teardown() {
- $_SERVER = $this->_server;
- }
-
- private function _get_proxy() {
- $album = test::random_album();
- $photo = test::random_photo($album);
-
- access::deny(identity::everybody(), "view_full", $album);
- access::deny(identity::registered_users(), "view_full", $album);
-
- $proxy = ORM::factory("digibug_proxy");
- $proxy->uuid = random::hash();
- $proxy->item_id = $photo->id;
- return $proxy->save();
- }
-
- public function digibug_request_thumb_test() {
- $proxy = $this->_get_proxy();
-
- $controller = new Digibug_Controller();
- $controller->print_proxy("thumb", $proxy->uuid);
- }
-
- public function digibug_request_full_malicious_ip_test() {
- $_SERVER["REMOTE_ADDR"] = "123.123.123.123";
- try {
- $controller = new Digibug_Controller();
- $controller->print_proxy("full", $this->_get_proxy()->uuid);
- $this->assert_true(false, "Should have failed with an 404 exception");
- } catch (Kohana_404_Exception $e) {
- // expected behavior
- }
- }
-
- public function digibug_request_full_authorized_ip_test() {
- $config = Kohana::config("digibug");
- $this->assert_true(!empty($config), "The Digibug config is empty");
-
- $ranges = array_values($config["ranges"]);
- $low = ip2long($ranges[0]["low"]);
- $high = ip2long($ranges[0]["high"]);
-
- $_SERVER["REMOTE_ADDR"] = long2ip(rand($low, $high));
- $controller = new Digibug_Controller();
- $controller->print_proxy("full", $this->_get_proxy()->uuid);
- }
-}
diff --git a/modules/digibug/views/admin_digibug.html.php b/modules/digibug/views/admin_digibug.html.php
deleted file mode 100644
index d673b116..00000000
--- a/modules/digibug/views/admin_digibug.html.php
+++ /dev/null
@@ -1,20 +0,0 @@
-<?php defined("SYSPATH") or die("No direct script access.") ?>
-<div class="g-block">
- <img src="<?= url::file("modules/digibug/images/digibug_logo.png") ?>" alt="Digibug logo" class="g-right"/>
- <h1> <?= t("Digibug photo printing") ?> </h1>
- <div class="g-block-content">
- <p>
- <?= t("Turn your photos into a wide variety of prints, gifts and games!") ?>
- </p>
- <ul>
- <li class="g-module-status g-success">
- <?= t("You're ready to print photos!") ?>
- </li>
- </ul>
- <p>
- <?= t("You don't need an account with Digibug, but if you <a href=\"%signup_url\">register with Digibug</a> and enter your Digibug id in the <a href=\"%advanced_settings_url\">Advanced Settings</a> page you can make money off of your photos!",
- array("signup_url" => "http://www.digibug.com/signup.php",
- "advanced_settings_url" => html::mark_clean(url::site("admin/advanced_settings")))) ?>
- </p>
- </div>
-</div>
diff --git a/modules/digibug/views/digibug_form.html.php b/modules/digibug/views/digibug_form.html.php
deleted file mode 100644
index af5a88b4..00000000
--- a/modules/digibug/views/digibug_form.html.php
+++ /dev/null
@@ -1,13 +0,0 @@
-<?php defined("SYSPATH") or die("No direct script access.") ?>
-<html>
- <body>
- <?= form::open("http://www.digibug.com/dapi/order.php") ?>
- <? foreach ($order_params as $key => $value): ?>
- <?= form::hidden($key, $value) ?>
- <? endforeach ?>
- </form>
- <script type="text/javascript">
- document.forms[0].submit();
- </script>
- </body>
-</html>
diff --git a/modules/g2_import/controllers/g2.php b/modules/g2_import/controllers/g2.php
index c9b1d182..c24d52e9 100644
--- a/modules/g2_import/controllers/g2.php
+++ b/modules/g2_import/controllers/g2.php
@@ -37,7 +37,7 @@ class G2_Controller extends Controller {
// Tags did not have mappings created, so we need to catch them first. However, if a g2_itemId was
// passed, we'll want to show lookup the mapping anyway
- if (($path && 0 === strpos($path, "tag/")) || $view = "tags.VirtualAlbum") {
+ if (($path && 0 === strpos($path, "tag/")) || $view == "tags.VirtualAlbum") {
if (0 === strpos($path, "tag/")) {
$tag_name = substr($path, 4);
}
diff --git a/modules/gallery/controllers/admin_movies.php b/modules/gallery/controllers/admin_movies.php
new file mode 100644
index 00000000..38fa44a5
--- /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/albums.php b/modules/gallery/controllers/albums.php
index d545b415..0fb033a8 100644
--- a/modules/gallery/controllers/albums.php
+++ b/modules/gallery/controllers/albums.php
@@ -98,9 +98,9 @@ class Albums_Controller extends Items_Controller {
"breadcrumbs" => Breadcrumb::array_from_item_parents($item));
}
- static function get_siblings($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();
+ return $item->parent()->viewable()->children($limit, $offset);
}
public function create($parent_id) {
diff --git a/modules/gallery/controllers/upgrader.php b/modules/gallery/controllers/upgrader.php
index e60385d9..d3c6e2ec 100644
--- a/modules/gallery/controllers/upgrader.php
+++ b/modules/gallery/controllers/upgrader.php
@@ -107,7 +107,11 @@ class Upgrader_Controller extends Controller {
print "Upgrade complete\n";
}
} else {
- url::redirect("upgrader?failed=" . join(",", $failed));
+ 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
index 55c65c95..78437071 100644
--- a/modules/gallery/controllers/uploader.php
+++ b/modules/gallery/controllers/uploader.php
@@ -63,10 +63,6 @@ class Uploader_Controller extends Controller {
$item->parent_id = $album->id;
$item->set_data_file($temp_filename);
- // Remove double extensions from the filename - they'll be disallowed in the model but if
- // we don't do it here then it'll result in a failed upload.
- $item->name = legal_file::smash_extensions($item->name);
-
$path_info = @pathinfo($temp_filename);
if (array_key_exists("extension", $path_info) &&
legal_file::get_movie_extensions($path_info["extension"])) {
diff --git a/modules/gallery/helpers/gallery_event.php b/modules/gallery/helpers/gallery_event.php
index aeb1c7eb..54c60296 100644
--- a/modules/gallery/helpers/gallery_event.php
+++ b/modules/gallery/helpers/gallery_event.php
@@ -399,6 +399,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_graphics.php b/modules/gallery/helpers/gallery_graphics.php
index b78bd9a7..eb76353f 100644
--- a/modules/gallery/helpers/gallery_graphics.php
+++ b/modules/gallery/helpers/gallery_graphics.php
@@ -172,6 +172,11 @@ class gallery_graphics_Core {
module::event("graphics_composite_completed", $input_file, $output_file, $options, $item);
} catch (ErrorException $e) {
+ // Unlike rotate and resize, composite catches its exceptions here. This is because
+ // composite is typically called for watermarks. If during thumb/resize generation
+ // the watermark fails, we'd still like the image resized, just without its watermark.
+ // If the exception isn't caught here, graphics::generate will replace it with a
+ // placeholder.
Kohana_Log::add("error", $e->getMessage());
}
}
diff --git a/modules/gallery/helpers/gallery_installer.php b/modules/gallery/helpers/gallery_installer.php
index 7f10cdee..051a66cf 100644
--- a/modules/gallery/helpers/gallery_installer.php
+++ b/modules/gallery/helpers/gallery_installer.php
@@ -315,6 +315,7 @@ class gallery_installer {
module::set_var("gallery", "timezone", null);
module::set_var("gallery", "lock_timeout", 1);
module::set_var("gallery", "movie_extract_frame_time", 3);
+ module::set_var("gallery", "movie_allow_uploads", "autodetect");
}
static function upgrade($version) {
@@ -789,6 +790,13 @@ class gallery_installer {
module::set_version("gallery", $version = 55);
}
+ if ($version == 55) {
+ // In v56, we added the ability to change the default behavior regarding movie uploads. It
+ // can be set to "always", "never", or "autodetect" to match the previous behavior where they
+ // are allowed only if FFmpeg is found.
+ module::set_var("gallery", "movie_allow_uploads", "autodetect");
+ module::set_version("gallery", $version = 56);
+ }
}
static function uninstall() {
diff --git a/modules/gallery/helpers/graphics.php b/modules/gallery/helpers/graphics.php
index 7c8e89d5..e66908c4 100644
--- a/modules/gallery/helpers/graphics.php
+++ b/modules/gallery/helpers/graphics.php
@@ -149,6 +149,19 @@ class graphics_Core {
if (@filesize($output_file) == 0) {
try {
movie::extract_frame($working_file, $output_file, $movie_options_wrapper->movie_options);
+ // If we're here, we know ffmpeg is installed and the movie is valid. Because the
+ // user may not always have had ffmpeg installed, the movie's width, height, and
+ // mime type may need updating. Let's use this opportunity to make sure they're
+ // correct. It's not optimal to do it at this low level, but it's not trivial to find
+ // these cases quickly in an upgrade script.
+ list ($width, $height, $mime_type) = movie::get_file_metadata($working_file);
+ // Only set them if they need updating to avoid marking them as "changed"
+ if (($item->width != $width) || ($item->height != $height) ||
+ ($item->mime_type != $mime_type)) {
+ $item->width = $width;
+ $item->height = $height;
+ $item->mime_type = $mime_type;
+ }
} catch (Exception $e) {
// Didn't work, likely because of MISSING_FFMPEG - use placeholder
graphics::_replace_image_with_placeholder($item, $target);
@@ -224,7 +237,16 @@ class graphics_Core {
graphics::_replace_image_with_placeholder($item, "resize");
}
graphics::_replace_image_with_placeholder($item, "thumb");
- graphics::_update_item_dimensions($item);
+ try {
+ graphics::_update_item_dimensions($item);
+ } catch (Exception $e) {
+ // Looks like get_file_metadata couldn't identify our placeholders. We should never get
+ // here, but in the odd case we do, we need to do something. Let's put in hardcoded values.
+ if ($item->is_photo()) {
+ list ($item->resize_width, $item->resize_height) = array(200, 200);
+ }
+ list ($item->thumb_width, $item->thumb_height) = array(200, 200);
+ }
$item->save();
throw $e;
}
@@ -314,12 +336,19 @@ class graphics_Core {
}
/**
- * Mark thumbnails and resizes as dirty. They will have to be rebuilt.
+ * Mark thumbnails and resizes as dirty. They will have to be rebuilt. Optionally, only those of
+ * a specified type and/or mime type can be marked (e.g. $type="movie" to rebuild movies only).
*/
- static function mark_dirty($thumbs, $resizes) {
+ static function mark_dirty($thumbs, $resizes, $type=null, $mime_type=null) {
if ($thumbs || $resizes) {
$db = db::build()
->update("items");
+ if ($type) {
+ $db->where("type", "=", $type);
+ }
+ if ($mime_type) {
+ $db->where("mime_type", "=", $mime_type);
+ }
if ($thumbs) {
$db->set("thumb_dirty", 1);
}
diff --git a/modules/gallery/helpers/legal_file.php b/modules/gallery/helpers/legal_file.php
index ab9047c8..eb9c25de 100644
--- a/modules/gallery/helpers/legal_file.php
+++ b/modules/gallery/helpers/legal_file.php
@@ -24,6 +24,8 @@ class legal_file_Core {
private static $movie_extensions;
private static $photo_types;
private static $movie_types;
+ private static $blacklist = array("php", "php3", "php4", "php5", "phtml", "phtm", "shtml", "shtm",
+ "pl", "cgi", "asp", "sh", "py", "c", "js");
/**
* Create a default list of allowed photo MIME types paired with their extensions and then let
@@ -38,6 +40,9 @@ class legal_file_Core {
$types_by_extension_wrapper->types_by_extension = array(
"jpg" => "image/jpeg", "jpeg" => "image/jpeg", "gif" => "image/gif", "png" => "image/png");
module::event("photo_types_by_extension", $types_by_extension_wrapper);
+ foreach (self::$blacklist as $key) {
+ unset($types_by_extension_wrapper->types_by_extension[$key]);
+ }
self::$photo_types_by_extension = $types_by_extension_wrapper->types_by_extension;
}
if ($extension) {
@@ -67,6 +72,9 @@ class legal_file_Core {
$types_by_extension_wrapper->types_by_extension = array(
"flv" => "video/x-flv", "mp4" => "video/mp4", "m4v" => "video/x-m4v");
module::event("movie_types_by_extension", $types_by_extension_wrapper);
+ foreach (self::$blacklist as $key) {
+ unset($types_by_extension_wrapper->types_by_extension[$key]);
+ }
self::$movie_types_by_extension = $types_by_extension_wrapper->types_by_extension;
}
if ($extension) {
@@ -90,7 +98,7 @@ class legal_file_Core {
*/
static function get_types_by_extension($extension=null) {
$types_by_extension = legal_file::get_photo_types_by_extension();
- if (movie::find_ffmpeg()) {
+ if (movie::allow_uploads()) {
$types_by_extension = array_merge($types_by_extension,
legal_file::get_movie_types_by_extension());
}
@@ -118,7 +126,7 @@ class legal_file_Core {
$extensions_wrapper = new stdClass();
$extensions_wrapper->extensions = array_keys(legal_file::get_photo_types_by_extension());
module::event("legal_photo_extensions", $extensions_wrapper);
- self::$photo_extensions = $extensions_wrapper->extensions;
+ self::$photo_extensions = array_diff($extensions_wrapper->extensions, self::$blacklist);
}
if ($extension) {
// return true if in array, false if not
@@ -139,7 +147,7 @@ class legal_file_Core {
$extensions_wrapper = new stdClass();
$extensions_wrapper->extensions = array_keys(legal_file::get_movie_types_by_extension());
module::event("legal_movie_extensions", $extensions_wrapper);
- self::$movie_extensions = $extensions_wrapper->extensions;
+ self::$movie_extensions = array_diff($extensions_wrapper->extensions, self::$blacklist);
}
if ($extension) {
// return true if in array, false if not
@@ -157,7 +165,7 @@ class legal_file_Core {
*/
static function get_extensions($extension=null) {
$extensions = legal_file::get_photo_extensions();
- if (movie::find_ffmpeg()) {
+ if (movie::allow_uploads()) {
$extensions = array_merge($extensions, legal_file::get_movie_extensions());
}
if ($extension) {
@@ -227,6 +235,10 @@ class legal_file_Core {
* Reduce the given file to having a single extension.
*/
static function smash_extensions($filename) {
+ if (!$filename) {
+ // It's harmless, so return it before it causes issues with pathinfo.
+ return $filename;
+ }
$parts = pathinfo($filename);
$result = "";
if ($parts["dirname"] != ".") {
@@ -235,7 +247,64 @@ class legal_file_Core {
$parts["filename"] = str_replace(".", "_", $parts["filename"]);
$parts["filename"] = preg_replace("/[_]+/", "_", $parts["filename"]);
$parts["filename"] = trim($parts["filename"], "_");
- $result .= "{$parts['filename']}.{$parts['extension']}";
+ $result .= isset($parts["extension"]) ? "{$parts['filename']}.{$parts['extension']}" : $parts["filename"];
return $result;
}
+
+ /**
+ * Sanitize a filename for a given type (given as "photo" or "movie") and a target file format
+ * (given as an extension). This returns a completely legal and valid filename,
+ * or throws an exception if the type or extension given is invalid or illegal. It tries to
+ * maintain the filename's original extension even if it's not identical to the given extension
+ * (e.g. don't change "JPG" or "jpeg" to "jpg").
+ *
+ * Note: it is not okay if the extension given is legal but does not match the type (e.g. if
+ * extension is "mp4" and type is "photo", it will throw an exception)
+ *
+ * @param string $filename (with no directory)
+ * @param string $extension (can be uppercase or lowercase)
+ * @param string $type (as "photo" or "movie")
+ * @return string sanitized filename (or null if bad extension argument)
+ */
+ static function sanitize_filename($filename, $extension, $type) {
+ // Check if the type is valid - if so, get the mime types of the
+ // original and target extensions; if not, throw an exception.
+ $original_extension = pathinfo($filename, PATHINFO_EXTENSION);
+ switch ($type) {
+ case "photo":
+ $mime_type = legal_file::get_photo_types_by_extension($extension);
+ $original_mime_type = legal_file::get_photo_types_by_extension($original_extension);
+ break;
+ case "movie":
+ $mime_type = legal_file::get_movie_types_by_extension($extension);
+ $original_mime_type = legal_file::get_movie_types_by_extension($original_extension);
+ break;
+ default:
+ throw new Exception("@todo INVALID_TYPE");
+ }
+
+ // Check if the target extension is blank or invalid - if so, throw an exception.
+ if (!$extension || !$mime_type) {
+ throw new Exception("@todo ILLEGAL_EXTENSION");
+ }
+
+ // Check if the mime types of the original and target extensions match - if not, fix it.
+ if (!$original_extension || ($mime_type != $original_mime_type)) {
+ $filename = legal_file::change_extension($filename, $extension);
+ }
+
+ // It should be a filename without a directory - remove all slashes (and backslashes).
+ $filename = str_replace("/", "_", $filename);
+ $filename = str_replace("\\", "_", $filename);
+
+ // Remove extra dots from the filename. This will also remove extraneous 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.
+ if (empty($filename) || (substr($filename, 0, 1) == ".")) {
+ $filename = $type . $filename; // e.g. "photo.jpg" or "movie.mp4"
+ }
+
+ return $filename;
+ }
}
diff --git a/modules/gallery/helpers/movie.php b/modules/gallery/helpers/movie.php
index 6844771b..aff2acc1 100644
--- a/modules/gallery/helpers/movie.php
+++ b/modules/gallery/helpers/movie.php
@@ -24,6 +24,8 @@
* Note: by design, this class does not do any permission checking.
*/
class movie_Core {
+ private static $allow_uploads;
+
static function get_edit_form($movie) {
$form = new Forge("movies/update/$movie->id", "", "post", array("id" => "g-edit-movie-form"));
$form->hidden("from_id")->value($movie->id);
@@ -110,6 +112,29 @@ class movie_Core {
}
/**
+ * Return true if movie uploads are allowed, false if not. This is based on the
+ * "movie_allow_uploads" Gallery variable as well as whether or not ffmpeg is found.
+ */
+ static function allow_uploads() {
+ if (empty(self::$allow_uploads)) {
+ // Refresh ffmpeg settings
+ $ffmpeg = movie::find_ffmpeg();
+ switch (module::get_var("gallery", "movie_allow_uploads", "autodetect")) {
+ case "always":
+ self::$allow_uploads = true;
+ break;
+ case "never":
+ self::$allow_uploads = false;
+ break;
+ default:
+ self::$allow_uploads = !empty($ffmpeg);
+ break;
+ }
+ }
+ return self::$allow_uploads;
+ }
+
+ /**
* Return the path to the ffmpeg binary if one exists and is executable, or null.
*/
static function find_ffmpeg() {
@@ -122,6 +147,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.
@@ -138,9 +191,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).
*/
@@ -192,8 +243,16 @@ class movie_Core {
$metadata->extension = strtolower($extension);
}
- // Run movie_get_file_metadata events which can modify the class, then return results.
+ // Run movie_get_file_metadata events which can modify the class.
module::event("movie_get_file_metadata", $file_path, $metadata);
+
+ // If the post-events results are invalid, throw an exception. Note that, unlike photos, having
+ // zero width and height isn't considered invalid (as is the case when FFmpeg isn't installed).
+ if (!$metadata->mime_type || !$metadata->extension ||
+ ($metadata->mime_type != legal_file::get_movie_types_by_extension($metadata->extension))) {
+ throw new Exception("@todo ILLEGAL_OR_UNINDENTIFIABLE_FILE");
+ }
+
return array($metadata->width, $metadata->height, $metadata->mime_type,
$metadata->extension, $metadata->duration);
}
diff --git a/modules/gallery/helpers/photo.php b/modules/gallery/helpers/photo.php
index 51e51507..004cc7c4 100644
--- a/modules/gallery/helpers/photo.php
+++ b/modules/gallery/helpers/photo.php
@@ -94,10 +94,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).
*/
@@ -133,8 +131,15 @@ class photo_Core {
$metadata->height = 0;
}
- // Run photo_get_file_metadata events which can modify the class, then return results.
+ // Run photo_get_file_metadata events which can modify the class.
module::event("photo_get_file_metadata", $file_path, $metadata);
+
+ // If the post-events results are invalid, throw an exception.
+ if (!$metadata->width || !$metadata->height || !$metadata->mime_type || !$metadata->extension ||
+ ($metadata->mime_type != legal_file::get_photo_types_by_extension($metadata->extension))) {
+ throw new Exception("@todo ILLEGAL_OR_UNINDENTIFIABLE_FILE");
+ }
+
return array($metadata->width, $metadata->height, $metadata->mime_type, $metadata->extension);
}
}
diff --git a/modules/gallery/helpers/system.php b/modules/gallery/helpers/system.php
index fa834824..e1398103 100644
--- a/modules/gallery/helpers/system.php
+++ b/modules/gallery/helpers/system.php
@@ -20,22 +20,42 @@
class system_Core {
/**
* Return the path to an executable version of the named binary, or null.
- * Traverse the PATH environment variable looking for the given file. If
- * the $priority_path variable is set, check that path first.
+ * The paths are traversed in the following order:
+ * 1. $priority_path (if specified)
+ * 2. Gallery's own bin directory (DOCROOT . "bin")
+ * 3. PATH environment variable
+ * 4. extra_binary_paths Gallery variable (if specified)
+ * In addition, if the file is found inside Gallery's bin directory but
+ * it's not executable, we try to change its permissions to 0755.
+ *
+ * @param string $binary
+ * @param string $priority_path (optional)
+ * @return string path to binary if found; null if not found
*/
static function find_binary($binary, $priority_path=null) {
- $paths = array_merge(
- explode(":", getenv("PATH")),
- explode(":", module::get_var("gallery", "extra_binary_paths")));
+ $bin_path = DOCROOT . "bin";
+
if ($priority_path) {
- array_unshift($paths, $priority_path);
+ $paths = array($priority_path, $bin_path);
+ } else {
+ $paths = array($bin_path);
}
+ $paths = array_merge($paths,
+ explode(":", getenv("PATH")),
+ explode(":", module::get_var("gallery", "extra_binary_paths")));
foreach ($paths as $path) {
$candidate = "$path/$binary";
// @suppress errors below to avoid open_basedir issues
- if (@file_exists($candidate) && @is_executable($candidate)) {
- return $candidate;
+ if (@file_exists($candidate)) {
+ if (!@is_executable($candidate) &&
+ (substr_compare($bin_path, $candidate, 0, strlen($bin_path)) == 0)) {
+ // Binary isn't executable but is in Gallery's bin directory - try fixing permissions.
+ @chmod($candidate, 0755);
+ }
+ if (@is_executable($candidate)) {
+ return $candidate;
+ }
}
}
return null;
diff --git a/modules/gallery/images/ffmpeg.png b/modules/gallery/images/ffmpeg.png
new file mode 100644
index 00000000..6be8b62a
--- /dev/null
+++ b/modules/gallery/images/ffmpeg.png
Binary files differ
diff --git a/modules/gallery/libraries/Form_Uploadify.php b/modules/gallery/libraries/Form_Uploadify.php
index 56793c69..1e58018d 100644
--- a/modules/gallery/libraries/Form_Uploadify.php
+++ b/modules/gallery/libraries/Form_Uploadify.php
@@ -46,7 +46,7 @@ class Form_Uploadify_Core extends Form_Input {
$v->album = $this->data["album"];
$v->script_data = $this->data["script_data"];
$v->simultaneous_upload_limit = module::get_var("gallery", "simultaneous_upload_limit");
- $v->movies_allowed = (bool) movie::find_ffmpeg();
+ $v->movies_allowed = movie::allow_uploads();
$v->extensions = legal_file::get_filters();
$v->suhosin_session_encrypt = (bool) ini_get("suhosin.session.encrypt");
diff --git a/modules/gallery/libraries/Theme_View.php b/modules/gallery/libraries/Theme_View.php
index cf384109..986fc8a2 100644
--- a/modules/gallery/libraries/Theme_View.php
+++ b/modules/gallery/libraries/Theme_View.php
@@ -86,8 +86,10 @@ class Theme_View_Core extends Gallery_View {
return $this->item;
}
- public function siblings() {
- return call_user_func_array($this->siblings_callback[0], $this->siblings_callback[1]);
+ public function siblings($limit=null, $offset=null) {
+ return call_user_func_array(
+ $this->siblings_callback[0],
+ array_merge($this->siblings_callback[1], array($offset, $limit)));
}
public function tag() {
diff --git a/modules/gallery/models/item.php b/modules/gallery/models/item.php
index f80fc53a..43b9a292 100644
--- a/modules/gallery/models/item.php
+++ b/modules/gallery/models/item.php
@@ -21,6 +21,7 @@ class Item_Model_Core extends ORM_MPTT {
protected $children = "items";
protected $sorting = array();
public $data_file = null;
+ private $data_file_error = null;
public function __construct($id=null) {
parent::__construct($id);
@@ -129,10 +130,11 @@ class Item_Model_Core extends ORM_MPTT {
/**
* Return the server-relative url to this item, eg:
- * /gallery3/index.php/BobsWedding?page=2
- * /gallery3/index.php/BobsWedding/Eating-Cake.jpg
+ * album: /gallery3/index.php/Bobs%20Wedding?page=2
+ * photo: /gallery3/index.php/Bobs%20Wedding/Eating-Cake
+ * movie: /gallery3/index.php/Bobs%20Wedding/First-Dance
*
- * @param string $query the query string (eg "show=3")
+ * @param string $query the query string (eg "page=2")
*/
public function url($query=null) {
$url = url::site($this->relative_url());
@@ -144,10 +146,11 @@ class Item_Model_Core extends ORM_MPTT {
/**
* Return the full url to this item, eg:
- * http://example.com/gallery3/index.php/BobsWedding?page=2
- * http://example.com/gallery3/index.php/BobsWedding/Eating-Cake.jpg
+ * album: http://example.com/gallery3/index.php/Bobs%20Wedding?page=2
+ * photo: http://example.com/gallery3/index.php/Bobs%20Wedding/Eating-Cake
+ * movie: http://example.com/gallery3/index.php/Bobs%20Wedding/First-Dance
*
- * @param string $query the query string (eg "show=3")
+ * @param string $query the query string (eg "page=2")
*/
public function abs_url($query=null) {
$url = url::abs_site($this->relative_url());
@@ -158,16 +161,24 @@ class Item_Model_Core extends ORM_MPTT {
}
/**
- * album: /var/albums/album1/album2
- * photo: /var/albums/album1/album2/photo.jpg
+ * Return the full path to this item's file, eg:
+ * album: /usr/home/www/gallery3/var/albums/Bobs Wedding
+ * photo: /usr/home/www/gallery3/var/albums/Bobs Wedding/Eating-Cake.jpg
+ * movie: /usr/home/www/gallery3/var/albums/Bobs Wedding/First-Dance.mp4
*/
public function file_path() {
return VARPATH . "albums/" . urldecode($this->relative_path());
}
/**
- * album: http://example.com/gallery3/var/resizes/album1/
- * photo: http://example.com/gallery3/var/albums/album1/photo.jpg
+ * Return the relative url to this item's file, with cache buster, eg:
+ * album: var/albums/Bobs%20Wedding?m=1234567890
+ * photo: var/albums/Bobs%20Wedding/Eating-Cake.jpg?m=1234567890
+ * movie: var/albums/Bobs%20Wedding/First-Dance.mp4?m=1234567890
+ * If $full_uri==true, return the full url to this item's file, with cache buster, eg:
+ * album: http://example.com/gallery3/var/albums/Bobs%20Wedding?m=1234567890
+ * photo: http://example.com/gallery3/var/albums/Bobs%20Wedding/Eating-Cake.jpg?m=1234567890
+ * movie: http://example.com/gallery3/var/albums/Bobs%20Wedding/First-Dance.mp4?m=1234567890
*/
public function file_url($full_uri=false) {
$relative_path = "var/albums/" . $this->relative_path();
@@ -177,8 +188,10 @@ class Item_Model_Core extends ORM_MPTT {
}
/**
- * album: /var/resizes/album1/.thumb.jpg
- * photo: /var/albums/album1/photo.thumb.jpg
+ * Return the full path to this item's thumb, eg:
+ * album: /usr/home/www/gallery3/var/thumbs/Bobs Wedding/.album.jpg
+ * photo: /usr/home/www/gallery3/var/thumbs/Bobs Wedding/Eating-Cake.jpg
+ * movie: /usr/home/www/gallery3/var/thumbs/Bobs Wedding/First-Dance.jpg
*/
public function thumb_path() {
$base = VARPATH . "thumbs/" . urldecode($this->relative_path());
@@ -200,8 +213,14 @@ class Item_Model_Core extends ORM_MPTT {
}
/**
- * album: http://example.com/gallery3/var/resizes/album1/.thumb.jpg
- * photo: http://example.com/gallery3/var/albums/album1/photo.thumb.jpg
+ * Return the relative url to this item's thumb, with cache buster, eg:
+ * album: var/thumbs/Bobs%20Wedding/.album.jpg?m=1234567890
+ * photo: var/thumbs/Bobs%20Wedding/Eating-Cake.jpg?m=1234567890
+ * movie: var/thumbs/Bobs%20Wedding/First-Dance.mp4?m=1234567890
+ * If $full_uri==true, return the full url to this item's file, with cache buster, eg:
+ * album: http://example.com/gallery3/var/thumbs/Bobs%20Wedding/.album.jpg?m=1234567890
+ * photo: http://example.com/gallery3/var/thumbs/Bobs%20Wedding/Eating-Cake.jpg?m=1234567890
+ * movie: http://example.com/gallery3/var/thumbs/Bobs%20Wedding/First-Dance.mp4?m=1234567890
*/
public function thumb_url($full_uri=false) {
$cache_buster = $this->_cache_buster($this->thumb_path());
@@ -219,8 +238,11 @@ class Item_Model_Core extends ORM_MPTT {
}
/**
- * album: /var/resizes/album1/.resize.jpg
- * photo: /var/albums/album1/photo.resize.jpg
+ * Return the full path to this item's resize, eg:
+ * album: /usr/home/www/gallery3/var/resizes/Bobs Wedding/.album.jpg (*)
+ * photo: /usr/home/www/gallery3/var/resizes/Bobs Wedding/Eating-Cake.jpg
+ * movie: /usr/home/www/gallery3/var/resizes/Bobs Wedding/First-Dance.mp4 (*)
+ * (*) Since only photos have resizes, album and movie paths are fictitious.
*/
public function resize_path() {
return VARPATH . "resizes/" . urldecode($this->relative_path()) .
@@ -228,8 +250,15 @@ class Item_Model_Core extends ORM_MPTT {
}
/**
- * album: http://example.com/gallery3/var/resizes/album1/.resize.jpg
- * photo: http://example.com/gallery3/var/albums/album1/photo.resize.jpg
+ * Return the relative url to this item's resize, with cache buster, eg:
+ * album: var/resizes/Bobs%20Wedding/.album.jpg?m=1234567890 (*)
+ * photo: var/resizes/Bobs%20Wedding/Eating-Cake.jpg?m=1234567890
+ * movie: var/resizes/Bobs%20Wedding/First-Dance.mp4?m=1234567890 (*)
+ * If $full_uri==true, return the full url to this item's file, with cache buster, eg:
+ * album: http://example.com/gallery3/var/resizes/Bobs%20Wedding/.album.jpg?m=1234567890 (*)
+ * photo: http://example.com/gallery3/var/resizes/Bobs%20Wedding/Eating-Cake.jpg?m=1234567890
+ * movie: http://example.com/gallery3/var/resizes/Bobs%20Wedding/First-Dance.mp4?m=1234567890 (*)
+ * (*) Since only photos have resizes, album and movie urls are fictitious.
*/
public function resize_url($full_uri=false) {
$relative_path = "var/resizes/" . $this->relative_path();
@@ -336,6 +365,14 @@ class Item_Model_Core extends ORM_MPTT {
$this->weight = item::get_max_weight();
}
+ // Process the data file info.
+ if (isset($this->data_file)) {
+ $this->_process_data_file_info();
+ } else if (!$this->is_album()) {
+ // Unless it's an album, new items must have a data file.
+ $this->data_file_error = true;
+ }
+
// Make an url friendly slug from the name, if necessary
if (empty($this->slug)) {
$this->slug = item::convert_filename_to_slug(pathinfo($this->name, PATHINFO_FILENAME));
@@ -348,23 +385,6 @@ class Item_Model_Core extends ORM_MPTT {
}
}
- // Get the width, height and mime type from our data file for photos and movies.
- if ($this->is_photo() || $this->is_movie()) {
- if ($this->is_photo()) {
- list ($this->width, $this->height, $this->mime_type, $extension) =
- photo::get_file_metadata($this->data_file);
- } else if ($this->is_movie()) {
- list ($this->width, $this->height, $this->mime_type, $extension) =
- movie::get_file_metadata($this->data_file);
- }
-
- // Force an extension onto the name if necessary
- $pi = pathinfo($this->data_file);
- if (empty($pi["extension"])) {
- $this->name = "{$this->name}.$extension";
- }
- }
-
$this->_check_and_fix_conflicts();
parent::save();
@@ -402,24 +422,19 @@ class Item_Model_Core extends ORM_MPTT {
// keep it around.
$original = ORM::factory("item", $this->id);
- // Preserve the extension of the data file. Many helpers, (e.g. ImageMagick), assume
+ // If we have a new data file, process its info. This will get its metadata and
+ // preserve the extension of the data file. Many helpers, (e.g. ImageMagick), assume
// the MIME type from the extension. So when we adopt the new data file, it's important
// to adopt the new extension. That ensures that the item's extension is always
// appropriate for its data. We don't try to preserve the name of the data file, though,
// because the name is typically a temporary randomly-generated name.
if (isset($this->data_file)) {
- $extension = pathinfo($this->data_file, PATHINFO_EXTENSION);
- $new_name = pathinfo($this->name, PATHINFO_FILENAME) . ".$extension";
- if (!empty($extension) && strcmp($this->name, $new_name)) {
- $this->name = $new_name;
- }
- if ($this->is_photo()) {
- list ($this->width, $this->height, $this->mime_type, $extension) =
- photo::get_file_metadata($this->data_file);
- } else if ($this->is_movie()) {
- list ($this->width, $this->height, $this->mime_type, $extension) =
- movie::get_file_metadata($this->data_file);
- }
+ $this->_process_data_file_info();
+ } else if (!$this->is_album() && array_key_exists("name", $this->changed)) {
+ // There's no new data file, but the name changed. If it's a photo or movie,
+ // make sure the new name still agrees with the file type.
+ $this->name = legal_file::sanitize_filename($this->name,
+ pathinfo($original->name, PATHINFO_EXTENSION), $this->type);
}
// If an album's cover has changed (or been removed), delete any existing album cover,
@@ -496,13 +511,6 @@ class Item_Model_Core extends ORM_MPTT {
// Replace the data file, if requested.
if ($this->data_file && ($this->is_photo() || $this->is_movie())) {
copy($this->data_file, $this->file_path());
-
- // Get the width, height and mime type from our data file for photos and movies.
- if ($this->is_photo()) {
- list ($this->width, $this->height) = photo::get_file_metadata($this->file_path());
- } else if ($this->is_movie()) {
- list ($this->width, $this->height) = movie::get_file_metadata($this->file_path());
- }
$this->thumb_dirty = 1;
$this->resize_dirty = 1;
}
@@ -588,6 +596,40 @@ class Item_Model_Core extends ORM_MPTT {
}
/**
+ * Process the data file info. Get its metadata and extension.
+ * If valid, use it to sanitize the item name and update the
+ * width, height, and mime type.
+ */
+ private function _process_data_file_info() {
+ try {
+ if ($this->is_photo()) {
+ list ($this->width, $this->height, $this->mime_type, $extension) =
+ photo::get_file_metadata($this->data_file);
+ } else if ($this->is_movie()) {
+ list ($this->width, $this->height, $this->mime_type, $extension) =
+ movie::get_file_metadata($this->data_file);
+ } else {
+ // Albums don't have data files.
+ $this->data_file = null;
+ return;
+ }
+
+ // Sanitize the name based on the idenified extension, but only set $this->name if different
+ // to ensure it isn't unnecessarily marked as "changed"
+ $name = legal_file::sanitize_filename($this->name, $extension, $this->type);
+ if ($this->name != $name) {
+ $this->name = $name;
+ }
+
+ // Data file valid - make sure the flag is reset to false.
+ $this->data_file_error = false;
+ } catch (Exception $e) {
+ // Data file invalid - set the flag so it's reported during item validation.
+ $this->data_file_error = true;
+ }
+ }
+
+ /**
* Return the Item_Model representing the cover for this album.
* @return Item_Model or null if there's no cover
*/
@@ -938,6 +980,8 @@ class Item_Model_Core extends ORM_MPTT {
$v->add_error("name", "bad_data_file_path");
} else if (filesize($this->data_file) == 0) {
$v->add_error("name", "empty_data_file");
+ } else if ($this->data_file_error) {
+ $v->add_error("name", "invalid_data_file");
}
}
diff --git a/modules/gallery/module.info b/modules/gallery/module.info
index d79a5077..2383ec3c 100644
--- a/modules/gallery/module.info
+++ b/modules/gallery/module.info
@@ -1,6 +1,6 @@
name = "Gallery 3"
description = "Gallery core application"
-version = 55
+version = 56
author_name = "Gallery Team"
author_url = "http://codex.galleryproject.org/Gallery:Team"
info_url = "http://codex.galleryproject.org/Gallery3:Modules:gallery"
diff --git a/modules/gallery/tests/Item_Model_Test.php b/modules/gallery/tests/Item_Model_Test.php
index 41361b32..fcb5c2ad 100644
--- a/modules/gallery/tests/Item_Model_Test.php
+++ b/modules/gallery/tests/Item_Model_Test.php
@@ -126,14 +126,9 @@ class Item_Model_Test extends Gallery_Unit_Test_Case {
public function item_rename_wont_accept_slash_test() {
$item = test::random_photo();
- try {
- $item->name = test::random_name() . "/";
- $item->save();
- } catch (ORM_Validation_Exception $e) {
- $this->assert_equal(array("name" => "no_slashes"), $e->validation->errors());
- return;
- }
- $this->assert_true(false, "Shouldn't get here");
+ $item->name = "/no_slashes/allowed/";
+ $item->save();
+ $this->assert_equal("no_slashes_allowed.jpg", $item->name);
}
public function move_album_test() {
@@ -328,30 +323,17 @@ class Item_Model_Test extends Gallery_Unit_Test_Case {
}
public function photo_files_must_have_an_extension_test() {
- try {
- $photo = test::random_photo_unsaved();
- $photo->mime_type = "image/jpeg";
- $photo->name = "no_extension";
- $photo->save();
- } catch (ORM_Validation_Exception $e) {
- $this->assert_same(array("name" => "illegal_data_file_extension"), $e->validation->errors());
- return; // pass
- }
- $this->assert_true(false, "Shouldn't get here");
+ $photo = test::random_photo_unsaved();
+ $photo->name = "no_extension_photo";
+ $photo->save();
+ $this->assert_equal("no_extension_photo.jpg", $photo->name);
}
public function movie_files_must_have_an_extension_test() {
- try {
- $movie = test::random_movie_unsaved();
- $movie->type = "movie";
- $movie->mime_type = "video/x-flv";
- $movie->name = "no_extension";
- $movie->save();
- } catch (ORM_Validation_Exception $e) {
- $this->assert_same(array("name" => "illegal_data_file_extension"), $e->validation->errors());
- return; // pass
- }
- $this->assert_true(false, "Shouldn't get here");
+ $movie = test::random_movie_unsaved();
+ $movie->name = "no_extension_movie";
+ $movie->save();
+ $this->assert_equal("no_extension_movie.flv", $movie->name);
}
public function cant_delete_root_album_test() {
@@ -445,8 +427,21 @@ class Item_Model_Test extends Gallery_Unit_Test_Case {
$photo->set_data_file(MODPATH . "gallery/tests/Item_Model_Test.php");
$photo->save();
} catch (ORM_Validation_Exception $e) {
- $this->assert_same(array("mime_type" => "invalid", "name" => "illegal_data_file_extension"),
- $e->validation->errors());
+ $this->assert_same(array("name" => "invalid_data_file"), $e->validation->errors());
+ return; // pass
+ }
+ $this->assert_true(false, "Shouldn't get here");
+ }
+
+ public function unsafe_data_file_replacement_with_valid_extension_test() {
+ $temp_file = TMPPATH . "masquerading_php.jpg";
+ copy(MODPATH . "gallery/tests/Item_Model_Test.php", $temp_file);
+ try {
+ $photo = test::random_photo();
+ $photo->set_data_file($temp_file);
+ $photo->save();
+ } catch (ORM_Validation_Exception $e) {
+ $this->assert_same(array("name" => "invalid_data_file"), $e->validation->errors());
return; // pass
}
$this->assert_true(false, "Shouldn't get here");
@@ -464,55 +459,72 @@ class Item_Model_Test extends Gallery_Unit_Test_Case {
preg_match("|http://./var/albums/name_\w+\.jpg\?m=\d+|", $photo->file_url()),
$photo->file_url() . " is malformed");
- // Albums have special thumbnails. Empty album has cachebuster of 0 since it has no thumbnail
$album = test::random_album();
$this->assert_true(
- preg_match("|http://./var/thumbs/name_\w+/\.album\.jpg\?m=0|", $album->thumb_url()),
+ preg_match("|http://./var/thumbs/name_\w+/\.album\.jpg\?m=\d+|", $album->thumb_url()),
$album->thumb_url() . " is malformed");
$photo = test::random_photo($album);
$this->assert_true(
preg_match("|http://./var/thumbs/name_\w+/\.album\.jpg\?m=\d+|", $album->thumb_url()),
$album->thumb_url() . " is malformed");
+
+ // If the file does not exist, we should return a cache buster of m=0.
+ unlink($album->thumb_path());
+ $this->assert_true(
+ preg_match("|http://./var/thumbs/name_\w+/\.album\.jpg\?m=0|", $album->thumb_url()),
+ $album->thumb_url() . " is malformed");
}
- public function legal_extension_test() {
- foreach (array("test.gif", "test.GIF", "test.Gif", "test.jpeg", "test.JPG") as $name) {
+ public function legal_extension_that_does_match_gets_used_test() {
+ foreach (array("jpg", "JPG", "Jpg", "jpeg") as $extension) {
$photo = test::random_photo_unsaved(item::root());
- $photo->name = $name;
+ $photo->name = test::random_name() . ".{$extension}";
$photo->save();
+ // Should get renamed with the correct jpg extension of the data file.
+ $this->assert_equal($extension, pathinfo($photo->name, PATHINFO_EXTENSION));
}
}
public function illegal_extension_test() {
foreach (array("test.php", "test.PHP", "test.php5", "test.php4",
"test.pl", "test.php.png") as $name) {
- try {
- $photo = test::random_photo_unsaved(item::root());
- $photo->name = $name;
- $photo->save();
- } catch (ORM_Validation_Exception $e) {
- $this->assert_equal(array("name" => "illegal_data_file_extension"),
- $e->validation->errors());
- continue;
- }
- $this->assert_true(false, "Shouldn't get here");
+ $photo = test::random_photo_unsaved(item::root());
+ $photo->name = $name;
+ $photo->save();
+ // Should get renamed with the correct jpg extension of the data file.
+ $this->assert_equal("jpg", pathinfo($photo->name, PATHINFO_EXTENSION));
}
}
public function cant_rename_to_illegal_extension_test() {
foreach (array("test.php.test", "test.php", "test.PHP",
"test.php5", "test.php4", "test.pl") as $name) {
- try {
- $photo = test::random_photo(item::root());
- $photo->name = $name;
- $photo->save();
- } catch (ORM_Validation_Exception $e) {
- $this->assert_equal(array("name" => "illegal_data_file_extension"),
- $e->validation->errors());
- continue;
- }
- $this->assert_true(false, "Shouldn't get here");
+ $photo = test::random_photo(item::root());
+ $photo->name = $name;
+ $photo->save();
+ // Should get renamed with the correct jpg extension of the data file.
+ $this->assert_equal("jpg", pathinfo($photo->name, PATHINFO_EXTENSION));
+ }
+ }
+
+ public function legal_extension_that_doesnt_match_gets_fixed_test() {
+ foreach (array("test.png", "test.mp4", "test.GIF") as $name) {
+ $photo = test::random_photo_unsaved(item::root());
+ $photo->name = $name;
+ $photo->save();
+ // Should get renamed with the correct jpg extension of the data file.
+ $this->assert_equal("jpg", pathinfo($photo->name, PATHINFO_EXTENSION));
+ }
+ }
+
+ public function rename_to_legal_extension_that_doesnt_match_gets_fixed_test() {
+ foreach (array("test.png", "test.mp4", "test.GIF") as $name) {
+ $photo = test::random_photo(item::root());
+ $photo->name = $name;
+ $photo->save();
+ // Should get renamed with the correct jpg extension of the data file.
+ $this->assert_equal("jpg", pathinfo($photo->name, PATHINFO_EXTENSION));
}
}
diff --git a/modules/gallery/tests/Legal_File_Helper_Test.php b/modules/gallery/tests/Legal_File_Helper_Test.php
index 84a29a52..7ed5214b 100644
--- a/modules/gallery/tests/Legal_File_Helper_Test.php
+++ b/modules/gallery/tests/Legal_File_Helper_Test.php
@@ -136,10 +136,62 @@ class Legal_File_Helper_Test extends Gallery_Unit_Test_Case {
public function smash_extensions_test() {
$this->assert_equal("foo_bar.jpg", legal_file::smash_extensions("foo.bar.jpg"));
$this->assert_equal("foo_bar_baz.jpg", legal_file::smash_extensions("foo.bar.baz.jpg"));
- $this->assert_equal("foo_bar_baz.jpg", legal_file::smash_extensions("foo.bar.baz.jpg"));
$this->assert_equal("foo_bar_baz.jpg", legal_file::smash_extensions("...foo...bar..baz...jpg"));
$this->assert_equal("/path/to/foo_bar.jpg", legal_file::smash_extensions("/path/to/foo.bar.jpg"));
$this->assert_equal("/path/to.to/foo_bar.jpg", legal_file::smash_extensions("/path/to.to/foo.bar.jpg"));
$this->assert_equal("foo_bar-12345678.jpg", legal_file::smash_extensions("foo.bar-12345678.jpg"));
}
+
+ public function smash_extensions_pass_thru_names_without_extensions_test() {
+ $this->assert_equal("foo", legal_file::smash_extensions("foo"));
+ $this->assert_equal("foo.", legal_file::smash_extensions("foo."));
+ $this->assert_equal(".foo", legal_file::smash_extensions(".foo"));
+ $this->assert_equal(".", legal_file::smash_extensions("."));
+ $this->assert_equal("", legal_file::smash_extensions(""));
+ $this->assert_equal(null, legal_file::smash_extensions(null));
+ }
+
+ public function sanitize_filename_with_no_rename_test() {
+ $this->assert_equal("foo.jpeg", legal_file::sanitize_filename("foo.jpeg", "jpg", "photo"));
+ $this->assert_equal("foo.jpg", legal_file::sanitize_filename("foo.jpg", "jpeg", "photo"));
+ $this->assert_equal("foo.MP4", legal_file::sanitize_filename("foo.MP4", "mp4", "movie"));
+ $this->assert_equal("foo.mp4", legal_file::sanitize_filename("foo.mp4", "MP4", "movie"));
+ }
+
+ public function sanitize_filename_with_corrected_extension_test() {
+ $this->assert_equal("foo.jpg", legal_file::sanitize_filename("foo.png", "jpg", "photo"));
+ $this->assert_equal("foo.MP4", legal_file::sanitize_filename("foo.jpg", "MP4", "movie"));
+ $this->assert_equal("foo.jpg", legal_file::sanitize_filename("foo.php", "jpg", "photo"));
+ }
+
+ public function sanitize_filename_with_non_standard_chars_and_dots_test() {
+ $this->assert_equal("foo.jpg", legal_file::sanitize_filename("foo", "jpg", "photo"));
+ $this->assert_equal("foo.mp4", legal_file::sanitize_filename("foo.", "mp4", "movie"));
+ $this->assert_equal("foo.jpeg", legal_file::sanitize_filename(".foo.jpeg", "jpg", "photo"));
+ $this->assert_equal("foo_2013_02_10.jpeg",
+ legal_file::sanitize_filename("foo.2013/02/10.jpeg", "jpg", "photo"));
+ $this->assert_equal("foo_bar_baz.jpg",
+ legal_file::sanitize_filename("...foo...bar..baz...png", "jpg", "photo"));
+ $this->assert_equal("j'écris@un#nom_bizarre(mais quand_même_ça_passe.jpg",
+ legal_file::sanitize_filename("/j'écris@un#nom/bizarre(mais quand.même/ça_passe.\$ÇÀ@€#_", "jpg", "photo"));
+ }
+
+ public function sanitize_filename_with_no_base_name_test() {
+ $this->assert_equal("photo.jpg", legal_file::sanitize_filename(".png", "jpg", "photo"));
+ $this->assert_equal("movie.mp4", legal_file::sanitize_filename("__..__", "mp4", "movie"));
+ $this->assert_equal("photo.jpg", legal_file::sanitize_filename(".", "jpg", "photo"));
+ $this->assert_equal("movie.mp4", legal_file::sanitize_filename(null, "mp4", "movie"));
+ }
+
+ public function sanitize_filename_with_invalid_arguments_test() {
+ foreach (array("flv" => "photo", "jpg" => "movie", "php" => "photo",
+ null => "movie", "jpg" => "album", "jpg" => null) as $extension => $type) {
+ try {
+ legal_file::sanitize_filename("foo.jpg", $extension, $type);
+ $this->assert_true(false, "Shouldn't get here");
+ } catch (Exception $e) {
+ // pass
+ }
+ }
+ }
} \ No newline at end of file
diff --git a/modules/gallery/tests/Movie_Helper_Test.php b/modules/gallery/tests/Movie_Helper_Test.php
index 0c262620..03fa2da9 100644
--- a/modules/gallery/tests/Movie_Helper_Test.php
+++ b/modules/gallery/tests/Movie_Helper_Test.php
@@ -64,18 +64,42 @@ class Movie_Helper_Test extends Gallery_Unit_Test_Case {
public function get_file_metadata_with_no_extension_test() {
copy(MODPATH . "gallery/tests/test.flv", TMPPATH . "test_flv_with_no_extension");
- $this->assert_equal(array(360, 288, null, null, 6.00),
- movie::get_file_metadata(TMPPATH . "test_flv_with_no_extension"));
+ // Since mime type and extension are based solely on the filename, this is considered invalid.
+ try {
+ $metadata = movie::get_file_metadata(TMPPATH . "test_flv_with_no_extension");
+ $this->assert_true(false, "Shouldn't get here");
+ } catch (Exception $e) {
+ // pass
+ }
}
public function get_file_metadata_with_illegal_extension_test() {
- $this->assert_equal(array(0, 0, null, null, 0),
- movie::get_file_metadata(MODPATH . "gallery/tests/Movie_Helper_Test.php"));
+ try {
+ $metadata = movie::get_file_metadata(MODPATH . "gallery/tests/Movie_Helper_Test.php");
+ $this->assert_true(false, "Shouldn't get here");
+ } catch (Exception $e) {
+ // pass
+ }
}
public function get_file_metadata_with_illegal_extension_but_valid_file_contents_test() {
copy(MODPATH . "gallery/tests/test.flv", TMPPATH . "test_flv_with_php_extension.php");
- $this->assert_equal(array(360, 288, null, null, 6.00),
- movie::get_file_metadata(TMPPATH . "test_flv_with_php_extension.php"));
+ // Since mime type and extension are based solely on the filename, this is considered invalid.
+ try {
+ $metadata = movie::get_file_metadata(TMPPATH . "test_flv_with_php_extension.php");
+ $this->assert_true(false, "Shouldn't get here");
+ } catch (Exception $e) {
+ // pass
+ }
+ }
+
+ public function get_file_metadata_with_valid_extension_but_illegal_file_contents_test() {
+ copy(MODPATH . "gallery/tests/Photo_Helper_Test.php", TMPPATH . "test_php_with_flv_extension.flv");
+ // Since mime type and extension are based solely on the filename, this is considered valid.
+ // Of course, FFmpeg cannot extract width, height, or duration from the file. Note that this
+ // isn't a really a security problem, since the filename doesn't have a php extension and
+ // therefore will never be executed.
+ $this->assert_equal(array(0, 0, "video/x-flv", "flv", 0),
+ movie::get_file_metadata(TMPPATH . "test_php_with_flv_extension.flv"));
}
}
diff --git a/modules/gallery/tests/Photo_Helper_Test.php b/modules/gallery/tests/Photo_Helper_Test.php
index 5207a6db..79b5ccfd 100644
--- a/modules/gallery/tests/Photo_Helper_Test.php
+++ b/modules/gallery/tests/Photo_Helper_Test.php
@@ -40,8 +40,12 @@ class Photo_Helper_Test extends Gallery_Unit_Test_Case {
}
public function get_file_metadata_with_illegal_extension_test() {
- $this->assert_equal(array(0, 0, null, null),
- photo::get_file_metadata(MODPATH . "gallery/tests/Photo_Helper_Test.php"));
+ try {
+ $metadata = photo::get_file_metadata(MODPATH . "gallery/tests/Photo_Helper_Test.php");
+ $this->assert_true(false, "Shouldn't get here");
+ } catch (Exception $e) {
+ // pass
+ }
}
public function get_file_metadata_with_illegal_extension_but_valid_file_contents_test() {
@@ -53,4 +57,14 @@ class Photo_Helper_Test extends Gallery_Unit_Test_Case {
$this->assert_equal(array(1024, 768, "image/jpeg", "jpg"),
photo::get_file_metadata(TMPPATH . "test_jpg_with_php_extension.php"));
}
+
+ public function get_file_metadata_with_valid_extension_but_illegal_file_contents_test() {
+ copy(MODPATH . "gallery/tests/Photo_Helper_Test.php", TMPPATH . "test_php_with_jpg_extension.jpg");
+ try {
+ $metadata = photo::get_file_metadata(TMPPATH . "test_php_with_jpg_extension.jpg");
+ $this->assert_true(false, "Shouldn't get here");
+ } catch (Exception $e) {
+ // pass
+ }
+ }
}
diff --git a/modules/gallery/tests/xss_data.txt b/modules/gallery/tests/xss_data.txt
index 51347f86..67a8b948 100644
--- a/modules/gallery/tests/xss_data.txt
+++ b/modules/gallery/tests/xss_data.txt
@@ -111,6 +111,7 @@ modules/gallery/views/admin_modules_confirm.html.php 11 DIRTY_ATTR $css
modules/gallery/views/admin_modules_confirm.html.php 11 DIRTY $message
modules/gallery/views/admin_modules_confirm.html.php 16 DIRTY access::csrf_form_field()
modules/gallery/views/admin_modules_confirm.html.php 18 DIRTY form::hidden($module,1)
+modules/gallery/views/admin_movies.html.php 43 DIRTY $form
modules/gallery/views/admin_sidebar.html.php 50 DIRTY $available
modules/gallery/views/admin_sidebar.html.php 58 DIRTY $active
modules/gallery/views/admin_sidebar_blocks.html.php 4 DIRTY_ATTR $ref
diff --git a/modules/gallery/views/admin_movies.html.php b/modules/gallery/views/admin_movies.html.php
new file mode 100644
index 00000000..e7810711
--- /dev/null
+++ b/modules/gallery/views/admin_movies.html.php
@@ -0,0 +1,44 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<div id="g-movies-admin" class="g-block ui-helper-clearfix">
+ <h1> <?= t("Movies settings") ?> </h1>
+ <p>
+ <?= t("Gallery comes with everything it needs to upload and play movies.") ?>
+ <?= t("However, it needs the FFmpeg toolkit to extract thumbnails and size information from them.") ?>
+ </p>
+ <p>
+ <?= t("Although popular, FFmpeg is not installed on all Linux systems.") ?>
+ <?= t("To use FFmpeg without fully installing it, download a pre-compiled, <b>static build</b> of FFmpeg from one of the links <a href=\"%url\">here</a>.", array("url" => "http://ffmpeg.org/download.html")) ?>
+ <?= t("Then, put the \"ffmpeg\" file in Gallery's \"bin\" directory (e.g. \"/gallery/bin\"), where Gallery will auto-detect it.") ?>
+ </p>
+ <p>
+ <?= t("Movies will work without FFmpeg, but their thumbnails will be placeholders.") ?>
+ </p>
+ <p>
+ <?= t("Can't get FFmpeg configured on your system? <a href=\"%url\">We can help!</a>",
+ array("url" => "http://codex.galleryproject.org/Gallery3:FAQ#Why_does_it_say_I.27m_missing_ffmpeg.3F")) ?>
+ </p>
+
+ <div class="g-available">
+ <h2> <?= t("Current configuration") ?> </h2>
+ <div id="g-ffmpeg" class="g-block">
+ <img class="logo" width="284" height="70" src="<?= url::file("modules/gallery/images/ffmpeg.png"); ?>" alt="<? t("Visit the FFmpeg project site") ?>" />
+ <p>
+ <?= t("FFmpeg is a cross-platform standalone audio/video program.") ?><br/>
+ <?= t("Please refer to the <a href=\"%url\">FFmpeg website</a> for more information.", array("url" => "http://ffmpeg.org")) ?>
+ </p>
+ <div class="g-module-status g-info">
+ <? if ($ffmpeg_dir): ?>
+ <? if ($ffmpeg_version): ?>
+ <p><?= t("FFmpeg version %version was found in %dir", array("version" => $ffmpeg_version, "dir" => $ffmpeg_dir)) ?></p>
+ <? else: ?>
+ <p><?= t("FFmpeg (of unknown version) was found in %dir", array("dir" => $ffmpeg_dir)) ?></p>
+ <? endif ?>
+ <? else: ?>
+ <p><?= t("We could not locate FFmpeg on your system.") ?></p>
+ <? endif ?>
+ </div>
+ </div>
+ </div>
+
+ <?= $form ?>
+</div>
diff --git a/modules/gallery/views/form_uploadify.html.php b/modules/gallery/views/form_uploadify.html.php
index 4426514a..c13e3418 100644
--- a/modules/gallery/views/form_uploadify.html.php
+++ b/modules/gallery/views/form_uploadify.html.php
@@ -131,7 +131,7 @@
<? if (identity::active_user()->admin && !$movies_allowed): ?>
<p class="g-warning">
- <?= t("Can't find <i>ffmpeg</i> on your system. Movie uploading disabled. <a href=\"%help_url\">Help!</a>", array("help_url" => "http://codex.galleryproject.org/Gallery3:FAQ#Why_does_it_say_I.27m_missing_ffmpeg.3F")) ?>
+ <?= t("Movie uploading is disabled on your system. <a href=\"%help_url\">Help!</a>", array("help_url" => url::site("admin/movies"))) ?>
</p>
<? endif ?>
</div>
diff --git a/modules/search/controllers/search.php b/modules/search/controllers/search.php
index 673a281f..753d9b69 100644
--- a/modules/search/controllers/search.php
+++ b/modules/search/controllers/search.php
@@ -110,7 +110,14 @@ class Search_Controller extends Controller {
Breadcrumb::instance($item->title, $item->url())->set_last()));
}
- static function get_siblings($q, $album) {
- return search::search_within_album(search::add_query_terms($q), $album, 1000, 1)[1];
+ static function get_siblings($q, $album, $limit, $offset) {
+ if (!isset($limit)) {
+ $limit = 100;
+ }
+ if (!isset($offset)) {
+ $offset = 1;
+ }
+ $result = search::search_within_album(search::add_query_terms($q), $album, $limit, $offset);
+ return $result[1];
}
}
diff --git a/modules/search/helpers/search.php b/modules/search/helpers/search.php
index b1bde359..b21e59dd 100644
--- a/modules/search/helpers/search.php
+++ b/modules/search/helpers/search.php
@@ -132,11 +132,12 @@ class search_Core {
static function get_position_within_album($item, $q, $album) {
$page_size = module::get_var("gallery", "page_size", 9);
- $query = self::_build_query_base($q, $album, array("{items}.id = " . $item->id));
+ $query = self::_build_query_base($q, $album, array("{items}.id = " . $item->id)) .
+ "ORDER BY `score` DESC ";
$db = Database::instance();
// Truncate the score by two decimal places as this resolves the issues
- // that arise due to in exact numeric conversions.
+ // that arise due to inexact numeric conversions.
$current = $db->query($query)->current();
if (!$current) {
// We can't find this result in our result set - perhaps we've fallen out of context? Clear
@@ -149,7 +150,10 @@ class search_Core {
$score = substr($score, 0, strlen($score) - 2);
}
- $data = $db->query(self::_build_query_base($q, $album) . " HAVING `score` >= " . $score);
+ // Redo the query but only look for results greater than or equal to our current location
+ // then seek backwards until we find our item.
+ $data = $db->query(self::_build_query_base($q, $album) . " HAVING `score` >= " . $score .
+ "ORDER BY `score` DESC ");
$data->seek($data->count() - 1);
while ($data->get("id") != $item->id && $data->prev()->valid()) {
diff --git a/modules/watermark/controllers/admin_watermarks.php b/modules/watermark/controllers/admin_watermarks.php
index 27c2efc9..b058d6a5 100644
--- a/modules/watermark/controllers/admin_watermarks.php
+++ b/modules/watermark/controllers/admin_watermarks.php
@@ -97,23 +97,19 @@ class Admin_Watermarks_Controller extends Admin_Controller {
// validation logic will correctly reject it. So, we skip validation when we're running tests.
if (TEST_MODE || $form->validate()) {
$file = $_POST["file"];
- $pathinfo = pathinfo($file);
// Forge prefixes files with "uploadfile-xxxxxxx" for uniqueness
- $name = preg_replace("/uploadfile-[^-]+-(.*)/", '$1', $pathinfo["basename"]);
- $name = legal_file::smash_extensions($name);
+ $name = preg_replace("/uploadfile-[^-]+-(.*)/", '$1', basename($file));
- list ($width, $height, $mime_type, $extension) = photo::get_file_metadata($file);
- if (!$width || !$height || !$mime_type || !$extension ||
- !legal_file::get_photo_extensions($extension)) {
+ try {
+ list ($width, $height, $mime_type, $extension) = photo::get_file_metadata($file);
+ // Sanitize filename, which ensures a valid extension. This renaming prevents the issues
+ // addressed in ticket #1855, where an image that looked valid (header said jpg) with a
+ // php extension was previously accepted without changing its extension.
+ $name = legal_file::sanitize_filename($name, $extension, "photo");
+ } catch (Exception $e) {
message::error(t("Invalid or unidentifiable image file"));
@unlink($file);
return;
- } else {
- // Force correct, legal extension type on file, which will be of our canonical type
- // (i.e. all lowercase, jpg instead of jpeg, etc.). This renaming prevents the issues
- // addressed in ticket #1855, where an image that looked valid (header said jpg) with a
- // php extension was previously accepted without changing its extension.
- $name = legal_file::change_extension($name, $extension);
}
rename($file, VARPATH . "modules/watermark/$name");
diff --git a/system/libraries/ORM.php b/system/libraries/ORM.php
index eb34221c..16e047bc 100644
--- a/system/libraries/ORM.php
+++ b/system/libraries/ORM.php
@@ -1469,6 +1469,7 @@ class ORM_Core {
// Load the result
$result = $this->db_builder->execute($this->db);
+ $this->db_applied = array();
if ($array === TRUE)
{