summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.build_number2
-rw-r--r--index.php6
-rw-r--r--installer/install.sql5
-rw-r--r--modules/comment/controllers/admin_comments.php4
-rw-r--r--modules/comment/helpers/comment_installer.php14
-rw-r--r--modules/comment/helpers/comment_rss.php2
-rw-r--r--modules/comment/module.info2
-rw-r--r--modules/g2_import/module.info2
-rw-r--r--modules/gallery/controllers/file_proxy.php10
-rw-r--r--modules/gallery/controllers/items.php10
-rw-r--r--modules/gallery/helpers/gallery_event.php12
-rw-r--r--modules/gallery/helpers/gallery_graphics.php2
-rw-r--r--modules/gallery/helpers/graphics.php4
-rw-r--r--modules/gallery/helpers/legal_file.php12
-rw-r--r--modules/gallery/helpers/module.php6
-rw-r--r--modules/gallery/helpers/movie.php2
-rw-r--r--modules/gallery/images/missing_movie.jpgbin0 -> 3428 bytes
-rw-r--r--modules/gallery/images/missing_movie.pngbin8474 -> 0 bytes
-rw-r--r--modules/gallery/libraries/Admin_View.php7
-rw-r--r--modules/gallery/libraries/IdentityProvider.php9
-rw-r--r--modules/gallery/libraries/Theme_View.php7
-rw-r--r--modules/gallery/models/item.php24
-rw-r--r--modules/gallery/tests/Item_Model_Test.php50
-rw-r--r--modules/gallery/tests/Legal_File_Helper_Test.php32
-rw-r--r--modules/gallery/views/error_admin.html.php2
-rw-r--r--modules/image_block/controllers/image_block.php26
-rw-r--r--modules/image_block/views/image_block_block.html.php2
-rw-r--r--modules/info/helpers/info_block.php5
-rw-r--r--modules/organize/controllers/organize.php14
-rw-r--r--modules/organize/views/organize_dialog.html.php2
-rw-r--r--modules/organize/views/organize_frame.html.php2
-rw-r--r--modules/rss/controllers/rss.php2
-rw-r--r--modules/rss/views/feed.mrss.php2
-rw-r--r--modules/server_add/controllers/admin_server_add.php8
-rw-r--r--modules/server_add/controllers/server_add.php9
-rw-r--r--modules/tag/helpers/tag_event.php3
-rw-r--r--modules/user/helpers/user_installer.php2
-rw-r--r--modules/watermark/controllers/admin_watermarks.php14
-rw-r--r--system/core/Kohana.php8
-rw-r--r--system/libraries/Input.php44
-rw-r--r--themes/admin_wind/views/admin.html.php1
-rw-r--r--themes/wind/views/dynamic.html.php2
-rw-r--r--themes/wind/views/page.html.php5
43 files changed, 293 insertions, 84 deletions
diff --git a/.build_number b/.build_number
index 74ed7356..d0bb43fa 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=193
+build_number=218
diff --git a/index.php b/index.php
index 6e3ee4d4..689c0770 100644
--- a/index.php
+++ b/index.php
@@ -24,6 +24,12 @@ define("IN_PRODUCTION", true);
version_compare(PHP_VERSION, "5.2.3", "<") and
exit("Gallery requires PHP 5.2.3 or newer (you're using " . PHP_VERSION . ")");
+// 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")) {
+ ini_set("date.timezone", "UTC");
+}
+
// Gallery requires short_tags to be on
!ini_get("short_open_tag") and exit("Gallery requires short_open_tag to be on.");
diff --git a/installer/install.sql b/installer/install.sql
index 2b8ec11e..2ba168d2 100644
--- a/installer/install.sql
+++ b/installer/install.sql
@@ -246,7 +246,7 @@ CREATE TABLE {modules} (
/*!40101 SET character_set_client = @saved_cs_client */;
INSERT INTO {modules} VALUES (1,1,'gallery',49,1);
INSERT INTO {modules} VALUES (2,1,'user',4,2);
-INSERT INTO {modules} VALUES (3,1,'comment',4,3);
+INSERT INTO {modules} VALUES (3,1,'comment',6,3);
INSERT INTO {modules} VALUES (4,1,'organize',4,4);
INSERT INTO {modules} VALUES (5,1,'info',2,5);
INSERT INTO {modules} VALUES (6,1,'rss',1,6);
@@ -382,7 +382,7 @@ CREATE TABLE {vars} (
`value` text,
PRIMARY KEY (`id`),
UNIQUE KEY `module_name` (`module_name`,`name`)
-) AUTO_INCREMENT=43 DEFAULT CHARSET=utf8;
+) AUTO_INCREMENT=44 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');
@@ -419,6 +419,7 @@ INSERT INTO {vars} VALUES (NULL,'gallery','identity_provider','user');
INSERT INTO {vars} VALUES (NULL,'user','minimum_password_length','5');
INSERT INTO {vars} VALUES (NULL,'comment','spam_caught','0');
INSERT INTO {vars} VALUES (NULL,'comment','access_permissions','everybody');
+INSERT INTO {vars} VALUES (NULL,'comment','rss_visible','both');
INSERT INTO {vars} VALUES (NULL,'info','show_title','1');
INSERT INTO {vars} VALUES (NULL,'info','show_description','1');
INSERT INTO {vars} VALUES (NULL,'info','show_owner','1');
diff --git a/modules/comment/controllers/admin_comments.php b/modules/comment/controllers/admin_comments.php
index bcd6a939..00a7a608 100644
--- a/modules/comment/controllers/admin_comments.php
+++ b/modules/comment/controllers/admin_comments.php
@@ -32,8 +32,8 @@ class Admin_Comments_Controller extends Admin_Controller {
$form->validate();
module::set_var("comment", "access_permissions",
$form->comment_settings->access_permissions->value);
- module::set_var("comment", "rss_available",
- $form->comment_settings->rss_available->value);
+ module::set_var("comment", "rss_visible",
+ $form->comment_settings->rss_visible->value);
message::success(t("Comment settings updated"));
url::redirect("admin/comments");
}
diff --git a/modules/comment/helpers/comment_installer.php b/modules/comment/helpers/comment_installer.php
index a64064f6..cbb8c783 100644
--- a/modules/comment/helpers/comment_installer.php
+++ b/modules/comment/helpers/comment_installer.php
@@ -48,8 +48,8 @@ class comment_installer {
module::set_var("comment", "spam_caught", 0);
module::set_var("comment", "access_permissions", "everybody");
- module::set_var("comment", "rss_available", "both");
- module::set_version("comment", 5);
+ module::set_var("comment", "rss_visible", "both");
+ module::set_version("comment", 6);
}
static function upgrade($version) {
@@ -81,6 +81,16 @@ class comment_installer {
module::set_var("comment", "rss_visible", "all");
module::set_version("comment", $version = 5);
}
+
+ // In version 5 we accidentally set the installer variable to rss_available when it should
+ // have been rss_visible. Migrate it over now, if necessary.
+ if ($version == 5) {
+ if (!module::get_var("comment", "rss_visible")) {
+ module::set_var("comment", "rss_visible", module::get_var("comment", "rss_available"));
+ }
+ module::clear_var("comment", "rss_available");
+ module::set_version("comment", $version = 6);
+ }
}
static function uninstall() {
diff --git a/modules/comment/helpers/comment_rss.php b/modules/comment/helpers/comment_rss.php
index cfee4727..be1968dc 100644
--- a/modules/comment/helpers/comment_rss.php
+++ b/modules/comment/helpers/comment_rss.php
@@ -65,7 +65,7 @@ class comment_rss_Core {
foreach ($comments->find_all($limit, $offset) as $comment) {
$item = $comment->item();
$feed->comments[] = new ArrayObject(
- array("pub_date" => date("D, d M Y H:i:s T", $comment->created),
+ array("pub_date" => date("D, d M Y H:i:s O", $comment->created),
"text" => nl2br(html::purify($comment->text)),
"thumb_url" => $item->thumb_url(),
"thumb_height" => $item->thumb_height,
diff --git a/modules/comment/module.info b/modules/comment/module.info
index ecbf8885..bd4abe9f 100644
--- a/modules/comment/module.info
+++ b/modules/comment/module.info
@@ -1,6 +1,6 @@
name = "Comments"
description = "Allows users and guests to leave comments on photos and albums."
-version = 5
+version = 6
author_name = "Gallery Team"
author_url = "http://codex.gallery2.org/Gallery:Team"
info_url = "http://codex.gallery2.org/Gallery3:Modules:comment"
diff --git a/modules/g2_import/module.info b/modules/g2_import/module.info
index 30fb46d4..6b03d097 100644
--- a/modules/g2_import/module.info
+++ b/modules/g2_import/module.info
@@ -1,4 +1,4 @@
-name = "Gallery2 Import"
+name = "Gallery 2 Import"
description = "Import your Gallery 2 content into Gallery 3"
version = 2
author_name = "Gallery Team"
diff --git a/modules/gallery/controllers/file_proxy.php b/modules/gallery/controllers/file_proxy.php
index 5c958a8d..36c6bc2a 100644
--- a/modules/gallery/controllers/file_proxy.php
+++ b/modules/gallery/controllers/file_proxy.php
@@ -122,7 +122,15 @@ class File_Proxy_Controller extends Controller {
} else {
header("Content-Type: $item->mime_type");
}
- Kohana::close_buffers(false);
+
+ // Don't use Kohana::close_buffers(false) here because that only closes all the buffers
+ // that Kohana started. We want to close *all* buffers at this point because otherwise we're
+ // going to buffer up whatever file we're proxying (and it may be very large). This may
+ // affect embedding or systems with PHP's output_buffering enabled.
+ while (ob_get_level()) {
+ ob_end_clean();
+ }
+
readfile($file);
}
}
diff --git a/modules/gallery/controllers/items.php b/modules/gallery/controllers/items.php
index 0c20803c..318fb431 100644
--- a/modules/gallery/controllers/items.php
+++ b/modules/gallery/controllers/items.php
@@ -24,15 +24,15 @@ class Items_Controller extends Controller {
throw new Kohana_404_Exception();
}
- // Redirect to the more specific resource type, since it will render
- // differently. We can't delegate here because we may have gotten to this
- // page via /items/<id> which means that we don't have a type-specific controller. Also, we
- // want to drive a single canonical resource mapping where possible.
+ // Redirect to the more specific resource type, since it will render differently. We can't
+ // delegate here because we may have gotten to this page via /items/<id> which means that we
+ // don't have a type-specific controller. Also, we want to drive a single canonical resource
+ // mapping where possible.
access::required("view", $item);
url::redirect($item->abs_url());
}
- // Return the width/height dimensinons for the given item
+ // Return the width/height dimensions for the given item
public function dimensions($id) {
$item = ORM::factory("item", $id);
access::required("view", $item);
diff --git a/modules/gallery/helpers/gallery_event.php b/modules/gallery/helpers/gallery_event.php
index db087588..6225633f 100644
--- a/modules/gallery/helpers/gallery_event.php
+++ b/modules/gallery/helpers/gallery_event.php
@@ -23,6 +23,14 @@ class gallery_event_Core {
* Initialization.
*/
static function gallery_ready() {
+ if (!get_cfg_var("date.timezone")) {
+ if (!(rand() % 4)) {
+ Kohana_Log::add("error", "date.timezone setting not detected in " .
+ get_cfg_var("cfg_file_path") . " falling back to UTC. " .
+ "Consult http://php.net/manual/function.get-cfg-var.php for help.");
+ }
+ }
+
identity::load_user();
theme::load_themes();
locales::set_request_locale();
@@ -549,8 +557,8 @@ class gallery_event_Core {
$value = $data->user->$field;
if ($field == "locale") {
$value = locales::display_name($value);
- } elseif ($field == "url") {
- $value = html::mark_clean(html::anchor($data->user->$field));
+ } else if ($field == "url") {
+ $value = html::mark_clean(html::anchor(html::clean($data->user->$field)));
}
$v->user_profile_data[(string) $label] = $value;
}
diff --git a/modules/gallery/helpers/gallery_graphics.php b/modules/gallery/helpers/gallery_graphics.php
index 02f628a1..d2b92c87 100644
--- a/modules/gallery/helpers/gallery_graphics.php
+++ b/modules/gallery/helpers/gallery_graphics.php
@@ -126,7 +126,7 @@ class gallery_graphics_Core {
module::event("graphics_composite_completed", $input_file, $output_file, $options, $item);
} catch (ErrorException $e) {
- Kohana_Log::add("error", $e->get_message());
+ Kohana_Log::add("error", $e->getMessage());
}
}
}
diff --git a/modules/gallery/helpers/graphics.php b/modules/gallery/helpers/graphics.php
index 7e0bbbea..c19fbe6d 100644
--- a/modules/gallery/helpers/graphics.php
+++ b/modules/gallery/helpers/graphics.php
@@ -156,12 +156,12 @@ class graphics_Core {
foreach ($ops as $target => $output_file) {
if ($input_item->is_movie()) {
// Convert the movie to a JPG first
- $output_file = preg_replace("/...$/", "jpg", $output_file);
+ $output_file = legal_file::change_extension($output_file, "jpg");
try {
movie::extract_frame($input_file, $output_file);
} catch (Exception $e) {
// Assuming this is MISSING_FFMPEG for now
- copy(MODPATH . "gallery/images/missing_movie.png", $output_file);
+ copy(MODPATH . "gallery/images/missing_movie.jpg", $output_file);
}
$working_file = $output_file;
} else {
diff --git a/modules/gallery/helpers/legal_file.php b/modules/gallery/helpers/legal_file.php
index 6ec65e97..af6472ca 100644
--- a/modules/gallery/helpers/legal_file.php
+++ b/modules/gallery/helpers/legal_file.php
@@ -80,4 +80,16 @@ class legal_file_Core {
module::event("legal_movie_types", $types_wrapper);
return $types_wrapper->types;
}
+
+ /**
+ * Convert the extension of a filename. If the original filename has no
+ * extension, add the new one to the end.
+ */
+ static function change_extension($filename, $new_ext) {
+ if (strpos($filename, ".") === false) {
+ return "{$filename}.{$new_ext}";
+ } else {
+ return preg_replace("/\..*?$/", ".{$new_ext}", $filename);
+ }
+ }
}
diff --git a/modules/gallery/helpers/module.php b/modules/gallery/helpers/module.php
index 3368e39b..7292b106 100644
--- a/modules/gallery/helpers/module.php
+++ b/modules/gallery/helpers/module.php
@@ -109,7 +109,11 @@ class module_Core {
$modules->gallery->locked = true;
$identity_module = module::get_var("gallery", "identity_provider", "user");
$modules->$identity_module->locked = true;
- $modules->ksort();
+
+ function natural_name_sort($a, $b) {
+ return strnatcasecmp($a->name, $b->name);
+ }
+ $modules->uasort('natural_name_sort');
self::$available = $modules;
}
diff --git a/modules/gallery/helpers/movie.php b/modules/gallery/helpers/movie.php
index 79b5a7c2..b54811df 100644
--- a/modules/gallery/helpers/movie.php
+++ b/modules/gallery/helpers/movie.php
@@ -106,7 +106,7 @@ class movie_Core {
$cmd = escapeshellcmd($ffmpeg) . " -i " . escapeshellarg($file_path) . " 2>&1";
$result = `$cmd`;
- if (preg_match("/Stream.*?Video:.*?(\d+)x(\d+)/", $result, $regs)) {
+ if (preg_match("/Stream.*?Video:.*?, (\d+)x(\d+)/", $result, $regs)) {
list ($width, $height) = array($regs[1], $regs[2]);
} else {
list ($width, $height) = array(0, 0);
diff --git a/modules/gallery/images/missing_movie.jpg b/modules/gallery/images/missing_movie.jpg
new file mode 100644
index 00000000..452db225
--- /dev/null
+++ b/modules/gallery/images/missing_movie.jpg
Binary files differ
diff --git a/modules/gallery/images/missing_movie.png b/modules/gallery/images/missing_movie.png
deleted file mode 100644
index fdc97779..00000000
--- a/modules/gallery/images/missing_movie.png
+++ /dev/null
Binary files differ
diff --git a/modules/gallery/libraries/Admin_View.php b/modules/gallery/libraries/Admin_View.php
index fcfe7aa2..66b8c20c 100644
--- a/modules/gallery/libraries/Admin_View.php
+++ b/modules/gallery/libraries/Admin_View.php
@@ -31,7 +31,12 @@ class Admin_View_Core extends Gallery_View {
$this->theme_name = module::get_var("gallery", "active_admin_theme");
if (identity::active_user()->admin) {
- $this->theme_name = Input::instance()->get("theme", $this->theme_name);
+ $theme_name = Input::instance()->get("theme");
+ if ($theme_name &&
+ file_exists(THEMEPATH . $theme_name) &&
+ strpos(realpath(THEMEPATH . $theme_name), THEMEPATH) == 0) {
+ $this->theme_name = $theme_name;
+ }
}
$this->sidebar = "";
$this->set_global(array("theme" => $this,
diff --git a/modules/gallery/libraries/IdentityProvider.php b/modules/gallery/libraries/IdentityProvider.php
index 66c68dad..c9e8688f 100644
--- a/modules/gallery/libraries/IdentityProvider.php
+++ b/modules/gallery/libraries/IdentityProvider.php
@@ -85,6 +85,10 @@ class IdentityProvider_Core {
call_user_func("{$new_provider}_installer::initialize");
}
+ if (!$provider->admin_user()) {
+ throw new Exception("IdentityProvider $new_provider: Couldn't find the admin user!");
+ }
+
module::event("identity_provider_changed", $current_provider, $new_provider);
identity::set_active_user($provider->admin_user());
@@ -100,7 +104,12 @@ class IdentityProvider_Core {
// Make sure new provider is not in the database
try {
module::uninstall($new_provider);
+ } catch (Exception $e2) {
+ Kohana_Log::add("error", "Error uninstalling failed new provider\n" .
+ $e2->getMessage() . "\n" . $e2->getTraceAsString());
+ }
+ try {
// Lets reset to the current provider so that the gallery installation is still
// working.
module::set_var("gallery", "identity_provider", null);
diff --git a/modules/gallery/libraries/Theme_View.php b/modules/gallery/libraries/Theme_View.php
index 031da6de..78b74cde 100644
--- a/modules/gallery/libraries/Theme_View.php
+++ b/modules/gallery/libraries/Theme_View.php
@@ -33,7 +33,12 @@ class Theme_View_Core extends Gallery_View {
$this->theme_name = module::get_var("gallery", "active_site_theme");
if (identity::active_user()->admin) {
- $this->theme_name = Input::instance()->get("theme", $this->theme_name);
+ $theme_name = Input::instance()->get("theme");
+ if ($theme_name &&
+ file_exists(THEMEPATH . $theme_name) &&
+ strpos(realpath(THEMEPATH . $theme_name), THEMEPATH) == 0) {
+ $this->theme_name = $theme_name;
+ }
}
$this->item = null;
$this->tag = null;
diff --git a/modules/gallery/models/item.php b/modules/gallery/models/item.php
index e90e0fcb..98a2c4df 100644
--- a/modules/gallery/models/item.php
+++ b/modules/gallery/models/item.php
@@ -188,7 +188,7 @@ class Item_Model_Core extends ORM_MPTT {
return $base . "/.album.jpg";
} else if ($this->is_movie()) {
// Replace the extension with jpg
- return preg_replace("/...$/", "jpg", $base);
+ return legal_file::change_extension($base, "jpg");
}
}
@@ -213,7 +213,7 @@ class Item_Model_Core extends ORM_MPTT {
return $base . "/.album.jpg" . $cache_buster;
} else if ($this->is_movie()) {
// Replace the extension with jpg
- $base = preg_replace("/...$/", "jpg", $base);
+ $base = legal_file::change_extension($base, "jpg");
return $base . $cache_buster;
}
}
@@ -803,18 +803,22 @@ class Item_Model_Core extends ORM_MPTT {
}
if ($this->is_movie() || $this->is_photo()) {
- if (!$this->loaded()) {
+ $ext = pathinfo($this->name, PATHINFO_EXTENSION);
+
+ if (!$this->loaded() && !$ext) {
// New items must have an extension
- $ext = pathinfo($this->name, PATHINFO_EXTENSION);
- if (!$ext) {
+ $v->add_error("name", "illegal_data_file_extension");
+ return;
+ }
+
+ if ($this->is_photo()) {
+ if (!in_array(strtolower($ext), legal_file::get_photo_extensions())) {
$v->add_error("name", "illegal_data_file_extension");
- return;
}
+ }
- if ($this->is_photo() &&
- !in_array(strtolower($ext), array_map("strtolower", legal_file::get_photo_extensions())) ||
- $this->is_movie() &&
- !in_array(strtolower($ext), array_map("strtolower", legal_file::get_movie_extensions()))) {
+ if ($this->is_movie()) {
+ if (!in_array(strtolower($ext), legal_file::get_movie_extensions())) {
$v->add_error("name", "illegal_data_file_extension");
}
}
diff --git a/modules/gallery/tests/Item_Model_Test.php b/modules/gallery/tests/Item_Model_Test.php
index 205d0a08..6d40230f 100644
--- a/modules/gallery/tests/Item_Model_Test.php
+++ b/modules/gallery/tests/Item_Model_Test.php
@@ -333,7 +333,36 @@ class Item_Model_Test extends Gallery_Unit_Test_Case {
$photo->mime_type = "video/x-flv";
$photo->save();
} catch (ORM_Validation_Exception $e) {
- $this->assert_same(array("type" => "read_only"), $e->validation->errors());
+ $this->assert_same(
+ array("name" => "illegal_data_file_extension", "type" => "read_only"),
+ $e->validation->errors());
+ return; // pass
+ }
+ $this->assert_true(false, "Shouldn't get here");
+ }
+
+ 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");
+ }
+
+ public function movie_files_must_have_an_extension_test() {
+ try {
+ $movie = test::random_photo_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");
@@ -421,7 +450,8 @@ 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"), $e->validation->errors());
+ $this->assert_same(array("mime_type" => "invalid", "name" => "illegal_data_file_extension"),
+ $e->validation->errors());
return; // pass
}
$this->assert_true(false, "Shouldn't get here");
@@ -473,4 +503,20 @@ class Item_Model_Test extends Gallery_Unit_Test_Case {
$this->assert_true(false, "Shouldn't get here");
}
}
+
+ 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");
+ }
+ }
}
diff --git a/modules/gallery/tests/Legal_File_Helper_Test.php b/modules/gallery/tests/Legal_File_Helper_Test.php
new file mode 100644
index 00000000..c101de10
--- /dev/null
+++ b/modules/gallery/tests/Legal_File_Helper_Test.php
@@ -0,0 +1,32 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2012 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 Legal_File_Helper_Test extends Gallery_Unit_Test_Case {
+ public function change_extension_test() {
+ $this->assert_equal("foo.jpg", legal_file::change_extension("foo.png", "jpg"));
+ }
+
+ public function change_four_letter_extension_test() {
+ $this->assert_equal("foo.flv", legal_file::change_extension("foo.mpeg", "flv"));
+ }
+
+ public function change_extension_with_no_extension_test() {
+ $this->assert_equal("foo.flv", legal_file::change_extension("foo", "flv"));
+ }
+} \ No newline at end of file
diff --git a/modules/gallery/views/error_admin.html.php b/modules/gallery/views/error_admin.html.php
index af78c59c..a391746e 100644
--- a/modules/gallery/views/error_admin.html.php
+++ b/modules/gallery/views/error_admin.html.php
@@ -184,7 +184,7 @@
<?= $type?> [ <?= $code ?> ]:
</span>
<span class="message">
- <?= $message?>
+ <?= html::purify($message) ?>
</span>
</h3>
<div id="<?= $error_id ?>" class="content">
diff --git a/modules/image_block/controllers/image_block.php b/modules/image_block/controllers/image_block.php
new file mode 100644
index 00000000..94024b3b
--- /dev/null
+++ b/modules/image_block/controllers/image_block.php
@@ -0,0 +1,26 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2012 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 Image_Block_Controller extends Controller {
+ public function random($item_id) {
+ $item = ORM::factory("item", $item_id);
+ item::set_display_context_callback("Albums_Controller::get_display_context");
+ url::redirect($item->abs_url());
+ }
+}
diff --git a/modules/image_block/views/image_block_block.html.php b/modules/image_block/views/image_block_block.html.php
index 2a57c395..6f68e5b8 100644
--- a/modules/image_block/views/image_block_block.html.php
+++ b/modules/image_block/views/image_block_block.html.php
@@ -1,7 +1,7 @@
<?php defined("SYSPATH") or die("No direct script access.") ?>
<? foreach ($items as $item): ?>
<div class="g-image-block">
- <a href="<?= $item->url() ?>">
+ <a href="<?= url::site("image_block/random/" . $item->id); ?>">
<?= $item->thumb_img(array("class" => "g-thumbnail")) ?>
</a>
</div>
diff --git a/modules/info/helpers/info_block.php b/modules/info/helpers/info_block.php
index c4470dbe..3dcfa338 100644
--- a/modules/info/helpers/info_block.php
+++ b/modules/info/helpers/info_block.php
@@ -60,8 +60,9 @@ class info_block_Core {
if ($theme->item->owner->url) {
$info["owner"] = array(
"label" => t("Owner:"),
- "value" => "<a href=\"{$theme->item->owner->url}\">" .
- html::clean($display_name) . "</a>"
+ "value" => html::anchor(
+ html::clean($theme->item->owner->url),
+ html::clean($display_name))
);
} else {
$info["owner"] = array(
diff --git a/modules/organize/controllers/organize.php b/modules/organize/controllers/organize.php
index 5a2c3e4f..b0c13e7d 100644
--- a/modules/organize/controllers/organize.php
+++ b/modules/organize/controllers/organize.php
@@ -56,7 +56,7 @@ class Organize_Controller extends Controller {
"sort_column" => $album->sort_column,
"sort_order" => $album->sort_order,
"editable" => access::can("edit", $album),
- "title" => $album->title,
+ "title" => (string)html::clean($album->title),
"children" => array());
foreach ($album->viewable()->children() as $child) {
@@ -67,7 +67,7 @@ class Organize_Controller extends Controller {
"width" => $dims[1],
"height" => $dims[0],
"type" => $child->type,
- "title" => $child->title);
+ "title" => (string)html::clean($child->title));
}
json::reply($data);
}
@@ -81,6 +81,9 @@ class Organize_Controller extends Controller {
foreach (explode(",", $input->post("source_ids")) as $source_id) {
$source = ORM::factory("item", $source_id);
+ if (!$source->loaded()) {
+ continue;
+ }
access::required("edit", $source->parent());
if ($source->contains($new_parent) || $source->id == $new_parent->id) {
@@ -116,6 +119,11 @@ class Organize_Controller extends Controller {
$input = Input::instance();
$target = ORM::factory("item", $input->post("target_id"));
+ if (!$target->loaded()) {
+ json::reply(null);
+ return;
+ }
+
$album = $target->parent();
access::required("edit", $album);
@@ -187,7 +195,7 @@ class Organize_Controller extends Controller {
"expandable" => false,
"id" => $child->id,
"leaf" => $child->children_count(array(array("type", "=", "album"))) == 0,
- "text" => $child->title,
+ "text" => (string)html::clean($child->title),
"nodeType" => "async");
// If the child is in the selected path, open it now. Else, mark it async.
diff --git a/modules/organize/views/organize_dialog.html.php b/modules/organize/views/organize_dialog.html.php
index a386fa77..9ea4d923 100644
--- a/modules/organize/views/organize_dialog.html.php
+++ b/modules/organize/views/organize_dialog.html.php
@@ -11,7 +11,7 @@
var set_title = function(title) {
$("#g-dialog").dialog("option", "title", ORGANIZE_TITLE.replace("__TITLE__", title));
}
- set_title("<?= $album->title ?>");
+ set_title("<?= html::clean($album->title) ?>");
var done_loading = function() {
$("#g-organize-app-loading").hide();
diff --git a/modules/organize/views/organize_frame.html.php b/modules/organize/views/organize_frame.html.php
index 20a1a6da..51d49104 100644
--- a/modules/organize/views/organize_frame.html.php
+++ b/modules/organize/views/organize_frame.html.php
@@ -506,7 +506,7 @@
root: {
allowDrop: Boolean(<?= access::can("edit", item::root()) ?>),
nodeType: "async",
- text: "<?= item::root()->title ?>",
+ text: "<?= html::clean(item::root()->title) ?>",
draggable: false,
id: "<?= item::root()->id ?>",
expanded: true
diff --git a/modules/rss/controllers/rss.php b/modules/rss/controllers/rss.php
index 799ba989..288bf635 100644
--- a/modules/rss/controllers/rss.php
+++ b/modules/rss/controllers/rss.php
@@ -50,7 +50,7 @@ class Rss_Controller extends Controller {
unset($feed->view);
$view->feed = $feed;
- $view->pub_date = date("D, d M Y H:i:s T");
+ $view->pub_date = date("D, d M Y H:i:s O");
$feed->uri = url::abs_site(url::merge($_GET));
if ($page > 1) {
diff --git a/modules/rss/views/feed.mrss.php b/modules/rss/views/feed.mrss.php
index 3f0010bb..b609a541 100644
--- a/modules/rss/views/feed.mrss.php
+++ b/modules/rss/views/feed.mrss.php
@@ -25,7 +25,7 @@
<title><?= html::purify($item->title) ?></title>
<link><?= url::abs_site("{$item->type}s/{$item->id}") ?></link>
<guid isPermaLink="true"><?= url::abs_site("{$item->type}s/{$item->id}") ?></guid>
- <pubDate><?= date("D, d M Y H:i:s T", $item->created); ?></pubDate>
+ <pubDate><?= date("D, d M Y H:i:s O", $item->created); ?></pubDate>
<description><?= html::purify($item->description) ?></description>
<content:encoded>
<![CDATA[
diff --git a/modules/server_add/controllers/admin_server_add.php b/modules/server_add/controllers/admin_server_add.php
index 0c741513..954c9ef6 100644
--- a/modules/server_add/controllers/admin_server_add.php
+++ b/modules/server_add/controllers/admin_server_add.php
@@ -35,12 +35,12 @@ class Admin_Server_Add_Controller extends Admin_Controller {
$form = $this->_get_admin_form();
$paths = unserialize(module::get_var("server_add", "authorized_paths", "a:0:{}"));
if ($form->validate()) {
- if (is_link($form->add_path->path->value)) {
+ $path = html_entity_decode($form->add_path->path->value);
+ if (is_link($path)) {
$form->add_path->path->add_error("is_symlink", 1);
- } else if (!is_readable($form->add_path->path->value)) {
+ } else if (!is_readable($path)) {
$form->add_path->path->add_error("not_readable", 1);
} else {
- $path = $form->add_path->path->value;
$paths[$path] = 1;
module::set_var("server_add", "authorized_paths", serialize($paths));
message::success(t("Added path %path", array("path" => $path)));
@@ -75,7 +75,7 @@ class Admin_Server_Add_Controller extends Admin_Controller {
$path_prefix = Input::instance()->get("q");
foreach (glob("{$path_prefix}*") as $file) {
if (is_dir($file) && !is_link($file)) {
- $directories[] = $file;
+ $directories[] = html::clean($file);
}
}
diff --git a/modules/server_add/controllers/server_add.php b/modules/server_add/controllers/server_add.php
index a3333ae2..c6d36a11 100644
--- a/modules/server_add/controllers/server_add.php
+++ b/modules/server_add/controllers/server_add.php
@@ -61,7 +61,7 @@ class Server_Add_Controller extends Admin_Controller {
}
if (!is_dir($file)) {
$ext = strtolower(pathinfo($file, PATHINFO_EXTENSION));
- if (!in_array($ext, array("gif", "jpeg", "jpg", "png", "flv", "mp4", "m4v"))) {
+ if (!in_array($ext, legal_file::get_extensions())) {
continue;
}
}
@@ -169,8 +169,7 @@ class Server_Add_Controller extends Admin_Controller {
foreach ($child_paths as $child_path) {
if (!is_dir($child_path)) {
$ext = strtolower(pathinfo($child_path, PATHINFO_EXTENSION));
- if (!in_array($ext, array("gif", "jpeg", "jpg", "png", "flv", "mp4", "m4v")) ||
- !filesize($child_path)) {
+ if (!in_array($ext, legal_file::get_extensions()) || !filesize($child_path)) {
// Not importable, skip it.
continue;
}
@@ -256,7 +255,7 @@ class Server_Add_Controller extends Admin_Controller {
} else {
try {
$extension = strtolower(pathinfo($name, PATHINFO_EXTENSION));
- if (in_array($extension, array("gif", "png", "jpg", "jpeg"))) {
+ if (in_array($extension, legal_file::get_photo_extensions())) {
$photo = ORM::factory("item");
$photo->type = "photo";
$photo->parent_id = $parent->id;
@@ -266,7 +265,7 @@ class Server_Add_Controller extends Admin_Controller {
$photo->owner_id = $owner_id;
$photo->save();
$entry->item_id = $photo->id;
- } else if (in_array($extension, array("flv", "mp4", "m4v"))) {
+ } else if (in_array($extension, legal_file::get_movie_extensions())) {
$movie = ORM::factory("item");
$movie->type = "movie";
$movie->parent_id = $parent->id;
diff --git a/modules/tag/helpers/tag_event.php b/modules/tag/helpers/tag_event.php
index 26876d83..d4f1c757 100644
--- a/modules/tag/helpers/tag_event.php
+++ b/modules/tag/helpers/tag_event.php
@@ -149,7 +149,8 @@ class tag_event_Core {
static function info_block_get_metadata($block, $item) {
$tags = array();
foreach (tag::item_tags($item) as $tag) {
- $tags[] = "<a href=\"{$tag->url()}\">{$tag->name}</a>";
+ $tags[] = "<a href=\"{$tag->url()}\">" .
+ html::clean($tag->name) . "</a>";
}
if ($tags) {
$info = $block->content->metadata;
diff --git a/modules/user/helpers/user_installer.php b/modules/user/helpers/user_installer.php
index c07b624f..1ba1aeaf 100644
--- a/modules/user/helpers/user_installer.php
+++ b/modules/user/helpers/user_installer.php
@@ -22,7 +22,7 @@ class user_installer {
return array("warn" => array(IdentityProvider::confirmation_message()));
}
- static function install() {
+ static function activate() {
IdentityProvider::change_provider("user");
// Set the latest version in initialize() below
}
diff --git a/modules/watermark/controllers/admin_watermarks.php b/modules/watermark/controllers/admin_watermarks.php
index 2c4c602d..92a44a86 100644
--- a/modules/watermark/controllers/admin_watermarks.php
+++ b/modules/watermark/controllers/admin_watermarks.php
@@ -106,6 +106,20 @@ class Admin_Watermarks_Controller extends Admin_Controller {
return;
}
+ if (!in_array($pathinfo["extension"], legal_file::get_photo_extensions())) {
+ switch ($image_info[2]) {
+ case IMAGETYPE_GIF:
+ $name = legal_file::change_extension($name, "gif");
+ break;
+ case IMAGETYPE_JPEG:
+ $name = legal_file::change_extension($name, "jpg");
+ break;
+ case IMAGETYPE_PNG:
+ $name = legal_file::change_extension($name, "png");
+ break;
+ }
+ }
+
rename($file, VARPATH . "modules/watermark/$name");
module::set_var("watermark", "name", $name);
module::set_var("watermark", "width", $image_info[0]);
diff --git a/system/core/Kohana.php b/system/core/Kohana.php
index f7f6b326..96d969ed 100644
--- a/system/core/Kohana.php
+++ b/system/core/Kohana.php
@@ -525,8 +525,12 @@ abstract class Kohana_Core {
$close();
}
- // Store the Kohana output buffer
- ob_end_clean();
+ // Store the Kohana output buffer. Apparently there was a change in PHP
+ // 5.4 such that if you call this you wind up with a blank page.
+ // Disabling it for now. See ticket #1839
+ if (version_compare(PHP_VERSION, "5.4", "<")) {
+ ob_end_clean();
+ }
}
}
diff --git a/system/libraries/Input.php b/system/libraries/Input.php
index c6c84fca..2bef3ff4 100644
--- a/system/libraries/Input.php
+++ b/system/libraries/Input.php
@@ -334,33 +334,37 @@ class Input_Core {
// * Removed parentheses where possible
// * Split up alternation alternatives
// * Made some quantifiers possessive
+ //
+ // Gallery Modifications:
+ // * Wrap the loop around all the changes to detect nested exploits
+
+ do
+ {
+ $old_data = $data;
- // Fix &entity\n;
- $data = str_replace(array('&amp;','&lt;','&gt;'), array('&amp;amp;','&amp;lt;','&amp;gt;'), $data);
- $data = preg_replace('/(&#*\w+)[\x00-\x20]+;/u', '$1;', $data);
- $data = preg_replace('/(&#x*[0-9A-F]+);*/iu', '$1;', $data);
- $data = html_entity_decode($data, ENT_COMPAT, 'UTF-8');
+ // Fix &entity\n;
+ $data = str_replace(array('&amp;','&lt;','&gt;'), array('&amp;amp;','&amp;lt;','&amp;gt;'), $data);
+ $data = preg_replace('/(&#*\w+)[\x00-\x20]+;/u', '$1;', $data);
+ $data = preg_replace('/(&#x*[0-9A-F]+);*/iu', '$1;', $data);
+ $data = html_entity_decode($data, ENT_COMPAT, 'UTF-8');
- // Remove any attribute starting with "on" or xmlns
- $data = preg_replace('#(?:on[a-z]+|xmlns)\s*=\s*[\'"\x00-\x20]?[^\'>"]*[\'"\x00-\x20]?\s?#iu', '', $data);
+ // Remove any attribute starting with "on" or xmlns
+ $data = preg_replace('#(?:on[a-z]+|xmlns)\s*=\s*[\'"\x00-\x20]?[^\'>"]*[\'"\x00-\x20]?\s?#iu', '', $data);
- // Remove javascript: and vbscript: protocols
- $data = preg_replace('#([a-z]*)[\x00-\x20]*=[\x00-\x20]*([`\'"]*)[\x00-\x20]*j[\x00-\x20]*a[\x00-\x20]*v[\x00-\x20]*a[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2nojavascript...', $data);
- $data = preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*v[\x00-\x20]*b[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2novbscript...', $data);
- $data = preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*-moz-binding[\x00-\x20]*:#u', '$1=$2nomozbinding...', $data);
+ // Remove javascript: and vbscript: protocols
+ $data = preg_replace('#([a-z]*)[\x00-\x20]*=[\x00-\x20]*([`\'"]*)[\x00-\x20]*j[\x00-\x20]*a[\x00-\x20]*v[\x00-\x20]*a[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2nojavascript...', $data);
+ $data = preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*v[\x00-\x20]*b[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2novbscript...', $data);
+ $data = preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*-moz-binding[\x00-\x20]*:#u', '$1=$2nomozbinding...', $data);
- // Only works in IE: <span style="width: expression(alert('Ping!'));"></span>
- $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?expression[\x00-\x20]*\([^>]*+>#i', '$1>', $data);
- $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?behaviour[\x00-\x20]*\([^>]*+>#i', '$1>', $data);
- $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:*[^>]*+>#iu', '$1>', $data);
+ // Only works in IE: <span style="width: expression(alert('Ping!'));"></span>
+ $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?expression[\x00-\x20]*\([^>]*+>#i', '$1>', $data);
+ $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?behaviour[\x00-\x20]*\([^>]*+>#i', '$1>', $data);
+ $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:*[^>]*+>#iu', '$1>', $data);
- // Remove namespaced elements (we do not need them)
- $data = preg_replace('#</*\w+:\w[^>]*+>#i', '', $data);
+ // Remove namespaced elements (we do not need them)
+ $data = preg_replace('#</*\w+:\w[^>]*+>#i', '', $data);
- do
- {
// Remove really unwanted tags
- $old_data = $data;
$data = preg_replace('#</*(?:applet|b(?:ase|gsound|link)|embed|frame(?:set)?|i(?:frame|layer)|l(?:ayer|ink)|meta|object|s(?:cript|tyle)|title|xml)[^>]*+>#i', '', $data);
}
while ($old_data !== $data);
diff --git a/themes/admin_wind/views/admin.html.php b/themes/admin_wind/views/admin.html.php
index 9a149149..0300f7af 100644
--- a/themes/admin_wind/views/admin.html.php
+++ b/themes/admin_wind/views/admin.html.php
@@ -1,4 +1,5 @@
<?php defined("SYSPATH") or die("No direct script access.") ?>
+<?php header("X-Frame-Options: SAMEORIGIN"); ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" <?= $theme->html_attributes() ?> xml:lang="en" lang="en">
diff --git a/themes/wind/views/dynamic.html.php b/themes/wind/views/dynamic.html.php
index 67360da7..33e05de3 100644
--- a/themes/wind/views/dynamic.html.php
+++ b/themes/wind/views/dynamic.html.php
@@ -3,7 +3,7 @@
<div id="g-album-header-buttons">
<?= $theme->dynamic_top() ?>
</div>
- <h1><?= html::clean($title) ?></h1>
+ <h1><?= html::purify($title) ?></h1>
</div>
<ul id="g-album-grid" class="ui-helper-clearfix">
diff --git a/themes/wind/views/page.html.php b/themes/wind/views/page.html.php
index 24d3347e..c3e212c5 100644
--- a/themes/wind/views/page.html.php
+++ b/themes/wind/views/page.html.php
@@ -1,4 +1,5 @@
<?php defined("SYSPATH") or die("No direct script access.") ?>
+<?php header("X-Frame-Options: SAMEORIGIN"); ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" <?= $theme->html_attributes() ?> xml:lang="en" lang="en">
@@ -10,11 +11,11 @@
<?= $page_title ?>
<? else: ?>
<? if ($theme->item()): ?>
- <?= $theme->item()->title ?>
+ <?= html::purify($theme->item()->title) ?>
<? elseif ($theme->tag()): ?>
<?= t("Photos tagged with %tag_title", array("tag_title" => $theme->tag()->name)) ?>
<? else: /* Not an item, not a tag, no page_title specified. Help! */ ?>
- <?= item::root()->title ?>
+ <?= html::purify(item::root()->title) ?>
<? endif ?>
<? endif ?>
</title>