Imported Debian patch 3.0.2-1

This commit is contained in:
Michael C. Schultheiss 2011-07-06 23:11:37 +00:00 committed by Anthony Callegaro
commit 4e01cf5361
118 changed files with 2501 additions and 1481 deletions

2
README
View File

@ -1,4 +1,4 @@
Gallery 3.0.1
Gallery 3.0.2
ABOUT:
Gallery 3 is a web based software product that lets you manage your

7
debian/changelog vendored
View File

@ -1,3 +1,10 @@
gallery3 (3.0.2-1) unstable; urgency=low
* New upstream release
* debian/copyright: Add licenses of included libraries
-- Michael C. Schultheiss <schultmc@debian.org> Wed, 06 Jul 2011 23:11:37 +0000
gallery3 (3.0.1-3) unstable; urgency=low
* debian/postinst: add port to installer call

184
debian/copyright vendored
View File

@ -12,9 +12,15 @@ Upstream Author(s):
Copyright:
Copyright (C) 2000-2010 Bharat Mediratta
Gallery Copyright (C) 2000-2011 Bharat Mediratta
Flowplayer Copyright (C) Flowplayer Ltd.
Superfish Copyright (C) 2008 Joel Birch
Uploadify Copyright (C) 2010 Ronnie Garcia, Travis Nickels
YUI Copyright (C) 2011, Yahoo! Inc.
Kohana Copyright (C) 2007-2009 Kohana Team
jQuery Copyright (C) 2009 John Resig
License:
Gallery 3 License:
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
@ -23,6 +29,180 @@ License:
See "/usr/share/common-licenses/GPL-2".
lib/flowplayer* License:
The Flowplayer Free version is released under the
GNU GENERAL PUBLIC LICENSE Version 3 (GPL).
See "/usr/share/common-licenses/GPL-3"
The GPL requires that you not remove the Flowplayer copyright
notices from the user interface. See section 5.d below.
Commercial licenses are available. The commercial player version
does not require any Flowplayer notices or texts and also provides
some additional features.
ADDITIONAL TERM per GPL Section 7
If you convey this program (or any modifications of it) and assume
contractual liability for the program to recipients of it, you agree
to indemnify Flowplayer, Ltd. for any liability that those
contractual assumptions impose on Flowplayer, Ltd.
Except as expressly provided herein, no trademark rights are granted
in any trademarks of Flowplayer, Ltd. Licensees are granted a
limited, non-exclusive right to use the mark Flowplayer and the
Flowplayer logos in connection with unmodified copies of the Program
and the copyright notices required by section 5.d of the GPL
license. For the purposes of this limited trademark license grant,
customizing the Flowplayer by skinning, scripting, or including
PlugIns provided by Flowplayer, Ltd. is not considered modifying
the Program.
Licensees that do modify the Program, taking advantage of the
open-source license, may not use the Flowplayer mark or Flowplayer
logos and must change the fullscreen notice (and the non-fullscreen
notice, if that option is enabled), the copyright notice in the
dialog box, and the notice on the Canvas as follows:
the full screen (and non-fullscreen equivalent, if activated) notice
should read: "Based on Flowplayer source code"; in the context menu
(right-click menu), the link to "About Flowplayer free version
#.#.#" can remain. The copyright notice can remain, but must be
supplemented with an additional notice, stating that the licensee
modified the Flowplayer. A suitable notice might read "Flowplayer
Source code modified by ModOrg 2009"; for the canvas, the notice
should read "Based on Flowplayer source code". In addition,
licensees that modify the Program must give the modified Program a
new name that is not confusingly similar to Flowplayer and may not
distribute it under the name Flowplayer.
lib/superfish/* License:
Dual licensed under the MIT and GPL licenses
The MIT License
Copyright (c) 2008 Joel Birch
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
See "/usr/share/common-licenses/GPL".
lib/uploadify/* License:
Copyright (c) 2010 Ronnie Garcia, Travis Nickels
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
lib/yui/*.css License:
Copyright (c) 2011, Yahoo! Inc.
All rights reserved.
Licensed under the BSD License. See
"/usr/share/common-licenses/BSD".
lib/jquery* License:
Copyright (c) 2009 John Ressig
Dual licensed under the MIT License and GPL
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
See "/usr/share/common-licenses/GPL-2"
system/* License:
This license is a legal agreement between you and the Kohana Team for
the use of Kohana Framework (the "Software"). By obtaining the
Software you agree to comply with the terms and conditions of this
license.
Copyright (c) 2007-2009 Kohana Team
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the
distribution.
* Neither the name of the Kohana nor the names of its contributors
may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The Debian packaging is:

View File

@ -67,8 +67,8 @@ CREATE TABLE {comments} (
`server_http_referer` varchar(255) DEFAULT NULL,
`server_http_user_agent` varchar(128) DEFAULT NULL,
`server_query_string` varchar(64) DEFAULT NULL,
`server_remote_addr` varchar(32) DEFAULT NULL,
`server_remote_host` varchar(64) DEFAULT NULL,
`server_remote_addr` varchar(40) DEFAULT NULL,
`server_remote_host` varchar(255) DEFAULT NULL,
`server_remote_port` varchar(16) DEFAULT NULL,
`state` varchar(15) DEFAULT 'unpublished',
`text` text,
@ -244,15 +244,15 @@ CREATE TABLE {modules} (
KEY `weight` (`weight`)
) AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
INSERT INTO {modules} VALUES (1,1,'gallery',46,1);
INSERT INTO {modules} VALUES (2,1,'user',3,2);
INSERT INTO {modules} VALUES (3,1,'comment',3,3);
INSERT INTO {modules} VALUES (1,1,'gallery',49,1);
INSERT INTO {modules} VALUES (2,1,'user',4,2);
INSERT INTO {modules} VALUES (3,1,'comment',4,3);
INSERT INTO {modules} VALUES (4,1,'organize',4,4);
INSERT INTO {modules} VALUES (5,1,'info',2,5);
INSERT INTO {modules} VALUES (6,1,'rss',1,6);
INSERT INTO {modules} VALUES (7,1,'search',1,7);
INSERT INTO {modules} VALUES (8,1,'slideshow',2,8);
INSERT INTO {modules} VALUES (9,1,'tag',2,9);
INSERT INTO {modules} VALUES (9,1,'tag',3,9);
DROP TABLE IF EXISTS {outgoing_translations};
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
@ -382,7 +382,7 @@ CREATE TABLE {vars} (
`value` text,
PRIMARY KEY (`id`),
UNIQUE KEY `module_name` (`module_name`,`name`)
) AUTO_INCREMENT=40 DEFAULT CHARSET=utf8;
) AUTO_INCREMENT=43 DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
INSERT INTO {vars} VALUES (NULL,'gallery','active_site_theme','wind');
INSERT INTO {vars} VALUES (NULL,'gallery','active_admin_theme','admin_wind');
@ -406,15 +406,17 @@ INSERT INTO {vars} VALUES (NULL,'gallery','admin_area_timeout','5400');
INSERT INTO {vars} VALUES (NULL,'gallery','maintenance_mode','0');
INSERT INTO {vars} VALUES (NULL,'gallery','visible_title_length','15');
INSERT INTO {vars} VALUES (NULL,'gallery','favicon_url','lib/images/favicon.ico');
INSERT INTO {vars} VALUES (NULL,'gallery','apple_touch_icon_url','lib/images/apple-touch-icon.png');
INSERT INTO {vars} VALUES (NULL,'gallery','email_from','unknown@unknown.com');
INSERT INTO {vars} VALUES (NULL,'gallery','email_reply_to','unknown@unknown.com');
INSERT INTO {vars} VALUES (NULL,'gallery','email_line_length','70');
INSERT INTO {vars} VALUES (NULL,'gallery','email_header_separator','s:1:\"\n\";');
INSERT INTO {vars} VALUES (NULL,'gallery','show_user_profiles_to','registered_users');
INSERT INTO {vars} VALUES (NULL,'gallery','extra_binary_paths','/usr/local/bin:/opt/local/bin:/opt/bin');
INSERT INTO {vars} VALUES (NULL,'gallery','timezone',NULL);
INSERT INTO {vars} VALUES (NULL,'gallery','blocks_site_sidebar','a:4:{i:10;a:2:{i:0;s:7:\"gallery\";i:1;s:8:\"language\";}i:11;a:2:{i:0;s:4:\"info\";i:1;s:8:\"metadata\";}i:12;a:2:{i:0;s:3:\"rss\";i:1;s:9:\"rss_feeds\";}i:13;a:2:{i:0;s:3:\"tag\";i:1;s:3:\"tag\";}}');
INSERT INTO {vars} VALUES (NULL,'gallery','identity_provider','user');
INSERT INTO {vars} VALUES (NULL,'user','mininum_password_length','5');
INSERT INTO {vars} VALUES (NULL,'user','minimum_password_length','5');
INSERT INTO {vars} VALUES (NULL,'comment','spam_caught','0');
INSERT INTO {vars} VALUES (NULL,'comment','access_permissions','everybody');
INSERT INTO {vars} VALUES (NULL,'info','show_title','1');
@ -423,3 +425,4 @@ INSERT INTO {vars} VALUES (NULL,'info','show_owner','1');
INSERT INTO {vars} VALUES (NULL,'info','show_name','1');
INSERT INTO {vars} VALUES (NULL,'info','show_captured','1');
INSERT INTO {vars} VALUES (NULL,'slideshow','max_scale','0');
INSERT INTO {vars} VALUES (NULL,'tag','tag_cloud_size','30');

View File

@ -191,8 +191,10 @@ class installer {
$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", "ñ")) {
$errors[] = "PHP is missing <a href=\"http://php.net/pcre\">Perl-Compatible Regular Expression</a> with UTF-8 support.";
} else if (!preg_match("/^\pL$/u", "ñ")) {
$errors[] = "PHP is missing <a href=\"http://php.net/pcre\">Perl-Compatible Regular Expression</a> with Unicode support.";
}
if (!(function_exists("spl_autoload_register"))) {
@ -211,6 +213,10 @@ class installer {
$errors[] = "PHP is missing the <a href=\"http://php.net/iconv\">iconv extension</a>";
}
if (!(extension_loaded("xml"))) {
$errors[] = "PHP is missing the <a href=\"http://php.net/xml\">XML Parser extension</a>";
}
if (!(extension_loaded("simplexml"))) {
$errors[] = "PHP is missing the <a href=\"http://php.net/simplexml\">SimpleXML extension</a>";
}

Binary file not shown.

View File

@ -10,13 +10,13 @@ function el(id){return document.getElementById(id);}
function extend(to,from,skipFuncs){if(typeof from!='object'){return to;}
if(to&&from){each(from,function(name,value){if(!skipFuncs||typeof value!='function'){to[name]=value;}});}
return to;}
function select(query){var index=query.indexOf(".");if(index!=-1){var tag=query.substring(0,index)||"*";var klass=query.substring(index+1,query.length);var els=[];each(document.getElementsByTagName(tag),function(){if(this.className&&this.className.indexOf(klass)!=-1){els.push(this);}});return els;}}
function select(query){var index=query.indexOf(".");if(index!=-1){var tag=query.slice(0,index)||"*";var klass=query.slice(index+1,query.length);var els=[];each(document.getElementsByTagName(tag),function(){if(this.className&&this.className.indexOf(klass)!=-1){els.push(this);}});return els;}}
function stopEvent(e){e=e||window.event;if(e.preventDefault){e.stopPropagation();e.preventDefault();}else{e.returnValue=false;e.cancelBubble=true;}
return false;}
function bind(to,evt,fn){to[evt]=to[evt]||[];to[evt].push(fn);}
function makeId(){return"_"+(""+Math.random()).substring(2,10);}
var Clip=function(json,index,player){var self=this;var cuepoints={};var listeners={};self.index=index;if(typeof json=='string'){json={url:json};}
extend(this,json,true);each(("Begin*,Start,Pause*,Resume*,Seek*,Stop*,Finish*,LastSecond,Update,BufferFull,BufferEmpty,BufferStop").split(","),function(){var evt="on"+this;if(evt.indexOf("*")!=-1){evt=evt.substring(0,evt.length-1);var before="onBefore"+evt.substring(2);self[before]=function(fn){bind(listeners,before,fn);return self;};}
function makeId(){return"_"+(""+Math.random()).slice(2,10);}
var Clip=function(json,index,player){var self=this,cuepoints={},listeners={};self.index=index;if(typeof json=='string'){json={url:json};}
extend(this,json,true);each(("Begin*,Start,Pause*,Resume*,Seek*,Stop*,Finish*,LastSecond,Update,BufferFull,BufferEmpty,BufferStop").split(","),function(){var evt="on"+this;if(evt.indexOf("*")!=-1){evt=evt.slice(0,evt.length-1);var before="onBefore"+evt.slice(2);self[before]=function(fn){bind(listeners,before,fn);return self;};}
self[evt]=function(fn){bind(listeners,evt,fn);return self;};if(index==-1){if(self[before]){player[before]=self[before];}
if(self[evt]){player[evt]=self[evt];}}});extend(this,{onCuepoint:function(points,fn){if(arguments.length==1){cuepoints.embedded=[null,points];return self;}
if(typeof points=='number'){points=[points];}
@ -26,7 +26,7 @@ var conf=player.getConfig();var clip=(index==-1)?conf.clip:conf.playlist[index];
target=target||self;if(evt=='onCuepoint'){var fn=cuepoints[arg1];if(fn){return fn[1].call(player,target,arg2);}}
if(arg1&&"onBeforeBegin,onMetaData,onStart,onUpdate,onResume".indexOf(evt)!=-1){extend(target,arg1);if(arg1.metaData){if(!target.duration){target.duration=arg1.metaData.duration;}else{target.fullDuration=arg1.metaData.duration;}}}
var ret=true;each(listeners[evt],function(){ret=this.call(player,target,arg1,arg2);});return ret;}});if(json.onCuepoint){var arg=json.onCuepoint;self.onCuepoint.apply(self,typeof arg=='function'?[arg]:arg);delete json.onCuepoint;}
each(json,function(key,val){if(typeof val=='function'){bind(listeners,key,val);delete json[key];}});if(index==-1){player.onCuepoint=this.onCuepoint;}};var Plugin=function(name,json,player,fn){var listeners={};var self=this;var hasMethods=false;if(fn){extend(listeners,fn);}
each(json,function(key,val){if(typeof val=='function'){bind(listeners,key,val);delete json[key];}});if(index==-1){player.onCuepoint=this.onCuepoint;}};var Plugin=function(name,json,player,fn){var self=this,listeners={},hasMethods=false;if(fn){extend(listeners,fn);}
each(json,function(key,val){if(typeof val=='function'){listeners[key]=val;delete json[key];}});extend(this,{animate:function(props,speed,fn){if(!props){return self;}
if(typeof speed=='function'){fn=speed;speed=500;}
if(typeof props=='string'){var key=props;props={};props[key]=speed;speed=500;}
@ -37,32 +37,37 @@ json=player._api().fp_css(name,props);extend(self,json);return self;},show:funct
if(fn){var fnId=makeId();listeners[fnId]=fn;}
this.display=player._api().fp_fadeTo(name,o,speed,fnId);this.opacity=o;return self;},fadeIn:function(speed,fn){return self.fadeTo(1,speed,fn);},fadeOut:function(speed,fn){return self.fadeTo(0,speed,fn);},getName:function(){return name;},getPlayer:function(){return player;},_fireEvent:function(evt,arg,arg2){if(evt=='onUpdate'){var json=player._api().fp_getPlugin(name);if(!json){return;}
extend(self,json);delete self.methods;if(!hasMethods){each(json.methods,function(){var method=""+this;self[method]=function(){var a=[].slice.call(arguments);var ret=player._api().fp_invoke(name,method,a);return ret==='undefined'||ret===undefined?self:ret;};});hasMethods=true;}}
var fn=listeners[evt];if(fn){fn.apply(self,arg);if(evt.substring(0,1)=="_"){delete listeners[evt];}}}});};function Player(wrapper,params,conf){var
self=this,api=null,html,commonClip,playlist=[],plugins={},listeners={},playerId,apiId,playerIndex,activeIndex,swfHeight,wrapperHeight;extend(self,{id:function(){return playerId;},isLoaded:function(){return(api!==null);},getParent:function(){return wrapper;},hide:function(all){if(all){wrapper.style.height="0px";}
if(api){api.style.height="0px";}
return self;},show:function(){wrapper.style.height=wrapperHeight+"px";if(api){api.style.height=swfHeight+"px";}
return self;},isHidden:function(){return api&&parseInt(api.style.height,10)===0;},load:function(fn){if(!api&&self._fireEvent("onBeforeLoad")!==false){each(players,function(){this.unload();});html=wrapper.innerHTML;if(html&&!flashembed.isSupported(params.version)){wrapper.innerHTML="";}
flashembed(wrapper,params,{config:conf});if(fn){fn.cached=true;bind(listeners,"onLoad",fn);}}
return self;},unload:function(){if(html.replace(/\s/g,'')!==''){if(self._fireEvent("onBeforeUnload")===false){return self;}
try{if(api){api.fp_close();self._fireEvent("onUnload");}}catch(error){}
api=null;wrapper.innerHTML=html;}
var fn=listeners[evt];if(fn){var ret=fn.apply(self,arg);if(evt.slice(0,1)=="_"){delete listeners[evt];}
return ret;}
return self;}});};function Player(wrapper,params,conf){var self=this,api=null,isUnloading=false,html,commonClip,playlist=[],plugins={},listeners={},playerId,apiId,playerIndex,activeIndex,swfHeight,wrapperHeight;extend(self,{id:function(){return playerId;},isLoaded:function(){return(api!==null&&api.fp_play!==undefined&&!isUnloading);},getParent:function(){return wrapper;},hide:function(all){if(all){wrapper.style.height="0px";}
if(self.isLoaded()){api.style.height="0px";}
return self;},show:function(){wrapper.style.height=wrapperHeight+"px";if(self.isLoaded()){api.style.height=swfHeight+"px";}
return self;},isHidden:function(){return self.isLoaded()&&parseInt(api.style.height,10)===0;},load:function(fn){if(!self.isLoaded()&&self._fireEvent("onBeforeLoad")!==false){var onPlayersUnloaded=function(){html=wrapper.innerHTML;if(html&&!flashembed.isSupported(params.version)){wrapper.innerHTML="";}
if(fn){fn.cached=true;bind(listeners,"onLoad",fn);}
flashembed(wrapper,params,{config:conf});};var unloadedPlayersNb=0;each(players,function(){this.unload(function(wasUnloaded){if(++unloadedPlayersNb==players.length){onPlayersUnloaded();}});});}
return self;},unload:function(fn){if(this.isFullscreen()&&/WebKit/i.test(navigator.userAgent)){if(fn){fn(false);}
return self;}
if(html.replace(/\s/g,'')!==''){if(self._fireEvent("onBeforeUnload")===false){if(fn){fn(false);}
return self;}
isUnloading=true;try{if(api){api.fp_close();self._fireEvent("onUnload");}}catch(error){}
var clean=function(){api=null;wrapper.innerHTML=html;isUnloading=false;if(fn){fn(true);}};setTimeout(clean,50);}
else if(fn){fn(false);}
return self;},getClip:function(index){if(index===undefined){index=activeIndex;}
return playlist[index];},getCommonClip:function(){return commonClip;},getPlaylist:function(){return playlist;},getPlugin:function(name){var plugin=plugins[name];if(!plugin&&self.isLoaded()){var json=self._api().fp_getPlugin(name);if(json){plugin=new Plugin(name,json,self);plugins[name]=plugin;}}
return plugin;},getScreen:function(){return self.getPlugin("screen");},getControls:function(){return self.getPlugin("controls");},getConfig:function(copy){return copy?clone(conf):conf;},getFlashParams:function(){return params;},loadPlugin:function(name,url,props,fn){if(typeof props=='function'){fn=props;props={};}
var fnId=fn?makeId():"_";self._api().fp_loadPlugin(name,url,props,fnId);var arg={};arg[fnId]=fn;var p=new Plugin(name,null,self,arg);plugins[name]=p;return p;},getState:function(){return api?api.fp_getState():-1;},play:function(clip,instream){function play(){if(clip!==undefined){self._api().fp_play(clip,instream);}else{self._api().fp_play();}}
if(api){play();}else{self.load(function(){play();});}
return self;},getVersion:function(){var js="flowplayer.js 3.1.4";if(api){var ver=api.fp_getVersion();ver.push(js);return ver;}
return js;},_api:function(){if(!api){throw"Flowplayer "+self.id()+" not loaded when calling an API method";}
return api;},setClip:function(clip){self.setPlaylist([clip]);return self;},getIndex:function(){return playerIndex;}});each(("Click*,Load*,Unload*,Keypress*,Volume*,Mute*,Unmute*,PlaylistReplace,ClipAdd,Fullscreen*,FullscreenExit,Error,MouseOver,MouseOut").split(","),function(){var name="on"+this;if(name.indexOf("*")!=-1){name=name.substring(0,name.length-1);var name2="onBefore"+name.substring(2);self[name2]=function(fn){bind(listeners,name2,fn);return self;};}
self[name]=function(fn){bind(listeners,name,fn);return self;};});each(("pause,resume,mute,unmute,stop,toggle,seek,getStatus,getVolume,setVolume,getTime,isPaused,isPlaying,startBuffering,stopBuffering,isFullscreen,toggleFullscreen,reset,close,setPlaylist,addClip,playFeed").split(","),function(){var name=this;self[name]=function(a1,a2){if(!api){return self;}
return plugin;},getScreen:function(){return self.getPlugin("screen");},getControls:function(){return self.getPlugin("controls")._fireEvent("onUpdate");},getLogo:function(){try{return self.getPlugin("logo")._fireEvent("onUpdate");}catch(ignored){}},getPlay:function(){return self.getPlugin("play")._fireEvent("onUpdate");},getConfig:function(copy){return copy?clone(conf):conf;},getFlashParams:function(){return params;},loadPlugin:function(name,url,props,fn){if(typeof props=='function'){fn=props;props={};}
var fnId=fn?makeId():"_";self._api().fp_loadPlugin(name,url,props,fnId);var arg={};arg[fnId]=fn;var p=new Plugin(name,null,self,arg);plugins[name]=p;return p;},getState:function(){return self.isLoaded()?api.fp_getState():-1;},play:function(clip,instream){var p=function(){if(clip!==undefined){self._api().fp_play(clip,instream);}else{self._api().fp_play();}};if(self.isLoaded()){p();}else if(isUnloading){setTimeout(function(){self.play(clip,instream);},50);}else{self.load(function(){p();});}
return self;},getVersion:function(){var js="flowplayer.js 3.2.6";if(self.isLoaded()){var ver=api.fp_getVersion();ver.push(js);return ver;}
return js;},_api:function(){if(!self.isLoaded()){throw"Flowplayer "+self.id()+" not loaded when calling an API method";}
return api;},setClip:function(clip){self.setPlaylist([clip]);return self;},getIndex:function(){return playerIndex;},_swfHeight:function(){return api.clientHeight;}});each(("Click*,Load*,Unload*,Keypress*,Volume*,Mute*,Unmute*,PlaylistReplace,ClipAdd,Fullscreen*,FullscreenExit,Error,MouseOver,MouseOut").split(","),function(){var name="on"+this;if(name.indexOf("*")!=-1){name=name.slice(0,name.length-1);var name2="onBefore"+name.slice(2);self[name2]=function(fn){bind(listeners,name2,fn);return self;};}
self[name]=function(fn){bind(listeners,name,fn);return self;};});each(("pause,resume,mute,unmute,stop,toggle,seek,getStatus,getVolume,setVolume,getTime,isPaused,isPlaying,startBuffering,stopBuffering,isFullscreen,toggleFullscreen,reset,close,setPlaylist,addClip,playFeed,setKeyboardShortcutsEnabled,isKeyboardShortcutsEnabled").split(","),function(){var name=this;self[name]=function(a1,a2){if(!self.isLoaded()){return self;}
var ret=null;if(a1!==undefined&&a2!==undefined){ret=api["fp_"+name](a1,a2);}else{ret=(a1===undefined)?api["fp_"+name]():api["fp_"+name](a1);}
return ret==='undefined'||ret===undefined?self:ret;};});self._fireEvent=function(a){if(typeof a=='string'){a=[a];}
var evt=a[0],arg0=a[1],arg1=a[2],arg2=a[3],i=0;if(conf.debug){log(a);}
if(!api&&evt=='onLoad'&&arg0=='player'){api=api||el(apiId);swfHeight=api.clientHeight;each(playlist,function(){this._fireEvent("onLoad");});each(plugins,function(name,p){p._fireEvent("onUpdate");});commonClip._fireEvent("onLoad");}
if(!self.isLoaded()&&evt=='onLoad'&&arg0=='player'){api=api||el(apiId);swfHeight=self._swfHeight();each(playlist,function(){this._fireEvent("onLoad");});each(plugins,function(name,p){p._fireEvent("onUpdate");});commonClip._fireEvent("onLoad");}
if(evt=='onLoad'&&arg0!='player'){return;}
if(evt=='onError'){if(typeof arg0=='string'||(typeof arg0=='number'&&typeof arg1=='number')){arg0=arg1;arg1=arg2;}}
if(evt=='onContextMenu'){each(conf.contextMenu[arg0],function(key,fn){fn.call(self);});return;}
if(evt=='onPluginEvent'){var name=arg0.name||arg0;var p=plugins[name];if(p){p._fireEvent("onUpdate",arg0);p._fireEvent(arg1,a.slice(3));}
if(evt=='onPluginEvent'||evt=='onBeforePluginEvent'){var name=arg0.name||arg0;var p=plugins[name];if(p){p._fireEvent("onUpdate",arg0);return p._fireEvent(arg1,a.slice(3));}
return;}
if(evt=='onPlaylistReplace'){playlist=[];var index=0;each(arg0,function(){playlist.push(new Clip(this,index++,self));});}
if(evt=='onClipAdd'){if(arg0.isInStream){return;}
@ -72,60 +77,143 @@ if(!clip||ret!==false){ret=commonClip._fireEvent(evt,arg1,arg2,clip);}}
each(listeners[evt],function(){ret=this.call(self,arg0,arg1);if(this.cached){listeners[evt].splice(i,1);}
if(ret===false){return false;}
i++;});return ret;};function init(){if($f(wrapper)){$f(wrapper).getParent().innerHTML="";playerIndex=$f(wrapper).getIndex();players[playerIndex]=self;}else{players.push(self);playerIndex=players.length-1;}
wrapperHeight=parseInt(wrapper.style.height,10)||wrapper.clientHeight;if(typeof params=='string'){params={src:params};}
playerId=wrapper.id||"fp"+makeId();apiId=params.id||playerId+"_api";params.id=apiId;conf.playerId=playerId;if(typeof conf=='string'){conf={clip:{url:conf}};}
wrapperHeight=parseInt(wrapper.style.height,10)||wrapper.clientHeight;playerId=wrapper.id||"fp"+makeId();apiId=params.id||playerId+"_api";params.id=apiId;conf.playerId=playerId;if(typeof conf=='string'){conf={clip:{url:conf}};}
if(typeof conf.clip=='string'){conf.clip={url:conf.clip};}
conf.clip=conf.clip||{};if(wrapper.getAttribute("href",2)&&!conf.clip.url){conf.clip.url=wrapper.getAttribute("href",2);}
commonClip=new Clip(conf.clip,-1,self);conf.playlist=conf.playlist||[conf.clip];var index=0;each(conf.playlist,function(){var clip=this;if(typeof clip=='object'&&clip.length){clip={url:""+clip};}
each(conf.clip,function(key,val){if(val!==undefined&&clip[key]===undefined&&typeof val!='function'){clip[key]=val;}});conf.playlist[index]=clip;clip=new Clip(clip,index,self);playlist.push(clip);index++;});each(conf,function(key,val){if(typeof val=='function'){if(commonClip[key]){commonClip[key](val);}else{bind(listeners,key,val);}
delete conf[key];}});each(conf.plugins,function(name,val){if(val){plugins[name]=new Plugin(name,val,self);}});if(!conf.plugins||conf.plugins.controls===undefined){plugins.controls=new Plugin("controls",null,self);}
plugins.canvas=new Plugin("canvas",null,self);params.bgcolor=params.bgcolor||"#000000";params.version=params.version||[9,0];params.expressInstall='http://www.flowplayer.org/swf/expressinstall.swf';function doClick(e){if(!self.isLoaded()&&self._fireEvent("onBeforeClick")!==false){self.load();}
plugins.canvas=new Plugin("canvas",null,self);html=wrapper.innerHTML;function doClick(e){var hasiPadSupport=self.hasiPadSupport&&self.hasiPadSupport();if(/iPad|iPhone|iPod/i.test(navigator.userAgent)&&!/.flv$/i.test(playlist[0].url)&&!hasiPadSupport){return true;}
if(!self.isLoaded()&&self._fireEvent("onBeforeClick")!==false){self.load();}
return stopEvent(e);}
html=wrapper.innerHTML;if(html.replace(/\s/g,'')!==''){if(wrapper.addEventListener){wrapper.addEventListener("click",doClick,false);}else if(wrapper.attachEvent){wrapper.attachEvent("onclick",doClick);}}else{if(wrapper.addEventListener){wrapper.addEventListener("click",stopEvent,false);}
function installPlayer(){if(html.replace(/\s/g,'')!==''){if(wrapper.addEventListener){wrapper.addEventListener("click",doClick,false);}else if(wrapper.attachEvent){wrapper.attachEvent("onclick",doClick);}}else{if(wrapper.addEventListener){wrapper.addEventListener("click",stopEvent,false);}
self.load();}}
if(typeof wrapper=='string'){flashembed.domReady(function(){var node=el(wrapper);if(!node){throw"Flowplayer cannot access element: "+wrapper;}else{wrapper=node;init();}});}else{init();}}
setTimeout(installPlayer,0);}
if(typeof wrapper=='string'){var node=el(wrapper);if(!node){throw"Flowplayer cannot access element: "+wrapper;}
wrapper=node;init();}else{init();}}
var players=[];function Iterator(arr){this.length=arr.length;this.each=function(fn){each(arr,fn);};this.size=function(){return arr.length;};}
window.flowplayer=window.$f=function(){var instance=null;var arg=arguments[0];if(!arguments.length){each(players,function(){if(this.isLoaded()){instance=this;return false;}});return instance||players[0];}
if(arguments.length==1){if(typeof arg=='number'){return players[arg];}else{if(arg=='*'){return new Iterator(players);}
each(players,function(){if(this.id()==arg.id||this.id()==arg||this.getParent()==arg){instance=this;return false;}});return instance;}}
if(arguments.length>1){var swf=arguments[1];var conf=(arguments.length==3)?arguments[2]:{};if(typeof arg=='string'){if(arg.indexOf(".")!=-1){var instances=[];each(select(arg),function(){instances.push(new Player(this,clone(swf),clone(conf)));});return new Iterator(instances);}else{var node=el(arg);return new Player(node!==null?node:arg,swf,conf);}}else if(arg){return new Player(arg,swf,conf);}}
return null;};extend(window.$f,{fireEvent:function(){var a=[].slice.call(arguments);var p=$f(a[0]);return p?p._fireEvent(a.slice(1)):null;},addPlugin:function(name,fn){Player.prototype[name]=fn;return $f;},each:each,extend:extend});if(typeof jQuery=='function'){jQuery.prototype.flowplayer=function(params,conf){if(!arguments.length||typeof arguments[0]=='number'){var arr=[];this.each(function(){var p=$f(this);if(p){arr.push(p);}});return arguments.length?arr[arguments[0]]:new Iterator(arr);}
return this.each(function(){$f(this,clone(params),conf?clone(conf):{});});};}})();(function(){var jQ=typeof jQuery=='function';var options={width:'100%',height:'100%',allowfullscreen:true,allowscriptaccess:'always',quality:'high',version:null,onFail:null,expressInstall:null,w3c:false,cachebusting:false};if(jQ){jQuery.tools=jQuery.tools||{};jQuery.tools.flashembed={version:'1.0.4',conf:options};}
function isDomReady(){if(domReady.done){return false;}
var d=document;if(d&&d.getElementsByTagName&&d.getElementById&&d.body){clearInterval(domReady.timer);domReady.timer=null;for(var i=0;i<domReady.ready.length;i++){domReady.ready[i].call();}
domReady.ready=null;domReady.done=true;}}
var domReady=jQ?jQuery:function(f){if(domReady.done){return f();}
if(domReady.timer){domReady.ready.push(f);}else{domReady.ready=[f];domReady.timer=setInterval(isDomReady,13);}};function extend(to,from){if(from){for(key in from){if(from.hasOwnProperty(key)){to[key]=from[key];}}}
if(arguments.length>1){var params=arguments[1],conf=(arguments.length==3)?arguments[2]:{};if(typeof params=='string'){params={src:params};}
params=extend({bgcolor:"#000000",version:[9,0],expressInstall:"http://static.flowplayer.org/swf/expressinstall.swf",cachebusting:false},params);if(typeof arg=='string'){if(arg.indexOf(".")!=-1){var instances=[];each(select(arg),function(){instances.push(new Player(this,clone(params),clone(conf)));});return new Iterator(instances);}else{var node=el(arg);return new Player(node!==null?node:arg,params,conf);}}else if(arg){return new Player(arg,params,conf);}}
return null;};extend(window.$f,{fireEvent:function(){var a=[].slice.call(arguments);var p=$f(a[0]);return p?p._fireEvent(a.slice(1)):null;},addPlugin:function(name,fn){Player.prototype[name]=fn;return $f;},each:each,extend:extend});if(typeof jQuery=='function'){jQuery.fn.flowplayer=function(params,conf){if(!arguments.length||typeof arguments[0]=='number'){var arr=[];this.each(function(){var p=$f(this);if(p){arr.push(p);}});return arguments.length?arr[arguments[0]]:new Iterator(arr);}
return this.each(function(){$f(this,clone(params),conf?clone(conf):{});});};}})();(function(){var IE=document.all,URL='http://www.adobe.com/go/getflashplayer',JQUERY=typeof jQuery=='function',RE=/(\d+)[^\d]+(\d+)[^\d]*(\d*)/,GLOBAL_OPTS={width:'100%',height:'100%',id:"_"+(""+Math.random()).slice(9),allowfullscreen:true,allowscriptaccess:'always',quality:'high',version:[3,0],onFail:null,expressInstall:null,w3c:false,cachebusting:false};if(window.attachEvent){window.attachEvent("onbeforeunload",function(){__flash_unloadHandler=function(){};__flash_savedUnloadHandler=function(){};});}
function extend(to,from){if(from){for(var key in from){if(from.hasOwnProperty(key)){to[key]=from[key];}}}
return to;}
var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},rep;function string2JsonString(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==='string'?c:'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4);})+'"':'"'+string+'"';}
function asString(obj){switch(typeOf(obj)){case'string':return string2JsonString(obj);case'array':return'['+map(obj,function(el){return asString(el);}).join(',')+']';case'function':return'"function()"';case'object':var str=[];for(var prop in obj){if(obj.hasOwnProperty(prop)){str.push('"'+prop+'":'+asString(obj[prop]));}}
return'{'+str.join(',')+'}';}
return String(obj).replace(/\s/g," ").replace(/\'/g,"\"");}
function typeOf(obj){if(obj===null||obj===undefined){return false;}
var type=typeof obj;return(type=='object'&&obj.push)?'array':type;}
if(window.attachEvent){window.attachEvent("onbeforeunload",function(){__flash_unloadHandler=function(){};__flash_savedUnloadHandler=function(){};});}
function map(arr,func){var newArr=[];for(var i in arr){if(arr.hasOwnProperty(i)){newArr[i]=func(arr[i]);}}
return newArr;}
function getHTML(p,c){var e=extend({},p);var ie=document.all;var html='<object width="'+e.width+'" height="'+e.height+'"';if(ie&&!e.id){e.id="_"+(""+Math.random()).substring(9);}
if(e.id){html+=' id="'+e.id+'"';}
if(e.cachebusting){e.src+=((e.src.indexOf("?")!=-1?"&":"?")+Math.random());}
if(e.w3c||!ie){html+=' data="'+e.src+'" type="application/x-shockwave-flash"';}else{html+=' classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"';}
html+='>';if(e.w3c||ie){html+='<param name="movie" value="'+e.src+'" />';}
e.width=e.height=e.id=e.w3c=e.src=null;for(var k in e){if(e[k]!==null){html+='<param name="'+k+'" value="'+e[k]+'" />';}}
var vars="";if(c){for(var key in c){if(c[key]!==null){vars+=encodeURIComponent(key)+'='
+encodeURIComponent(typeof c[key]=='object'?asString(c[key]):c[key])
+'&';}}
vars=vars.substring(0,vars.length-1);html+='<param name="flashvars" value="'+vars+'" />';}
html+="</object>";return html;}
function Flash(root,opts,flashvars){var version=flashembed.getVersion();extend(this,{getContainer:function(){return root;},getConf:function(){return opts;},getVersion:function(){return version;},getFlashvars:function(){return flashvars;},getApi:function(){return root.firstChild;},getHTML:function(){return getHTML(opts,flashvars);}});var required=opts.version;var express=opts.expressInstall;var ok=!required||flashembed.isSupported(required);if(ok){opts.onFail=opts.version=opts.expressInstall=null;root.innerHTML=getHTML(opts,flashvars);}else if(required&&express&&flashembed.isSupported([6,65])){extend(opts,{src:express});flashvars={MMredirectURL:location.href,MMplayerType:'PlugIn',MMdoctitle:document.title};root.innerHTML=getHTML(opts,flashvars);}else{if(root.innerHTML.replace(/\s/g,'')!==''){}else{root.innerHTML="<h2>Flash version "+required+" or greater is required</h2>"+"<h3>"+
(version[0]>0?"Your version is "+version:"You have no flash plugin installed")+"</h3>"+
(root.tagName=='A'?"<p>Click here to download latest version</p>":"<p>Download latest version from <a href='http://www.adobe.com/go/getflashplayer'>here</a></p>");if(root.tagName=='A'){root.onclick=function(){location.href='http://www.adobe.com/go/getflashplayer';};}}}
if(!ok&&opts.onFail){var ret=opts.onFail.call(this);if(typeof ret=='string'){root.innerHTML=ret;}}
if(document.all){window[opts.id]=document.getElementById(opts.id);}}
window.flashembed=function(root,conf,flashvars){if(typeof root=='string'){var el=document.getElementById(root);if(el){root=el;}else{domReady(function(){flashembed(root,conf,flashvars);});return;}}
window.flashembed=function(root,opts,conf){if(typeof root=='string'){root=document.getElementById(root.replace("#",""));}
if(!root){return;}
if(typeof conf=='string'){conf={src:conf};}
var opts=extend({},options);extend(opts,conf);return new Flash(root,opts,flashvars);};extend(window.flashembed,{getVersion:function(){var version=[0,0];if(navigator.plugins&&typeof navigator.plugins["Shockwave Flash"]=="object"){var _d=navigator.plugins["Shockwave Flash"].description;if(typeof _d!="undefined"){_d=_d.replace(/^.*\s+(\S+\s+\S+$)/,"$1");var _m=parseInt(_d.replace(/^(.*)\..*$/,"$1"),10);var _r=/r/.test(_d)?parseInt(_d.replace(/^.*r(.*)$/,"$1"),10):0;version=[_m,_r];}}else if(window.ActiveXObject){try{var _a=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");}catch(e){try{_a=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");version=[6,0];_a.AllowScriptAccess="always";}catch(ee){if(version[0]==6){return version;}}
try{_a=new ActiveXObject("ShockwaveFlash.ShockwaveFlash");}catch(eee){}}
if(typeof _a=="object"){_d=_a.GetVariable("$version");if(typeof _d!="undefined"){_d=_d.replace(/^\S+\s+(.*)$/,"$1").split(",");version=[parseInt(_d[0],10),parseInt(_d[2],10)];}}}
return version;},isSupported:function(version){var now=flashembed.getVersion();var ret=(now[0]>version[0])||(now[0]==version[0]&&now[1]>=version[1]);return ret;},domReady:domReady,asString:asString,getHTML:getHTML});if(jQ){jQuery.fn.flashembed=function(conf,flashvars){var el=null;this.each(function(){el=flashembed(this,conf,flashvars);});return conf.api===false?this:el;};}})();
if(typeof opts=='string'){opts={src:opts};}
return new Flash(root,extend(extend({},GLOBAL_OPTS),opts),conf);};var f=extend(window.flashembed,{conf:GLOBAL_OPTS,getVersion:function(){var fo,ver;try{ver=navigator.plugins["Shockwave Flash"].description.slice(16);}catch(e){try{fo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");ver=fo&&fo.GetVariable("$version");}catch(err){try{fo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");ver=fo&&fo.GetVariable("$version");}catch(err2){}}}
ver=RE.exec(ver);return ver?[ver[1],ver[3]]:[0,0];},asString:function(obj){if(obj===null||obj===undefined){return null;}
var type=typeof obj;if(type=='object'&&obj.push){type='array';}
switch(type){case'string':return string2JsonString(obj);case'array':return'['+map(obj,function(el){return f.asString(el);}).join(',')+']';case'function':return'"function()"';case'object':var str=[];for(var prop in obj){if(obj.hasOwnProperty(prop)){str.push('"'+prop+'":'+f.asString(obj[prop]));}}
return'{'+str.join(',')+'}';}
return String(obj).replace(/\s/g," ").replace(/\'/g,"\"");},getHTML:function(opts,conf){opts=extend({},opts);var html='<object width="'+opts.width+'" height="'+opts.height+'" id="'+opts.id+'" name="'+opts.id+'"';if(opts.cachebusting){opts.src+=((opts.src.indexOf("?")!=-1?"&":"?")+Math.random());}
if(opts.w3c||!IE){html+=' data="'+opts.src+'" type="application/x-shockwave-flash"';}else{html+=' classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"';}
html+='>';if(opts.w3c||IE){html+='<param name="movie" value="'+opts.src+'" />';}
opts.width=opts.height=opts.id=opts.w3c=opts.src=null;opts.onFail=opts.version=opts.expressInstall=null;for(var key in opts){if(opts[key]){html+='<param name="'+key+'" value="'+opts[key]+'" />';}}
var vars="";if(conf){for(var k in conf){if(conf[k]){var val=conf[k];vars+=encodeURIComponent(k)+'='
+encodeURIComponent(/function|object/.test(typeof val)?f.asString(val):val)
+'&';}}
vars=vars.slice(0,-1);html+='<param name="flashvars" value="'+vars+'" />';}
html+="</object>";return html;},isSupported:function(ver){return VERSION[0]>ver[0]||VERSION[0]==ver[0]&&VERSION[1]>=ver[1];}});var VERSION=f.getVersion();function Flash(root,opts,conf){if(f.isSupported(opts.version)){root.innerHTML=f.getHTML(opts,conf);}else if(opts.expressInstall&&f.isSupported([6,65])){root.innerHTML=f.getHTML(extend(opts,{src:opts.expressInstall}),{MMredirectURL:location.href,MMplayerType:'PlugIn',MMdoctitle:document.title});}else{if(!root.innerHTML.replace(/\s/g,'')){root.innerHTML="<h2>Flash version "+opts.version+" or greater is required</h2>"+"<h3>"+
(VERSION[0]>0?"Your version is "+VERSION:"You have no flash plugin installed")+"</h3>"+
(root.tagName=='A'?"<p>Click here to download latest version</p>":"<p>Download latest version from <a href='"+URL+"'>here</a></p>");if(root.tagName=='A'){root.onclick=function(){location.href=URL;};}}
if(opts.onFail){var ret=opts.onFail.call(this);if(typeof ret=='string'){root.innerHTML=ret;}}}
if(IE){window[opts.id]=document.getElementById(opts.id);}
extend(this,{getRoot:function(){return root;},getOptions:function(){return opts;},getConf:function(){return conf;},getApi:function(){return root.firstChild;}});}
var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},rep;function string2JsonString(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==='string'?c:'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4);})+'"':'"'+string+'"';}
if(JQUERY){jQuery.tools=jQuery.tools||{version:'3.2.6'};jQuery.tools.flashembed={conf:GLOBAL_OPTS};jQuery.fn.flashembed=function(opts,conf){return this.each(function(){jQuery(this).data("flashembed",flashembed(this,opts,conf));});};}})();$f.addPlugin("ipad",function(options){var STATE_UNLOADED=-1;var STATE_LOADED=0;var STATE_UNSTARTED=1;var STATE_BUFFERING=2;var STATE_PLAYING=3;var STATE_PAUSED=4;var STATE_ENDED=5;var self=this;var currentVolume=1;var onStartFired=false;var stopping=false;var playAfterSeek=false;var activeIndex=0;var activePlaylist=[];var clipDefaults={accelerated:false,autoBuffering:false,autoPlay:true,baseUrl:null,bufferLength:3,connectionProvider:null,cuepointMultiplier:1000,cuepoints:[],controls:{},duration:0,extension:'',fadeInSpeed:1000,fadeOutSpeed:1000,image:false,linkUrl:null,linkWindow:'_self',live:false,metaData:{},originalUrl:null,position:0,playlist:[],provider:'http',scaling:'scale',seekableOnBegin:false,start:0,url:null,urlResolvers:[]};var currentState=STATE_UNLOADED;var previousState=STATE_UNLOADED;var isiDevice=/iPad|iPhone|iPod/i.test(navigator.userAgent);var video=null;function extend(to,from,includeFuncs){if(from){for(key in from){if(key){if(from[key]&&typeof from[key]=="function"&&!includeFuncs)
continue;if(from[key]&&typeof from[key]=="object"&&from[key].length==undefined){var cp={};extend(cp,from[key]);to[key]=cp;}else{to[key]=from[key];}}}}
return to;}
var opts={simulateiDevice:false,controlsSizeRatio:1.5,controls:true,debug:false,validExtensions:/mov|m4v|mp4|avi/gi};extend(opts,options);function log(){if(opts.debug){if(isiDevice){var str=[].splice.call(arguments,0).join(', ');console.log.apply(console,[str]);}else{console.log.apply(console,arguments);}}}
function stateDescription(state){switch(state){case-1:return"UNLOADED";case 0:return"LOADED";case 1:return"UNSTARTED";case 2:return"BUFFERING";case 3:return"PLAYING";case 4:return"PAUSED";case 5:return"ENDED";}
return"UNKOWN";}
function actionAllowed(eventName){var ret=$f.fireEvent(self.id(),"onBefore"+eventName,activeIndex);return ret!==false;}
function stopEvent(e){e.stopPropagation();e.preventDefault();return false;}
function setState(state,force){if(currentState==STATE_UNLOADED&&!force)
return;previousState=currentState;currentState=state;stopPlayTimeTracker();if(state==STATE_PLAYING)
startPlayTimeTracker();log(stateDescription(state));}
function resetState(){video.fp_stop();onStartFired=false;stopping=false;playAfterSeek=false;setState(STATE_UNSTARTED);setState(STATE_UNSTARTED);}
var _playTimeTracker=null;function startPlayTimeTracker(){if(_playTimeTracker)
return;console.log("starting tracker");_playTimeTracker=setInterval(onTimeTracked,100);onTimeTracked();}
function stopPlayTimeTracker(){clearInterval(_playTimeTracker);_playTimeTracker=null;}
function onTimeTracked(){var currentTime=Math.floor(video.fp_getTime()*10)*100;var duration=Math.floor(video.duration*10)*100;var fireTime=(new Date()).time;function fireCuePointsIfNeeded(time,cues){time=time>=0?time:duration-Math.abs(time);for(var i=0;i<cues.length;i++){if(cues[i].lastTimeFired>fireTime){cues[i].lastTimeFired=-1;}else if(cues[i].lastTimeFired+500>fireTime){continue;}else{if(time==currentTime||(currentTime-500<time&&currentTime>time)){cues[i].lastTimeFired=fireTime;$f.fireEvent(self.id(),'onCuepoint',activeIndex,cues[i].fnId,cues[i].parameters);}}}}
$f.each(self.getCommonClip()._cuepoints,fireCuePointsIfNeeded);$f.each(activePlaylist[activeIndex]._cuepoints,fireCuePointsIfNeeded);}
function replay(){resetState();playAfterSeek=true;video.fp_seek(0);}
function scaleVideo(clip){}
function addAPI(){function fixClip(clip){var extendedClip={};extend(extendedClip,clipDefaults);extend(extendedClip,self.getCommonClip());extend(extendedClip,clip);if(extendedClip.ipadUrl)
url=decodeURIComponent(extendedClip.ipadUrl);else if(extendedClip.url)
url=extendedClip.url;if(url&&url.indexOf('://')==-1&&extendedClip.baseUrl)
url=extendedClip.baseUrl+'/'+url;extendedClip.originalUrl=extendedClip.url;extendedClip.completeUrl=url;extendedClip.extension=extendedClip.completeUrl.substr(extendedClip.completeUrl.lastIndexOf('.'));extendedClip.type='video';delete extendedClip.index;log("fixed clip",extendedClip);return extendedClip;}
video.fp_play=function(clip,inStream,forcePlay){var url=null;var autoBuffering=true;var autoPlay=true;log("Calling play() "+clip,clip);if(inStream){log("ERROR: inStream clips not yet supported");return;}
if(clip!==undefined){if(typeof clip=="number"){if(activeIndex>=activePlaylist.length)
return;activeIndex=clip;clip=activePlaylist[activeIndex];}else{if(typeof clip=="string"){clip={url:clip};}
video.fp_setPlaylist(clip.length!==undefined?clip:[clip]);}
if(!opts.validExtensions.test(activePlaylist[activeIndex].extension)){if(activePlaylist.length>1&&activeIndex<(activePlaylist.length-1)){log("Not last clip in the playlist, moving to next one");video.fp_play(++activeIndex,false,true);}
return;}
clip=activePlaylist[activeIndex];url=clip.completeUrl;if(clip.autoBuffering!==undefined&&clip.autoBuffering===false)
autoBuffering=false;if(clip.autoPlay===undefined||clip.autoPlay===true||forcePlay===true){autoBuffering=true;autoPlay=true;}else{autoPlay=false;}}else{log("clip was not given, simply calling video.play, if not already buffering");if(currentState!=STATE_BUFFERING)
video.play();return;}
log("about to play "+url,autoBuffering,autoPlay);resetState();if(url){log("Changing SRC attribute"+url);video.setAttribute('src',url);}
if(autoBuffering){if(!actionAllowed('Begin'))
return false;$f.fireEvent(self.id(),'onBegin',activeIndex);log("calling video.load()");video.load();}
if(autoPlay){log("calling video.play()");video.play();}}
video.fp_pause=function(){log("pause called");if(!actionAllowed('Pause'))
return false;video.pause();};video.fp_resume=function(){log("resume called");if(!actionAllowed('Resume'))
return false;video.play();};video.fp_stop=function(){log("stop called");if(!actionAllowed('Stop'))
return false;stopping=true;video.pause();try{video.currentTime=0;}catch(ignored){}};video.fp_seek=function(position){log("seek called "+position);if(!actionAllowed('Seek'))
return false;var seconds=0;var position=position+"";if(position.charAt(position.length-1)=='%'){var percentage=parseInt(position.substr(0,position.length-1))/100;var duration=video.duration;seconds=duration*percentage;}else{seconds=position;}
try{video.currentTime=seconds;}catch(e){log("Wrong seek time");}};video.fp_getTime=function(){return video.currentTime;};video.fp_mute=function(){log("mute called");if(!actionAllowed('Mute'))
return false;currentVolume=video.volume;video.volume=0;};video.fp_unmute=function(){if(!actionAllowed('Unmute'))
return false;video.volume=currentVolume;};video.fp_getVolume=function(){return video.volume*100;};video.fp_setVolume=function(volume){if(!actionAllowed('Volume'))
return false;video.volume=volume/100;};video.fp_toggle=function(){log('toggle called');if(self.getState()==STATE_ENDED){replay();return;}
if(video.paused)
video.fp_play();else
video.fp_pause();};video.fp_isPaused=function(){return video.paused;};video.fp_isPlaying=function(){return!video.paused;};video.fp_getPlugin=function(name){if(name=='canvas'||name=='controls'){var config=self.getConfig();return config['plugins']&&config['plugins'][name]?config['plugins'][name]:null;}
log("ERROR: no support for "+name+" plugin on iDevices");return null;};video.fp_close=function(){setState(STATE_UNLOADED);video.parentNode.removeChild(video);video=null;};video.fp_getStatus=function(){var bufferStart=0;var bufferEnd=0;try{bufferStart=video.buffered.start();bufferEnd=video.buffered.end();}catch(ignored){}
return{bufferStart:bufferStart,bufferEnd:bufferEnd,state:currentState,time:video.fp_getTime(),muted:video.muted,volume:video.fp_getVolume()};};video.fp_getState=function(){return currentState;};video.fp_startBuffering=function(){if(currentState==STATE_UNSTARTED)
video.load();};video.fp_setPlaylist=function(playlist){log("Setting playlist");activeIndex=0;for(var i=0;i<playlist.length;i++)
playlist[i]=fixClip(playlist[i]);activePlaylist=playlist;$f.fireEvent(self.id(),'onPlaylistReplace',playlist);};video.fp_addClip=function(clip,index){clip=fixClip(clip);activePlaylist.splice(index,0,clip);$f.fireEvent(self.id(),'onClipAdd',clip,index);};video.fp_updateClip=function(clip,index){extend(activePlaylist[index],clip);return activePlaylist[index];};video.fp_getVersion=function(){return'3.2.3';}
video.fp_isFullscreen=function(){return false;}
video.fp_toggleFullscreen=function(){if(video.fp_isFullscreen())
video.webkitExitFullscreen();else
video.webkitEnterFullscreen();}
video.fp_addCuepoints=function(points,index,fnId){var clip=index==-1?self.getCommonClip():activePlaylist[index];clip._cuepoints=clip._cuepoints||{};points=points instanceof Array?points:[points];for(var i=0;i<points.length;i++){var time=typeof points[i]=="object"?(points[i]['time']||null):points[i];if(time==null)continue;time=Math.floor(time/100)*100;var parameters=time;if(typeof points[i]=="object"){parameters=extend({},points[i],false);if(parameters['time']!=undefined)delete parameters['time'];if(parameters['parameters']!=undefined){extend(parameters,parameters['parameters'],false);delete parameters['parameters'];}}
clip._cuepoints[time]=clip._cuepoints[time]||[];clip._cuepoints[time].push({fnId:fnId,lastTimeFired:-1,parameters:parameters});}}
$f.each(("toggleFullscreen,stopBuffering,reset,playFeed,setKeyboardShortcutsEnabled,isKeyboardShortcutsEnabled,css,animate,showPlugin,hidePlugin,togglePlugin,fadeTo,invoke,loadPlugin").split(","),function(){var name=this;video["fp_"+name]=function(){log("ERROR: unsupported API on iDevices "+name);return false;};});}
function addListeners(){var events=['abort','canplay','canplaythrough','durationchange','emptied','ended','error','loadeddata','loadedmetadata','loadstart','pause','play','playing','progress','ratechange','seeked','seeking','stalled','suspend','volumechange','waiting'];var eventsLogger=function(e){log("Got event "+e.type,e);}
for(var i=0;i<events.length;i++)
video.addEventListener(events[i],eventsLogger,false);var onBufferEmpty=function(e){log("got onBufferEmpty event "+e.type)
setState(STATE_BUFFERING);$f.fireEvent(self.id(),'onBufferEmpty',activeIndex);};video.addEventListener('emptied',onBufferEmpty,false);video.addEventListener('waiting',onBufferEmpty,false);var onBufferFull=function(e){if(previousState==STATE_UNSTARTED||previousState==STATE_BUFFERING){}else{log("Restoring old state "+stateDescription(previousState));setState(previousState);}
$f.fireEvent(self.id(),'onBufferFull',activeIndex);};video.addEventListener('canplay',onBufferFull,false);video.addEventListener('canplaythrough',onBufferFull,false);var onMetaData=function(e){video.fp_updateClip({duration:video.duration,metaData:{duration:video.duration}},activeIndex);activePlaylist[activeIndex].duration=video.duration;$f.fireEvent(self.id(),'onMetaData',activeIndex,activePlaylist[activeIndex]);};video.addEventListener('loadedmetadata',onMetaData,false);video.addEventListener('durationchange',onMetaData,false);var onStart=function(e){if(currentState==STATE_PAUSED){if(!actionAllowed('Resume')){log("Resume disallowed, pausing");video.fp_pause();return stopEvent(e);}
$f.fireEvent(self.id(),'onResume',activeIndex);}
setState(STATE_PLAYING);if(!onStartFired){onStartFired=true;$f.fireEvent(self.id(),'onStart',activeIndex);}};video.addEventListener('playing',onStart,false);var onFinish=function(e){if(!actionAllowed('Finish')){if(activePlaylist.length==1){log("Active playlist only has one clip, onBeforeFinish returned false. Replaying");replay();}else if(activeIndex!=(activePlaylist.length-1)){log("Not the last clip in the playlist, but onBeforeFinish returned false. Returning to the beginning of current clip");video.fp_seek(0);}else{log("Last clip in playlist, but onBeforeFinish returned false, start again from the beginning");video.fp_play(0);}
return stopEvent(e);}
setState(STATE_ENDED);$f.fireEvent(self.id(),'onFinish',activeIndex);if(activePlaylist.length>1&&activeIndex<(activePlaylist.length-1)){log("Not last clip in the playlist, moving to next one");video.fp_play(++activeIndex,false,true);}};video.addEventListener('ended',onFinish,false);var onError=function(e){setState(STATE_LOADED,true);$f.fireEvent(self.id(),'onError',activeIndex,201);if(opts.onFail&&opts.onFail instanceof Function)
opts.onFail.apply(self,[]);};video.addEventListener('error',onError,false);var onPause=function(e){log("got pause event from player"+self.id());if(stopping)
return;if(currentState==STATE_BUFFERING&&previousState==STATE_UNSTARTED){log("forcing play");setTimeout(function(){video.play();},0);return;}
if(!actionAllowed('Pause')){video.fp_resume();return stopEvent(e);}
setState(STATE_PAUSED);$f.fireEvent(self.id(),'onPause',activeIndex);}
video.addEventListener('pause',onPause,false);var onSeek=function(e){$f.fireEvent(self.id(),'onBeforeSeek',activeIndex);};video.addEventListener('seeking',onSeek,false);var onSeekDone=function(e){if(stopping){stopping=false;$f.fireEvent(self.id(),'onStop',activeIndex);}
else
$f.fireEvent(self.id(),'onSeek',activeIndex);log("seek done, currentState",stateDescription(currentState));if(playAfterSeek){playAfterSeek=false;video.fp_play();}else if(currentState!=STATE_PLAYING)
video.fp_pause();};video.addEventListener('seeked',onSeekDone,false);var onVolumeChange=function(e){$f.fireEvent(self.id(),'onVolume',video.fp_getVolume());};video.addEventListener('volumechange',onVolumeChange,false);}
function onPlayerLoaded(){video.fp_play(0);}
function installControlbar(){}
if(isiDevice||opts.simulateiDevice){if(!window.flashembed.__replaced){var realFlashembed=window.flashembed;window.flashembed=function(root,opts,conf){if(typeof root=='string'){root=document.getElementById(root.replace("#",""));}
if(!root){return;}
var style=window.getComputedStyle(root,null);var width=parseInt(style.width);var height=parseInt(style.height);while(root.firstChild)
root.removeChild(root.firstChild);var container=document.createElement('div');var api=document.createElement('video');container.appendChild(api);root.appendChild(container);container.style.height=height+'px';container.style.width=width+'px';container.style.display='block';container.style.position='relative';container.style.background='-webkit-gradient(linear, left top, left bottom, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0.7)))';container.style.cursor='default';container.style.webkitUserDrag='none';api.style.height='100%';api.style.width='100%';api.style.display='block';api.id=opts.id;api.name=opts.id;api.style.cursor='pointer';api.style.webkitUserDrag='none';api.type="video/mp4";api.playerConfig=conf.config;$f.fireEvent(conf.config.playerId,'onLoad','player');};flashembed.getVersion=realFlashembed.getVersion;flashembed.asString=realFlashembed.asString;flashembed.isSupported=function(){return true;}
flashembed.__replaced=true;}
var __fireEvent=self._fireEvent;self._fireEvent=function(a){if(a[0]=='onLoad'&&a[1]=='player'){video=self.getParent().querySelector('video');if(opts.controls)
video.controls="controls";addAPI();addListeners();setState(STATE_LOADED,true);video.fp_setPlaylist(video.playerConfig.playlist);onPlayerLoaded();__fireEvent.apply(self,[a]);}
var shouldFireEvent=currentState!=STATE_UNLOADED;if(currentState==STATE_UNLOADED&&typeof a=='string')
shouldFireEvent=true;if(shouldFireEvent)
return __fireEvent.apply(self,[a]);}
self._swfHeight=function(){return parseInt(video.style.height);}
self.hasiPadSupport=function(){return true;}}
return self;});

Binary file not shown.

Binary file not shown.

View File

@ -48,7 +48,7 @@
var content = "";
if (mimeType[1] == "application/json") {
data = JSON.parse(data);
content = unescape(data.html);
content = data.html;
} else {
content = data;
}
@ -160,7 +160,7 @@
}
if (data.html) {
$("#g-dialog").html(unescape(data.html));
$("#g-dialog").html(data.html);
$("#g-dialog").dialog("option", "position", "center");
$("#g-dialog form :submit").removeClass("ui-state-disabled")
.attr("disabled", null);

View File

@ -48,7 +48,7 @@
var content = "";
if (mimeType[1] == "application/json") {
data = JSON.parse(data);
content = unescape(data.html);
content = data.html;
} else {
content = data;
}

View File

@ -20,7 +20,7 @@
image_size = $.gallery_auto_fit_window(image_width, image_height);
} else {
image_size = {
top: Math.round((height - image_height) / 2),
top: 12,
left: Math.round((width - image_width) / 2),
width: Math.round(image_width),
height: Math.round(image_height)

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

2
lib/jquery-ui.js vendored
View File

@ -18,7 +18,7 @@ this.started=false;},_mouseDestroy:function(){this.element.unbind('.'+this.widge
(this._mouseStarted&&this._mouseUp(event));this._mouseDownEvent=event;var self=this,btnIsLeft=(event.which==1),elIsCancel=(typeof this.options.cancel=="string"?$(event.target).parents().add(event.target).filter(this.options.cancel).length:false);if(!btnIsLeft||elIsCancel||!this._mouseCapture(event)){return true;}
this.mouseDelayMet=!this.options.delay;if(!this.mouseDelayMet){this._mouseDelayTimer=setTimeout(function(){self.mouseDelayMet=true;},this.options.delay);}
if(this._mouseDistanceMet(event)&&this._mouseDelayMet(event)){this._mouseStarted=(this._mouseStart(event)!==false);if(!this._mouseStarted){event.preventDefault();return true;}}
this._mouseMoveDelegate=function(event){return self._mouseMove(event);};this._mouseUpDelegate=function(event){return self._mouseUp(event);};$(document).bind('mousemove.'+this.widgetName,this._mouseMoveDelegate).bind('mouseup.'+this.widgetName,this._mouseUpDelegate);($.browser.safari||event.preventDefault());event.originalEvent.mouseHandled=true;return true;},_mouseMove:function(event){if($.browser.msie&&!event.button){return this._mouseUp(event);}
this._mouseMoveDelegate=function(event){return self._mouseMove(event);};this._mouseUpDelegate=function(event){return self._mouseUp(event);};$(document).bind('mousemove.'+this.widgetName,this._mouseMoveDelegate).bind('mouseup.'+this.widgetName,this._mouseUpDelegate);($.browser.safari||event.preventDefault());event.originalEvent.mouseHandled=true;return true;},_mouseMove:function(event){if($.browser.msie&&!(document.documentMode>=9)&&!event.button){return this._mouseUp(event);}
if(this._mouseStarted){this._mouseDrag(event);return event.preventDefault();}
if(this._mouseDistanceMet(event)&&this._mouseDelayMet(event)){this._mouseStarted=(this._mouseStart(this._mouseDownEvent,event)!==false);(this._mouseStarted?this._mouseDrag(event):this._mouseUp(event));}
return!this._mouseStarted;},_mouseUp:function(event){$(document).unbind('mousemove.'+this.widgetName,this._mouseMoveDelegate).unbind('mouseup.'+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted=false;this._preventClickEvent=(event.target==this._mouseDownEvent.target);this._mouseStop(event);}

View File

@ -1,3 +1,7 @@
name = "Akismet"
description = "Filter comments through the Akismet web service to detect and eliminate spam (http://akismet.com). You'll need a WordPress.com API key to use it."
version = 1
author_name = "Gallery Team"
author_url = "http://codex.gallery2.org/Gallery:Team"
info_url = "http://codex.gallery2.org/Gallery3:Modules:akismet"
discuss_url = "http://gallery.menalto.com/forum_module_akismet"

View File

@ -28,8 +28,10 @@ class Admin_Manage_Comments_Controller extends Admin_Controller {
->where("updated", "<", db::expr("UNIX_TIMESTAMP() - 86400 * 7"))
->execute();
// Redirect to the appropriate queue
url::redirect("admin/manage_comments/queue/unpublished");
$view = new Admin_View("admin.html");
$view->content = new View("admin_manage_comments.html");
$view->content->menu = $this->_menu($this->_counts());
print $view;
}
public function menu_labels() {
@ -43,25 +45,32 @@ class Admin_Manage_Comments_Controller extends Admin_Controller {
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")
$view = new Gallery_View("admin_manage_comments_queue.html");
$view->counts = $this->_counts();
$view->menu = $this->_menu($view->counts);
$view->state = $state;
$view->comments = ORM::factory("comment")
->order_by("created", "DESC")
->order_by("id", "DESC")
->where("state", "=", $state)
->limit(self::$items_per_page)
->offset(($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"));
// This view is not themed so we can't use $theme->url() in the view and have to
// reproduce Gallery_View::url() logic here.
$atn = theme::$admin_theme_name;
$view->fallback_avatar_url = url::abs_file("themes/$atn/images/avatar.jpg");
$view->page = $page;
$view->page_type = "collection";
$view->page_subtype = "admin_comments";
$view->page_size = self::$items_per_page;
$view->children_count = $this->_counts()->$state;
$view->max_pages = ceil($view->children_count / $view->page_size);
// Also we want to use $theme->paginator() so we need a dummy theme
$view->theme = $view;
print $view;
}

View File

@ -37,8 +37,8 @@ class comment_installer {
`server_http_referer` varchar(255) default NULL,
`server_http_user_agent` varchar(128) default NULL,
`server_query_string` varchar(64) default NULL,
`server_remote_addr` varchar(32) default NULL,
`server_remote_host` varchar(64) default NULL,
`server_remote_addr` varchar(40) default NULL,
`server_remote_host` varchar(255) default NULL,
`server_remote_port` varchar(16) default NULL,
`state` varchar(15) default 'unpublished',
`text` text,
@ -48,7 +48,7 @@ class comment_installer {
module::set_var("comment", "spam_caught", 0);
module::set_var("comment", "access_permissions", "everybody");
module::set_version("comment", 3);
module::set_version("comment", 4);
}
static function upgrade($version) {
@ -62,6 +62,19 @@ class comment_installer {
module::set_var("comment", "access_permissions", "everybody");
module::set_version("comment", $version = 3);
}
if ($version == 3) {
// 40 bytes for server_remote_addr is enough to swallow the longest
// representation of an IPv6 addy.
//
// 255 bytes for server_remote_host is enough to swallow the longest
// legit DNS entry, with a few bytes to spare.
$db->query(
"ALTER TABLE {comments} CHANGE `server_remote_addr` `server_remote_addr` varchar(40)");
$db->query(
"ALTER TABLE {comments} CHANGE `server_remote_host` `server_remote_host` varchar(255)");
module::set_version("comment", $version = 4);
}
}
static function uninstall() {

View File

@ -98,8 +98,8 @@ class Comment_Model_Core extends ORM {
$this->server_http_referer = substr($input->server("HTTP_REFERER"), 0, 255);
$this->server_http_user_agent = substr($input->server("HTTP_USER_AGENT"), 0, 128);
$this->server_query_string = substr($input->server("QUERY_STRING"), 0, 64);
$this->server_remote_addr = substr($input->server("REMOTE_ADDR"), 0, 32);
$this->server_remote_host = substr($input->server("REMOTE_HOST"), 0, 64);
$this->server_remote_addr = substr($input->server("REMOTE_ADDR"), 0, 40);
$this->server_remote_host = substr($input->server("REMOTE_HOST"), 0, 255);
$this->server_remote_port = substr($input->server("REMOTE_PORT"), 0, 16);
}

View File

@ -1,3 +1,7 @@
name = "Comments"
description = "Allows users and guests to leave comments on photos and albums."
version = 3
version = 4
author_name = "Gallery Team"
author_url = "http://codex.gallery2.org/Gallery:Team"
info_url = "http://codex.gallery2.org/Gallery3:Modules:comment"
discuss_url = "http://gallery.menalto.com/forum_module_comment"

View File

@ -2,200 +2,45 @@
<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),
var set_state = function(state, id) {
$("#g-comment-" + id).fadeOut("fast", function() {
$.get(set_state_url.replace("__STATE__", state).replace("__ID__", id),
{},
function() {
$("#g-comment-" + id).slideUp();
update_menu();
});
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() {
var update_menu = function() {
$.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]);
$("#g-admin-comments ul li:eq(" + i + ") a").html(data[i]);
}
},
"json");
}
// Paginator clicks load their href in the active tab panel
var fix_links = function() {
$(".g-paginator a, a#g-delete-all-spam").click(function(event) {
event.stopPropagation();
$.scrollTo(0, 800, { easing: "swing" });
$(this).parents(".ui-tabs-panel").load(
$(this).attr("href"),
function() {
fix_links();
});
return false;
});
}
$(document).ready(function() {
$("#g-admin-comments").tabs({
show: fix_links,
});
});
</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>
<?= $menu->render() ?>
</div>

View File

@ -0,0 +1,157 @@
<?php defined("SYSPATH") or die("No direct script access.") ?>
<div class="g-block-content">
<? 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 id="g-delete-all-spam"
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 ?>
<div class="g-paginator">
<?= $theme->paginator() ?>
</div>
<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, $fallback_avatar_url) ?>"
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" && $comment->state != "deleted"): ?>
<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>
<? if ($state == "deleted"): ?>
<?= t("Undelete") ?>
<? else: ?>
<?= t("Approve") ?>
<? endif ?>
</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>
-->
<? if ($comment->state != "deleted"): ?>
<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>
<? endif ?>
</ul>
</td>
</tr>
<? endforeach ?>
</table>
<div class="g-paginator">
<?= $theme->paginator() ?>
</div>
</div>

View File

@ -33,8 +33,8 @@ class Digibug_Controller extends Controller {
$proxy->uuid = random::hash();
$proxy->item_id = $item->id;
$proxy->save();
$full_url = url::abs_site("digibug/print_proxy/full/$proxy->uuid");
$thumb_url = url::abs_site("digibug/print_proxy/thumb/$proxy->uuid");
$full_url = url::abs_site("digibug/print_proxy/full/$proxy->uuid/$item->id");
$thumb_url = url::abs_site("digibug/print_proxy/thumb/$proxy->uuid/$item->id");
}
$v = new View("digibug_form.html");
@ -114,7 +114,7 @@ class Digibug_Controller extends Controller {
private function _clean_expired() {
db::build()
->delete("digibug_proxies")
->where("request_date", "<=", db::expr("(CURDATE() - INTERVAL 10 DAY)"))
->where("request_date", "<=", db::expr("(CURDATE() - INTERVAL 90 DAY)"))
->limit(20)
->execute();
}

View File

@ -1,3 +1,7 @@
name = "Digibug"
description = "Digibug Photo Printing Module"
version = 2
author_name = "Gallery Team"
author_url = "http://codex.gallery2.org/Gallery:Team"
info_url = "http://codex.gallery2.org/Gallery3:Modules:digibug"
discuss_url = "http://gallery.menalto.com/forum_module_digibug"

View File

@ -36,10 +36,7 @@ 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, "ISO-8859-1, UTF-8") != "UTF-8") {
$value = utf8_encode($value);
}
$value = encoding::convert_to_utf8($value);
$keys[$field] = Input::clean($value);
if ($field == "DateTime") {
@ -60,10 +57,7 @@ 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, "ISO-8859-1, UTF-8") != "UTF-8") {
$value = utf8_encode($value);
}
$value = encoding::convert_to_utf8($value);
$keys[$keyword] = Input::clean($value);
if ($keyword == "Caption" && !$item->description) {

View File

@ -24,6 +24,12 @@ class exif_event_Core {
}
}
static function item_updated_data_file($item) {
if (!$item->is_album()) {
exif::extract($item);
}
}
static function item_deleted($item) {
db::build()
->delete("exif_records")

View File

@ -1,3 +1,7 @@
name = "Exif Data"
description = "Extract Exif data and display it on photo pages."
version = 1
author_name = "Gallery Team"
author_url = "http://codex.gallery2.org/Gallery:Team"
info_url = "http://codex.gallery2.org/Gallery3:Modules:exif"
discuss_url = "http://gallery.menalto.com/forum_module_exif"

View File

@ -24,23 +24,47 @@ class Admin_g2_import_Controller extends Admin_Controller {
g2_import::init();
}
if (class_exists("GalleryCoreApi")) {
$g2_stats = g2_import::stats();
$g2_sizes = g2_import::common_sizes();
}
$view = new Admin_View("admin.html");
$view->page_title = t("Gallery 2 import");
$view->content = new View("admin_g2_import.html");
if (class_exists("GalleryCoreApi")) {
$view->content->g2_stats = $g2_stats = g2_import::g2_stats();
$view->content->g3_stats = $g3_stats = g2_import::g3_stats();
$view->content->g2_sizes = g2_import::common_sizes();
$view->content->g2_version = g2_import::version();
// Don't count tags because we don't track them in g2_map
$view->content->g2_resource_count =
$g2_stats["users"] + $g2_stats["groups"] + $g2_stats["albums"] +
$g2_stats["photos"] + $g2_stats["movies"] + $g2_stats["comments"];
$view->content->g3_resource_count =
$g3_stats["user"] + $g3_stats["group"] + $g3_stats["album"] +
$g3_stats["item"] + $g3_stats["comment"] + $g3_stats["tag"];
}
$view->content->form = $this->_get_import_form();
$view->content->version = "";
$view->content->thumb_size = module::get_var("gallery", "thumb_size");
$view->content->resize_size = module::get_var("gallery", "resize_size");
if (g2_import::is_initialized()) {
$view->content->g2_stats = $g2_stats;
$view->content->g2_sizes = $g2_sizes;
$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();
if ((bool)ini_get("eaccelerator.enable") || (bool)ini_get("xcache.cacher")) {
message::warning(t("The eAccelerator and XCache PHP performance extensions are known to cause issues. If you're using either of those and are having problems, please disable them while you do your import. Add the following lines: <pre>%lines</pre> to gallery3/.htaccess and remove them when the import is done.", array("lines" => "\n\n php_value eaccelerator.enable 0\n php_value xcache.cacher off\n php_value xcache.optimizer off\n\n")));
}
foreach (array("notification", "search", "exif") as $module_id) {
if (module::is_active($module_id)) {
message::warning(
t("<a href=\"%url\">Deactivating</a> the <b>%module_id</b> module during your import will make it faster",
array("url" => url::site("admin/modules"), "module_id" => $module_id)));
}
}
if (module::is_active("akismet")) {
message::warning(
t("The Akismet module may mark some or all of your imported comments as spam. <a href=\"%url\">Deactivate</a> it to avoid that outcome.",
array("url" => url::site("admin/modules"))));
}
} else if (g2_import::is_configured()) {
$view->content->form->configure_g2_import->embed_path->add_error("invalid", 1);
}
@ -59,12 +83,12 @@ class Admin_g2_import_Controller extends Admin_Controller {
$embed_path = "$embed_path/embed.php";
}
if (g2_import::is_valid_embed_path($embed_path)) {
if (($g2_init_error = g2_import::is_valid_embed_path($embed_path)) == "ok") {
message::success(t("Gallery 2 path saved"));
module::set_var("g2_import", "embed_path", $embed_path);
url::redirect("admin/g2_import");
} else {
$form->configure_g2_import->embed_path->add_error("invalid", 1);
$form->configure_g2_import->embed_path->add_error($g2_init_error, 1);
}
}
@ -75,15 +99,37 @@ class Admin_g2_import_Controller extends Admin_Controller {
print $view;
}
public function autocomplete() {
$directories = array();
$path_prefix = Input::instance()->get("q");
foreach (glob("{$path_prefix}*") as $file) {
if (is_dir($file) && !is_link($file)) {
$directories[] = $file;
// If we find an embed.php, include it as well
if (file_exists("$file/embed.php")) {
$directories[] = "$file/embed.php";
}
}
}
print implode("\n", $directories);
}
private function _get_import_form() {
$embed_path = module::get_var("g2_import", "embed_path", "");
$form = new Forge(
"admin/g2_import/save", "", "post", array("id" => "g-admin-configure-g2-import-form"));
$group = $form->group("configure_g2_import")->label(t("Configure Gallery 2 Import"));
$group->input("embed_path")->label(t("Filesystem path to your Gallery 2 embed.php file"))
->value(module::get_var("g2_import", "embed_path", ""));
->value($embed_path);
$group->embed_path->error_messages(
"invalid", t("The path you entered is not a Gallery 2 installation."));
$group->submit("")->value(t("Save"));
$group->embed_path->error_messages(
"broken", t("Your Gallery 2 install isn't working properly. Please verify it!"));
$group->embed_path->error_messages(
"missing", t("The path you entered does not exist."));
$group->submit("")->value($embed_path ? t("Change") : t("Continue"));
return $form;
}
}

View File

@ -41,7 +41,9 @@ class G2_Controller extends Controller {
// (bbcode, embedding) people are using the id style URLs although URL rewriting is enabled.
$where = array(array("g2_id", "=", $id));
$view = $input->get("g2_view");
if ($view) {
if ($view == "core.DownloadItem") {
$where[] = array("resource_type", "IN", array("file", "resize", "thumbnail", "full"));
} else if ($view) {
$where[] = array("g2_url", "like", "%g2_view=$view%");
} // else: Assuming that the first search hit is sufficiently good.
} else if ($path) {

View File

@ -31,7 +31,7 @@ class g2_import_Core {
}
static function is_initialized() {
return g2_import::$init;
return g2_import::$init == "ok";
}
static function init() {
@ -52,146 +52,163 @@ class g2_import_Core {
if (file_exists($mod_path)) {
dir::unlink($mod_path);
}
return file_exists($embed_path) && g2_import::init_embed($embed_path);
return g2_import::init_embed($embed_path);
}
/**
* Initialize the embedded Gallery 2 instance. Call this before any other Gallery 2 calls.
*
* Return values:
* "ok" - the Gallery 2 install is fine
* "missing" - the embed path does not exist
* "invalid" - the install path is not a valid Gallery 2 code base
* "broken" - the embed path is correct, but the Gallery 2 install is broken
*/
static function init_embed($embed_path) {
if (!is_file($embed_path)) {
return false;
return "missing";
}
// Gallery 2 defines a class called Gallery. So does Gallery 3. They don't get along. So do
// a total hack here and copy over a few critical files (embed.php, main.php, bootstrap.inc
// and Gallery.class) and munge them so that we can rename the Gallery class to be
// G2_Gallery. Is this retarded? Why yes it is.
//
// Store the munged files in a directory that's the md5 hash of the embed path so that
// multiple import sources don't interfere with each other.
try {
// Gallery 2 defines a class called Gallery. So does Gallery 3. They don't get along. So do
// a total hack here and copy over a few critical files (embed.php, main.php, bootstrap.inc
// and Gallery.class) and munge them so that we can rename the Gallery class to be
// G2_Gallery. Is this retarded? Why yes it is.
//
// Store the munged files in a directory that's the md5 hash of the embed path so that
// multiple import sources don't interfere with each other.
$mod_path = VARPATH . "modules/g2_import/" . md5($embed_path);
if (!file_exists($mod_path) || !file_exists("$mod_path/embed.php")) {
@dir::unlink($mod_path);
mkdir($mod_path);
$mod_path = VARPATH . "modules/g2_import/" . md5($embed_path);
if (!file_exists($mod_path) || !file_exists("$mod_path/embed.php")) {
@dir::unlink($mod_path);
mkdir($mod_path);
$config_dir = dirname($embed_path);
if (filesize($embed_path) > 200) {
// Regular install
$base_dir = $config_dir;
} else {
// Multisite install. Line 2 of embed.php will be something like:
// require('/usr/home/bharat/public_html/gallery2/embed.php');
$lines = file($embed_path);
preg_match("#require\('(.*)/embed.php'\);#", $lines[2], $matches);
$base_dir = $matches[1];
$config_dir = dirname($embed_path);
if (filesize($embed_path) > 200) {
// Regular install
$base_dir = $config_dir;
} else {
// Multisite install. Line 2 of embed.php will be something like:
// require('/usr/home/bharat/public_html/gallery2/embed.php');
$lines = file($embed_path);
preg_match("#require\('(.*)/embed.php'\);#", $lines[2], $matches);
$base_dir = $matches[1];
}
file_put_contents(
"$mod_path/embed.php",
str_replace(
array(
"require_once(dirname(__FILE__) . '/modules/core/classes/GalleryDataCache.class');",
"require(dirname(__FILE__) . '/modules/core/classes/GalleryEmbed.class');"),
array(
"require_once('$base_dir/modules/core/classes/GalleryDataCache.class');",
"require('$base_dir/modules/core/classes/GalleryEmbed.class');"),
array_merge(
array("<?php defined(\"SYSPATH\") or die(\"No direct script access.\") ?>\n"),
file("$base_dir/embed.php"))));
file_put_contents(
"$mod_path/main.php",
str_replace(
array(
"include(dirname(__FILE__) . '/bootstrap.inc');",
"require_once(dirname(__FILE__) . '/init.inc');"),
array(
"include(dirname(__FILE__) . '/bootstrap.inc');",
"require_once('$base_dir/init.inc');"),
array_merge(
array("<?php defined(\"SYSPATH\") or die(\"No direct script access.\") ?>\n"),
file("$base_dir/main.php"))));
file_put_contents(
"$mod_path/bootstrap.inc",
str_replace(
array(
"require_once(dirname(__FILE__) . '/modules/core/classes/Gallery.class');",
"require_once(dirname(__FILE__) . '/modules/core/classes/GalleryDataCache.class');",
"define('GALLERY_CONFIG_DIR', dirname(__FILE__));",
"\$gallery =& new Gallery();",
"\$GLOBALS['gallery'] =& new Gallery();",
"\$gallery = new Gallery();"),
array(
"require_once(dirname(__FILE__) . '/Gallery.class');",
"require_once('$base_dir/modules/core/classes/GalleryDataCache.class');",
"define('GALLERY_CONFIG_DIR', '$config_dir');",
"\$gallery =& new G2_Gallery();",
"\$GLOBALS['gallery'] =& new G2_Gallery();",
"\$gallery = new G2_Gallery();"),
array_merge(
array("<?php defined(\"SYSPATH\") or die(\"No direct script access.\") ?>\n"),
file("$base_dir/bootstrap.inc"))));
file_put_contents(
"$mod_path/Gallery.class",
str_replace(
array("class Gallery",
"function Gallery"),
array("class G2_Gallery",
"function G2_Gallery"),
array_merge(
array("<?php defined(\"SYSPATH\") or die(\"No direct script access.\") ?>\n"),
file("$base_dir/modules/core/classes/Gallery.class"))));
} else {
// Ok, this is a good one. If you're running a bytecode accelerator and you move your
// Gallery install, these files sometimes get cached with the wrong path and then fail to
// load properly.
// Documented in https://sourceforge.net/apps/trac/gallery/ticket/1253
touch("$mod_path/embed.php");
touch("$mod_path/main.php");
touch("$mod_path/bootstrap.inc");
touch("$mod_path/Gallery.class.inc");
}
require("$mod_path/embed.php");
if (!class_exists("GalleryEmbed")) {
return "invalid";
}
file_put_contents(
"$mod_path/embed.php",
str_replace(
array(
"require_once(dirname(__FILE__) . '/modules/core/classes/GalleryDataCache.class');",
"require(dirname(__FILE__) . '/modules/core/classes/GalleryEmbed.class');"),
array(
"require_once('$base_dir/modules/core/classes/GalleryDataCache.class');",
"require('$base_dir/modules/core/classes/GalleryEmbed.class');"),
array_merge(array("<?php defined(\"SYSPATH\") or die(\"No direct script access.\") ?>\n"),
file("$base_dir/embed.php"))));
$ret = GalleryEmbed::init();
if ($ret) {
Kohana_Log::add("error", "Gallery 2 call failed with: " . $ret->getAsText());
return "broken";
}
file_put_contents(
"$mod_path/main.php",
str_replace(
array(
"include(dirname(__FILE__) . '/bootstrap.inc');",
"require_once(dirname(__FILE__) . '/init.inc');"),
array(
"include(dirname(__FILE__) . '/bootstrap.inc');",
"require_once('$base_dir/init.inc');"),
array_merge(array("<?php defined(\"SYSPATH\") or die(\"No direct script access.\") ?>\n"),
file("$base_dir/main.php"))));
$admin_group_id = g2(GalleryCoreApi::getPluginParameter("module", "core", "id.adminGroup"));
$admins = g2(GalleryCoreApi::fetchUsersForGroup($admin_group_id, 1));
$admin_id = current(array_flip($admins));
$admin = g2(GalleryCoreApi::loadEntitiesById($admin_id));
$GLOBALS["gallery"]->setActiveUser($admin);
file_put_contents(
"$mod_path/bootstrap.inc",
str_replace(
array("require_once(dirname(__FILE__) . '/modules/core/classes/Gallery.class');",
"require_once(dirname(__FILE__) . '/modules/core/classes/GalleryDataCache.class');",
"define('GALLERY_CONFIG_DIR', dirname(__FILE__));",
"\$gallery =& new Gallery();",
"\$GLOBALS['gallery'] =& new Gallery();",
"\$gallery = new Gallery();"),
array("require_once(dirname(__FILE__) . '/Gallery.class');",
"require_once('$base_dir/modules/core/classes/GalleryDataCache.class');",
"define('GALLERY_CONFIG_DIR', '$config_dir');",
"\$gallery =& new G2_Gallery();",
"\$GLOBALS['gallery'] =& new G2_Gallery();",
"\$gallery = new G2_Gallery();"),
array_merge(array("<?php defined(\"SYSPATH\") or die(\"No direct script access.\") ?>\n"),
file("$base_dir/bootstrap.inc"))));
file_put_contents(
"$mod_path/Gallery.class",
str_replace(
array("class Gallery",
"function Gallery"),
array("class G2_Gallery",
"function G2_Gallery"),
array_merge(array("<?php defined(\"SYSPATH\") or die(\"No direct script access.\") ?>\n"),
file("$base_dir/modules/core/classes/Gallery.class"))));
} else {
// Ok, this is a good one. If you're running a bytecode accelerator and you move your
// Gallery install, these files sometimes get cached with the wrong path and then fail to
// load properly.
// Documented in https://sourceforge.net/apps/trac/gallery/ticket/1253
touch("$mod_path/embed.php");
touch("$mod_path/main.php");
touch("$mod_path/bootstrap.inc");
touch("$mod_path/Gallery.class.inc");
}
require("$mod_path/embed.php");
if (!class_exists("GalleryEmbed")) {
return false;
}
$ret = GalleryEmbed::init();
if ($ret) {
Kohana_Log::add("error", "Gallery 2 call failed with: " . $ret->getAsText());
return false;
}
$admin_group_id = g2(GalleryCoreApi::getPluginParameter("module", "core", "id.adminGroup"));
$admins = g2(GalleryCoreApi::fetchUsersForGroup($admin_group_id, 1));
$admin_id = current(array_flip($admins));
$admin = g2(GalleryCoreApi::loadEntitiesById($admin_id));
$GLOBALS["gallery"]->setActiveUser($admin);
// Make sure we have an embed location so that embedded url generation comes out ok. Without
// this, the Gallery2 ModRewrite code won't try to do url generation.
$g2_embed_location =
g2(GalleryCoreApi::getPluginParameter("module", "rewrite", "modrewrite.embeddedLocation"));
if (empty($g2_embed_location)) {
// Make sure we have an embed location so that embedded url generation comes out ok. Without
// this, the Gallery2 ModRewrite code won't try to do url generation.
$g2_embed_location =
g2(GalleryCoreApi::getPluginParameter("module", "rewrite", "modrewrite.galleryLocation"));
g2(GalleryCoreApi::setPluginParameter(
"module", "rewrite", "modrewrite.embeddedLocation", $g2_embed_location));
g2($gallery->getStorage()->checkPoint());
g2(GalleryCoreApi::getPluginParameter("module", "rewrite", "modrewrite.embeddedLocation"));
if (empty($g2_embed_location)) {
$g2_embed_location =
g2(GalleryCoreApi::getPluginParameter("module", "rewrite", "modrewrite.galleryLocation"));
g2(GalleryCoreApi::setPluginParameter("module", "rewrite", "modrewrite.embeddedLocation",
$g2_embed_location));
g2($gallery->getStorage()->checkPoint());
}
if ($g2_embed_location) {
self::$g2_base_url = $g2_embed_location;
} else {
self::$g2_base_url = $GLOBALS["gallery"]->getUrlGenerator()->generateUrl(
array(),
array("forceSessionId" => false,
"htmlEntities" => false,
"urlEncode" => false,
"useAuthToken" => false));
}
} catch (ErrorException $e) {
Kohana_Log::add("error", $e->getMessage() . "\n" . $e->getTraceAsString());
return "broken";
}
if ($g2_embed_location) {
self::$g2_base_url = $g2_embed_location;
} else {
self::$g2_base_url = $GLOBALS["gallery"]->getUrlGenerator()->generateUrl(
array(),
array("forceSessionId" => false,
"htmlEntities" => false,
"urlEncode" => false,
"useAuthToken" => false));
}
return true;
return "ok";
}
/**
@ -219,7 +236,7 @@ class g2_import_Core {
* Return a set of statistics about the number of users, groups, albums, photos, movies and
* comments available for import from the Gallery 2 instance.
*/
static function stats() {
static function g2_stats() {
global $gallery;
$root_album_id = g2(GalleryCoreApi::getDefaultAlbumId());
$stats["users"] = g2(GalleryCoreApi::fetchUserCount());
@ -247,6 +264,25 @@ class g2_import_Core {
return $stats;
}
/**
* Return a set of statistics about the number of users, groups, albums, photos, movies and
* comments already imported into the Gallery 3 instance.
*/
static function g3_stats() {
$g3_stats = array(
"album" => 0, "comment" => 0, "item" => 0, "user" => 0, "group" => 0, "tag" => 0);
foreach (db::build()
->select("resource_type")
->select(array("C" => 'COUNT("*")'))
->from("g2_maps")
->where("resource_type", "IN", array("album", "comment", "item", "user", "group"))
->group_by("resource_type")
->execute() as $row) {
$g3_stats[$row->resource_type] = $row->C;
}
return $g3_stats;
}
/**
* Import a single group.
*/
@ -429,49 +465,8 @@ class g2_import_Core {
$album = ORM::factory("item");
$album->type = "album";
$album->parent_id = self::map($g2_album->getParentId());
$album->name = $g2_album->getPathComponent();
$album->title = self::_decode_html_special_chars($g2_album->getTitle());
$album->title or $album->title = $album->name;
$album->description = self::_decode_html_special_chars(self::extract_description($g2_album));
$album->owner_id = self::map($g2_album->getOwnerId());
try {
$album->view_count = (int) g2(GalleryCoreApi::fetchItemViewCount($g2_album_id));
} catch (Exception $e) {
// @todo log
$album->view_count = 0;
}
$album->created = $g2_album->getCreationTimestamp();
$order_map = array(
"originationTimestamp" => "captured",
"creationTimestamp" => "created",
"description" => "description",
"modificationTimestamp" => "updated",
"orderWeight" => "weight",
"pathComponent" => "name",
"summary" => "description",
"title" => "title",
"viewCount" => "view_count");
$direction_map = array(
1 => "ASC",
ORDER_ASCENDING => "ASC",
ORDER_DESCENDING => "DESC");
// 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];
}
g2_import::set_album_values($album, $g2_album);
try {
$album->save();
@ -493,18 +488,67 @@ class g2_import_Core {
self::_import_permissions($g2_album, $album);
}
/**
* Transfer over all the values from a G2 album to a G3 album.
*/
static function set_album_values($album, $g2_album) {
$album->name = $g2_album->getPathComponent();
$album->title = self::_decode_html_special_chars($g2_album->getTitle());
$album->title or $album->title = $album->name;
$album->description = self::_decode_html_special_chars(self::extract_description($g2_album));
$album->owner_id = self::map($g2_album->getOwnerId());
try {
$album->view_count = (int) g2(GalleryCoreApi::fetchItemViewCount($g2_album_id));
} catch (Exception $e) {
// @todo log
$album->view_count = 0;
}
$album->created = $g2_album->getCreationTimestamp();
$order_map = array(
"originationTimestamp" => "captured",
"creationTimestamp" => "created",
"description" => "description",
"modificationTimestamp" => "updated",
"orderWeight" => "weight",
"pathComponent" => "name",
"summary" => "description",
"title" => "title",
"viewCount" => "view_count");
$direction_map = array(
1 => "ASC",
ORDER_ASCENDING => "ASC",
ORDER_DESCENDING => "DESC");
// G2 sorts can either be <sort> or <presort>|<sort>. Right now we can't
// map presorts so ignore them.
$g2_order = explode("|", $g2_album->getOrderBy() . "");
$g2_order = end($g2_order);
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];
}
}
/**
* Set the highlight properly for a single album
*/
static function set_album_highlight(&$queue) {
// Dequeue the current album and enqueue its children
list($g2_album_id, $children) = each($queue);
if (empty($children)) {
return;
}
unset($queue[$g2_album_id]);
foreach ($children as $key => $value) {
$queue[$key] = $value;
if (!empty($children)) {
foreach ($children as $key => $value) {
$queue[$key] = $value;
}
}
$messages = array();
@ -516,7 +560,7 @@ class g2_import_Core {
$table = g2(GalleryCoreApi::fetchThumbnailsByItemIds(array($g2_album_id)));
if (isset($table[$g2_album_id])) {
// Backtrack the source id to an item
$g2_source = $table[$g2_album_id];
$orig_g2_source = $g2_source = $table[$g2_album_id];
while (GalleryUtilities::isA($g2_source, "GalleryDerivative")) {
$g2_source = g2(GalleryCoreApi::loadEntitiesById($g2_source->getDerivativeSourceId()));
}
@ -540,6 +584,11 @@ class g2_import_Core {
array("name" => $g3_album->name)),
$e);
}
self::set_map(
$orig_g2_source->getId(), $g3_album->id,
"thumbnail",
self::g2_url(array("view" => "core.DownloadItem", "itemId" => $orig_g2_source->getId())));
}
}
}
@ -610,7 +659,7 @@ class g2_import_Core {
if ($g2_preferred && $g2_preferred instanceof GalleryDerivative) {
if (preg_match("/rotate\|(-?\d+)/", $g2_preferred->getDerivativeOperations(), $matches)) {
$tmpfile = tempnam(TMPPATH, "rotate");
gallery_graphics::rotate($item->file_path(), $tmpfile, array("degrees" => $matches[1]));
gallery_graphics::rotate($item->file_path(), $tmpfile, array("degrees" => $matches[1]), $item);
$item->set_data_file($tmpfile);
$item->save();
unlink($tmpfile);
@ -859,9 +908,13 @@ class g2_import_Core {
array("id" => $g2_comment_id, "exception" => (string)$e));
}
if (self::map($g2_comment->getId())) {
// Already imported
return;
if ($id = self::map($g2_comment->getId())) {
if (ORM::factory("comment", $id)->loaded()) {
// Already imported and still exists
return;
}
// This comment was already imported, but now it no longer exists. Import it again, per
// ticket #1736.
}
$item_id = self::map($g2_comment->getParentId());
@ -899,10 +952,11 @@ class g2_import_Core {
self::set_map($g2_comment->getId(), $comment->id, "comment");
// Backdate the creation date. We can't do this at creation time because
// Comment_Model::save() will override it.
// Comment_Model::save() will override it. Leave the updated date alone
// so that if the comments get marked as spam, they don't immediately get
// flushed (see ticket #1736)
db::update("comments")
->set("created", $g2_comment->getDate())
->set("updated", $g2_comment->getDate())
->where("id", "=", $comment->id)
->execute();
}
@ -1243,6 +1297,7 @@ class g2_import_Core {
* Associate a Gallery 2 id with a Gallery 3 item id.
*/
static function set_map($g2_id, $g3_id, $resource_type, $g2_url=null) {
self::clear_map($g2_id, $resource_type);
$g2_map = ORM::factory("g2_map");
$g2_map->g3_id = $g3_id;
$g2_map->g2_id = $g2_id;
@ -1257,6 +1312,17 @@ class g2_import_Core {
self::$map[$g2_id] = $g3_id;
}
/**
* Remove all map entries associated with the given Gallery 2 id.
*/
static function clear_map($g2_id, $resource_type) {
db::build()
->delete("g2_maps")
->where("g2_id", "=", $g2_id)
->where("resource_type", "=", $resource_type)
->execute();
}
static function log($msg) {
message::warning($msg);
Kohana_Log::add("alert", $msg);

View File

@ -34,7 +34,7 @@ class g2_import_event_Core {
->get("settings_menu")
->append(Menu::factory("link")
->id("g2_import")
->label(t("Gallery 2 Import"))
->label(t("Gallery 2 import"))
->url(url::site("admin/g2_import")));
}
}

View File

@ -56,7 +56,7 @@ class g2_import_task_Core {
$mode = $task->get("mode");
$queue = $task->get("queue");
if (!isset($mode)) {
$stats = g2_import::stats();
$stats = g2_import::g2_stats();
$stats["items"] = $stats["photos"] + $stats["movies"];
unset($stats["photos"]);
unset($stats["movies"]);
@ -127,6 +127,12 @@ class g2_import_task_Core {
$g2_root_id = g2(GalleryCoreApi::getDefaultAlbumId());
$tree = g2(GalleryCoreApi::fetchAlbumTree());
$task->set("queue", $queue = array($g2_root_id => $tree));
// Update the root album to reflect the Gallery2 root album.
$root_album = item::root();
g2_import::set_album_values(
$root_album, g2(GalleryCoreApi::loadEntitiesById($g2_root_id)));
$root_album->save();
}
$log_message = g2_import::import_album($queue);
if ($log_message) {

View File

@ -1,3 +1,7 @@
name = "Gallery2 Import"
description = "Import your Gallery 2 content into Gallery 3"
version = 2
author_name = "Gallery Team"
author_url = "http://codex.gallery2.org/Gallery:Team"
info_url = "http://codex.gallery2.org/Gallery3:Modules:g2_import"
discuss_url = "http://gallery.menalto.com/forum_module_g2_import"

View File

@ -1,24 +1,64 @@
<?php defined("SYSPATH") or die("No direct script access.") ?>
<?= $theme->css("jquery.autocomplete.css") ?>
<?= $theme->script("jquery.autocomplete.js") ?>
<script type="text/javascript">
$("document").ready(function() {
$("form input[name=embed_path]").autocomplete(
"<?= url::site("__ARGS__") ?>".replace("__ARGS__", "admin/g2_import/autocomplete"),
{
max: 256,
loadingClass: "g-loading-small",
});
});
</script>
<div id="g-admin-g2-import" class="g-block">
<h1> <?= t("Gallery 2 import") ?> </h1>
<p>
<?= t("Import your Gallery 2 users, photos, movies, comments and tags into your new Gallery 3 installation.") ?>
</p>
<div class="g-block-content">
<?= $form ?>
</div>
<script type="text/javascript">
$(document).ready(function() {
$("#g-admin-g2-import-tabs").tabs()
<? if (!isset($g2_version)): ?>
.tabs("disable", 1)
.tabs("disable", 2)
<? elseif ($g3_resource_count > .9 * $g2_resource_count): ?>
.tabs("select", 2)
<? else: ?>
.tabs("select", 1)
<? endif ?>
;
<div class="g-block-content">
<? if (g2_import::is_initialized()): ?>
<div id="g-admin-g2-import-details">
<h2> <?= t("Import") ?> </h2>
<ul id="g-action-status" class="g-message-block">
<li class="g-success">
<?= t("Gallery version %version detected", array("version" => $version)) ?>
// Show the tabs after the page has loaded to prevent Firefox from rendering the
// unstyled page and then flashing.
$("#g-admin-g2-import-tabs").show();
});
</script>
<div id="g-admin-g2-import-tabs" class="g-block-content" style="display: none">
<ul>
<li>
<a href="#g-admin-g2-import-configure"><?= t("1. Configure Gallery2 path") ?></a>
</li>
<li>
<a href="#g-admin-g2-import-import"><?= t("2. Import!") ?></a>
</li>
<li>
<a href="#g-admin-g2-import-notes"><?= t("3. After your import") ?></a>
</li>
</ul>
<div id="g-admin-g2-import-configure" class="g-block-content">
<?= $form ?>
</div>
<div id="g-admin-g2-import-import">
<? if (isset($g2_version)): ?>
<ul>
<li>
<?= t("Gallery version %version detected", array("version" => $g2_version)) ?>
</li>
<? if ($g2_sizes["thumb"]["size"] && $thumb_size != $g2_sizes["thumb"]["size"]): ?>
<li class="g-warning">
<li>
<?= t("Your most common thumbnail size in Gallery 2 is %g2_pixels pixels, but your Gallery 3 thumbnail size is set to %g3_pixels pixels. <a href=\"%url\">Using the same value</a> will speed up your import.",
array("g2_pixels" => $g2_sizes["thumb"]["size"],
"g3_pixels" => $thumb_size,
@ -27,73 +67,84 @@
<? endif ?>
<? if ($g2_sizes["resize"]["size"] && $resize_size != $g2_sizes["resize"]["size"]): ?>
<li class="g-warning">
<li>
<?= t("Your most common intermediate size in Gallery 2 is %g2_pixels pixels, but your Gallery 3 intermediate size is set to %g3_pixels pixels. <a href=\"%url\">Using the same value</a> will speed up your import.",
array("g2_pixels" => $g2_sizes["resize"]["size"],
"g3_pixels" => $resize_size,
"url" => html::mark_clean(url::site("admin/theme_options")))) ?>
array("g2_pixels" => $g2_sizes["resize"]["size"],
"g3_pixels" => $resize_size,
"url" => html::mark_clean(url::site("admin/theme_options")))) ?>
</li>
<? endif ?>
<li class="g-info">
<?= t("Your Gallery 2 has the following importable data in it:") ?>
<p>
<?= t2("1 user", "%count users", $g2_stats["users"]) ?>,
<?= t2("1 group", "%count groups", $g2_stats["groups"]) ?>,
<?= t2("1 album", "%count albums", $g2_stats["albums"]) ?>,
<?= t2("1 photo", "%count photos", $g2_stats["photos"]) ?>,
<?= t2("1 movie", "%count movies", $g2_stats["movies"]) ?>,
<?= t2("1 comment", "%count comments", $g2_stats["comments"]) ?>,
<?= t2("1 tagged photo/movie/album",
"%count tagged photos/movies/albums", $g2_stats["tags"]) ?>
</p>
<li>
<?
$t = array();
$t[] = t2("1 user", "%count users", $g2_stats["users"]);
$t[] = t2("1 group", "%count groups", $g2_stats["groups"]);
$t[] = t2("1 album", "%count albums", $g2_stats["albums"]);
$t[] = t2("1 photo", "%count photos/movies", $g2_stats["photos"] + $g2_stats["movies"]);
$t[] = t2("1 comment", "%count comments", $g2_stats["comments"]);
$t[] = t2("1 tagged photo/movie/album", "%count tagged photos/movies/albums",
$g2_stats["tags"]);
?>
<?= t("Your Gallery 2 has the following importable data in it: %t0, %t1, %t2, %t3, %t4, %t5",
array("t0" => $t[0], "t1" => $t[1], "t2" => $t[2],
"t3" => $t[3], "t4" => $t[4], "t5" => $t[5])) ?>
</li>
</ul>
<? if ($g3_resource_count): ?>
<li>
<?
$t = array();
$t[] = t2("1 user", "%count users", $g3_stats["user"]);
$t[] = t2("1 group", "%count groups", $g3_stats["group"]);
$t[] = t2("1 album", "%count albums", $g3_stats["album"]);
$t[] = t2("1 photo/movie", "%count photos/movies", $g3_stats["item"]);
$t[] = t2("1 comment", "%count comments", $g3_stats["comment"]);
$t[] = t2("1 tagged photo/movie/album", "%count tagged photos/movies/albums", $g3_stats["tag"]);
?>
<?= t("It looks like you've imported the following Gallery 2 data already: %t0, %t1, %t2, %t3, %t4, %t5",
array("t0" => $t[0], "t1" => $t[1], "t2" => $t[2],
"t3" => $t[3], "t4" => $t[4], "t5" => $t[5])) ?>
</li>
<? endif ?>
</ul>
<p>
<a class="g-button g-dialog-link ui-state-default ui-corner-all"
href="<?= url::site("admin/maintenance/start/g2_import_task::import?csrf=$csrf") ?>">
<?= t("Begin import!") ?>
</a>
</p>
</div>
<div class="g-block-content">
<div id="g-admin-g2-import-notes">
<h2> <?= t("Notes") ?> </h2>
<ul class="enumeration">
<li>
<?= t("Gallery 3 does not support per-user / per-item permissions. <b>Review permissions after your import is done.</b>") ?>
</li>
<li>
<?= t("The only supported file formats are JPG, PNG and GIF, FLV and MP4. Other formats will be skipped.") ?>
</li>
<li>
<?= t("Deactivating the <b>notification</b>, <b>search</b> and <b>exif</b> modules during your import will make it go faster.") ?>
</li>
<li>
<?= t("The eAccelerator and XCache PHP performance extensions are known to cause issues. If you're using either of those and are having problems, please disable them while you do your import. Add the following lines: <pre>%lines</pre> to gallery3/.htaccess and remove them when the import is done.", array("lines" => "\n\n php_value eaccelerator.enable 0\n php_value xcache.cacher off\n php_value xcache.optimizer off\n\n")) ?>
</li>
</ul>
</div>
</div>
<div class="g-block-content">
<div>
<h2> <?= t("Migrating from Gallery 2") ?> </h2>
<p>
<?= t("Once your migration is complete, put this block at the top of your gallery2/.htaccess file and all Gallery 2 urls will be redirected to Gallery 3") ?>
</p>
<textarea rows="4" cols="60">&lt;IfModule mod_rewrite.c&gt;
Options +FollowSymLinks
RewriteEngine On
RewriteBase <?= html::clean(g2_import::$g2_base_url) ?>
RewriteRule ^(.*)$ <?= url::site("g2/map?path=\$1") ?> [QSA,L,R=301]
&lt;/IfModule&gt;</textarea>
</div>
<? endif ?>
</div>
<div id="g-admin-g2-import-notes" class="g-text">
<ul>
<li>
<?= t("Gallery 3 does not support per-user / per-item permissions. <b>Review permissions!</b>") ?>
</li>
<li>
<?= t("The only supported file formats are JPG, PNG and GIF, FLV and MP4. Other formats will be skipped.") ?>
</li>
<li>
<p>
<?= t("Redirecting Gallery 2 URLs once your migration is complete. Put this block at the top of your gallery2/.htaccess file and all Gallery 2 urls will be redirected to Gallery 3") ?>
</p>
<textarea id="g-g2-redirect-rules" rows="4" cols="60">&lt;IfModule mod_rewrite.c&gt;
Options +FollowSymLinks
RewriteEngine On
RewriteBase <?= html::clean(g2_import::$g2_base_url) ?>
RewriteRule ^(.*)$ <?= url::site("g2/map?path=\$1") ?> [QSA,L,R=301]
&lt;/IfModule&gt;</textarea>
<script type="text/javascript">
$(document).ready(function() {
$("#g-g2-redirect-rules").click(function(event) {
this.select();
});
});
</script>
</li>
</ul>
</div>
</div>
</div>

View File

@ -29,13 +29,14 @@
$config['language'] = array('en_US', 'English_United States');
/**
* Locale timezone. Defaults to use the server timezone.
* Locale timezone. Set in 'Advanced' settings, falling back to the server's zone.
* @see http://php.net/timezones
*/
$config['timezone'] = ini_get('date.timezone');
if (empty($config['timezone'])) {
// This is a required field. Pick something as a default.
$config['timezone'] = "America/Los_Angeles";
if (file_exists(VARPATH . "database.php")) {
$config['timezone'] = module::get_var("gallery", "timezone", date_default_timezone_get());
} else {
// Gallery3 is not installed yet -- don't make module::get_var() calls.
$config['timezone'] = date_default_timezone_get();
}
// i18n settings

View File

@ -19,6 +19,9 @@
*/
class Admin_Modules_Controller extends Admin_Controller {
public function index() {
// If modules need upgrading, this will get recreated in module::available()
site_status::clear("upgrade_now");
$view = new Admin_View("admin.html");
$view->page_title = t("Modules");
$view->content = new View("admin_modules.html");
@ -103,9 +106,6 @@ class Admin_Modules_Controller extends Admin_Controller {
module::event("module_change", $changes);
// If modules need upgrading, this will get recreated
site_status::clear("upgrade_now");
// @todo this type of collation is questionable from an i18n perspective
if ($activated_names) {
message::success(t("Activated: %names", array("names" => join(", ", $activated_names))));

View File

@ -59,6 +59,7 @@ class Admin_Theme_Options_Controller extends Admin_Controller {
module::set_var("gallery", "footer_text", $form->edit_theme->footer_text->value);
module::set_var("gallery", "show_credits", $form->edit_theme->show_credits->value);
module::set_var("gallery", "favicon_url", $form->edit_theme->favicon_url->value);
module::set_var("gallery", "apple_touch_icon_url", $form->edit_theme->apple_touch_icon_url->value);
module::event("theme_edit_form_completed", $form);
@ -77,8 +78,10 @@ class Admin_Theme_Options_Controller extends Admin_Controller {
$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")
->callback(array($this, "_valididate_page_size"))
->error_messages("required", t("You must enter a number"))
->error_messages("valid_digit", t("You must enter a number"))
->error_messages("valid_min_value", t("The value must be greater than zero"))
->value(module::get_var("gallery", "page_size"));
$group->input("thumb_size")->label(t("Thumbnail size (in pixels)"))->id("g-thumb-size")
->rules("required|valid_digit")
@ -93,6 +96,9 @@ class Admin_Theme_Options_Controller extends Admin_Controller {
$group->input("favicon_url")->label(t("URL (or relative path) to your favicon.ico"))
->id("g-favicon")
->value(module::get_var("gallery", "favicon_url"));
$group->input("apple_touch_icon_url")->label(t("URL (or relative path) to your Apple Touch icon"))
->id("g-apple-touch")
->value(module::get_var("gallery", "apple_touch_icon_url"));
$group->textarea("header_text")->label(t("Header text"))->id("g-header-text")
->value(module::get_var("gallery", "header_text"));
$group->textarea("footer_text")->label(t("Footer text"))->id("g-footer-text")
@ -102,9 +108,15 @@ class Admin_Theme_Options_Controller extends Admin_Controller {
module::event("theme_edit_form", $form);
$group = $form->group("buttons");
$group->submit("")->value(t("Save"));
return $form;
}
function _valididate_page_size($input) {
if ($input->value < 1) {
$input->add_error("valid_min_value", true);
}
}
}

View File

@ -25,6 +25,9 @@ class Admin_Themes_Controller extends Admin_Controller {
$view->content->admin = module::get_var("gallery", "active_admin_theme");
$view->content->site = module::get_var("gallery", "active_site_theme");
$view->content->themes = $this->_get_themes();
site_status::clear("missing_site_theme");
site_status::clear("missing_admin_theme");
print $view;
}

View File

@ -25,7 +25,7 @@ class Admin_Upgrade_Checker_Controller extends Admin_Controller {
if ($message) {
$message .= t(
" <a href=\"%hide-url\"><i>(remind me later)</i></a>",
array("url" => url::site("admin/upgrade_checker/remind_me_later?csrf=__CSRF__")));
array("hide-url" => url::site("admin/upgrade_checker/remind_me_later?csrf=__CSRF__")));
site_status::info($message, "upgrade_checker");
} else {
site_status::clear("upgrade_checker");

View File

@ -42,8 +42,9 @@ class Login_Controller extends Controller {
public function html() {
$view = new Theme_View("page.html", "other", "login");
$view->page_title = t("Login");
$view->content = auth::get_login_form("login/auth_html");
$view->page_title = t("Log in to Gallery");
$view->content = new View("login_ajax.html");
$view->content->form = auth::get_login_form("login/auth_html");
print $view;
}

View File

@ -36,9 +36,9 @@ class Quick_Controller extends Controller {
}
if ($degrees) {
$tmpfile = tempnam(TMPPATH, "rotate") . "." .
pathinfo($item->file_path(), PATHINFO_EXTENSION);
gallery_graphics::rotate($item->file_path(), $tmpfile, array("degrees" => $degrees));
$tmpfile = system::temp_filename("rotate",
pathinfo($item->file_path(), PATHINFO_EXTENSION));
gallery_graphics::rotate($item->file_path(), $tmpfile, array("degrees" => $degrees), $item);
$item->set_data_file($tmpfile);
$item->save();
unlink($tmpfile);

View File

@ -29,12 +29,12 @@
#g-add-photos-canvas object,
#g-add-photos-button {
left: 137px;
margin: .5em 0;
left: 90px;
margin: .5em 0;
padding: .4em 1em;
position: absolute;
top: 0;
width: 175px;
width: 300px;
}
#g-add-photos-canvas object {

View File

@ -37,4 +37,18 @@ class num extends num_Core {
return $val;
}
/**
* Convert a size value as accepted by PHP's shorthand to bytes.
* ref: http://us2.php.net/manual/en/function.ini-get.php
* ref: http://us2.php.net/manual/en/faq.using.php#faq.using.shorthandbytes
*/
static function convert_to_human_readable($num) {
foreach (array("G" => 1e9, "M" => 1e6, "K" => 1e3) as $k => $v) {
if ($num > $v) {
$num = round($num / $v) . $k;
}
}
return $num;
}
}

View File

@ -17,19 +17,16 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
class Pagination extends Pagination_Core {
public function render($style=NULL) {
// Hide single page pagination
if ($this->auto_hide === TRUE AND $this->total_pages <= 1) {
return "";
class encoding_Core {
static function convert_to_utf8($value) {
if (function_exists("mb_detect_encoding") &&
function_exists("mb_convert_encoding") &&
mb_detect_encoding($value, "ISO-8859-1, UTF-8") != "UTF-8") {
$value = mb_convert_encoding($value, "UTF-8", mb_detect_encoding($value));
} else if (function_exists("mb_detect_encoding") &&
mb_detect_encoding($value, "ISO-8859-1, UTF-8") != "UTF-8") {
$value = utf8_encode($value);
}
if ($style === NULL) {
// Use default style
$style = $this->style;
}
// Return rendered pagination view
return View::factory("pager.html", get_object_vars($this))->render();
return $value;
}
}
}

View File

@ -18,8 +18,8 @@
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
class gallery_Core {
const VERSION = "3.0.1";
const CODE_NAME = "Menlo Park";
const VERSION = "3.0.2";
const CODE_NAME = "Coollanta";
const RELEASE_CHANNEL = "release";
const RELEASE_BRANCH = "3.0.x";
@ -193,19 +193,25 @@ class gallery_Core {
*/
static function version_string() {
if (gallery::RELEASE_CHANNEL == "git") {
$build_number = gallery::build_number();
return sprintf(
"%s (branch %s build %s)", gallery::VERSION, gallery::RELEASE_BRANCH,
gallery::build_number());
"%s (branch %s, %s)", gallery::VERSION, gallery::RELEASE_BRANCH,
$build_number ? " build $build_number" : "unknown build number");
} else {
return sprintf("%s (%s)", gallery::VERSION, gallery::CODE_NAME);
}
}
/**
* Return the contents of the .build_number file, which should be a single integer.
* Return the contents of the .build_number file, which should be a single integer
* or return null if the .build_number file is missing.
*/
static function build_number() {
$result = parse_ini_file(DOCROOT . ".build_number");
return $result["build_number"];
$build_file = DOCROOT . ".build_number";
if (file_exists($build_file)) {
$result = parse_ini_file(DOCROOT . ".build_number");
return $result["build_number"];
}
return null;
}
}

View File

@ -82,9 +82,13 @@ class gallery_block_Core {
break;
case "block_adder":
$block->css_id = "g-block-adder";
$block->title = t("Dashboard content");
$block->content = gallery_block::get_add_block_form();
if ($form = gallery_block::get_add_block_form()) {
$block->css_id = "g-block-adder";
$block->title = t("Dashboard content");
$block->content = $form;
} else {
$block = "";
}
break;
case "language":
@ -112,16 +116,28 @@ class gallery_block_Core {
$block->content->version_info = upgrade_checker::version_info();
$block->content->auto_check_enabled = upgrade_checker::auto_check_enabled();
$block->content->new_version = upgrade_checker::get_upgrade_message();
$block->content->build_number = gallery::build_number();
}
return $block;
}
static function get_add_block_form() {
$available_blocks = block_manager::get_available_admin_blocks();
$active = array();
foreach (array_merge(block_manager::get_active("dashboard_sidebar"),
block_manager::get_active("dashboard_center")) as $b) {
unset($available_blocks[implode(":", $b)]);
}
if (!$available_blocks) {
return;
}
$form = new Forge("admin/dashboard/add_block", "", "post",
array("id" => "g-add-dashboard-block-form"));
$group = $form->group("add_block")->label(t("Add Block"));
$group->dropdown("id")->label(t("Available Blocks"))
->options(block_manager::get_available_admin_blocks());
$group->dropdown("id")->label(t("Available blocks"))->options($available_blocks);
$group->submit("center")->value(t("Add to center"));
$group->submit("sidebar")->value(t("Add to sidebar"));
return $form;

View File

@ -539,9 +539,9 @@ class gallery_event_Core {
$v = new View("user_profile_info.html");
$fields = array("name" => t("Name"), "locale" => t("Language Preference"),
"email" => t("Email"), "full_name" => t("Full name"), "url" => "Web site");
"email" => t("Email"), "full_name" => t("Full name"), "url" => t("Web site"));
if (!$data->user->guest) {
$fields = array("name" => t("Name"), "full_name" => t("Full name"), "url" => "Web site");
$fields = array("name" => t("Name"), "full_name" => t("Full name"), "url" => t("Web site"));
}
$v->user_profile_data = array();
foreach ($fields as $field => $label) {
@ -549,6 +549,8 @@ class gallery_event_Core {
$value = $data->user->$field;
if ($field == "locale") {
$value = locales::display_name($value);
} elseif ($field == "url") {
$value = html::mark_clean(html::anchor($data->user->$field));
}
$v->user_profile_data[(string) $label] = $value;
}

View File

@ -24,18 +24,19 @@ class gallery_graphics_Core {
* @param string $input_file
* @param string $output_file
* @param array $options
* @param Item_Model $item (optional)
*/
static function rotate($input_file, $output_file, $options) {
static function rotate($input_file, $output_file, $options, $item=null) {
graphics::init_toolkit();
module::event("graphics_rotate", $input_file, $output_file, $options);
module::event("graphics_rotate", $input_file, $output_file, $options, $item);
Image::factory($input_file)
->quality(module::get_var("gallery", "image_quality"))
->rotate($options["degrees"])
->save($output_file);
module::event("graphics_rotate_completed", $input_file, $output_file, $options);
module::event("graphics_rotate_completed", $input_file, $output_file, $options, $item);
}
/**
@ -45,11 +46,12 @@ class gallery_graphics_Core {
* @param string $input_file
* @param string $output_file
* @param array $options
* @param Item_Model $item (optional)
*/
static function resize($input_file, $output_file, $options) {
static function resize($input_file, $output_file, $options, $item=null) {
graphics::init_toolkit();
module::event("graphics_resize", $input_file, $output_file, $options);
module::event("graphics_resize", $input_file, $output_file, $options, $item);
if (@filesize($input_file) == 0) {
throw new Exception("@todo EMPTY_INPUT_FILE");
@ -69,7 +71,7 @@ class gallery_graphics_Core {
$image->save($output_file);
}
module::event("graphics_resize_completed", $input_file, $output_file, $options);
module::event("graphics_resize_completed", $input_file, $output_file, $options, $item);
}
/**
@ -86,12 +88,13 @@ class gallery_graphics_Core {
* @param string $input_file
* @param string $output_file
* @param array $options
* @param Item_Model $item (optional)
*/
static function composite($input_file, $output_file, $options) {
static function composite($input_file, $output_file, $options, $item=null) {
try {
graphics::init_toolkit();
module::event("graphics_composite", $input_file, $output_file, $options);
module::event("graphics_composite", $input_file, $output_file, $options, $item);
list ($width, $height) = getimagesize($input_file);
list ($w_width, $w_height) = getimagesize($options["file"]);
@ -121,7 +124,7 @@ class gallery_graphics_Core {
->quality(module::get_var("gallery", "image_quality"))
->save($output_file);
module::event("graphics_composite_completed", $input_file, $output_file, $options);
module::event("graphics_composite_completed", $input_file, $output_file, $options, $item);
} catch (ErrorException $e) {
Kohana_Log::add("error", $e->get_message());
}

View File

@ -304,14 +304,16 @@ class gallery_installer {
module::set_var("gallery", "maintenance_mode", 0);
module::set_var("gallery", "visible_title_length", 15);
module::set_var("gallery", "favicon_url", "lib/images/favicon.ico");
module::set_var("gallery", "apple_touch_icon_url", "lib/images/apple-touch-icon.png");
module::set_var("gallery", "email_from", "");
module::set_var("gallery", "email_reply_to", "");
module::set_var("gallery", "email_line_length", 70);
module::set_var("gallery", "email_header_separator", serialize("\n"));
module::set_var("gallery", "show_user_profiles_to", "registered_users");
module::set_var("gallery", "extra_binary_paths", "/usr/local/bin:/opt/local/bin:/opt/bin");
module::set_var("gallery", "timezone", null);
module::set_version("gallery", 46);
module::set_version("gallery", 49);
}
static function upgrade($version) {
@ -677,6 +679,19 @@ class gallery_installer {
module::set_var("gallery", "upgrade_checker_auto_enabled", true);
module::set_version("gallery", $version = 46);
}
if ($version == 46) {
module::set_var("gallery", "apple_touch_icon_url", "lib/images/apple-touch-icon.png");
module::set_version("gallery", $version = 47);
}
if ($version == 47 || $version == 48) {
// Add configuration variable to set timezone. Defaults to the currently
// used timezone (from PHP configuration). Note that in v48 we werew
// setting this value incorrectly, so we're going to stomp this value for v49.
module::set_var("gallery", "timezone", null);
module::set_version("gallery", $version = 49);
}
}
static function uninstall() {

View File

@ -64,7 +64,7 @@ class gallery_theme_Core {
if ($session->get("l10n_mode", false)) {
$buf .= $theme->css("l10n_client.css");
$buf .= $theme->script("jquery.cookie.js");
$buf .=$theme->script("l10n_client.js");
$buf .= $theme->script("l10n_client.js");
}
return $buf;
}

View File

@ -169,7 +169,7 @@ class graphics_Core {
}
foreach (self::_get_rules($target) as $rule) {
$args = array($working_file, $output_file, unserialize($rule->args));
$args = array($working_file, $output_file, unserialize($rule->args), $item);
call_user_func_array($rule->operation, $args);
$working_file = $output_file;
}
@ -316,10 +316,10 @@ class graphics_Core {
// ImageMagick & GraphicsMagick
$magick_kits = array(
"imagemagick" => array(
"name" => "ImageMagick", "binary" => "convert", "version" => "convert -v",
"name" => "ImageMagick", "binary" => "convert", "version_arg" => "-v",
"version_regex" => "/Version: \S+ (\S+)/"),
"graphicsmagick" => array(
"name" => "GraphicsMagick", "binary" => "gm", "version" => "gm version",
"name" => "GraphicsMagick", "binary" => "gm", "version_arg" => "version",
"version_regex" => "/\S+ (\S+)/"));
// Loop through the kits
foreach ($magick_kits as $index => $settings) {
@ -328,7 +328,8 @@ class graphics_Core {
$toolkits->$index->name = $settings["name"];
if ($path) {
if (@is_file($path) &&
preg_match($settings["version_regex"], shell_exec($settings["version"]), $matches)) {
preg_match(
$settings["version_regex"], shell_exec($path . " " . $settings["version_arg"]), $matches)) {
$version = $matches[1];
$toolkits->$index->installed = true;
@ -423,4 +424,23 @@ class graphics_Core {
return true;
}
/**
* Return the max file size that this graphics toolkit can handle.
*/
static function max_filesize() {
if (module::get_var("gallery", "graphics_toolkit") == "gd") {
$memory_limit = trim(ini_get("memory_limit"));
$memory_limit_bytes = num::convert_to_bytes($memory_limit);
// GD expands images in memory and uses 4 bytes of RAM for every byte
// in the file.
$max_filesize = $memory_limit_bytes / 4;
$max_filesize_human_readable = num::convert_to_human_readable($max_filesize);
return array($max_filesize, $max_filesize_human_readable);
}
// Some arbitrarily large size
return array(1000000000, "1G");
}
}

View File

@ -152,8 +152,18 @@ class item_Core {
* @param string $filename
*/
static function convert_filename_to_slug($filename) {
$result = pathinfo($filename, PATHINFO_FILENAME);
$result = str_replace("&", "-and-", $filename);
$result = str_replace(" ", "-", $result);
// It's not easy to extend the text helper since it's called by the Input class which is
// referenced in hooks/init_gallery, so it's
if (class_exists("transliterate")) {
$result = transliterate::utf8_to_ascii($result);
} else {
$result = text::transliterate_to_ascii($result);
}
$result = preg_replace("/[^A-Za-z0-9-_]+/", "-", $result);
$result = preg_replace("/-+/", "-", $result);
return trim($result, "-");
}

View File

@ -101,7 +101,7 @@ class module_Core {
$m->locked = false;
if ($m->active && $m->version != $m->code_version) {
site_status::warning(t("Some of your modules are out of date. <a href=\"%upgrader_url\">Upgrade now!</a>", array("upgrader_url" => url::site("upgrader"))), "upgrade_now");
site_status::warning(t("Some of your modules are out of date. <a href=\"%upgrader_url\">Upgrade now!</a>", array("upgrader_url" => url::abs_site("upgrader"))), "upgrade_now");
}
}

View File

@ -19,21 +19,13 @@
*/
class random_Core {
/**
* Return a random 32 bit hash value.
* Return a random 32 byte hash value.
* @param string extra entropy data
*/
static function hash($entropy="") {
return md5($entropy . uniqid(mt_rand(), true));
}
/**
* Return a random hexadecimal string of the given length.
* @param int the desired length of the string
*/
static function string($length) {
return substr(random::hash(), 0, $length);
}
/**
* Return a random floating point number between 0 and 1
*/

View File

@ -40,4 +40,25 @@ class system_Core {
}
return null;
}
/**
* Create a file with a unique file name.
* This helper is similar to the built-in tempnam.
* It allows the caller to specify a prefix and an extension.
* It always places the file in TMPPATH.
*/
static function temp_filename($prefix="", $extension="") {
do {
$basename = tempnam(TMPPATH, $prefix);
if (!$basename) {
return false;
}
$filename = "$basename.$extension";
$success = !file_exists($filename) && @rename($basename, $filename);
if (!$success) {
@unlink($basename);
}
} while (!$success);
return $filename;
}
}

View File

@ -41,11 +41,34 @@ class theme_Core {
$config = Kohana_Config::instance();
$modules = $config->get("core.modules");
// Normally Router::find_uri() strips off the url suffix for us, but we're working off of the
// PATH_INFO here so we need to strip it off manually
if ($suffix = Kohana::config("core.url_suffix")) {
$path = preg_replace("#" . preg_quote($suffix) . "$#u", "", $path);
}
self::$is_admin = $path == "/admin" || !strncmp($path, "/admin/", 7);
self::$site_theme_name = module::get_var("gallery", "active_site_theme");
// If the site theme doesn't exist, fall back to wind.
if (!file_exists(THEMEPATH . self::$site_theme_name . "/theme.info")) {
site_status::error(t("Theme '%name' is missing. Falling back to the Wind theme.",
array("name" => self::$site_theme_name)), "missing_site_theme");
module::set_var("gallery", "active_site_theme", self::$site_theme_name = "wind");
}
if (self::$is_admin) {
// Load the admin theme
self::$admin_theme_name = module::get_var("gallery", "active_admin_theme");
// If the admin theme doesn't exist, fall back to admin_wind.
if (!file_exists(THEMEPATH . self::$admin_theme_name . "/theme.info")) {
site_status::error(t("Admin theme '%name' is missing! Falling back to the Wind theme.",
array("name" => self::$admin_theme_name)), "missing_admin_theme");
module::set_var("gallery", "active_admin_theme", self::$admin_theme_name = "admin_wind");
}
array_unshift($modules, THEMEPATH . self::$admin_theme_name);
// If the site theme has an admin subdir, load that as a module so that

View File

@ -42,7 +42,8 @@ class upgrade_checker_Core {
static function should_auto_check() {
if (upgrade_checker::auto_check_enabled() && random::int(1, 100) == 1) {
$version_info = upgrade_checker::version_info();
return (!$version_info || (time() - $version_info->timestamp) > AUTO_CHECK_INTERVAL);
return (!$version_info ||
(time() - $version_info->timestamp) > upgrade_checker::AUTO_CHECK_INTERVAL);
}
return false;
}

View File

@ -48,6 +48,20 @@ class Form_Uploadify_Core extends Form_Input {
$v->simultaneous_upload_limit = module::get_var("gallery", "simultaneous_upload_limit");
$v->movies_allowed = (bool) movie::find_ffmpeg();
$v->suhosin_session_encrypt = (bool) ini_get("suhosin.session.encrypt");
list ($toolkit_max_filesize_bytes, $toolkit_max_filesize) = graphics::max_filesize();
$upload_max_filesize = trim(ini_get("upload_max_filesize"));
$upload_max_filesize_bytes = num::convert_to_bytes($upload_max_filesize);
if ($upload_max_filesize_bytes < $toolkit_max_filesize_bytes) {
$v->size_limit_bytes = $upload_max_filesize_bytes;
$v->size_limit = $upload_max_filesize;
} else {
$v->size_limit_bytes = $toolkit_max_filesize_bytes;
$v->size_limit = $toolkit_max_filesize;
}
return $v;
}

View File

@ -30,6 +30,52 @@ class Gallery_View_Core extends View {
return $absolute_url ? url::abs_file($arg) : url::file($arg);
}
/**
* Set up the data and render a pager.
*
* See themes/wind/views/pager.html for documentation on the variables generated here.
*/
public function paginator() {
$v = new View("paginator.html");
$v->page_type = $this->page_type;
$v->page_subtype = $this->page_subtype;
$v->first_page_url = null;
$v->previous_page_url = null;
$v->next_page_url = null;
$v->last_page_url = null;
if ($this->page_type == "collection") {
$v->page = $this->page;
$v->max_pages = $this->max_pages;
$v->total = $this->children_count;
if ($this->page != 1) {
$v->first_page_url = url::site(url::merge(array("page" => 1)));
$v->previous_page_url = url::site(url::merge(array("page" => $this->page - 1)));
}
if ($this->page != $this->max_pages) {
$v->next_page_url = url::site(url::merge(array("page" => $this->page + 1)));
$v->last_page_url = url::site(url::merge(array("page" => $this->max_pages)));
}
$v->first_visible_position = ($this->page - 1) * $this->page_size + 1;
$v->last_visible_position = min($this->page * $this->page_size, $v->total);
} else if ($this->page_type == "item") {
$v->position = $this->position;
$v->total = $this->sibling_count;
if ($this->previous_item) {
$v->previous_page_url = $this->previous_item->url();
}
if ($this->next_item) {
$v->next_page_url = $this->next_item->url();
}
}
return $v;
}
/**
* Begin gather up scripts or css files so that they can be combined into a single request.
*
@ -111,6 +157,8 @@ class Gallery_View_Core extends View {
$contents = $cache->get($key);
if (empty($contents)) {
module::event("before_combine", $type, $this->combine_queue[$type][$group]);
$contents = "";
foreach (array_keys($this->combine_queue[$type][$group]) as $path) {
if ($type == "css") {
@ -120,6 +168,8 @@ class Gallery_View_Core extends View {
}
}
module::event("after_combine", $type, $contents);
$cache->set($key, $contents, array($type), 30 * 84600);
$use_gzip = function_exists("gzencode") &&
@ -128,9 +178,13 @@ class Gallery_View_Core extends View {
$cache->set("{$key}_gz", gzencode($contents, 9, FORCE_GZIP),
array($type, "gzip"), 30 * 84600);
}
}
unset($this->combine_queue[$type][$group]);
if (empty($this->combine_queue[$type])) {
unset($this->combine_queue[$type]);
}
if ($type == "css") {
return html::stylesheet("combined/css/$key", "screen,print,projection", true);
@ -158,6 +212,7 @@ class Gallery_View_Core extends View {
$replace[] = "url('" . url::abs_file($relative) . "')";
} else {
Kohana_Log::add("error", "Missing URL reference '{$match[1]}' in CSS file '$css_file'");
}
}
$replace = str_replace(DIRECTORY_SEPARATOR, "/", $replace);

View File

@ -56,8 +56,12 @@ class InPlaceEdit_Core {
}
public function validate() {
$post = Validation::factory($_POST)
->add_callbacks("input", $this->callback);
$post = Validation::factory($_POST);
if (!empty($this->callback)) {
$post->add_callbacks("input", $this->callback);
}
foreach ($this->rules as $rule) {
$post->add_rules("input", $rule);
}

View File

@ -38,6 +38,7 @@ class Theme_View_Core extends Gallery_View {
$this->item = null;
$this->tag = null;
$this->set_global(array("theme" => $this,
"theme_info" => theme::get_info($this->theme_name),
"user" => identity::active_user(),
"page_type" => $page_type,
"page_subtype" => $page_subtype,
@ -137,52 +138,6 @@ class Theme_View_Core extends Gallery_View {
return $menu->render();
}
/**
* Set up the data and render a pager.
*
* See themes/wind/views/pager.html for documentation on the variables generated here.
*/
public function paginator() {
$v = new View("paginator.html");
$v->page_type = $this->page_type;
$v->page_subtype = $this->page_subtype;
$v->first_page_url = null;
$v->previous_page_url = null;
$v->next_page_url = null;
$v->last_page_url = null;
if ($this->page_type == "collection") {
$v->page = $this->page;
$v->max_pages = $this->max_pages;
$v->total = $this->children_count;
if ($this->page != 1) {
$v->first_page_url = url::site(url::merge(array("page" => 1)));
$v->previous_page_url = url::site(url::merge(array("page" => $this->page - 1)));
}
if ($this->page != $this->max_pages) {
$v->next_page_url = url::site(url::merge(array("page" => $this->page + 1)));
$v->last_page_url = url::site(url::merge(array("page" => $this->max_pages)));
}
$v->first_visible_position = ($this->page - 1) * $this->page_size + 1;
$v->last_visible_position = min($this->page * $this->page_size, $v->total);
} else if ($this->page_type == "item") {
$v->position = $this->position;
$v->total = $this->sibling_count;
if ($this->previous_item) {
$v->previous_page_url = $this->previous_item->url();
}
if ($this->next_item) {
$v->next_page_url = $this->next_item->url();
}
}
return $v;
}
/**
* Print out any site wide status information.
*/

View File

@ -336,9 +336,7 @@ class Item_Model_Core extends ORM_MPTT {
// Make an url friendly slug from the name, if necessary
if (empty($this->slug)) {
$tmp = pathinfo($this->name, PATHINFO_FILENAME);
$tmp = preg_replace("/[^A-Za-z0-9-_]+/", "-", $tmp);
$this->slug = trim($tmp, "-");
$this->slug = item::convert_filename_to_slug(pathinfo($this->name, PATHINFO_FILENAME));
// If the filename is all invalid characters, then the slug may be empty here. Pick a
// random value.

View File

@ -1,3 +1,7 @@
name = "Gallery 3"
description = "Gallery core application"
version = 46
version = 49
author_name = "Gallery Team"
author_url = "http://codex.gallery2.org/Gallery:Team"
info_url = "http://codex.gallery2.org/Gallery3:Modules:gallery"
discuss_url = "http://gallery.menalto.com/forum_module_gallery"

View File

@ -2,7 +2,7 @@
<p>
<?= t("This is your administration dashboard and it provides a quick overview of status messages, recent updates, and frequently used options. Add or remove blocks and rearrange them to tailor to your needs. The admin menu provides quick access to all of Gallery 3's options and settings. Here are a few of the most used options to get you started.") ?>
</p>
<ul>
<ul class="g-text">
<li>
<?= t("General Settings - choose your <a href=\"%graphics_url\">graphics</a> and <a href=\"%language_url\">language</a> settings.",
array("graphics_url" => html::mark_clean(url::site("admin/graphics")),

View File

@ -51,7 +51,7 @@
<? foreach ($available_locales as $code => $display_name): ?>
<? if ($i == (int) (count($available_locales)/2)): ?>
</table>
<table>
<table class="g-left">
<tr>
<th> <?= t("Installed") ?> </th>
<th> <?= t("Language") ?> </th>

View File

@ -3,7 +3,9 @@
<h1> <?= t("Maintenance") ?> </h1>
<div class="g-block-content">
<div id="g-maintenance-mode">
<p>
<?= t("When you're performing maintenance on your Gallery, you can enable <b>maintenance mode</b> which prevents any non-admin from accessing your Gallery. Some of the tasks below will automatically put your Gallery in maintenance mode for you.") ?>
</p>
<ul id="g-action-status" class="g-message-block">
<? if (module::get_var("gallery", "maintenance_mode")): ?>
<li class="g-warning">

View File

@ -6,7 +6,7 @@
dataType: "json",
success: function(data) {
if (data.reload) {
window.location.reload();
window.location = "<? url::site("/admin/modules") ?>";
} else {
$("body").append('<div id="g-dialog">' + data.dialog + '</div>');
$("#g-dialog").dialog({
@ -43,7 +43,7 @@
</script>
<h1> <?= t("Gallery Modules") ?> </h1>
<p>
<?= t("Power up your Gallery by adding more modules! Each module provides new cool features.") ?>
<?= t("Power up your Gallery by <a href=\"%url\">adding more modules</a>! Each module provides new cool features.", array("url" => "http://codex.gallery2.org/Category:Gallery_3:Modules")) ?>
</p>
<div class="g-block-content">
@ -55,6 +55,7 @@
<th style="width: 8em"> <?= t("Name") ?> </th>
<th> <?= t("Version") ?> </th>
<th> <?= t("Description") ?> </th>
<th style="width: 60px"> <?= t("Details") ?> </th>
</tr>
<? foreach ($available as $module_name => $module_info): ?>
<tr class="<?= text::alternate("g-odd", "g-even") ?>">
@ -64,6 +65,55 @@
<td> <?= t($module_info->name) ?> </td>
<td> <?= $module_info->version ?> </td>
<td> <?= t($module_info->description) ?> </td>
<td style="white-space: nowrap">
<ul class="g-buttonset">
<li>
<a target="_blank"
<? if (isset($module_info->author_url)): ?>
class="ui-state-default ui-icon ui-icon-person ui-corner-left"
href="<?= $module_info->author_url ?>"
<? else: ?>
class="ui-state-disabled ui-icon ui-icon-person ui-corner-left"
href="#"
<? endif ?>
<? if (isset($module_info->author_name)): ?>
title="<?= $module_info->author_name ?>"
<? endif ?>
>
<? if (isset($module_info->author_name)): ?>
<?= $module_info->author_name ?>
<? endif ?>
</a>
</li>
<li>
<a target="_blank"
<? if (isset($module_info->info_url)): ?>
class="ui-state-default ui-icon ui-icon-info"
href="<?= $module_info->info_url ?>"
<? else: ?>
class="ui-state-disabled ui-icon ui-icon-info"
href="#"
<? endif ?>
>
<?= t("info") ?>
</a>
</li>
<li>
<a target="_blank"
<? if (isset($module_info->discuss_url)): ?>
class="ui-state-default ui-icon ui-icon-comment ui-corner-right"
href="<?= $module_info->discuss_url ?>"
<? else: ?>
class="ui-state-disabled ui-icon ui-icon-comment ui-corner-right"
href="#"
<? endif ?>
>
<?= t("discuss") ?>
</a>
</li>
</ul>
</td>
</tr>
<? endforeach ?>
</table>

View File

@ -10,7 +10,7 @@
<div class="g-block ui-helper-clearfix">
<h1> <?= t("Theme choice") ?> </h1>
<p>
<?= t("Gallery allows you to choose a theme for browsing your Gallery, as well as a special theme for the administration interface. Click a theme to preview and activate it.") ?>
<?= t("Make your Gallery beautiful <a href=\"%url\">with a new theme</a>! There are separate themes for the regular site and for the administration interface. Click a theme below to preview and activate it.", array("url" => "http://codex.gallery2.org/Category:Gallery_3:Themes")) ?>
</p>
<div class="g-block-content">
@ -23,6 +23,7 @@
<p>
<?= $themes[$site]->description ?>
</p>
<? $v = new View("admin_themes_buttonset.html"); $v->info = $themes[$site]; print $v; ?>
</div>
<h2> <?= t("Available Gallery themes") ?> </h2>
@ -40,13 +41,14 @@
<?= $info->description ?>
</p>
</a>
<? $v = new View("admin_themes_buttonset.html"); $v->info = $info; print $v; ?>
</div>
<? $count++ ?>
<? endforeach ?>
<? if (!$count): ?>
<p>
<?= t("There are no other site themes available.") ?>
<?= t("There are no other site themes available. <a href=\"%url\">Download one now!</a>", array("url" => "http://codex.gallery2.org/Category:Gallery_3:Modules")) ?>
</p>
<? endif ?>
</div>
@ -61,6 +63,7 @@
<p>
<?= $themes[$admin]->description ?>
</p>
<? $v = new View("admin_themes_buttonset.html"); $v->info = $themes[$admin]; print $v; ?>
</div>
<h2> <?= t("Available admin themes") ?> </h2>
@ -78,17 +81,18 @@
<?= $info->description ?>
</p>
</a>
<? $v = new View("admin_themes_buttonset.html"); $v->info = $info; print $v; ?>
</div>
<? $count++ ?>
<? endforeach ?>
<? if (!$count): ?>
<p>
<?= t("There are no other admin themes available.") ?>
<?= t("There are no other admin themes available. <a href=\"%url\">Download one now!</a>", array("url" => "http://codex.gallery2.org/Category:Gallery_3:Modules")) ?>
</p>
<? endif ?>
</div>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,48 @@
<?php defined("SYSPATH") or die("No direct script access.") ?>
<ul class="g-buttonset">
<li>
<a target="_blank"
<? if (isset($info['author_url'])): ?>
class="ui-state-default ui-icon ui-icon-person ui-corner-left"
href="<?= $info['author_url'] ?>"
<? else: ?>
class="ui-state-disabled ui-icon ui-icon-person ui-corner-left"
href="#"
<? endif ?>
<? if (isset($info['author_name'])): ?>
title="<?= $info['author_name'] ?>"
<? endif ?>
>
<? if (isset($info['author_name'])): ?>
<?= $info['author_name'] ?>
<? endif ?>
</a>
</li>
<li>
<a target="_blank"
<? if (isset($info['info_url'])): ?>
class="ui-state-default ui-icon ui-icon-info"
href="<?= $info['info_url'] ?>"
<? else: ?>
class="ui-state-disabled ui-icon ui-icon-info"
href="#"
<? endif ?>
>
<?= t("info") ?>
</a>
</li>
<li>
<a target="_blank"
<? if (isset($info['discuss_url'])): ?>
class="ui-state-default ui-icon ui-icon-comment ui-corner-right"
href="<?= $info['discuss_url'] ?>"
<? else: ?>
class="ui-state-disabled ui-icon ui-icon-comment ui-corner-right"
href="#"
<? endif ?>
>
<?= t("discuss") ?>
</a>
</li>
</ul>

View File

@ -32,6 +32,7 @@
fileDesc: <?= t("Photos and movies")->for_js() ?>,
cancelImg: "<?= url::file("lib/uploadify/cancel.png") ?>",
simUploadLimit: <?= $simultaneous_upload_limit ?>,
sizeLimit: <?= $size_limit_bytes ?>,
wmode: "transparent",
hideButton: true, /* should be true */
auto: true,
@ -66,26 +67,30 @@
return true;
},
onError: function(event, queueID, fileObj, errorObj) {
var msg = " - ";
if (errorObj.type == "HTTP") {
if (errorObj.info == "500") {
msg += <?= t("Unable to process this file")->for_js() ?>;
// Server error - check server logs
error_msg = <?= t("Unable to process this photo")->for_js() ?>;
} else if (errorObj.info == "404") {
msg += <?= t("The upload script was not found.")->for_js() ?>;
// Server script not found
error_msg = <?= t("The upload script was not found")->for_js() ?>;
} else if (errorObj.info == "400") {
error_msg = <?= t("This photo is too large (max is %size bytes)",
array("size" => $size_limit))->for_js() ?>;
} else {
// Server Error: status: errorObj.info
msg += (<?= t("Server error: __INFO__")->for_js() ?>.replace("__INFO__", errorObj.info));
msg += (<?= t("Server error: __INFO__ (__TYPE__)")->for_js() ?>
.replace("__INFO__", errorObj.info)
.replace("__TYPE__", errorObj.type));
}
} else if (errorObj.type == "File Size") {
var sizelimit = $("#g-uploadify").uploadifySettings(sizeLimit);
msg += fileObj.name+' '+errorObj.type+' Limit: '+Math.round(d.sizeLimit/1024)+'KB';
error_msg = <?= t("This photo is too large (max is %size bytes)",
array("size" => $size_limit))->for_js() ?>;
} else {
msg += (<?= t("Server error: __INFO__ (__TYPE__)")->for_js() ?>
.replace("__INFO__", errorObj.info)
.replace("__TYPE__", errorObj.type));
error_msg = <?= t("Server error: __INFO__ (__TYPE__)")->for_js() ?>
.replace("__INFO__", errorObj.info)
.replace("__TYPE__", errorObj.type);
}
msg = " - <a target=\"_blank\" href=\"http://codex.gallery2.org/Gallery3:Troubleshooting:Uploading\">" +
error_msg + "</a>";
$("#g-add-photos-status ul").append(
"<li id=\"q" + queueID + "\" class=\"g-error\">" + fileObj.name + msg + "</li>");
$("#g-uploadify").uploadifyCancel(queueID);
@ -131,10 +136,7 @@
<? endif ?>
<div>
<p>
<?= t("Photos will be uploaded to album: ") ?>
</p>
<ul class="g-breadcrumbs ui-helper-clearfix">
<ul class="g-breadcrumbs">
<? foreach ($album->parents() as $i => $parent): ?>
<li<? if ($i == 0) print " class=\"g-first\"" ?>> <?= html::clean($parent->title) ?> </li>
<? endforeach ?>
@ -143,7 +145,7 @@
</div>
<div id="g-add-photos-canvas">
<button id="g-add-photos-button" class="g-button ui-state-default ui-corner-all" href="#"><?= t("Select photos...") ?></button>
<button id="g-add-photos-button" class="g-button ui-state-default ui-corner-all" href="#"><?= t("Select photos (%size max per file)...", array("size" => $size_limit)) ?></button>
<span id="g-uploadify"></span>
</div>
<div id="g-add-photos-status">

View File

@ -22,5 +22,5 @@
}
}
}
)
).ipad();
</script>

View File

@ -6,8 +6,10 @@
<p>
<? if (gallery::RELEASE_CHANNEL == "release"): ?>
<?= t("You are using the official Gallery %version release, code named <i>%code_name</i>.", array("version" => gallery::VERSION, "code_name" => gallery::CODE_NAME)) ?>
<? elseif (isset($build_number)): ?>
<?= t("You are using an experimental snapshot of Gallery %version (build %build_number on branch %branch).", array("version" => gallery::VERSION, "branch" => gallery::RELEASE_BRANCH, "build_number" => $build_number)) ?>
<? else: ?>
<?= t("You are using an experimental snapshot of Gallery %version (build %build_number on branch %branch).", array("version" => gallery::VERSION, "branch" => gallery::RELEASE_BRANCH, "build_number" => gallery::build_number())) ?>
<?= t("You are using an experimental snapshot of Gallery %version (branch %branch) but your gallery3/.build_number file is missing so we don't know what build you have. You should probably upgrade so that you have that file.", array("version" => gallery::VERSION, "branch" => gallery::RELEASE_BRANCH, "build_number" => $build_number)) ?>
<? endif ?>
</p>

View File

@ -27,7 +27,7 @@
<div id="done" style="display: none">
<h1> <?= t("That's it!") ?> </h1>
<p>
<?= t("Your <a href=\"%url\">Gallery</a> is up to date.",
<?= t("Your Gallery is up to date.<br/><a href=\"%url\">Return to your Gallery</a>",
array("url" => html::mark_clean(url::base()))) ?>
</p>
</div>

View File

@ -1,3 +1,7 @@
name = "Image Block"
description = "Display a random image in the sidebar"
version = 3
author_name = "Gallery Team"
author_url = "http://codex.gallery2.org/Gallery:Team"
info_url = "http://codex.gallery2.org/Gallery3:Modules:image_block"
discuss_url = "http://gallery.menalto.com/forum_module_image_block"

View File

@ -1,3 +1,7 @@
name = "Info"
description = "Display extra information about photos and albums"
version = 2
author_name = "Gallery Team"
author_url = "http://codex.gallery2.org/Gallery:Team"
info_url = "http://codex.gallery2.org/Gallery3:Modules:info"
discuss_url = "http://gallery.menalto.com/forum_module_info"

View File

@ -1,3 +1,7 @@
name = "Notification"
description = "Send notifications to users when changes are made to watched albums."
version = 2
author_name = "Gallery Team"
author_url = "http://codex.gallery2.org/Gallery:Team"
info_url = "http://codex.gallery2.org/Gallery3:Modules:notification"
discuss_url = "http://gallery.menalto.com/forum_module_notification"

View File

@ -1,3 +1,7 @@
name = "Organize"
description = "Visually rearrange and move photos in your gallery"
version = 4
author_name = "Gallery Team"
author_url = "http://codex.gallery2.org/Gallery:Team"
info_url = "http://codex.gallery2.org/Gallery3:Modules:organize"
discuss_url = "http://gallery.menalto.com/forum_module_organize"

View File

@ -1,3 +1,7 @@
name = "reCAPTCHA"
description = "reCAPTCHA displays a graphical verification that protects the input form from abuse from 'bots,' or automated programs usually written to generate spam (http://recaptcha.net)."
version = 1
author_name = "Gallery Team"
author_url = "http://codex.gallery2.org/Gallery:Team"
info_url = "http://codex.gallery2.org/Gallery3:Modules:recaptcha"
discuss_url = "http://gallery.menalto.com/forum_module_recaptcha"

View File

@ -2,3 +2,7 @@ name = "REST API Module"
description = "A REST-based API that allows desktop clients and other apps to interact with Gallery 3"
version = 3
author_name = "Gallery Team"
author_url = "http://codex.gallery2.org/Gallery:Team"
info_url = "http://codex.gallery2.org/Gallery3:Modules:rest"
discuss_url = "http://gallery.menalto.com/forum_module_rest"

View File

@ -1,3 +1,7 @@
name = "RSS"
description = "Provides RSS feeds"
version = 1
author_name = "Gallery Team"
author_url = "http://codex.gallery2.org/Gallery:Team"
info_url = "http://codex.gallery2.org/Gallery3:Modules:rss"
discuss_url = "http://gallery.menalto.com/forum_module_rss"

View File

@ -22,14 +22,16 @@ class Search_Controller extends Controller {
$page_size = module::get_var("gallery", "page_size", 9);
$q = Input::instance()->get("q");
$page = Input::instance()->get("page", 1);
$offset = ($page - 1) * $page_size;
// Make sure that the page references a valid offset
if ($page < 1) {
$page = 1;
}
list ($count, $result) = search::search($q, $page_size, $offset);
$offset = ($page - 1) * $page_size;
$q_with_more_terms = search::add_query_terms($q);
list ($count, $result) = search::search($q_with_more_terms, $page_size, $offset);
$max_pages = max(ceil($count / $page_size), 1);

View File

@ -18,6 +18,22 @@
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
class search_Core {
/**
* Add more terms to the query by wildcarding the stem value of the first
* few terms in the query.
*/
static function add_query_terms($q) {
$MAX_TERMS = 5;
$terms = explode(" ", $q, $MAX_TERMS);
for ($i = 0; $i < min(count($terms), $MAX_TERMS - 1); $i++) {
// Don't wildcard quoted or already wildcarded terms
if ((substr($terms[$i], 0, 1) != '"') && (substr($terms[$i], -1, 1) != "*")) {
$terms[] = rtrim($terms[$i], "s") . "*";
}
}
return implode(" ", $terms);
}
static function search($q, $limit, $offset) {
$db = Database::instance();
$q = $db->escape($q);

View File

@ -1,3 +1,7 @@
name = "Search"
description = "Allows users to search their Gallery"
version = 1
author_name = "Gallery Team"
author_url = "http://codex.gallery2.org/Gallery:Team"
info_url = "http://codex.gallery2.org/Gallery3:Modules:search"
discuss_url = "http://gallery.menalto.com/forum_module_search"

View File

@ -286,7 +286,7 @@ class Server_Add_Controller extends Admin_Controller {
} catch (Exception $e) {
// This can happen if a photo file is invalid, like a BMP masquerading as a .jpg
$entry->item_id = 0;
$task->log("Skipping invalid file: {$entry->file}");
$task->log("Skipping invalid file: {$entry->path}");
}
}

View File

@ -24,20 +24,4 @@ class server_add_theme_Core {
. $theme->script("server_add.js");
}
}
static function admin_head($theme) {
$buf = "";
if (strpos(Router::$current_uri, "admin/server_add") !== false) {
$buf .= $theme->css("server_add.css")
. $theme->css("jquery.autocomplete.css");
$base = url::site("__ARGS__");
$csrf = access::csrf_token();
$buf .= "<script type=\"text/javascript\"> var base_url = \"$base\"; var csrf = \"$csrf\";</script>";
$buf .= $theme->script("jquery.autocomplete.js")
. $theme->script("admin.js");
}
return $buf;
}
}

View File

@ -1,8 +0,0 @@
/**
* Set up autocomplete on the server path list
*
*/
$("document").ready(function() {
$("#g-path").autocomplete(
base_url.replace("__ARGS__", "admin/server_add/autocomplete"), {max: 256});
});

View File

@ -1,3 +1,7 @@
name = "Server Add"
description = "Allows authorized users to load images directly from your web server"
version = 4
author_name = "Gallery Team"
author_url = "http://codex.gallery2.org/Gallery:Team"
info_url = "http://codex.gallery2.org/Gallery3:Modules:server_add"
discuss_url = "http://gallery.menalto.com/forum_module_server_add"

View File

@ -1,4 +1,18 @@
<?php defined("SYSPATH") or die("No direct script access.") ?>
<?= $theme->css("server_add.css") ?>
<?= $theme->css("jquery.autocomplete.css") ?>
<?= $theme->script("jquery.autocomplete.js") ?>
<script type="text/javascript">
$("document").ready(function() {
$("#g-path").autocomplete(
"<?= url::site("__ARGS__") ?>".replace("__ARGS__", "admin/server_add/autocomplete"),
{
max: 256,
loadingClass: "g-loading-small",
});
});
</script>
<div class="g-block">
<h1> <?= t("Add from server administration") ?> </h1>
<div class="g-block-content">
@ -8,12 +22,17 @@
<? if (empty($paths)): ?>
<li class="g-module-status g-info"><?= t("No authorized image source paths defined yet") ?></li>
<? endif ?>
<? foreach ($paths as $id => $path): ?>
<li>
<?= html::clean($path) ?>
<a href="<?= url::site("admin/server_add/remove_path?path=" . urlencode($path) . "&amp;csrf=$csrf") ?>"
<a href="<?= url::site("admin/server_add/remove_path?path=" . urlencode($path) . "&amp;csrf=<?= access::csrf_token() ?>") ?>"
id="icon_<?= $id ?>"
class="g-remove-dir g-button"><span class="ui-icon ui-icon-trash"><?= t("delete") ?></span></a>
class="g-remove-dir g-button">
<span class="ui-icon ui-icon-trash">
<?= t("delete") ?>
</span>
</a>
</li>
<? endforeach ?>
</ul>

View File

@ -1,3 +1,7 @@
name = "Slideshow"
description = "Allows users to view a slideshow of photos"
version = 2
author_name = "Gallery Team"
author_url = "http://codex.gallery2.org/Gallery:Team"
info_url = "http://codex.gallery2.org/Gallery3:Modules:slideshow"
discuss_url = "http://gallery.menalto.com/forum_module_slideshow"

View File

@ -81,17 +81,25 @@ class Admin_Tags_Controller extends Admin_Controller {
$in_place_edit = InPlaceEdit::factory($tag->name)
->action("admin/tags/rename/$tag->id")
->rules(array("required", "length[1,64]"))
->messages(array("in_use" => t("There is already a tag with that name")))
->callback(array($this, "check_for_duplicate"));
->rules(array("required", "length[1,64]"));
if ($in_place_edit->validate()) {
$old_name = $tag->name;
$tag->name = $in_place_edit->value();
$new_name_or_list = $in_place_edit->value();
$tag_list = explode(",", $new_name_or_list);
$tag->name = array_shift($tag_list);
$tag->save();
$message = t("Renamed tag <b>%old_name</b> to <b>%new_name</b>",
array("old_name" => $old_name, "new_name" => $tag->name));
if (!empty($tag_list)) {
$this->_copy_items_for_tags($tag, $tag_list);
$message = t("Split tag <i>%old_name</i> into <i>%tag_list</i>",
array("old_name" => $old_name, "tag_list" => $new_name_or_list));
} else {
$message = t("Renamed tag <i>%old_name</i> to <i>%new_name</i>",
array("old_name" => $old_name, "new_name" => $tag->name));
}
message::success($message);
log::success("tags", $message);
@ -101,12 +109,11 @@ class Admin_Tags_Controller extends Admin_Controller {
}
}
public function check_for_duplicate(Validation $post_data, $field) {
$tag_exists = ORM::factory("tag")->where("name", "=", $post_data[$field])->count_all();
if ($tag_exists) {
$post_data->add_error($field, "in_use");
private function _copy_items_for_tags($tag, $tag_list) {
foreach ($tag->items() as $item) {
foreach ($tag_list as $new_tag_name) {
tag::add($item, trim($new_tag_name));
}
}
}
}

View File

@ -19,8 +19,8 @@
*/
class Tag_Controller extends Controller {
public function __call($function, $args) {
$tag_name = $function;
$tag = ORM::factory("tag")->where("name", "=", $tag_name)->find();
$tag_id = $function;
$tag = ORM::factory("tag")->where("id", "=", $tag_id)->find();
$page_size = module::get_var("gallery", "page_size", 9);
$page = (int) Input::instance()->get("page", "1");
$children_count = $tag->items_count();

View File

@ -22,7 +22,8 @@ class Tags_Controller extends Controller {
// Far from perfection, but at least require view permission for the root album
$album = ORM::factory("item", 1);
access::required("view", $album);
print tag::cloud(30);
print tag::cloud(module::get_var("tag", "tag_cloud_size", 30));
}
public function create($item_id) {

View File

@ -48,6 +48,7 @@ class tag_Core {
* @return ORM_Iterator of Tag_Model in descending tag count order
*/
static function popular_tags($count) {
$count = max($count, 1);
return ORM::factory("tag")
->order_by("count", "DESC")
->limit($count)

View File

@ -30,7 +30,7 @@ class tag_block_Core {
$block->css_id = "g-tag";
$block->title = t("Popular tags");
$block->content = new View("tag_block.html");
$block->content->cloud = tag::cloud(30);
$block->content->cloud = tag::cloud(module::get_var("tag", "tag_cloud_size", 30));
if ($theme->item() && $theme->page_subtype() != "tag" && access::can("edit", $theme->item())) {
$controller = new Tags_Controller();

View File

@ -36,10 +36,7 @@ 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, "ISO-8859-1, UTF-8") != "UTF-8") {
$word = utf8_encode($word);
}
$word = encoding::convert_to_utf8($word);
$tags[$word] = 1;
}
}
@ -113,11 +110,11 @@ class tag_event_Core {
}
static function add_photos_form($album, $form) {
if (!isset($group->uploadify)) {
$group = $form->add_photos;
if (!is_object($group->uploadify)) {
return;
}
$group = $form->add_photos;
$group->input("tags")
->label(t("Add tags to all uploaded files"))
->value("");
@ -136,7 +133,8 @@ class tag_event_Core {
}
static function add_photos_form_completed($album, $form) {
if (!isset($group->uploadify)) {
$group = $form->add_photos;
if (!is_object($group->uploadify)) {
return;
}
@ -151,7 +149,7 @@ class tag_event_Core {
static function info_block_get_metadata($block, $item) {
$tags = array();
foreach (tag::item_tags($item) as $tag) {
$tags[] = "<a href=\"" . url::site("tag/{$tag->name}") . "\">{$tag->name}</a>";
$tags[] = "<a href=\"{$tag->url()}\">{$tag->name}</a>";
}
if ($tags) {
$info = $block->content->metadata;

View File

@ -36,7 +36,8 @@ class tag_installer {
KEY(`tag_id`, `id`),
KEY(`item_id`, `id`))
DEFAULT CHARSET=utf8;");
module::set_version("tag", 2);
module::set_var("tag", "tag_cloud_size", 30);
module::set_version("tag", 3);
}
static function upgrade($version) {
@ -45,6 +46,10 @@ class tag_installer {
$db->query("ALTER TABLE {tags} MODIFY COLUMN `name` VARCHAR(128)");
module::set_version("tag", $version = 2);
}
if ($version == 2) {
module::set_var("tag", "tag_cloud_size", 30);
module::set_version("tag", $version = 3);
}
}
static function uninstall() {

View File

@ -29,6 +29,7 @@ class tag_item_rest_Core {
static function delete($request) {
list ($tag, $item) = rest::resolve($request->url);
access::required("edit", $item);
$tag->remove($item);
$tag->save();
}

View File

@ -51,6 +51,7 @@ class tag_items_rest_Core {
static function delete($request) {
list ($tag, $item) = rest::resolve($request->url);
access::required("edit", $item);
$tag->remove($item);
$tag->save();
}

View File

@ -69,13 +69,23 @@ class Tag_Model_Core extends ORM {
* to this tag.
*/
public function save() {
$related_item_ids = array();
foreach (db::build()
->select("item_id")
->from("items_tags")
->where("tag_id", "=", $this->id)
->execute() as $row) {
$related_item_ids[$row->item_id] = 1;
// Check to see if another tag exists with the same name
$duplicate_tag = ORM::factory("tag")
->where("name", "=", $this->name)
->where("id", "!=", $this->id)
->find();
if ($duplicate_tag->loaded()) {
// If so, tag its items with this tag so as to merge it
$duplicate_tag_items = ORM::factory("item")
->join("items_tags", "items.id", "items_tags.item_id")
->where("items_tags.tag_id", "=", $duplicate_tag->id)
->find_all();
foreach ($duplicate_tag_items as $item) {
$this->add($item);
}
// ... and remove the duplicate tag
$duplicate_tag->delete();
}
if (isset($this->object_relations["items"])) {
@ -132,7 +142,7 @@ class Tag_Model_Core extends ORM {
* @param string $query the query string (eg "page=3")
*/
public function url($query=null) {
$url = url::site("tag/{$this->name}");
$url = url::site("tag/{$this->id}/" . urlencode($this->name));
if ($query) {
$url .= "?$query";
}

View File

@ -1,3 +1,7 @@
name = "Tags"
description = "Allows users to tag photos and albums"
version = 2
version = 3
author_name = "Gallery Team"
author_url = "http://codex.gallery2.org/Gallery:Team"
info_url = "http://codex.gallery2.org/Gallery3:Modules:tag"
discuss_url = "http://gallery.menalto.com/forum_module_tag"

View File

@ -21,6 +21,8 @@ class Admin_Users_Controller extends Admin_Controller {
public function index() {
$view = new Admin_View("admin.html");
$view->page_title = t("Users and groups");
$view->page_type = "collection";
$view->page_subtype = "admin_users";
$view->content = new View("admin_users.html");
// @todo: add this as a config option
@ -29,6 +31,12 @@ class Admin_Users_Controller extends Admin_Controller {
$builder = db::build();
$user_count = $builder->from("users")->count_records();
// Pagination info
$view->page = $page;
$view->page_size = $page_size;
$view->children_count = $user_count;
$view->max_pages = ceil($view->children_count / $view->page_size);
$view->content->pager = new Pagination();
$view->content->pager->initialize(
array("query_string" => "page",

Some files were not shown because too many files have changed in this diff Show More