summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Kinkade <nkinkade@nkinka.de>2010-07-08 00:29:37 +0000
committerNathan Kinkade <nkinkade@nkinka.de>2010-07-08 00:29:37 +0000
commitc83650d83ad8b1f4bda30cac2ae8efa6e1c97287 (patch)
tree482cf980e87cd7c80c28a89bb9395eba6b53026f
parenta0b0b415515bff5f9edd43d373e8e78f3b3f8e4d (diff)
parent9d66783f47636153bf3661d1d89e694dd5188c36 (diff)
Merge branch 'master' of git://github.com/gallery/gallery3
-rw-r--r--.htaccess11
-rw-r--r--README29
-rw-r--r--index.php7
-rw-r--r--installer/install.sql31
-rw-r--r--installer/installer.php66
-rw-r--r--lib/gallery.common.css124
-rw-r--r--lib/gallery.common.js2
-rw-r--r--lib/gallery.dialog.js4
-rw-r--r--lib/uploadify/uploadify.css5
-rw-r--r--modules/comment/controllers/admin_comments.php121
-rw-r--r--modules/comment/controllers/admin_manage_comments.php133
-rw-r--r--modules/comment/controllers/comments.php9
-rw-r--r--modules/comment/helpers/comment.php15
-rw-r--r--modules/comment/helpers/comment_event.php8
-rw-r--r--modules/comment/helpers/comment_installer.php10
-rw-r--r--modules/comment/helpers/comment_rest.php74
-rw-r--r--modules/comment/helpers/comment_rss.php13
-rw-r--r--modules/comment/helpers/comments_rest.php62
-rw-r--r--modules/comment/helpers/item_comments_rest.php50
-rw-r--r--modules/comment/models/comment.php31
-rw-r--r--modules/comment/module.info2
-rw-r--r--modules/comment/tests/Comment_Event_Test.php1
-rw-r--r--modules/comment/tests/Comment_Model_Test.php31
-rw-r--r--modules/comment/views/admin_comments.html.php200
-rw-r--r--modules/comment/views/admin_manage_comments.html.php201
-rw-r--r--modules/comment/views/comment.mrss.php18
-rw-r--r--modules/comment/views/comments.html.php16
-rw-r--r--modules/digibug/helpers/digibug_event.php17
-rw-r--r--modules/exif/helpers/exif.php6
-rw-r--r--modules/exif/lib/exif.php602
-rw-r--r--modules/exif/lib/makers/canon.php15
-rw-r--r--modules/exif/lib/makers/fujifilm.php13
-rw-r--r--modules/exif/lib/makers/gps.php128
-rw-r--r--modules/exif/lib/makers/nikon.php301
-rw-r--r--modules/exif/lib/makers/olympus.php13
-rw-r--r--modules/exif/lib/makers/panasonic.php12
-rw-r--r--modules/exif/lib/makers/sanyo.php13
-rw-r--r--modules/exif/tests/Exif_Test.php4
-rw-r--r--modules/g2_import/controllers/admin_g2_import.php6
-rw-r--r--modules/g2_import/helpers/g2_import.php11
-rw-r--r--modules/gallery/controllers/admin.php10
-rw-r--r--modules/gallery/controllers/albums.php4
-rw-r--r--modules/gallery/controllers/file_proxy.php6
-rw-r--r--modules/gallery/controllers/flash_uploader.php (renamed from modules/gallery/controllers/simple_uploader.php)4
-rw-r--r--modules/gallery/controllers/login.php7
-rw-r--r--modules/gallery/controllers/logout.php11
-rw-r--r--modules/gallery/controllers/packager.php11
-rw-r--r--modules/gallery/controllers/quick.php4
-rw-r--r--modules/gallery/controllers/reauthenticate.php4
-rw-r--r--modules/gallery/css/gallery.css19
-rw-r--r--modules/gallery/helpers/MY_url.php6
-rw-r--r--modules/gallery/helpers/auth.php1
-rw-r--r--modules/gallery/helpers/gallery.php2
-rw-r--r--modules/gallery/helpers/gallery_block.php4
-rw-r--r--modules/gallery/helpers/gallery_event.php91
-rw-r--r--modules/gallery/helpers/gallery_rss.php8
-rw-r--r--modules/gallery/helpers/item.php9
-rw-r--r--modules/gallery/helpers/item_rest.php36
-rw-r--r--modules/gallery/helpers/items_rest.php70
-rw-r--r--modules/gallery/helpers/message.php1
-rw-r--r--modules/gallery/helpers/module.php7
-rw-r--r--modules/gallery/helpers/photo.php2
-rw-r--r--modules/gallery/helpers/site_status.php2
-rw-r--r--modules/gallery/helpers/theme.php16
-rw-r--r--modules/gallery/hooks/init_gallery.php9
-rw-r--r--modules/gallery/js/item_form_delete.js5
-rw-r--r--modules/gallery/js/l10n_client.js22
-rw-r--r--modules/gallery/libraries/MY_Kohana_Exception.php64
-rw-r--r--modules/gallery/libraries/Theme_View.php4
-rw-r--r--modules/gallery/models/item.php20
-rw-r--r--modules/gallery/tests/File_Structure_Test.php9
-rw-r--r--modules/gallery/tests/Gallery_Filters.php5
-rw-r--r--modules/gallery/tests/Item_Helper_Test.php12
-rw-r--r--modules/gallery/tests/Item_Model_Test.php13
-rw-r--r--modules/gallery/tests/Item_Rest_Helper_Test.php10
-rw-r--r--modules/gallery/tests/Items_Rest_Helper_Test.php206
-rw-r--r--modules/gallery/tests/controller_auth_data.txt8
-rw-r--r--modules/gallery/tests/xss_data.txt195
-rw-r--r--modules/gallery/views/admin_modules.html.php2
-rw-r--r--modules/gallery/views/admin_theme_options.html.php34
-rw-r--r--modules/gallery/views/admin_themes_preview.html.php1
-rw-r--r--modules/gallery/views/error_404.html.php7
-rw-r--r--modules/gallery/views/error_admin.html.php272
-rw-r--r--modules/gallery/views/error_cli.txt.php3
-rw-r--r--modules/gallery/views/error_user.html.php42
-rw-r--r--modules/gallery/views/form_uploadify.html.php2
-rw-r--r--modules/gallery/views/kohana/error.php320
-rw-r--r--modules/gallery/views/login_ajax.html.php7
-rw-r--r--modules/gallery_unit_test/controllers/gallery_unit_test.php4
-rw-r--r--modules/image_block/helpers/image_block_block.php2
-rw-r--r--modules/organize/controllers/organize.php169
-rw-r--r--modules/organize/css/organize.css156
-rw-r--r--modules/organize/css/organize_theme.css18
-rw-r--r--modules/organize/helpers/organize_event.php18
-rw-r--r--modules/organize/helpers/organize_installer.php46
-rw-r--r--modules/organize/helpers/organize_theme.php6
-rw-r--r--modules/organize/js/organize.js310
-rw-r--r--modules/organize/lib/Gallery3WebClient.swfbin0 -> 147776 bytes
-rw-r--r--modules/organize/module.info2
-rw-r--r--modules/organize/views/organize_dialog.html.php169
-rw-r--r--modules/organize/views/organize_thumb_grid.html.php22
-rw-r--r--modules/organize/views/organize_tree.html.php29
-rw-r--r--modules/rest/controllers/rest.php76
-rw-r--r--modules/rest/helpers/rest.php25
-rw-r--r--modules/rest/helpers/rest_event.php7
-rw-r--r--modules/rest/helpers/rest_installer.php8
-rw-r--r--modules/rest/libraries/Rest_Exception.php9
-rw-r--r--modules/rest/module.info6
-rw-r--r--modules/rest/tests/Rest_Controller_Test.php15
-rw-r--r--modules/rest/views/error_rest.json.php2
-rw-r--r--modules/rss/views/feed.mrss.php66
-rw-r--r--modules/search/helpers/search.php2
-rw-r--r--modules/slideshow/helpers/slideshow_theme.php2
-rw-r--r--modules/tag/controllers/tags.php2
-rw-r--r--modules/tag/helpers/tag_event.php7
-rw-r--r--modules/tag/helpers/tag_installer.php12
-rw-r--r--modules/tag/helpers/tag_rss.php2
-rw-r--r--modules/tag/helpers/tags_rest.php19
-rw-r--r--modules/tag/module.info2
-rw-r--r--modules/tag/tests/Tags_Rest_Helper_Test.php2
-rw-r--r--modules/user/views/admin_users.html.php2
-rw-r--r--modules/watermark/controllers/admin_watermarks.php2
-rw-r--r--robots.txt1
-rw-r--r--themes/admin_wind/css/screen.css25
-rw-r--r--themes/admin_wind/css/themeroller/images/ui-bg_flat_0_aaaaaa_40x100.png (renamed from lib/themeroller/images/ui-bg_flat_0_aaaaaa_40x100.png)bin180 -> 180 bytes
-rw-r--r--themes/admin_wind/css/themeroller/images/ui-bg_flat_55_fbec88_40x100.png (renamed from lib/themeroller/images/ui-bg_flat_55_fbec88_40x100.png)bin182 -> 182 bytes
-rw-r--r--themes/admin_wind/css/themeroller/images/ui-bg_glass_75_d0e5f5_1x400.png (renamed from lib/themeroller/images/ui-bg_glass_75_d0e5f5_1x400.png)bin124 -> 124 bytes
-rw-r--r--themes/admin_wind/css/themeroller/images/ui-bg_glass_85_dfeffc_1x400.png (renamed from lib/themeroller/images/ui-bg_glass_85_dfeffc_1x400.png)bin123 -> 123 bytes
-rw-r--r--themes/admin_wind/css/themeroller/images/ui-bg_glass_95_fef1ec_1x400.png (renamed from lib/themeroller/images/ui-bg_glass_95_fef1ec_1x400.png)bin119 -> 119 bytes
-rw-r--r--themes/admin_wind/css/themeroller/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png (renamed from lib/themeroller/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png)bin4033 -> 4033 bytes
-rw-r--r--themes/admin_wind/css/themeroller/images/ui-bg_inset-hard_100_f5f8f9_1x100.png (renamed from lib/themeroller/images/ui-bg_inset-hard_100_f5f8f9_1x100.png)bin104 -> 104 bytes
-rw-r--r--themes/admin_wind/css/themeroller/images/ui-bg_inset-hard_100_fcfdfd_1x100.png (renamed from lib/themeroller/images/ui-bg_inset-hard_100_fcfdfd_1x100.png)bin88 -> 88 bytes
-rw-r--r--themes/admin_wind/css/themeroller/images/ui-icons_217bc0_256x240.png (renamed from lib/themeroller/images/ui-icons_217bc0_256x240.png)bin7638 -> 7638 bytes
-rw-r--r--themes/admin_wind/css/themeroller/images/ui-icons_2e83ff_256x240.png (renamed from lib/themeroller/images/ui-icons_2e83ff_256x240.png)bin7626 -> 7626 bytes
-rw-r--r--themes/admin_wind/css/themeroller/images/ui-icons_469bdd_256x240.png (renamed from lib/themeroller/images/ui-icons_469bdd_256x240.png)bin5399 -> 5399 bytes
-rw-r--r--themes/admin_wind/css/themeroller/images/ui-icons_6da8d5_256x240.png (renamed from lib/themeroller/images/ui-icons_6da8d5_256x240.png)bin8447 -> 8447 bytes
-rw-r--r--themes/admin_wind/css/themeroller/images/ui-icons_cd0a0a_256x240.png (renamed from lib/themeroller/images/ui-icons_cd0a0a_256x240.png)bin4379 -> 4379 bytes
-rw-r--r--themes/admin_wind/css/themeroller/images/ui-icons_d8e7f3_256x240.png (renamed from lib/themeroller/images/ui-icons_d8e7f3_256x240.png)bin4379 -> 4379 bytes
-rw-r--r--themes/admin_wind/css/themeroller/images/ui-icons_f9bd01_256x240.png (renamed from lib/themeroller/images/ui-icons_f9bd01_256x240.png)bin4379 -> 4379 bytes
-rw-r--r--themes/admin_wind/css/themeroller/ui.base.css (renamed from lib/themeroller/ui.base.css)0
-rw-r--r--themes/admin_wind/css/themeroller/ui.core.css (renamed from lib/themeroller/ui.core.css)0
-rw-r--r--themes/admin_wind/css/themeroller/ui.datepicker.css (renamed from lib/themeroller/ui.datepicker.css)0
-rw-r--r--themes/admin_wind/css/themeroller/ui.dialog.css (renamed from lib/themeroller/ui.dialog.css)0
-rw-r--r--themes/admin_wind/css/themeroller/ui.progressbar.css (renamed from lib/themeroller/ui.progressbar.css)0
-rw-r--r--themes/admin_wind/css/themeroller/ui.resizable.css (renamed from lib/themeroller/ui.resizable.css)0
-rw-r--r--themes/admin_wind/css/themeroller/ui.tabs.css (renamed from lib/themeroller/ui.tabs.css)0
-rw-r--r--themes/admin_wind/css/themeroller/ui.theme.css (renamed from lib/themeroller/ui.theme.css)18
-rw-r--r--themes/admin_wind/js/ui.init.js6
-rw-r--r--themes/admin_wind/views/admin.html.php6
-rw-r--r--themes/wind/css/screen.css11
-rw-r--r--themes/wind/css/themeroller/images/ui-bg_flat_0_aaaaaa_40x100.pngbin0 -> 180 bytes
-rw-r--r--themes/wind/css/themeroller/images/ui-bg_flat_55_fbec88_40x100.pngbin0 -> 182 bytes
-rw-r--r--themes/wind/css/themeroller/images/ui-bg_glass_75_d0e5f5_1x400.pngbin0 -> 124 bytes
-rw-r--r--themes/wind/css/themeroller/images/ui-bg_glass_85_dfeffc_1x400.pngbin0 -> 123 bytes
-rw-r--r--themes/wind/css/themeroller/images/ui-bg_glass_95_fef1ec_1x400.pngbin0 -> 119 bytes
-rw-r--r--themes/wind/css/themeroller/images/ui-bg_gloss-wave_55_5c9ccc_500x100.pngbin0 -> 4033 bytes
-rw-r--r--themes/wind/css/themeroller/images/ui-bg_inset-hard_100_f5f8f9_1x100.pngbin0 -> 104 bytes
-rw-r--r--themes/wind/css/themeroller/images/ui-bg_inset-hard_100_fcfdfd_1x100.pngbin0 -> 88 bytes
-rw-r--r--themes/wind/css/themeroller/images/ui-icons_217bc0_256x240.pngbin0 -> 7638 bytes
-rw-r--r--themes/wind/css/themeroller/images/ui-icons_2e83ff_256x240.pngbin0 -> 7626 bytes
-rw-r--r--themes/wind/css/themeroller/images/ui-icons_469bdd_256x240.pngbin0 -> 5399 bytes
-rw-r--r--themes/wind/css/themeroller/images/ui-icons_6da8d5_256x240.pngbin0 -> 8447 bytes
-rw-r--r--themes/wind/css/themeroller/images/ui-icons_cd0a0a_256x240.pngbin0 -> 4379 bytes
-rw-r--r--themes/wind/css/themeroller/images/ui-icons_d8e7f3_256x240.pngbin0 -> 4379 bytes
-rw-r--r--themes/wind/css/themeroller/images/ui-icons_f9bd01_256x240.pngbin0 -> 4379 bytes
-rw-r--r--themes/wind/css/themeroller/ui.base.css7
-rw-r--r--themes/wind/css/themeroller/ui.core.css37
-rw-r--r--themes/wind/css/themeroller/ui.datepicker.css62
-rw-r--r--themes/wind/css/themeroller/ui.dialog.css13
-rw-r--r--themes/wind/css/themeroller/ui.progressbar.css4
-rw-r--r--themes/wind/css/themeroller/ui.resizable.css13
-rw-r--r--themes/wind/css/themeroller/ui.tabs.css9
-rw-r--r--themes/wind/css/themeroller/ui.theme.css243
-rw-r--r--themes/wind/js/ui.init.js6
-rw-r--r--themes/wind/views/album.html.php2
-rw-r--r--themes/wind/views/movie.html.php5
-rw-r--r--themes/wind/views/page.html.php10
-rw-r--r--themes/wind/views/photo.html.php3
178 files changed, 3409 insertions, 2313 deletions
diff --git a/.htaccess b/.htaccess
index 1d8bcb34..404b43f5 100644
--- a/.htaccess
+++ b/.htaccess
@@ -17,6 +17,17 @@
SecFilterScanPOST Off
</IfModule>
+# Increase security by uncommenting this block. It keeps browsers
+# from seeing support files that they shouldn't have access to. We
+# comment this out because Apache2 requires some minor configuration
+# in order for you to use it. You must specify "AllowOverride Limit"
+# in your Apache2 config file before you uncomment this block or
+# you'll get an "Internal Server Error".
+#
+# <FilesMatch "(\.(class|fla|inc|sql|txt|gitignore)|(README|LICENSE))$">
+# Order allow,deny
+# </FilesMatch>
+
# Improve performance by uncommenting this block. It tells the
# browser that your images don't change very often so it won't keep
# asking for them. If you get an error after uncommenting this, make
diff --git a/README b/README
index b3426212..67efff4b 100644
--- a/README
+++ b/README
@@ -1,3 +1,5 @@
+Gallery 3.0 (code name "Santa Fe")
+
ABOUT:
Gallery 3 is a web based software product that lets you manage your
photos on your own website. You must have your own website with PHP
@@ -7,26 +9,19 @@ interface.
SECURITY (& INTENDED AUDIENCE):
-This is the third and final beta release of Gallery 3.0 and while it's
-not a finished product, it's heading into the home stretch. You can
-install it on public websites, but remember that until the final
-release is out, we make no guarantees that it won't do bad things.
+This is the second (and hopefully final) release candidate of Gallery
+3.0. We're putting it out there so that we can find out if we
+overlooked any small things. We expect the final version to be
+virtually identical. You can install it on public websites and use it
+freely -- we recommend it!
Note:
- We've contracted a professional security audit, received their results
- and resolved all the really dire issues they found. There are still some
- issues, but they are more along the lines of "you should ask for the old
- password as a confirmation when you let users change their password".
- Ie, they're issues but they're not really bad. We'll take care of them
- before the final release.
- - Most of the key features are in, but some of them (notably the "add from
- server" and "organize album" features) are probably going to be completely
- rewritten.
+ and resolved all the issues they found.
- You can upgrade from beta 1, but not from alpha releases.
-The intended audience of this release is folks who are willing to live
-a little bit on the edge. We'll do our best to take care of your data
-and your security, but we might screw it up here or there. We welcome
+This version is intended for broad distribution. We stand ready to
+support the product and help you to make the most of it. We welcome
theme and module developers to play with this release and start
turning out slick new designs for our happy users.
@@ -61,7 +56,7 @@ INSTALLATION FROM THE COMMAND LINE:
BUGS?
Go to http://apps.sourceforge.net/trac/gallery/ click the "login" link
and log in with your SourceForge username and password, then click the
-"new ticket" button. Mark any issues you find with the "Beta 2"
+"new ticket" button. Mark any issues you find with the "3.0"
milestone and we'll try to get 'em done for the next release.
@@ -70,5 +65,3 @@ QUESTIONS, PROBLEMS:
- Post to the Gallery 3 forums: http://gallery.menalto.com/forum/96
- Email gallery-devel@lists.sourceforge.net
-
-
diff --git a/index.php b/index.php
index 6ef215ab..4ef3d943 100644
--- a/index.php
+++ b/index.php
@@ -64,9 +64,12 @@ if (PHP_SAPI == "cli") {
case "test":
array_splice($_SERVER["argv"], 1, 1, "gallery_unit_test");
define("TEST_MODE", 1);
- @mkdir("test/var/logs", 0777, true);
+ if (!is_dir("test/var")) {
+ @mkdir("test/var", 0777, true);
+ @mkdir("test/var/logs", 0777, true);
+ }
+ @copy("var/database.php", "test/var/database.php");
define("VARPATH", realpath("test/var") . "/");
- @copy("var/database.php", VARPATH . "database.php");
break;
default:
diff --git a/installer/install.sql b/installer/install.sql
index ebe3651d..687da129 100644
--- a/installer/install.sql
+++ b/installer/install.sql
@@ -238,17 +238,18 @@ CREATE TABLE {modules} (
`version` int(9) default NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
-) AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;
+) AUTO_INCREMENT=11 DEFAULT CHARSET=utf8;
SET character_set_client = @saved_cs_client;
INSERT INTO {modules} VALUES (1,1,'gallery',30);
INSERT INTO {modules} VALUES (2,1,'user',3);
-INSERT INTO {modules} VALUES (3,1,'comment',2);
+INSERT INTO {modules} VALUES (3,1,'comment',3);
INSERT INTO {modules} VALUES (4,1,'organize',1);
INSERT INTO {modules} VALUES (5,1,'info',1);
-INSERT INTO {modules} VALUES (6,1,'rss',1);
-INSERT INTO {modules} VALUES (7,1,'search',1);
-INSERT INTO {modules} VALUES (8,1,'slideshow',2);
-INSERT INTO {modules} VALUES (9,1,'tag',1);
+INSERT INTO {modules} VALUES (6,1,'rest',3);
+INSERT INTO {modules} VALUES (7,1,'rss',1);
+INSERT INTO {modules} VALUES (8,1,'search',1);
+INSERT INTO {modules} VALUES (9,1,'slideshow',2);
+INSERT INTO {modules} VALUES (10,1,'tag',2);
DROP TABLE IF EXISTS {outgoing_translations};
SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
@@ -308,7 +309,7 @@ SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
CREATE TABLE {tags} (
`id` int(9) NOT NULL auto_increment,
- `name` varchar(64) NOT NULL,
+ `name` varchar(128) NOT NULL,
`count` int(10) unsigned NOT NULL default '0',
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
@@ -345,6 +346,18 @@ CREATE TABLE {themes} (
SET character_set_client = @saved_cs_client;
INSERT INTO {themes} VALUES (1,'wind',1);
INSERT INTO {themes} VALUES (2,'admin_wind',1);
+DROP TABLE IF EXISTS {user_access_keys};
+SET @saved_cs_client = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE {user_access_keys} (
+ `id` int(9) NOT NULL auto_increment,
+ `user_id` int(9) NOT NULL,
+ `access_key` char(32) NOT NULL,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `access_key` (`access_key`),
+ UNIQUE KEY `user_id` (`user_id`)
+) DEFAULT CHARSET=utf8;
+SET character_set_client = @saved_cs_client;
DROP TABLE IF EXISTS {users};
SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
@@ -378,7 +391,7 @@ CREATE TABLE {vars} (
`value` text,
PRIMARY KEY (`id`),
UNIQUE KEY `module_name` (`module_name`,`name`)
-) AUTO_INCREMENT=40 DEFAULT CHARSET=utf8;
+) AUTO_INCREMENT=42 DEFAULT CHARSET=utf8;
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');
@@ -400,6 +413,8 @@ INSERT INTO {vars} VALUES (NULL,'gallery','blocks_dashboard_center','a:3:{i:6;a:
INSERT INTO {vars} VALUES (NULL,'gallery','choose_default_tookit','1');
INSERT INTO {vars} VALUES (NULL,'gallery','identity_provider','user');
INSERT INTO {vars} VALUES (NULL,'user','mininum_password_length','5');
+INSERT INTO {vars} VALUES (NULL,'comment','access_permissions','everybody');
INSERT INTO {vars} VALUES (NULL,'comment','spam_caught','0');
+INSERT INTO {vars} VALUES (NULL,'rest','allow_guest_access','0');
INSERT INTO {vars} VALUES (NULL,'gallery','blocks_site_sidebar','a:3:{i:9;a:2:{i:0;s:4:\"info\";i:1;s:8:\"metadata\";}i:10;a:2:{i:0;s:3:\"rss\";i:1;s:9:\"rss_feeds\";}i:11;a:2:{i:0;s:3:\"tag\";i:1;s:3:\"tag\";}}');
INSERT INTO {vars} VALUES (NULL,'slideshow','max_scale','0');
diff --git a/installer/installer.php b/installer/installer.php
index bd5fbff1..53a5e3db 100644
--- a/installer/installer.php
+++ b/installer/installer.php
@@ -187,45 +187,49 @@ class installer {
}
static function check_environment() {
- if (!function_exists("mysql_query") && !function_exists("mysqli_set_charset")) {
- $errors[] = "Gallery 3 requires a MySQL database, but PHP doesn't have either the <a href=\"http://php.net/mysql\">MySQL</a> or the <a href=\"http://php.net/mysqli\">MySQLi</a> extension.";
- }
+ if (!function_exists("mysql_query") && !function_exists("mysqli_set_charset")) {
+ $errors[] = "Gallery 3 requires a MySQL database, but PHP doesn't have either the <a href=\"http://php.net/mysql\">MySQL</a> or the <a href=\"http://php.net/mysqli\">MySQLi</a> extension.";
+ }
- if (!@preg_match("/^.$/u", utf8_encode("\xF1"))) {
- $errors[] = "PHP is missing <a href=\"http://php.net/pcre\">Perl-Compatible Regular Expression</a> support.";
- }
+ if (!@preg_match("/^.$/u", utf8_encode("\xF1"))) {
+ $errors[] = "PHP is missing <a href=\"http://php.net/pcre\">Perl-Compatible Regular Expression</a> support.";
+ }
- if (!(function_exists("spl_autoload_register"))) {
- $errors[] = "PHP is missing <a href=\"http://php.net/spl\">Standard PHP Library (SPL)</a> support";
- }
+ if (!(function_exists("spl_autoload_register"))) {
+ $errors[] = "PHP is missing <a href=\"http://php.net/spl\">Standard PHP Library (SPL)</a> support";
+ }
- if (!(class_exists("ReflectionClass"))) {
- $errors[] = "PHP is missing <a href=\"http://php.net/reflection\">reflection</a> support";
- }
+ if (!(class_exists("ReflectionClass"))) {
+ $errors[] = "PHP is missing <a href=\"http://php.net/reflection\">reflection</a> support";
+ }
- if (!(function_exists("filter_list"))) {
- $errors[] = "PHP is missing the <a href=\"http://php.net/filter\">filter extension</a>";
- }
+ if (!(function_exists("filter_list"))) {
+ $errors[] = "PHP is missing the <a href=\"http://php.net/filter\">filter extension</a>";
+ }
- if (!(extension_loaded("iconv"))) {
- $errors[] = "PHP is missing the <a href=\"http://php.net/iconv\">iconv extension</a>";
- }
+ if (!(extension_loaded("iconv"))) {
+ $errors[] = "PHP is missing the <a href=\"http://php.net/iconv\">iconv extension</a>";
+ }
- if (!(extension_loaded("simplexml"))) {
- $errors[] = "PHP is missing the <a href=\"http://php.net/simplexml\">SimpleXML extension</a>";
- }
+ if (!(extension_loaded("simplexml"))) {
+ $errors[] = "PHP is missing the <a href=\"http://php.net/simplexml\">SimpleXML extension</a>";
+ }
- if (!extension_loaded("mbstring")) {
- $errors[] = "PHP is missing the <a href=\"http://php.net/mbstring\">mbstring extension</a>";
- } else if (ini_get("mbstring.func_overload") & MB_OVERLOAD_STRING) {
- $errors[] = "The <a href=\"http://php.net/mbstring\">mbstring extension</a> is overloading PHP's native string functions. Please disable it.";
- }
+ if (!extension_loaded("mbstring")) {
+ $errors[] = "PHP is missing the <a href=\"http://php.net/mbstring\">mbstring extension</a>";
+ } else if (ini_get("mbstring.func_overload") & MB_OVERLOAD_STRING) {
+ $errors[] = "The <a href=\"http://php.net/mbstring\">mbstring extension</a> is overloading PHP's native string functions. Please disable it.";
+ }
- if (!function_exists("json_encode")) {
- $errors[] = "PHP is missing the <a href=\"http://php.net/manual/en/book.json.php\">JavaScript Object Notation (JSON) extension</a>. Please install it.";
- }
+ if (!function_exists("json_encode")) {
+ $errors[] = "PHP is missing the <a href=\"http://php.net/manual/en/book.json.php\">JavaScript Object Notation (JSON) extension</a>. Please install it.";
+ }
- return @$errors;
-}
+ if (!ini_get("short_open_tag")) {
+ $errors[] = "Gallery requires <a href=\"http://php.net/manual/en/ini.core.php\">short_open_tag</a> to be on. Please enable it in your php.ini.";
+ }
+
+ return @$errors;
+ }
}
diff --git a/lib/gallery.common.css b/lib/gallery.common.css
index 31988b67..2bb5b6e2 100644
--- a/lib/gallery.common.css
+++ b/lib/gallery.common.css
@@ -363,13 +363,11 @@ form .g-error {
.g-loading-large,
.g-dialog-loading-large {
- background: #e8e8e8 url('images/loading-large.gif') no-repeat center center;
- font-size: 0;
+ background: #e8e8e8 url('images/loading-large.gif') no-repeat center center !important;
}
.g-loading-small {
- background: #e8e8e8 url('images/loading-small.gif') no-repeat center center;
- font-size: 0;
+ background: #e8e8e8 url('images/loading-small.gif') no-repeat center center !important;
}
/** *******************************************************************
@@ -454,6 +452,10 @@ ul.sf-menu li li li.sfHover ul {
-moz-outline-style: none;
}
+button {
+ padding: 2px 4px 2px 4px;
+}
+
/* jQuery UI ThemeRoller buttons ~~~~~~~~~ */
.g-buttonset {
@@ -690,18 +692,95 @@ div#g-action-status {
}
.rtl input.checkbox {
- margin-right: .4em;
+ margin-left: .4em;
}
-.rtl #g-admin-comment-button {
+.rtl #g-add-comment {
right: inherit;
left: 0;
}
+.rtl .ui-icon-left .ui-icon {
+ margin-left: .2em;
+}
+
+.rtl .ui-icon-right .ui-icon {
+ margin-right: .2em;
+}
+
+/* RTL Corner radius ~~~~~~~~~~~~~~~~~~~~~~ */
+.rtl .g-buttonset .ui-corner-tl {
+ -moz-border-radius-topleft: 0;
+ -webkit-border-top-left-radius: 0;
+ border-top-left-radius: 0;
+ -moz-border-radius-topright: 5px !important;
+ -webkit-border-top-right-radius: 5px !important;
+ border-top-right-radius: 5px !important;
+}
+
+.rtl .g-buttonset .ui-corner-tr {
+ -moz-border-radius-topright: 0;
+ -webkit-border-top-right-radius: 0;
+ border-top-right-radius: 0;
+ -moz-border-radius-topleft: 5px !important;
+ -webkit-border-top-left-radius: 5px !important;
+ border-top-left-radius: 5px !important;
+}
+
+.rtl .g-buttonset .ui-corner-bl {
+ -moz-border-radius-bottomleft: 0;
+ -webkit-border-bottom-left-radius: 0;
+ border-bottom-left-radius: 0;
+ -moz-border-radius-bottomright: 5px !important;
+ -webkit-border-bottom-right-radius: 5px !important;
+ border-bottom-right-radius: 5px !important;
+}
+
+.rtl .g-buttonset .ui-corner-br {
+ -moz-border-radius-bottomright: 0;
+ -webkit-border-bottom-right-radius: 0;
+ border-bottom-right-radius: 0;
+ -moz-border-radius-bottomleft: 5px !important;
+ -webkit-border-bottom-left-radius: 5px !important;
+ border-bottom-left-radius: 5px !important;
+}
+
+.rtl .g-buttonset .ui-corner-right,
+.rtl .ui-progressbar .ui-corner-right {
+ -moz-border-radius-topright: 0;
+ -webkit-border-top-right-radius: 0;
+ border-top-right-radius: 0;
+ -moz-border-radius-topleft: 5px !important;
+ -webkit-border-top-left-radius: 5px !important;
+ border-top-left-radius: 5px !important;
+ -moz-border-radius-bottomright: 0;
+ -webkit-border-bottom-right-radius: 0;
+ border-bottom-right-radius: 0;
+ -moz-border-radius-bottomleft: 5px !important;
+ -webkit-border-bottom-left-radius: 5px !important;
+ border-bottom-left-radius: 5px !important;
+}
+
+.rtl .g-buttonset .ui-corner-left,
+.rtl .ui-progressbar .ui-corner-left {
+ -moz-border-radius-topleft: 0;
+ -webkit-border-top-left-radius: 0;
+ border-top-left-radius: 0;
+ -moz-border-radius-topright: 5px !important;
+ -webkit-border-top-right-radius: 5px !important;
+ border-top-right-radius: 5px !important;
+ -moz-border-radius-bottomleft: 0;
+ -webkit-border-bottom-left-radius: 0;
+ border-bottom-left-radius: 0;
+ -moz-border-radius-bottomright: 5px !important;
+ -webkit-border-bottom-right-radius: 5px !important;
+ border-bottom-right-radius: 5px !important;
+}
+
/* RTL Superfish ~~~~~~~~~~~~~~~~~~~~~~~~~ */
.rtl .sf-menu a {
- border-left: none;
+ border-left: none;
border-right:1px solid #fff;
}
@@ -712,7 +791,7 @@ div#g-action-status {
.rtl .sf-sub-indicator {
left: .75em !important;
- right: auto;
+ right: auto;
background: url('superfish/images/arrows-ffffff-rtl.png') no-repeat -10px -100px; /* 8-bit indexed alpha png. IE6 gets solid image only */
}
.rtl a > .sf-sub-indicator { /* give all except IE6 the correct values */
@@ -743,27 +822,54 @@ div#g-action-status {
.rtl .sf-menu li:hover ul,
.rtl .sf-menu li.sfHover ul {
right: 0;
+ left: auto;
}
.rtl ul.sf-menu li li:hover ul,
.rtl ul.sf-menu li li.sfHover ul {
right: 12em; /* match ul width */
+ left: auto;
}
.rtl ul.sf-menu li li li:hover ul,
.rtl ul.sf-menu li li li.sfHover ul {
right: 12em; /* match ul width */
+ left: auto;
}
/*** shadows for all but IE6 ***/
.rtl .sf-shadow ul {
background: url('superfish/images/shadow.png') no-repeat bottom left;
padding: 0 0 9px 8px;
- -moz-border-radius-bottomright: 17px;
+ border-top-right-radius: 0;
+ border-bottom-left-radius: 0;
+ -moz-border-radius-topright: 0;
+ -moz-border-radius-bottomleft: 0;
+ -webkit-border-top-right-radius: 0;
+ -webkit-border-bottom-left-radius: 0;
-moz-border-radius-topleft: 17px;
+ -moz-border-radius-bottomright: 17px;
-webkit-border-top-left-radius: 17px;
-webkit-border-bottom-right-radius: 17px;
+ border-top-left-radius: 17px;
+ border-bottom-right-radius: 17px;
+}
+
+/* RTL ThemeRoller ~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+.rtl .ui-dialog .ui-dialog-titlebar {
+ padding: 0.5em 1em 0.3em 0.3em;
+}
+
+.rtl .ui-dialog .ui-dialog-title {
+ float: right;
+}
+
+.rtl .ui-dialog .ui-dialog-titlebar-close {
+ left: 0.3em;
+ right: auto;
}
+
/* RTL paginator ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
.rtl .g-paginator .g-info {
diff --git a/lib/gallery.common.js b/lib/gallery.common.js
index eb57c86c..a9aa6b2c 100644
--- a/lib/gallery.common.js
+++ b/lib/gallery.common.js
@@ -61,7 +61,7 @@
size = "small";
break;
}
- $(this).toggleClass("g-loading" + size);
+ $(this).toggleClass("g-loading-" + size);
});
};
diff --git a/lib/gallery.dialog.js b/lib/gallery.dialog.js
index 3587108c..6ec8c634 100644
--- a/lib/gallery.dialog.js
+++ b/lib/gallery.dialog.js
@@ -40,6 +40,7 @@
$(".ui-dialog-titlebar").remove();
} else if ($("#g-dialog h1").length) {
$("#g-dialog").dialog('option', 'title', $("#g-dialog h1:eq(0)").html());
+ $("#g-dialog h1:eq(0)").hide();
} else if ($("#g-dialog fieldset legend").length) {
$("#g-dialog").dialog('option', 'title', $("#g-dialog fieldset legend:eq(0)").html());
}
@@ -114,7 +115,8 @@
},
success: function(data) {
if (data.form) {
- $("#g-dialog form").replaceWith(data.form);
+ var formData = unescape(data.form);
+ $("#g-dialog form").replaceWith(formData);
$("#g-dialog form :submit").removeClass("ui-state-disabled")
.attr("disabled", null);
self._ajaxify_dialog();
diff --git a/lib/uploadify/uploadify.css b/lib/uploadify/uploadify.css
index a0279443..7eaa9e93 100644
--- a/lib/uploadify/uploadify.css
+++ b/lib/uploadify/uploadify.css
@@ -51,3 +51,8 @@ THE SOFTWARE.
width: 1px;
height: 3px;
}
+
+/* RTL support ~~~~~~~~~~~~~~~~~~~~~~~~~ */
+.rtl .uploadifyQueueItem .cancel {
+ float: left;
+} \ No newline at end of file
diff --git a/modules/comment/controllers/admin_comments.php b/modules/comment/controllers/admin_comments.php
index 68794638..fda3873c 100644
--- a/modules/comment/controllers/admin_comments.php
+++ b/modules/comment/controllers/admin_comments.php
@@ -18,116 +18,35 @@
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
class Admin_Comments_Controller extends Admin_Controller {
- private static $items_per_page = 20;
-
public function index() {
- // Get rid of old deleted/spam comments once in a while
- db::build()
- ->delete("comments")
- ->where("state", "IN", array("deleted", "spam"))
- ->where("updated", "<", "UNIX_TIMESTAMP() - 86400 * 7")
- ->execute();
-
- // Redirect to the appropriate queue
- url::redirect("admin/comments/queue/unpublished");
- }
-
- public function menu_labels() {
- $menu = $this->_menu($this->_counts());
- print json_encode(array((string) $menu->get("unpublished")->label,
- (string) $menu->get("published")->label,
- (string) $menu->get("spam")->label,
- (string) $menu->get("deleted")->label));
- }
-
- public function queue($state) {
- $page = max(Input::instance()->get("page"), 1);
-
$view = new Admin_View("admin.html");
- $view->page_title = t("Manage comments");
+ $view->page_title = t("Comment settings");
$view->content = new View("admin_comments.html");
- $view->content->counts = $this->_counts();
- $view->content->menu = $this->_menu($view->content->counts);
- $view->content->state = $state;
- $view->content->comments = ORM::factory("comment")
- ->order_by("created", "DESC")
- ->where("state", "=", $state)
- ->limit(self::$items_per_page, ($page - 1) * self::$items_per_page)
- ->find_all();
- $view->content->pager = new Pagination();
- $view->content->pager->initialize(
- array("query_string" => "page",
- "total_items" => $view->content->counts->$state,
- "items_per_page" => self::$items_per_page,
- "style" => "classic"));
-
+ $view->content->form = $this->_get_admin_form();
print $view;
}
- private function _menu($counts) {
- return Menu::factory("root")
- ->append(Menu::factory("link")
- ->id("unpublished")
- ->label(t2("Awaiting Moderation (%count)",
- "Awaiting Moderation (%count)",
- $counts->unpublished))
- ->url(url::site("admin/comments/queue/unpublished")))
- ->append(Menu::factory("link")
- ->id("published")
- ->label(t2("Approved (%count)",
- "Approved (%count)",
- $counts->published))
- ->url(url::site("admin/comments/queue/published")))
- ->append(Menu::factory("link")
- ->id("spam")
- ->label(t2("Spam (%count)",
- "Spam (%count)",
- $counts->spam))
- ->url(url::site("admin/comments/queue/spam")))
- ->append(Menu::factory("link")
- ->id("deleted")
- ->label(t2("Recently Deleted (%count)",
- "Recently Deleted (%count)",
- $counts->deleted))
- ->url(url::site("admin/comments/queue/deleted")));
- }
-
- private function _counts() {
- $counts = new stdClass();
- $counts->unpublished = 0;
- $counts->published = 0;
- $counts->spam = 0;
- $counts->deleted = 0;
- foreach (db::build()
- ->select("state")
- ->select(array("c" => 'COUNT("*")'))
- ->from("comments")
- ->group_by("state")
- ->execute() as $row) {
- $counts->{$row->state} = $row->c;
- }
- return $counts;
- }
-
- public function set_state($id, $state) {
+ public function save() {
access::verify_csrf();
-
- $comment = ORM::factory("comment", $id);
- $orig = clone $comment;
- if ($comment->loaded()) {
- $comment->state = $state;
- $comment->save();
- }
+ $form = $this->_get_admin_form();
+ $form->validate();
+ module::set_var("comment", "access_permissions",
+ $form->comment_settings->access_permissions->value);
+ message::success(t("Comment settings updated"));
+ url::redirect("admin/comments");
}
- public function delete_all_spam() {
- access::verify_csrf();
-
- db::build()
- ->delete("comments")
- ->where("state", "=", "spam")
- ->execute();
- url::redirect("admin/comments/queue/spam");
+ private function _get_admin_form() {
+ $form = new Forge("admin/comments/save", "", "post",
+ array("id" => "g-comments-admin-form"));
+ $comment_settings = $form->group("comment_settings")->label(t("Permissions"));
+ $comment_settings->dropdown("access_permissions")
+ ->label(t("Who can leave comments?"))
+ ->options(array("everybody" => t("Everybody"),
+ "registered_users" => t("Only registered users")))
+ ->selected(module::get_var("comment", "access_permissions"));
+ $comment_settings->submit("save")->value(t("Save"));
+ return $form;
}
}
diff --git a/modules/comment/controllers/admin_manage_comments.php b/modules/comment/controllers/admin_manage_comments.php
new file mode 100644
index 00000000..bc1c9e64
--- /dev/null
+++ b/modules/comment/controllers/admin_manage_comments.php
@@ -0,0 +1,133 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2010 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_Manage_Comments_Controller extends Admin_Controller {
+ private static $items_per_page = 20;
+
+ public function index() {
+ // Get rid of old deleted/spam comments once in a while
+ db::build()
+ ->delete("comments")
+ ->where("state", "IN", array("deleted", "spam"))
+ ->where("updated", "<", "UNIX_TIMESTAMP() - 86400 * 7")
+ ->execute();
+
+ // Redirect to the appropriate queue
+ url::redirect("admin/manage_comments/queue/unpublished");
+ }
+
+ public function menu_labels() {
+ $menu = $this->_menu($this->_counts());
+ print json_encode(array((string) $menu->get("unpublished")->label,
+ (string) $menu->get("published")->label,
+ (string) $menu->get("spam")->label,
+ (string) $menu->get("deleted")->label));
+ }
+
+ public function queue($state) {
+ $page = max(Input::instance()->get("page"), 1);
+
+ $view = new Admin_View("admin.html");
+ $view->page_title = t("Manage comments");
+ $view->content = new View("admin_manage_comments.html");
+ $view->content->counts = $this->_counts();
+ $view->content->menu = $this->_menu($view->content->counts);
+ $view->content->state = $state;
+ $view->content->comments = ORM::factory("comment")
+ ->order_by("created", "DESC")
+ ->where("state", "=", $state)
+ ->limit(self::$items_per_page, ($page - 1) * self::$items_per_page)
+ ->find_all();
+ $view->content->pager = new Pagination();
+ $view->content->pager->initialize(
+ array("query_string" => "page",
+ "total_items" => $view->content->counts->$state,
+ "items_per_page" => self::$items_per_page,
+ "style" => "classic"));
+
+ print $view;
+ }
+
+ private function _menu($counts) {
+ return Menu::factory("root")
+ ->append(Menu::factory("link")
+ ->id("unpublished")
+ ->label(t2("Awaiting Moderation (%count)",
+ "Awaiting Moderation (%count)",
+ $counts->unpublished))
+ ->url(url::site("admin/manage_comments/queue/unpublished")))
+ ->append(Menu::factory("link")
+ ->id("published")
+ ->label(t2("Approved (%count)",
+ "Approved (%count)",
+ $counts->published))
+ ->url(url::site("admin/manage_comments/queue/published")))
+ ->append(Menu::factory("link")
+ ->id("spam")
+ ->label(t2("Spam (%count)",
+ "Spam (%count)",
+ $counts->spam))
+ ->url(url::site("admin/manage_comments/queue/spam")))
+ ->append(Menu::factory("link")
+ ->id("deleted")
+ ->label(t2("Recently Deleted (%count)",
+ "Recently Deleted (%count)",
+ $counts->deleted))
+ ->url(url::site("admin/manage_comments/queue/deleted")));
+ }
+
+ private function _counts() {
+ $counts = new stdClass();
+ $counts->unpublished = 0;
+ $counts->published = 0;
+ $counts->spam = 0;
+ $counts->deleted = 0;
+ foreach (db::build()
+ ->select("state")
+ ->select(array("c" => 'COUNT("*")'))
+ ->from("comments")
+ ->group_by("state")
+ ->execute() as $row) {
+ $counts->{$row->state} = $row->c;
+ }
+ return $counts;
+ }
+
+ public function set_state($id, $state) {
+ access::verify_csrf();
+
+ $comment = ORM::factory("comment", $id);
+ $orig = clone $comment;
+ if ($comment->loaded()) {
+ $comment->state = $state;
+ $comment->save();
+ }
+ }
+
+ public function delete_all_spam() {
+ access::verify_csrf();
+
+ db::build()
+ ->delete("comments")
+ ->where("state", "=", "spam")
+ ->execute();
+ url::redirect("admin/manage_comments/queue/spam");
+ }
+}
+
diff --git a/modules/comment/controllers/comments.php b/modules/comment/controllers/comments.php
index 9e0f86d2..c42ad24e 100644
--- a/modules/comment/controllers/comments.php
+++ b/modules/comment/controllers/comments.php
@@ -24,6 +24,9 @@ class Comments_Controller extends Controller {
public function create($id) {
$item = ORM::factory("item", $id);
access::required("view", $item);
+ if (!comment::can_comment()) {
+ access::forbidden();
+ }
$form = comment::get_add_form($item);
try {
@@ -58,6 +61,7 @@ class Comments_Controller extends Controller {
"view" => (string) $view,
"form" => (string) comment::get_add_form($item)));
} else {
+ $form = comment::prefill_add_form($form);
print json_encode(array("result" => "error", "form" => (string) $form));
}
}
@@ -68,7 +72,10 @@ class Comments_Controller extends Controller {
public function form_add($item_id) {
$item = ORM::factory("item", $item_id);
access::required("view", $item);
+ if (!comment::can_comment()) {
+ access::forbidden();
+ }
- print comment::get_add_form($item);
+ print comment::prefill_add_form(comment::get_add_form($item));
}
}
diff --git a/modules/comment/helpers/comment.php b/modules/comment/helpers/comment.php
index e3486e83..92a286c7 100644
--- a/modules/comment/helpers/comment.php
+++ b/modules/comment/helpers/comment.php
@@ -33,7 +33,9 @@ class comment_Core {
->error_messages("required", t("You must enter a name for yourself"));
$group->input("email")
->label(t("Email (hidden)"))
- ->id("g-email");
+ ->id("g-email")
+ ->error_messages("required", t("You must enter a valid email address"))
+ ->error_messages("invalid", t("You must enter a valid email address"));
$group->input("url")
->label(t("Website (hidden)"))
->id("g-url");
@@ -45,14 +47,23 @@ class comment_Core {
module::event("comment_add_form", $form);
$group->submit("")->value(t("Add"))->class("ui-state-default ui-corner-all");
+ return $form;
+ }
+
+ static function prefill_add_form($form) {
$active = identity::active_user();
if (!$active->guest) {
+ $group = $form->add_comment;
$group->inputs["name"]->value($active->full_name)->disabled("disabled");
$group->email->value($active->email)->disabled("disabled");
$group->url->value($active->url)->disabled("disabled");
}
-
return $form;
}
+
+ static function can_comment() {
+ return !identity::active_user()->guest ||
+ module::get_var("comment", "access_permissions") == "everybody";
+ }
}
diff --git a/modules/comment/helpers/comment_event.php b/modules/comment/helpers/comment_event.php
index 51e663e6..33d4cd05 100644
--- a/modules/comment/helpers/comment_event.php
+++ b/modules/comment/helpers/comment_event.php
@@ -51,11 +51,17 @@ class comment_event_Core {
}
static function admin_menu($menu, $theme) {
+ $menu->get("settings_menu")
+ ->append(Menu::factory("link")
+ ->id("comment")
+ ->label(t("Comments"))
+ ->url(url::site("admin/comments")));
+
$menu->get("content_menu")
->append(Menu::factory("link")
->id("comments")
->label(t("Comments"))
- ->url(url::site("admin/comments")));
+ ->url(url::site("admin/manage_comments")));
}
static function photo_menu($menu, $theme) {
diff --git a/modules/comment/helpers/comment_installer.php b/modules/comment/helpers/comment_installer.php
index 9ca47f1a..18d51758 100644
--- a/modules/comment/helpers/comment_installer.php
+++ b/modules/comment/helpers/comment_installer.php
@@ -47,14 +47,20 @@ class comment_installer {
DEFAULT CHARSET=utf8;");
module::set_var("comment", "spam_caught", 0);
- module::set_version("comment", 2);
+ module::set_var("comment", "access_permissions", "everybody");
+ module::set_version("comment", 3);
}
static function upgrade($version) {
$db = Database::instance();
if ($version == 1) {
$db->query("ALTER TABLE {comments} CHANGE `state` `state` varchar(15) default 'unpublished'");
- module::set_version("comment", 2);
+ module::set_version("comment", $version = 2);
+ }
+
+ if ($version == 2) {
+ module::set_var("comment", "access_permissions", "everybody");
+ module::set_version("comment", $version = 3);
}
}
diff --git a/modules/comment/helpers/comment_rest.php b/modules/comment/helpers/comment_rest.php
new file mode 100644
index 00000000..bd3011cc
--- /dev/null
+++ b/modules/comment/helpers/comment_rest.php
@@ -0,0 +1,74 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2010 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 comment_rest_Core {
+ static function get($request) {
+ $comment = rest::resolve($request->url);
+ access::required("view", $comment->item());
+
+ return array(
+ "url" => $request->url,
+ "entity" => $comment->as_restful_array(),
+ "relationships" => rest::relationships("comment", $comment));
+ }
+
+ static function put($request) {
+ // Only admins can edit comments, for now
+ if (!identity::active_user()->admin) {
+ access::forbidden();
+ }
+
+ $comment = rest::resolve($request->url);
+ $comment = ORM::factory("comment");
+ $comment->text = $request->params->text;
+ $comment->save();
+ }
+
+ static function delete($request) {
+ if (!identity::active_user()->admin) {
+ access::forbidden();
+ }
+
+ $comment = rest::resolve($request->url);
+ access::required("edit", $comment->item());
+
+ $comment->delete();
+ }
+
+ static function relationships($resource_type, $resource) {
+ switch ($resource_type) {
+ case "item":
+ return array(
+ "comments" => array(
+ "url" => rest::url("item_comments", $resource)));
+ }
+ }
+
+ static function resolve($id) {
+ $comment = ORM::factory("comment", $id);
+ if (!access::can("view", $comment->item())) {
+ throw new Kohana_404_Exception();
+ }
+ return $comment;
+ }
+
+ static function url($comment) {
+ return url::abs_site("rest/comment/{$comment->id}");
+ }
+}
diff --git a/modules/comment/helpers/comment_rss.php b/modules/comment/helpers/comment_rss.php
index eee6f750..26d98d21 100644
--- a/modules/comment/helpers/comment_rss.php
+++ b/modules/comment/helpers/comment_rss.php
@@ -35,19 +35,22 @@ class comment_rss_Core {
$comments = ORM::factory("comment")
->viewable()
- ->where("state", "=", "published")
- ->order_by("created", "DESC");
+ ->where("comments.state", "=", "published")
+ ->order_by("comments.created", "DESC");
if ($feed_id == "item") {
- $comments->where("item_id", "=", $id);
+ $item = ORM::factory("item", $id);
+ $comments
+ ->where("items.left_ptr", ">=", $item->left_ptr)
+ ->where("items.right_ptr", "<=", $item->right_ptr);
}
$feed = new stdClass();
$feed->view = "comment.mrss";
- $feed->children = array();
+ $feed->comments = array();
foreach ($comments->find_all($limit, $offset) as $comment) {
$item = $comment->item();
- $feed->children[] = new ArrayObject(
+ $feed->comments[] = new ArrayObject(
array("pub_date" => date("D, d M Y H:i:s T", $comment->created),
"text" => nl2br(html::purify($comment->text)),
"thumb_url" => $item->thumb_url(),
diff --git a/modules/comment/helpers/comments_rest.php b/modules/comment/helpers/comments_rest.php
new file mode 100644
index 00000000..1cedb80b
--- /dev/null
+++ b/modules/comment/helpers/comments_rest.php
@@ -0,0 +1,62 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2010 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 comments_rest_Core {
+ /**
+ * Possible request parameters:
+ * start=#
+ * start at the Nth comment (zero based)
+ *
+ * num=#
+ * return up to N comments (max 100)
+ */
+ static function get($request) {
+ $comments = array();
+
+ $p = $request->params;
+ $num = isset($p->num) ? min((int)$p->num, 100) : 10;
+ $start = isset($p->start) ? (int)$p->start : 0;
+
+ foreach (ORM::factory("comment")->viewable()->find_all($num, $start) as $comment) {
+ $comments[] = rest::url("comment", $comment);
+ }
+ return array("url" => rest::url("comments"),
+ "members" => $comments);
+ }
+
+
+ static function post($request) {
+ $entity = $request->params->entity;
+
+ $item = rest::resolve($entity->item);
+ access::required("edit", $item);
+
+ $comment = ORM::factory("comment");
+ $comment->author_id = identity::active_user()->id;
+ $comment->item_id = $item->id;
+ $comment->text = $entity->text;
+ $comment->save();
+
+ return array("url" => rest::url("comment", $comment));
+ }
+
+ static function url() {
+ return url::abs_site("rest/comments");
+ }
+}
diff --git a/modules/comment/helpers/item_comments_rest.php b/modules/comment/helpers/item_comments_rest.php
new file mode 100644
index 00000000..1fe5c35f
--- /dev/null
+++ b/modules/comment/helpers/item_comments_rest.php
@@ -0,0 +1,50 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2010 Bharat Mediratta
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+class item_comments_rest_Core {
+ static function get($request) {
+ $item = rest::resolve($request->url);
+ access::required("view", $item);
+
+ $comments = array();
+ foreach (ORM::factory("comment")
+ ->viewable()
+ ->where("item_id", "=", $item->id)
+ ->order_by("created", "DESC")
+ ->find_all() as $comment) {
+ $comments[] = rest::url("comment", $comment);
+ }
+
+ return array(
+ "url" => $request->url,
+ "members" => $comments);
+ }
+
+ static function resolve($id) {
+ $item = ORM::factory("item", $id);
+ if (!access::can("view", $item)) {
+ throw new Kohana_404_Exception();
+ }
+ return $item;
+ }
+
+ static function url($item) {
+ return url::abs_site("rest/item_comments/{$item->id}");
+ }
+}
diff --git a/modules/comment/models/comment.php b/modules/comment/models/comment.php
index 48084340..772e8b60 100644
--- a/modules/comment/models/comment.php
+++ b/modules/comment/models/comment.php
@@ -61,7 +61,7 @@ class Comment_Model extends ORM {
if (!$array) {
$this->rules = array(
"guest_name" => array("callbacks" => array(array($this, "valid_author"))),
- "guest_email" => array("rules" => array("email")),
+ "guest_email" => array("callbacks" => array(array($this, "valid_email"))),
"guest_url" => array("rules" => array("url")),
"item_id" => array("callbacks" => array(array($this, "valid_item"))),
"state" => array("rules" => array("Comment_Model::valid_state")),
@@ -145,6 +145,19 @@ class Comment_Model extends ORM {
}
/**
+ * Make sure that the email address is legal.
+ */
+ public function valid_email(Validation $v, $field) {
+ if ($this->author_id == identity::guest()->id) {
+ if (empty($v->guest_email)) {
+ $v->add_error("guest_email", "required");
+ } else if (!valid::email($v->guest_email)) {
+ $v->add_error("guest_email", "invalid");
+ }
+ }
+ }
+
+ /**
* Make sure we have a valid associated item id.
*/
public function valid_item(Validation $v, $field) {
@@ -162,4 +175,20 @@ class Comment_Model extends ORM {
static function valid_state($value) {
return in_array($value, array("published", "unpublished", "spam", "deleted"));
}
+
+ /**
+ * Same as ORM::as_array() but convert id fields into their RESTful form.
+ */
+ public function as_restful_array() {
+ $data = array();
+ foreach ($this->as_array() as $key => $value) {
+ if (strncmp($key, "server_", 7)) {
+ $data[$key] = $value;
+ }
+ }
+ $data["item"] = rest::url("item", $this->item());
+ unset($data["item_id"]);
+
+ return $data;
+ }
}
diff --git a/modules/comment/module.info b/modules/comment/module.info
index c371cf27..cd34f140 100644
--- a/modules/comment/module.info
+++ b/modules/comment/module.info
@@ -1,3 +1,3 @@
name = "Comments"
description = "Allows users and guests to leave comments on photos and albums."
-version = 2
+version = 3
diff --git a/modules/comment/tests/Comment_Event_Test.php b/modules/comment/tests/Comment_Event_Test.php
index 62ffec2f..7cae9297 100644
--- a/modules/comment/tests/Comment_Event_Test.php
+++ b/modules/comment/tests/Comment_Event_Test.php
@@ -25,6 +25,7 @@ class Comment_Event_Test extends Gallery_Unit_Test_Case {
$comment->item_id = $album->id;
$comment->author_id = identity::guest()->id;
$comment->guest_name = "test";
+ $comment->guest_email = "test@test.com";
$comment->text = "text";
$comment->save();
diff --git a/modules/comment/tests/Comment_Model_Test.php b/modules/comment/tests/Comment_Model_Test.php
index f4e944f0..ee4d3d3c 100644
--- a/modules/comment/tests/Comment_Model_Test.php
+++ b/modules/comment/tests/Comment_Model_Test.php
@@ -22,6 +22,37 @@ class Comment_Model_Test extends Gallery_Unit_Test_Case {
identity::set_active_user(identity::admin_user());
}
+ public function guest_name_and_email_is_required_test() {
+ try {
+ $comment = ORM::factory("comment");
+ $comment->item_id = item::root()->id;
+ $comment->author_id = identity::guest()->id;
+ $comment->text = "text";
+ $comment->save();
+ } catch (ORM_Validation_Exception $e) {
+ $this->assert_equal(array("guest_name" => "required",
+ "guest_email" => "required"),
+ $e->validation->errors());
+ return;
+ }
+ }
+
+ public function guest_email_must_be_well_formed_test() {
+ try {
+ $comment = ORM::factory("comment");
+ $comment->item_id = item::root()->id;
+ $comment->author_id = identity::guest()->id;
+ $comment->guest_name = "guest";
+ $comment->guest_email = "bogus";
+ $comment->text = "text";
+ $comment->save();
+ } catch (ORM_Validation_Exception $e) {
+ $this->assert_equal(array("guest_email" => "invalid"),
+ $e->validation->errors());
+ return;
+ }
+ }
+
public function cant_view_comments_for_unviewable_items_test() {
$album = test::random_album();
diff --git a/modules/comment/views/admin_comments.html.php b/modules/comment/views/admin_comments.html.php
index f58267bd..dc6985b2 100644
--- a/modules/comment/views/admin_comments.html.php
+++ b/modules/comment/views/admin_comments.html.php
@@ -1,201 +1,7 @@
<?php defined("SYSPATH") or die("No direct script access.") ?>
-<script type="text/javascript">
- var set_state_url =
- <?= html::js_string(url::site("admin/comments/set_state/__ID__/__STATE__?csrf=$csrf")) ?>;
- function set_state(state, id) {
- $.get(set_state_url.replace("__STATE__", state).replace("__ID__", id),
- {},
- function() {
- $("#g-comment-" + id).slideUp();
- update_menu();
- });
- }
-
- var delete_url =
- <?= html::js_string(url::site("admin/comments/delete/__ID__?csrf=$csrf")) ?>;
-
- function del(id) {
- $.get(delete_url.replace("__ID__", id),
- {},
- function() {
- $("#g-comment-" + id).slideUp();
- update_menu();
- });
- }
-
- function update_menu() {
- $.get(<?= html::js_string(url::site("admin/comments/menu_labels")) ?>, {},
- function(data) {
- for (var i = 0; i < data.length; i++) {
- $("#g-admin-comments-menu li:eq(" + i + ") a").html(data[i]);
- }
- },
- "json");
- }
-</script>
-
-<div id="g-admin-comments" class="g-block">
- <h1> <?= t("Manage comments") ?> </h1>
-
+<div class="g-block">
+ <h1> <?= t("Comment settings") ?> </h1>
<div class="g-block-content">
- <!-- @todo: Highlight active menu option -->
- <div id="g-admin-comments-menu" class="ui-helper-clearfix">
- <?= $menu->render() ?>
- </div>
-
- <!-- @todo: Remove after setting active option? -->
- <h2>
- <? if ($state == "published"): ?>
- <?= t("Approved comments") ?>
- <? elseif ($state == "unpublished"): ?>
- <?= t("Comments awaiting moderation") ?>
- <? elseif ($state == "spam"): ?>
- <?= t("Spam comments") ?>
- <? elseif ($state == "deleted"): ?>
- <?= t("Recently deleted comments") ?>
- <? endif ?>
- </h2>
-
- <? if ($state == "spam"): ?>
- <div>
- <? $spam_caught = module::get_var("comment", "spam_caught") ?>
- <? if ($spam_caught > 0): ?>
- <p>
- <?= t2("Gallery has caught %count spam for you since you installed spam filtering.",
- "Gallery has caught %count spam for you since you installed spam filtering.",
- $spam_caught) ?>
- </p>
- <? endif ?>
- <p>
- <? if ($counts->spam): ?>
- <?= t2("There is currently one comment in your spam queue. You can delete it with a single click, but there is no undo operation so you may want to check the message first to make sure that it really is spam.",
- "There are currently %count comments in your spam queue. You can delete them all with a single click, but there is no undo operation so you may want to check the messages first to make sure that they really are spam. All spam messages will be deleted after 7 days automatically.",
- $counts->spam) ?>
- </p>
- <p>
- <a href="<?= url::site("admin/comments/delete_all_spam?csrf=$csrf") ?>">
- <?= t("Delete all spam") ?>
- </a>
- <? else: ?>
- <?= t("Your spam queue is empty!") ?>
- <? endif ?>
- </p>
- </div>
- <? endif ?>
-
- <? if ($state == "deleted"): ?>
- <div>
- <p>
- <?= t("These are messages that have been recently deleted. They will be permanently erased automatically after 7 days.") ?>
- </p>
- </div>
- <? endif ?>
-
- <table id="g-admin-comments-list">
- <tr>
- <th>
- <?= t("Author") ?>
- </th>
- <th>
- <?= t("Comment") ?>
- </th>
- <th>
- <?= t("Actions") ?>
- </th>
- </tr>
- <? foreach ($comments as $comment): ?>
- <tr id="g-comment-<?= $comment->id ?>" class="<?= text::alternate("g-odd", "g-even") ?>">
- <td>
- <a href="#">
- <img src="<?= $comment->author()->avatar_url(40, $theme->url("images/avatar.jpg", true)) ?>"
- class="g-avatar"
- alt="<?= html::clean_attribute($comment->author_name()) ?>"
- width="40"
- height="40" />
- </a>
- <p><a href="mailto:<?= html::clean_attribute($comment->author_email()) ?>"
- title="<?= html::clean_attribute($comment->author_email()) ?>"> <?= html::clean($comment->author_name()) ?> </a></p>
- </td>
- <td>
- <div class="g-right">
- <? $item = $comment->item() ?>
- <div class="g-item g-photo">
- <a href="<?= $item->url() ?>">
- <? if ($item->has_thumb()): ?>
- <img src="<?= $item->thumb_url() ?>"
- alt="<?= html::purify($item->title)->for_html_attr() ?>"
- <?= photo::img_dimensions($item->thumb_width, $item->thumb_height, 75) ?>
- />
- <? else: ?>
- <?= t("No thumbnail") ?>
- <? endif ?>
- </a>
- </div>
- </div>
- <p><?= gallery::date($comment->created) ?></p>
- <?= nl2br(html::purify($comment->text)) ?>
- </td>
- <td>
- <ul class="g-buttonset-vertical">
- <? if ($comment->state != "unpublished"): ?>
- <li>
- <a href="javascript:set_state('unpublished',<?=$comment->id?>)"
- class="g-button ui-state-default ui-icon-left">
- <span class="ui-icon ui-icon-check"></span>
- <?= t("Unapprove") ?>
- </a>
- </li>
- <? endif ?>
- <? if ($comment->state != "published"): ?>
- <li>
- <a href="javascript:set_state('published',<?=$comment->id?>)"
- class="g-button ui-state-default ui-icon-left">
- <span class="ui-icon ui-icon-check"></span>
- <?= t("Approve") ?>
- </a>
- </li>
- <? endif ?>
- <? if ($comment->state != "spam"): ?>
- <li>
- <a href="javascript:set_state('spam',<?=$comment->id?>)"
- class="g-button ui-state-default ui-icon-left">
- <span class="ui-icon ui-icon-cancel"></span>
- <?= t("Spam") ?>
- </a>
- </li>
- <? endif ?>
- <!--
- <li>
- <a href="javascript:reply(<?=$comment->id?>)"
- class="g-button ui-state-default ui-icon-left">
- <span class="ui-icon ui-icon-arrowreturnthick-1-w"></span>
- <?= t("Reply") ?>
- </a>
- </li>
- <li>
- <a href="javascript:Edit(<?=$comment->id?>)"
- class="g-button ui-state-default ui-icon-left">
- <span class="ui-icon ui-icon-pencil"></span>
- <?= t("Edit") ?>
- </a>
- </li>
- -->
- <li>
- <a href="javascript:set_state('deleted',<?=$comment->id?>)"
- class="g-button ui-state-default ui-icon-left">
- <span class="ui-icon ui-icon-trash"></span>
- <?= t("Delete") ?>
- </a>
- </li>
- </ul>
- </td>
- </tr>
- <? endforeach ?>
- </table>
-
- <div class="g-paginator">
- <?= $pager ?>
- </div>
-
+ <?= $form ?>
</div>
</div>
diff --git a/modules/comment/views/admin_manage_comments.html.php b/modules/comment/views/admin_manage_comments.html.php
new file mode 100644
index 00000000..34a28986
--- /dev/null
+++ b/modules/comment/views/admin_manage_comments.html.php
@@ -0,0 +1,201 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<script type="text/javascript">
+ var set_state_url =
+ <?= html::js_string(url::site("admin/manage_comments/set_state/__ID__/__STATE__?csrf=$csrf")) ?>;
+ function set_state(state, id) {
+ $.get(set_state_url.replace("__STATE__", state).replace("__ID__", id),
+ {},
+ function() {
+ $("#g-comment-" + id).slideUp();
+ update_menu();
+ });
+ }
+
+ var delete_url =
+ <?= html::js_string(url::site("admin/manage_comments/delete/__ID__?csrf=$csrf")) ?>;
+
+ function del(id) {
+ $.get(delete_url.replace("__ID__", id),
+ {},
+ function() {
+ $("#g-comment-" + id).slideUp();
+ update_menu();
+ });
+ }
+
+ function update_menu() {
+ $.get(<?= html::js_string(url::site("admin/manage_comments/menu_labels")) ?>, {},
+ function(data) {
+ for (var i = 0; i < data.length; i++) {
+ $("#g-admin-comments-menu li:eq(" + i + ") a").html(data[i]);
+ }
+ },
+ "json");
+ }
+</script>
+
+<div id="g-admin-comments" class="g-block">
+ <h1> <?= t("Manage comments") ?> </h1>
+
+ <div class="g-block-content">
+ <!-- @todo: Highlight active menu option -->
+ <div id="g-admin-comments-menu" class="ui-helper-clearfix">
+ <?= $menu->render() ?>
+ </div>
+
+ <!-- @todo: Remove after setting active option? -->
+ <h2>
+ <? if ($state == "published"): ?>
+ <?= t("Approved comments") ?>
+ <? elseif ($state == "unpublished"): ?>
+ <?= t("Comments awaiting moderation") ?>
+ <? elseif ($state == "spam"): ?>
+ <?= t("Spam comments") ?>
+ <? elseif ($state == "deleted"): ?>
+ <?= t("Recently deleted comments") ?>
+ <? endif ?>
+ </h2>
+
+ <? if ($state == "spam"): ?>
+ <div>
+ <? $spam_caught = module::get_var("comment", "spam_caught") ?>
+ <? if ($spam_caught > 0): ?>
+ <p>
+ <?= t2("Gallery has caught %count spam for you since you installed spam filtering.",
+ "Gallery has caught %count spam for you since you installed spam filtering.",
+ $spam_caught) ?>
+ </p>
+ <? endif ?>
+ <p>
+ <? if ($counts->spam): ?>
+ <?= t2("There is currently one comment in your spam queue. You can delete it with a single click, but there is no undo operation so you may want to check the message first to make sure that it really is spam.",
+ "There are currently %count comments in your spam queue. You can delete them all with a single click, but there is no undo operation so you may want to check the messages first to make sure that they really are spam. All spam messages will be deleted after 7 days automatically.",
+ $counts->spam) ?>
+ </p>
+ <p>
+ <a href="<?= url::site("admin/manage_comments/delete_all_spam?csrf=$csrf") ?>">
+ <?= t("Delete all spam") ?>
+ </a>
+ <? else: ?>
+ <?= t("Your spam queue is empty!") ?>
+ <? endif ?>
+ </p>
+ </div>
+ <? endif ?>
+
+ <? if ($state == "deleted"): ?>
+ <div>
+ <p>
+ <?= t("These are messages that have been recently deleted. They will be permanently erased automatically after 7 days.") ?>
+ </p>
+ </div>
+ <? endif ?>
+
+ <table id="g-admin-comments-list">
+ <tr>
+ <th>
+ <?= t("Author") ?>
+ </th>
+ <th>
+ <?= t("Comment") ?>
+ </th>
+ <th>
+ <?= t("Actions") ?>
+ </th>
+ </tr>
+ <? foreach ($comments as $comment): ?>
+ <tr id="g-comment-<?= $comment->id ?>" class="<?= text::alternate("g-odd", "g-even") ?>">
+ <td>
+ <a href="#">
+ <img src="<?= $comment->author()->avatar_url(40, $theme->url("images/avatar.jpg", true)) ?>"
+ class="g-avatar"
+ alt="<?= html::clean_attribute($comment->author_name()) ?>"
+ width="40"
+ height="40" />
+ </a>
+ <p><a href="mailto:<?= html::clean_attribute($comment->author_email()) ?>"
+ title="<?= html::clean_attribute($comment->author_email()) ?>"> <?= html::clean($comment->author_name()) ?> </a></p>
+ </td>
+ <td>
+ <div class="g-right">
+ <? $item = $comment->item() ?>
+ <div class="g-item g-photo">
+ <a href="<?= $item->url() ?>">
+ <? if ($item->has_thumb()): ?>
+ <img src="<?= $item->thumb_url() ?>"
+ alt="<?= html::purify($item->title)->for_html_attr() ?>"
+ <?= photo::img_dimensions($item->thumb_width, $item->thumb_height, 75) ?>
+ />
+ <? else: ?>
+ <?= t("No thumbnail") ?>
+ <? endif ?>
+ </a>
+ </div>
+ </div>
+ <p><?= gallery::date($comment->created) ?></p>
+ <?= nl2br(html::purify($comment->text)) ?>
+ </td>
+ <td>
+ <ul class="g-buttonset-vertical">
+ <? if ($comment->state != "unpublished"): ?>
+ <li>
+ <a href="javascript:set_state('unpublished',<?=$comment->id?>)"
+ class="g-button ui-state-default ui-icon-left">
+ <span class="ui-icon ui-icon-check"></span>
+ <?= t("Unapprove") ?>
+ </a>
+ </li>
+ <? endif ?>
+ <? if ($comment->state != "published"): ?>
+ <li>
+ <a href="javascript:set_state('published',<?=$comment->id?>)"
+ class="g-button ui-state-default ui-icon-left">
+ <span class="ui-icon ui-icon-check"></span>
+ <?= t("Approve") ?>
+ </a>
+ </li>
+ <? endif ?>
+ <? if ($comment->state != "spam"): ?>
+ <li>
+ <a href="javascript:set_state('spam',<?=$comment->id?>)"
+ class="g-button ui-state-default ui-icon-left">
+ <span class="ui-icon ui-icon-cancel"></span>
+ <?= t("Spam") ?>
+ </a>
+ </li>
+ <? endif ?>
+ <!--
+ <li>
+ <a href="javascript:reply(<?=$comment->id?>)"
+ class="g-button ui-state-default ui-icon-left">
+ <span class="ui-icon ui-icon-arrowreturnthick-1-w"></span>
+ <?= t("Reply") ?>
+ </a>
+ </li>
+ <li>
+ <a href="javascript:Edit(<?=$comment->id?>)"
+ class="g-button ui-state-default ui-icon-left">
+ <span class="ui-icon ui-icon-pencil"></span>
+ <?= t("Edit") ?>
+ </a>
+ </li>
+ -->
+ <li>
+ <a href="javascript:set_state('deleted',<?=$comment->id?>)"
+ class="g-button ui-state-default ui-icon-left">
+ <span class="ui-icon ui-icon-trash"></span>
+ <?= t("Delete") ?>
+ </a>
+ </li>
+ </ul>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </table>
+
+ <div class="g-paginator">
+ <?= $pager ?>
+ </div>
+
+ </div>
+</div>
diff --git a/modules/comment/views/comment.mrss.php b/modules/comment/views/comment.mrss.php
index c2a4b538..809e7890 100644
--- a/modules/comment/views/comment.mrss.php
+++ b/modules/comment/views/comment.mrss.php
@@ -20,19 +20,19 @@
<? endif ?>
<pubDate><?= $pub_date ?></pubDate>
<lastBuildDate><?= $pub_date ?></lastBuildDate>
- <? foreach ($feed->children as $child): ?>
+ <? foreach ($feed->comments as $comment): ?>
<item>
- <title><?= html::purify($child->title) ?></title>
- <link><?= html::clean($child->item_uri) ?></link>
- <author><?= html::clean($child->author) ?></author>
- <guid isPermaLink="true"><?= $child->item_uri ?></guid>
- <pubDate><?= $child->pub_date ?></pubDate>
+ <title><?= html::purify($comment->title) ?></title>
+ <link><?= html::clean($comment->item_uri) ?></link>
+ <author><?= html::clean($comment->author) ?></author>
+ <guid isPermaLink="true"><?= $comment->item_uri ?></guid>
+ <pubDate><?= $comment->pub_date ?></pubDate>
<content:encoded>
<![CDATA[
- <p><?= nl2br(html::purify($child->text)) ?></p>
+ <p><?= nl2br(html::purify($comment->text)) ?></p>
<p>
- <img alt="" src="<?= $child->thumb_url ?>"
- height="<?= $child->thumb_height ?>" width="<?= $child->thumb_width ?>" />
+ <img alt="" src="<?= $comment->thumb_url ?>"
+ height="<?= $comment->thumb_height ?>" width="<?= $comment->thumb_width ?>" />
<br />
</p>
]]>
diff --git a/modules/comment/views/comments.html.php b/modules/comment/views/comments.html.php
index e4322e08..da45f57b 100644
--- a/modules/comment/views/comments.html.php
+++ b/modules/comment/views/comments.html.php
@@ -1,17 +1,27 @@
<?php defined("SYSPATH") or die("No direct script access.") ?>
- <a href="<?= url::site("form/add/comments/{$item->id}") ?>#comment-form" id="g-add-comment"
+<? if (comment::can_comment()): ?>
+<a href="<?= url::site("form/add/comments/{$item->id}") ?>#comment-form" id="g-add-comment"
class="g-button ui-corner-all ui-icon-left ui-state-default">
<span class="ui-icon ui-icon-comment"></span>
<?= t("Add a comment") ?>
</a>
+<? endif ?>
+
<div id="g-comment-detail">
<? if (!$comments->count()): ?>
<p class="g-no-comments">
+ <? if (comment::can_comment()): ?>
<?= t("No comments yet. Be the first to <a %attrs>comment</a>!",
array("attrs" => html::mark_clean("href=\"" . url::site("form/add/comments/{$item->id}") . "\" class=\"showCommentForm\""))) ?>
- </p>
- <ul><li class="g-no-comments">&nbsp;</li></ul>
+ <? else: ?>
+ <?= t("No comments yet.") ?>
+ <? endif ?>
+ </p>
+ <ul>
+ <li class="g-no-comments">&nbsp;</li>
+ </ul>
<? endif ?>
+
<? if ($comments->count()): ?>
<ul>
<? foreach ($comments as $comment): ?>
diff --git a/modules/digibug/helpers/digibug_event.php b/modules/digibug/helpers/digibug_event.php
index cf7cdf21..413bf586 100644
--- a/modules/digibug/helpers/digibug_event.php
+++ b/modules/digibug/helpers/digibug_event.php
@@ -26,14 +26,17 @@ class digibug_event_Core {
->url(url::site("admin/digibug")));
}
- static function photo_menu($menu, $theme) {
+ static function site_menu($menu, $theme) {
$item = $theme->item();
- $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"));
+ 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) {
diff --git a/modules/exif/helpers/exif.php b/modules/exif/helpers/exif.php
index 943feba7..aa77b42e 100644
--- a/modules/exif/helpers/exif.php
+++ b/modules/exif/helpers/exif.php
@@ -36,7 +36,8 @@ class exif_Core {
foreach(self::_keys() as $field => $exifvar) {
if (isset($exif_raw[$exifvar[0]][$exifvar[1]])) {
$value = $exif_raw[$exifvar[0]][$exifvar[1]];
- if (function_exists("mb_detect_encoding") && mb_detect_encoding($value) != "UTF-8") {
+ if (function_exists("mb_detect_encoding") &&
+ mb_detect_encoding($value, "ISO-8859-1, UTF-8") != "UTF-8") {
$value = utf8_encode($value);
}
$keys[$field] = Input::clean($value);
@@ -59,7 +60,8 @@ class exif_Core {
foreach (array("Keywords" => "2#025", "Caption" => "2#120") as $keyword => $iptc_key) {
if (!empty($iptc[$iptc_key])) {
$value = implode(" ", $iptc[$iptc_key]);
- if (function_exists("mb_detect_encoding") && mb_detect_encoding($value) != "UTF-8") {
+ if (function_exists("mb_detect_encoding") &&
+ mb_detect_encoding($value, "ISO-8859-1, UTF-8") != "UTF-8") {
$value = utf8_encode($value);
}
$keys[$keyword] = Input::clean($value);
diff --git a/modules/exif/lib/exif.php b/modules/exif/lib/exif.php
index 189f61b5..8ba85c8e 100644
--- a/modules/exif/lib/exif.php
+++ b/modules/exif/lib/exif.php
@@ -140,6 +140,8 @@
+ Fixed bug with newer Olympus cameras where number of fields was miscalculated leading to bad performance.
+ More logical fraction calculation for shutter speed.
+
+2009: For all further changes, see the Zenphoto change logs.
*/
@@ -160,13 +162,11 @@ function intel2Moto($intel) {
$cache[$intel] = '';
$len = strlen($intel);
- if ($len > 1000) {
- debugLogBacktrace('intel2Moto called with unreasonable data string: length='.$len);
- trigger_error(sprintf((string) t('intel2Moto called with unreasonable data string: length=%s. See debug log for details. (Setting DEBUG_EXIF to true might help locate problem images.)'),$len));
- } else {
- for($i = 0; $i <= $len; $i += 2) {
- $cache[$intel] .= substr($intel, $len-$i, 2);
- }
+ if ($len > 1000) { // an unreasonable length, override it.
+ $len = 1000;
+ }
+ for($i = 0; $i <= $len; $i += 2) {
+ $cache[$intel] .= substr($intel, $len-$i, 2);
}
return $cache[$intel];
}
@@ -212,7 +212,7 @@ function lookup_tag($tag) {
case '8827': $tag = 'ISOSpeedRatings'; break; // integer 0-65535
case '9000': $tag = 'ExifVersion'; break; // ??
case '9003': $tag = 'DateTimeOriginal'; break; // YYYY:MM:DD HH:MM:SS
- case '9004': $tag = 'DateTimedigitized'; break; // YYYY:MM:DD HH:MM:SS
+ case '9004': $tag = 'DateTimeDigitized'; break; // YYYY:MM:DD HH:MM:SS
case '9101': $tag = 'ComponentsConfiguration'; break; // ??
case '9102': $tag = 'CompressedBitsPerPixel'; break; // positive rational number
case '9201': $tag = 'ShutterSpeedValue'; break; // seconds or fraction of seconds 1/x
@@ -348,258 +348,321 @@ function lookup_type(&$type,&$size) {
}
//================================================================================================
-// Formats Data for the data type
+// processes a irrational number
//================================================================================================
-function formatData($type,$tag,$intel,$data) {
-
- if ($type == 'ASCII') {
- // Search for a null byte and stop there.
- if (($pos = strpos($data, chr(0))) !== false) {
- $data = substr($data, 0, $pos);
- }
- // Format certain kinds of strings nicely (Camera make etc.)
- if ($tag == '010f') $data = ucwords(strtolower(trim($data)));
-
- } else if ($type == 'URATIONAL' || $type == 'SRATIONAL') {
+function unRational($data, $type, $intel) {
$data = bin2hex($data);
- if ($intel == 1) $data = intel2Moto($data);
-
- if ($intel == 1) $top = hexdec(substr($data,8,8)); // intel stores them bottom-top
- else $top = hexdec(substr($data,0,8)); // motorola stores them top-bottom
-
- if ($intel == 1) $bottom = hexdec(substr($data,0,8)); // intel stores them bottom-top
- else $bottom = hexdec(substr($data,8,8)); // motorola stores them top-bottom
+ if ($intel == 1) {
+ $data = intel2Moto($data);
+ $top = hexdec(substr($data,8,8)); // intel stores them bottom-top
+ $bottom = hexdec(substr($data,0,8)); // intel stores them bottom-top
+ } else {
+ $top = hexdec(substr($data,0,8)); // motorola stores them top-bottom
+ $bottom = hexdec(substr($data,8,8)); // motorola stores them top-bottom
+ }
if ($type == 'SRATIONAL' && $top > 2147483647) $top = $top - 4294967296; // this makes the number signed instead of unsigned
- if ($bottom != 0) $data=$top/$bottom;
- else if ($top == 0) $data = 0;
- else $data = $top.'/'.$bottom;
-
- if (($tag == '011a' || $tag == '011b') && $bottom == 1) { // XResolution YResolution
- $data = $top.' dots per ResolutionUnit';
- } else if ($tag == '829a') { // Exposure Time
- if ($bottom != 0) {
- $data = $top / $bottom;
- } else {
+ if ($bottom != 0)
+ $data=$top/$bottom;
+ else
+ if ($top == 0)
$data = 0;
+ else
+ $data = $top.'/'.$bottom;
+ return $data;
+}
+
+//================================================================================================
+// processes a rational number
+//================================================================================================
+function rational($data,$type,$intel) {
+ if (($type == 'USHORT' || $type == 'SSHORT')) {
+ $data = substr($data,0,2);
+ }
+ $data = bin2hex($data);
+ if ($intel == 1) {
+ $data = intel2Moto($data);
+ }
+ $data = hexdec($data);
+ if ($type == 'SSHORT' && $data > 32767) $data = $data - 65536; // this makes the number signed instead of unsigned
+ if ($type == 'SLONG' && $data > 2147483647) $data = $data - 4294967296; // this makes the number signed instead of unsigned
+ return $data;
+}
+
+//================================================================================================
+// Formats Data for the data type
+//================================================================================================
+function formatData($type,$tag,$intel,$data) {
+ switch ($type) {
+ case 'ASCII':
+ if (($pos = strpos($data, chr(0))) !== false) { // Search for a null byte and stop there.
+ $data = substr($data, 0, $pos);
}
- $data = formatExposure($data);
- } else if ($tag == '829d') { // FNumber
- $data = 'f/'.$data;
- } else if ($tag == '9204') { // ExposureBiasValue
- $data = round($data, 2) . ' EV';
- } else if ($tag == '9205' || $tag == '9202') { // ApertureValue and MaxApertureValue
- // ApertureValue is given in the APEX Mode. Many thanks to Matthieu Froment for this code
- // The formula is : Aperture = 2*log2(FNumber) <=> FNumber = e((Aperture.ln(2))/2)
- $data = exp(($data*log(2))/2);
- $data = round($data, 1);// Focal is given with a precision of 1 digit.
- $data='f/'.$data;
- } else if ($tag == '920a') { // FocalLength
- $data = $data.' mm';
- } else if ($tag == '9201') { // ShutterSpeedValue
- // The ShutterSpeedValue is given in the APEX mode. Many thanks to Matthieu Froment for this code
- // The formula is : Shutter = - log2(exposureTime) (Appendix C of EXIF spec.)
- // Where shutter is in APEX, log2(exposure) = ln(exposure)/ln(2)
- // So final formula is : exposure = exp(-ln(2).shutter)
- // The formula can be developed : exposure = 1/(exp(ln(2).shutter))
- $data = exp($data * log(2));
- if ($data != 0) $data = 1/$data;
- $data = formatExposure($data);
- }
-
- } else if ($type == 'USHORT' || $type == 'SSHORT' || $type == 'ULONG' || $type == 'SLONG' || $type == 'FLOAT' || $type == 'DOUBLE') {
- $data = bin2hex($data);
- if ($intel == 1) $data = intel2Moto($data);
- if ($intel == 0 && ($type == 'USHORT' || $type == 'SSHORT')) $data = substr($data,0,4);
- $data = hexdec($data);
-
- if ($type == 'SSHORT' && $data > 32767) $data = $data - 65536; // this makes the number signed instead of unsigned
- if ($type == 'SLONG' && $data > 2147483647) $data = $data - 4294967296; // this makes the number signed instead of unsigned
-
- if ($tag == '0112') { // Orientation
- // Example of how all of these tag formatters should be...
- switch ($data) {
- case 1 : $data = (string) t('1: Normal (0 deg)'); break;
- case 2 : $data = (string) t('2: Mirrored'); break;
- case 3 : $data = (string) t('3: Upsidedown'); break;
- case 4 : $data = (string) t('4: Upsidedown Mirrored'); break;
- case 5 : $data = (string) t('5: 90 deg CW Mirrored'); break;
- case 6 : $data = (string) t('6: 90 deg CCW'); break;
- case 7 : $data = (string) t('7: 90 deg CCW Mirrored'); break;
- case 8 : $data = (string) t('8: 90 deg CW'); break;
- default : $data = (string) t('Unknown').': '.$data;
+ if ($tag == '010f') $data = ucwords(strtolower(trim($data))); // Format certain kinds of strings nicely (Camera make etc.)
+ break;
+ case 'URATIONAL':
+ case 'SRATIONAL':
+ switch ($tag) {
+ case '011a': // XResolution
+ case '011b': // YResolution
+ $data = round(unRational($data,$type,$intel)).' dots per ResolutionUnit';
+ break;
+ case '829a': // Exposure Time
+ $data = formatExposure(unRational($data,$type,$intel));
+ break;
+ case '829d': // FNumber
+ $data = 'f/'.unRational($data,$type,$intel);
+ break;
+ case '9204': // ExposureBiasValue
+ $data = round(unRational($data,$type,$intel), 2) . ' EV';
+ break;
+ case '9205': // ApertureValue
+ case '9202': // MaxApertureValue
+ // ApertureValue is given in the APEX Mode. Many thanks to Matthieu Froment for this code
+ // The formula is : Aperture = 2*log2(FNumber) <=> FNumber = e((Aperture.ln(2))/2)
+ $datum = exp((unRational($data,$type,$intel)*log(2))/2);
+ $data = round($datum, 1);// Focal is given with a precision of 1 digit.
+ $data='f/'.$datum;
+ break;
+ case '920a': // FocalLength
+ $data = unRational($data,$type,$intel).' mm';
+ break;
+ case '9201': // ShutterSpeedValue
+ // The ShutterSpeedValue is given in the APEX mode. Many thanks to Matthieu Froment for this code
+ // The formula is : Shutter = - log2(exposureTime) (Appendix C of EXIF spec.)
+ // Where shutter is in APEX, log2(exposure) = ln(exposure)/ln(2)
+ // So final formula is : exposure = exp(-ln(2).shutter)
+ // The formula can be developed : exposure = 1/(exp(ln(2).shutter))
+ $datum = exp(unRational($data,$type,$intel) * log(2));
+ if ($datum != 0) $datum = 1/$datum;
+ $data = formatExposure($datum);
+ break;
+ default:
+ $data = unRational($data,$type,$intel);
+ break;
}
-
- } else if ($tag == '0128' || $tag == 'a210' || $tag == '0128') { // ResolutionUnit and FocalPlaneResolutionUnit and ThumbnailResolutionUnit
- if ($data == 1) $data = (string) t('No Unit');
- else if ($data == 2) $data = (string) t('Inch');
- else if ($data == 3) $data = (string) t('Centimeter');
-
- } else if ($tag == '0213') { // YCbCrPositioning
- if ($data == 1) $data = (string) t('Center of Pixel Array');
- else if ($data == 2) $data = (string) t('Datum Point');
-
- } else if ($tag == '8822') { // ExposureProgram
- if ($data == 1) $data = (string) t('Manual');
- else if ($data == 2) $data = (string) t('Program');
- else if ($data == 3) $data = (string) t('Aperture Priority');
- else if ($data == 4) $data = (string) t('Shutter Priority');
- else if ($data == 5) $data = (string) t('Program Creative');
- else if ($data == 6) $data = (string) t('Program Action');
- else if ($data == 7) $data = (string) t('Portrat');
- else if ($data == 8) $data = (string) t('Landscape');
- else $data = (string) t('Unknown').': '.$data;
-
- } else if ($tag == '9207') { // MeteringMode
- if ($data == 0) $data = (string) t('Unknown');
- else if ($data == 1) $data = (string) t('Average');
- else if ($data == 2) $data = (string) t('Center Weighted Average');
- else if ($data == 3) $data = (string) t('Spot');
- else if ($data == 4) $data = (string) t('Multi-Spot');
- else if ($data == 5) $data = (string) t('Multi-Segment');
- else if ($data == 6) $data = (string) t('Partial');
- else if ($data == 255) $data = (string) t('Other');
- else $data = (string) t('Unknown').': '.$data;
-
- } else if ($tag == '9208') { // LightSource
- if ($data == 0) $data = (string) t('Unknown or Auto');
- else if ($data == 1) $data = (string) t('Daylight');
- else if ($data == 2) $data = (string) t('Flourescent');
- else if ($data == 3) $data = (string) t('Tungsten'); // 3 Tungsten (Incandescent light)
- // 4 Flash
- // 9 Fine Weather
- else if ($data == 10) $data = (string) t('Flash'); // 10 Cloudy Weather
- // 11 Shade
- // 12 Daylight Fluorescent (D 5700 - 7100K)
- // 13 Day White Fluorescent (N 4600 - 5400K)
- // 14 Cool White Fluorescent (W 3900 -4500K)
- // 15 White Fluorescent (WW 3200 - 3700K)
- // 10 Flash
- else if ($data == 17) $data = (string) t('Standard Light A');
- else if ($data == 18) $data = (string) t('Standard Light B');
- else if ($data == 19) $data = (string) t('Standard Light C');
- else if ($data == 20) $data = (string) t('D55');
- else if ($data == 21) $data = (string) t('D65');
- else if ($data == 22) $data = (string) t('D75');
- else if ($data == 23) $data = (string) t('D50');
- else if ($data == 24) $data = (string) t('ISO Studio Tungsten');
- else if ($data == 255) $data = (string) t('Other');
- else $data = (string) t('Unknown').': '.$data;
-
- } else if ($tag == '9209') { // Flash
- if ($data == 0) $data = (string) t('No Flash');
- else if ($data == 1) $data = (string) t('Flash');
- else if ($data == 5) $data = (string) t('Flash, strobe return light not detected');
- else if ($data == 7) $data = (string) t('Flash, strobe return light detected');
- else if ($data == 9) $data = (string) t('Compulsory Flash');
- else if ($data == 13) $data = (string) t('Compulsory Flash, Return light not detected');
- else if ($data == 15) $data = (string) t('Compulsory Flash, Return light detected');
- else if ($data == 16) $data = (string) t('No Flash');
- else if ($data == 24) $data = (string) t('No Flash');
- else if ($data == 25) $data = (string) t('Flash, Auto-Mode');
- else if ($data == 29) $data = (string) t('Flash, Auto-Mode, Return light not detected');
- else if ($data == 31) $data = (string) t('Flash, Auto-Mode, Return light detected');
- else if ($data == 32) $data = (string) t('No Flash');
- else if ($data == 65) $data = (string) t('Red Eye');
- else if ($data == 69) $data = (string) t('Red Eye, Return light not detected');
- else if ($data == 71) $data = (string) t('Red Eye, Return light detected');
- else if ($data == 73) $data = (string) t('Red Eye, Compulsory Flash');
- else if ($data == 77) $data = (string) t('Red Eye, Compulsory Flash, Return light not detected');
- else if ($data == 79) $data = (string) t('Red Eye, Compulsory Flash, Return light detected');
- else if ($data == 89) $data = (string) t('Red Eye, Auto-Mode');
- else if ($data == 93) $data = (string) t('Red Eye, Auto-Mode, Return light not detected');
- else if ($data == 95) $data = (string) t('Red Eye, Auto-Mode, Return light detected');
- else $data = (string) t('Unknown').': '.$data;
-
- } else if ($tag == 'a001') { // ColorSpace
- if ($data == 1) $data = (string) t('sRGB');
- else $data = (string) t('Uncalibrated');
-
- } else if ($tag == 'a002' || $tag == 'a003') { // ExifImageWidth/Height
- $data = $data. ' '.(string) t('pixels');
-
- } else if ($tag == '0103') { // Compression
- if ($data == 1) $data = (string) t('No Compression');
- else if ($data == 6) $data = (string) t('Jpeg Compression');
- else $data = (string) t('Unknown').': '.$data;
-
- } else if ($tag == 'a217') { // SensingMethod
- if ($data == 1) $data = (string) t('Not defined');
- if ($data == 2) $data = (string) t('One Chip Color Area Sensor');
- if ($data == 3) $data = (string) t('Two Chip Color Area Sensor');
- if ($data == 4) $data = (string) t('Three Chip Color Area Sensor');
- if ($data == 5) $data = (string) t('Color Sequential Area Sensor');
- if ($data == 7) $data = (string) t('Trilinear Sensor');
- if ($data == 8) $data = (string) t('Color Sequential Linear Sensor');
- else $data = (string) t('Unknown').': '.$data;
-
- } else if ($tag == '0106') { // PhotometricInterpretation
- if ($data == 1) $data = (string) t('Monochrome');
- else if ($data == 2) $data = (string) t('RGB');
- else if ($data == 6) $data = (string) t('YCbCr');
- else $data = (string) t('Unknown').': '.$data;
- }
- //} else if($tag=="a408" || $tag=="a40a") { // Contrast, Sharpness
- // switch($data) {
- // case 0: $data="Normal"; break;
- // case 1: $data="Soft"; break;
- // case 2: $data="Hard"; break;
- // default: $data="Unknown"; break;
- // }
- //} else if($tag=="a409") { // Saturation
- // switch($data) {
- // case 0: $data="Normal"; break;
- // case 1: $data="Low saturation"; break;
- // case 2: $data="High saturation"; break;
- // default: $data="Unknown"; break;
- // }
- //} else if($tag=="a402") { // Exposure Mode
- // switch($data) {
- // case 0: $data="Auto exposure"; break;
- // case 1: $data="Manual exposure"; break;
- // case 2: $data="Auto bracket"; break;
- // default: $data="Unknown"; break;
- // }
-
- } else if ($type == 'UNDEFINED') {
-
- if ($tag == '9000' || $tag == 'a000' || $tag == '0002') { // ExifVersion,FlashPixVersion,InteroperabilityVersion
- $data=(string) t('version').' '.$data/100;
- }
- if ($tag == 'a300') { // FileSource
- $data = bin2hex($data);
- $data = str_replace('00','',$data);
- $data = str_replace('03',(string) t('Digital Still Camera'),$data);
- }
- if ($tag == 'a301') { // SceneType
- $data = bin2hex($data);
- $data = str_replace('00','',$data);
- $data = str_replace('01',(string) t('Directly Photographed'),$data);
- }
- if ($tag == '9101') { // ComponentsConfiguration
+ break;
+ case 'USHORT':
+ case 'SSHORT':
+ case 'ULONG':
+ case 'SLONG':
+ case 'FLOAT':
+ case 'DOUBLE':
+ $data = rational($data,$type,$intel);
+ switch ($tag) {
+ case '0112': // Orientation
+ // Example of how all of these tag formatters should be...
+ switch ($data) {
+ case 0 : // not set, presume normal
+ case 1 : $data = (string) t('1: Normal (0 deg)'); break;
+ case 2 : $data = (string) t('2: Mirrored'); break;
+ case 3 : $data = (string) t('3: Upside-down'); break;
+ case 4 : $data = (string) t('4: Upside-down Mirrored'); break;
+ case 5 : $data = (string) t('5: 90 deg CW Mirrored'); break;
+ case 6 : $data = (string) t('6: 90 deg CCW'); break;
+ case 7 : $data = (string) t('7: 90 deg CCW Mirrored'); break;
+ case 8 : $data = (string) t('8: 90 deg CW'); break;
+ default : $data = sprintf((string) t('%d: Unknown'),$data); break;
+ }
+ break;
+ case '0128': // ResolutionUnit
+ case 'a210': // FocalPlaneResolutionUnit
+ case '0128': // ThumbnailResolutionUnit
+ switch ($data) {
+ case 1: $data = (string) t('No Unit'); break;
+ case 2: $data = (string) t('Inch'); break;
+ case 3: $data = (string) t('Centimeter'); break;
+ }
+ break;
+ case '0213': // YCbCrPositioning
+ switch ($data) {
+ case 1: $data = (string) t('Center of Pixel Array'); break;
+ case 2: $data = (string) t('Datum Point'); break;
+ }
+ break;
+ case '8822': // ExposureProgram
+ switch ($data) {
+ case 1: $data = (string) t('Manual'); break;
+ case 2: $data = (string) t('Program'); break;
+ case 3: $data = (string) t('Aperture Priority'); break;
+ case 4: $data = (string) t('Shutter Priority'); break;
+ case 5: $data = (string) t('Program Creative'); break;
+ case 6: $data = (string) t('Program Action'); break;
+ case 7: $data = (string) t('Portrait'); break;
+ case 8: $data = (string) t('Landscape'); break;
+ default: $data = (string) t('Unknown').': '.$data; break;
+ }
+ break;
+ case '9207': // MeteringMode
+ switch ($data) {
+ case 1: $data = (string) t('Average'); break;
+ case 2: $data = (string) t('Center Weighted Average'); break;
+ case 3: $data = (string) t('Spot'); break;
+ case 4: $data = (string) t('Multi-Spot'); break;
+ case 5: $data = (string) t('Pattern'); break;
+ case 6: $data = (string) t('Partial'); break;
+ case 255: $data = (string) t('Other'); break;
+ default: $data = (string) t('Unknown').': '.$data; break;
+ }
+ break;
+ case '9208': // LightSource
+ switch ($data) {
+ case 1: $data = (string) t('Daylight'); break;
+ case 2: $data = (string) t('Fluorescent'); break;
+ case 3: $data = (string) t('Tungsten'); break; // 3 Tungsten (Incandescent light)
+ // 4 Flash
+ // 9 Fine Weather
+ case 10: $data = (string) t('Flash'); break; // 10 Cloudy Weather
+ // 11 Shade
+ // 12 Daylight Fluorescent (D 5700 - 7100K)
+ // 13 Day White Fluorescent (N 4600 - 5400K)
+ // 14 Cool White Fluorescent (W 3900 -4500K)
+ // 15 White Fluorescent (WW 3200 - 3700K)
+ // 10 Flash
+ case 17: $data = (string) t('Standard Light A'); break;
+ case 18: $data = (string) t('Standard Light B'); break;
+ case 19: $data = (string) t('Standard Light C'); break;
+ case 20: $data = (string) t('D55'); break;
+ case 21: $data = (string) t('D65'); break;
+ case 22: $data = (string) t('D75'); break;
+ case 23: $data = (string) t('D50'); break;
+ case 24: $data = (string) t('ISO Studio Tungsten'); break;
+ case 255: $data = (string) t('Other'); break;
+ default: $data = (string) t('Unknown').': '.$data; break;
+ }
+ break;
+ case '9209': // Flash
+ switch ($data) {
+ case 0: $data = (string) t('No Flash'); break;
+ case 1: $data = (string) t('Flash'); break;
+ case 5: $data = (string) t('Flash, strobe return light not detected'); break;
+ case 7: $data = (string) t('Flash, strobe return light detected'); break;
+ case 9: $data = (string) t('Compulsory Flash'); break;
+ case 13: $data = (string) t('Compulsory Flash, Return light not detected'); break;
+ case 15: $data = (string) t('Compulsory Flash, Return light detected'); break;
+ case 16: $data = (string) t('No Flash'); break;
+ case 24: $data = (string) t('No Flash'); break;
+ case 25: $data = (string) t('Flash, Auto-Mode'); break;
+ case 29: $data = (string) t('Flash, Auto-Mode, Return light not detected'); break;
+ case 31: $data = (string) t('Flash, Auto-Mode, Return light detected'); break;
+ case 32: $data = (string) t('No Flash'); break;
+ case 65: $data = (string) t('Red Eye'); break;
+ case 69: $data = (string) t('Red Eye, Return light not detected'); break;
+ case 71: $data = (string) t('Red Eye, Return light detected'); break;
+ case 73: $data = (string) t('Red Eye, Compulsory Flash'); break;
+ case 77: $data = (string) t('Red Eye, Compulsory Flash, Return light not detected'); break;
+ case 79: $data = (string) t('Red Eye, Compulsory Flash, Return light detected'); break;
+ case 89: $data = (string) t('Red Eye, Auto-Mode'); break;
+ case 93: $data = (string) t('Red Eye, Auto-Mode, Return light not detected'); break;
+ case 95: $data = (string) t('Red Eye, Auto-Mode, Return light detected'); break;
+ default: $data = (string) t('Unknown').': '.$data; break;
+ }
+ break;
+ case 'a001': // ColorSpace
+ if ($data == 1) $data = (string) t('sRGB');
+ else $data = (string) t('Uncalibrated');
+ break;
+ case 'a002': // ExifImageWidth
+ case 'a003': // ExifImageHeight
+ $data = $data. ' '.(string) t('pixels');
+ break;
+ case '0103': // Compression
+ switch ($data) {
+ case 1: $data = (string) t('No Compression'); break;
+ case 6: $data = (string) t('Jpeg Compression'); break;
+ default: $data = (string) t('Unknown').': '.$data; break;
+ }
+ break;
+ case 'a217': // SensingMethod
+ switch ($data) {
+ case 1: $data = (string) t('Not defined'); break;
+ case 2: $data = (string) t('One Chip Color Area Sensor'); break;
+ case 3: $data = (string) t('Two Chip Color Area Sensor'); break;
+ case 4: $data = (string) t('Three Chip Color Area Sensor'); break;
+ case 5: $data = (string) t('Color Sequential Area Sensor'); break;
+ case 7: $data = (string) t('Trilinear Sensor'); break;
+ case 8: $data = (string) t('Color Sequential Linear Sensor'); break;
+ default: $data = (string) t('Unknown').': '.$data; break;
+ }
+ break;
+ case '0106': // PhotometricInterpretation
+ switch ($data) {
+ case 1: $data = (string) t('Monochrome'); break;
+ case 2: $data = (string) t('RGB'); break;
+ case 6: $data = (string) t('YCbCr'); break;
+ default: $data = (string) t('Unknown').': '.$data; break;
+ }
+ break;
+ //case "a408": // Contrast
+ //case "a40a": //Sharpness
+ // switch($data) {
+ // case 0: $data="Normal"; break;
+ // case 1: $data="Soft"; break;
+ // case 2: $data="Hard"; break;
+ // default: $data="Unknown"; break;
+ // }
+ // break;
+ //case "a409": // Saturation
+ // switch($data) {
+ // case 0: $data="Normal"; break;
+ // case 1: $data="Low saturation"; break;
+ // case 2: $data="High saturation"; break;
+ // default: $data="Unknown"; break;
+ // }
+ // break;
+ //case "a402": // Exposure Mode
+ // switch($data) {
+ // case 0: $data="Auto exposure"; break;
+ // case 1: $data="Manual exposure"; break;
+ // case 2: $data="Auto bracket"; break;
+ // default: $data="Unknown"; break;
+ // }
+ // break;
+ }
+ break;
+ case 'UNDEFINED':
+ switch ($tag) {
+ case '9000': // ExifVersion
+ case 'a000': // FlashPixVersion
+ case '0002': // InteroperabilityVersion
+ $data=(string) t('version').' '.$data/100;
+ break;
+ case 'a300': // FileSource
+ $data = bin2hex($data);
+ $data = str_replace('00','',$data);
+ $data = str_replace('03',(string) t('Digital Still Camera'),$data);
+ break;
+ case 'a301': // SceneType
+ $data = bin2hex($data);
+ $data = str_replace('00','',$data);
+ $data = str_replace('01',(string) t('Directly Photographed'),$data);
+ break;
+ case '9101': // ComponentsConfiguration
+ $data = bin2hex($data);
+ $data = str_replace('01','Y',$data);
+ $data = str_replace('02','Cb',$data);
+ $data = str_replace('03','Cr',$data);
+ $data = str_replace('04','R',$data);
+ $data = str_replace('05','G',$data);
+ $data = str_replace('06','B',$data);
+ $data = str_replace('00','',$data);
+ break;
+ //case "9286": //UserComment
+ // $encoding = rtrim(substr($data, 0, 8));
+ // $data = rtrim(substr($data, 8));
+ // break;
+ }
+ break;
+ default:
$data = bin2hex($data);
- $data = str_replace('01','Y',$data);
- $data = str_replace('02','Cb',$data);
- $data = str_replace('03','Cr',$data);
- $data = str_replace('04','R',$data);
- $data = str_replace('05','G',$data);
- $data = str_replace('06','B',$data);
- $data = str_replace('00','',$data);
- }
- //if($tag=="9286") { //UserComment
- // $encoding = rtrim(substr($data, 0, 8));
- // $data = rtrim(substr($data, 8));
- //}
- } else {
- $data = bin2hex($data);
- if ($intel == 1) $data = intel2Moto($data);
+ if ($intel == 1) $data = intel2Moto($data);
+ break;
}
-
return $data;
}
function formatExposure($data) {
- if ($data > 0) {
+ if (strpos($data,'/')===false) {
if ($data > 1) {
return round($data, 2).' '.(string) t('sec');
} else {
@@ -666,30 +729,30 @@ function read_entry(&$result,$in,$seek,$intel,$ifd_name,$globalOffset) {
if ($result['VerboseOutput'] == 1) {
$result[$ifd_name]['MakerNote']['RawData'] = $data;
}
- if (eregi('NIKON',$make)) {
+ if (preg_match('/NIKON/i',$make)) {
require_once(dirname(__FILE__).'/makers/nikon.php');
parseNikon($data,$result);
$result[$ifd_name]['KnownMaker'] = 1;
- } else if (eregi('OLYMPUS',$make)) {
+ } else if (preg_match('/OLYMPUS/i',$make)) {
require_once(dirname(__FILE__).'/makers/olympus.php');
parseOlympus($data,$result,$seek,$globalOffset);
$result[$ifd_name]['KnownMaker'] = 1;
- } else if (eregi('Canon',$make)) {
+ } else if (preg_match('/Canon/i',$make)) {
require_once(dirname(__FILE__).'/makers/canon.php');
parseCanon($data,$result,$seek,$globalOffset);
$result[$ifd_name]['KnownMaker'] = 1;
- } else if (eregi('FUJIFILM',$make)) {
+ } else if (preg_match('/FUJIFILM/i',$make)) {
require_once(dirname(__FILE__).'/makers/fujifilm.php');
parseFujifilm($data,$result);
$result[$ifd_name]['KnownMaker'] = 1;
- } else if (eregi('SANYO',$make)) {
+ } else if (preg_match('/SANYO/i',$make)) {
require_once(dirname(__FILE__).'/makers/sanyo.php');
parseSanyo($data,$result,$seek,$globalOffset);
$result[$ifd_name]['KnownMaker'] = 1;
- } else if (eregi('Panasonic',$make)) {
- require_once(dirname(__FILE__).'/makers/panasonic.php');
- parsePanasonic($data,$result,$seek,$globalOffset);
- $result[$ifd_name]['KnownMaker'] = 1;
+ } else if (preg_match('/Panasonic/i',$make)) {
+ require_once(dirname(__FILE__).'/makers/panasonic.php');
+ parsePanasonic($data,$result,$seek,$globalOffset);
+ $result[$ifd_name]['KnownMaker'] = 1;
} else {
$result[$ifd_name]['KnownMaker'] = 0;
}
@@ -709,9 +772,9 @@ function read_entry(&$result,$in,$seek,$intel,$ifd_name,$globalOffset) {
$data = bin2hex($data);
if ($intel == 1) $data = intel2Moto($data);
}
- $result[$ifd_name][$tag_name.'_Verbose']['RawData'] = $data;
+ $result[$ifd_name][$tag_name.'_Verbose']['RawData'] = $data;
$result[$ifd_name][$tag_name.'_Verbose']['Type'] = $type;
- $result[$ifd_name][$tag_name.'_Verbose']['Bytes'] = $bytesofdata;
+ $result[$ifd_name][$tag_name.'_Verbose']['Bytes'] = $bytesofdata;
}
}
}
@@ -912,7 +975,7 @@ if ($result['ValidJpeg'] == 1) {
$v = fseek($in,$globalOffset+$ExitOffset);
if ($v == -1) {
$result['Errors'] = $result['Errors']+1;
- $result['Error'][$result['Errors']] = (string) t('Couldnt Find SubIFD');
+ $result['Error'][$result['Errors']] = (string) t('Could not Find SubIFD');
}
//===========================================================
@@ -932,7 +995,12 @@ if ($result['ValidJpeg'] == 1) {
}
// Add the 35mm equivalent focal length:
- $result['SubIFD']['FocalLength35mmEquiv'] = get35mmEquivFocalLength($result);
+ if (isset($result['IFD0']['FocalLengthIn35mmFilm']) && !isset($result['SubIFD']['FocalLengthIn35mmFilm'])) { // found in the wrong place
+ $result['SubIFD']['FocalLengthIn35mmFilm'] = $result['IFD0']['FocalLengthIn35mmFilm'];
+ }
+ if (!isset($result['SubIFD']['FocalLengthIn35mmFilm'])) {
+ $result['SubIFD']['FocalLengthIn35mmFilm'] = get35mmEquivFocalLength($result);
+ }
// Check for IFD1
if (!isset($result['IFD1Offset']) || $result['IFD1Offset'] == 0) {
@@ -944,7 +1012,7 @@ if ($result['ValidJpeg'] == 1) {
$v = fseek($in,$globalOffset+$result['IFD1Offset']);
if ($v == -1) {
$result['Errors'] = $result['Errors']+1;
- $result['Error'][$result['Errors']] = (string) t('Couldnt Find IFD1');
+ $result['Error'][$result['Errors']] = (string) t('Could not Find IFD1');
}
//===========================================================
@@ -984,7 +1052,7 @@ if ($result['ValidJpeg'] == 1) {
$v = fseek($in,$globalOffset+$result['SubIFD']['ExifInteroperabilityOffset']);
if ($v == -1) {
$result['Errors'] = $result['Errors']+1;
- $result['Error'][$result['Errors']] = (string) t('Couldnt Find InteroperabilityIFD');
+ $result['Error'][$result['Errors']] = (string) t('Could not Find InteroperabilityIFD');
}
//===========================================================
@@ -1029,7 +1097,7 @@ function ConvertToFraction($v, &$n, &$d)
//================================================================================================
function get35mmEquivFocalLength(&$result) {
if (isset($result['SubIFD']['ExifImageWidth'])) {
- $width = $result['SubIFD']['ExifImageWidth'];
+ $width = $result['SubIFD']['ExifImageWidth'];
} else {
$width = 0;
}
@@ -1055,7 +1123,7 @@ function get35mmEquivFocalLength(&$result) {
} else {
$fl = 0;
}
-
+
if (($width != 0) && !empty($units) && !empty($xres) && !empty($fl) && !empty($width)) {
$ccdwidth = ($width * $unitfactor) / $xres;
$equivfl = $fl / $ccdwidth*36+0.5;
@@ -1064,10 +1132,4 @@ function get35mmEquivFocalLength(&$result) {
return null;
}
-if (!function_exists('debugLogBacktrace')) {
- // define this function for stand-alone uses if exifier
- function debugLogBacktrace($msg) {
- }
-}
-
?>
diff --git a/modules/exif/lib/makers/canon.php b/modules/exif/lib/makers/canon.php
index 75cf0b7b..aecd266d 100644
--- a/modules/exif/lib/makers/canon.php
+++ b/modules/exif/lib/makers/canon.php
@@ -40,6 +40,7 @@ function lookup_Canon_tag($tag) {
case "0009": $tag = "OwnerName";break;
case "000c": $tag = "CameraSerialNumber";break;
case "000f": $tag = "CustomFunctions";break;
+ case "0095": $tag = "LensInfo";break;
default: $tag = "unknown:".$tag;break;
}
@@ -57,13 +58,7 @@ function formatCanonData($type,$tag,$intel,$data,$exif,&$result) {
if($type=="ASCII") {
$result = $data = str_replace("\0", "", $data);
} else if($type=="URATIONAL" || $type=="SRATIONAL") {
- $data = bin2hex($data);
- if($intel==1) $data = intel2Moto($data);
- $top = hexdec(substr($data,8,8));
- $bottom = hexdec(substr($data,0,8));
- if($bottom!=0) $data=$top/$bottom;
- else if($top==0) $data = 0;
- else $data=$top."/".$bottom;
+ $data = unRational($data,$type,$intel);
if($tag=="0204") { //DigitalZoom
$data=$data."x";
@@ -71,7 +66,7 @@ function formatCanonData($type,$tag,$intel,$data,$exif,&$result) {
} else if($type=="USHORT" || $type=="SSHORT" || $type=="ULONG" || $type=="SLONG" || $type=="FLOAT" || $type=="DOUBLE") {
- $data = bin2hex($data);
+ $data = rational($data,$type,$intel);
$result['RAWDATA'] = $data;
if($tag=="0001") { //first chunk
@@ -377,20 +372,18 @@ function parseCanon($block,&$result,$seek, $globalOffset) {
//2 byte type
$type = bin2hex(substr($block,$place,2));$place+=2;
if($intel==1) $type = intel2Moto($type);
- lookup_type($type,$size);
+ lookup_type($type,$size);
//4 byte count of number of data units
$count = bin2hex(substr($block,$place,4));$place+=4;
if($intel==1) $count = intel2Moto($count);
$bytesofdata = $size*hexdec($count);
-
if($bytesofdata<=0) {
return; //if this value is 0 or less then we have read all the tags we can
}
//4 byte value of data or pointer to data
$value = substr($block,$place,4);$place+=4;
-
if($bytesofdata<=4) {
$data = $value;
} else {
diff --git a/modules/exif/lib/makers/fujifilm.php b/modules/exif/lib/makers/fujifilm.php
index a88e51c3..a1f2f416 100644
--- a/modules/exif/lib/makers/fujifilm.php
+++ b/modules/exif/lib/makers/fujifilm.php
@@ -44,7 +44,6 @@ function lookup_Fujifilm_tag($tag) {
case "1021": $tag = "FocusMode";break;
case "1030": $tag = "SlowSync";break;
case "1031": $tag = "PictureMode";break;
- case "1032": $tag = "Unknown";break;
case "1100": $tag = "ContinuousTakingBracket";break;
case "1200": $tag = "Unknown";break;
case "1300": $tag = "BlurWarning";break;
@@ -66,22 +65,14 @@ function formatFujifilmData($type,$tag,$intel,$data) {
} else if($type=="URATIONAL" || $type=="SRATIONAL") {
- $data = bin2hex($data);
- if($intel==1) $data = intel2Moto($data);
- $top = hexdec(substr($data,8,8));
- $bottom = hexdec(substr($data,0,8));
- if($bottom!=0) $data=$top/$bottom;
- else if($top==0) $data = 0;
- else $data=$top."/".$bottom;
+ $data = unRational($data,$type,$intel);
if($tag=="1011") { //FlashStrength
$data=$data." EV";
}
} else if($type=="USHORT" || $type=="SSHORT" || $type=="ULONG" || $type=="SLONG" || $type=="FLOAT" || $type=="DOUBLE") {
- $data = bin2hex($data);
- if($intel==1) $data = intel2Moto($data);
- $data=hexdec($data);
+ $data =rational($data,$type,$intel);
if($tag=="1001") { //Sharpness
if($data == 1) $data = (string) t("Soft");
diff --git a/modules/exif/lib/makers/gps.php b/modules/exif/lib/makers/gps.php
index 9a6ab137..462aae68 100644
--- a/modules/exif/lib/makers/gps.php
+++ b/modules/exif/lib/makers/gps.php
@@ -73,102 +73,65 @@ function lookup_GPS_tag($tag) {
}
//=================
-// Formats a rational number
-//====================================================================
-function GPSRational($data, $intel) {
-
- if($intel==1) $top = hexdec(substr($data,8,8)); //intel stores them bottom-top
- else $top = hexdec(substr($data,0,8)); //motorola stores them top-bottom
-
- if($intel==1) $bottom = hexdec(substr($data,0,8)); //intel stores them bottom-top
- else $bottom = hexdec(substr($data,8,8)); //motorola stores them top-bottom
-
- if($bottom!=0) $data=$top/$bottom;
- else if($top==0) $data = 0;
- else $data=$top."/".$bottom;
-
- return $data;
-}
-//=================
// Formats Data for the data type
//====================================================================
function formatGPSData($type,$tag,$intel,$data) {
if($type=="ASCII") {
- if($tag=="0001" || $tag=="0003"){ // Latitude Reference, Longitude Reference
- $data = ($data{1} == $data{2} && $data{1} == $data{3}) ? $data{0} : $data;
- }
-
+ if($tag=="0001" || $tag=="0003"){ // Latitude Reference, Longitude Reference
+ $data = ($data{1} == $data{2} && $data{1} == $data{3}) ? $data{0} : $data;
+ }
+
} else if($type=="URATIONAL" || $type=="SRATIONAL") {
- $data = bin2hex($data);
- if($intel==1) $data = intel2Moto($data);
-
- if($intel==1) $top = hexdec(substr($data,8,8)); //intel stores them bottom-top
- else $top = hexdec(substr($data,0,8)); //motorola stores them top-bottom
-
- if($intel==1) $bottom = hexdec(substr($data,0,8)); //intel stores them bottom-top
- else $bottom = hexdec(substr($data,8,8)); //motorola stores them top-bottom
-
- if($type=="SRATIONAL" && $top>2147483647) $top = $top - 4294967296; //this makes the number signed instead of unsigned
-
- if($tag=="0002" || $tag=="0004") { //Latitude, Longitude
-
- if($intel==1){
- $seconds = GPSRational(substr($data,0,16),$intel);
- $hour = GPSRational(substr($data,32,16),$intel);
- } else {
- $hour= GPSRational(substr($data,0,16),$intel);
- $seconds = GPSRational(substr($data,32,16),$intel);
+ if($tag=="0002" || $tag=="0004" || $tag=='0007') { //Latitude, Longitude, Time
+ $datum = array();
+ for ($i=0;$i<strlen($data);$i=$i+8) {
+ array_push($datum,substr($data, $i, 8));
+ }
+ $hour = unRational($datum[0],$type,$intel);
+ $minutes = unRational($datum[1],$type,$intel);
+ $seconds = unRational($datum[2],$type,$intel);
+ if($tag=="0007") { //Time
+ $data = $hour.":".$minutes.":".$seconds;
+ } else {
+ $data = $hour+$minutes/60+$seconds/3600;
}
- $minutes = GPSRational(substr($data,16,16),$intel);
-
- $data = $hour+$minutes/60+$seconds/3600;
- } else if($tag=="0007") { //Time
- $seconds = GPSRational(substr($data,0,16),$intel);
- $minutes = GPSRational(substr($data,16,16),$intel);
- $hour = GPSRational(substr($data,32,16),$intel);
-
- $data = $hour.":".$minutes.":".$seconds;
} else {
- if($bottom!=0) $data=$top/$bottom;
- else if($top==0) $data = 0;
- else $data=$top."/".$bottom;
-
- if($tag=="0006"){
- $data .= 'm';
- }
+ $data = unRational($data,$type,$intel);
+
+ if($tag=="0006"){
+ $data .= 'm';
+ }
}
} else if($type=="USHORT" || $type=="SSHORT" || $type=="ULONG" || $type=="SLONG" || $type=="FLOAT" || $type=="DOUBLE") {
- $data = bin2hex($data);
- if($intel==1) $data = intel2Moto($data);
- $data=hexdec($data);
-
-
+ $data = rational($data,$type,$intel);
+
+
} else if($type=="UNDEFINED") {
-
-
-
+
+
+
} else if($type=="UBYTE") {
$data = bin2hex($data);
if($intel==1) $num = intel2Moto($data);
if($tag=="0000") { // VersionID
- $data = hexdec(substr($data,0,2)) .
+ $data = hexdec(substr($data,0,2)) .
".". hexdec(substr($data,2,2)) .
".". hexdec(substr($data,4,2)) .
".". hexdec(substr($data,6,2));
- } else if($tag=="0005"){ // Altitude Reference
- if($data == "00000000"){ $data = 'Above Sea Level'; }
- else if($data == "01000000"){ $data = 'Below Sea Level'; }
- }
-
+ } else if($tag=="0005"){ // Altitude Reference
+ if($data == "00000000"){ $data = '+'; }
+ else if($data == "01000000"){ $data = '-'; }
+ }
+
} else {
$data = bin2hex($data);
if($intel==1) $data = intel2Moto($data);
}
-
+
return $data;
}
@@ -220,21 +183,26 @@ function parseGPS($block,&$result,$offset,$seek, $globalOffset) {
//4 byte value or pointer to value if larger than 4 bytes
$value = substr($block,$place,4);$place+=4;
-
if($bytesofdata<=4) {
$data = $value;
} else {
- $value = bin2hex($value);
- if($intel==1) $value = intel2Moto($value);
-
- $v = fseek($seek,$globalOffset+hexdec($value)); //offsets are from TIFF header which is 12 bytes from the start of the file
- if($v==0) {
- $data = fread($seek, $bytesofdata);
- } else if($v==-1) {
+ if (strpos('unknown',$tag_name) !== false || $bytesofdata > 1024) {
$result['Errors'] = $result['Errors']++;
+ $data = '';
+ $type = 'ASCII';
+ } else {
+ $value = bin2hex($value);
+ if($intel==1) $value = intel2Moto($value);
+ $v = fseek($seek,$globalOffset+hexdec($value)); //offsets are from TIFF header which is 12 bytes from the start of the file
+ if($v==0) {
+ $data = fread($seek, $bytesofdata);
+ } else {
+ $result['Errors'] = $result['Errors']++;
+ $data = '';
+ $type = 'ASCII';
+ }
}
}
-
if($result['VerboseOutput']==1) {
$result['GPS'][$tag_name] = formatGPSData($type,$tag,$intel,$data);
$result['GPS'][$tag_name."_Verbose"]['RawData'] = bin2hex($data);
diff --git a/modules/exif/lib/makers/nikon.php b/modules/exif/lib/makers/nikon.php
index ebc2af7c..d2fff9a2 100644
--- a/modules/exif/lib/makers/nikon.php
+++ b/modules/exif/lib/makers/nikon.php
@@ -57,8 +57,32 @@ function lookup_Nikon_tag($tag,$model) {
case "0008": $tag = "FlashSetting";break;
case "0009": $tag = "FlashMode";break;
case "000b": $tag = "WhiteBalanceFine";break;
+ case "000c": $tag = "WB_RBLevels";break;
+ case "000d": $tag = "ProgramShift";break;
+ case "000e": $tag = "ExposureDifference";break;
case "000f": $tag = "ISOSelection";break;
- case "0013": $tag = "ISOSelection2";break;
+ case "0010": $tag = "DataDump";break;
+ case "0011": $tag = "NikonPreview";break;
+ case "0012": $tag = "FlashExposureComp";break;
+ case "0013": $tag = "ISOSetting2";break;
+ case "0014": $tag = "ColorBalanceA";break;
+ case "0016": $tag = "ImageBoundary";break;
+ case "0017": $tag = "FlashExposureComp";break;
+ case "0018": $tag = "FlashExposureBracketValue";break;
+ case "0019": $tag = "ExposureBracketValue";break;
+ case "001a": $tag = "ImageProcessing";break;
+ case "001b": $tag = "CropHiSpeed";break;
+ case "001c": $tag = "ExposureTuning";break;
+ case "001d": $tag = "SerialNumber";break;
+ case "001e": $tag = "ColorSpace";break;
+ case "001f": $tag = "VRInfo";break;
+ case "0020": $tag = "ImageAuthentication";break;
+ case "0022": $tag = "ActiveD-Lighting";break;
+ case "0023": $tag = "PictureControl";break;
+ case "0024": $tag = "WorldTime";break;
+ case "0025": $tag = "ISOInfo";break;
+ case "002a": $tag = "VignetteControl";break;
+ case "002b": $tag = "DistortInfo";break;
case "0080": $tag = "ImageAdjustment";break;
case "0081": $tag = "ToneCompensation";break;
case "0082": $tag = "Adapter";break;
@@ -68,11 +92,16 @@ function lookup_Nikon_tag($tag,$model) {
case "0086": $tag = "DigitalZoom";break;
case "0087": $tag = "FlashUsed";break;
case "0088": $tag = "AFFocusPosition";break;
+ case "0089": $tag = "ShootingMode";break;
+ case "008b": $tag = "LensFStops";break;
+ case "008c": $tag = "ContrastCurve";break;
case "008d": $tag = "ColorMode";break;
case "0090": $tag = "LightType";break;
+ case "0092": $tag = "HueAdjustment";break;
+ case "0093": $tag = "NEFCompression";break;
case "0094": $tag = "Saturation";break;
case "0095": $tag = "NoiseReduction";break;
- case "0010": $tag = "DataDump";break;
+ case "009a": $tag = "SensorPixelSize";break;
default: $tag = "unknown:".$tag;break;
}
@@ -81,120 +110,172 @@ function lookup_Nikon_tag($tag,$model) {
return $tag;
}
+
//=================
// Formats Data for the data type
//====================================================================
function formatNikonData($type,$tag,$intel,$model,$data) {
-
- if($type=="ASCII") {
-
-
- } else if($type=="URATIONAL" || $type=="SRATIONAL") {
- $data = bin2hex($data);
- if($intel==1) $data = intel2Moto($data);
- $top = hexdec(substr($data,8,8));
- $bottom = hexdec(substr($data,0,8));
- if($bottom!=0) $data=$top/$bottom;
- else if($top==0) $data = 0;
- else $data=$top."/".$bottom;
-
- if($tag=="0085" && $model==1) { //ManualFocusDistance
- $data=$data." m";
- }
- if($tag=="0086" && $model==1) { //DigitalZoom
- $data=$data."x";
- }
- if($tag=="000a" && $model==0) { //DigitalZoom
- $data=$data."x";
- }
- } else if($type=="USHORT" || $type=="SSHORT" || $type=="ULONG" || $type=="SLONG" || $type=="FLOAT" || $type=="DOUBLE") {
- $data = bin2hex($data);
- if($intel==1) $data = intel2Moto($data);
- $data=hexdec($data);
-
- if($tag=="0003" && $model==0) { //Quality
- if($data == 1) $data = (string) t("VGA Basic");
- else if($data == 2) $data = (string) t("VGA Normal");
- else if($data == 3) $data = (string) t("VGA Fine");
- else if($data == 4) $data = (string) t("SXGA Basic");
- else if($data == 5) $data = (string) t("SXGA Normal");
- else if($data == 6) $data = (string) t("SXGA Fine");
- else $data = (string) t("Unknown").": ".$data;
- }
- if($tag=="0004" && $model==0) { //Color
- if($data == 1) $data = (string) t("Color");
- else if($data == 2) $data = (string) t("Monochrome");
- else $data = (string) t("Unknown").": ".$data;
- }
- if($tag=="0005" && $model==0) { //Image Adjustment
- if($data == 0) $data = (string) t("Normal");
- else if($data == 1) $data = (string) t("Bright+");
- else if($data == 2) $data = (string) t("Bright-");
- else if($data == 3) $data = (string) t("Contrast+");
- else if($data == 4) $data = (string) t("Contrast-");
- else $data = (string) t("Unknown").": ".$data;
- }
- if($tag=="0006" && $model==0) { //CCD Sensitivity
- if($data == 0) $data = "ISO-80";
- else if($data == 2) $data = "ISO-160";
- else if($data == 4) $data = "ISO-320";
- else if($data == 5) $data = "ISO-100";
- else $data = (string) t("Unknown").": ".$data;
- }
- if($tag=="0007" && $model==0) { //White Balance
- if($data == 0) $data = (string) t("Auto");
- else if($data == 1) $data = (string) t("Preset");
- else if($data == 2) $data = (string) t("Daylight");
- else if($data == 3) $data = (string) t("Incandescense");
- else if($data == 4) $data = (string) t("Flourescence");
- else if($data == 5) $data = (string) t("Cloudy");
- else if($data == 6) $data = (string) t("SpeedLight");
- else $data = (string) t("Unknown").": ".$data;
- }
- if($tag=="000b" && $model==0) { //Converter
- if($data == 0) $data = (string) t("None");
- else if($data == 1) $data = (string) t("Fisheye");
- else $data = (string) t("Unknown").": ".$data;
- }
- } else if($type=="UNDEFINED") {
-
- if($tag=="0001" && $model==1) { //Unknown (Version?)
- $data=$data/100;
- }
- if($tag=="0088" && $model==1) { //AF Focus Position
- $temp = (string) t("Center");
+ switch ($type) {
+ case "ASCII":
+ break; // do nothing!
+ case "URATIONAL":
+ case"SRATIONAL":
+ switch ($tag) {
+ case '0084': // LensInfo
+ $minFL = unRational(substr($data,0,8),$type,$intel);
+ $maxFL = unRational(substr($data,8,8),$type,$intel);
+ $minSP = unRational(substr($data,16,8),$type,$intel);
+ $maxSP = unRational(substr($data,24,8),$type,$intel);
+ if ($minFL == $maxFL) {
+ $data = sprintf('%0.0f f/%0.0f',$minFL,$minSP);
+ } elseif ($minSP == $maxSP) {
+ $data = sprintf('%0.0f-%0.0fmm f/%0.1f',$minFL,$maxFL,$minSP);
+ } else {
+ $data = sprintf('%0.0f-%0.0fmm f/%0.1f-%0.1f',$minFL,$maxFL,$minSP,$maxSP);
+ }
+ break;
+ case "0085":
+ if ($model==1) $data=unRational($data,$type,$intel)." m"; //ManualFocusDistance
+ break;
+ case "0086":
+ if ($model==1) $data=unRational($data,$type,$intel)."x"; //DigitalZoom
+ break;
+ case "000a":
+ if ($model==0) $data=unRational($data,$type,$intel)."x"; //DigitalZoom
+ break;
+ default:
+ $data=unRational($data,$type,$intel);
+ break;
+ }
+ break;
+ case "USHORT":
+ case $type=="SSHORT":
+ case $type=="ULONG":
+ case $type=="SLONG":
+ case $type=="FLOAT":
+ case $type=="DOUBLE":
+ $data = rational($data,$type,$intel);
+ switch ($tag) {
+ case "0003":
+ if ($model==0) { //Quality
+ switch ($data) {
+ case 1: $data = (string) t("VGA Basic"); break;
+ case 2: $data = (string) t("VGA Normal"); break;
+ case 3: $data = (string) t("VGA Fine"); break;
+ case 4: $data = (string) t("SXGA Basic"); break;
+ case 5: $data = (string) t("SXGA Normal"); break;
+ case 6: $data = (string) t("SXGA Fine"); break;
+ default: $data = (string) t("Unknown").": ".$data; break;
+ }
+ }
+ break;
+ case "0004":
+ if ($model==0) { //Color
+ switch ($data) {
+ case 1: $data = (string) t("Color"); break;
+ case 2: $data = (string) t("Monochrome"); break;
+ default: $data = (string) t("Unknown").": ".$data; break;
+ }
+ }
+ break;
+ case "0005":
+ if ($model==0) { //Image Adjustment
+ switch ($data) {
+ case 0: $data = (string) t("Normal"); break;
+ case 1: $data = (string) t("Bright+"); break;
+ case 2: $data = (string) t("Bright-"); break;
+ case 3: $data = (string) t("Contrast+"); break;
+ case 4: $data = (string) t("Contrast-"); break;
+ default: $data = (string) t("Unknown").": ".$data; break;
+ }
+ }
+ break;
+ case "0006":
+ if ($model==0) { //CCD Sensitivity
+ switch($data) {
+ case 0: $data = "ISO-80"; break;
+ case 2: $data = "ISO-160"; break;
+ case 4: $data = "ISO-320"; break;
+ case 5: $data = "ISO-100"; break;
+ default: $data = (string) t("Unknown").": ".$data; break;
+ }
+ }
+ break;
+ case "0007":
+ if ($model==0) { //White Balance
+ switch ($data) {
+ case 0: $data = (string) t("Auto"); break;
+ case 1: $data = (string) t("Preset"); break;
+ case 2: $data = (string) t("Daylight"); break;
+ case 3: $data = (string) t("Incandescence"); break;
+ case 4: $data = (string) t("Fluorescence"); break;
+ case 5: $data = (string) t("Cloudy"); break;
+ case 6: $data = (string) t("SpeedLight"); break;
+ default: $data = (string) t("Unknown").": ".$data; break;
+ }
+ }
+ break;
+ case "000b":
+ if ($model==0) { //Converter
+ switch ($data) {
+ case 0: $data = (string) t("None"); break;
+ case 1: $data = (string) t("Fisheye"); break;
+ default: $data = (string) t("Unknown").": ".$data; break;
+ }
+ }
+ break;
+ }
+ break;
+ case "UNDEFINED":
+ switch ($tag) {
+ case "0001":
+ if ($model==1) $data=$data/100; break; //Unknown (Version?)
+ break;
+ case "0088":
+ if ($model==1) { //AF Focus Position
+ $temp = (string) t("Center");
+ $data = bin2hex($data);
+ $data = str_replace("01","Top",$data);
+ $data = str_replace("02","Bottom",$data);
+ $data = str_replace("03","Left",$data);
+ $data = str_replace("04","Right",$data);
+ $data = str_replace("00","",$data);
+ if(strlen($data)==0) $data = $temp;
+ }
+ break;
+ }
+ break;
+ default:
$data = bin2hex($data);
- $data = str_replace("01","Top",$data);
- $data = str_replace("02","Bottom",$data);
- $data = str_replace("03","Left",$data);
- $data = str_replace("04","Right",$data);
- $data = str_replace("00","",$data);
- if(strlen($data)==0) $data = $temp;
- }
-
- } else {
- $data = bin2hex($data);
- if($intel==1) $data = intel2Moto($data);
-
- if($tag=="0083" && $model==1) { //Lens Type
- $data = hexdec(substr($data,0,2));
- if($data == 0) $data = (string) t("AF non D");
- else if($data == 1) $data = (string) t("Manual");
- else if($data == 2) $data = "AF-D or AF-S";
- else if($data == 6) $data = "AF-D G";
- else if($data == 10) $data = "AF-D VR";
- else $data = (string) t("Unknown").": ".$data;
- }
- if($tag=="0087" && $model==1) { //Flash type
- $data = hexdec(substr($data,0,2));
- if($data == 0) $data = (string) t("Did Not Fire");
- else if($data == 4) $data = (string) t("Unknown");
- else if($data == 7) $data = (string) t("External");
- else if($data == 9) $data = (string) t("On Camera");
- else $data = (string) t("Unknown").": ".$data;
- }
+ if($intel==1) $data = intel2Moto($data);
+ switch ($tag) {
+ case "0083":
+ if ($model==1) { //Lens Type
+ $data = hexdec(substr($data,0,2));
+ switch ($data) {
+ case 0: $data = (string) t("AF non D"); break;
+ case 1: $data = (string) t("Manual"); break;
+ case 2: $data = "AF-D or AF-S"; break;
+ case 6: $data = "AF-D G"; break;
+ case 10: $data = "AF-D VR"; break;
+ case 14: $data = "AF-D G VR"; break;
+ default: $data = (string) t("Unknown").": ".$data; break;
+ }
+ }
+ break;
+ case "0087":
+ if ($model==1) { //Flash type
+ $data = hexdec(substr($data,0,2));
+ if($data == 0) $data = (string) t("Did Not Fire");
+ else if($data == 4) $data = (string) t("Unknown");
+ else if($data == 7) $data = (string) t("External");
+ else if($data == 9) $data = (string) t("On Camera");
+ else $data = (string) t("Unknown").": ".$data;
+ }
+ break;
+ }
+ break;
}
-
return $data;
}
diff --git a/modules/exif/lib/makers/olympus.php b/modules/exif/lib/makers/olympus.php
index 17334bd8..3382fc79 100644
--- a/modules/exif/lib/makers/olympus.php
+++ b/modules/exif/lib/makers/olympus.php
@@ -57,24 +57,17 @@ function formatOlympusData($type,$tag,$intel,$data) {
if($type=="ASCII") {
} else if($type=="URATIONAL" || $type=="SRATIONAL") {
- $data = bin2hex($data);
+ $data = unRational($data,$type,$intel);
if($intel==1) $data = intel2Moto($data);
- $top = hexdec(substr($data,8,8));
- $bottom = hexdec(substr($data,0,8));
- if($bottom!=0) $data=$top/$bottom;
- else if($top==0) $data = 0;
- else $data=$top."/".$bottom;
if($tag=="0204") { //DigitalZoom
$data=$data."x";
}
if($tag=="0205") { //Unknown2
- $data=$top."/".$bottom;
+
}
} else if($type=="USHORT" || $type=="SSHORT" || $type=="ULONG" || $type=="SLONG" || $type=="FLOAT" || $type=="DOUBLE") {
- $data = bin2hex($data);
- if($intel==1) $data = intel2Moto($data);
- $data=hexdec($data);
+ $data = rational($data,$type,$intel);
if($tag=="0201") { //JPEGQuality
if($data == 1) $data = "SQ";
diff --git a/modules/exif/lib/makers/panasonic.php b/modules/exif/lib/makers/panasonic.php
index d82d374d..47a05996 100644
--- a/modules/exif/lib/makers/panasonic.php
+++ b/modules/exif/lib/makers/panasonic.php
@@ -85,18 +85,10 @@ function formatPanasonicData($type,$tag,$intel,$data) {
}
} else if($type=="URATIONAL" || $type=="SRATIONAL") {
- $data = bin2hex($data);
- if($intel==1) $data = intel2Moto($data);
- $top = hexdec(substr($data,8,8));
- $bottom = hexdec(substr($data,0,8));
- if($bottom!=0) $data=$top/$bottom;
- else if($top==0) $data = 0;
- else $data=$top."/".$bottom;
+ $data = unRational($data,$type,$intel);
} else if($type=="USHORT" || $type=="SSHORT" || $type=="ULONG" || $type=="SLONG" || $type=="FLOAT" || $type=="DOUBLE") {
- $data = bin2hex($data);
- if($intel==1) $data = intel2Moto($data);
- $data=hexdec($data);
+ $data = rational($data,$type,$intel);
if($tag=="0001") { //Image Quality
if($data == 2) $data = (string) t("High");
diff --git a/modules/exif/lib/makers/sanyo.php b/modules/exif/lib/makers/sanyo.php
index 661741dd..3eef201e 100644
--- a/modules/exif/lib/makers/sanyo.php
+++ b/modules/exif/lib/makers/sanyo.php
@@ -54,19 +54,10 @@ function formatSanyoData($type,$tag,$intel,$data) {
} else if($type=="URATIONAL" || $type=="SRATIONAL") {
- $data = bin2hex($data);
- if($intel==1) $data = intel2Moto($data);
- $top = hexdec(substr($data,8,8));
- $bottom = hexdec(substr($data,0,8));
- if($bottom!=0) $data=$top/$bottom;
- else if($top==0) $data = 0;
- else $data=$top."/".$bottom;
-
+ $data = unRational($data,$type,$intel);
} else if($type=="USHORT" || $type=="SSHORT" || $type=="ULONG" || $type=="SLONG" || $type=="FLOAT" || $type=="DOUBLE") {
- $data = bin2hex($data);
- if($intel==1) $data = intel2Moto($data);
- $data=hexdec($data);
+ $data = rational($data,$type,$intel);
if($tag=="0200") { //SpecialMode
if($data == 0) $data = (string) t("Normal");
diff --git a/modules/exif/tests/Exif_Test.php b/modules/exif/tests/Exif_Test.php
index cf5af851..404b6cde 100644
--- a/modules/exif/tests/Exif_Test.php
+++ b/modules/exif/tests/Exif_Test.php
@@ -33,8 +33,8 @@ class Exif_Test extends Gallery_Unit_Test_Case {
array("caption" => "Exposure Time", "value" => "1/60 sec"),
array("caption" => "Flash", "value" => "No Flash"),
array("caption" => "Focal Length", "value" => "50 mm"),
- array("caption" => "ISO", "value" => "6553700"),
- array("caption" => "Metering Mode", "value" => "Multi-Segment"),
+ array("caption" => "ISO", "value" => "100"),
+ array("caption" => "Metering Mode", "value" => "Pattern"),
array("caption" => "Date/Time", "value" => "2008:03:17 17:41:25"),
array("caption" => "Copyright", "value" => "(C) 2008 - T. Almdal"),
array("caption" => "Orientation", "value" => "1: Normal (0 deg)"),
diff --git a/modules/g2_import/controllers/admin_g2_import.php b/modules/g2_import/controllers/admin_g2_import.php
index b1018560..b9427f79 100644
--- a/modules/g2_import/controllers/admin_g2_import.php
+++ b/modules/g2_import/controllers/admin_g2_import.php
@@ -33,7 +33,7 @@ class Admin_g2_import_Controller extends Admin_Controller {
$view->page_title = t("Gallery 2 import");
$view->content = new View("admin_g2_import.html");
$view->content->form = $this->_get_import_form();
- $view->content->version = '';
+ $view->content->version = "";
if (g2_import::is_initialized()) {
$view->content->g2_stats = $g2_stats;
@@ -41,6 +41,8 @@ class Admin_g2_import_Controller extends Admin_Controller {
$view->content->thumb_size = module::get_var("gallery", "thumb_size");
$view->content->resize_size = module::get_var("gallery", "resize_size");
$view->content->version = g2_import::version();
+ } else if (g2_import::is_configured()) {
+ $view->content->form->configure_g2_import->embed_path->add_error("invalid", 1);
}
g2_import::restore_error_reporting();
print $view;
@@ -58,7 +60,7 @@ class Admin_g2_import_Controller extends Admin_Controller {
}
if (g2_import::is_valid_embed_path($embed_path)) {
- message::success("Gallery 2 path saved.");
+ message::success(t("Gallery 2 path saved"));
module::set_var("g2_import", "embed_path", $embed_path);
url::redirect("admin/g2_import");
} else {
diff --git a/modules/g2_import/helpers/g2_import.php b/modules/g2_import/helpers/g2_import.php
index 575d02bb..c0ea09d6 100644
--- a/modules/g2_import/helpers/g2_import.php
+++ b/modules/g2_import/helpers/g2_import.php
@@ -438,8 +438,15 @@ class g2_import_Core {
// Only consider G2's first sort order
$g2_order = explode("|", $g2_album->getOrderBy() . "");
$g2_order = $g2_order[0];
+ if (empty($g2_order)) {
+ $g2_order = g2(GalleryCoreApi::getPluginParameter('module', 'core', 'default.orderBy'));
+ }
$g2_order_direction = explode("|", $g2_album->getOrderDirection() . "");
$g2_order_direction = $g2_order_direction[0];
+ if (empty($g2_order_direction)) {
+ $g2_order_direction =
+ g2(GalleryCoreApi::getPluginParameter('module', 'core', 'default.orderDirection'));
+ }
if (array_key_exists($g2_order, $order_map)) {
$album->sort_column = $order_map[$g2_order];
$album->sort_order = $direction_map[$g2_order_direction];
@@ -502,7 +509,7 @@ class g2_import_Core {
}
try {
$g3_album->save();
- graphics::generate($g2_album);
+ graphics::generate($g3_album);
} catch (Exception $e) {
return (string) new G2_Import_Exception(
t("Failed to generate an album highlight for album '%name'.",
@@ -826,6 +833,7 @@ class g2_import_Core {
$text .= " ";
}
$text .= $g2_comment->getComment();
+ $text = html_entity_decode($text);
// Just import the fields we know about. Do this outside of the comment API for now so that
// we don't trigger spam filtering events
@@ -835,6 +843,7 @@ class g2_import_Core {
if ($comment->author_id == identity::guest()->id) {
$comment->guest_name = $g2_comment->getAuthor();
$comment->guest_name or $comment->guest_name = (string) t("Anonymous coward");
+ $comment->guest_email = "unknown@nobody.com";
}
$comment->item_id = $item_id;
$comment->text = self::_transform_bbcode($text);
diff --git a/modules/gallery/controllers/admin.php b/modules/gallery/controllers/admin.php
index 787a2138..40dd260b 100644
--- a/modules/gallery/controllers/admin.php
+++ b/modules/gallery/controllers/admin.php
@@ -22,7 +22,12 @@ class Admin_Controller extends Controller {
public function __construct($theme=null) {
if (!identity::active_user()->admin) {
- access::forbidden();
+ if (identity::active_user()->guest) {
+ Session::instance()->set("continue_url", url::abs_current(true));
+ url::redirect("login");
+ } else {
+ access::forbidden();
+ }
}
parent::__construct();
@@ -69,6 +74,7 @@ class Admin_Controller extends Controller {
$result = new stdClass();
$result->result = "success";
if ($time_remaining < 30) {
+ message::success(t("Automatically logged out of the admin area for your security"));
$result->location = url::abs_site("");
}
@@ -78,7 +84,7 @@ class Admin_Controller extends Controller {
private static function _prompt_for_reauth($controller_name, $args) {
if (request::method() == "get" && !request::is_ajax()) {
// Avoid anti-phishing protection by passing the url as session variable.
- Session::instance()->set("continue_url", url::current(true));
+ Session::instance()->set("continue_url", url::abs_current(true));
}
url::redirect("reauthenticate");
}
diff --git a/modules/gallery/controllers/albums.php b/modules/gallery/controllers/albums.php
index ea15418f..eaa09be5 100644
--- a/modules/gallery/controllers/albums.php
+++ b/modules/gallery/controllers/albums.php
@@ -73,8 +73,8 @@ class Albums_Controller extends Items_Controller {
// We can't use math in ORM or the query builder, so do this by hand. It's important
// that we do this with math, otherwise concurrent accesses will damage accuracy.
- db::query(
- "UPDATE {items} SET `view_count` = `view_count` + 1 WHERE `id` = $album->id");
+ db::query("UPDATE {items} SET `view_count` = `view_count` + 1 WHERE `id` = $album->id")
+ ->execute();
print $template;
}
diff --git a/modules/gallery/controllers/file_proxy.php b/modules/gallery/controllers/file_proxy.php
index fff90ec5..32690fc0 100644
--- a/modules/gallery/controllers/file_proxy.php
+++ b/modules/gallery/controllers/file_proxy.php
@@ -60,12 +60,12 @@ class File_Proxy_Controller extends Controller {
foreach (explode("/", $path) as $path_part) {
$encoded_path[] = rawurlencode($path_part);
}
-
+ $encoded_path = implode("/", $encoded_path);
// We now have the relative path to the item. Search for it in the path cache
// The patch cache is urlencoded so re-encode the path. (it was decoded earlier to
// insure that the paths are normalized.
$item = ORM::factory("item")
- ->where("relative_path_cache", "=", implode("/", $encoded_path))->find();
+ ->where("relative_path_cache", "=", $encoded_path)->find();
if (!$item->loaded()) {
// We didn't turn it up. It's possible that the relative_path_cache is out of date here.
// There was fallback code, but bharat deleted it in 8f1bca74. If it turns out to be
@@ -76,7 +76,7 @@ class File_Proxy_Controller extends Controller {
// So try some alternate types:
if (preg_match('/.jpg$/', $path)) {
foreach (array("flv", "mp4") as $ext) {
- $movie_path = preg_replace('/.jpg$/', ".$ext", $path);
+ $movie_path = preg_replace('/.jpg$/', ".$ext", $encoded_path);
$item = ORM::factory("item")->where("relative_path_cache", "=", $movie_path)->find();
if ($item->loaded()) {
break;
diff --git a/modules/gallery/controllers/simple_uploader.php b/modules/gallery/controllers/flash_uploader.php
index c7e5031b..f7da5124 100644
--- a/modules/gallery/controllers/simple_uploader.php
+++ b/modules/gallery/controllers/flash_uploader.php
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
-class Simple_Uploader_Controller extends Controller {
+class Flash_Uploader_Controller extends Controller {
public function app($id) {
$item = ORM::factory("item", $id);
access::required("view", $item);
@@ -109,7 +109,7 @@ class Simple_Uploader_Controller extends Controller {
}
private function _get_add_form($album) {
- $form = new Forge("simple_uploader/finish", "", "post", array("id" => "g-add-photos-form"));
+ $form = new Forge("flash_uploader/finish", "", "post", array("id" => "g-add-photos-form"));
$group = $form->group("add_photos")
->label(t("Add photos to %album_title", array("album_title" => html::purify($album->title))));
$group->uploadify("uploadify")->album($album);
diff --git a/modules/gallery/controllers/login.php b/modules/gallery/controllers/login.php
index 40125476..2b60316b 100644
--- a/modules/gallery/controllers/login.php
+++ b/modules/gallery/controllers/login.php
@@ -38,15 +38,18 @@ class Login_Controller extends Controller {
}
public function html() {
- print auth::get_login_form("login/auth_html");
+ $view = new Theme_View("page.html", "other", "login");
+ $view->page_title = t("Login");
+ $view->content = auth::get_login_form("login/auth_html");
+ print $view;
}
public function auth_html() {
access::verify_csrf();
- $continue_url = Session::instance()->get("continue_url", null);
list ($valid, $form) = $this->_auth("login/auth_html");
if ($valid) {
+ $continue_url = $form->continue_url->value;
url::redirect($continue_url ? $continue_url : item::root()->abs_url());
} else {
$view = new Theme_View("page.html", "other", "login");
diff --git a/modules/gallery/controllers/logout.php b/modules/gallery/controllers/logout.php
index 967dad49..20fa8074 100644
--- a/modules/gallery/controllers/logout.php
+++ b/modules/gallery/controllers/logout.php
@@ -21,14 +21,9 @@ class Logout_Controller extends Controller {
public function index() {
access::verify_csrf();
auth::logout();
- if ($continue_url = Input::instance()->get("continue")) {
- $item = url::get_item_from_uri($continue_url);
- if (access::can("view", $item)) {
- // Don't use url::redirect() because it'll call url::site() and munge the continue url.
- header("Location: $continue_url");
- } else {
- url::redirect(item::root()->abs_url());
- }
+ if ($continue_url = Input::instance()->get("continue_url")) {
+ url::redirect($continue_url);
}
+ url::redirect(item::root()->abs_url());
}
} \ No newline at end of file
diff --git a/modules/gallery/controllers/packager.php b/modules/gallery/controllers/packager.php
index 6eafd9df..835cb903 100644
--- a/modules/gallery/controllers/packager.php
+++ b/modules/gallery/controllers/packager.php
@@ -63,8 +63,8 @@ class Packager_Controller extends Controller {
module::load_modules();
- foreach (array("user", "comment", "organize", "info", "rss",
- "search", "slideshow", "tag") as $module_name) {
+ foreach (array("user", "comment", "organize", "info", "rest",
+ "rss", "search", "slideshow", "tag") as $module_name) {
module::install($module_name);
module::activate($module_name);
}
@@ -163,9 +163,11 @@ class Packager_Controller extends Controller {
$paths = array();
foreach($objects as $name => $file){
- if ($file->getBasename() == "database.php") {
+ $path = $file->getPath();
+ $basename = $file->getBasename();
+ if ($basename == "database.php" || $basename == "." || $basename == "..") {
continue;
- } else if (basename($file->getPath()) == "logs" && $file->getBasename() != ".htaccess") {
+ } else if (basename($path) == "logs" && $basename != ".htaccess") {
continue;
}
@@ -186,6 +188,7 @@ class Packager_Controller extends Controller {
foreach ($paths as $path) {
fwrite($fd, "!file_exists($path) && mkdir($path);\n");
}
+ ksort($files);
foreach ($files as $file => $contents) {
fwrite($fd, "file_put_contents($file, base64_decode(\"$contents\"));\n");
}
diff --git a/modules/gallery/controllers/quick.php b/modules/gallery/controllers/quick.php
index 813d1a93..6cfbbc62 100644
--- a/modules/gallery/controllers/quick.php
+++ b/modules/gallery/controllers/quick.php
@@ -58,12 +58,12 @@ class Quick_Controller extends Controller {
if (Input::instance()->get("page_type") == "collection") {
print json_encode(
- array("src" => $item->thumb_url() . "?rnd=" . rand(),
+ array("src" => $item->thumb_url(),
"width" => $item->thumb_width,
"height" => $item->thumb_height));
} else {
print json_encode(
- array("src" => $item->resize_url() . "?rnd=" . rand(),
+ array("src" => $item->resize_url(),
"width" => $item->resize_width,
"height" => $item->resize_height));
}
diff --git a/modules/gallery/controllers/reauthenticate.php b/modules/gallery/controllers/reauthenticate.php
index 3503d80a..acb27f6a 100644
--- a/modules/gallery/controllers/reauthenticate.php
+++ b/modules/gallery/controllers/reauthenticate.php
@@ -37,8 +37,7 @@ class Reauthenticate_Controller extends Controller {
if ($valid) {
message::success(t("Successfully re-authenticated!"));
module::event("user_auth", $user);
- $continue_url = Session::instance()->get_once("continue_url", "admin");
- url::redirect($continue_url);
+ url::redirect($form->continue_url->value);
} else {
$name = $user->name;
log::warning("user", t("Failed re-authentication for %name", array("name" => $name)));
@@ -59,6 +58,7 @@ class Reauthenticate_Controller extends Controller {
private static function _form() {
$form = new Forge("reauthenticate/auth", "", "post", array("id" => "g-reauthenticate-form"));
$form->set_attr('class', "g-narrow");
+ $form->hidden("continue_url")->value(Session::instance()->get("continue_url", "admin"));
$group = $form->group("reauthenticate")->label(t("Re-authenticate"));
$group->password("password")->label(t("Password"))->id("g-password")->class(null)
->callback("auth::validate_too_many_failed_auth_attempts")
diff --git a/modules/gallery/css/gallery.css b/modules/gallery/css/gallery.css
index c2fb97e8..08bd4749 100644
--- a/modules/gallery/css/gallery.css
+++ b/modules/gallery/css/gallery.css
@@ -30,7 +30,7 @@
#g-add-photos-canvas object,
#g-add-photos-button {
left: 137px;
- margin: 0 0 .5em 0;
+ margin: .5em 0;
padding: .4em 1em;
position: absolute;
top: 0;
@@ -38,10 +38,13 @@
}
#g-add-photos-canvas object {
- margin: 0;
z-index: 100;
}
+#g-add-photos-canvas .uploadifyQueue {
+ margin-top: .5em;
+}
+
#g-add-photos-canvas .uploadifyQueueItem {
margin: 0;
}
@@ -81,6 +84,10 @@
clear: both;
}
+#g-edit-permissions-form th {
+ text-align: center;
+}
+
#g-edit-permissions-form td {
background-image: none;
}
@@ -197,3 +204,11 @@
.rtl #g-user-profile .g-avatar {
margin-left: .6em;
}
+
+.rtl #g-languages-form table {
+ margin: 0 0 1em 3em;
+}
+
+.rtl #g-translations ol {
+ margin: 0 2em 1em 0;
+}
diff --git a/modules/gallery/helpers/MY_url.php b/modules/gallery/helpers/MY_url.php
index 57ce9623..877c5ada 100644
--- a/modules/gallery/helpers/MY_url.php
+++ b/modules/gallery/helpers/MY_url.php
@@ -70,8 +70,7 @@ class url extends url_Core {
* Just like url::file() except that it returns an absolute URI
*/
static function abs_file($path) {
- return url::base(
- false, (empty($_SERVER['HTTPS']) || $_SERVER['HTTPS'] === 'off') ? 'http' : 'https') . $path;
+ return url::base(false, request::protocol()) . $path;
}
/**
@@ -79,8 +78,7 @@ class url extends url_Core {
* doesn't take a protocol parameter.
*/
static function abs_site($path) {
- return url::site(
- $path, (empty($_SERVER['HTTPS']) || $_SERVER['HTTPS'] === 'off') ? 'http' : 'https');
+ return url::site($path, request::protocol());
}
/**
diff --git a/modules/gallery/helpers/auth.php b/modules/gallery/helpers/auth.php
index 1a9fe869..48b5fc32 100644
--- a/modules/gallery/helpers/auth.php
+++ b/modules/gallery/helpers/auth.php
@@ -21,6 +21,7 @@ class auth_Core {
static function get_login_form($url) {
$form = new Forge($url, "", "post", array("id" => "g-login-form"));
$form->set_attr("class", "g-narrow");
+ $form->hidden("continue_url")->value(Session::instance()->get("continue_url"));
$group = $form->group("login")->label(t("Login"));
$group->input("name")->label(t("Username"))->id("g-username")->class(null)
->callback("auth::validate_too_many_failed_logins")
diff --git a/modules/gallery/helpers/gallery.php b/modules/gallery/helpers/gallery.php
index 7f7db10b..d4078209 100644
--- a/modules/gallery/helpers/gallery.php
+++ b/modules/gallery/helpers/gallery.php
@@ -18,7 +18,7 @@
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
class gallery_Core {
- const VERSION = "3.0 RC1 (Santa Fe)";
+ const VERSION = "3.0 RC2 (Santa Fe)";
/**
* If Gallery is in maintenance mode, then force all non-admins to get routed to a "This site is
diff --git a/modules/gallery/helpers/gallery_block.php b/modules/gallery/helpers/gallery_block.php
index 08ce21b7..cb28cbcd 100644
--- a/modules/gallery/helpers/gallery_block.php
+++ b/modules/gallery/helpers/gallery_block.php
@@ -70,9 +70,9 @@ class gallery_block_Core {
$block->css_id = "g-platform";
$block->title = t("Platform information");
$block->content = new View("admin_block_platform.html");
- if (@is_readable("/proc/loadavg")) {
+ if (@is_readable("/proc/loadavg") && $first_line = current(@file("/proc/loadavg"))) {
$block->content->load_average =
- join(" ", array_slice(explode(" ", current(file("/proc/loadavg"))), 0, 3));
+ join(" ", array_slice(explode(" ", $first_line), 0, 3));
} else {
$block->content->load_average = t("Unavailable");
}
diff --git a/modules/gallery/helpers/gallery_event.php b/modules/gallery/helpers/gallery_event.php
index 2416f2e5..272fd205 100644
--- a/modules/gallery/helpers/gallery_event.php
+++ b/modules/gallery/helpers/gallery_event.php
@@ -98,6 +98,15 @@ class gallery_event_Core {
static function item_deleted($item) {
access::delete_item($item);
+ // Find any other albums that had the deleted item as the album cover and null it out.
+ // In some cases this may leave us with a missing album cover up in this item's parent
+ // hierarchy, but in most cases it'll work out fine.
+ foreach (ORM::factory("item")
+ ->where("album_cover_item_id", "=", $item->id)
+ ->find_all() as $parent) {
+ item::remove_album_cover($parent);
+ }
+
$parent = $item->parent();
if (!$parent->album_cover_item_id) {
// Assume we deleted the album cover and pick a new one. Choosing the first photo in the
@@ -157,17 +166,28 @@ class gallery_event_Core {
->view("login_current_user.html")
->url(user_profile::url($user->id))
->label($user->display_name()));
+
+ if (isset($theme->item)) {
+ if (access::user_can(identity::guest(), "view", $theme->item)) {
+ $continue_url = $theme->item->abs_url();
+ } else {
+ $continue_url = item::root()->abs_url();
+ }
+ } else {
+ $continue_url = url::abs_current();
+ }
+
$menu->append(Menu::factory("link")
->id("user_menu_logout")
->css_id("g-logout-link")
- ->url(url::site("logout?csrf=$csrf&amp;continue=" .
- urlencode(url::abs_current())))
+ ->url(url::site("logout?csrf=$csrf&amp;continue_url=" .
+ urlencode($continue_url)))
->label(t("Logout")));
}
}
}
- static function site_menu($menu, $theme) {
+ static function site_menu($menu, $theme, $item_css_selector) {
if ($theme->page_subtype != "login") {
$menu->append(Menu::factory("link")
->id("home")
@@ -191,7 +211,7 @@ class gallery_event_Core {
$add_menu->append(Menu::factory("dialog")
->id("add_photos_item")
->label(t("Add photos"))
- ->url(url::site("simple_uploader/app/$item->id")));
+ ->url(url::site("flash_uploader/app/$item->id")));
if ($item->is_album()) {
$add_menu->append(Menu::factory("dialog")
->id("add_album_item")
@@ -208,14 +228,17 @@ class gallery_event_Core {
case "album":
$option_text = t("Album options");
$edit_text = t("Edit album");
+ $delete_text = t("Delete album");
break;
case "movie":
$option_text = t("Movie options");
$edit_text = t("Edit movie");
+ $delete_text = t("Delete movie");
break;
default:
$option_text = t("Photo options");
$edit_text = t("Edit photo");
+ $delete_text = t("Delete photo");
}
$menu->append($options_menu = Menu::factory("submenu")
@@ -238,6 +261,63 @@ class gallery_event_Core {
}
}
}
+
+ $csrf = access::csrf_token();
+ $theme_item = $theme->item();
+ $page_type = $theme->page_type();
+ if ($can_edit && $item->is_photo() && graphics::can("rotate")) {
+ $options_menu
+ ->append(
+ Menu::factory("ajax_link")
+ ->id("rotate_ccw")
+ ->label(t("Rotate 90° counter clockwise"))
+ ->css_class("ui-icon-rotate-ccw")
+ ->ajax_handler("function(data) { " .
+ "\$.gallery_replace_image(data, \$('$item_css_selector')) }")
+ ->url(url::site("quick/rotate/$item->id/ccw?csrf=$csrf&amp;from_id=$theme_item->id&amp;page_type=$page_type")))
+ ->append(
+ Menu::factory("ajax_link")
+ ->id("rotate_cw")
+ ->label(t("Rotate 90° clockwise"))
+ ->css_class("ui-icon-rotate-cw")
+ ->ajax_handler("function(data) { " .
+ "\$.gallery_replace_image(data, \$('$item_css_selector')) }")
+ ->url(url::site("quick/rotate/$item->id/cw?csrf=$csrf&amp;from_id=$theme_item->id&amp;page_type=$page_type")));
+ }
+
+ if ($item->id != item::root()->id) {
+ $parent = $item->parent();
+ if (access::can("edit", $parent)) {
+ // We can't make this item the highlight if it's an album with no album cover, or if it's
+ // already the album cover.
+ if (($item->type == "album" && empty($item->album_cover_item_id)) ||
+ ($item->type == "album" && $parent->album_cover_item_id == $item->album_cover_item_id) ||
+ $parent->album_cover_item_id == $item->id) {
+ $disabledState = " ui-state-disabled";
+ } else {
+ $disabledState = " ";
+ }
+
+ if ($item->parent()->id != 1) {
+ $options_menu
+ ->append(
+ Menu::factory("ajax_link")
+ ->id("make_album_cover")
+ ->label(t("Choose as the album cover"))
+ ->css_class("ui-icon-star")
+ ->ajax_handler("function(data) { window.location.reload() }")
+ ->url(url::site("quick/make_album_cover/$item->id?csrf=$csrf")));
+ }
+ $options_menu
+ ->append(
+ Menu::factory("dialog")
+ ->id("delete")
+ ->label($delete_text)
+ ->css_class("ui-icon-trash")
+ ->css_class("g-quick-delete")
+ ->url(url::site("quick/form_delete/$item->id?csrf=$csrf&amp;from_id=$theme_item->id&amp;page_type=$page_type")));
+ }
+ }
}
if (identity::active_user()->admin) {
@@ -394,7 +474,6 @@ class gallery_event_Core {
->id("delete")
->label($delete_title)
->css_class("ui-icon-trash")
- ->css_class("g-quick-delete")
->url(url::site("quick/form_delete/$item->id?csrf=$csrf&amp;from_id=$theme_item->id&amp;page_type=$page_type")));
}
@@ -404,7 +483,7 @@ class gallery_event_Core {
->id("add_item")
->label(t("Add a photo"))
->css_class("ui-icon-plus")
- ->url(url::site("simple_uploader/app/$item->id")))
+ ->url(url::site("flash_uploader/app/$item->id")))
->append(Menu::factory("dialog")
->id("add_album")
->label(t("Add an album"))
diff --git a/modules/gallery/helpers/gallery_rss.php b/modules/gallery/helpers/gallery_rss.php
index 9c528c0e..bec34912 100644
--- a/modules/gallery/helpers/gallery_rss.php
+++ b/modules/gallery/helpers/gallery_rss.php
@@ -28,18 +28,18 @@ class gallery_rss_Core {
$feed = new stdClass();
switch ($feed_id) {
case "latest":
- $feed->children = ORM::factory("item")
+ $feed->items = ORM::factory("item")
->viewable()
->where("type", "<>", "album")
->order_by("created", "DESC")
->find_all($limit, $offset);
- $all_children = ORM::factory("item")
+ $all_items = ORM::factory("item")
->viewable()
->where("type", "<>", "album")
->order_by("created", "DESC");
- $feed->max_pages = ceil($all_children->find_all()->count() / $limit);
+ $feed->max_pages = ceil($all_items->find_all()->count() / $limit);
$feed->title = t("Recent updates");
$feed->description = t("Recent updates");
return $feed;
@@ -48,7 +48,7 @@ class gallery_rss_Core {
$item = ORM::factory("item", $id);
access::required("view", $item);
- $feed->children = $item
+ $feed->items = $item
->viewable()
->descendants($limit, $offset, array(array("type", "=", "photo")));
$feed->max_pages = ceil(
diff --git a/modules/gallery/helpers/item.php b/modules/gallery/helpers/item.php
index 43c93225..aef68c6e 100644
--- a/modules/gallery/helpers/item.php
+++ b/modules/gallery/helpers/item.php
@@ -136,7 +136,7 @@ class item_Core {
*/
static function convert_filename_to_title($filename) {
$title = strtr($filename, "_", " ");
- $title = preg_replace("/\..*?$/", "", $title);
+ $title = preg_replace("/\..{3,4}$/", "", $title);
$title = preg_replace("/ +/", " ", $title);
return $title;
}
@@ -162,6 +162,8 @@ class item_Core {
"quick/delete/$item->id?page_type=$page_type", "", "post", array("id" => "g-confirm-delete"));
$group = $form->group("confirm_delete")->label(t("Confirm Deletion"));
$group->submit("")->value(t("Delete"));
+ $form->script("")
+ ->url(url::abs_file("modules/gallery/js/item_form_delete.js"));
return $form;
}
@@ -209,17 +211,14 @@ class item_Core {
/**
* Return a query to get a random Item_Model, with optional filters
- *
- * @param array (optional) where tuple
*/
- static function random_query($where=null) {
+ static function random_query() {
// Pick a random number and find the item that's got nearest smaller number.
// This approach works best when the random numbers in the system are roughly evenly
// distributed so this is going to be more efficient with larger data sets.
return ORM::factory("item")
->viewable()
->where("rand_key", "<", ((float)mt_rand()) / (float)mt_getrandmax())
- ->merge_where($where)
->order_by("rand_key", "DESC");
}
} \ No newline at end of file
diff --git a/modules/gallery/helpers/item_rest.php b/modules/gallery/helpers/item_rest.php
index 36d2ca62..6869181d 100644
--- a/modules/gallery/helpers/item_rest.php
+++ b/modules/gallery/helpers/item_rest.php
@@ -126,18 +126,19 @@ class item_rest_Core {
}
}
}
+ $item->save();
- $weight = 0;
- if (isset($request->params->members)) {
+ if (isset($request->params->members) && $item->sort_column == "weight") {
+ $weight = 0;
foreach ($request->params->members as $url) {
$child = rest::resolve($url);
if ($child->parent_id == $item->id && $child->weight != $weight) {
- $child->weight = $weight++;
+ $child->weight = $weight;
$child->save();
}
+ $weight++;
}
}
- $item->save();
}
static function post($request) {
@@ -151,7 +152,7 @@ class item_rest_Core {
$item->type = "album";
$item->parent_id = $parent->id;
$item->name = $entity->name;
- $item->title = isset($entity->title) ? $entity->title : $name;
+ $item->title = isset($entity->title) ? $entity->title : $entity->name;
$item->description = isset($entity->description) ? $entity->description : null;
$item->slug = isset($entity->slug) ? $entity->slug : null;
$item->save();
@@ -159,18 +160,23 @@ class item_rest_Core {
case "photo":
case "movie":
- $item->type = $entity->type;
- $item->parent_id = $parent->id;
- $item->set_data_file($request->file);
- $item->name = $entity->name;
- $item->title = isset($entity->title) ? $entity->title : $entity->name;
- $item->description = isset($entity->description) ? $entity->description : null;
- $item->slug = isset($entity->slug) ? $entity->slug : null;
- $item->save();
- break;
+ if (empty($request->file)) {
+ throw new Rest_Exception(
+ "Bad Request", 400, array("errors" => array("file" => t("Upload failed"))));
+ }
+ $item->type = $entity->type;
+ $item->parent_id = $parent->id;
+ $item->set_data_file($request->file);
+ $item->name = $entity->name;
+ $item->title = isset($entity->title) ? $entity->title : $entity->name;
+ $item->description = isset($entity->description) ? $entity->description : null;
+ $item->slug = isset($entity->slug) ? $entity->slug : null;
+ $item->save();
+ break;
default:
- throw new Rest_Exception("Invalid type: $entity->type", 400);
+ throw new Rest_Exception(
+ "Bad Request", 400, array("errors" => array("type" => "invalid")));
}
return array("url" => rest::url("item", $item));
diff --git a/modules/gallery/helpers/items_rest.php b/modules/gallery/helpers/items_rest.php
index 5d8e80b2..9cca9a54 100644
--- a/modules/gallery/helpers/items_rest.php
+++ b/modules/gallery/helpers/items_rest.php
@@ -18,28 +18,74 @@
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
class items_rest_Core {
+ /**
+ * To retrieve a collection of items, you can specify the following query parameters to specify
+ * the type of the collection. If both are specified, then the url parameter is used and the
+ * ancestors_for is ignored. Specifying the "type" parameter with the urls parameter, will
+ * filter the results based on the specified type. Using the type parameter with the
+ * ancestors_for parameter makes no sense and will be ignored.
+ *
+ * urls=url1,url2,url3
+ * return items that match the specified urls. Typically used to return the member detail
+ *
+ * ancestors_for=url
+ * return the ancestors of the specified item
+ *
+ * type=<comma separate list of photo, movie or album>
+ * limit the type to types in this list. eg, "type=photo,movie"
+ */
static function get($request) {
-
$items = array();
- if (isset($request->params->url)) {
- foreach (json_decode($request->params->url) as $url) {
+ if (isset($request->params->urls)) {
+ foreach (json_decode($request->params->urls) as $url) {
+ if (isset($request->params->type)) {
+ $types = explode(",", $request->params->type);
+ }
$item = rest::resolve($url);
if (access::can("view", $item)) {
- $item_rest = array("url" => $url,
- "entity" => $item->as_restful_array(),
- "relationship" => rest::relationships("item", $item));
- if ($item->type == "album") {
- $members = array();
- foreach ($item->children() as $child) {
- $members[] = rest::url("item", $child);
+ if (isset($types)) {
+ if (in_array($item->type, $types)) {
+ $items[] = items_rest::_format_restful_item($item);
}
- $item_rest["members"] = $members;
+ } else {
+ $items[] = items_rest::_format_restful_item($item);
}
- $items[] = $item_rest;
}
}
+ } else if (isset($request->params->ancestors_for)) {
+ $item = rest::resolve($request->params->ancestors_for);
+ if (!access::can("view", $item)) {
+ throw new Kohana_404_Exception();
+ }
+ $items[] = items_rest::_format_restful_item($item);
+ while (($item = $item->parent()) != null) {
+ array_unshift($items, items_rest::_format_restful_item($item));
+ };
}
return $items;
}
+
+ static function resolve($id) {
+ $item = ORM::factory("item", $id);
+ if (!access::can("view", $item)) {
+ throw new Kohana_404_Exception();
+ }
+ return $item;
+ }
+
+ private static function _format_restful_item($item) {
+ $item_rest = array("url" => rest::url("item", $item),
+ "entity" => $item->as_restful_array(),
+ "relationships" => rest::relationships("item", $item));
+ if ($item->type == "album") {
+ $members = array();
+ foreach ($item->children() as $child) {
+ $members[] = rest::url("item", $child);
+ }
+ $item_rest["members"] = $members;
+ }
+
+ return $item_rest;
+ }
}
diff --git a/modules/gallery/helpers/message.php b/modules/gallery/helpers/message.php
index 047eb2c7..1f69e2a9 100644
--- a/modules/gallery/helpers/message.php
+++ b/modules/gallery/helpers/message.php
@@ -78,6 +78,7 @@ class message_Core {
$messages = Session::instance()->get_once("messages", array());
foreach ($messages as $msg) {
+ $msg[0] = str_replace("__CSRF__", access::csrf_token(), $msg[0]);
$buf[] = "<li class=\"" . self::severity_class($msg[1]) . "\">$msg[0]</li>";
}
if ($buf) {
diff --git a/modules/gallery/helpers/module.php b/modules/gallery/helpers/module.php
index 18d65ed5..5134c7b3 100644
--- a/modules/gallery/helpers/module.php
+++ b/modules/gallery/helpers/module.php
@@ -214,13 +214,6 @@ class module_Core {
throw new Exception("@todo UNKNOWN_MODULE");
}
}
-
- // Now the module is upgraded so deactivate it, but we can'it deactivae gallery or the
- // current identity provider.
- $identity_provider = module::get_var("gallery", "identity_provider", "user");
- if (!in_array($module_name, array("gallery", $identity_provider)) ) {
- self::deactivate($module_name);
- }
module::load_modules();
$version_after = module::get_version($module_name);
diff --git a/modules/gallery/helpers/photo.php b/modules/gallery/helpers/photo.php
index f20d37a3..73cd60c0 100644
--- a/modules/gallery/helpers/photo.php
+++ b/modules/gallery/helpers/photo.php
@@ -26,7 +26,7 @@
class photo_Core {
static function get_edit_form($photo) {
$form = new Forge("photos/update/$photo->id", "", "post", array("id" => "g-edit-photo-form"));
- $form->hidden("from_id");
+ $form->hidden("from_id")->value($photo->id);
$group = $form->group("edit_item")->label(t("Edit Photo"));
$group->input("title")->label(t("Title"))->value($photo->title)
->error_messages("required", t("You must provide a title"))
diff --git a/modules/gallery/helpers/site_status.php b/modules/gallery/helpers/site_status.php
index 759eb382..13c42dda 100644
--- a/modules/gallery/helpers/site_status.php
+++ b/modules/gallery/helpers/site_status.php
@@ -100,7 +100,7 @@ class site_status_Core {
}
$buf = array();
foreach (ORM::factory("message")->find_all() as $msg) {
- $value = str_replace('__CSRF__', access::csrf_token(), $msg->value);
+ $value = str_replace("__CSRF__", access::csrf_token(), $msg->value);
$buf[] = "<li class=\"" . self::severity_class($msg->severity) . "\">$value</li>";
}
diff --git a/modules/gallery/helpers/theme.php b/modules/gallery/helpers/theme.php
index 980ee11a..3589a5b7 100644
--- a/modules/gallery/helpers/theme.php
+++ b/modules/gallery/helpers/theme.php
@@ -53,13 +53,22 @@ class theme_Core {
if (file_exists(THEMEPATH . self::$site_theme_name . "/admin")) {
array_unshift($modules, THEMEPATH . self::$site_theme_name . "/admin");
}
+ // Admins can override the site theme, temporarily. This lets us preview themes.
+ if (identity::active_user()->admin && $override = $input->get("theme")) {
+ if (file_exists(THEMEPATH . $override)) {
+ self::$admin_theme_name = $override;
+ array_unshift($modules, THEMEPATH . self::$admin_theme_name);
+ } else {
+ Kohana_Log::add("error", "Missing override admin theme: '$override'");
+ }
+ }
} else {
// Admins can override the site theme, temporarily. This lets us preview themes.
if (identity::active_user()->admin && $override = $input->get("theme")) {
if (file_exists(THEMEPATH . $override)) {
self::$site_theme_name = $override;
} else {
- Kohana_Log::add("error", "Missing override theme: '$override'");
+ Kohana_Log::add("error", "Missing override site theme: '$override'");
}
}
array_unshift($modules, THEMEPATH . self::$site_theme_name);
@@ -70,7 +79,7 @@ class theme_Core {
static function get_edit_form_admin() {
$form = new Forge("admin/theme_options/save/", "", null, array("id" =>"g-theme-options-form"));
- $group = $form->group("edit_theme");
+ $group = $form->group("edit_theme")->label(t("Theme layout"));
$group->input("page_size")->label(t("Items per page"))->id("g-page-size")
->rules("required|valid_digit")
->error_messages("required", t("You must enter a number"))
@@ -95,7 +104,8 @@ class theme_Core {
module::event("theme_edit_form", $form);
- $group = $form->group("buttons");
+ $group = $form->group("buttons")
+ ->set_attr("style","border: none");
$group->submit("")->value(t("Save"));
return $form;
}
diff --git a/modules/gallery/hooks/init_gallery.php b/modules/gallery/hooks/init_gallery.php
index 10383e9a..64e44b56 100644
--- a/modules/gallery/hooks/init_gallery.php
+++ b/modules/gallery/hooks/init_gallery.php
@@ -24,6 +24,15 @@ if (!file_exists(VARPATH . "database.php")) {
url::redirect(url::abs_file("installer"));
}
+// Simple and cheap test to make sure that the database config is ok. Do this before we do
+// anything else database related.
+try {
+ Database::instance()->connect();
+} catch (Kohana_PHP_Exception $e) {
+ print "Database configuration error. Please check var/database.php";
+ exit;
+}
+
Event::add("system.ready", array("Gallery_I18n", "instance"));
Event::add("system.ready", array("module", "load_modules"));
Event::add("system.ready", array("gallery", "ready"));
diff --git a/modules/gallery/js/item_form_delete.js b/modules/gallery/js/item_form_delete.js
new file mode 100644
index 00000000..fa3f24a2
--- /dev/null
+++ b/modules/gallery/js/item_form_delete.js
@@ -0,0 +1,5 @@
+$("#g-confirm-delete").submit(
+ function() {
+ $("#g-confirm-delete input[type=submit]").gallery_show_loading();
+ }
+);
diff --git a/modules/gallery/js/l10n_client.js b/modules/gallery/js/l10n_client.js
index a1170e2d..a1b970e7 100644
--- a/modules/gallery/js/l10n_client.js
+++ b/modules/gallery/js/l10n_client.js
@@ -60,25 +60,21 @@ jQuery.extend(Gallery, {
$('#l10n-client').height('22em').removeClass('hidden');
//$('#l10n-client').slideUp();
$('#g-minimize-l10n').text("_");
- /*
- * This CSS clashes with Gallery's CSS, probably due to
- * YUI's grid / floats.
- if(!$.browser.msie) {
- $('body').css('border-bottom', '22em solid #fff');
- }
- */
+ // This CSS clashes with Gallery's CSS, probably due to
+ // YUI's grid / floats.
+ // if(!$.browser.msie) {
+ // $('body').css('border-bottom', '22em solid #fff');
+ // }
$.cookie('Gallery_l10n_client', '1', {expires: 7, path: '/'});
break;
case 0:
$('#l10n-client-string-select, #l10n-client-string-editor, #l10n-client .labels .label').hide();
$('#l10n-client').height('2em').addClass('hidden');
// TODO: Localize this message
- $('#g-minimize-l10n').text(MSG_TRANSLATE_TEXT);
- /*
- if(!$.browser.msie) {
- $('body').css('border-bottom', '0px');
- }
- */
+ $('#g-minimize-l10n').text(MSG_TRANSLATE_TEXT);
+ // if(!$.browser.msie) {
+ // $('body').css('border-bottom', '0px');
+ // }
$.cookie('Gallery_l10n_client', '0', {expires: 7, path: '/'});
break;
}
diff --git a/modules/gallery/libraries/MY_Kohana_Exception.php b/modules/gallery/libraries/MY_Kohana_Exception.php
index e7ebdb1f..72cb2ac0 100644
--- a/modules/gallery/libraries/MY_Kohana_Exception.php
+++ b/modules/gallery/libraries/MY_Kohana_Exception.php
@@ -29,70 +29,6 @@ class Kohana_Exception extends Kohana_Exception_Core {
$e->getTraceAsString());
}
- public static function handle(Exception $e) {
- if ($e instanceof ORM_Validation_Exception) {
- Kohana_Log::add("error", "Validation errors: " . print_r($e->validation->errors(), 1));
- }
- try {
- $user = identity::active_user();
- $try_themed_view = $user && !$user->admin;
- } catch (Exception $e2) {
- $try_themed_view = false;
- }
-
- if ($try_themed_view) {
- try {
- return self::_show_themed_error_page($e);
- } catch (Exception $e3) {
- Kohana_Log::add("error", "Exception in exception handling code: " . self::text($e3));
- return parent::handle($e);
- }
- } else {
- return parent::handle($e);
- }
- }
-
- /**
- * Shows a themed error page.
- * @see Kohana_Exception::handle
- */
- private static function _show_themed_error_page(Exception $e) {
- // Create a text version of the exception
- $error = Kohana_Exception::text($e);
-
- // Add this exception to the log
- Kohana_Log::add('error', $error);
-
- // Manually save logs after exceptions
- Kohana_Log::save();
-
- if (!headers_sent()) {
- if ($e instanceof Kohana_Exception) {
- $e->sendHeaders();
- } else {
- header("HTTP/1.1 500 Internal Server Error");
- }
- }
-
- $view = new Theme_View("page.html", "other", "error");
- if ($e instanceof Kohana_404_Exception) {
- $view->page_title = t("Dang... Page not found!");
- $view->content = new View("error_404.html");
- $user = identity::active_user();
- $view->content->is_guest = $user && $user->guest;
- if ($view->content->is_guest) {
- $view->content->login_form = new View("login_ajax.html");
- $view->content->login_form->form = auth::get_login_form("login/auth_html");
- // Avoid anti-phishing protection by passing the url as session variable.
- Session::instance()->set("continue_url", url::current(true));
- }
- } else {
- $view->page_title = t("Dang... Something went wrong!");
- $view->content = new View("error.html");
- }
- print $view;
- }
-
/**
* @see Kohana_Exception::dump()
*/
diff --git a/modules/gallery/libraries/Theme_View.php b/modules/gallery/libraries/Theme_View.php
index 8b432fb6..6246c6f1 100644
--- a/modules/gallery/libraries/Theme_View.php
+++ b/modules/gallery/libraries/Theme_View.php
@@ -86,9 +86,9 @@ class Theme_View_Core extends Gallery_View {
return $menu->render();
}
- public function site_menu() {
+ public function site_menu($item_css_selector) {
$menu = Menu::factory("root");
- module::event("site_menu", $menu, $this);
+ module::event("site_menu", $menu, $this, $item_css_selector);
return $menu->render();
}
diff --git a/modules/gallery/models/item.php b/modules/gallery/models/item.php
index 7fc37325..4d05e4da 100644
--- a/modules/gallery/models/item.php
+++ b/modules/gallery/models/item.php
@@ -671,10 +671,23 @@ class Item_Model extends ORM_MPTT {
*/
public function movie_img($extra_attrs) {
$v = new View("movieplayer.html");
- $v->attrs = array_merge($extra_attrs,
- array("style" => "display:block;width:{$this->width}px;height:{$this->height}px"));
+ $max_size = module::get_var("gallery", "resize_size", 640);
+ $width = $this->width;
+ $height = $this->height;
+ if ($width > $max_size || $height > $max_size) {
+ if ($width > $height) {
+ $height *= $max_size / $width;
+ $width = $max_size;
+ } else {
+ $width *= $max_size / $height;
+ $height = $max_size;
+ }
+ }
+
+ $v->attrs = array_merge($extra_attrs, array("style" => "width:{$width}px;height:{$height}px",
+ "class" => "g-movie"));
if (empty($v->attrs["id"])) {
- $v->attrs["id"] = "g-movie-id-{$this->id}";
+ $v->attrs["id"] = "g-item-id-{$this->id}";
}
return $v;
}
@@ -944,6 +957,7 @@ class Item_Model extends ORM_MPTT {
$data["resize_url"] = $tmp;
}
$data["thumb_url"] = $this->thumb_url(true);
+ $data["can_edit"] = access::can("edit", $this);
// Elide some internal-only data that is going to cause confusion in the client.
foreach (array("relative_path_cache", "relative_url_cache", "left_ptr", "right_ptr",
diff --git a/modules/gallery/tests/File_Structure_Test.php b/modules/gallery/tests/File_Structure_Test.php
index 39df9f06..96e0b758 100644
--- a/modules/gallery/tests/File_Structure_Test.php
+++ b/modules/gallery/tests/File_Structure_Test.php
@@ -23,13 +23,18 @@ class File_Structure_Test extends Gallery_Unit_Test_Case {
public function no_trailing_closing_php_tag_test() {
$dir = new GalleryCodeFilterIterator(
new RecursiveIteratorIterator(new RecursiveDirectoryIterator(DOCROOT)));
+ $count = 0;
foreach ($dir as $file) {
+ $count++;
if (!preg_match("|\.html\.php$|", $file->getPathname())) {
$this->assert_false(
preg_match('/\?\>\s*$/', file_get_contents($file)),
"{$file->getPathname()} ends in ?>");
}
}
+
+ $this->assert_true($count > 500, "We should have analyzed at least this 500 files");
+ $this->assert_true($count < 1000, "We shouldn't be shipping 1000 files!");
}
public function view_files_correct_suffix_test() {
@@ -42,8 +47,8 @@ class File_Structure_Test extends Gallery_Unit_Test_Case {
if (strpos($file, "views")) {
$this->assert_true(
- preg_match("#/views/.*?(\.html|mrss|txt)\.php$#", $file->getPathname()),
- "{$file->getPathname()} should end in .{html,mrss,txt}.php");
+ preg_match("#/views/.*?\.(html|mrss|txt|json)\.php$#", $file->getPathname()),
+ "{$file->getPathname()} should end in .{html,mrss,txt,json}.php");
}
}
}
diff --git a/modules/gallery/tests/Gallery_Filters.php b/modules/gallery/tests/Gallery_Filters.php
index 4e32553b..052990d5 100644
--- a/modules/gallery/tests/Gallery_Filters.php
+++ b/modules/gallery/tests/Gallery_Filters.php
@@ -28,8 +28,11 @@ class GalleryCodeFilterIterator extends FilterIterator {
public function accept() {
// Skip anything that we didn"t write
$path_name = $this->getInnerIterator()->getPathName();
+ $file_name = $this->getInnerIterator()->getFileName();
return !(
- strpos($path_name, ".svn") ||
+ $file_name == "." ||
+ $file_name == ".." ||
+ strpos($path_name, DOCROOT . ".git") !== false ||
strpos($path_name, DOCROOT . "test") !== false ||
strpos($path_name, DOCROOT . "var") !== false ||
strpos($path_name, MODPATH . "forge") !== false ||
diff --git a/modules/gallery/tests/Item_Helper_Test.php b/modules/gallery/tests/Item_Helper_Test.php
index 4771b11a..eb2458cb 100644
--- a/modules/gallery/tests/Item_Helper_Test.php
+++ b/modules/gallery/tests/Item_Helper_Test.php
@@ -41,6 +41,11 @@ class Item_Helper_Test extends Gallery_Unit_Test_Case {
ORM::factory("item")->viewable()->where("id", "=", $item->id)->count_all());
}
+ public function convert_filename_to_title_test() {
+ $this->assert_equal("foo", item::convert_filename_to_title("foo.jpg"));
+ $this->assert_equal("foo.bar", item::convert_filename_to_title("foo.bar.jpg"));
+ }
+
public function convert_filename_to_slug_test() {
$this->assert_equal("foo", item::convert_filename_to_slug("{[foo]}"));
$this->assert_equal("foo-bar", item::convert_filename_to_slug("{[foo!@#!$@#^$@($!(@bar]}"));
@@ -106,15 +111,18 @@ class Item_Helper_Test extends Gallery_Unit_Test_Case {
$this->assert_not_same($rand, $photo2->slug);
}
- public function delete_cover_photo_picks_new_album_cover() {
- $album = test::random_album();
+ public function delete_cover_photo_picks_new_album_cover_test() {
+ $parent = test::random_album();
+ $album = test::random_album($parent);
$photo1 = test::random_photo($album);
// At this point, $photo1 is the album cover. We verify this in
// Item_Model_Test::first_photo_becomes_album_cover
$photo2 = test::random_photo($album);
$photo1->delete();
$album->reload();
+ $parent->reload();
$this->assert_same($photo2->id, $album->album_cover_item_id);
+ $this->assert_same($photo2->id, $parent->album_cover_item_id);
}
}
diff --git a/modules/gallery/tests/Item_Model_Test.php b/modules/gallery/tests/Item_Model_Test.php
index 15aa2d8c..907cfe24 100644
--- a/modules/gallery/tests/Item_Model_Test.php
+++ b/modules/gallery/tests/Item_Model_Test.php
@@ -18,6 +18,10 @@
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
class Item_Model_Test extends Gallery_Unit_Test_Case {
+ public function teardown() {
+ identity::set_active_user(identity::admin_user());
+ }
+
public function saving_sets_created_and_updated_dates_test() {
$item = test::random_photo();
$this->assert_true(!empty($item->created));
@@ -364,6 +368,15 @@ class Item_Model_Test extends Gallery_Unit_Test_Case {
$this->assert_true(!array_key_exists("album_cover_item_id", $result));
}
+ public function as_restful_array_with_edit_bit_test() {
+ $response = item::root()->as_restful_array(true);
+ $this->assert_true($response["can_edit"]);
+
+ identity::set_active_user(identity::guest());
+ $response = item::root()->as_restful_array(true);
+ $this->assert_false($response["can_edit"]);
+ }
+
public function first_photo_becomes_album_cover() {
$album = test::random_album();
$photo = test::random_photo($album);
diff --git a/modules/gallery/tests/Item_Rest_Helper_Test.php b/modules/gallery/tests/Item_Rest_Helper_Test.php
index 0b5e0471..a2ab534b 100644
--- a/modules/gallery/tests/Item_Rest_Helper_Test.php
+++ b/modules/gallery/tests/Item_Rest_Helper_Test.php
@@ -43,6 +43,8 @@ class Item_Rest_Helper_Test extends Gallery_Unit_Test_Case {
array("url" => rest::url("item", $album1),
"entity" => $album1->as_restful_array(),
"relationships" => array(
+ "comments" => array(
+ "url" => rest::url("item_comments", $album1)),
"tags" => array(
"url" => rest::url("item_tags", $album1),
"members" => array())),
@@ -58,6 +60,8 @@ class Item_Rest_Helper_Test extends Gallery_Unit_Test_Case {
array("url" => rest::url("item", $album1),
"entity" => $album1->as_restful_array(),
"relationships" => array(
+ "comments" => array(
+ "url" => rest::url("item_comments", $album1)),
"tags" => array(
"url" => rest::url("item_tags", $album1),
"members" => array())),
@@ -73,6 +77,8 @@ class Item_Rest_Helper_Test extends Gallery_Unit_Test_Case {
array("url" => rest::url("item", $album1),
"entity" => $album1->as_restful_array(),
"relationships" => array(
+ "comments" => array(
+ "url" => rest::url("item_comments", $album1)),
"tags" => array(
"url" => rest::url("item_tags", $album1),
"members" => array())),
@@ -100,6 +106,8 @@ class Item_Rest_Helper_Test extends Gallery_Unit_Test_Case {
array("url" => rest::url("item", $album1),
"entity" => $album1->as_restful_array(),
"relationships" => array(
+ "comments" => array(
+ "url" => rest::url("item_comments", $album1)),
"tags" => array(
"url" => rest::url("item_tags", $album1),
"members" => array())),
@@ -123,6 +131,8 @@ class Item_Rest_Helper_Test extends Gallery_Unit_Test_Case {
array("url" => rest::url("item", $album1),
"entity" => $album1->as_restful_array(),
"relationships" => array(
+ "comments" => array(
+ "url" => rest::url("item_comments", $album1)),
"tags" => array(
"url" => rest::url("item_tags", $album1),
"members" => array())),
diff --git a/modules/gallery/tests/Items_Rest_Helper_Test.php b/modules/gallery/tests/Items_Rest_Helper_Test.php
new file mode 100644
index 00000000..8e53110a
--- /dev/null
+++ b/modules/gallery/tests/Items_Rest_Helper_Test.php
@@ -0,0 +1,206 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2010 Bharat Mediratta
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+class Items_Rest_Helper_Test extends Gallery_Unit_Test_Case {
+ public function get_url_test() {
+ $album1 = test::random_album();
+ $photo1 = test::random_photo($album1);
+ $album2 = test::random_album($album1);
+ $photo2 = test::random_photo($album2);
+ $album1->reload();
+ $album2->reload();
+
+ $request = new stdClass();
+ $request->params = new stdClass();
+ $request->params->urls = json_encode(array(
+ rest::url("item", $photo1),
+ rest::url("item", $album2)));
+ $this->assert_equal_array(
+ array(
+ array("url" => rest::url("item", $photo1),
+ "entity" => $photo1->as_restful_array(),
+ "relationships" => array(
+ "comments" => array(
+ "url" => rest::url("item_comments", $photo1)),
+ "tags" => array(
+ "url" => rest::url("item_tags", $photo1),
+ "members" => array()))),
+ array("url" => rest::url("item", $album2),
+ "entity" => $album2->as_restful_array(),
+ "relationships" => array(
+ "comments" => array(
+ "url" => rest::url("item_comments", $album2)),
+ "tags" => array(
+ "url" => rest::url("item_tags", $album2),
+ "members" => array())),
+ "members" => array(
+ rest::url("item", $photo2)))),
+ items_rest::get($request));
+ }
+
+ public function get_url_filter_album_test() {
+ $album1 = test::random_album();
+ $photo1 = test::random_photo($album1);
+ $album2 = test::random_album($album1);
+ $photo2 = test::random_photo($album2);
+ $album1->reload();
+ $album2->reload();
+
+ $request = new stdClass();
+ $request->params = new stdClass();
+ $request->params->urls = json_encode(array(
+ rest::url("item", $photo1),
+ rest::url("item", $album2)));
+ $request->params->type = "album";
+ $this->assert_equal_array(
+ array(
+ array("url" => rest::url("item", $album2),
+ "entity" => $album2->as_restful_array(),
+ "relationships" => array(
+ "comments" => array(
+ "url" => rest::url("item_comments", $album2)),
+ "tags" => array(
+ "url" => rest::url("item_tags", $album2),
+ "members" => array())),
+ "members" => array(
+ rest::url("item", $photo2)))),
+ items_rest::get($request));
+ }
+
+ public function get_url_filter_photo_test() {
+ $album1 = test::random_album();
+ $photo1 = test::random_photo($album1);
+ $album2 = test::random_album($album1);
+ $photo2 = test::random_photo($album2);
+ $album1->reload();
+ $album2->reload();
+
+ $request = new stdClass();
+ $request->params = new stdClass();
+ $request->params->urls = json_encode(array(
+ rest::url("item", $photo1),
+ rest::url("item", $album2)));
+ $request->params->type = "photo";
+ $this->assert_equal_array(
+ array(
+ array("url" => rest::url("item", $photo1),
+ "entity" => $photo1->as_restful_array(),
+ "relationships" => array(
+ "comments" => array(
+ "url" => rest::url("item_comments", $photo1)),
+ "tags" => array(
+ "url" => rest::url("item_tags", $photo1),
+ "members" => array())))),
+ items_rest::get($request));
+ }
+
+ public function get_url_filter_albums_photos_test() {
+ $album1 = test::random_album();
+ $photo1 = test::random_photo($album1);
+ $album2 = test::random_album($album1);
+ $photo2 = test::random_photo($album2);
+ $album1->reload();
+ $album2->reload();
+
+ $request = new stdClass();
+ $request->params = new stdClass();
+ $request->params->urls = json_encode(array(
+ rest::url("item", $photo1),
+ rest::url("item", $album2)));
+ $request->params->type = "photo,album";
+ $this->assert_equal_array(
+ array(
+ array("url" => rest::url("item", $photo1),
+ "entity" => $photo1->as_restful_array(),
+ "relationships" => array(
+ "comments" => array(
+ "url" => rest::url("item_comments", $photo1)),
+ "tags" => array(
+ "url" => rest::url("item_tags", $photo1),
+ "members" => array()))),
+ array("url" => rest::url("item", $album2),
+ "entity" => $album2->as_restful_array(),
+ "relationships" => array(
+ "comments" => array(
+ "url" => rest::url("item_comments", $album2)),
+ "tags" => array(
+ "url" => rest::url("item_tags", $album2),
+ "members" => array())),
+ "members" => array(
+ rest::url("item", $photo2)))),
+ items_rest::get($request));
+ }
+
+ public function get_ancestors_test() {
+ $album1 = test::random_album();
+ $photo1 = test::random_photo($album1);
+ $album2 = test::random_album($album1);
+ $photo2 = test::random_photo($album2);
+ $album1->reload();
+ $album2->reload();
+
+ $root = ORM::factory("item", 1);
+ $restful_root = array(
+ "url" => rest::url("item", $root),
+ "entity" => $root->as_restful_array(),
+ "relationships" => rest::relationships("item", $root));
+ $restful_root["members"] = array();
+ foreach ($root->children() as $child) {
+ $restful_root["members"][] = rest::url("item", $child);
+ }
+
+ $request = new stdClass();
+ $request->params = new stdClass();
+ $request->params->ancestors_for = rest::url("item", $photo2);
+ $this->assert_equal_array(
+ array(
+ $restful_root,
+ array("url" => rest::url("item", $album1),
+ "entity" => $album1->as_restful_array(),
+ "relationships" => array(
+ "comments" => array(
+ "url" => rest::url("item_comments", $album1)),
+ "tags" => array(
+ "url" => rest::url("item_tags", $album1),
+ "members" => array())),
+ "members" => array(
+ rest::url("item", $photo1),
+ rest::url("item", $album2)),
+ ),
+ array("url" => rest::url("item", $album2),
+ "entity" => $album2->as_restful_array(),
+ "relationships" => array(
+ "comments" => array(
+ "url" => rest::url("item_comments", $album2)),
+ "tags" => array(
+ "url" => rest::url("item_tags", $album2),
+ "members" => array())),
+ "members" => array(
+ rest::url("item", $photo2))),
+ array("url" => rest::url("item", $photo2),
+ "entity" => $photo2->as_restful_array(),
+ "relationships" => array(
+ "comments" => array(
+ "url" => rest::url("item_comments", $photo2)),
+ "tags" => array(
+ "url" => rest::url("item_tags", $photo2),
+ "members" => array())))),
+ items_rest::get($request));
+ }
+}
diff --git a/modules/gallery/tests/controller_auth_data.txt b/modules/gallery/tests/controller_auth_data.txt
index 0aa26057..f7ceed90 100644
--- a/modules/gallery/tests/controller_auth_data.txt
+++ b/modules/gallery/tests/controller_auth_data.txt
@@ -1,4 +1,4 @@
-modules/comment/controllers/admin_comments.php queue DIRTY_CSRF
+modules/comment/controllers/admin_manage_comments.php queue DIRTY_CSRF
modules/comment/helpers/comment_rss.php feed DIRTY_AUTH
modules/digibug/controllers/digibug.php print_proxy DIRTY_CSRF|DIRTY_AUTH
modules/digibug/controllers/digibug.php close_window DIRTY_AUTH
@@ -9,6 +9,8 @@ modules/gallery/controllers/albums.php show
modules/gallery/controllers/combined.php javascript DIRTY_AUTH
modules/gallery/controllers/combined.php css DIRTY_AUTH
modules/gallery/controllers/file_proxy.php __call DIRTY_CSRF|DIRTY_AUTH
+modules/gallery/controllers/flash_uploader.php start DIRTY_AUTH
+modules/gallery/controllers/flash_uploader.php finish DIRTY_AUTH
modules/gallery/controllers/login.php ajax DIRTY_AUTH
modules/gallery/controllers/login.php auth_ajax DIRTY_AUTH
modules/gallery/controllers/login.php html DIRTY_AUTH
@@ -16,13 +18,13 @@ modules/gallery/controllers/login.php auth_html
modules/gallery/controllers/logout.php index DIRTY_AUTH
modules/gallery/controllers/maintenance.php index DIRTY_AUTH
modules/gallery/controllers/quick.php form_edit DIRTY_CSRF
-modules/gallery/controllers/simple_uploader.php start DIRTY_AUTH
-modules/gallery/controllers/simple_uploader.php finish DIRTY_AUTH
modules/gallery/controllers/upgrader.php index DIRTY_AUTH
modules/gallery/controllers/user_profile.php show DIRTY_AUTH
modules/gallery/controllers/user_profile.php contact DIRTY_AUTH
modules/gallery/controllers/user_profile.php send DIRTY_AUTH
modules/gallery/controllers/welcome_message.php index DIRTY_AUTH
+modules/organize/controllers/organize.php dialog DIRTY_CSRF
+modules/organize/controllers/organize.php add_album_fields DIRTY_AUTH
modules/rest/controllers/rest.php index DIRTY_CSRF|DIRTY_AUTH
modules/rest/controllers/rest.php __call DIRTY_CSRF|DIRTY_AUTH
modules/rss/controllers/rss.php feed DIRTY_CSRF|DIRTY_AUTH
diff --git a/modules/gallery/tests/xss_data.txt b/modules/gallery/tests/xss_data.txt
index afad9e13..26edaebc 100644
--- a/modules/gallery/tests/xss_data.txt
+++ b/modules/gallery/tests/xss_data.txt
@@ -4,21 +4,22 @@ modules/akismet/views/admin_akismet_stats.html.php 9 DIRTY_ATTR urle
modules/comment/views/admin_block_recent_comments.html.php 4 DIRTY_ATTR text::alternate("g-even","g-odd")
modules/comment/views/admin_block_recent_comments.html.php 5 DIRTY_ATTR $comment->author()->avatar_url(32,$theme->url(,true))
modules/comment/views/admin_block_recent_comments.html.php 10 DIRTY gallery::date_time($comment->created)
-modules/comment/views/admin_comments.html.php 43 DIRTY $menu->render()
-modules/comment/views/admin_comments.html.php 107 DIRTY_ATTR $comment->id
-modules/comment/views/admin_comments.html.php 107 DIRTY_ATTR text::alternate("g-odd","g-even")
-modules/comment/views/admin_comments.html.php 110 DIRTY_ATTR $comment->author()->avatar_url(40,$theme->url(,true))
-modules/comment/views/admin_comments.html.php 123 DIRTY_JS $item->url()
-modules/comment/views/admin_comments.html.php 125 DIRTY_ATTR $item->thumb_url()
-modules/comment/views/admin_comments.html.php 127 DIRTY photo::img_dimensions($item->thumb_width,$item->thumb_height,75)
-modules/comment/views/admin_comments.html.php 135 DIRTY gallery::date($comment->created)
-modules/comment/views/admin_comments.html.php 142 DIRTY_JS $comment->id
-modules/comment/views/admin_comments.html.php 151 DIRTY_JS $comment->id
-modules/comment/views/admin_comments.html.php 160 DIRTY_JS $comment->id
-modules/comment/views/admin_comments.html.php 169 DIRTY_JS $comment->id
-modules/comment/views/admin_comments.html.php 176 DIRTY_JS $comment->id
-modules/comment/views/admin_comments.html.php 184 DIRTY_JS $comment->id
-modules/comment/views/admin_comments.html.php 197 DIRTY $pager
+modules/comment/views/admin_comments.html.php 5 DIRTY $form
+modules/comment/views/admin_manage_comments.html.php 43 DIRTY $menu->render()
+modules/comment/views/admin_manage_comments.html.php 107 DIRTY_ATTR $comment->id
+modules/comment/views/admin_manage_comments.html.php 107 DIRTY_ATTR text::alternate("g-odd","g-even")
+modules/comment/views/admin_manage_comments.html.php 110 DIRTY_ATTR $comment->author()->avatar_url(40,$theme->url(,true))
+modules/comment/views/admin_manage_comments.html.php 123 DIRTY_JS $item->url()
+modules/comment/views/admin_manage_comments.html.php 125 DIRTY_ATTR $item->thumb_url()
+modules/comment/views/admin_manage_comments.html.php 127 DIRTY photo::img_dimensions($item->thumb_width,$item->thumb_height,75)
+modules/comment/views/admin_manage_comments.html.php 135 DIRTY gallery::date($comment->created)
+modules/comment/views/admin_manage_comments.html.php 142 DIRTY_JS $comment->id
+modules/comment/views/admin_manage_comments.html.php 151 DIRTY_JS $comment->id
+modules/comment/views/admin_manage_comments.html.php 160 DIRTY_JS $comment->id
+modules/comment/views/admin_manage_comments.html.php 169 DIRTY_JS $comment->id
+modules/comment/views/admin_manage_comments.html.php 176 DIRTY_JS $comment->id
+modules/comment/views/admin_manage_comments.html.php 184 DIRTY_JS $comment->id
+modules/comment/views/admin_manage_comments.html.php 197 DIRTY $pager
modules/comment/views/comment.html.php 2 DIRTY_ATTR $comment->id;
modules/comment/views/comment.html.php 5 DIRTY_ATTR $comment->author()->avatar_url(40,$theme->url(,true))
modules/comment/views/comment.mrss.php 10 DIRTY $feed->uri
@@ -27,13 +28,13 @@ modules/comment/views/comment.mrss.php 16 DIRTY_JS $feed-
modules/comment/views/comment.mrss.php 19 DIRTY_JS $feed->next_page_uri
modules/comment/views/comment.mrss.php 21 DIRTY $pub_date
modules/comment/views/comment.mrss.php 22 DIRTY $pub_date
-modules/comment/views/comment.mrss.php 28 DIRTY $child->item_uri
-modules/comment/views/comment.mrss.php 29 DIRTY $child->pub_date
-modules/comment/views/comment.mrss.php 34 DIRTY_ATTR $child->thumb_url
-modules/comment/views/comment.mrss.php 35 DIRTY_ATTR $child->thumb_height
-modules/comment/views/comment.mrss.php 35 DIRTY_ATTR $child->thumb_width
-modules/comment/views/comments.html.php 18 DIRTY_ATTR $comment->id
-modules/comment/views/comments.html.php 21 DIRTY_ATTR $comment->author()->avatar_url(40,$theme->url(,true))
+modules/comment/views/comment.mrss.php 28 DIRTY $comment->item_uri
+modules/comment/views/comment.mrss.php 29 DIRTY $comment->pub_date
+modules/comment/views/comment.mrss.php 34 DIRTY_ATTR $comment->thumb_url
+modules/comment/views/comment.mrss.php 35 DIRTY_ATTR $comment->thumb_height
+modules/comment/views/comment.mrss.php 35 DIRTY_ATTR $comment->thumb_width
+modules/comment/views/comments.html.php 28 DIRTY_ATTR $comment->id
+modules/comment/views/comments.html.php 31 DIRTY_ATTR $comment->author()->avatar_url(40,$theme->url(,true))
modules/comment/views/user_profile_comments.html.php 5 DIRTY_ATTR $comment->id
modules/comment/views/user_profile_comments.html.php 10 DIRTY_JS $comment->item()->url()
modules/comment/views/user_profile_comments.html.php 11 DIRTY $comment->item()->thumb_img(array(),50)
@@ -108,7 +109,7 @@ modules/gallery/views/admin_sidebar.html.php 50 DIRTY $avail
modules/gallery/views/admin_sidebar.html.php 58 DIRTY $active
modules/gallery/views/admin_sidebar_blocks.html.php 4 DIRTY_ATTR $ref
modules/gallery/views/admin_sidebar_blocks.html.php 4 DIRTY $text
-modules/gallery/views/admin_theme_options.html.php 6 DIRTY $form
+modules/gallery/views/admin_theme_options.html.php 36 DIRTY $form
modules/gallery/views/admin_themes.html.php 3 DIRTY_JS url::site("admin/themes/choose")
modules/gallery/views/admin_themes.html.php 5 DIRTY_JS $csrf
modules/gallery/views/admin_themes.html.php 22 DIRTY $themes[$site]->name
@@ -119,10 +120,54 @@ modules/gallery/views/admin_themes.html.php 60 DIRTY $theme
modules/gallery/views/admin_themes.html.php 62 DIRTY $themes[$admin]->description
modules/gallery/views/admin_themes.html.php 76 DIRTY $info->name
modules/gallery/views/admin_themes.html.php 78 DIRTY $info->description
-modules/gallery/views/admin_themes_preview.html.php 7 DIRTY_ATTR $url
+modules/gallery/views/admin_themes_preview.html.php 8 DIRTY_ATTR $url
modules/gallery/views/error_404.html.php 14 DIRTY $login_form
+modules/gallery/views/error_admin.html.php 150 DIRTY $type
+modules/gallery/views/error_admin.html.php 150 DIRTY $code
+modules/gallery/views/error_admin.html.php 153 DIRTY $message
+modules/gallery/views/error_admin.html.php 156 DIRTY_ATTR $error_id
+modules/gallery/views/error_admin.html.php 161 DIRTY Kohana_Exception::debug_path($file)
+modules/gallery/views/error_admin.html.php 161 DIRTY $line
+modules/gallery/views/error_admin.html.php 166 DIRTY_ATTR ($num==$line)?"highlight":""
+modules/gallery/views/error_admin.html.php 166 DIRTY $num
+modules/gallery/views/error_admin.html.php 166 DIRTY htmlspecialchars($row,ENT_NOQUOTES,Kohana::CHARSET)
+modules/gallery/views/error_admin.html.php 178 DIRTY_ATTR $source_id
+modules/gallery/views/error_admin.html.php 178 DIRTY_JS $source_id
+modules/gallery/views/error_admin.html.php 178 DIRTY Kohana_Exception::debug_path($step["file"])
+modules/gallery/views/error_admin.html.php 178 DIRTY $step["line"]
+modules/gallery/views/error_admin.html.php 180 DIRTY Kohana_Exception::debug_path($step["file"])
+modules/gallery/views/error_admin.html.php 180 DIRTY $step["line"]
+modules/gallery/views/error_admin.html.php 187 DIRTY $step["function"]
+modules/gallery/views/error_admin.html.php 188 DIRTY_ATTR $args_id
+modules/gallery/views/error_admin.html.php 188 DIRTY_JS $args_id
+modules/gallery/views/error_admin.html.php 192 DIRTY_ATTR $args_id
+modules/gallery/views/error_admin.html.php 197 DIRTY $name
+modules/gallery/views/error_admin.html.php 200 DIRTY Kohana_Exception::safe_dump($arg,$name)
+modules/gallery/views/error_admin.html.php 208 DIRTY_ATTR $source_id
+modules/gallery/views/error_admin.html.php 208 DIRTY_ATTR ($num==$step["line"])?"highlight":""
+modules/gallery/views/error_admin.html.php 208 DIRTY $num
+modules/gallery/views/error_admin.html.php 208 DIRTY htmlspecialchars($row,ENT_NOQUOTES,Kohana::CHARSET)
+modules/gallery/views/error_admin.html.php 218 DIRTY_ATTR $env_id=$error_id."environment"
+modules/gallery/views/error_admin.html.php 218 DIRTY_JS $env_id
+modules/gallery/views/error_admin.html.php 220 DIRTY_ATTR $env_id
+modules/gallery/views/error_admin.html.php 222 DIRTY_ATTR $env_id=$error_id."environment_included"
+modules/gallery/views/error_admin.html.php 222 DIRTY_JS $env_id
+modules/gallery/views/error_admin.html.php 222 DIRTY count($included)
+modules/gallery/views/error_admin.html.php 223 DIRTY_ATTR $env_id
+modules/gallery/views/error_admin.html.php 228 DIRTY Kohana_Exception::debug_path($file)
+modules/gallery/views/error_admin.html.php 235 DIRTY_ATTR $env_id=$error_id."environment_loaded"
+modules/gallery/views/error_admin.html.php 235 DIRTY_JS $env_id
+modules/gallery/views/error_admin.html.php 235 DIRTY count($included)
+modules/gallery/views/error_admin.html.php 236 DIRTY_ATTR $env_id
+modules/gallery/views/error_admin.html.php 241 DIRTY Kohana_Exception::debug_path($file)
+modules/gallery/views/error_admin.html.php 249 DIRTY_ATTR $env_id="$error_id.environment".strtolower($var)
+modules/gallery/views/error_admin.html.php 250 DIRTY_JS $env_id
+modules/gallery/views/error_admin.html.php 250 DIRTY $var
+modules/gallery/views/error_admin.html.php 251 DIRTY_ATTR $env_id
+modules/gallery/views/error_admin.html.php 257 DIRTY $key
+modules/gallery/views/error_admin.html.php 261 DIRTY Kohana_Exception::safe_dump($value,$key)
modules/gallery/views/form_uploadify.html.php 9 DIRTY_JS url::file("lib/uploadify/uploadify.swf")
-modules/gallery/views/form_uploadify.html.php 10 DIRTY_JS url::site("simple_uploader/add_photo/{$album->id}")
+modules/gallery/views/form_uploadify.html.php 10 DIRTY_JS url::site("flash_uploader/add_photo/{$album->id}")
modules/gallery/views/form_uploadify.html.php 14 DIRTY_JS url::file("lib/uploadify/cancel.png")
modules/gallery/views/form_uploadify.html.php 15 DIRTY_JS $simultaneous_upload_limit
modules/gallery/views/in_place_edit.html.php 2 DIRTY form::open($action,array("method"=>"post","id"=>"g-in-place-edit-form","class"=>"g-short-form"))
@@ -145,7 +190,7 @@ modules/gallery/views/l10n_client.html.php 58 DIRTY form::
modules/gallery/views/l10n_client.html.php 62 DIRTY form::textarea("l10n-edit-plural-translation-many","",' rows="2"')
modules/gallery/views/l10n_client.html.php 67 DIRTY form::textarea("l10n-edit-plural-translation-other","",' rows="2"')
modules/gallery/views/login_ajax.html.php 6 DIRTY_JS url::site("password/reset")
-modules/gallery/views/login_ajax.html.php 37 DIRTY $form
+modules/gallery/views/login_ajax.html.php 44 DIRTY $form
modules/gallery/views/maintenance.html.php 46 DIRTY auth::get_login_form("login/auth_html")
modules/gallery/views/menu.html.php 4 DIRTY $menu->css_id?"id='$menu->css_id'":""
modules/gallery/views/menu.html.php 4 DIRTY_ATTR $menu->css_class
@@ -175,7 +220,7 @@ modules/gallery/views/move_tree.html.php 15 DIRTY_JS $child
modules/gallery/views/movieplayer.html.php 2 DIRTY html::anchor($item->file_url(true),"",$attrs)
modules/gallery/views/movieplayer.html.php 5 DIRTY_JS $attrs["id"]
modules/gallery/views/movieplayer.html.php 7 DIRTY_JS url::abs_file("lib/flowplayer.swf")
-modules/gallery/views/movieplayer.html.php 13 DIRTY_JS url::abs_file("lib/flowplayer.h264streaming.swf")
+modules/gallery/views/movieplayer.html.php 14 DIRTY_JS url::abs_file("lib/flowplayer.pseudostreaming.swf")
modules/gallery/views/permissions_browse.html.php 3 DIRTY_JS url::site("permissions/form/__ITEM__")
modules/gallery/views/permissions_browse.html.php 16 DIRTY_JS url::site("permissions/change/__CMD__/__GROUP__/__PERM__/__ITEM__?csrf=$csrf")
modules/gallery/views/permissions_browse.html.php 43 DIRTY_ATTR $parent->id
@@ -234,27 +279,16 @@ modules/notification/views/item_updated.html.php 20 DIRTY_JS $item-
modules/notification/views/item_updated.html.php 20 DIRTY $item->abs_url()
modules/notification/views/user_profile_notification.html.php 5 DIRTY_ATTR $subscription->id
modules/notification/views/user_profile_notification.html.php 6 DIRTY_JS $subscription->url
-modules/organize/views/organize_dialog.html.php 3 DIRTY_JS url::site("organize/move_to/__ALBUM_ID__?csrf=$csrf")
-modules/organize/views/organize_dialog.html.php 4 DIRTY_JS url::site("organize/rearrange/__TARGET_ID__/__BEFORE__?csrf=$csrf")
-modules/organize/views/organize_dialog.html.php 5 DIRTY_JS url::site("organize/sort_order/__ALBUM_ID__/__COL__/__DIR__?csrf=$csrf")
-modules/organize/views/organize_dialog.html.php 6 DIRTY_JS url::site("organize/tree/__ALBUM_ID__")
-modules/organize/views/organize_dialog.html.php 14 DIRTY $album_tree
-modules/organize/views/organize_dialog.html.php 23 DIRTY $micro_thumb_grid
-modules/organize/views/organize_dialog.html.php 32 DIRTY form::dropdown(array("id"=>"g-organize-sort-column"),album::get_sort_order_options(),$album->sort_column)
-modules/organize/views/organize_thumb_grid.html.php 3 DIRTY_ATTR $child->is_album()?"g-album":"g-photo"
-modules/organize/views/organize_thumb_grid.html.php 4 DIRTY_ATTR $child->id
-modules/organize/views/organize_thumb_grid.html.php 5 DIRTY $child->thumb_img(array("class"=>"g-thumbnail","ref"=>$child->id),90,true)
-modules/organize/views/organize_thumb_grid.html.php 6 DIRTY $child->is_album()?" class=\"ui-icon ui-icon-note\"":""
-modules/organize/views/organize_thumb_grid.html.php 13 DIRTY_JS url::site("organize/album/$album->id/".($offset+25))
-modules/organize/views/organize_tree.html.php 2 DIRTY_ATTR access::can("edit",$album)?"":"g-view-only"
-modules/organize/views/organize_tree.html.php 3 DIRTY_ATTR $album->id
-modules/organize/views/organize_tree.html.php 6 DIRTY_ATTR $selected&&$album->id==$selected->id?"ui-state-focus":""
-modules/organize/views/organize_tree.html.php 7 DIRTY_ATTR $album->id
-modules/organize/views/organize_tree.html.php 15 DIRTY View::factory("organize_tree.html",array("selected"=>$selected,"album"=>$child));
-modules/organize/views/organize_tree.html.php 17 DIRTY_ATTR access::can("edit",$child)?"":"g-view-only"
-modules/organize/views/organize_tree.html.php 18 DIRTY_ATTR $child->id
-modules/organize/views/organize_tree.html.php 20 DIRTY_ATTR $selected&&$child->id==$selected->id?"ui-state-focus":""
-modules/organize/views/organize_tree.html.php 20 DIRTY_ATTR $child->id
+modules/organize/views/organize_dialog.html.php 90 DIRTY_JS $domain
+modules/organize/views/organize_dialog.html.php 91 DIRTY_JS $access_key
+modules/organize/views/organize_dialog.html.php 92 DIRTY_JS request::protocol()
+modules/organize/views/organize_dialog.html.php 93 DIRTY_JS $file_filter
+modules/organize/views/organize_dialog.html.php 94 DIRTY_JS $sort_order
+modules/organize/views/organize_dialog.html.php 95 DIRTY_JS $sort_fields
+modules/organize/views/organize_dialog.html.php 96 DIRTY_JS $album->id
+modules/organize/views/organize_dialog.html.php 97 DIRTY_JS $rest_uri
+modules/organize/views/organize_dialog.html.php 98 DIRTY_JS $controller_uri
+modules/organize/views/organize_dialog.html.php 122 DIRTY_JS $swf_uri
modules/recaptcha/views/admin_recaptcha.html.php 11 DIRTY $form
modules/recaptcha/views/admin_recaptcha.html.php 23 DIRTY_JS $public_key
modules/recaptcha/views/form_recaptcha.html.php 7 DIRTY_JS $public_key
@@ -264,26 +298,26 @@ modules/rss/views/feed.mrss.php 16 DIRTY_JS $feed-
modules/rss/views/feed.mrss.php 19 DIRTY_JS $feed->next_page_uri
modules/rss/views/feed.mrss.php 21 DIRTY $pub_date
modules/rss/views/feed.mrss.php 22 DIRTY $pub_date
-modules/rss/views/feed.mrss.php 28 DIRTY date("D, d M Y H:i:s T",$child->created);
-modules/rss/views/feed.mrss.php 35 DIRTY_ATTR $child->resize_url(true)
-modules/rss/views/feed.mrss.php 37 DIRTY_ATTR $child->resize_height
-modules/rss/views/feed.mrss.php 37 DIRTY_ATTR $child->resize_width
-modules/rss/views/feed.mrss.php 40 DIRTY_ATTR $child->thumb_url(true)
-modules/rss/views/feed.mrss.php 42 DIRTY_ATTR $child->thumb_height
-modules/rss/views/feed.mrss.php 42 DIRTY_ATTR $child->thumb_width
-modules/rss/views/feed.mrss.php 48 DIRTY_ATTR $child->thumb_url(true)
-modules/rss/views/feed.mrss.php 49 DIRTY_ATTR $child->thumb_height
-modules/rss/views/feed.mrss.php 50 DIRTY_ATTR $child->thumb_width
-modules/rss/views/feed.mrss.php 57 DIRTY_ATTR $child->resize_url(true)
-modules/rss/views/feed.mrss.php 58 DIRTY_ATTR @filesize($child->resize_path())
-modules/rss/views/feed.mrss.php 59 DIRTY_ATTR $child->mime_type
-modules/rss/views/feed.mrss.php 60 DIRTY_ATTR $child->resize_height
-modules/rss/views/feed.mrss.php 61 DIRTY_ATTR $child->resize_width
-modules/rss/views/feed.mrss.php 65 DIRTY_ATTR $child->file_url(true)
-modules/rss/views/feed.mrss.php 66 DIRTY_ATTR @filesize($child->file_path())
-modules/rss/views/feed.mrss.php 67 DIRTY_ATTR $child->mime_type
-modules/rss/views/feed.mrss.php 68 DIRTY_ATTR $child->height
-modules/rss/views/feed.mrss.php 69 DIRTY_ATTR $child->width
+modules/rss/views/feed.mrss.php 28 DIRTY date("D, d M Y H:i:s T",$item->created);
+modules/rss/views/feed.mrss.php 35 DIRTY_ATTR $item->resize_url(true)
+modules/rss/views/feed.mrss.php 37 DIRTY_ATTR $item->resize_height
+modules/rss/views/feed.mrss.php 37 DIRTY_ATTR $item->resize_width
+modules/rss/views/feed.mrss.php 40 DIRTY_ATTR $item->thumb_url(true)
+modules/rss/views/feed.mrss.php 42 DIRTY_ATTR $item->thumb_height
+modules/rss/views/feed.mrss.php 42 DIRTY_ATTR $item->thumb_width
+modules/rss/views/feed.mrss.php 48 DIRTY_ATTR $item->thumb_url(true)
+modules/rss/views/feed.mrss.php 49 DIRTY_ATTR $item->thumb_height
+modules/rss/views/feed.mrss.php 50 DIRTY_ATTR $item->thumb_width
+modules/rss/views/feed.mrss.php 57 DIRTY_ATTR $item->resize_url(true)
+modules/rss/views/feed.mrss.php 58 DIRTY_ATTR @filesize($item->resize_path())
+modules/rss/views/feed.mrss.php 59 DIRTY_ATTR $item->mime_type
+modules/rss/views/feed.mrss.php 60 DIRTY_ATTR $item->resize_height
+modules/rss/views/feed.mrss.php 61 DIRTY_ATTR $item->resize_width
+modules/rss/views/feed.mrss.php 65 DIRTY_ATTR $item->file_url(true)
+modules/rss/views/feed.mrss.php 66 DIRTY_ATTR @filesize($item->file_path())
+modules/rss/views/feed.mrss.php 67 DIRTY_ATTR $item->mime_type
+modules/rss/views/feed.mrss.php 68 DIRTY_ATTR $item->height
+modules/rss/views/feed.mrss.php 69 DIRTY_ATTR $item->width
modules/rss/views/rss_block.html.php 6 DIRTY_JS rss::url($url)
modules/search/views/search.html.php 27 DIRTY_ATTR $item_class
modules/search/views/search.html.php 28 DIRTY_JS $item->url()
@@ -320,20 +354,19 @@ modules/user/views/admin_users_group.html.php 24 DIRTY_JS $group
modules/watermark/views/admin_watermarks.html.php 20 DIRTY_ATTR $width
modules/watermark/views/admin_watermarks.html.php 20 DIRTY_ATTR $height
modules/watermark/views/admin_watermarks.html.php 20 DIRTY_ATTR $url
-themes/admin_wind/views/admin.html.php 9 DIRTY $page_title
themes/admin_wind/views/admin.html.php 22 DIRTY_JS $theme->url()
themes/admin_wind/views/admin.html.php 39 DIRTY $theme->admin_head()
themes/admin_wind/views/admin.html.php 43 DIRTY $theme->admin_page_top()
themes/admin_wind/views/admin.html.php 51 DIRTY $theme->admin_header_top()
themes/admin_wind/views/admin.html.php 52 DIRTY_JS item::root()->url()
themes/admin_wind/views/admin.html.php 55 DIRTY $theme->user_menu()
-themes/admin_wind/views/admin.html.php 57 DIRTY $theme->admin_menu()
-themes/admin_wind/views/admin.html.php 59 DIRTY $theme->admin_header_bottom()
-themes/admin_wind/views/admin.html.php 66 DIRTY $content
-themes/admin_wind/views/admin.html.php 72 DIRTY $sidebar
-themes/admin_wind/views/admin.html.php 77 DIRTY $theme->admin_footer()
-themes/admin_wind/views/admin.html.php 79 DIRTY $theme->admin_credits()
-themes/admin_wind/views/admin.html.php 83 DIRTY $theme->admin_page_bottom()
+themes/admin_wind/views/admin.html.php 58 DIRTY $theme->admin_menu()
+themes/admin_wind/views/admin.html.php 61 DIRTY $theme->admin_header_bottom()
+themes/admin_wind/views/admin.html.php 68 DIRTY $content
+themes/admin_wind/views/admin.html.php 74 DIRTY $sidebar
+themes/admin_wind/views/admin.html.php 79 DIRTY $theme->admin_footer()
+themes/admin_wind/views/admin.html.php 81 DIRTY $theme->admin_credits()
+themes/admin_wind/views/admin.html.php 85 DIRTY $theme->admin_page_bottom()
themes/admin_wind/views/block.html.php 3 DIRTY_ATTR $anchor
themes/admin_wind/views/block.html.php 5 DIRTY $id
themes/admin_wind/views/block.html.php 5 DIRTY_ATTR $css_id
@@ -363,7 +396,7 @@ themes/wind/views/dynamic.html.php 16 DIRTY_ATTR $chi
themes/wind/views/dynamic.html.php 17 DIRTY_ATTR $child->thumb_height
themes/wind/views/dynamic.html.php 29 DIRTY $theme->paginator()
themes/wind/views/movie.html.php 5 DIRTY $theme->paginator()
-themes/wind/views/movie.html.php 8 DIRTY $item->movie_img(array("class"=>"g-movie","id"=>"g-movie-id-{$item->id}"))
+themes/wind/views/movie.html.php 9 DIRTY $item->movie_img(array("class"=>"g-movie","id"=>"g-item-id-{$item->id}"))
themes/wind/views/page.html.php 9 DIRTY $page_title
themes/wind/views/page.html.php 33 DIRTY_JS $theme->url()
themes/wind/views/page.html.php 42 DIRTY $new_width
@@ -373,9 +406,9 @@ themes/wind/views/page.html.php 81 DIRTY $heade
themes/wind/views/page.html.php 83 DIRTY_JS item::root()->url()
themes/wind/views/page.html.php 87 DIRTY $theme->user_menu()
themes/wind/views/page.html.php 108 DIRTY_JS $parent->url($parent==$theme->item()->parent()?"show={$theme->item()->id}":null)
-themes/wind/views/page.html.php 124 DIRTY $content
-themes/wind/views/page.html.php 130 DIRTY newView("sidebar.html")
-themes/wind/views/page.html.php 137 DIRTY $footer_text
+themes/wind/views/page.html.php 126 DIRTY $content
+themes/wind/views/page.html.php 132 DIRTY newView("sidebar.html")
+themes/wind/views/page.html.php 139 DIRTY $footer_text
themes/wind/views/paginator.html.php 33 DIRTY_JS $first_page_url
themes/wind/views/paginator.html.php 42 DIRTY_JS $previous_page_url
themes/wind/views/paginator.html.php 70 DIRTY_JS $next_page_url
@@ -384,4 +417,4 @@ themes/wind/views/photo.html.php 8 DIRTY_JS $theme
themes/wind/views/photo.html.php 8 DIRTY_JS $theme->item()->height
themes/wind/views/photo.html.php 18 DIRTY $theme->paginator()
themes/wind/views/photo.html.php 23 DIRTY_JS $item->file_url()
-themes/wind/views/photo.html.php 25 DIRTY $item->resize_img(array("id"=>"g-photo-id-{$item->id}","class"=>"g-resize"))
+themes/wind/views/photo.html.php 25 DIRTY $item->resize_img(array("id"=>"g-item-id-{$item->id}","class"=>"g-resize"))
diff --git a/modules/gallery/views/admin_modules.html.php b/modules/gallery/views/admin_modules.html.php
index c5015e68..4d6fe5f0 100644
--- a/modules/gallery/views/admin_modules.html.php
+++ b/modules/gallery/views/admin_modules.html.php
@@ -52,7 +52,7 @@
<table>
<tr>
<th> <?= t("Installed") ?> </th>
- <th> <?= t("Name") ?> </th>
+ <th style="width: 8em"> <?= t("Name") ?> </th>
<th> <?= t("Version") ?> </th>
<th> <?= t("Description") ?> </th>
</tr>
diff --git a/modules/gallery/views/admin_theme_options.html.php b/modules/gallery/views/admin_theme_options.html.php
index a4bf1c4e..b4a90682 100644
--- a/modules/gallery/views/admin_theme_options.html.php
+++ b/modules/gallery/views/admin_theme_options.html.php
@@ -1,7 +1,37 @@
<?php defined("SYSPATH") or die("No direct script access.") ?>
-<div class="g-block">
- <h1> <?= t("Theme Options") ?> </h1>
+<script type="text/javascript">
+ $("#g-theme-options-form").ready(function() {
+ var contents = $("#g-theme-options-form fieldset:not(:last-child)");
+ if (contents.length > 1) {
+ $("<div id='g-theme-options-form-tabs'>" +
+ " <ul class='tabnav'></ul>" +
+ "</div>").insertBefore("#g-theme-options-form fieldset:last-child");
+ $(contents).each(function(index) {
+ var text = $("legend", this).text();
+ var tabId = "tab_" + index;
+ var tabContentId = "tab_content_" + index;
+ if (text == "") {
+ text = <?= t("Tab_")->for_js() ?> + index;
+ }
+ $(".tabnav").append(
+ "<li><a id='" + tabId + "' href='#" + tabContentId + "'>" + text + "</a></li>");
+ $("#g-theme-options-form-tabs").append(
+ "<div id='" + tabContentId + "' class='tabdiv'></div>");
+ if ($("li.g-error", this).length > 0) {
+ $("#" + tabId).addClass("g-error");
+ }
+ $("#" + tabContentId).append($("ul", this));
+ $(this).remove();
+ });
+ $("#g-theme-options-form-tabs").tabs({});
+ } else {
+ $("#g-theme-options-form fieldset:first legend").hide();
+ }
+ });
+</script>
+<div class="g-block">
+ <h1> <?= t("Theme options") ?> </h1>
<div class="g-block-content">
<?= $form ?>
</div>
diff --git a/modules/gallery/views/admin_themes_preview.html.php b/modules/gallery/views/admin_themes_preview.html.php
index a7aea172..80a6158b 100644
--- a/modules/gallery/views/admin_themes_preview.html.php
+++ b/modules/gallery/views/admin_themes_preview.html.php
@@ -1,4 +1,5 @@
<?php defined("SYSPATH") or die("No direct script access.") ?>
+<h1><?= t("Preview of the %theme_name theme", array("theme_name" => $info->name)) ?></h1>
<p>
<a href="<?= url::site("admin/themes/choose/$type/$theme_name?csrf=$csrf") ?>">
<?= t("Activate <strong>%theme_name</strong>", array("theme_name" => $info->name)) ?>
diff --git a/modules/gallery/views/error_404.html.php b/modules/gallery/views/error_404.html.php
index 4b037a79..42f62b6c 100644
--- a/modules/gallery/views/error_404.html.php
+++ b/modules/gallery/views/error_404.html.php
@@ -12,10 +12,15 @@
<?= t("Please sign in to find out.") ?>
</p>
<?= $login_form ?>
+ <script type="text/javascript">
+ $(document).ready(function() {
+ $("#g-username").focus();
+ });
+ </script>
<? else: ?>
<p>
<?= t("Maybe the page exists, but is only visible to authorized users.") ?>
<?= t("If you think this is an error, talk to your Gallery administrator!") ?>
</p>
<? endif; ?>
-</div> \ No newline at end of file
+</div>
diff --git a/modules/gallery/views/error_admin.html.php b/modules/gallery/views/error_admin.html.php
new file mode 100644
index 00000000..40eb7374
--- /dev/null
+++ b/modules/gallery/views/error_admin.html.php
@@ -0,0 +1,272 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<? $error_id = uniqid("error") ?>
+<? if (!function_exists("t")) { function t($msg) { return $msg; } } ?>
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+ <head>
+ <style type="text/css">
+ body {
+ background: #fff;
+ font-size: 14px;
+ line-height: 130%;
+ }
+
+ div.big_box {
+ padding: 10px;
+ background: #eee;
+ border: solid 1px #ccc;
+ font-family: sans-serif;
+ color: #111;
+ width: 60em;
+ margin: 20px auto;
+ }
+
+ div#framework_error {
+ text-align: center;
+ }
+
+ div#error_details {
+ text-align: left;
+ }
+
+ code {
+ font-family: monospace;
+ font-size: 12px;
+ margin: 20px 20px 20px 0px;
+ color: #333;
+ white-space: pre-wrap;
+ white-space: -moz-pre-wrap;
+ word-wrap: break-word;
+ }
+
+ code .line {
+ padding-left: 10px;
+ }
+
+ h3 {
+ font-family: sans-serif;
+ margin: 2px 0px 0px 0px;
+ padding: 8px 0px 0px 0px;
+ border-top: 1px solid #ddd;
+ }
+
+ p {
+ padding: 0px;
+ margin: 0px 0px 10px 0px;
+ }
+
+ li, pre {
+ padding: 0px;
+ margin: 0px;
+ }
+
+ .collapsed {
+ display: none;
+ }
+
+ .highlight {
+ font-weight: bold;
+ color: darkred;
+ }
+
+ #kohana_error .message {
+ display: block;
+ padding-bottom: 10px;
+ }
+
+ .source {
+ border: solid 1px #ccc;
+ background: #efe;
+ margin-bottom: 5px;
+ }
+
+ table {
+ width: 100%;
+ display: block;
+ margin: 0 0 0.4em;
+ padding: 0;
+ border-collapse: collapse;
+ background: #efe;
+ }
+
+ table td {
+ border: solid 1px #ddd;
+ text-align: left;
+ vertical-align: top;
+ padding: 0.4em;
+ }
+
+ .args table td.key {
+ width: 200px;
+ }
+
+ .number {
+ padding-right: 1em;
+ }
+ </style>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+ <title><?= t("Something went wrong!") ?></title>
+
+ <script type="text/javascript">
+ function koggle(elem) {
+ elem = document.getElementById(elem);
+ if (elem.style && elem.style["display"]) {
+ // Only works with the "style" attr
+ var disp = elem.style["display"];
+ } else {
+ if (elem.currentStyle) {
+ // For MSIE, naturally
+ var disp = elem.currentStyle["display"];
+ } else {
+ if (window.getComputedStyle) {
+ // For most other browsers
+ var disp = document.defaultView.getComputedStyle(elem, null).getPropertyValue('display');
+ }
+ }
+ }
+
+ // Toggle the state of the "display" style
+ elem.style.display = disp == 'block' ? 'none' : 'block';
+ return false;
+ }
+ </script>
+ </head>
+ <body>
+ <? try { $user = identity::active_user(); } catch (Exception $e) { } ?>
+ <div class="big_box" id="framework_error">
+ <h1>
+ <?= t("Dang... Something went wrong!") ?>
+ </h1>
+ <h2>
+ <?= t("We tried really hard, but it's broken.") ?>
+ </h2>
+ </div>
+ <div class="big_box" id="error_details">
+ <h2>
+ <?= t("Hey wait, you're an admin! We can tell you stuff.") ?>
+ </h2>
+ <div id="kohana_error">
+ <h3>
+ <span class="type">
+ <?= $type?> [ <?= $code ?> ]:
+ </span>
+ <span class="message">
+ <?= $message?>
+ </span>
+ </h3>
+ <div id="<?= $error_id ?>" class="content">
+ <ol class="trace">
+ <li class="snippet">
+ <p>
+ <span class="file">
+ <?= Kohana_Exception::debug_path($file)?>[ <?= $line?> ]
+ </span>
+ </p>
+
+ <div class="source">
+ <? if (Kohana_Exception::$source_output and $source_code = Kohana_Exception::debug_source($file, $line)): ?><code><? foreach ($source_code as $num => $row): ?><span class="line <?= ($num == $line) ? "highlight" : ""?>"><span class="number"><?= $num ?></span><?= htmlspecialchars($row, ENT_NOQUOTES, Kohana::CHARSET) ?></span><? endforeach ?></code>
+ <? endif ?>
+ </div>
+ </li>
+
+ <? if (Kohana_Exception::$trace_output): ?>
+ <? foreach (Kohana_Exception::trace($trace) as $i => $step): ?>
+ <li class="snippet">
+ <p>
+ <span class="file">
+ <? if ($step["file"]): $source_id = "$error_id.source.$i" ?>
+ <? if (Kohana_Exception::$source_output and $step["source"]): ?>
+ <a href="#<?= $source_id ?>" onclick="return koggle('<?= $source_id ?>')"><?= Kohana_Exception::debug_path($step["file"])?>[ <?= $step["line"]?> ]</a>
+ <? else: ?>
+ <span class="file"><?= Kohana_Exception::debug_path($step["file"])?>[ <?= $step["line"]?> ]</span>
+ <? endif ?>
+ <? else: ?>
+ {<?= t("PHP internal call")?>}
+ <? endif?>
+ </span>
+ &raquo;
+ <?= $step["function"]?>(<? if ($step["args"]): $args_id = "$error_id.args.$i" ?>
+ <a href="#<?= $args_id ?>" onclick="return koggle('<?= $args_id ?>')"><?= t("arguments")?></a>
+ <? endif?>)
+ </p>
+ <? if (isset($args_id)): ?>
+ <div id="<?= $args_id ?>" class="args collapsed">
+ <table cellspacing="0">
+ <? foreach ($step["args"] as $name => $arg): ?>
+ <tr>
+ <td class="key">
+ <pre><?= $name?></pre>
+ </td>
+ <td class="value">
+ <pre><?= Kohana_Exception::safe_dump($arg, $name) ?></pre>
+ </td>
+ </tr>
+ <? endforeach?>
+ </table>
+ </div>
+ <? endif?>
+ <? if (Kohana_Exception::$source_output and $step["source"] and isset($source_id)): ?>
+ <pre id="<?= $source_id ?>" class="source collapsed"><code><? foreach ($step["source"] as $num => $row): ?><span class="line <?= ($num == $step["line"]) ? "highlight" : "" ?>"><span class="number"><?= $num ?></span><?= htmlspecialchars($row, ENT_NOQUOTES, Kohana::CHARSET) ?></span><? endforeach ?></code></pre>
+ <? endif?>
+ </li>
+ <? unset($args_id, $source_id) ?>
+ <? endforeach?>
+ </ol>
+ <? endif ?>
+
+ </div>
+ <h2>
+ <a href="#<?= $env_id = $error_id."environment" ?>" onclick="return koggle('<?= $env_id ?>')"><?= t("Environment")?></a>
+ </h2>
+ <div id="<?= $env_id ?>" class="content collapsed">
+ <? $included = get_included_files()?>
+ <h3><a href="#<?= $env_id = $error_id."environment_included" ?>" onclick="return koggle('<?= $env_id ?>')"><?= t("Included files")?></a>(<?= count($included)?>)</h3>
+ <div id="<?= $env_id ?>" class="collapsed">
+ <table cellspacing="0">
+ <? foreach ($included as $file): ?>
+ <tr>
+ <td>
+ <pre><?= Kohana_Exception::debug_path($file)?></pre>
+ </td>
+ </tr>
+ <? endforeach?>
+ </table>
+ </div>
+ <? $included = get_loaded_extensions()?>
+ <h3><a href="#<?= $env_id = $error_id."environment_loaded" ?>" onclick="return koggle('<?= $env_id ?>')"><?= t("Loaded extensions")?></a>(<?= count($included)?>)</h3>
+ <div id="<?= $env_id ?>" class="collapsed">
+ <table cellspacing="0">
+ <? foreach ($included as $file): ?>
+ <tr>
+ <td>
+ <pre><?= Kohana_Exception::debug_path($file)?></pre>
+ </td>
+ </tr>
+ <? endforeach?>
+ </table>
+ </div>
+ <? foreach (array("_SESSION", "_GET", "_POST", "_FILES", "_COOKIE", "_SERVER") as $var): ?>
+ <? if ( empty($GLOBALS[$var]) OR ! is_array($GLOBALS[$var])) continue ?>
+ <h3><a href="#<?= $env_id = "$error_id.environment" . strtolower($var) ?>"
+ onclick="return koggle('<?= $env_id ?>')">$<?= $var?></a></h3>
+ <div id="<?= $env_id ?>" class="collapsed">
+ <table cellspacing="0">
+ <? foreach ($GLOBALS[$var] as $key => $value): ?>
+ <tr>
+ <td class="key">
+ <code>
+ <?= $key?>
+ </code>
+ </td>
+ <td class="value">
+ <pre><?= Kohana_Exception::safe_dump($value, $key) ?></pre>
+ </td>
+ </tr>
+ <? endforeach?>
+ </table>
+ </div>
+ <? endforeach?>
+ </div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/modules/gallery/views/error_cli.txt.php b/modules/gallery/views/error_cli.txt.php
new file mode 100644
index 00000000..9f476f54
--- /dev/null
+++ b/modules/gallery/views/error_cli.txt.php
@@ -0,0 +1,3 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<? echo Kohana_Exception::text($e), "\n";
+
diff --git a/modules/gallery/views/error_user.html.php b/modules/gallery/views/error_user.html.php
new file mode 100644
index 00000000..74c6a8fb
--- /dev/null
+++ b/modules/gallery/views/error_user.html.php
@@ -0,0 +1,42 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<? if (!function_exists("t")) { function t($msg) { return $msg; } } ?>
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+ <head>
+ <style type="text/css">
+ body {
+ background: #fff;
+ font-size: 14px;
+ line-height: 130%;
+ }
+
+ div.big_box {
+ padding: 10px;
+ background: #eee;
+ border: solid 1px #ccc;
+ font-family: sans-serif;
+ color: #111;
+ width: 60em;
+ margin: 20px auto;
+ }
+
+ div#framework_error {
+ text-align: center;
+ }
+ </style>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+ <title><?= t("Something went wrong!") ?></title>
+ </head>
+ <body>
+ <div class="big_box" id="framework_error">
+ <h1>
+ <?= t("Dang... Something went wrong!") ?>
+ </h1>
+ <h2>
+ <?= t("We tried really hard, but it's broken.") ?>
+ </h2>
+ <p>
+ <?= t("Talk to your Gallery administrator for help fixing this!") ?>
+ </p>
+ </div>
+ </body>
+</html>
diff --git a/modules/gallery/views/form_uploadify.html.php b/modules/gallery/views/form_uploadify.html.php
index d811f913..588fa16d 100644
--- a/modules/gallery/views/form_uploadify.html.php
+++ b/modules/gallery/views/form_uploadify.html.php
@@ -7,7 +7,7 @@
width: 150,
height: 33,
uploader: "<?= url::file("lib/uploadify/uploadify.swf") ?>",
- script: "<?= url::site("simple_uploader/add_photo/{$album->id}") ?>",
+ script: "<?= url::site("flash_uploader/add_photo/{$album->id}") ?>",
scriptData: <?= json_encode($script_data) ?>,
fileExt: "*.gif;*.jpg;*.jpeg;*.png;*.flv;*.mp4;*.GIF;*.JPG;*.JPEG;*.PNG;*.FLV;*.MP4",
fileDesc: <?= t("Photos and movies")->for_js() ?>,
diff --git a/modules/gallery/views/kohana/error.php b/modules/gallery/views/kohana/error.php
index d55105a0..cc9d2e84 100644
--- a/modules/gallery/views/kohana/error.php
+++ b/modules/gallery/views/kohana/error.php
@@ -1,280 +1,42 @@
<?php defined("SYSPATH") or die("No direct script access.") ?>
-<? $error_id = uniqid("error") ?>
-<? if (!function_exists("t")) { function t($msg) { return $msg; } } ?>
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
- <head>
- <style type="text/css">
- body {
- background: #fff;
- font-size: 14px;
- line-height: 130%;
- }
-
- div.big_box {
- padding: 10px;
- background: #eee;
- border: solid 1px #ccc;
- font-family: sans-serif;
- color: #111;
- width: 60em;
- margin: 20px auto;
- }
-
- div#framework_error {
- text-align: center;
- }
-
- div#error_details {
- text-align: left;
- }
-
- code {
- font-family: monospace;
- font-size: 12px;
- margin: 20px 20px 20px 0px;
- color: #333;
- white-space: pre-wrap;
- white-space: -moz-pre-wrap;
- word-wrap: break-word;
- }
-
- code .line {
- padding-left: 10px;
- }
-
- h3 {
- font-family: sans-serif;
- margin: 2px 0px 0px 0px;
- padding: 8px 0px 0px 0px;
- border-top: 1px solid #ddd;
- }
-
- p {
- padding: 0px;
- margin: 0px 0px 10px 0px;
- }
-
- li, pre {
- padding: 0px;
- margin: 0px;
- }
-
- .collapsed {
- display: none;
- }
-
- .highlight {
- font-weight: bold;
- color: darkred;
- }
-
- #kohana_error .message {
- display: block;
- padding-bottom: 10px;
- }
-
- .source {
- border: solid 1px #ccc;
- background: #efe;
- margin-bottom: 5px;
- }
-
- table {
- width: 100%;
- display: block;
- margin: 0 0 0.4em;
- padding: 0;
- border-collapse: collapse;
- background: #efe;
- }
-
- table td {
- border: solid 1px #ddd;
- text-align: left;
- vertical-align: top;
- padding: 0.4em;
- }
-
- .args table td.key {
- width: 200px;
- }
-
- .number {
- padding-right: 1em;
- }
- </style>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
- <title><?= t("Something went wrong!") ?></title>
-
- <script type="text/javascript">
- function koggle(elem) {
- elem = document.getElementById(elem);
- if (elem.style && elem.style["display"]) {
- // Only works with the "style" attr
- var disp = elem.style["display"];
- } else {
- if (elem.currentStyle) {
- // For MSIE, naturally
- var disp = elem.currentStyle["display"];
- } else {
- if (window.getComputedStyle) {
- // For most other browsers
- var disp = document.defaultView.getComputedStyle(elem, null).getPropertyValue('display');
- }
- }
- }
-
- // Toggle the state of the "display" style
- elem.style.display = disp == 'block' ? 'none' : 'block';
- return false;
- }
- </script>
- </head>
- <body>
- <? try { $user = identity::active_user(); } catch (Exception $e) { } ?>
- <? $admin = php_sapi_name() == "cli" || (class_exists("User_Model") && isset($user) && $user->admin) ?>
- <div class="big_box" id="framework_error">
- <h1>
- <?= t("Dang... Something went wrong!") ?>
- </h1>
- <h2>
- <?= t("We tried really hard, but it's broken.") ?>
- </h2>
- <? if (!$admin): ?>
- <p>
- <?= t("Talk to your Gallery administrator for help fixing this!") ?>
- </p>
- <? endif ?>
- </div>
- <? if ($admin): ?>
- <div class="big_box" id="error_details">
- <h2>
- <?= t("Hey wait, you're an admin! We can tell you stuff.") ?>
- </h2>
- <div id="kohana_error">
- <h3>
- <span class="type">
- <?= $type?> [ <?= $code ?> ]:
- </span>
- <span class="message">
- <?= $message?>
- </span>
- </h3>
- <div id="<?= $error_id ?>" class="content">
- <ol class="trace">
- <li class="snippet">
- <p>
- <span class="file">
- <?= Kohana_Exception::debug_path($file)?>[ <?= $line?> ]
- </span>
- </p>
-
- <div class="source">
- <? if (Kohana_Exception::$source_output and $source_code = Kohana_Exception::debug_source($file, $line)): ?><code><? foreach ($source_code as $num => $row): ?><span class="line <?= ($num == $line) ? "highlight" : ""?>"><span class="number"><?= $num ?></span><?= htmlspecialchars($row, ENT_NOQUOTES, Kohana::CHARSET) ?></span><? endforeach ?></code>
- <? endif ?>
- </div>
- </li>
-
- <? if (Kohana_Exception::$trace_output): ?>
- <? foreach (Kohana_Exception::trace($trace) as $i => $step): ?>
- <li class="snippet">
- <p>
- <span class="file">
- <? if ($step["file"]): $source_id = "$error_id.source.$i" ?>
- <? if (Kohana_Exception::$source_output and $step["source"]): ?>
- <a href="#<?= $source_id ?>" onclick="return koggle('<?= $source_id ?>')"><?= Kohana_Exception::debug_path($step["file"])?>[ <?= $step["line"]?> ]</a>
- <? else: ?>
- <span class="file"><?= Kohana_Exception::debug_path($step["file"])?>[ <?= $step["line"]?> ]</span>
- <? endif ?>
- <? else: ?>
- {<?= t("PHP internal call")?>}
- <? endif?>
- </span>
- &raquo;
- <?= $step["function"]?>(<? if ($step["args"]): $args_id = "$error_id.args.$i" ?>
- <a href="#<?= $args_id ?>" onclick="return koggle('<?= $args_id ?>')"><?= t("arguments")?></a>
- <? endif?>)
- </p>
- <? if (isset($args_id)): ?>
- <div id="<?= $args_id ?>" class="args collapsed">
- <table cellspacing="0">
- <? foreach ($step["args"] as $name => $arg): ?>
- <tr>
- <td class="key">
- <pre><?= $name?></pre>
- </td>
- <td class="value">
- <pre><?= Kohana_Exception::safe_dump($arg, $name) ?></pre>
- </td>
- </tr>
- <? endforeach?>
- </table>
- </div>
- <? endif?>
- <? if (Kohana_Exception::$source_output and $step["source"] and isset($source_id)): ?>
- <pre id="<?= $source_id ?>" class="source collapsed"><code><? foreach ($step["source"] as $num => $row): ?><span class="line <?= ($num == $step["line"]) ? "highlight" : "" ?>"><span class="number"><?= $num ?></span><?= htmlspecialchars($row, ENT_NOQUOTES, Kohana::CHARSET) ?></span><? endforeach ?></code></pre>
- <? endif?>
- </li>
- <? unset($args_id, $source_id) ?>
- <? endforeach?>
- </ol>
- <? endif ?>
-
- </div>
- <h2>
- <a href="#<?= $env_id = $error_id."environment" ?>" onclick="return koggle('<?= $env_id ?>')"><?= t("Environment")?></a>
- </h2>
- <div id="<?= $env_id ?>" class="content collapsed">
- <? $included = get_included_files()?>
- <h3><a href="#<?= $env_id = $error_id."environment_included" ?>" onclick="return koggle('<?= $env_id ?>')"><?= t("Included files")?></a>(<?= count($included)?>)</h3>
- <div id="<?= $env_id ?>" class="collapsed">
- <table cellspacing="0">
- <? foreach ($included as $file): ?>
- <tr>
- <td>
- <pre><?= Kohana_Exception::debug_path($file)?></pre>
- </td>
- </tr>
- <? endforeach?>
- </table>
- </div>
- <? $included = get_loaded_extensions()?>
- <h3><a href="#<?= $env_id = $error_id."environment_loaded" ?>" onclick="return koggle('<?= $env_id ?>')"><?= t("Loaded extensions")?></a>(<?= count($included)?>)</h3>
- <div id="<?= $env_id ?>" class="collapsed">
- <table cellspacing="0">
- <? foreach ($included as $file): ?>
- <tr>
- <td>
- <pre><?= Kohana_Exception::debug_path($file)?></pre>
- </td>
- </tr>
- <? endforeach?>
- </table>
- </div>
- <? foreach (array("_SESSION", "_GET", "_POST", "_FILES", "_COOKIE", "_SERVER") as $var): ?>
- <? if ( empty($GLOBALS[$var]) OR ! is_array($GLOBALS[$var])) continue ?>
- <h3><a href="#<?= $env_id = "$error_id.environment" . strtolower($var) ?>"
- onclick="return koggle('<?= $env_id ?>')">$<?= $var?></a></h3>
- <div id="<?= $env_id ?>" class="collapsed">
- <table cellspacing="0">
- <? foreach ($GLOBALS[$var] as $key => $value): ?>
- <tr>
- <td class="key">
- <code>
- <?= $key?>
- </code>
- </td>
- <td class="value">
- <pre><?= Kohana_Exception::safe_dump($value, $key) ?></pre>
- </td>
- </tr>
- <? endforeach?>
- </table>
- </div>
- <? endforeach?>
- </div>
- </div>
- </div>
- <? endif ?>
- </body>
-</html>
+<?
+// This is the template for all HTML errors. If you're throwing an exception and you want your
+// error to appear differently, extend Kohana_Exception and specify a different template.
+
+// Log validation exceptions to ease debugging
+if ($e instanceof ORM_Validation_Exception) {
+ Kohana_Log::add("error", "Validation errors: " . print_r($e->validation->errors(), 1));
+}
+
+if (php_sapi_name() == "cli") {
+ include Kohana::find_file("views", "error_cli.txt");
+ return;
+}
+
+try {
+ // Admins get a special error page
+ $user = identity::active_user();
+ if ($user && $user->admin) {
+ include Kohana::find_file("views", "error_admin.html");
+ return;
+ }
+} catch (Exception $ignored) {
+}
+
+// Try to show a themed error page for 404 errors
+if ($e instanceof Kohana_404_Exception) {
+ $view = new Theme_View("page.html", "other", "error");
+ $view->page_title = t("Dang... Page not found!");
+ $view->content = new View("error_404.html");
+ $user = identity::active_user();
+ $view->content->is_guest = $user && $user->guest;
+ if ($view->content->is_guest) {
+ $view->content->login_form = new View("login_ajax.html");
+ $view->content->login_form->form = auth::get_login_form("login/auth_html");
+ }
+ print $view;
+ return;
+}
+
+header("HTTP/1.1 500 Internal Server Error");
+include Kohana::find_file("views", "error_user.html");
diff --git a/modules/gallery/views/login_ajax.html.php b/modules/gallery/views/login_ajax.html.php
index 36647f9d..88fe2389 100644
--- a/modules/gallery/views/login_ajax.html.php
+++ b/modules/gallery/views/login_ajax.html.php
@@ -10,9 +10,16 @@
$(".submit").addClass("g-button ui-state-default ui-corner-all");
$(".submit").gallery_hover_init();
ajaxify_login_reset_form();
+
+ // See comment about IE7 below
+ setTimeout('$("#g-name").focus()', 100);
}
});
});
+
+ // Setting the focus here doesn't work on IE7, perhaps because the field is
+ // not ready yet? So set a timeout and do it the next time we're idle
+ setTimeout('$("#g-username").focus()', 100);
});
function ajaxify_login_reset_form() {
diff --git a/modules/gallery_unit_test/controllers/gallery_unit_test.php b/modules/gallery_unit_test/controllers/gallery_unit_test.php
index 80ee16d9..e241e1dd 100644
--- a/modules/gallery_unit_test/controllers/gallery_unit_test.php
+++ b/modules/gallery_unit_test/controllers/gallery_unit_test.php
@@ -89,7 +89,9 @@ class Gallery_Unit_Test_Controller extends Controller {
}
}
- // Clean out the filesystem
+ // Clean out the filesystem. Note that this cleans out test/var/database.php, but that's ok
+ // because we technically don't need it anymore. If this is confusing, we could always
+ // arrange to preserve that one file.
@system("rm -rf test/var");
@mkdir('test/var/logs', 0777, true);
diff --git a/modules/image_block/helpers/image_block_block.php b/modules/image_block/helpers/image_block_block.php
index 51ccc4a0..da6e8782 100644
--- a/modules/image_block/helpers/image_block_block.php
+++ b/modules/image_block/helpers/image_block_block.php
@@ -31,7 +31,7 @@ class image_block_block_Core {
// @todo Consider another fallback if further optimizations are necessary.
$attempts = 0;
do {
- $item = item::random_query(array(array("type", "!=", "album")))->find_all(1)->current();
+ $item = item::random_query()->where("type", "!=", "album")->find_all(1)->current();
} while (!$item && $attempts++ < 3);
if ($item && $item->loaded()) {
$block = new Block();
diff --git a/modules/organize/controllers/organize.php b/modules/organize/controllers/organize.php
index 8dc8692c..135a6fc9 100644
--- a/modules/organize/controllers/organize.php
+++ b/modules/organize/controllers/organize.php
@@ -19,159 +19,42 @@
*/
class Organize_Controller extends Controller {
function dialog($album_id) {
- $album = ORM::factory("item", $album_id);
- access::required("view", $album);
- access::required("edit", $album);
-
- $v = new View("organize_dialog.html");
- $v->album = $album;
- $v->album_tree = self::_expanded_tree(ORM::factory("item", 1), $album);
- $v->micro_thumb_grid = self::_get_micro_thumb_grid($album, 0);
- print $v;
- }
-
- function album($album_id, $offset) {
- $album = ORM::factory("item", $album_id);
- access::required("view", $album);
- access::required("edit", $album);
-
- print json_encode(
- array("grid" => (string)self::_get_micro_thumb_grid($album, $offset),
- "sort_column" => $album->sort_column,
- "sort_order" => $album->sort_order));
- }
-
- function move_to($target_album_id) {
- access::verify_csrf();
-
- $target_album = ORM::factory("item", $target_album_id);
- access::required("view", $target_album);
- access::required("add", $target_album);
-
- $source_album = null;
- foreach (Input::instance()->post("source_ids") as $source_id) {
- $source = ORM::factory("item", $source_id);
- if (empty($source_album)) { // get the source_album
- $source_album = $source->parent();
- }
- if (!$source->contains($target_album)) {
- access::required("edit", $source);
- item::move($source, $target_album);
- }
- }
-
- print json_encode(
- array("tree" => (string)self::_expanded_tree(ORM::factory("item", 1), $source_album),
- "grid" => (string)self::_get_micro_thumb_grid($source_album, 0)));
- }
-
- function rearrange($target_id, $before_or_after) {
- access::verify_csrf();
-
- $target = ORM::factory("item", $target_id);
- $album = $target->parent();
- access::required("view", $album);
- access::required("edit", $album);
-
- //if (locales::is_rtl()) { // invert the position if the locale is rtl
- // $before_or_after = $before_or_after == "after" ? "before" : "after";
- //}
-
- $source_ids = Input::instance()->post("source_ids", array());
-
- if ($album->sort_column != "weight") {
- $i = 0;
- foreach ($album->children() as $child) {
- // Do this directly in the database to avoid sending notifications
- db::build()
- ->update("items")
- ->set("weight", ++$i)
- ->where("id", "=", $child->id)
- ->execute();
- }
- $album->sort_column = "weight";
- $album->sort_order = "ASC";
- $album->save();
- $target->reload();
- }
-
- // Find the insertion point
- $target_weight = $target->weight;
- if ($before_or_after == "after") {
- $target_weight++;
- }
-
- // Make a hole
- $count = count($source_ids);
- db::build()
- ->update("items")
- ->set("weight", new Database_Expression("`weight` + $count"))
- ->where("weight", ">=", $target_weight)
- ->where("parent_id", "=", $album->id)
- ->execute();
-
- // Insert source items into the hole
- foreach ($source_ids as $source_id) {
- db::build()
- ->update("items")
- ->set("weight", $target_weight++)
- ->where("id", "=", $source_id)
- ->execute();
- }
-
- module::event("album_rearrange", $album);
-
- print json_encode(
- array("grid" => (string)self::_get_micro_thumb_grid($album, 0),
- "sort_column" => $album->sort_column,
- "sort_order" => $album->sort_order));
- }
-
- public function sort_order($album_id, $col, $dir) {
- access::verify_csrf();
+ $input = Input::instance();
$album = ORM::factory("item", $album_id);
access::required("view", $album);
access::required("edit", $album);
- $options = album::get_sort_order_options();
- if (!isset($options[$col])) {
- return;
+ $user = identity::active_user();
+ $sort_fields = array();
+ foreach (album::get_sort_order_options() as $field => $description) {
+ $sort_fields[$field] = (string)$description;
}
+ $sort_order = array("ASC" => (string)t("Ascending"), "DESC" => (string)t("Descending"));
+ $file_filter = json_encode(
+ array("photo" => array("label" => "Images",
+ "types" => array("*.jpg", "*.jpeg", "*.png", "*.gif")),
+ "movie" => array("label" => "Movies", "types" => array("*.flv", "*.mp4"))));
- $album->sort_column = $col;
- $album->sort_order = $dir;
- $album->save();
-
- print json_encode(
- array("grid" => (string)self::_get_micro_thumb_grid($album, 0),
- "sort_column" => $album->sort_column,
- "sort_order" => $album->sort_order));
- }
-
- private static function _get_micro_thumb_grid(Item_Model $album, $offset) {
- $v = new View("organize_thumb_grid.html");
+ $v = new View("organize_dialog.html");
$v->album = $album;
- $v->offset = (int) $offset;
- return $v;
+ $v->domain = $input->server("SERVER_NAME");
+ $v->access_key = rest::access_key();
+ $v->file_filter = addslashes($file_filter);
+ $v->sort_order = addslashes(json_encode($sort_order));
+ $v->sort_fields = addslashes(json_encode($sort_fields));
+ $v->rest_uri = url::site("rest") . "/";
+ $v->controller_uri = url::site("organize") . "/";
+ $v->swf_uri = url::file("modules/organize/lib/Gallery3WebClient.swf?") .
+ filemtime(MODPATH . "organize/lib/Gallery3WebClient.swf");
+ print $v;
}
- public function tree($album_id) {
- $album = ORM::factory("item", $album_id);
- access::required("view", $album);
-
- print self::_expanded_tree($album);
+ function add_album_fields() {
+ print json_encode(array("title" => (string)t("Title"),
+ "description" => (string)t("Description"),
+ "name" => (string)t("Directory name"),
+ "slug" => (string)t("Internet Address")));
}
- /**
- * Create an HTML representation of the tree from the root down to the selected album. We only
- * include albums along the descendant hierarchy that includes the selected album, and the
- * immediate child albums.
- */
- private static function _expanded_tree($root, $selected_album=null) {
- $v = new View("organize_tree.html");
- $v->album = $root;
- $v->selected = $selected_album;
- return $v;
- }
}
diff --git a/modules/organize/css/organize.css b/modules/organize/css/organize.css
deleted file mode 100644
index 7a8c3a5f..00000000
--- a/modules/organize/css/organize.css
+++ /dev/null
@@ -1,156 +0,0 @@
-/*******************************************************************
- * Dialog wide styles
- */
-
-#g-organize {
- margin: 0 !important;
- min-height: auto;
- padding: 0 !important;
- position: relative;
- width: 100%;
-}
-
-#g-organize-content-pane {
- height: 100%;
- margin: 0 !important;
- padding: 0 !important;
- position: absolute;
- width: 100%;
-}
-
-/*******************************************************************
- * Album Tree styles
- */
-
-#g-organize #g-organize-tree-container {
- margin: 0;
- min-height: 100%;
- padding: 0;
- position: relative;
- width: 20%;
-}
-
-#g-organize #g-organize-tree-container h3 {
- margin-bottom: 0.1em;
-}
-
-#g-organize-album-tree {
- overflow: auto;
-}
-
-#g-organize-album-tree ul li {
- padding: 0 0 .2em 1.2em;
- width: 90%;
-}
-
-.rtl #g-organize-album-tree ul li {
- padding: 0 1.2em .2em 0;
- width: 90%;
-}
-
-.g-organize-album span {
- cursor: pointer;
-}
-
-.g-organize-album-text {
- cursor: pointer;
- display: block;
- margin: 2px 0px 1px 2px;
- width: auto;
-}
-
-.rtl .g-organize-album-text {
- cursor: pointer;
- display: block;
- margin: 2px 2px 1px 1px;
- width: auto;
-}
-
-.g-organize-album-text:hover {
- border-width: 1px;
- border-style: dotted;
-}
-
-/*******************************************************************
- * Album panel styles
- */
-
-#g-organize #g-organize-detail {
- margin: 0 !important;
- min-height: 100%;
- padding: 0 !important;
- position: relative;
- width: 80%;
-}
-
-#g-organize #g-organize-detail .g-message-block {
- margin: 0;
-}
-
-#g-organize #g-organize-detail .g-message-block li {
- padding-bottom: .2em;
- padding-top: .2em;
- width: auto;
-}
-
-#g-organize-microthumb-grid {
- border-width: 1px;
- border-style: solid;
- bottom: 1.8em;
- left: 0;
- margin: 0 !important;
- overflow-x: hidden;
- overflow-y: auto;
- padding: .4em !important;
- position: absolute;
- right: 0;
- top: 1.6em;
-}
-.g-organize-microthumb-grid-cell {
- display: block;
- height: 100px;
- margin: 6px;
- padding: .4em 0 !important;
- position: relative;
- text-align: center;
- width: 110px;
-}
-
-.ui-selectable-helper {
- z-index: 2000 !important;
-}
-
-.g-organize-microthumb-grid-cell .ui-icon {
- bottom: 0;
- left: 0;
- position: absolute;
- z-index: 4000;
-}
-
-/****************************************************************
- * Controls styles
- */
-
-#g-organize-controls {
- bottom: 0;
- height: 1.9em;
- left: 0;
- margin: 0 !important;
- padding: .1em .4em;
- position: absolute;
- right: 0;
-}
-
-#g-organize-controls #g-organize-sort-order-text {
- padding: .2em 0 0 0;
-}
-
-
-#g-organize-controls select {
- margin-left: .42em;
- display: inline;
-}
-
-#g-organize-close {
- margin-right: 12px;
-}
diff --git a/modules/organize/css/organize_theme.css b/modules/organize/css/organize_theme.css
index 3d289755..e698f88d 100644
--- a/modules/organize/css/organize_theme.css
+++ b/modules/organize/css/organize_theme.css
@@ -1,16 +1,18 @@
/** *******************************************************************
* Organize styles that are theme overrideable
*********************************************************************/
-.g-organize-microthumb-grid-cell.ui-selected {
- background: #DFEFFC !important;
+#g-organize {
+ background-color: #FFFFFF;
+ border: 0px solid #000000;
+ color: #0E2B52;
}
-#g-organize-microthumb-grid,
-#g-organize-drop-target-marker,
-.g-organize-album-text:hover {
- border-color: #79B7E7;
+#g-organize-hover {
+ background-color: #CFDEFF;
+ display: none;
}
-#g-organize-drop-target-marker {
- background-color: #79B7E7;
+#g-organize-active {
+ background-color: #6699CC;
+ display: none;
}
diff --git a/modules/organize/helpers/organize_event.php b/modules/organize/helpers/organize_event.php
index a9d64637..ae05fb5d 100644
--- a/modules/organize/helpers/organize_event.php
+++ b/modules/organize/helpers/organize_event.php
@@ -42,4 +42,22 @@ class organize_event_Core {
}
}
+ static function pre_deactivate($data) {
+ if ($data->module == "rest") {
+ $data->messages["warn"][] = t("The Organize module requires the Rest module.");
+ }
+ }
+
+ static function module_change($changes) {
+ if (!module::is_active("rest") || in_array("rest", $changes->deactivate)) {
+ site_status::warning(
+ t("The Organize module requires the Rest module. " .
+ "<a href=\"%url\">Activate the Rest module now</a>",
+ array("url" => html::mark_clean(url::site("admin/modules")))),
+ "organize_needs_rest");
+ } else {
+ site_status::clear("organize_needs_rest");
+ }
+ }
+
}
diff --git a/modules/organize/helpers/organize_installer.php b/modules/organize/helpers/organize_installer.php
new file mode 100644
index 00000000..bbe6fc65
--- /dev/null
+++ b/modules/organize/helpers/organize_installer.php
@@ -0,0 +1,46 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2010 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 organize_installer {
+ static function deactivate() {
+ site_status::clear("organize_needs_rest");
+ }
+
+ static function upgrade($version) {
+ if ($version == 1) {
+ if (!module::is_active("rest")) {
+ site_status::warning(
+ t("The Organize module requires the Rest module. " .
+ "<a href=\"%url\">Activate the Rest module now</a>",
+ array("url" => html::mark_clean(url::site("admin/modules")))),
+ "organize_needs_rest");
+ }
+
+ module::set_version("organize", $version = 2);
+ }
+ }
+
+ static function can_activate() {
+ $messages = array();
+ if (!module::is_active("rest")) {
+ $messages["warn"][] = t("The Organize module requires the Rest module.");
+ }
+ return $messages;
+ }
+}
diff --git a/modules/organize/helpers/organize_theme.php b/modules/organize/helpers/organize_theme.php
index da4a1b41..d69ab82c 100644
--- a/modules/organize/helpers/organize_theme.php
+++ b/modules/organize/helpers/organize_theme.php
@@ -21,12 +21,6 @@ class organize_theme {
static function head($theme) {
$item = $theme->item();
if ($item && access::can("edit", $item) && $item->is_album()) {
- // @todo: Defer loading js/css until we're loading the organize dialog as <script> and
- // <link> elements so that we're not forcing them to be downloaded on every page view (which
- // is expensive in terms of browser latency). When we do that, we'll have to figure out an
- // approach that lets us continue to use the Kohana cascading filesystem.
- $theme->script("organize.js");
- $theme->css("organize.css");
$theme->css("organize_theme.css");
}
}
diff --git a/modules/organize/js/organize.js b/modules/organize/js/organize.js
deleted file mode 100644
index 5a483caf..00000000
--- a/modules/organize/js/organize.js
+++ /dev/null
@@ -1,310 +0,0 @@
-(function($) {
- $.organize = {
- micro_thumb_draggable: {
- handle: ".ui-selected",
- distance: 10,
- cursorAt: { left: -10, top: -10},
- appendTo: "#g-organize-content-pane",
- helper: function(event, ui) {
- var selected = $(".ui-draggable.ui-selected img");
- var set = $('<div class="g-drag-helper"></div>')
- .css({
- zIndex: 2000,
- width: 80,
- height: Math.ceil(selected.length / 5) * 16
- });
-
- selected.each(function(i) {
- var row = parseInt(i / 5);
- var j = i - (row * 5);
- var o = $(this).offset();
- var copy = $(this).clone()
- .css({
- width: $(this).width(), height: $(this).height(), display: "block",
- margin: 0, position: 'absolute', outline: '5px solid #fff',
- left: o.left - event.pageX, top: o.top - event.pageY
- })
- .appendTo(set)
- .animate({ width: 10, height: 10, outlineWidth: 1, margin: 1,
- left: (20 * j), top: (row * 20) }, 500);
- });
- return set;
- },
-
- start: function(event, ui) {
- $("#g-organize-microthumb-grid .ui-selected").hide();
- },
-
- drag: function(event, ui) {
- var top = $("#g-organize-microthumb-grid").offset().top;
- var height = $("#g-organize-microthumb-grid").height();
- var scrollTop = $("#g-organize-microthumb-grid").scrollTop();
- if (ui.offset.top > height + top - 20) {
- scrollTop += 100;
- } else if (ui.offset.top < top + 20) {
- scrollTop = Math.max(0, scrollTop - 100);
- }
- $("#g-organize-microthumb-grid").scrollTop(scrollTop);
- }
- },
-
- content_droppable: {
- accept: "*",
- tolerance: "pointer",
- greedy: true,
- drop: function(event, ui) {
- $(".g-mouse-drag-over").removeClass("g-mouse-drag-over");
- var target = $("#g-organize-drop-target-marker").data("drop_position");
- if (target == null) {
- target = {
- position: false,
- id: $(".g-organize-microthumb-grid-cell:visible:last").attr("ref")
- };
- }
- $.organize.do_drop({
- url: rearrange_url
- .replace("__TARGET_ID__", target.id)
- .replace("__BEFORE__", target.position ? "before" : "after"),
- source: $(ui.helper).children("img")
- });
- }
- },
-
- branch_droppable: {
- accept: "*",
- tolerance: "pointer",
- greedy: true,
- drop: function(event, ui) {
- if ($(event.target).hasClass("g-view-only")) {
- $("#g-organize-drop-target-marker").remove();
- $(".ui-selected").show();
- } else {
- $.organize.do_drop({
- url: move_url.replace("__ALBUM_ID__", $(event.target).attr("ref")),
- source: $(ui.helper).children("img")
- });
- }
- }
- },
-
- do_drop: function(options) {
- $("#g-organize-microthumb-grid").selectable("destroy");
- var source_ids = [];
- $(options.source).each(function(i) {
- source_ids.push($(this).attr("ref"));
- });
-
- if (source_ids.length) {
- var loading = $('<div class="g-dialog-loading-large">&nbsp;</div>')
- .css({bottom: 5,
- opacity: .5,
- left: 0,
- position: "absolute",
- right: 0,
- top: 0,
- zIndex: 2000
- });
- $("#g-organize-microthumb-grid").append(loading);
-
- $.post(options.url,
- { "source_ids[]": source_ids },
- function(data) {
- $.organize._refresh(data);
- $(".g-dialog-loading-large").remove();
- },
- "json");
- }
- },
-
- _refresh: function(data) {
- if (data.tree) {
- $("#g-organize-album-tree").html(data.tree);
- }
- if (data.grid) {
- $("#g-organize-microthumb-grid").html(data.grid);
- $("#g-organize-sort-column").attr("value", data.sort_column);
- $("#g-organize-sort-order").attr("value", data.sort_order);
- }
- $.organize.set_handlers();
- },
-
- grid_mouse_leave_handler: function(event) {
- if ($(".g-drag-helper").length && $("#g-organize-drop-target-marker").length) {
- $("#g-organize-drop-target-marker").remove();
- }
- },
-
- grid_mouse_move_handler: function(event) {
- if ($(".g-drag-helper").length) {
- var organizeData = $("#g-organize").data("organizeData");
- var thumbGrid = $("#g-organize-microthumb-grid");
- var visibleCells = $(".g-organize-microthumb-grid-cell:visible");
- var scrollTop = thumbGrid.scrollTop();
-
- var item = $(".g-mouse-drag-over");
- if (item.length == 0) {
- var itemColumn = Math.floor((event.pageX - thumbGrid.offset().left) / organizeData.width);
- itemColumn = organizeData.rtl ? organizeData.width - itemColumn : itemColumn;
- var itemRow = Math.floor((event.pageY + scrollTop - thumbGrid.offset().top) / organizeData.height);
- var itemIndex = Math.min(itemRow * organizeData.columns + itemColumn, visibleCells.length - 1);
- item = visibleCells.get(itemIndex);
- }
-
- var before = event.pageX < ($(item).offset().left + $(item).width() / 2);
- var left = $(item).position().left + (before ? 0 : organizeData.width) - 3;
- var top = $(item).position().top + 6 + scrollTop;
-
- if ($("#g-organize-drop-target-marker").length) {
- $("#g-organize-drop-target-marker").remove();
- }
-
- var set = $('<div id="g-organize-drop-target-marker"></div>')
- .css({zIndex: 2000,
- width: 2,
- height: 112,
- borderWidth: 1,
- borderStyle: "solid",
- position: "absolute",
- top: top, left: left
- })
- .data("drop_position", {id: $(item).attr("ref"),
- position: organizeData.rtl ? !before : before});
- thumbGrid.append(set);
- }
- return true;
- },
-
- /**
- * Dynamically initialize the organize dialog when it is displayed
- */
- init: function(data) {
- var self = this;
- // Deal with ui.jquery bug: http://dev.jqueryui.com/ticket/4475 (target 1.8?)
- $(".sf-menu li.sfHover ul").css("z-index", 68);
- $("#g-dialog").dialog("option", "zIndex", 70);
- $("#g-dialog").bind("dialogopen", function(event, ui) {
- var outerHeight = $(".g-organize-microthumb-grid-cell").outerHeight(true);
- var outerWidth = $(".g-organize-microthumb-grid-cell").outerWidth(true);
- var gridInnerWidth = $("#g-organize-microthumb-grid").innerWidth() - 2 * parseFloat($("#g-organize-microthumb-grid").css("paddingLeft"));
- $("#g-organize")
- .height($("#g-dialog").innerHeight() - 20)
- .data("organizeData", {
- rtl: $("body").hasClass("rtl"),
- height: outerHeight,
- width: outerWidth,
- columns: Math.floor(gridInnerWidth / outerWidth)
- });
- });
-
- $("#g-dialog").bind("dialogclose", function(event, ui) {
- window.location.reload();
- });
-
- $("#g-organize-close").click(function(event) {
- $("#g-dialog").dialog("close");
- });
-
- $("#g-organize-sort-column,#g-organize-sort-order").change(function(event) {
- $.organize.resort($("#g-organize-sort-column").attr("value"),
- $("#g-organize-sort-order").attr("value"));
- });
-
- $.organize.set_handlers();
- },
-
- set_handlers: function() {
- $("#g-organize-microthumb-grid")
- .selectable({filter: ".g-organize-microthumb-grid-cell"})
- .mousemove($.organize.grid_mouse_move_handler)
- .mouseleave($.organize.grid_mouse_leave_handler)
- .droppable($.organize.content_droppable);
- $(".g-organize-microthumb-grid-cell")
- // need to manually add this class in case we care calling with additional elements
- .addClass("ui-selectee")
- .mouseleave(function(event) {
- if ($(".g-drag-helper").length) {
- $(this).removeClass("g-mouse-drag-over");
- }
- })
- .mouseenter(function(event) {
- $(".g-mouse-drag-over").removeClass("g-mouse-drag-over");
- if ($(".g-drag-helper").length) {
- $(this).addClass("g-mouse-drag-over");
- }
- })
- .draggable($.organize.micro_thumb_draggable);
- $(".g-organize-album").droppable($.organize.branch_droppable);
- $(".g-organize-album-text").click($.organize.show_album);
- $("#g-organize-album-tree .ui-icon-plus,#g-organize-album-tree .ui-icon-minus").click($.organize.toggle_branch);
- },
-
- toggle_branch: function(event) {
- event.preventDefault();
- var target = $(event.currentTarget);
- var branch = $(target).parent();
- var id = $(event.currentTarget).parent().attr("ref");
-
- if ($(target).hasClass("ui-icon-plus")) {
- // Expanding
- if (!branch.find("ul").length) {
- $.get(tree_url.replace("__ALBUM_ID__", id), { }, function(data) {
- branch.replaceWith(data);
- $.organize.set_handlers();
- });
- } else {
- branch.find("ul:eq(0)").slideDown();
- }
- } else {
- // Contracting
- branch.find("ul:eq(0)").slideUp();
- }
- $(target).toggleClass("ui-icon-plus");
- $(target).toggleClass("ui-icon-minus");
- },
-
- /**
- * When the text of a selection is clicked, then show that albums contents
- */
- show_album: function(event) {
- event.preventDefault();
- if ($(event.currentTarget).hasClass("ui-state-focus")) {
- return;
- }
- var parent = $(event.currentTarget).parents(".g-organize-album");
- if ($(parent).hasClass("g-view-only")) {
- return;
- }
- $("#g-organize-microthumb-grid").selectable("destroy");
- var id = $(event.currentTarget).attr("ref");
- $(".g-organize-album-text.ui-state-focus").removeClass("ui-state-focus");
- $(".g-organize-album-text[ref=" + id + "]").addClass("ui-state-focus");
- var url = $("#g-organize-microthumb-grid").attr("ref").replace("__ITEM_ID__", id).replace("__OFFSET__", 0);
- $.get(url, {},
- function(data) {
- $("#g-organize-microthumb-grid").html(data.grid);
- $("#g-organize-sort-column").attr("value", data.sort_column);
- $("#g-organize-sort-order").attr("value", data.sort_order);
- $.organize.set_handlers();
- },
- "json");
- },
-
- /**
- * Change the sort order.
- */
- resort: function(column, dir) {
- var url = sort_order_url
- .replace("__ALBUM_ID__", $("#g-organize-album-tree .ui-state-focus").attr("ref"))
- .replace("__COL__", column)
- .replace("__DIR__", dir);
- $.get(url, {},
- function(data) {
- $("#g-organize-microthumb-grid").html(data.grid);
- $("#g-organize-sort-column").attr("value", data.sort_column);
- $("#g-organize-sort-order").attr("value", data.sort_order);
- $.organize.set_handlers();
- },
- "json");
- }
- };
-})(jQuery);
diff --git a/modules/organize/lib/Gallery3WebClient.swf b/modules/organize/lib/Gallery3WebClient.swf
new file mode 100644
index 00000000..40249a73
--- /dev/null
+++ b/modules/organize/lib/Gallery3WebClient.swf
Binary files differ
diff --git a/modules/organize/module.info b/modules/organize/module.info
index 5c6b1de0..d7199571 100644
--- a/modules/organize/module.info
+++ b/modules/organize/module.info
@@ -1,3 +1,3 @@
name = "Organize"
description = "Organize your gallery by apply tags or moving images"
-version = 1
+version = 2
diff --git a/modules/organize/views/organize_dialog.html.php b/modules/organize/views/organize_dialog.html.php
index 38d05b81..c41e5960 100644
--- a/modules/organize/views/organize_dialog.html.php
+++ b/modules/organize/views/organize_dialog.html.php
@@ -1,48 +1,131 @@
<?php defined("SYSPATH") or die("No direct script access.") ?>
+<script type="text/javascript" src="<?= url::file("lib/swfobject.js") ?>"></script>
+<style type="text/css" media="screen">
+ #flashContent {
+ display:none;
+ }
+
+ .g-organize {
+ padding: 0;
+ margins: 0;
+ }
+
+ object {
+ display: block;
+ outline: none;
+ }
+
+ #g-dialog {
+ padding: 0;
+ }
+</style>
+
<script type="text/javascript">
- var move_url = "<?= url::site("organize/move_to/__ALBUM_ID__?csrf=$csrf") ?>";
- var rearrange_url = "<?= url::site("organize/rearrange/__TARGET_ID__/__BEFORE__?csrf=$csrf") ?>";
- var sort_order_url = "<?= url::site("organize/sort_order/__ALBUM_ID__/__COL__/__DIR__?csrf=$csrf") ?>";
- var tree_url = "<?= url::site("organize/tree/__ALBUM_ID__") ?>";
+ $("#g-dialog").bind("dialogclose", function(event, ui) {
+ // @todo do a call to organize/closing to end the batch
+ window.location.reload();
+ });
+
+ function closeOrganizeDialog() {
+ $("#g-dialog").dialog("close");
+ }
+
+ function setTitle(title) {
+ $("#ui-dialog-title-g-dialog").text(<?= t("Organize :: ")->for_js() ?> + title);
+ }
+
+ function getOrganizeStyles() {
+ return {
+ color: colorToHex($("#g-organize").css("color")),
+ backgroundColor: colorToHex($("#g-organize").css("backgroundColor")),
+ borderColor: colorToHex($("#g-organize").css("borderLeftColor")),
+ rollOverColor: colorToHex($("#g-organize-hover").css("backgroundColor")),
+ selectionColor: colorToHex($("#g-organize-active").css("backgroundColor"))
+ };
+ }
+
+ function colorToHex(color) {
+ // Surprising no one, the color extracted from the css is in a different format
+ // in IE than it is when extracted from FF or Chrome. FF and Chrome return
+ // the of "rgb(nn,nn,nn)". Where as IE returns it as #hhhhhh.
+
+ if (color.indexOf("#") === 0) {
+ return '0x' + color.substring(1);
+ } else {
+ var digits = /(.*?)rgb\((\d+), (\d+), (\d+)\)/.exec(color);
+
+ var red = parseInt(digits[2]);
+ var green = parseInt(digits[3]);
+ var blue = parseInt(digits[4]);
+
+ var rgb = blue | (green << 8) | (red << 16);
+ return digits[1] + '0x' + rgb.toString(16);
+ }
+ }
+
+ function getTextStrings() {
+ return {
+ statusText: <?= t("Drag and drop photos to re-order or move between album")->for_js() ?>,
+ remoteError:
+ <?= t("Remote server error, please contact your gallery administrator")->for_js() ?>,
+ addAlbumError: <?= t("The above highlighted fields are invalid")->for_js() ?>,
+ errorOccurred: <?= t("Remote error ocurred")->for_js() ?>,
+ addAlbum: <?= t("Add album")->for_js() ?>,
+ addImages: <?= t("Add photo")->for_js() ?>,
+ deleteSelected: <?= t("Delete")->for_js() ?>,
+ uploadedText: <?= t("Uploaded {0}")->for_js() ?>,
+ removeFileText: <?= t("Remove")->for_js() ?>,
+ progressLabel: <?= t("Completed image %1 of %2")->for_js() ?>,
+ uploadLabel: <?= t("Loaded %1 of %2 bytes")->for_js() ?>,
+ moveTitle: <?= t("Move images")->for_js() ?>,
+ deleteTitle: <?= t("Delete image")->for_js() ?>,
+ uploadTitle: <?= t("Upload image")->for_js() ?>,
+ cancel: <?= t("Cancel")->for_js() ?>,
+ close: <?= t("Close")->for_js() ?>
+ };
+ }
+
+ function getGalleryParameters() {
+ return {
+ domain: "<?= $domain ?>",
+ accessKey: "<?= $access_key ?>",
+ protocol: "<?= request::protocol() ?>",
+ fileFilter: "<?= $file_filter ?>",
+ sortOrder: "<?= $sort_order ?>",
+ sortFields: "<?= $sort_fields ?>",
+ albumId: "<?= $album->id ?>",
+ restUri: "<?= $rest_uri ?>",
+ controllerUri: "<?= $controller_uri ?>"
+ };
+ };
+ /*
+ For version detection, set to min. required Flash Player version, or 0 (or 0.0.0),
+ for no version detection.
+ */
+ var swfVersionStr = "0.0.0";
+ /* To use express install, set to playerProductInstall.swf, otherwise the empty string.*/
+ var xiSwfUrlStr = "";
+ var flashvars = {};
+
+ var size = $.gallery_get_viewport_size();
+
+ var params = {};
+ params.quality = "high";
+ params.bgcolor = "#ffffff";
+ params.allowNetworking = "all";
+ params.allowscriptaccess = "sameDomain";
+ params.allowfullscreen = "true";
+ var attributes = {};
+ attributes.id = "Gallery3WebClient";
+ attributes.name = "Gallery3WebClient";
+ attributes.align = "middle";
+ swfobject.embedSWF("<?= $swf_uri ?>",
+ "flashContent", size.width() - 100, size.height() - 135,
+ swfVersionStr, xiSwfUrlStr, flashvars, params, attributes);
</script>
<div id="g-organize" class="g-dialog-panel">
- <h1 style="display:none"><?= t("Organize %name", array("name" => html::purify($album->title))) ?></h1>
- <div id="g-organize-content-pane">
- <div id="g-organize-tree-container" class="g-left ui-helper-clearfix">
- <h3><?= t("Albums") ?></h3>
- <ul id="g-organize-album-tree">
- <?= $album_tree ?>
- </ul>
- </div>
- <div id="g-organize-detail" class="g-left ui-helper-clearfix">
- <ul id="g-action-status" class="g-message-block">
- <li class="g-info"><?= t("Drag and drop photos to re-order or move between albums") ?></li>
- </ul>
- <div id="g-organize-microthumb-grid" class="ui-widget"
- ref="<?= url::site("organize/album/__ITEM_ID__/__OFFSET__") ?>">
- <?= $micro_thumb_grid ?>
- </div>
- <div id="g-organize-controls" class="ui-widget-header">
- <a id="g-organize-close" href="#" ref="done"
- class="g-button g-right ui-corner-all ui-state-default"><?= t("Close") ?></a>
- <form>
- <ul>
- <li id="g-organize-sort-order-text" class="g-left"><?= t("Sort order") ?></li>
- <li class="g-left">
- <?= form::dropdown(array("id" => "g-organize-sort-column"),
- album::get_sort_order_options(), $album->sort_column) ?>
- </li>
- <li class="g-left">
- <?= form::dropdown(array("id" => "g-organize-sort-order"),
- array("ASC" => t("Ascending"), "DESC" => t("Descending")), $album->sort_order) ?>
- </li>
- </ul>
- </form>
- </div>
- </div>
- </div>
+ <!-- The following spans are placeholders so we can load the hover and active styles for the flex component -->
+ <span id="g-organize-hover" /><span id="g-organize-active" />
+ <h1 style="display:none"><?= t("Organize :: %name", array("name" => html::purify($album->title))) ?></h1>
+ <div id="flashContent">&nbsp;</div>
</div>
-
-<script type="text/javascript">
- $("#g-organize").ready($.organize.init);
-</script>
diff --git a/modules/organize/views/organize_thumb_grid.html.php b/modules/organize/views/organize_thumb_grid.html.php
deleted file mode 100644
index f5db53d4..00000000
--- a/modules/organize/views/organize_thumb_grid.html.php
+++ /dev/null
@@ -1,22 +0,0 @@
-<?php defined("SYSPATH") or die("No direct script access.") ?>
-<? foreach ($album->children(25, $offset) as $child): ?>
-<div class="g-organize-microthumb-grid-cell g-left ui-state-default ui-state-active <?= $child->is_album() ? "g-album" : "g-photo" ?>"
- ref="<?= $child->id ?>">
- <?= $child->thumb_img(array("class" => "g-thumbnail", "ref" => $child->id), 90, true) ?>
- <span<?= $child->is_album() ? " class=\"ui-icon ui-icon-note\"" : "" ?>></span>
-</div>
-<? endforeach ?>
-
-<? if ($album->children_count() > $offset): ?>
-<script type="text/javascript">
- setTimeout(function() {
- $.get("<?= url::site("organize/album/$album->id/" . ($offset + 25)) ?>",
- {},
- function(data) {
- $("#g-organize-microthumb-grid").append(data.grid);
- $.organize.set_handlers();
- },
- "json");
- }, 50);
-</script>
-<? endif ?>
diff --git a/modules/organize/views/organize_tree.html.php b/modules/organize/views/organize_tree.html.php
deleted file mode 100644
index 044b6858..00000000
--- a/modules/organize/views/organize_tree.html.php
+++ /dev/null
@@ -1,29 +0,0 @@
-<?php defined("SYSPATH") or die("No direct script access.") ?>
-<li class="g-organize-album ui-icon-left <?= access::can("edit", $album) ? "" : "g-view-only" ?>"
- ref="<?= $album->id ?>">
- <span class="ui-icon ui-icon-minus g-left">
- </span>
- <span class="g-organize-album-text <?= $selected && $album->id == $selected->id ? "ui-state-focus" : "" ?>"
- ref="<?= $album->id ?>">
- <?= html::clean($album->title) ?>
- </span>
- <? $child_albums = $album->viewable()->children(null, null, array(array("type", "=", "album"))); ?>
- <? if (!empty($child_albums)): ?>
- <ul>
- <? foreach ($child_albums as $child): ?>
- <? if ($selected && $child->contains($selected)): ?>
- <?= View::factory("organize_tree.html", array("selected" => $selected, "album" => $child)); ?>
- <? else: ?>
- <li class="g-organize-album ui-icon-left <?= access::can("edit", $child) ? "" : "g-view-only" ?>"
- ref="<?= $child->id ?>">
- <span class="ui-icon ui-icon-plus g-left"></span>
- <span class="g-organize-album-text <?= $selected && $child->id == $selected->id ? "ui-state-focus" : "" ?>" ref="<?= $child->id ?>">
- <?= html::clean($child->title) ?>
- </span>
- </li>
- <? endif ?>
- <? endforeach ?>
- </ul>
- <? endif ?>
-</li>
-
diff --git a/modules/rest/controllers/rest.php b/modules/rest/controllers/rest.php
index dab54976..f8a46515 100644
--- a/modules/rest/controllers/rest.php
+++ b/modules/rest/controllers/rest.php
@@ -34,53 +34,59 @@ class Rest_Controller extends Controller {
auth::login($user);
- $key = rest::get_access_key($user->id);
- rest::reply($key->access_key);
+ rest::reply(rest::access_key());
}
public function __call($function, $args) {
- $input = Input::instance();
- $request = new stdClass();
- switch ($method = strtolower($input->server("REQUEST_METHOD"))) {
- case "get":
- $request->params = (object) $input->get();
- break;
+ try {
+ $input = Input::instance();
+ $request = new stdClass();
+
+ switch ($method = strtolower($input->server("REQUEST_METHOD"))) {
+ case "get":
+ $request->params = (object) $input->get();
+ break;
- case "post":
- $request->params = (object) $input->post();
- if (isset($_FILES["file"])) {
- $request->file = upload::save("file");
+ default:
+ $request->params = (object) $input->post();
+ if (isset($_FILES["file"])) {
+ $request->file = upload::save("file");
+ }
+ break;
}
- break;
- }
- if (isset($request->params->entity)) {
- $request->params->entity = json_decode($request->params->entity);
- }
- if (isset($request->params->members)) {
- $request->params->members = json_decode($request->params->members);
- }
+ if (isset($request->params->entity)) {
+ $request->params->entity = json_decode($request->params->entity);
+ }
+ if (isset($request->params->members)) {
+ $request->params->members = json_decode($request->params->members);
+ }
- $request->method = strtolower($input->server("HTTP_X_GALLERY_REQUEST_METHOD", $method));
- $request->access_key = $input->server("HTTP_X_GALLERY_REQUEST_KEY");
- $request->url = url::abs_current(true);
+ $request->method = strtolower($input->server("HTTP_X_GALLERY_REQUEST_METHOD", $method));
+ $request->access_key = $input->server("HTTP_X_GALLERY_REQUEST_KEY");
- rest::set_active_user($request->access_key);
+ if (empty($request->access_key) && !empty($request->params->access_key)) {
+ $request->access_key = $request->params->access_key;
+ }
- $handler_class = "{$function}_rest";
- $handler_method = $request->method;
+ $request->url = url::abs_current(true);
- if (!method_exists($handler_class, $handler_method)) {
- throw new Rest_Exception("Bad Request", 400);
- }
+ rest::set_active_user($request->access_key);
- try {
- rest::reply(call_user_func(array($handler_class, $handler_method), $request));
- } catch (ORM_Validation_Exception $e) {
- foreach ($e->validation->errors() as $key => $value) {
- $msgs[] = "$key: $value";
+ $handler_class = "{$function}_rest";
+ $handler_method = $request->method;
+
+ if (!method_exists($handler_class, $handler_method)) {
+ throw new Rest_Exception("Bad Request", 400);
}
- throw new Rest_Exception("Bad Request: " . join(", ", $msgs), 400);
+
+ $response = call_user_func(array($handler_class, $handler_method), $request);
+ rest::reply($response);
+ } catch (ORM_Validation_Exception $e) {
+ // Note: this is totally insufficient because it doesn't take into account localization. We
+ // either need to map the result values to localized strings in the application code, or every
+ // client needs its own l10n string set.
+ throw new Rest_Exception("Bad Request", 400, $e->validation->errors());
}
}
} \ No newline at end of file
diff --git a/modules/rest/helpers/rest.php b/modules/rest/helpers/rest.php
index 49999520..bcb12d58 100644
--- a/modules/rest/helpers/rest.php
+++ b/modules/rest/helpers/rest.php
@@ -18,9 +18,12 @@
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
class rest_Core {
+ const API_VERSION = "3.0";
+
static function reply($data=array()) {
Session::instance()->abort_save();
+ header("X-Gallery-API-Version: " . rest::API_VERSION);
if (Input::instance()->get("output") == "html") {
header("Content-type: text/html");
if ($data) {
@@ -39,7 +42,12 @@ class rest_Core {
static function set_active_user($access_key) {
if (empty($access_key)) {
- throw new Rest_Exception("Forbidden", 403);
+ if (module::get_var("rest", "allow_guest_access")) {
+ identity::set_active_user(identity::guest());
+ return;
+ } else {
+ throw new Rest_Exception("Forbidden", 403);
+ }
}
$key = ORM::factory("user_access_key")
@@ -58,17 +66,18 @@ class rest_Core {
identity::set_active_user($user);
}
- static function get_access_key($user_id) {
+ static function access_key() {
$key = ORM::factory("user_access_key")
- ->where("user_id", "=", $user_id)
+ ->where("user_id", "=", identity::active_user()->id)
->find();
if (!$key->loaded()) {
- $key->user_id = $user_id;
+ $key->user_id = identity::active_user()->id;
$key->access_key = md5(md5(uniqid(mt_rand(), true) . access::private_key()));
$key->save();
}
- return $key;
+
+ return $key->access_key;
}
/**
@@ -129,9 +138,9 @@ class rest_Core {
foreach (glob(MODPATH . "{$module->name}/helpers/*_rest.php") as $filename) {
$class = str_replace(".php", "", basename($filename));
if (method_exists($class, "relationships")) {
- $results = array_merge(
- $results,
- call_user_func(array($class, "relationships"), $resource_type, $resource));
+ if ($tmp = call_user_func(array($class, "relationships"), $resource_type, $resource)) {
+ $results = array_merge($results, $tmp);
+ }
}
}
}
diff --git a/modules/rest/helpers/rest_event.php b/modules/rest/helpers/rest_event.php
index e4e53ef6..f23b9a58 100644
--- a/modules/rest/helpers/rest_event.php
+++ b/modules/rest/helpers/rest_event.php
@@ -29,6 +29,13 @@ class rest_event {
->execute();
}
+
+ static function change_provider($new_provider) {
+ db::build()
+ ->delete("user_access_keys")
+ ->execute();
+ }
+
/**
* Called after a user has been added. Just add a remote access key
* on every add.
diff --git a/modules/rest/helpers/rest_installer.php b/modules/rest/helpers/rest_installer.php
index aeb9573e..c2694a29 100644
--- a/modules/rest/helpers/rest_installer.php
+++ b/modules/rest/helpers/rest_installer.php
@@ -28,7 +28,8 @@ class rest_installer {
UNIQUE KEY(`access_key`),
UNIQUE KEY(`user_id`))
DEFAULT CHARSET=utf8;");
- module::set_version("rest", 2);
+ module::set_var("rest", "allow_guest_access", false);
+ module::set_version("rest", 3);
}
static function upgrade($version) {
@@ -37,6 +38,11 @@ class rest_installer {
$db->query("RENAME TABLE {user_access_tokens} TO {user_access_keys}");
module::set_version("rest", $version = 2);
}
+
+ if ($version == 2) {
+ module::set_var("rest", "allow_guest_access", false);
+ module::set_version("rest", $version = 3);
+ }
}
static function uninstall() {
diff --git a/modules/rest/libraries/Rest_Exception.php b/modules/rest/libraries/Rest_Exception.php
index 505c2e7a..087da939 100644
--- a/modules/rest/libraries/Rest_Exception.php
+++ b/modules/rest/libraries/Rest_Exception.php
@@ -18,8 +18,11 @@
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
class Rest_Exception_Core extends Kohana_Exception {
- public function __construct($message, $code) {
+ var $response = array();
+
+ public function __construct($message, $code, $response=array()) {
parent::__construct($message, null, $code);
+ $this->response = $response;
}
public function sendHeaders() {
@@ -27,4 +30,8 @@ class Rest_Exception_Core extends Kohana_Exception {
header("HTTP/1.1 " . $this->getCode() . " " . $this->getMessage());
}
}
+
+ public function getTemplate() {
+ return "error_rest.json";
+ }
} \ No newline at end of file
diff --git a/modules/rest/module.info b/modules/rest/module.info
index 3ab7e165..5aaffc28 100644
--- a/modules/rest/module.info
+++ b/modules/rest/module.info
@@ -1,4 +1,4 @@
-name = "REST Access Module"
-description = "The RESTful implementation/interface to Gallery3"
+name = "REST API Module"
+description = "A REST-based API that allows desktop clients and other apps to interact with Gallery 3"
-version = 2
+version = 3
diff --git a/modules/rest/tests/Rest_Controller_Test.php b/modules/rest/tests/Rest_Controller_Test.php
index fe83283d..0c8a4a98 100644
--- a/modules/rest/tests/Rest_Controller_Test.php
+++ b/modules/rest/tests/Rest_Controller_Test.php
@@ -21,8 +21,7 @@ class Rest_Controller_Test extends Gallery_Unit_Test_Case {
public function setup() {
$this->_save = array($_GET, $_POST, $_SERVER);
- $key = rest::get_access_key(1); // admin user
- $_SERVER["HTTP_X_GALLERY_REQUEST_KEY"] = $key->access_key;
+ $_SERVER["HTTP_X_GALLERY_REQUEST_KEY"] = rest::access_key();
}
public function teardown() {
@@ -83,11 +82,10 @@ class Rest_Controller_Test extends Gallery_Unit_Test_Case {
$_SERVER["REQUEST_METHOD"] = "GET";
$_GET["key"] = "value";
- $key = rest::get_access_key(1); // admin user
$this->assert_array_equal_to_json(
array("params" => array("key" => "value"),
"method" => "get",
- "access_key" => $key->access_key,
+ "access_key" => rest::access_key(),
"url" => "http://./index.php/gallery_unit_test"),
test::call_and_capture(array(new Rest_Controller(), "mock")));
}
@@ -96,11 +94,10 @@ class Rest_Controller_Test extends Gallery_Unit_Test_Case {
$_SERVER["REQUEST_METHOD"] = "POST";
$_POST["key"] = "value";
- $key = rest::get_access_key(1); // admin user
$this->assert_array_equal_to_json(
array("params" => array("key" => "value"),
"method" => "post",
- "access_key" => $key->access_key,
+ "access_key" => rest::access_key(),
"url" => "http://./index.php/gallery_unit_test"),
test::call_and_capture(array(new Rest_Controller(), "mock")));
}
@@ -110,11 +107,10 @@ class Rest_Controller_Test extends Gallery_Unit_Test_Case {
$_SERVER["HTTP_X_GALLERY_REQUEST_METHOD"] = "put";
$_POST["key"] = "value";
- $key = rest::get_access_key(1); // admin user
$this->assert_array_equal_to_json(
array("params" => array("key" => "value"),
"method" => "put",
- "access_key" => $key->access_key,
+ "access_key" => rest::access_key(),
"url" => "http://./index.php/gallery_unit_test"),
test::call_and_capture(array(new Rest_Controller(), "mock")));
}
@@ -124,11 +120,10 @@ class Rest_Controller_Test extends Gallery_Unit_Test_Case {
$_SERVER["HTTP_X_GALLERY_REQUEST_METHOD"] = "delete";
$_POST["key"] = "value";
- $key = rest::get_access_key(1); // admin user
$this->assert_array_equal_to_json(
array("params" => array("key" => "value"),
"method" => "delete",
- "access_key" => $key->access_key,
+ "access_key" => rest::access_key(),
"url" => "http://./index.php/gallery_unit_test"),
test::call_and_capture(array(new Rest_Controller(), "mock")));
}
diff --git a/modules/rest/views/error_rest.json.php b/modules/rest/views/error_rest.json.php
new file mode 100644
index 00000000..179ce7f9
--- /dev/null
+++ b/modules/rest/views/error_rest.json.php
@@ -0,0 +1,2 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<?= json_encode($e->response); \ No newline at end of file
diff --git a/modules/rss/views/feed.mrss.php b/modules/rss/views/feed.mrss.php
index 0fd8095d..3f0010bb 100644
--- a/modules/rss/views/feed.mrss.php
+++ b/modules/rss/views/feed.mrss.php
@@ -20,57 +20,57 @@
<? endif ?>
<pubDate><?= $pub_date ?></pubDate>
<lastBuildDate><?= $pub_date ?></lastBuildDate>
- <? foreach ($feed->children as $child): ?>
+ <? foreach ($feed->items as $item): ?>
<item>
- <title><?= html::purify($child->title) ?></title>
- <link><?= url::abs_site("{$child->type}s/{$child->id}") ?></link>
- <guid isPermaLink="true"><?= url::abs_site("{$child->type}s/{$child->id}") ?></guid>
- <pubDate><?= date("D, d M Y H:i:s T", $child->created); ?></pubDate>
- <description><?= html::purify($child->description) ?></description>
+ <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>
+ <description><?= html::purify($item->description) ?></description>
<content:encoded>
<![CDATA[
- <span><?= html::purify($child->description) ?></span>
+ <span><?= html::purify($item->description) ?></span>
<p>
- <? if ($child->type == "photo"): ?>
- <img alt="" src="<?= $child->resize_url(true) ?>"
- title="<?= html::purify($child->title)->for_html_attr() ?>"
- height="<?= $child->resize_height ?>" width="<?= $child->resize_width ?>" /><br />
+ <? if ($item->type == "photo"): ?>
+ <img alt="" src="<?= $item->resize_url(true) ?>"
+ title="<?= html::purify($item->title)->for_html_attr() ?>"
+ height="<?= $item->resize_height ?>" width="<?= $item->resize_width ?>" /><br />
<? else: ?>
- <a href="<?= url::abs_site("{$child->type}s/{$child->id}") ?>">
- <img alt="" src="<?= $child->thumb_url(true) ?>"
- title="<?= html::purify($child->title)->for_html_attr() ?>"
- height="<?= $child->thumb_height ?>" width="<?= $child->thumb_width ?>" /></a><br />
+ <a href="<?= url::abs_site("{$item->type}s/{$item->id}") ?>">
+ <img alt="" src="<?= $item->thumb_url(true) ?>"
+ title="<?= html::purify($item->title)->for_html_attr() ?>"
+ height="<?= $item->thumb_height ?>" width="<?= $item->thumb_width ?>" /></a><br />
<? endif ?>
- <?= html::purify($child->description) ?>
+ <?= html::purify($item->description) ?>
</p>
]]>
</content:encoded>
- <media:thumbnail url="<?= $child->thumb_url(true) ?>"
- height="<?= $child->thumb_height ?>"
- width="<?= $child->thumb_width ?>"
+ <media:thumbnail url="<?= $item->thumb_url(true) ?>"
+ height="<?= $item->thumb_height ?>"
+ width="<?= $item->thumb_width ?>"
/>
- <? $view_full = access::can("view_full", $child); ?>
- <? if ($child->type == "photo" && $view_full): ?>
+ <? $view_full = access::can("view_full", $item); ?>
+ <? if ($item->type == "photo" && $view_full): ?>
<media:group>
<? endif ?>
- <? if ($child->type == "photo"): ?>
- <media:content url="<?= $child->resize_url(true) ?>"
- fileSize="<?= @filesize($child->resize_path()) ?>"
- type="<?= $child->mime_type ?>"
- height="<?= $child->resize_height ?>"
- width="<?= $child->resize_width ?>"
+ <? if ($item->type == "photo"): ?>
+ <media:content url="<?= $item->resize_url(true) ?>"
+ fileSize="<?= @filesize($item->resize_path()) ?>"
+ type="<?= $item->mime_type ?>"
+ height="<?= $item->resize_height ?>"
+ width="<?= $item->resize_width ?>"
/>
<? endif ?>
<? if ($view_full): ?>
- <media:content url="<?= $child->file_url(true) ?>"
- fileSize="<?= @filesize($child->file_path()) ?>"
- type="<?= $child->mime_type ?>"
- height="<?= $child->height ?>"
- width="<?= $child->width ?>"
+ <media:content url="<?= $item->file_url(true) ?>"
+ fileSize="<?= @filesize($item->file_path()) ?>"
+ type="<?= $item->mime_type ?>"
+ height="<?= $item->height ?>"
+ width="<?= $item->width ?>"
isDefault="true"
/>
<? endif ?>
- <? if ($child->type == "photo" && $view_full): ?>
+ <? if ($item->type == "photo" && $view_full): ?>
</media:group>
<? endif ?>
</item>
diff --git a/modules/search/helpers/search.php b/modules/search/helpers/search.php
index 22f83218..24c4ed2b 100644
--- a/modules/search/helpers/search.php
+++ b/modules/search/helpers/search.php
@@ -42,7 +42,7 @@ class search_Core {
$data = $db->query($query);
$count = $db->query("SELECT FOUND_ROWS() as c")->current()->c;
- return array($count, new ORM_Iterator(ORM::factory("item"), $db->query($query)));
+ return array($count, new ORM_Iterator(ORM::factory("item"), $data));
}
/**
diff --git a/modules/slideshow/helpers/slideshow_theme.php b/modules/slideshow/helpers/slideshow_theme.php
index c23326cf..3203b7bc 100644
--- a/modules/slideshow/helpers/slideshow_theme.php
+++ b/modules/slideshow/helpers/slideshow_theme.php
@@ -19,7 +19,7 @@
*/
class slideshow_theme_Core {
static function page_bottom($theme) {
- $proto = (empty($_SERVER["HTTPS"]) || $_SERVER["HTTPS"] === "off") ? "http" : "https";
+ $proto = request::protocol();
return "<script src=\"$proto://apps.cooliris.com/slideshow/go.js\" " .
"type=\"text/javascript\"></script>";
}
diff --git a/modules/tag/controllers/tags.php b/modules/tag/controllers/tags.php
index f9a56ccf..f3d456d3 100644
--- a/modules/tag/controllers/tags.php
+++ b/modules/tag/controllers/tags.php
@@ -41,7 +41,7 @@ class Tags_Controller extends Controller {
$template->set_global("children", $tag->items($page_size, $offset));
$template->set_global("children_count", $children_count);
$template->content = new View("dynamic.html");
- $template->content->title = $tag->name;
+ $template->content->title = t("Tag: %tag_name", array("tag_name" => $tag->name));
print $template;
}
diff --git a/modules/tag/helpers/tag_event.php b/modules/tag/helpers/tag_event.php
index a790b930..7fe9fba3 100644
--- a/modules/tag/helpers/tag_event.php
+++ b/modules/tag/helpers/tag_event.php
@@ -36,7 +36,8 @@ class tag_event_Core {
$tag = str_replace("\0", "", $tag);
foreach (explode(",", $tag) as $word) {
$word = trim($word);
- if (function_exists("mb_detect_encoding") && mb_detect_encoding($word) != "UTF-8") {
+ if (function_exists("mb_detect_encoding") &&
+ mb_detect_encoding($word, "ISO-8859-1, UTF-8") != "UTF-8") {
$word = utf8_encode($word);
}
$tags[$word] = 1;
@@ -67,8 +68,8 @@ class tag_event_Core {
static function item_edit_form($item, $form) {
$url = url::site("tags/autocomplete");
$form->script("")
- ->text("$('form input[id=tags]').ready(function() {
- $('form input[id=tags]').autocomplete(
+ ->text("$('form input[name=tags]').ready(function() {
+ $('form input[name=tags]').autocomplete(
'$url', {max: 30, multiple: true, multipleSeparator: ',', cacheLength: 1});
});");
diff --git a/modules/tag/helpers/tag_installer.php b/modules/tag/helpers/tag_installer.php
index 6ccaf835..df6f0c65 100644
--- a/modules/tag/helpers/tag_installer.php
+++ b/modules/tag/helpers/tag_installer.php
@@ -22,7 +22,7 @@ class tag_installer {
$db = Database::instance();
$db->query("CREATE TABLE IF NOT EXISTS {tags} (
`id` int(9) NOT NULL auto_increment,
- `name` varchar(64) NOT NULL,
+ `name` varchar(128) NOT NULL,
`count` int(10) unsigned NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY(`name`))
@@ -36,7 +36,15 @@ class tag_installer {
KEY(`tag_id`, `id`),
KEY(`item_id`, `id`))
DEFAULT CHARSET=utf8;");
- module::set_version("tag", 1);
+ module::set_version("tag", 2);
+ }
+
+ static function upgrade($version) {
+ $db = Database::instance();
+ if ($version == 1) {
+ $db->query("ALTER TABLE {tags} MODIFY COLUMN `name` VARCHAR(128)");
+ module::set_version("tag", $version = 2);
+ }
}
static function uninstall() {
diff --git a/modules/tag/helpers/tag_rss.php b/modules/tag/helpers/tag_rss.php
index 7d52814b..ea3865be 100644
--- a/modules/tag/helpers/tag_rss.php
+++ b/modules/tag/helpers/tag_rss.php
@@ -36,7 +36,7 @@ class tag_rss_Core {
}
$feed = new stdClass();
- $feed->children = $tag->items($limit, $offset, "photo");
+ $feed->items = $tag->items($limit, $offset, "photo");
$feed->max_pages = ceil($tag->count / $limit);
$feed->title = $tag->name;
$feed->description = t("Photos related to %tag_name", array("tag_name" => $tag->name));
diff --git a/modules/tag/helpers/tags_rest.php b/modules/tag/helpers/tags_rest.php
index 434e774a..4f40e7f4 100644
--- a/modules/tag/helpers/tags_rest.php
+++ b/modules/tag/helpers/tags_rest.php
@@ -18,9 +18,26 @@
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
class tags_rest_Core {
+ /**
+ * Possible request parameters:
+ * start=#
+ * start at the Nth comment (zero based)
+ *
+ * num=#
+ * return up to N comments (max 100)
+ */
static function get($request) {
$tags = array();
- foreach (ORM::factory("tag")->find_all() as $tag) {
+
+ $num = 10;
+ $start = 0;
+ if (isset($request->params)) {
+ $p = $request->params;
+ $num = isset($p->num) ? min((int)$p->num, 100) : 10;
+ $start = isset($p->start) ? (int)$p->start : 0;
+ }
+
+ foreach (ORM::factory("tag")->find_all($num, $start) as $tag) {
$tags[] = rest::url("tag", $tag);
}
return array("url" => rest::url("tags"),
diff --git a/modules/tag/module.info b/modules/tag/module.info
index e505dd81..8851d119 100644
--- a/modules/tag/module.info
+++ b/modules/tag/module.info
@@ -1,3 +1,3 @@
name = "Tags"
description = "Allows users to tag photos and albums"
-version = 1
+version = 2
diff --git a/modules/tag/tests/Tags_Rest_Helper_Test.php b/modules/tag/tests/Tags_Rest_Helper_Test.php
index 99332c7c..1b909e50 100644
--- a/modules/tag/tests/Tags_Rest_Helper_Test.php
+++ b/modules/tag/tests/Tags_Rest_Helper_Test.php
@@ -45,7 +45,7 @@ class Tags_Rest_Helper_Test extends Gallery_Unit_Test_Case {
}
public function post_test() {
- identity::set_active_user(identity::guest());
+ identity::set_active_user(identity::admin_user());
$request = new stdClass();
$request->params = new stdClass();
diff --git a/modules/user/views/admin_users.html.php b/modules/user/views/admin_users.html.php
index 270a7207..b2526bd8 100644
--- a/modules/user/views/admin_users.html.php
+++ b/modules/user/views/admin_users.html.php
@@ -120,7 +120,7 @@
<div class="g-block-content">
<ul>
<? foreach ($groups as $i => $group): ?>
- <li id="g-group-<?= $group->id ?>" class="g-group g-left <?= ($group->special ? "g-default-group" : "") ?>" />
+ <li id="g-group-<?= $group->id ?>" class="g-group g-left <?= ($group->special ? "g-default-group" : "") ?>">
<? $v = new View("admin_users_group.html"); $v->group = $group; ?>
<?= $v ?>
</li>
diff --git a/modules/watermark/controllers/admin_watermarks.php b/modules/watermark/controllers/admin_watermarks.php
index d26919d5..18b463ca 100644
--- a/modules/watermark/controllers/admin_watermarks.php
+++ b/modules/watermark/controllers/admin_watermarks.php
@@ -124,7 +124,7 @@ class Admin_Watermarks_Controller extends Admin_Controller {
array("result" => "success",
"location" => url::site("admin/watermarks")));
} else {
- print json_encode(array("result" => "error", "form" => (string) $form));
+ print json_encode(array("result" => "error", "form" => rawurlencode((string) $form)));
}
}
diff --git a/robots.txt b/robots.txt
index bc7b5ac9..000aac95 100644
--- a/robots.txt
+++ b/robots.txt
@@ -11,3 +11,4 @@ Disallow: /var/resizes/
Disallow: /var/thumbs/
Disallow: /var/tmp/
Disallow: /var/uploads/
+Disallow: /digibug/print_photo/
diff --git a/themes/admin_wind/css/screen.css b/themes/admin_wind/css/screen.css
index ac47a3db..937c4d15 100644
--- a/themes/admin_wind/css/screen.css
+++ b/themes/admin_wind/css/screen.css
@@ -399,6 +399,26 @@ th {
background-color: #FFF;
}
+/* Theme options ~~~~~~~~~~~~~~~~~~~~~~~~ */
+#g-theme-options-form {
+ border: 1px solid #a6c9e2;
+}
+#g-theme-options-form-tabs {
+ border: none !important;
+}
+#g-theme-options-form fieldset {
+ border: none;
+}
+
+.ui-tabs .ui-tabs-nav li a {
+ padding: 0 1em;
+}
+
+.ui-tabs .ui-tabs-nav li a.g-error {
+ background: none no-repeat scroll 0 0 transparent;
+ color: #FF0000 !important;
+}
+
/** *******************************************************************
* 5) Navigation and menus
*********************************************************************/
@@ -483,3 +503,8 @@ th {
padding-left: 0;
padding-right: 1.2em;
}
+
+.rtl .g-selected img,
+.rtl .g-available .g-block img {
+ margin: 0 0 1em 1em;
+}
diff --git a/lib/themeroller/images/ui-bg_flat_0_aaaaaa_40x100.png b/themes/admin_wind/css/themeroller/images/ui-bg_flat_0_aaaaaa_40x100.png
index 5b5dab2a..5b5dab2a 100644
--- a/lib/themeroller/images/ui-bg_flat_0_aaaaaa_40x100.png
+++ b/themes/admin_wind/css/themeroller/images/ui-bg_flat_0_aaaaaa_40x100.png
Binary files differ
diff --git a/lib/themeroller/images/ui-bg_flat_55_fbec88_40x100.png b/themes/admin_wind/css/themeroller/images/ui-bg_flat_55_fbec88_40x100.png
index 47acaadd..47acaadd 100644
--- a/lib/themeroller/images/ui-bg_flat_55_fbec88_40x100.png
+++ b/themes/admin_wind/css/themeroller/images/ui-bg_flat_55_fbec88_40x100.png
Binary files differ
diff --git a/lib/themeroller/images/ui-bg_glass_75_d0e5f5_1x400.png b/themes/admin_wind/css/themeroller/images/ui-bg_glass_75_d0e5f5_1x400.png
index 9fb564f8..9fb564f8 100644
--- a/lib/themeroller/images/ui-bg_glass_75_d0e5f5_1x400.png
+++ b/themes/admin_wind/css/themeroller/images/ui-bg_glass_75_d0e5f5_1x400.png
Binary files differ
diff --git a/lib/themeroller/images/ui-bg_glass_85_dfeffc_1x400.png b/themes/admin_wind/css/themeroller/images/ui-bg_glass_85_dfeffc_1x400.png
index 01495152..01495152 100644
--- a/lib/themeroller/images/ui-bg_glass_85_dfeffc_1x400.png
+++ b/themes/admin_wind/css/themeroller/images/ui-bg_glass_85_dfeffc_1x400.png
Binary files differ
diff --git a/lib/themeroller/images/ui-bg_glass_95_fef1ec_1x400.png b/themes/admin_wind/css/themeroller/images/ui-bg_glass_95_fef1ec_1x400.png
index 4443fdc1..4443fdc1 100644
--- a/lib/themeroller/images/ui-bg_glass_95_fef1ec_1x400.png
+++ b/themes/admin_wind/css/themeroller/images/ui-bg_glass_95_fef1ec_1x400.png
Binary files differ
diff --git a/lib/themeroller/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png b/themes/admin_wind/css/themeroller/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png
index 0cdbda36..0cdbda36 100644
--- a/lib/themeroller/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png
+++ b/themes/admin_wind/css/themeroller/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png
Binary files differ
diff --git a/lib/themeroller/images/ui-bg_inset-hard_100_f5f8f9_1x100.png b/themes/admin_wind/css/themeroller/images/ui-bg_inset-hard_100_f5f8f9_1x100.png
index 4f3faf8a..4f3faf8a 100644
--- a/lib/themeroller/images/ui-bg_inset-hard_100_f5f8f9_1x100.png
+++ b/themes/admin_wind/css/themeroller/images/ui-bg_inset-hard_100_f5f8f9_1x100.png
Binary files differ
diff --git a/lib/themeroller/images/ui-bg_inset-hard_100_fcfdfd_1x100.png b/themes/admin_wind/css/themeroller/images/ui-bg_inset-hard_100_fcfdfd_1x100.png
index 38c38335..38c38335 100644
--- a/lib/themeroller/images/ui-bg_inset-hard_100_fcfdfd_1x100.png
+++ b/themes/admin_wind/css/themeroller/images/ui-bg_inset-hard_100_fcfdfd_1x100.png
Binary files differ
diff --git a/lib/themeroller/images/ui-icons_217bc0_256x240.png b/themes/admin_wind/css/themeroller/images/ui-icons_217bc0_256x240.png
index 7719d487..7719d487 100644
--- a/lib/themeroller/images/ui-icons_217bc0_256x240.png
+++ b/themes/admin_wind/css/themeroller/images/ui-icons_217bc0_256x240.png
Binary files differ
diff --git a/lib/themeroller/images/ui-icons_2e83ff_256x240.png b/themes/admin_wind/css/themeroller/images/ui-icons_2e83ff_256x240.png
index d9897d25..d9897d25 100644
--- a/lib/themeroller/images/ui-icons_2e83ff_256x240.png
+++ b/themes/admin_wind/css/themeroller/images/ui-icons_2e83ff_256x240.png
Binary files differ
diff --git a/lib/themeroller/images/ui-icons_469bdd_256x240.png b/themes/admin_wind/css/themeroller/images/ui-icons_469bdd_256x240.png
index d8161854..d8161854 100644
--- a/lib/themeroller/images/ui-icons_469bdd_256x240.png
+++ b/themes/admin_wind/css/themeroller/images/ui-icons_469bdd_256x240.png
Binary files differ
diff --git a/lib/themeroller/images/ui-icons_6da8d5_256x240.png b/themes/admin_wind/css/themeroller/images/ui-icons_6da8d5_256x240.png
index b3c7d662..b3c7d662 100644
--- a/lib/themeroller/images/ui-icons_6da8d5_256x240.png
+++ b/themes/admin_wind/css/themeroller/images/ui-icons_6da8d5_256x240.png
Binary files differ
diff --git a/lib/themeroller/images/ui-icons_cd0a0a_256x240.png b/themes/admin_wind/css/themeroller/images/ui-icons_cd0a0a_256x240.png
index 2db88b79..2db88b79 100644
--- a/lib/themeroller/images/ui-icons_cd0a0a_256x240.png
+++ b/themes/admin_wind/css/themeroller/images/ui-icons_cd0a0a_256x240.png
Binary files differ
diff --git a/lib/themeroller/images/ui-icons_d8e7f3_256x240.png b/themes/admin_wind/css/themeroller/images/ui-icons_d8e7f3_256x240.png
index 2c8aac46..2c8aac46 100644
--- a/lib/themeroller/images/ui-icons_d8e7f3_256x240.png
+++ b/themes/admin_wind/css/themeroller/images/ui-icons_d8e7f3_256x240.png
Binary files differ
diff --git a/lib/themeroller/images/ui-icons_f9bd01_256x240.png b/themes/admin_wind/css/themeroller/images/ui-icons_f9bd01_256x240.png
index e81603f5..e81603f5 100644
--- a/lib/themeroller/images/ui-icons_f9bd01_256x240.png
+++ b/themes/admin_wind/css/themeroller/images/ui-icons_f9bd01_256x240.png
Binary files differ
diff --git a/lib/themeroller/ui.base.css b/themes/admin_wind/css/themeroller/ui.base.css
index 1a1810c8..1a1810c8 100644
--- a/lib/themeroller/ui.base.css
+++ b/themes/admin_wind/css/themeroller/ui.base.css
diff --git a/lib/themeroller/ui.core.css b/themes/admin_wind/css/themeroller/ui.core.css
index d832ad7d..d832ad7d 100644
--- a/lib/themeroller/ui.core.css
+++ b/themes/admin_wind/css/themeroller/ui.core.css
diff --git a/lib/themeroller/ui.datepicker.css b/themes/admin_wind/css/themeroller/ui.datepicker.css
index 92986c9e..92986c9e 100644
--- a/lib/themeroller/ui.datepicker.css
+++ b/themes/admin_wind/css/themeroller/ui.datepicker.css
diff --git a/lib/themeroller/ui.dialog.css b/themes/admin_wind/css/themeroller/ui.dialog.css
index f10f4090..f10f4090 100644
--- a/lib/themeroller/ui.dialog.css
+++ b/themes/admin_wind/css/themeroller/ui.dialog.css
diff --git a/lib/themeroller/ui.progressbar.css b/themes/admin_wind/css/themeroller/ui.progressbar.css
index bc0939ec..bc0939ec 100644
--- a/lib/themeroller/ui.progressbar.css
+++ b/themes/admin_wind/css/themeroller/ui.progressbar.css
diff --git a/lib/themeroller/ui.resizable.css b/themes/admin_wind/css/themeroller/ui.resizable.css
index 44efeb2e..44efeb2e 100644
--- a/lib/themeroller/ui.resizable.css
+++ b/themes/admin_wind/css/themeroller/ui.resizable.css
diff --git a/lib/themeroller/ui.tabs.css b/themes/admin_wind/css/themeroller/ui.tabs.css
index 70ed3ef4..70ed3ef4 100644
--- a/lib/themeroller/ui.tabs.css
+++ b/themes/admin_wind/css/themeroller/ui.tabs.css
diff --git a/lib/themeroller/ui.theme.css b/themes/admin_wind/css/themeroller/ui.theme.css
index 21ece290..477252e5 100644
--- a/lib/themeroller/ui.theme.css
+++ b/themes/admin_wind/css/themeroller/ui.theme.css
@@ -228,15 +228,15 @@
----------------------------------*/
/* Corner radius */
-.ui-corner-tl { -moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; }
-.ui-corner-tr { -moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; }
-.ui-corner-bl { -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; }
-.ui-corner-br { -moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; }
-.ui-corner-top { -moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; -moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; }
-.ui-corner-bottom { -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; }
-.ui-corner-right { -moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; -moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; }
-.ui-corner-left { -moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; }
-.ui-corner-all { -moz-border-radius: 5px; -webkit-border-radius: 5px; }
+.ui-corner-tl { -moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; border-top-left-radius: 5px; }
+.ui-corner-tr { -moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; border-top-right-radius: 5px; }
+.ui-corner-bl { -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; border-bottom-left-radius: 5px; }
+.ui-corner-br { -moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; border-bottom-right-radius: 5px; }
+.ui-corner-top { -moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; border-top-left-radius: 5px; -moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; border-top-right-radius: 5px; }
+.ui-corner-bottom { -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; border-bottom-left-radius: 5px; -moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; border-bottom-right-radius: 5px; }
+.ui-corner-right { -moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; border-top-right-radius: 5px; -moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; border-bottom-right-radius: 5px; }
+.ui-corner-left { -moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; border-top-left-radius: 5px; -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; border-bottom-left-radius: 5px; }
+.ui-corner-all { -moz-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; }
/* Overlays */
.ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); }
diff --git a/themes/admin_wind/js/ui.init.js b/themes/admin_wind/js/ui.init.js
index e0210ce5..4ed912f8 100644
--- a/themes/admin_wind/js/ui.init.js
+++ b/themes/admin_wind/js/ui.init.js
@@ -4,7 +4,7 @@
*/
$(document).ready(function(){
-
+
// Initialize Superfish menus
$("#g-site-admin-menu .g-menu").hide().addClass("sf-menu");
$("#g-site-admin-menu .g-menu").superfish({
@@ -54,7 +54,9 @@ $(document).ready(function(){
$(".g-available .g-block").addClass("ui-corner-all");
$(".g-unavailable").addClass("ui-corner-all");
+ // Remove titles for menu options since we're displaying that text anyway
+ $(".sf-menu a, .sf-menu li").removeAttr("title");
+
// Initialize button hover effect
$.fn.gallery_hover_init();
-
});
diff --git a/themes/admin_wind/views/admin.html.php b/themes/admin_wind/views/admin.html.php
index 2f64c847..f9ef18c7 100644
--- a/themes/admin_wind/views/admin.html.php
+++ b/themes/admin_wind/views/admin.html.php
@@ -6,7 +6,7 @@
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<title>
<? if ($page_title): ?>
- <?= $page_title ?>
+ <?= t("Gallery Admin: %page_title", array("page_title" => $page_title)) ?>
<? else: ?>
<?= t("Admin dashboard") ?>
<? endif ?>
@@ -53,9 +53,11 @@
&larr; <?= t("back to the ...") ?>
</a>
<?= $theme->user_menu() ?>
- <div id="g-site-admin-menu" class="ui-helper-clearfix">
+ <!-- hide the menu until after the page has loaded, to minimize menu flicker -->
+ <div id="g-site-admin-menu" class="ui-helper-clearfix" style="visibility: hidden">
<?= $theme->admin_menu() ?>
</div>
+ <script type="text/javascript"> $(document).ready(function() { $("#g-site-admin-menu").css("visibility", "visible"); }) </script>
<?= $theme->admin_header_bottom() ?>
</div>
<div id="bd">
diff --git a/themes/wind/css/screen.css b/themes/wind/css/screen.css
index f8e26073..44582a92 100644
--- a/themes/wind/css/screen.css
+++ b/themes/wind/css/screen.css
@@ -302,7 +302,7 @@ td {
}
#g-item img.g-resize,
-#g-item a.g-movie object {
+#g-item a.g-movie {
display: block;
margin: 0 auto;
}
@@ -457,3 +457,12 @@ td {
background-image: url('../images/ico-view-slideshow-rtl.png');
}
+.rtl #g-sidebar .g-block-content {
+ padding-right: 1em;
+ padding-left: 0;
+}
+
+.rtl #g-footer #g-credits li {
+ padding-left: 1.2em !important;
+ padding-right: 0;
+} \ No newline at end of file
diff --git a/themes/wind/css/themeroller/images/ui-bg_flat_0_aaaaaa_40x100.png b/themes/wind/css/themeroller/images/ui-bg_flat_0_aaaaaa_40x100.png
new file mode 100644
index 00000000..5b5dab2a
--- /dev/null
+++ b/themes/wind/css/themeroller/images/ui-bg_flat_0_aaaaaa_40x100.png
Binary files differ
diff --git a/themes/wind/css/themeroller/images/ui-bg_flat_55_fbec88_40x100.png b/themes/wind/css/themeroller/images/ui-bg_flat_55_fbec88_40x100.png
new file mode 100644
index 00000000..47acaadd
--- /dev/null
+++ b/themes/wind/css/themeroller/images/ui-bg_flat_55_fbec88_40x100.png
Binary files differ
diff --git a/themes/wind/css/themeroller/images/ui-bg_glass_75_d0e5f5_1x400.png b/themes/wind/css/themeroller/images/ui-bg_glass_75_d0e5f5_1x400.png
new file mode 100644
index 00000000..9fb564f8
--- /dev/null
+++ b/themes/wind/css/themeroller/images/ui-bg_glass_75_d0e5f5_1x400.png
Binary files differ
diff --git a/themes/wind/css/themeroller/images/ui-bg_glass_85_dfeffc_1x400.png b/themes/wind/css/themeroller/images/ui-bg_glass_85_dfeffc_1x400.png
new file mode 100644
index 00000000..01495152
--- /dev/null
+++ b/themes/wind/css/themeroller/images/ui-bg_glass_85_dfeffc_1x400.png
Binary files differ
diff --git a/themes/wind/css/themeroller/images/ui-bg_glass_95_fef1ec_1x400.png b/themes/wind/css/themeroller/images/ui-bg_glass_95_fef1ec_1x400.png
new file mode 100644
index 00000000..4443fdc1
--- /dev/null
+++ b/themes/wind/css/themeroller/images/ui-bg_glass_95_fef1ec_1x400.png
Binary files differ
diff --git a/themes/wind/css/themeroller/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png b/themes/wind/css/themeroller/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png
new file mode 100644
index 00000000..0cdbda36
--- /dev/null
+++ b/themes/wind/css/themeroller/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png
Binary files differ
diff --git a/themes/wind/css/themeroller/images/ui-bg_inset-hard_100_f5f8f9_1x100.png b/themes/wind/css/themeroller/images/ui-bg_inset-hard_100_f5f8f9_1x100.png
new file mode 100644
index 00000000..4f3faf8a
--- /dev/null
+++ b/themes/wind/css/themeroller/images/ui-bg_inset-hard_100_f5f8f9_1x100.png
Binary files differ
diff --git a/themes/wind/css/themeroller/images/ui-bg_inset-hard_100_fcfdfd_1x100.png b/themes/wind/css/themeroller/images/ui-bg_inset-hard_100_fcfdfd_1x100.png
new file mode 100644
index 00000000..38c38335
--- /dev/null
+++ b/themes/wind/css/themeroller/images/ui-bg_inset-hard_100_fcfdfd_1x100.png
Binary files differ
diff --git a/themes/wind/css/themeroller/images/ui-icons_217bc0_256x240.png b/themes/wind/css/themeroller/images/ui-icons_217bc0_256x240.png
new file mode 100644
index 00000000..7719d487
--- /dev/null
+++ b/themes/wind/css/themeroller/images/ui-icons_217bc0_256x240.png
Binary files differ
diff --git a/themes/wind/css/themeroller/images/ui-icons_2e83ff_256x240.png b/themes/wind/css/themeroller/images/ui-icons_2e83ff_256x240.png
new file mode 100644
index 00000000..d9897d25
--- /dev/null
+++ b/themes/wind/css/themeroller/images/ui-icons_2e83ff_256x240.png
Binary files differ
diff --git a/themes/wind/css/themeroller/images/ui-icons_469bdd_256x240.png b/themes/wind/css/themeroller/images/ui-icons_469bdd_256x240.png
new file mode 100644
index 00000000..d8161854
--- /dev/null
+++ b/themes/wind/css/themeroller/images/ui-icons_469bdd_256x240.png
Binary files differ
diff --git a/themes/wind/css/themeroller/images/ui-icons_6da8d5_256x240.png b/themes/wind/css/themeroller/images/ui-icons_6da8d5_256x240.png
new file mode 100644
index 00000000..b3c7d662
--- /dev/null
+++ b/themes/wind/css/themeroller/images/ui-icons_6da8d5_256x240.png
Binary files differ
diff --git a/themes/wind/css/themeroller/images/ui-icons_cd0a0a_256x240.png b/themes/wind/css/themeroller/images/ui-icons_cd0a0a_256x240.png
new file mode 100644
index 00000000..2db88b79
--- /dev/null
+++ b/themes/wind/css/themeroller/images/ui-icons_cd0a0a_256x240.png
Binary files differ
diff --git a/themes/wind/css/themeroller/images/ui-icons_d8e7f3_256x240.png b/themes/wind/css/themeroller/images/ui-icons_d8e7f3_256x240.png
new file mode 100644
index 00000000..2c8aac46
--- /dev/null
+++ b/themes/wind/css/themeroller/images/ui-icons_d8e7f3_256x240.png
Binary files differ
diff --git a/themes/wind/css/themeroller/images/ui-icons_f9bd01_256x240.png b/themes/wind/css/themeroller/images/ui-icons_f9bd01_256x240.png
new file mode 100644
index 00000000..e81603f5
--- /dev/null
+++ b/themes/wind/css/themeroller/images/ui-icons_f9bd01_256x240.png
Binary files differ
diff --git a/themes/wind/css/themeroller/ui.base.css b/themes/wind/css/themeroller/ui.base.css
new file mode 100644
index 00000000..1a1810c8
--- /dev/null
+++ b/themes/wind/css/themeroller/ui.base.css
@@ -0,0 +1,7 @@
+@import "ui.core.css";
+@import "ui.theme.css";
+@import "ui.datepicker.css";
+@import "ui.dialog.css";
+@import "ui.progressbar.css";
+@import "ui.resizable.css";
+@import "ui.tabs.css";
diff --git a/themes/wind/css/themeroller/ui.core.css b/themes/wind/css/themeroller/ui.core.css
new file mode 100644
index 00000000..d832ad7d
--- /dev/null
+++ b/themes/wind/css/themeroller/ui.core.css
@@ -0,0 +1,37 @@
+/*
+* jQuery UI CSS Framework
+* Copyright (c) 2009 AUTHORS.txt (http://ui.jquery.com/about)
+* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
+*/
+
+/* Layout helpers
+----------------------------------*/
+.ui-helper-hidden { display: none; }
+.ui-helper-hidden-accessible { position: absolute; left: -99999999px; }
+.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
+.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
+.ui-helper-clearfix { display: inline-block; }
+/* required comment for clearfix to work in Opera \*/
+* html .ui-helper-clearfix { height:1%; }
+.ui-helper-clearfix { display:block; }
+/* end clearfix */
+.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
+
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-disabled { cursor: default !important; }
+
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Overlays */
+.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } \ No newline at end of file
diff --git a/themes/wind/css/themeroller/ui.datepicker.css b/themes/wind/css/themeroller/ui.datepicker.css
new file mode 100644
index 00000000..92986c9e
--- /dev/null
+++ b/themes/wind/css/themeroller/ui.datepicker.css
@@ -0,0 +1,62 @@
+/* Datepicker
+----------------------------------*/
+.ui-datepicker { width: 17em; padding: .2em .2em 0; }
+.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
+.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
+.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
+.ui-datepicker .ui-datepicker-prev { left:2px; }
+.ui-datepicker .ui-datepicker-next { right:2px; }
+.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
+.ui-datepicker .ui-datepicker-next-hover { right:1px; }
+.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; }
+.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
+.ui-datepicker .ui-datepicker-title select { float:left; font-size:1em; margin:1px 0; }
+.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
+.ui-datepicker select.ui-datepicker-month,
+.ui-datepicker select.ui-datepicker-year { width: 49%;}
+.ui-datepicker .ui-datepicker-title select.ui-datepicker-year { float: right; }
+.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
+.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
+.ui-datepicker td { border: 0; padding: 1px; }
+.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
+.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
+.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
+.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
+
+/* with multiple calendars */
+.ui-datepicker.ui-datepicker-multi { width:auto; }
+.ui-datepicker-multi .ui-datepicker-group { float:left; }
+.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
+.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
+.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
+.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
+.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
+.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
+.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
+.ui-datepicker-row-break { clear:left; width:100%; }
+
+/* RTL support */
+.ui-datepicker-rtl { direction: rtl; }
+.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
+.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
+.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
+.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
+.ui-datepicker-rtl .ui-datepicker-group { float:right; }
+.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
+.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
+
+/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
+.ui-datepicker-cover {
+ display: none; /*sorry for IE5*/
+ display/**/: block; /*sorry for IE5*/
+ position: absolute; /*must have*/
+ z-index: -1; /*must have*/
+ filter: mask(); /*must have*/
+ top: -4px; /*must have*/
+ left: -4px; /*must have*/
+ width: 200px; /*must have*/
+ height: 200px; /*must have*/
+} \ No newline at end of file
diff --git a/themes/wind/css/themeroller/ui.dialog.css b/themes/wind/css/themeroller/ui.dialog.css
new file mode 100644
index 00000000..f10f4090
--- /dev/null
+++ b/themes/wind/css/themeroller/ui.dialog.css
@@ -0,0 +1,13 @@
+/* Dialog
+----------------------------------*/
+.ui-dialog { position: relative; padding: .2em; width: 300px; }
+.ui-dialog .ui-dialog-titlebar { padding: .5em .3em .3em 1em; position: relative; }
+.ui-dialog .ui-dialog-title { float: left; margin: .1em 0 .2em; }
+.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
+.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
+.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
+.ui-dialog .ui-dialog-content { border: 0; padding: .5em 1em; background: none; overflow: auto; }
+.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
+.ui-dialog .ui-dialog-buttonpane button { float: right; margin: .5em .4em .5em 0; cursor: pointer; padding: .2em .6em .3em .6em; line-height: 1.4em; width:auto; overflow:visible; }
+.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
+.ui-draggable .ui-dialog-titlebar { cursor: move; } \ No newline at end of file
diff --git a/themes/wind/css/themeroller/ui.progressbar.css b/themes/wind/css/themeroller/ui.progressbar.css
new file mode 100644
index 00000000..bc0939ec
--- /dev/null
+++ b/themes/wind/css/themeroller/ui.progressbar.css
@@ -0,0 +1,4 @@
+/* Progressbar
+----------------------------------*/
+.ui-progressbar { height:2em; text-align: left; }
+.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; } \ No newline at end of file
diff --git a/themes/wind/css/themeroller/ui.resizable.css b/themes/wind/css/themeroller/ui.resizable.css
new file mode 100644
index 00000000..44efeb2e
--- /dev/null
+++ b/themes/wind/css/themeroller/ui.resizable.css
@@ -0,0 +1,13 @@
+/* Resizable
+----------------------------------*/
+.ui-resizable { position: relative;}
+.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;}
+.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
+.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0px; }
+.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0px; }
+.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0px; height: 100%; }
+.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0px; height: 100%; }
+.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
+.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
+.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
+.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;} \ No newline at end of file
diff --git a/themes/wind/css/themeroller/ui.tabs.css b/themes/wind/css/themeroller/ui.tabs.css
new file mode 100644
index 00000000..70ed3ef4
--- /dev/null
+++ b/themes/wind/css/themeroller/ui.tabs.css
@@ -0,0 +1,9 @@
+/* Tabs
+----------------------------------*/
+.ui-tabs {padding: .2em;}
+.ui-tabs .ui-tabs-nav { padding: .2em .2em 0 .2em; position: relative; }
+.ui-tabs .ui-tabs-nav li { float: left; border-bottom: 0 !important; margin: 0 .2em -1px 0; padding: 0; list-style: none; }
+.ui-tabs .ui-tabs-nav li a { display:block; text-decoration: none; padding: .5em 1em; }
+.ui-tabs .ui-tabs-nav li.ui-tabs-selected { padding-bottom: .1em; border-bottom: 0; }
+.ui-tabs .ui-tabs-panel { padding: 1em 1.4em; display: block; border: 0; background: none; }
+.ui-tabs .ui-tabs-hide { display: none !important; } \ No newline at end of file
diff --git a/themes/wind/css/themeroller/ui.theme.css b/themes/wind/css/themeroller/ui.theme.css
new file mode 100644
index 00000000..477252e5
--- /dev/null
+++ b/themes/wind/css/themeroller/ui.theme.css
@@ -0,0 +1,243 @@
+
+
+/*
+* jQuery UI CSS Framework
+* Copyright (c) 2009 AUTHORS.txt (http://ui.jquery.com/about)
+* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
+* To view and modify this theme, visit http://ui.jquery.com/themeroller/?tr=&ffDefault=Lucida%20Grande,%20Lucida%20Sans,%20Arial,%20sans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=5px&bgColorHeader=5c9ccc&bgTextureHeader=12_gloss_wave.png&bgImgOpacityHeader=55&borderColorHeader=4297d7&fcHeader=ffffff&iconColorHeader=d8e7f3&bgColorContent=fcfdfd&bgTextureContent=06_inset_hard.png&bgImgOpacityContent=100&borderColorContent=a6c9e2&fcContent=222222&iconColorContent=469bdd&bgColorDefault=dfeffc&bgTextureDefault=02_glass.png&bgImgOpacityDefault=85&borderColorDefault=c5dbec&fcDefault=2e6e9e&iconColorDefault=6da8d5&bgColorHover=d0e5f5&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=79b7e7&fcHover=1d5987&iconColorHover=217bc0&bgColorActive=f5f8f9&bgTextureActive=06_inset_hard.png&bgImgOpacityActive=100&borderColorActive=79b7e7&fcActive=e17009&iconColorActive=f9bd01&bgColorHighlight=fbec88&bgTextureHighlight=01_flat.png&bgImgOpacityHighlight=55&borderColorHighlight=fad42e&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
+*/
+
+
+/* Component containers
+----------------------------------*/
+.ui-widget { font-family: Lucida Grande, Lucida Sans, Arial, sans-serif; font-size: 1.1em; }
+.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Lucida Grande, Lucida Sans, Arial, sans-serif; font-size: 1em; }
+.ui-widget-header { border: 1px solid #4297d7; background: #5c9ccc url(images/ui-bg_gloss-wave_55_5c9ccc_500x100.png) 50% 50% repeat-x; color: #ffffff; font-weight: bold; }
+.ui-widget-header a { color: #ffffff; }
+.ui-widget-content { border: 1px solid #a6c9e2; background: #fcfdfd url(images/ui-bg_inset-hard_100_fcfdfd_1x100.png) 50% bottom repeat-x; color: #222222; }
+.ui-widget-content a { color: #222222; }
+
+/* Interaction states
+----------------------------------*/
+.ui-state-default, .ui-widget-content .ui-state-default { border: 1px solid #c5dbec; background: #dfeffc url(images/ui-bg_glass_85_dfeffc_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #2e6e9e; outline: none; }
+.ui-state-default a { color: #2e6e9e; text-decoration: none; outline: none; }
+.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus { border: 1px solid #79b7e7; background: #d0e5f5 url(images/ui-bg_glass_75_d0e5f5_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #1d5987; outline: none; }
+.ui-state-hover a { color: #1d5987; text-decoration: none; outline: none; }
+.ui-state-active, .ui-widget-content .ui-state-active { border: 1px solid #79b7e7; background: #f5f8f9 url(images/ui-bg_inset-hard_100_f5f8f9_1x100.png) 50% 50% repeat-x; font-weight: bold; color: #e17009; outline: none; }
+.ui-state-active a { color: #e17009; outline: none; text-decoration: none; }
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-highlight, .ui-widget-content .ui-state-highlight {border: 1px solid #fad42e; background: #fbec88 url(images/ui-bg_flat_55_fbec88_40x100.png) 50% 50% repeat-x; color: #363636; }
+.ui-state-error, .ui-widget-content .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; }
+.ui-state-error-text, .ui-widget-content .ui-state-error-text { color: #cd0a0a; }
+.ui-state-disabled, .ui-widget-content .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
+.ui-priority-primary, .ui-widget-content .ui-priority-primary { font-weight: bold; }
+.ui-priority-secondary, .ui-widget-content .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_469bdd_256x240.png); }
+.ui-widget-content .ui-icon {background-image: url(images/ui-icons_469bdd_256x240.png); }
+.ui-widget-header .ui-icon {background-image: url(images/ui-icons_d8e7f3_256x240.png); }
+.ui-state-default .ui-icon { background-image: url(images/ui-icons_6da8d5_256x240.png); }
+.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_217bc0_256x240.png); }
+.ui-state-active .ui-icon {background-image: url(images/ui-icons_f9bd01_256x240.png); }
+.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); }
+.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); }
+
+/* positioning */
+.ui-icon-carat-1-n { background-position: 0 0; }
+.ui-icon-carat-1-ne { background-position: -16px 0; }
+.ui-icon-carat-1-e { background-position: -32px 0; }
+.ui-icon-carat-1-se { background-position: -48px 0; }
+.ui-icon-carat-1-s { background-position: -64px 0; }
+.ui-icon-carat-1-sw { background-position: -80px 0; }
+.ui-icon-carat-1-w { background-position: -96px 0; }
+.ui-icon-carat-1-nw { background-position: -112px 0; }
+.ui-icon-carat-2-n-s { background-position: -128px 0; }
+.ui-icon-carat-2-e-w { background-position: -144px 0; }
+.ui-icon-triangle-1-n { background-position: 0 -16px; }
+.ui-icon-triangle-1-ne { background-position: -16px -16px; }
+.ui-icon-triangle-1-e { background-position: -32px -16px; }
+.ui-icon-triangle-1-se { background-position: -48px -16px; }
+.ui-icon-triangle-1-s { background-position: -64px -16px; }
+.ui-icon-triangle-1-sw { background-position: -80px -16px; }
+.ui-icon-triangle-1-w { background-position: -96px -16px; }
+.ui-icon-triangle-1-nw { background-position: -112px -16px; }
+.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
+.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
+.ui-icon-arrow-1-n { background-position: 0 -32px; }
+.ui-icon-arrow-1-ne { background-position: -16px -32px; }
+.ui-icon-arrow-1-e { background-position: -32px -32px; }
+.ui-icon-arrow-1-se { background-position: -48px -32px; }
+.ui-icon-arrow-1-s { background-position: -64px -32px; }
+.ui-icon-arrow-1-sw { background-position: -80px -32px; }
+.ui-icon-arrow-1-w { background-position: -96px -32px; }
+.ui-icon-arrow-1-nw { background-position: -112px -32px; }
+.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
+.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
+.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
+.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
+.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
+.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
+.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
+.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
+.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
+.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
+.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
+.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
+.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
+.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
+.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
+.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
+.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
+.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
+.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
+.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
+.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
+.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
+.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
+.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
+.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
+.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
+.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
+.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
+.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
+.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
+.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
+.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
+.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
+.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
+.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
+.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
+.ui-icon-arrow-4 { background-position: 0 -80px; }
+.ui-icon-arrow-4-diag { background-position: -16px -80px; }
+.ui-icon-extlink { background-position: -32px -80px; }
+.ui-icon-newwin { background-position: -48px -80px; }
+.ui-icon-refresh { background-position: -64px -80px; }
+.ui-icon-shuffle { background-position: -80px -80px; }
+.ui-icon-transfer-e-w { background-position: -96px -80px; }
+.ui-icon-transferthick-e-w { background-position: -112px -80px; }
+.ui-icon-folder-collapsed { background-position: 0 -96px; }
+.ui-icon-folder-open { background-position: -16px -96px; }
+.ui-icon-document { background-position: -32px -96px; }
+.ui-icon-document-b { background-position: -48px -96px; }
+.ui-icon-note { background-position: -64px -96px; }
+.ui-icon-mail-closed { background-position: -80px -96px; }
+.ui-icon-mail-open { background-position: -96px -96px; }
+.ui-icon-suitcase { background-position: -112px -96px; }
+.ui-icon-comment { background-position: -128px -96px; }
+.ui-icon-person { background-position: -144px -96px; }
+.ui-icon-print { background-position: -160px -96px; }
+.ui-icon-trash { background-position: -176px -96px; }
+.ui-icon-locked { background-position: -192px -96px; }
+.ui-icon-unlocked { background-position: -208px -96px; }
+.ui-icon-bookmark { background-position: -224px -96px; }
+.ui-icon-tag { background-position: -240px -96px; }
+.ui-icon-home { background-position: 0 -112px; }
+.ui-icon-flag { background-position: -16px -112px; }
+.ui-icon-calendar { background-position: -32px -112px; }
+.ui-icon-cart { background-position: -48px -112px; }
+.ui-icon-pencil { background-position: -64px -112px; }
+.ui-icon-clock { background-position: -80px -112px; }
+.ui-icon-disk { background-position: -96px -112px; }
+.ui-icon-calculator { background-position: -112px -112px; }
+.ui-icon-zoomin { background-position: -128px -112px; }
+.ui-icon-zoomout { background-position: -144px -112px; }
+.ui-icon-search { background-position: -160px -112px; }
+.ui-icon-wrench { background-position: -176px -112px; }
+.ui-icon-gear { background-position: -192px -112px; }
+.ui-icon-heart { background-position: -208px -112px; }
+.ui-icon-star { background-position: -224px -112px; }
+.ui-icon-link { background-position: -240px -112px; }
+.ui-icon-cancel { background-position: 0 -128px; }
+.ui-icon-plus { background-position: -16px -128px; }
+.ui-icon-plusthick { background-position: -32px -128px; }
+.ui-icon-minus { background-position: -48px -128px; }
+.ui-icon-minusthick { background-position: -64px -128px; }
+.ui-icon-close { background-position: -80px -128px; }
+.ui-icon-closethick { background-position: -96px -128px; }
+.ui-icon-key { background-position: -112px -128px; }
+.ui-icon-lightbulb { background-position: -128px -128px; }
+.ui-icon-scissors { background-position: -144px -128px; }
+.ui-icon-clipboard { background-position: -160px -128px; }
+.ui-icon-copy { background-position: -176px -128px; }
+.ui-icon-contact { background-position: -192px -128px; }
+.ui-icon-image { background-position: -208px -128px; }
+.ui-icon-video { background-position: -224px -128px; }
+.ui-icon-script { background-position: -240px -128px; }
+.ui-icon-alert { background-position: 0 -144px; }
+.ui-icon-info { background-position: -16px -144px; }
+.ui-icon-notice { background-position: -32px -144px; }
+.ui-icon-help { background-position: -48px -144px; }
+.ui-icon-check { background-position: -64px -144px; }
+.ui-icon-bullet { background-position: -80px -144px; }
+.ui-icon-radio-off { background-position: -96px -144px; }
+.ui-icon-radio-on { background-position: -112px -144px; }
+.ui-icon-pin-w { background-position: -128px -144px; }
+.ui-icon-pin-s { background-position: -144px -144px; }
+.ui-icon-play { background-position: 0 -160px; }
+.ui-icon-pause { background-position: -16px -160px; }
+.ui-icon-seek-next { background-position: -32px -160px; }
+.ui-icon-seek-prev { background-position: -48px -160px; }
+.ui-icon-seek-end { background-position: -64px -160px; }
+.ui-icon-seek-first { background-position: -80px -160px; }
+.ui-icon-stop { background-position: -96px -160px; }
+.ui-icon-eject { background-position: -112px -160px; }
+.ui-icon-volume-off { background-position: -128px -160px; }
+.ui-icon-volume-on { background-position: -144px -160px; }
+.ui-icon-power { background-position: 0 -176px; }
+.ui-icon-signal-diag { background-position: -16px -176px; }
+.ui-icon-signal { background-position: -32px -176px; }
+.ui-icon-battery-0 { background-position: -48px -176px; }
+.ui-icon-battery-1 { background-position: -64px -176px; }
+.ui-icon-battery-2 { background-position: -80px -176px; }
+.ui-icon-battery-3 { background-position: -96px -176px; }
+.ui-icon-circle-plus { background-position: 0 -192px; }
+.ui-icon-circle-minus { background-position: -16px -192px; }
+.ui-icon-circle-close { background-position: -32px -192px; }
+.ui-icon-circle-triangle-e { background-position: -48px -192px; }
+.ui-icon-circle-triangle-s { background-position: -64px -192px; }
+.ui-icon-circle-triangle-w { background-position: -80px -192px; }
+.ui-icon-circle-triangle-n { background-position: -96px -192px; }
+.ui-icon-circle-arrow-e { background-position: -112px -192px; }
+.ui-icon-circle-arrow-s { background-position: -128px -192px; }
+.ui-icon-circle-arrow-w { background-position: -144px -192px; }
+.ui-icon-circle-arrow-n { background-position: -160px -192px; }
+.ui-icon-circle-zoomin { background-position: -176px -192px; }
+.ui-icon-circle-zoomout { background-position: -192px -192px; }
+.ui-icon-circle-check { background-position: -208px -192px; }
+.ui-icon-circlesmall-plus { background-position: 0 -208px; }
+.ui-icon-circlesmall-minus { background-position: -16px -208px; }
+.ui-icon-circlesmall-close { background-position: -32px -208px; }
+.ui-icon-squaresmall-plus { background-position: -48px -208px; }
+.ui-icon-squaresmall-minus { background-position: -64px -208px; }
+.ui-icon-squaresmall-close { background-position: -80px -208px; }
+.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
+.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
+.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
+.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
+.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
+.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Corner radius */
+.ui-corner-tl { -moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; border-top-left-radius: 5px; }
+.ui-corner-tr { -moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; border-top-right-radius: 5px; }
+.ui-corner-bl { -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; border-bottom-left-radius: 5px; }
+.ui-corner-br { -moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; border-bottom-right-radius: 5px; }
+.ui-corner-top { -moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; border-top-left-radius: 5px; -moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; border-top-right-radius: 5px; }
+.ui-corner-bottom { -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; border-bottom-left-radius: 5px; -moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; border-bottom-right-radius: 5px; }
+.ui-corner-right { -moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; border-top-right-radius: 5px; -moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; border-bottom-right-radius: 5px; }
+.ui-corner-left { -moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; border-top-left-radius: 5px; -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; border-bottom-left-radius: 5px; }
+.ui-corner-all { -moz-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; }
+
+/* Overlays */
+.ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); }
+.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -webkit-border-radius: 8px; } \ No newline at end of file
diff --git a/themes/wind/js/ui.init.js b/themes/wind/js/ui.init.js
index 6edf6be4..a4fc0e2f 100644
--- a/themes/wind/js/ui.init.js
+++ b/themes/wind/js/ui.init.js
@@ -43,6 +43,9 @@ $(document).ready(function() {
});
}
+ // Remove titles for menu options since we're displaying that text anyway
+ $(".sf-menu a, .sf-menu li").removeAttr("title");
+
// Album and search results views
if ($("#g-album-grid").length) {
// Set equal height for album items and vertically align thumbnails/metadata
@@ -108,6 +111,9 @@ $(document).ready(function() {
duration: 1000,
hash: true
});
+
+ $(this).find(".g-dialog-link").gallery_dialog();
+ $(this).find(".g-ajax-link").gallery_ajax();
}
// Initialize button hover effect
diff --git a/themes/wind/views/album.html.php b/themes/wind/views/album.html.php
index eabe07c3..b9072e2b 100644
--- a/themes/wind/views/album.html.php
+++ b/themes/wind/views/album.html.php
@@ -29,7 +29,7 @@
<? endforeach ?>
<? else: ?>
<? if ($user->admin || access::can("add", $item)): ?>
- <? $addurl = url::file("index.php/simple_uploader/app/$item->id") ?>
+ <? $addurl = url::site("flash_uploader/app/$item->id") ?>
<li><?= t("There aren't any photos here yet! <a %attrs>Add some</a>.",
array("attrs" => html::mark_clean("href=\"$addurl\" class=\"g-dialog-link\""))) ?></li>
<? else: ?>
diff --git a/themes/wind/views/movie.html.php b/themes/wind/views/movie.html.php
index 27c293ce..158857db 100644
--- a/themes/wind/views/movie.html.php
+++ b/themes/wind/views/movie.html.php
@@ -5,8 +5,9 @@
<?= $theme->paginator() ?>
<div id="g-movie" class="ui-helper-clearfix">
- <?= $item->movie_img(array("class" => "g-movie", "id" => "g-movie-id-{$item->id}")) ?>
- <?= $theme->context_menu($item, "#g-movie-id-{$item->id}") ?>
+ <?= $theme->resize_top($item) ?>
+ <?= $item->movie_img(array("class" => "g-movie", "id" => "g-item-id-{$item->id}")) ?>
+ <?= $theme->resize_bottom($item) ?>
</div>
<div id="g-info">
diff --git a/themes/wind/views/page.html.php b/themes/wind/views/page.html.php
index ebfbf700..16e43c63 100644
--- a/themes/wind/views/page.html.php
+++ b/themes/wind/views/page.html.php
@@ -87,9 +87,9 @@
<?= $theme->user_menu() ?>
<?= $theme->header_top() ?>
- <!-- hide the menu and make it visible after the page has loaded, to minimize menu flicker -->
+ <!-- hide the menu until after the page has loaded, to minimize menu flicker -->
<div id="g-site-menu" style="visibility: hidden">
- <?= $theme->site_menu() ?>
+ <?= $theme->site_menu($theme->item() ? "#g-item-id-{$theme->item()->id}" : "") ?>
</div>
<script type="text/javascript"> $(document).ready(function() { $("#g-site-menu").css("visibility", "visible"); }) </script>
@@ -107,12 +107,14 @@
level you're on the right page. -->
<a href="<?= $parent->url($parent == $theme->item()->parent() ?
"show={$theme->item()->id}" : null) ?>">
- <?= html::purify($parent->title) ?>
+ <?= text::limit_chars(html::purify($parent->title), 15) ?>
</a>
</li>
<? $i++ ?>
<? endforeach ?>
- <li class="g-active<? if ($i == 0) print " g-first" ?>"><?= html::purify($theme->item()->title) ?></li>
+ <li class="g-active<? if ($i == 0) print " g-first" ?>">
+ <?= text::limit_chars(html::purify($theme->item()->title), 15) ?>
+ </li>
</ul>
<? endif ?>
</div>
diff --git a/themes/wind/views/photo.html.php b/themes/wind/views/photo.html.php
index e0fae3f1..f8b5511c 100644
--- a/themes/wind/views/photo.html.php
+++ b/themes/wind/views/photo.html.php
@@ -22,12 +22,11 @@
<? if (access::can("view_full", $item)): ?>
<a href="<?= $item->file_url() ?>" class="g-fullsize-link" title="<?= t("View full size")->for_html_attr() ?>">
<? endif ?>
- <?= $item->resize_img(array("id" => "g-photo-id-{$item->id}", "class" => "g-resize")) ?>
+ <?= $item->resize_img(array("id" => "g-item-id-{$item->id}", "class" => "g-resize")) ?>
<? if (access::can("view_full", $item)): ?>
</a>
<? endif ?>
<?= $theme->resize_bottom($item) ?>
- <?= $theme->context_menu($item, "#g-photo-id-{$item->id}") ?>
</div>
<div id="g-info">