Rev 229 Rev 236
1 <?php 1 <?php
2   2  
3 /** 3 /**
4 * Main class. 4 * Main class.
5 * @license http://opensource.org/licenses/gpl-license.php GNU General Public License 5 * @license http://opensource.org/licenses/gpl-license.php GNU General Public License
6 * @copyright (c)2003-2006 Tamlyn Rhodes 6 * @copyright (c)2003-2006 Tamlyn Rhodes
7 * @version $Id: singapore.class.php,v 1.75 2006/09/12 11:56:11 thepavian Exp $ 7 * @version $Id: singapore.class.php,v 1.75 2006/09/12 11:56:11 thepavian Exp $
8 */ 8 */
9   9  
10 //define constants for regular expressions 10 //define constants for regular expressions
11 define('SG_REGEXP_PROTOCOLURL', '(?:http://|https://|ftp://|mailto:)(?:[a-zA-Z0-9\-]+\.)+[a-zA-Z]{2,4}(?::[0-9]+)?(?:/[^ \n\r\"\'<]+)?'); 11 define('SG_REGEXP_PROTOCOLURL', '(?:http://|https://|ftp://|mailto:)(?:[a-zA-Z0-9\-]+\.)+[a-zA-Z]{2,4}(?::[0-9]+)?(?:/[^ \n\r\"\'<]+)?');
12 define('SG_REGEXP_WWWURL', 'www\.(?:[a-zA-Z0-9\-]+\.)*[a-zA-Z]{2,4}(?:/[^ \n\r\"\'<]+)?'); 12 define('SG_REGEXP_WWWURL', 'www\.(?:[a-zA-Z0-9\-]+\.)*[a-zA-Z]{2,4}(?:/[^ \n\r\"\'<]+)?');
13 define('SG_REGEXP_EMAILURL', '(?:[\w][\w\.\-]+)+@(?:[\w\-]+\.)+[a-zA-Z]{2,4}'); 13 define('SG_REGEXP_EMAILURL', '(?:[\w][\w\.\-]+)+@(?:[\w\-]+\.)+[a-zA-Z]{2,4}');
14   14  
15 /** 15 /**
16 * Provides functions for handling galleries and images 16 * Provides functions for handling galleries and images
17 * @package singapore 17 * @package singapore
18 * @author Tamlyn Rhodes <tam at zenology dot co dot uk> 18 * @author Tamlyn Rhodes <tam at zenology dot co dot uk>
19 */ 19 */
20 class Singapore 20 class Singapore
21 { 21 {
22 /** 22 /**
23 * current script version 23 * current script version
24 * @var string 24 * @var string
25 */ 25 */
26 var $version = "0.10.1"; 26 var $version = "0.10.1";
27 27
28 /** 28 /**
29 * instance of a {@link sgConfig} object representing the current 29 * instance of a {@link sgConfig} object representing the current
30 * script configuration 30 * script configuration
31 * @var sgConfig 31 * @var sgConfig
32 */ 32 */
33 var $config; 33 var $config;
34 34
35 /** 35 /**
36 * instance of the currently selected IO handler object 36 * instance of the currently selected IO handler object
37 * @var sgIO_csv 37 * @var sgIO_csv
38 */ 38 */
39 var $io; 39 var $io;
40 40
41 /** 41 /**
42 * instance of a {@link Translator} 42 * instance of a {@link Translator}
43 * @var Translator 43 * @var Translator
44 */ 44 */
45 var $translator; 45 var $translator;
46 46
47 /** 47 /**
48 * instance of a {@link sgGallery} representing the current gallery 48 * instance of a {@link sgGallery} representing the current gallery
49 * @var sgGallery 49 * @var sgGallery
50 */ 50 */
51 var $gallery; 51 var $gallery;
52 52
53 /** 53 /**
54 * reference to the currently selected {@link sgImage} object in the 54 * reference to the currently selected {@link sgImage} object in the
55 * $images array of {@link $gallery} 55 * $images array of {@link $gallery}
56 * @var sgImage 56 * @var sgImage
57 */ 57 */
58 var $image; 58 var $image;
59 59
60 /** 60 /**
61 * two character code of language currently in use 61 * two character code of language currently in use
62 * @var string 62 * @var string
63 */ 63 */
64 var $language = null; 64 var $language = null;
65 65
66 /** 66 /**
67 * name of template currently in use 67 * name of template currently in use
68 * @var string 68 * @var string
69 */ 69 */
70 var $template = null; 70 var $template = null;
71 71
72 /** 72 /**
73 * details of current user 73 * details of current user
74 * @var sgUser 74 * @var sgUser
75 */ 75 */
76 var $user = null; 76 var $user = null;
77 77
78 /** 78 /**
79 * name of action requested 79 * name of action requested
80 * @var string 80 * @var string
81 */ 81 */
82 var $action = null; 82 var $action = null;
83 83
84 /** 84 /**
85 * Constructor, does all init type stuff. This code is a total mess. 85 * Constructor, does all init type stuff. This code is a total mess.
86 * @param string the path to the base singapore directory 86 * @param string the path to the base singapore directory
87 */ 87 */
88 function Singapore($basePath = "") 88 function Singapore($basePath = "")
89 { 89 {
90 //import class definitions 90 //import class definitions
91 //io handler class included once config is loaded 91 //io handler class included once config is loaded
92 require_once $basePath."includes/translator.class.php"; 92 require_once $basePath."includes/translator.class.php";
93 require_once $basePath."includes/thumbnail.class.php"; 93 require_once $basePath."includes/thumbnail.class.php";
94 require_once $basePath."includes/gallery.class.php"; 94 require_once $basePath."includes/gallery.class.php";
95 require_once $basePath."includes/config.class.php"; 95 require_once $basePath."includes/config.class.php";
96 require_once $basePath."includes/image.class.php"; 96 require_once $basePath."includes/image.class.php";
97 require_once $basePath."includes/user.class.php"; 97 require_once $basePath."includes/user.class.php";
98 98
99 //start execution timer 99 //start execution timer
100 $this->scriptStartTime = microtime(); 100 $this->scriptStartTime = microtime();
101 101
102 //remove slashes 102 //remove slashes
103 if(get_magic_quotes_gpc()) 103 if(get_magic_quotes_gpc())
104 $_REQUEST = array_map(array("Singapore","arraystripslashes"), $_REQUEST); 104 $_REQUEST = array_map(array("Singapore","arraystripslashes"), $_REQUEST);
105 105
106 //desanitize request 106 //desanitize request
107 $_REQUEST = array_map("htmlentities", $_REQUEST); 107 $_REQUEST = array_map("htmlentities", $_REQUEST);
108 108
109 //load config from singapore root directory 109 //load config from singapore root directory
110 $this->config =& sgConfig::getInstance(); 110 $this->config =& sgConfig::getInstance();
111 $this->config->loadConfig($basePath."singapore.ini"); 111 $this->config->loadConfig($basePath."singapore.ini");
112 $this->config->loadConfig($basePath."secret.ini.php"); 112 $this->config->loadConfig($basePath."secret.ini.php");
113 113
114 //if instantiated remotely... 114 //if instantiated remotely...
115 if(!empty($basePath)) { 115 if(!empty($basePath)) {
116 //...try to guess base path and relative url 116 //...try to guess base path and relative url
117 if(empty($this->config->base_path)) 117 if(empty($this->config->base_path))
118 $this->config->base_path = $basePath; 118 $this->config->base_path = $basePath;
119 if(empty($this->config->base_url)) 119 if(empty($this->config->base_url))
120 $this->config->base_url = $basePath; 120 $this->config->base_url = $basePath;
121 //...load local config if present 121 //...load local config if present
122 //may over-ride guessed values above 122 //may over-ride guessed values above
123 $this->config->loadConfig("singapore.local.ini"); 123 $this->config->loadConfig("singapore.local.ini");
124 } 124 }
125 125
126 //set current gallery to root if not specified in url 126 //set current gallery to root if not specified in url
127 $galleryId = isset($_REQUEST[$this->config->url_gallery]) ? $_REQUEST[$this->config->url_gallery] : "."; 127 $galleryId = isset($_REQUEST[$this->config->url_gallery]) ? $_REQUEST[$this->config->url_gallery] : ".";
128 128
129 //load config from gallery ini file (gallery.ini) if present 129 //load config from gallery ini file (gallery.ini) if present
130 $this->config->loadConfig($basePath.$this->config->pathto_galleries.$galleryId."/gallery.ini"); 130 $this->config->loadConfig($basePath.$this->config->pathto_galleries.$galleryId."/gallery.ini");
131 131
132 //set current template from request vars or config 132 //set current template from request vars or config
133 //first, preset template to default one 133 //first, preset template to default one
134 $this->template = $this->config->default_template; 134 $this->template = $this->config->default_template;
135 //then check if requested template exists 135 //then check if requested template exists
136 if(!empty($_REQUEST[$this->config->url_template])) { 136 if(!empty($_REQUEST[$this->config->url_template])) {
137 $templates = Singapore::getListing($this->config->base_path.$this->config->pathto_templates); 137 $templates = Singapore::getListing($this->config->base_path.$this->config->pathto_templates);
138 foreach($templates->dirs as $single) { 138 foreach($templates->dirs as $single) {
139 if($single == $_REQUEST[$this->config->url_template]) { 139 if($single == $_REQUEST[$this->config->url_template]) {
140 $this->template = $single; 140 $this->template = $single;
141 break; 141 break;
142 } 142 }
143 } 143 }
144 } 144 }
145   145  
146 $this->config->pathto_current_template = $this->config->pathto_templates.$this->template.'/'; 146 $this->config->pathto_current_template = $this->config->pathto_templates.$this->template.'/';
147 //load config from template ini file (template.ini) if present 147 //load config from template ini file (template.ini) if present
148 $this->config->loadConfig($basePath.$this->config->pathto_current_template."template.ini"); 148 $this->config->loadConfig($basePath.$this->config->pathto_current_template."template.ini");
149 149
150 //set runtime values 150 //set runtime values
151 $this->config->pathto_logs = $this->config->pathto_data_dir."logs/"; 151 $this->config->pathto_logs = $this->config->pathto_data_dir."logs/";
152 $this->config->pathto_cache = $this->config->pathto_data_dir."cache/"; 152 $this->config->pathto_cache = $this->config->pathto_data_dir."cache/";
153 $this->config->pathto_admin_template = $this->config->pathto_templates.$this->config->admin_template_name."/"; 153 $this->config->pathto_admin_template = $this->config->pathto_templates.$this->config->admin_template_name."/";
154 154
155 //set current language from request vars or config 155 //set current language from request vars or config
156 if(!empty($_REQUEST[$this->config->url_lang])) 156 if(!empty($_REQUEST[$this->config->url_lang]))
157 $this->language = $_REQUEST[$this->config->url_lang]; 157 $this->language = $_REQUEST[$this->config->url_lang];
158 else { 158 else {
159 $this->language = $this->config->default_language; 159 $this->language = $this->config->default_language;
160 if($this->config->detect_language) 160 if($this->config->detect_language)
161 foreach($this->getBrowserLanguages() as $lang) 161 foreach($this->getBrowserLanguages() as $lang)
162 if($lang=="en" || file_exists($basePath.$this->config->pathto_locale."singapore.".$lang.".pmo")) { 162 if($lang=="en" || file_exists($basePath.$this->config->pathto_locale."singapore.".$lang.".pmo")) {
163 $this->language = $lang; 163 $this->language = $lang;
164 break; 164 break;
165 } 165 }
166 } 166 }
167 167
168 //read the language file 168 //read the language file
169 $this->translator =& Translator::getInstance($this->language); 169 $this->translator =& Translator::getInstance($this->language);
170 $this->translator->readLanguageFile($this->config->base_path.$this->config->pathto_locale."singapore.".$this->language.".pmo"); 170 $this->translator->readLanguageFile($this->config->base_path.$this->config->pathto_locale."singapore.".$this->language.".pmo");
171 171
172 //clear the UMASK 172 //clear the UMASK
173 umask(0); 173 umask(0);
174 174
175 //include IO handler class and create instance 175 //include IO handler class and create instance
176 require_once $basePath."includes/io_".$this->config->io_handler.".class.php"; 176 require_once $basePath."includes/io_".$this->config->io_handler.".class.php";
177 $ioClassName = "sgIO_".$this->config->io_handler; 177 $ioClassName = "sgIO_".$this->config->io_handler;
178 $this->io = new $ioClassName($this->config); 178 $this->io = new $ioClassName($this->config);
179 179
180 //load gallery and image info 180 //load gallery and image info
181 $this->selectGallery($galleryId); 181 $this->selectGallery($galleryId);
182 182
183 //set character set 183 //set character set
184 if(!empty($this->translator->languageStrings[0]["charset"])) 184 if(!empty($this->translator->languageStrings[0]["charset"]))
185 $this->character_set = $this->translator->languageStrings[0]["charset"]; 185 $this->character_set = $this->translator->languageStrings[0]["charset"];
186 else 186 else
187 $this->character_set = $this->config->default_charset; 187 $this->character_set = $this->config->default_charset;
188 188
189 //set action to perform 189 //set action to perform
190 if(empty($_REQUEST["action"])) $this->action = "view"; 190 if(empty($_REQUEST["action"])) $this->action = "view";
191 else $this->action = $_REQUEST["action"]; 191 else $this->action = $_REQUEST["action"];
192 192
193 193
194 } 194 }
195 195
196 /** 196 /**
197 * Load gallery and image info 197 * Load gallery and image info
198 * @param string the id of the gallery to load (optional) 198 * @param string the id of the gallery to load (optional)
199 */ 199 */
200 function selectGallery($galleryId = "") 200 function selectGallery($galleryId = "")
201 { 201 {
202 if(empty($galleryId)) $galleryId = isset($_REQUEST[$this->config->url_gallery]) ? $_REQUEST[$this->config->url_gallery] : "."; 202 if(empty($galleryId)) $galleryId = isset($_REQUEST[$this->config->url_gallery]) ? $_REQUEST[$this->config->url_gallery] : ".";
203 203
204 //try to validate gallery id 204 //try to validate gallery id
205 if(strlen($galleryId)>1 && $galleryId{1} != '/') $galleryId = './'.$galleryId; 205 if(strlen($galleryId)>1 && $galleryId{1} != '/') $galleryId = './'.$galleryId;
206 206
207 //detect back-references to avoid file-system walking 207 //detect back-references to avoid file-system walking
208 if(strpos($galleryId,"../")!==false) $galleryId = "."; 208 if(strpos($galleryId,"../")!==false) $galleryId = ".";
209 209
210 //find all ancestors to current gallery 210 //find all ancestors to current gallery
211 $this->ancestors = array(); 211 $this->ancestors = array();
212 $ancestorNames = explode("/", $galleryId); 212 $ancestorNames = explode("/", $galleryId);
213 $numberOfAncestors = count($ancestorNames); 213 $numberOfAncestors = count($ancestorNames);
214 214
215 //construct fully qualified gallery ids 215 //construct fully qualified gallery ids
216 $ancestorIds[0] = "."; 216 $ancestorIds[0] = ".";
217 for($i=1; $i<$numberOfAncestors; $i++) 217 for($i=1; $i<$numberOfAncestors; $i++)
218 $ancestorIds[$i] = $ancestorIds[$i-1]."/".$ancestorNames[$i]; 218 $ancestorIds[$i] = $ancestorIds[$i-1]."/".$ancestorNames[$i];
219 219
220 //fetch galleries passing previous gallery as parent pointer 220 //fetch galleries passing previous gallery as parent pointer
221 for($i=0; $i<$numberOfAncestors; $i++) 221 for($i=0; $i<$numberOfAncestors; $i++)
222 if(!$this->ancestors[$i] =& $this->io->getGallery( 222 if(!$this->ancestors[$i] =& $this->io->getGallery(
223 $ancestorIds[$i], $this->ancestors[$i-1], 223 $ancestorIds[$i], $this->ancestors[$i-1],
224 //only fetch children of bottom level gallery 224 //only fetch children of bottom level gallery
225 ($i==$numberOfAncestors-1) ? 1 : 0 225 ($i==$numberOfAncestors-1) ? 1 : 0
226 ) 226 )
227 ) 227 )
228 break; 228 break;
229 229
230 //need to remove bogus parent of root gallery created by previous step 230 //need to remove bogus parent of root gallery created by previous step
231 unset($this->ancestors[-1]); 231 unset($this->ancestors[-1]);
232 232
233 //set reference to current gallery 233 //set reference to current gallery
234 $this->gallery = &$this->ancestors[count($this->ancestors)-1]; 234 $this->gallery = &$this->ancestors[count($this->ancestors)-1];
235 235
236 //check if gallery was successfully fetched 236 //check if gallery was successfully fetched
237 if($this->gallery == null) { 237 if($this->gallery == null) {
238 $this->gallery = new sgGallery($galleryId, $this->ancestors[0]); 238 $this->gallery = new sgGallery($galleryId, $this->ancestors[0]);
239 $this->gallery->name = $this->translator->_g("Gallery not found '%s'",htmlspecialchars($galleryId)); 239 $this->gallery->name = $this->translator->_g("Gallery not found '%s'",htmlspecialchars($galleryId));
240 } 240 }
241 241
242 //sort galleries and images 242 //sort galleries and images
243 $GLOBALS["sgSortOrder"] = $this->config->gallery_sort_order; 243 $GLOBALS["sgSortOrder"] = $this->config->gallery_sort_order;
244 if($this->config->gallery_sort_order!="x") usort($this->gallery->galleries, array("Singapore","multiSort")); 244 if($this->config->gallery_sort_order!="x") usort($this->gallery->galleries, array("Singapore","multiSort"));
245 $GLOBALS["sgSortOrder"] = $this->config->image_sort_order; 245 $GLOBALS["sgSortOrder"] = $this->config->image_sort_order;
246 if($this->config->image_sort_order!="x") usort($this->gallery->images, array("Singapore","multiSort")); 246 if($this->config->image_sort_order!="x") usort($this->gallery->images, array("Singapore","multiSort"));
247 unset($GLOBALS["sgSortOrder"]); 247 unset($GLOBALS["sgSortOrder"]);
248 248
249 //if startat is set then cast to int otherwise startat 0 249 //if startat is set then cast to int otherwise startat 0
250 $this->gallery->startat = isset($_REQUEST[$this->config->url_startat]) ? (int)$_REQUEST[$this->config->url_startat] : 0; 250 $this->gallery->startat = isset($_REQUEST[$this->config->url_startat]) ? (int)$_REQUEST[$this->config->url_startat] : 0;
251 $this->startat = $this->gallery->startat; //depreciated 251 $this->startat = $this->gallery->startat; //depreciated
252 252
253 //select the image (if any) 253 //select the image (if any)
254 if(!empty($_REQUEST[$this->config->url_image])) 254 if(!empty($_REQUEST[$this->config->url_image]))
255 $this->selectImage($_REQUEST[$this->config->url_image]); 255 $this->selectImage($_REQUEST[$this->config->url_image]);
256 256
257 //load hit data 257 //load hit data
258 if($this->config->track_views || $this->config->show_views) 258 if($this->config->track_views || $this->config->show_views)
259 $this->io->getHits($this->gallery); 259 $this->io->getHits($this->gallery);
260 260
261 //update and save hit data 261 //update and save hit data
262 if($this->config->track_views) { 262 if($this->config->track_views) {
263 if($this->isImagePage()) { 263 if($this->isImagePage()) {
264 $this->image->hits++; 264 $this->image->hits++;
265 $this->image->lasthit = time(); 265 $this->image->lasthit = time();
266 } elseif($this->gallery->startat == 0) { 266 } elseif($this->gallery->startat == 0) {
267 $this->gallery->hits++; 267 $this->gallery->hits++;
268 $this->gallery->lasthit = time(); 268 $this->gallery->lasthit = time();
269 } 269 }
270 $this->io->putHits($this->gallery); 270 $this->io->putHits($this->gallery);
271 } 271 }
272 } 272 }
273 273
274 /** 274 /**
275 * Selects an image from the current gallery 275 * Selects an image from the current gallery
276 * @param mixed either the filename of the image to select or the integer 276 * @param mixed either the filename of the image to select or the integer
277 * index of its position in the images array 277 * index of its position in the images array
278 * @return boolean true on success; false otherwise 278 * @return boolean true on success; false otherwise
279 */ 279 */
280 function selectImage($image) 280 function selectImage($image)
281 { 281 {
282 if(is_string($image)) { 282 if(is_string($image)) {
283 foreach($this->gallery->images as $index => $img) 283 foreach($this->gallery->images as $index => $img)
284 if($img->id == $image) { 284 if($img->id == $image) {
285 $this->image =& $this->gallery->images[$index]; 285 $this->image =& $this->gallery->images[$index];
286 return true; 286 return true;
287 } 287 }
288 } elseif(is_int($image) && $image >= 0 && $image < count($this->gallery->images)) { 288 } elseif(is_int($image) && $image >= 0 && $image < count($this->gallery->images)) {
289 $this->image =& $this->gallery->images[$image]; 289 $this->image =& $this->gallery->images[$image];
290 return true; 290 return true;
291 } 291 }
292 $this->image =& new sgImage("", $this->gallery); 292 $this->image =& new sgImage("", $this->gallery);
293 $this->image->name = $this->translator->_g("Image not found '%s'",htmlspecialchars($image)); 293 $this->image->name = $this->translator->_g("Image not found '%s'",htmlspecialchars($image));
294 return false; 294 return false;
295 } 295 }
296 296
297 297
298 /** 298 /**
299 * Obfuscates the given email address by replacing "." with "dot" and "@" with "at" 299 * Obfuscates the given email address by replacing "." with "dot" and "@" with "at"
300 * @param string email address to obfuscate 300 * @param string email address to obfuscate
301 * @param boolean override the obfuscate_email config setting (optional) 301 * @param boolean override the obfuscate_email config setting (optional)
302 * @return string obfuscated email address or HTML mailto link 302 * @return string obfuscated email address or HTML mailto link
303 */ 303 */
304 function formatEmail($email, $forceObfuscate = false) 304 function formatEmail($email, $forceObfuscate = false)
305 { 305 {
306 if($this->config->obfuscate_email || $forceObfuscate) 306 if($this->config->obfuscate_email || $forceObfuscate)
307 return strtr($email,array("@" => ' <b>'.$this->translator->_g("email|at").'</b> ', "." => ' <b>'.$this->translator->_g("email|dot").'</b> ')); 307 return strtr($email,array("@" => ' <b>'.$this->translator->_g("email|at").'</b> ', "." => ' <b>'.$this->translator->_g("email|dot").'</b> '));
308 else 308 else
309 return "<a href=\"mailto:".$email."\">".$email."</a>"; 309 return "<a href=\"mailto:".$email."\">".$email."</a>";
310 } 310 }
311   311  
312 312
313 /** 313 /**
314 * Returns image name for image pages and gallery name for gallery pages. 314 * Returns image name for image pages and gallery name for gallery pages.
315 * If either of these is empty, returns gallery_name config option. 315 * If either of these is empty, returns gallery_name config option.
316 * 316 *
317 * @return string Title of current page 317 * @return string Title of current page
318 */ 318 */
319 function pageTitle() 319 function pageTitle()
320 { 320 {
321 $crumbArray = $this->crumbLineArray(); 321 $crumbArray = $this->crumbLineArray();
322 322
323 $ret = ""; 323 $ret = "";
324 for($i=count($crumbArray)-1;$i>0;$i--) 324 for($i=count($crumbArray)-1;$i>0;$i--)
325 $ret .= $crumbArray[$i]->nameForce()." &lt; "; 325 $ret .= $crumbArray[$i]->nameForce()." &lt; ";
326 $ret .= $crumbArray[$i]->nameForce(); 326 $ret .= $crumbArray[$i]->nameForce();
327 327
328 return $ret; 328 return $ret;
329 } 329 }
330 330
331 /** 331 /**
332 * @return bool true if this is an image page; false otherwise 332 * @return bool true if this is an image page; false otherwise
333 */ 333 */
334 function isImagePage() 334 function isImagePage()
335 { 335 {
336 return !empty($this->image); 336 return !empty($this->image);
337 } 337 }
338 338
339 /** 339 /**
340 * @return bool true if this is a non-album gallery page; false otherwise 340 * @return bool true if this is a non-album gallery page; false otherwise
341 */ 341 */
342 function isGalleryPage() 342 function isGalleryPage()
343 { 343 {
344 return !empty($this->gallery) && $this->gallery->galleryCount()>0;; 344 return !empty($this->gallery) && $this->gallery->galleryCount()>0;;
345 } 345 }
346 346
347 /** 347 /**
348 * @return bool true if this is an album page; false otherwise 348 * @return bool true if this is an album page; false otherwise
349 */ 349 */
350 function isAlbumPage() 350 function isAlbumPage()
351 { 351 {
352 return !$this->isGalleryPage() && !$this->isImagePage() && !empty($this->gallery); 352 return !$this->isGalleryPage() && !$this->isImagePage() && !empty($this->gallery);
353 } 353 }
354 354
355 355
356 /** 356 /**
357 * @return int the script execution time in seconds rounded to two decimal places 357 * @return int the script execution time in seconds rounded to two decimal places
358 */ 358 */
359 function scriptExecTime() 359 function scriptExecTime()
360 { 360 {
361 $scriptStartTime = $this->scriptStartTime; 361 $scriptStartTime = $this->scriptStartTime;
362 $scriptEndTime = microtime(); 362 $scriptEndTime = microtime();
363 363
364 list($usec, $sec) = explode(" ",$scriptStartTime); 364 list($usec, $sec) = explode(" ",$scriptStartTime);
365 $scriptStartTime = (float)$usec + (float)$sec; 365 $scriptStartTime = (float)$usec + (float)$sec;
366 list($usec, $sec) = explode(" ",$scriptEndTime); 366 list($usec, $sec) = explode(" ",$scriptEndTime);
367 $scriptEndTime = (float)$usec + (float)$sec; 367 $scriptEndTime = (float)$usec + (float)$sec;
368 368
369 $scriptExecTime = floor(($scriptEndTime - $scriptStartTime)*100)/100; 369 $scriptExecTime = floor(($scriptEndTime - $scriptStartTime)*100)/100;
370 return $scriptExecTime; 370 return $scriptExecTime;
371 } 371 }
372 372
373 /** 373 /**
374 * Displays the script execution time if configured to do so 374 * Displays the script execution time if configured to do so
375 * @returns string the script execution time 375 * @returns string the script execution time
376 */ 376 */
377 function scriptExecTimeText() 377 function scriptExecTimeText()
378 { 378 {
379 if($this->config->show_execution_time) 379 if($this->config->show_execution_time)
380 return $this->translator->_g("Page created in %s seconds",$this->scriptExecTime()); 380 return $this->translator->_g("Page created in %s seconds",$this->scriptExecTime());
381 else 381 else
382 return ""; 382 return "";
383 } 383 }
384 384
385 function poweredByText() 385 function poweredByText()
386 { 386 {
387 return $this->translator->_g("Powered by").' <a href="http://www.sgal.org/">singapore</a>'; 387 return $this->translator->_g("Powered by").' <a href="http://www.sgal.org/">singapore</a>';
388 } 388 }
389 389
390 function allRightsReserved() 390 function allRightsReserved()
391 { 391 {
392 return $this->translator->_g("All rights reserved."); 392 return $this->translator->_g("All rights reserved.");
393 } 393 }
394 394
395 function licenseText() 395 function licenseText()
396 { 396 {
397 return $this->translator->_g("Images may not be reproduced in any form without the express written permission of the copyright holder."); 397 return $this->translator->_g("Images may not be reproduced in any form without the express written permission of the copyright holder.");
398 } 398 }
399 399
400 function adminURL() 400 function adminURL()
401 { 401 {
402 return '<a href="'.$this->config->base_url.'admin.php">'; 402 return '<a href="'.$this->config->base_url.'admin.php">';
403 } 403 }
404 404
405 function adminLink() 405 function adminLink()
406 { 406 {
407 return $this->adminURL().$this->translator->_g("Log in")."</a>"; 407 return $this->adminURL().$this->translator->_g("Log in")."</a>";
408 } 408 }
409 409
410 410
411 /** 411 /**
412 * Checks to see if the user is currently logged in to admin mode. Also resets 412 * Checks to see if the user is currently logged in to admin mode. Also resets
413 * the login timeout to the current time. 413 * the login timeout to the current time.
414 * @returns boolean true if the user is logged in; false otherwise 414 * @returns boolean true if the user is logged in; false otherwise
415 * @static 415 * @static
416 */ 416 */
417 function isLoggedIn() 417 function isLoggedIn()
418 { 418 {
419 if( 419 if(
420 isset($this->user) && 420 isset($this->user) &&
421 $_SESSION["sgUser"]["ip"] == $_SERVER["REMOTE_ADDR"] && 421 $_SESSION["sgUser"]["ip"] == $_SERVER["REMOTE_ADDR"] &&
422 (time() - $_SESSION["sgUser"]["loginTime"] < 600) 422 (time() - $_SESSION["sgUser"]["loginTime"] < 600)
423 ) { 423 ) {
424 //reset loginTime to current time 424 //reset loginTime to current time
425 $_SESSION["sgUser"]["loginTime"] = time(); 425 $_SESSION["sgUser"]["loginTime"] = time();
426 return true; 426 return true;
427 } 427 }
428 return false; 428 return false;
429 } 429 }
430 430
431 function loadUser($username = null) 431 function loadUser($username = null)
432 { 432 {
433 if($username == null) 433 if($username == null)
434 if(isset($_SESSION["sgUser"])) 434 if(isset($_SESSION["sgUser"]))
435 $username = $_SESSION["sgUser"]["username"]; 435 $username = $_SESSION["sgUser"]["username"];
436 else 436 else
437 return false; 437 return false;
438 438
439 $users = $this->io->getUsers(); 439 $users = $this->io->getUsers();
440 foreach($users as $user) 440 foreach($users as $user)
441 if($user->username == $username) { 441 if($user->username == $username) {
442 $this->user = $user; 442 $this->user = $user;
443 return $user; 443 return $user;
444 } 444 }
445 return false; 445 return false;
446 } 446 }
447 447
448 /** 448 /**
449 * Creates an array of objects each representing an item in the crumb line. 449 * Creates an array of objects each representing an item in the crumb line.
450 * @return array the items of the crumb line 450 * @return array the items of the crumb line
451 */ 451 */
452 function crumbLineArray() 452 function crumbLineArray()
453 { 453 {
454 $crumb = $this->ancestors; 454 $crumb = $this->ancestors;
455 455
456 if($this->isImagePage()) $crumb[] = $this->image; 456 if($this->isImagePage()) $crumb[] = $this->image;
457 457
458 return $crumb; 458 return $crumb;
459 } 459 }
460 460
461 /** 461 /**
462 * @return string the complete crumb line with links 462 * @return string the complete crumb line with links
463 */ 463 */
464 function crumbLineText() 464 function crumbLineText()
465 { 465 {
466 $crumbArray = $this->crumbLineArray(); 466 $crumbArray = $this->crumbLineArray();
467   467  
468 $ret = ""; 468 $ret = "";
469 for($i=0;$i<count($crumbArray)-1;$i++) 469 for($i=0;$i<count($crumbArray)-1;$i++)
470 $ret .= $crumbArray[$i]->nameLink()." &gt;\n"; 470 $ret .= $crumbArray[$i]->nameLink()." &gt;\n";
471 $ret .= $crumbArray[$i]->nameForce(); 471 $ret .= $crumbArray[$i]->nameForce();
472   472  
473 return $ret; 473 return $ret;
474 } 474 }
475 475
476 function crumbLine() 476 function crumbLine()
477 { 477 {
478 return $this->translator->_g("crumb line|You are here:")." ".$this->crumbLineText(); 478 return $this->translator->_g("crumb line|You are here:")." ".$this->crumbLineText();
479 } 479 }
480 480
481 /** 481 /**
482 * Generates the HTML code for imagemap_navigation 482 * Generates the HTML code for imagemap_navigation
483 * @return string imagemap HTML code 483 * @return string imagemap HTML code
484 */ 484 */
485 function imageMap() 485 function imageMap()
486 { 486 {
487 if(!$this->config->imagemap_navigation) return ""; 487 if(!$this->config->imagemap_navigation) return "";
488 488
489 $imageWidth = $this->image->width(); 489 $imageWidth = $this->image->width();
490 $imageHeight = $this->image->height(); 490 $imageHeight = $this->image->height();
491 $middleX = round($imageWidth/2); 491 $middleX = round($imageWidth/2);
492 $middleY = round($imageHeight/2); 492 $middleY = round($imageHeight/2);
493 493
494 $ret = "<map name=\"sgNavMap\" id=\"sgNavMap\">\n"; 494 $ret = "<map name=\"sgNavMap\" id=\"sgNavMap\">\n";
495 if($this->image->hasNext()) $ret .= '<area href="'.$this->image->nextURL().'" alt="'.$this->image->nextText().'" title="'.$this->image->nextText().'" shape="poly" '; 495 if($this->image->hasNext()) $ret .= '<area href="'.$this->image->nextURL().'" alt="'.$this->image->nextText().'" title="'.$this->image->nextText().'" shape="poly" ';
496 else $ret .= '<area href="'.$this->image->parentURL().'" alt="'.$this->image->parentText().'" title="'.$this->image->parentText().'" shape="poly" '; 496 else $ret .= '<area href="'.$this->image->parentURL().'" alt="'.$this->image->parentText().'" title="'.$this->image->parentText().'" shape="poly" ';
497 $ret .= "coords=\"$middleX,$middleY,$imageWidth,$imageHeight,$imageWidth,0,$middleX,$middleY\" />\n"; 497 $ret .= "coords=\"$middleX,$middleY,$imageWidth,$imageHeight,$imageWidth,0,$middleX,$middleY\" />\n";
498 if($this->image->hasPrev()) $ret .= '<area href="'.$this->image->prevURL().'" alt="'.$this->image->prevText().'" title="'.$this->image->prevText().'" shape="poly" '; 498 if($this->image->hasPrev()) $ret .= '<area href="'.$this->image->prevURL().'" alt="'.$this->image->prevText().'" title="'.$this->image->prevText().'" shape="poly" ';
499 else $ret .= '<area href="'.$this->image->parentURL().'" alt="'.$this->image->parentText().'" title="'.$this->image->parentText().'" shape="poly" '; 499 else $ret .= '<area href="'.$this->image->parentURL().'" alt="'.$this->image->parentText().'" title="'.$this->image->parentText().'" shape="poly" ';
500 $ret .= "coords=\"$middleX,$middleY,0,0,0,$imageHeight,$middleX,$middleY\" />\n"; 500 $ret .= "coords=\"$middleX,$middleY,0,0,0,$imageHeight,$middleX,$middleY\" />\n";
501 $ret .= '<area href="'.$this->image->parentURL().'" alt="'.$this->image->parentText().'" title="'.$this->image->parentText().'" shape="poly" '; 501 $ret .= '<area href="'.$this->image->parentURL().'" alt="'.$this->image->parentText().'" title="'.$this->image->parentText().'" shape="poly" ';
502 $ret .= "coords=\"$middleX,$middleY,0,0,$imageWidth,0,$middleX,$middleY\" />\n"; 502 $ret .= "coords=\"$middleX,$middleY,0,0,$imageWidth,0,$middleX,$middleY\" />\n";
503 $ret .= '</map>'; 503 $ret .= '</map>';
504 504
505 return $ret; 505 return $ret;
506 } 506 }
507 507
508 /** 508 /**
509 * Generates the HTML code for the language select box 509 * Generates the HTML code for the language select box
510 * @return string select box HTML code 510 * @return string select box HTML code
511 */ 511 */
512 function languageFlipper() 512 function languageFlipper()
513 { 513 {
514 if(!$this->config->language_flipper) return ""; 514 if(!$this->config->language_flipper) return "";
515 515
516 $languageCache = $this->config->base_path.$this->config->pathto_data_dir."languages.cache"; 516 $languageCache = $this->config->base_path.$this->config->pathto_data_dir."languages.cache";
517 // Look for the language file 517 // Look for the language file
518 if(!file_exists($languageCache)) 518 if(!file_exists($languageCache))
519 return ""; 519 return "";
520 520
521 // Open the file 521 // Open the file
522 $fp = @fopen($languageCache, "r"); 522 $fp = @fopen($languageCache, "r");
523 if (!$fp) return ""; 523 if (!$fp) return "";
524 524
525 // Read contents 525 // Read contents
526 $str = ''; 526 $str = '';
527 while (!feof($fp)) $str .= fread($fp, 1024); 527 while (!feof($fp)) $str .= fread($fp, 1024);
528 // Unserialize 528 // Unserialize
529 $availableLanguages = @unserialize($str); 529 $availableLanguages = @unserialize($str);
530 530
531 $ret = '<div class="sgLanguageFlipper">'; 531 $ret = '<div class="sgLanguageFlipper">';
532 $ret .= '<form method="get" action="'.$_SERVER["PHP_SELF"]."\">\n"; 532 $ret .= '<form method="get" action="'.$_SERVER["PHP_SELF"]."\">\n";
533 //carry over current get vars 533 //carry over current get vars
534 foreach($_GET as $var => $val) 534 foreach($_GET as $var => $val)
535 $ret .= '<input type="hidden" name="'.$var.'" value="'.htmlspecialchars($val)."\" />\n"; 535 $ret .= '<input type="hidden" name="'.$var.'" value="'.htmlspecialchars($val)."\" />\n";
536 $ret .= '<select name="'.$this->config->url_lang."\">\n"; 536 $ret .= '<select name="'.$this->config->url_lang."\">\n";
537 $ret .= ' <option value="'.$this->config->default_language.'">'.$this->translator->_g("Select language...")."</option>\n"; 537 $ret .= ' <option value="'.$this->config->default_language.'">'.$this->translator->_g("Select language...")."</option>\n";
538 foreach($availableLanguages as $code => $name) { 538 foreach($availableLanguages as $code => $name) {
539 $ret .= ' <option value="'.$code.'"'; 539 $ret .= ' <option value="'.$code.'"';
540 if($code == $this->language && $this->language != $this->config->default_language) 540 if($code == $this->language && $this->language != $this->config->default_language)
541 $ret .= 'selected="true" '; 541 $ret .= 'selected="true" ';
542 $ret .= '>'.htmlentities($name)."</option>\n"; 542 $ret .= '>'.htmlentities($name)."</option>\n";
543 } 543 }
544 $ret .= "</select>\n"; 544 $ret .= "</select>\n";
545 $ret .= '<input type="submit" class="button" value="'.$this->translator->_g("Go")."\" />\n"; 545 $ret .= '<input type="submit" class="button" value="'.$this->translator->_g("Go")."\" />\n";
546 $ret .= "</form></div>\n"; 546 $ret .= "</form></div>\n";
547 return $ret; 547 return $ret;
548 } 548 }
549 549
550 /** 550 /**
551 * Generates the HTML code for the template select box 551 * Generates the HTML code for the template select box
552 * @return string select box HTML code 552 * @return string select box HTML code
553 */ 553 */
554 function templateFlipper() 554 function templateFlipper()
555 { 555 {
556 if(!$this->config->template_flipper) return ""; 556 if(!$this->config->template_flipper) return "";
557 557
558 //get list of installed templates 558 //get list of installed templates
559 $templates = Singapore::getListing($this->config->base_path.$this->config->pathto_templates, "dirs"); 559 $templates = Singapore::getListing($this->config->base_path.$this->config->pathto_templates, "dirs");
560 560
561 $ret = '<div class="sgTemplateFlipper">'; 561 $ret = '<div class="sgTemplateFlipper">';
562 $ret .= '<form method="get" action="'.$_SERVER["PHP_SELF"]."\">\n"; 562 $ret .= '<form method="get" action="'.$_SERVER["PHP_SELF"]."\">\n";
563 //carry over current get vars 563 //carry over current get vars
564 foreach($_GET as $var => $val) 564 foreach($_GET as $var => $val)
565 $ret .= '<input type="hidden" name="'.$var.'" value="'.htmlspecialchars($val)."\" />\n"; 565 $ret .= '<input type="hidden" name="'.$var.'" value="'.htmlspecialchars($val)."\" />\n";
566 $ret .= '<select name="'.$this->config->url_template."\">\n"; 566 $ret .= '<select name="'.$this->config->url_template."\">\n";
567 $ret .= ' <option value="'.$this->config->default_template.'">'.$this->translator->_g("Select template...")."</option>\n"; 567 $ret .= ' <option value="'.$this->config->default_template.'">'.$this->translator->_g("Select template...")."</option>\n";
568 foreach($templates->dirs as $name) 568 foreach($templates->dirs as $name)
569 //do not list admin template(s) 569 //do not list admin template(s)
570 if(strpos($name, "admin_")===false) { 570 if(strpos($name, "admin_")===false) {
571 $ret .= ' <option value="'.$name.'"'; 571 $ret .= ' <option value="'.$name.'"';
572 if($name == $this->template && $this->template != $this->config->default_template) 572 if($name == $this->template && $this->template != $this->config->default_template)
573 $ret .= 'selected="true" '; 573 $ret .= 'selected="true" ';
574 $ret .= '>'.$name."</option>\n"; 574 $ret .= '>'.$name."</option>\n";
575 } 575 }
576 $ret .= "</select>\n"; 576 $ret .= "</select>\n";
577 $ret .= '<input type="submit" class="button" value="'.$this->translator->_g("Go")."\" />\n"; 577 $ret .= '<input type="submit" class="button" value="'.$this->translator->_g("Go")."\" />\n";
578 $ret .= "</form></div>\n"; 578 $ret .= "</form></div>\n";
579 return $ret; 579 return $ret;
580 } 580 }
581 581
582 582
583 /** 583 /**
584 * @param string $seperator optional string to seperate the Gallery Tab Links 584 * @param string $seperator optional string to seperate the Gallery Tab Links
585 * @return string 585 * @return string
586 */ 586 */
587 function galleryTab($seperator = " | ") 587 function galleryTab($seperator = " | ")
588 { 588 {
589 $showing = $this->galleryTabShowing(); 589 $showing = $this->galleryTabShowing();
590 return Singapore::conditional($this->galleryTabLinks(), $showing.$seperator."%s", $showing); 590 return Singapore::conditional($this->galleryTabLinks(), $showing.$seperator."%s", $showing);
591 } 591 }
592 592
593 /** 593 /**
594 * @return string 594 * @return string
595 */ 595 */
596 function galleryTabShowing() 596 function galleryTabShowing()
597 { 597 {
598 if($this->isAlbumPage()) { 598 if($this->isAlbumPage()) {
599 $total = $this->gallery->imageCount(); 599 $total = $this->gallery->imageCount();
600 $perPage = $this->config->thumb_number_album; 600 $perPage = $this->config->thumb_number_album;
601 } else { 601 } else {
602 $total = $this->gallery->galleryCount(); 602 $total = $this->gallery->galleryCount();
603 $perPage = $this->config->thumb_number_gallery; 603 $perPage = $this->config->thumb_number_gallery;
604 } 604 }
605 605
606 if($this->gallery->startat+$perPage > $total) 606 if($this->gallery->startat+$perPage > $total)
607 $last = $total; 607 $last = $total;
608 else 608 else
609 $last = $this->gallery->startat+$perPage; 609 $last = $this->gallery->startat+$perPage;
610 610
611 return $this->translator->_g("Showing %s-%s of %s",($this->gallery->startat+1),$last,$total); 611 return $this->translator->_g("Showing %s-%s of %s",($this->gallery->startat+1),$last,$total);
612 } 612 }
613 613
614 /** 614 /**
615 * @return string 615 * @return string
616 */ 616 */
617 function galleryTabLinks() 617 function galleryTabLinks()
618 { 618 {
619 $ret = ""; 619 $ret = "";
620 if($this->hasPrevPage()) 620 if($this->hasPrevPage())
621 $ret .= $this->prevPageLink()." "; 621 $ret .= $this->prevPageLink()." ";
622 622
623 //This is for compatibility with old templates 623 //This is for compatibility with old templates
624 //it detects if compatibility mode is on using method_exists() 624 //it detects if compatibility mode is on using method_exists()
625 if(!$this->gallery->isRoot() && method_exists($this, 'galleryName')) 625 if(!$this->gallery->isRoot() && method_exists($this, 'galleryName'))
626 $ret .= $this->gallery->parentLink(); 626 $ret .= $this->gallery->parentLink();
627 627
628 if($this->hasNextPage()) 628 if($this->hasNextPage())
629 $ret .= " ".$this->nextPageLink(); 629 $ret .= " ".$this->nextPageLink();
630 630
631 return $ret; 631 return $ret;
632 } 632 }
633 633
634 function navigationLinks() { 634 function navigationLinks() {
635 $ret = "<link rel=\"Top\" title=\"".$this->config->gallery_name."\" href=\"".$this->ancestors[0]->URL()."\" />\n"; 635 $ret = "<link rel=\"Top\" title=\"".$this->config->gallery_name."\" href=\"".$this->ancestors[0]->URL()."\" />\n";
636 636
637 if($this->isImagePage()) { 637 if($this->isImagePage()) {
638 $ret .= "<link rel=\"Up\" title=\"".$this->image->parent->name()."\" href=\"".$this->image->parent->URL()."\" />\n"; 638 $ret .= "<link rel=\"Up\" title=\"".$this->image->parent->name()."\" href=\"".$this->image->parent->URL()."\" />\n";
639 if ($this->image->hasPrev()) { 639 if ($this->image->hasPrev()) {
640 $first= $this->image->firstImage(); 640 $first= $this->image->firstImage();
641 $prev = $this->image->prevImage(); 641 $prev = $this->image->prevImage();
642 $ret .= "<link rel=\"First\" title=\"".$first->name()."\" href=\"".$first->URL()."\" />\n"; 642 $ret .= "<link rel=\"First\" title=\"".$first->name()."\" href=\"".$first->URL()."\" />\n";
643 $ret .= "<link rel=\"Prev\" title=\"".$prev->name()."\" href=\"".$prev->URL()."\" />\n"; 643 $ret .= "<link rel=\"Prev\" title=\"".$prev->name()."\" href=\"".$prev->URL()."\" />\n";
644 } 644 }
645 if ($this->image->hasNext()) { 645 if ($this->image->hasNext()) {
646 $next = $this->image->nextImage(); 646 $next = $this->image->nextImage();
647 $last = $this->image->lastImage(); 647 $last = $this->image->lastImage();
648 $ret .= "<link rel=\"Next\" title=\"".$next->name()."\" href=\"".$next->URL()."\" />\n"; 648 $ret .= "<link rel=\"Next\" title=\"".$next->name()."\" href=\"".$next->URL()."\" />\n";
649 $ret .= "<link rel=\"Last\" title=\"".$last->name()."\" href=\"".$last->URL()."\" />\n"; 649 $ret .= "<link rel=\"Last\" title=\"".$last->name()."\" href=\"".$last->URL()."\" />\n";
650 //prefetch next image 650 //prefetch next image
651 $ret .= "<link rel=\"Prefetch\" href=\"".$next->imageURL()."\" />\n"; 651 $ret .= "<link rel=\"Prefetch\" href=\"".$next->imageURL()."\" />\n";
652 } 652 }
653 } else { 653 } else {
654 if(!$this->gallery->isRoot()) 654 if(!$this->gallery->isRoot())
655 $ret .= "<link rel=\"Up\" title=\"".$this->gallery->parent->name()."\" href=\"".$this->gallery->parent->URL()."\" />\n"; 655 $ret .= "<link rel=\"Up\" title=\"".$this->gallery->parent->name()."\" href=\"".$this->gallery->parent->URL()."\" />\n";
656 if($this->hasPrevPage()) { 656 if($this->hasPrevPage()) {
657 $ret .= "<link rel=\"Prev\" title=\"".$this->translator->_g("gallery|Previous")."\" href=\"".$this->prevPageURL()."\" />\n"; 657 $ret .= "<link rel=\"Prev\" title=\"".$this->translator->_g("gallery|Previous")."\" href=\"".$this->prevPageURL()."\" />\n";
658 $ret .= "<link rel=\"First\" title=\"".$this->translator->_g("gallery|First")."\" href=\"".$this->firstPageURL()."\" />\n"; 658 $ret .= "<link rel=\"First\" title=\"".$this->translator->_g("gallery|First")."\" href=\"".$this->firstPageURL()."\" />\n";
659 } 659 }
660 if($this->hasNextPage()) { 660 if($this->hasNextPage()) {
661 $ret .= "<link rel=\"Next\" title=\"".$this->translator->_g("gallery|Next")."\" href=\"".$this->nextPageURL()."\" />\n"; 661 $ret .= "<link rel=\"Next\" title=\"".$this->translator->_g("gallery|Next")."\" href=\"".$this->nextPageURL()."\" />\n";
662 $ret .= "<link rel=\"Last\" title=\"".$this->translator->_g("gallery|Last")."\" href=\"".$this->lastPageURL()."\" />\n"; 662 $ret .= "<link rel=\"Last\" title=\"".$this->translator->_g("gallery|Last")."\" href=\"".$this->lastPageURL()."\" />\n";
663 } 663 }
664 } 664 }
665 return $ret; 665 return $ret;
666 } 666 }
667 667
668 668
669 /** 669 /**
670 * @return int the number of 'pages' or 'screen-fulls' 670 * @return int the number of 'pages' or 'screen-fulls'
671 */ 671 */
672 function galleryPageCount() { 672 function galleryPageCount() {
673 if($this->isAlbumPage()) 673 if($this->isAlbumPage())
674 return intval($this->gallery->imageCount()/$this->config->thumb_number_album)+1; 674 return intval($this->gallery->imageCount()/$this->config->thumb_number_album)+1;
675 else 675 else
676 return intval($this->gallery->galleryCount()/$this->config->thumb_number_gallery)+1; 676 return intval($this->gallery->galleryCount()/$this->config->thumb_number_gallery)+1;
677 } 677 }
678 678
679 /** 679 /**
680 * @return int 680 * @return int
681 */ 681 */
682 function lastPageIndex() { 682 function lastPageIndex() {
683 if($this->isAlbumPage()) 683 if($this->isAlbumPage())
684 return ($this->galleryPageCount()-1)* 684 return ($this->galleryPageCount()-1)*
685 ($this->isAlbumPage()?$this->config->thumb_number_album:$this->config->thumb_number_gallery); 685 ($this->isAlbumPage()?$this->config->thumb_number_album:$this->config->thumb_number_gallery);
686 } 686 }
687 687
688 /** 688 /**
689 * @return bool true if there is at least one more page 689 * @return bool true if there is at least one more page
690 */ 690 */
691 function hasNextPage() { 691 function hasNextPage() {
692 if($this->isAlbumPage()) 692 if($this->isAlbumPage())
693 return count($this->gallery->images)>$this->startat+$this->config->thumb_number_album; 693 return count($this->gallery->images)>$this->startat+$this->config->thumb_number_album;
694 elseif($this->isGalleryPage()) 694 elseif($this->isGalleryPage())
695 return count($this->gallery->galleries)>$this->startat+$this->config->thumb_number_gallery; 695 return count($this->gallery->galleries)>$this->startat+$this->config->thumb_number_gallery;
696 elseif($this->isImagePage()) 696 elseif($this->isImagePage())
697 return isset($this->gallery->images[$this->image->index+1]); 697 return isset($this->gallery->images[$this->image->index+1]);
698 } 698 }
699 699
700 /** 700 /**
701 * @return bool true if there is at least one previous page 701 * @return bool true if there is at least one previous page
702 */ 702 */
703 function hasPrevPage() { 703 function hasPrevPage() {
704 if($this->isAlbumPage() || $this->isGalleryPage()) 704 if($this->isAlbumPage() || $this->isGalleryPage())
705 return $this->startat > 0; 705 return $this->startat > 0;
706 elseif($this->isImagePage()) 706 elseif($this->isImagePage())
707 return isset($this->gallery->images[$this->image->index-1]); 707 return isset($this->gallery->images[$this->image->index-1]);
708 } 708 }
709 709
710 function firstPageURL() { 710 function firstPageURL() {
711 return $this->gallery->URL(0); 711 return $this->gallery->URL(0);
712 } 712 }
713 713
714 function firstPageLink() { 714 function firstPageLink() {
715 return "<a href=\"".$this->firstPageURL()."\">".$this->translator->_g("First %s", $this->itemsPerPage())."</a>"; 715 return "<a href=\"".$this->firstPageURL()."\">".$this->translator->_g("First %s", $this->itemsPerPage())."</a>";
716 } 716 }
717 717
718 /** 718 /**
719 * @return string the URL of the previous page 719 * @return string the URL of the previous page
720 */ 720 */
721 function prevPageURL() { 721 function prevPageURL() {
722 return $this->gallery->URL($this->startat - $this->itemsPerPage()); 722 return $this->gallery->URL($this->startat - $this->itemsPerPage());
723 } 723 }
724 724
725 function prevPageLink() { 725 function prevPageLink() {
726 return "<a href=\"".$this->prevPageURL()."\">".$this->translator->_g("Previous %s", $this->itemsPerPage())."</a>"; 726 return "<a href=\"".$this->prevPageURL()."\">".$this->translator->_g("Previous %s", $this->itemsPerPage())."</a>";
727 } 727 }
728 728
729 /** 729 /**
730 * @return string the URL of the next page 730 * @return string the URL of the next page
731 */ 731 */
732 function nextPageURL() { 732 function nextPageURL() {
733 return $this->gallery->URL($this->startat + $this->itemsPerPage()); 733 return $this->gallery->URL($this->startat + $this->itemsPerPage());
734 } 734 }
735 735
736 function nextPageLink() { 736 function nextPageLink() {
737 return "<a href=\"".$this->nextPageURL()."\">".$this->translator->_g("Next %s", $this->itemsPerPage())."</a>"; 737 return "<a href=\"".$this->nextPageURL()."\">".$this->translator->_g("Next %s", $this->itemsPerPage())."</a>";
738 } 738 }
739 739
740 function lastPageURL() { 740 function lastPageURL() {
741 $perpage = $this->isAlbumPage() ? $this->config->thumb_number_album : $this->config->thumb_number_gallery; 741 $perpage = $this->isAlbumPage() ? $this->config->thumb_number_album : $this->config->thumb_number_gallery;
742 return $this->gallery->URL(floor($this->gallery->itemCount() / $perpage) * $perpage); 742 return $this->gallery->URL(floor($this->gallery->itemCount() / $perpage) * $perpage);
743 } 743 }
744 744
745 function lastPageLink() { 745 function lastPageLink() {
746 return "<a href=\"".$this->lastPageURL()."\">".$this->translator->_g("Last %s", $this->itemsPerPage())."</a>"; 746 return "<a href=\"".$this->lastPageURL()."\">".$this->translator->_g("Last %s", $this->itemsPerPage())."</a>";
747 } 747 }
748 748
749 function itemsPerPage() 749 function itemsPerPage()
750 { 750 {
751 return $this->isAlbumPage() ? $this->config->thumb_number_album : $this->config->thumb_number_gallery; 751 return $this->isAlbumPage() ? $this->config->thumb_number_album : $this->config->thumb_number_gallery;
752 } 752 }
753 753
754 /** 754 /**
755 * @return string link for adding a comment to image 755 * @return string link for adding a comment to image
756 */ 756 */
757 function imageCommentLink() 757 function imageCommentLink()
758 { 758 {
759 return "<a href=\"". 759 return "<a href=\"".
760 $this->formatURL($this->gallery->idEncoded(), $this->image->id, null, "addcomment"). 760 $this->formatURL($this->gallery->idEncoded(), $this->image->id, null, "addcomment").
761 "\">".$this->translator->_g("Add a comment")."</a>"; 761 "\">".$this->translator->_g("Add a comment")."</a>";
762 } 762 }
763 763
764 /** 764 /**
765 * @return array array of sgImage objects 765 * @return array array of sgImage objects
766 */ 766 */
767 function &previewThumbnailsArray() 767 function &previewThumbnailsArray()
768 { 768 {
769 $ret = array(); 769 $ret = array();
770 $index = $this->image->index(); 770 $index = $this->image->index();
771 $start = ceil($index - $this->config->thumb_number_preview/2); 771 $start = ceil($index - $this->config->thumb_number_preview/2);
772 772
773 for($i = $start; $i < $start + $this->config->thumb_number_preview; $i++) 773 for($i = $start; $i < $start + $this->config->thumb_number_preview; $i++)
774 if(isset($this->image->parent->images[$i])) 774 if(isset($this->image->parent->images[$i]))
775 $ret[$i] =& $this->image->parent->images[$i]; 775 $ret[$i] =& $this->image->parent->images[$i];
776 776
777 return $ret; 777 return $ret;
778 } 778 }
779 779
780 function previewThumbnails() 780 function previewThumbnails()
781 { 781 {
782 $thumbs =& $this->previewThumbnailsArray(); 782 $thumbs =& $this->previewThumbnailsArray();
783 $index = $this->image->index(); 783 $index = $this->image->index();
784 $ret = ""; 784 $ret = "";
785 foreach($thumbs as $key => $thumb) { 785 foreach($thumbs as $key => $thumb) {
786 $thumbClass = "sgThumbnailPreview"; 786 $thumbClass = "sgThumbnailPreview";
787 if($key==$index-1) $thumbClass .= " sgThumbnailPreviewPrev"; 787 if($key==$index-1) $thumbClass .= " sgThumbnailPreviewPrev";
788 elseif($key==$index) $thumbClass .= " sgThumbnailPreviewCurrent"; 788 elseif($key==$index) $thumbClass .= " sgThumbnailPreviewCurrent";
789 elseif($key==$index+1) $thumbClass .= " sgThumbnailPreviewNext"; 789 elseif($key==$index+1) $thumbClass .= " sgThumbnailPreviewNext";
790 $ret .= $thumb->thumbnailLink($thumbClass, "preview")."\n"; 790 $ret .= $thumb->thumbnailLink($thumbClass, "preview")."\n";
791 } 791 }
792 792
793 return $ret; 793 return $ret;
794 } 794 }
795 795
796 ////////////////////////////// 796 //////////////////////////////
797 //////ex-sgUtils methods////// 797 //////ex-sgUtils methods//////
798 ////////////////////////////// 798 //////////////////////////////
799 799
800 /** 800 /**
801 * Callback function for sorting things 801 * Callback function for sorting things
802 * @static 802 * @static
803 */ 803 */
804 function multiSort($a, $b) { 804 function multiSort($a, $b) {
805 switch($GLOBALS["sgSortOrder"]) { 805 switch($GLOBALS["sgSortOrder"]) {
806 case "f" : 806 case "f" :
807 case "p" : return strcmp($a->id, $b->id); //path 807 case "p" : return strcmp($a->id, $b->id); //path
808 case "F" : 808 case "F" :
809 case "P" : return strcmp($b->id, $a->id); //path (reverse) 809 case "P" : return strcmp($b->id, $a->id); //path (reverse)
810 case "n" : return strcmp($a->name, $b->name); //name 810 case "n" : return strcmp($a->name, $b->name); //name
811 case "N" : return strcmp($b->name, $a->name); //name (reverse) 811 case "N" : return strcmp($b->name, $a->name); //name (reverse)
812 case "i" : return strcasecmp($a->name, $b->name); //case-insensitive name 812 case "i" : return strcasecmp($a->name, $b->name); //case-insensitive name
813 case "I" : return strcasecmp($b->name, $a->name); //case-insensitive name (reverse) 813 case "I" : return strcasecmp($b->name, $a->name); //case-insensitive name (reverse)
814 case "a" : return strcmp($a->artist, $b->artist); //artist 814 case "a" : return strcmp($a->artist, $b->artist); //artist
815 case "A" : return strcmp($b->artist, $a->artist); //artist (reverse) 815 case "A" : return strcmp($b->artist, $a->artist); //artist (reverse)
816 case "d" : return strcmp($a->date, $b->date); //date 816 case "d" : return strcmp($a->date, $b->date); //date
817 case "D" : return strcmp($b->date, $a->date); //date (reverse) 817 case "D" : return strcmp($b->date, $a->date); //date (reverse)
818 case "l" : return strcmp($a->location, $b->location); //location 818 case "l" : return strcmp($a->location, $b->location); //location
819 case "L" : return strcmp($b->location, $a->location); //location (reverse) 819 case "L" : return strcmp($b->location, $a->location); //location (reverse)
820 } 820 }
821 } 821 }
822 822
823 /** 823 /**
824 * Slightly pointless method 824 * Slightly pointless method
825 */ 825 */
826 function conditional($conditional, $iftrue, $iffalse = null) 826 function conditional($conditional, $iftrue, $iffalse = null)
827 { 827 {
828 if($conditional) return sprintf($iftrue, $conditional); 828 if($conditional) return sprintf($iftrue, $conditional);
829 elseif($iffalse != null) return sprintf($iffalse, $conditional); 829 elseif($iffalse != null) return sprintf($iffalse, $conditional);
830 else return ""; 830 else return "";
831 } 831 }
832 832
833 /** 833 /**
834 * Callback function for recursively stripping slashes 834 * Callback function for recursively stripping slashes
835 * @static 835 * @static
836 */ 836 */
837 function arraystripslashes($toStrip) 837 function arraystripslashes($toStrip)
838 { 838 {
839 if(is_array($toStrip)) 839 if(is_array($toStrip))
840 return array_map(array("Singapore","arraystripslashes"), $toStrip); 840 return array_map(array("Singapore","arraystripslashes"), $toStrip);
841 else 841 else
842 return stripslashes($toStrip); 842 return stripslashes($toStrip);
843 } 843 }
844 844
845 function thumbnailPath($gallery, $image, $width, $height, $forceSize, $mode = 1) 845 function thumbnailPath($gallery, $image, $width, $height, $forceSize, $mode = 1)
846 { 846 {
847 $config =& sgConfig::getInstance(); 847 $config =& sgConfig::getInstance();
848 switch($mode) { 848 switch($mode) {
849 case 0 : 849 case 0 :
850 return $config->pathto_data_dir."cache/".$width."x".$height.($forceSize?"f":"").strtr("-$gallery-$image",":/?\\","----"); 850 return $config->pathto_data_dir."cache/".$width."x".$height.($forceSize?"f":"").strtr("-$gallery-$image",":/?\\","----");
851 case 1 : 851 case 1 :
852 return $config->pathto_galleries.$gallery."/_thumbs/".$width."x".$height.($forceSize?"f":"").strtr("-$image",":/?\\","----"); 852 return $config->pathto_galleries.$gallery."/_thumbs/".$width."x".$height.($forceSize?"f":"").strtr("-$image",":/?\\","----");
853 } 853 }
854 } 854 }
855 855
856 /** 856 /**
857 * @param string relative or absolute path to directory 857 * @param string relative or absolute path to directory
858 * @param string regular expression of files to return (optional) 858 * @param string regular expression of files to return (optional)
859 * @param bool true to get hidden directories too 859 * @param bool true to get hidden directories too
860 * @returns stdClass|false a data object representing the directory and its contents 860 * @returns stdClass|false a data object representing the directory and its contents
861 * @static 861 * @static
862 */ 862 */
863 function getListing($wd, $mask = null, $getHidden = false) 863 function getListing($wd, $mask = null, $getHidden = false)
864 { 864 {
865 $dir = new stdClass; 865 $dir = new stdClass;
866 $dir->path = realpath($wd)."/"; 866 $dir->path = realpath($wd)."/";
867 $dir->files = array(); 867 $dir->files = array();
868 $dir->dirs = array(); 868 $dir->dirs = array();
869 869
870 $dp = opendir($dir->path); 870 $dp = opendir($dir->path);
871 if(!$dp) return false; 871 if(!$dp) return false;
872   872  
873 while(false !== ($entry = readdir($dp))) 873 while(false !== ($entry = readdir($dp)))
874 if(is_dir($dir->path.$entry)) { 874 if(is_dir($dir->path.$entry)) {
875 if(($entry{0} != '.' && $entry{0} != '_') || $getHidden) 875 if(($entry{0} != '.' && $entry{0} != '_') || $getHidden)
876 $dir->dirs[] = $entry; 876 $dir->dirs[] = $entry;
877 } else { 877 } else {
878 if($mask == null || preg_match("/\.($mask)$/i",$entry)) 878 if($mask == null || preg_match("/\.($mask)$/i",$entry))
879 $dir->files[] = $entry; 879 $dir->files[] = $entry;
880 } 880 }
881 881
882 sort($dir->files); 882 sort($dir->files);
883 sort($dir->dirs); 883 sort($dir->dirs);
884 closedir($dp); 884 closedir($dp);
885 return $dir; 885 return $dir;
886 } 886 }
887 887
888 /** 888 /**
889 * Recursively deletes all directories and files in the specified directory. 889 * Recursively deletes all directories and files in the specified directory.
890 * USE WITH EXTREME CAUTION!! 890 * USE WITH EXTREME CAUTION!!
891 * @returns boolean true on success; false otherwise 891 * @returns boolean true on success; false otherwise
892 * @static 892 * @static
893 */ 893 */
894 function rmdir_all($wd) 894 function rmdir_all($wd)
895 { 895 {
896 if(!$dp = opendir($wd)) return false; 896 if(!$dp = opendir($wd)) return false;
897 $success = true; 897 $success = true;
898 while(false !== ($entry = readdir($dp))) { 898 while(false !== ($entry = readdir($dp))) {
899 if($entry == "." || $entry == "..") continue; 899 if($entry == "." || $entry == "..") continue;
900 if(is_dir("$wd/$entry")) $success &= Singapore::rmdir_all("$wd/$entry"); 900 if(is_dir("$wd/$entry")) $success &= Singapore::rmdir_all("$wd/$entry");
901 else $success &= unlink("$wd/$entry"); 901 else $success &= unlink("$wd/$entry");
902 } 902 }
903 closedir($dp); 903 closedir($dp);
904 $success &= rmdir($wd); 904 $success &= rmdir($wd);
905 return $success; 905 return $success;
906 } 906 }
907 907
908 /** 908 /**
909 * Returns an array of language codes specified in the Accept-Language HHTP 909 * Returns an array of language codes specified in the Accept-Language HHTP
910 * header field of the user's browser. q= components are ignored and removed. 910 * header field of the user's browser. q= components are ignored and removed.
911 * hyphens (-) are converted to underscores (_). 911 * hyphens (-) are converted to underscores (_).
912 * @return array accepted language codes 912 * @return array accepted language codes
913 * @static 913 * @static
914 */ 914 */
915 function getBrowserLanguages() 915 function getBrowserLanguages()
916 { 916 {
917 $langs = array(); 917 $langs = array();
918 foreach(explode(",",$_SERVER["HTTP_ACCEPT_LANGUAGE"]) as $bit) 918 foreach(explode(",",$_SERVER["HTTP_ACCEPT_LANGUAGE"]) as $bit)
919 if($pos = strpos($bit,";")) 919 if($pos = strpos($bit,";"))
920 $langs[] = strtr(substr($bit,0,$pos),"-","_"); 920 $langs[] = strtr(substr($bit,0,$pos),"-","_");
921 else 921 else
922 $langs[] = strtr($bit,"-","_"); 922 $langs[] = strtr($bit,"-","_");
923 return $langs; 923 return $langs;
924 } 924 }
925 925
926 /** 926 /**
927 * Wrapper for mkdir() implementing the safe-mode hack 927 * Wrapper for mkdir() implementing the safe-mode hack
928 */ 928 */
929 function mkdir($path) 929 function mkdir($path)
930 { 930 {
931 $config =& sgConfig::getInstance(); 931 $config =& sgConfig::getInstance();
932 if($config->safe_mode_hack) { 932 if($config->safe_mode_hack) {
933 $connection = ftp_connect($config->ftp_server); 933 $connection = ftp_connect($config->ftp_server);
934 // login to ftp server 934 // login to ftp server
935 $result = ftp_login($connection, $config->ftp_user, $config->ftp_pass); 935 $result = ftp_login($connection, $config->ftp_user, $config->ftp_pass);
936 936
937 // check if connection was made 937 // check if connection was made
938 if ((!$connection) || (!$result)) 938 if ((!$connection) || (!$result))
939 return false; 939 return false;
940 940
941 ftp_chdir($connection, $config->ftp_base_path); // go to destination dir 941 ftp_chdir($connection, $config->ftp_base_path); // go to destination dir
942 if(!ftp_mkdir($connection, $path)) // create directory 942 if(!ftp_mkdir($connection, $path)) // create directory
943 return false; 943 return false;
944 944
945 ftp_site($connection, "CHMOD ".$config->directory_mode." ".$path); 945 ftp_site($connection, "CHMOD ".$config->directory_mode." ".$path);
946 ftp_close($connection); // close connection 946 ftp_close($connection); // close connection
947 return true; 947 return true;
948 } else 948 } else
949 return mkdir($path, octdec($config->directory_mode)); 949 return mkdir($path, octdec($config->directory_mode));
950 } 950 }
951 951
952 /** 952 /**
953 * Tests if $child is within or is the same path as $parent. 953 * Tests if $child is within or is the same path as $parent.
954 * 954 *
955 * @param string path to parent directory 955 * @param string path to parent directory
956 * @param string path to child directory or file 956 * @param string path to child directory or file
957 * @param bool set false to prevent canonicalisation of paths (optional) 957 * @param bool set false to prevent canonicalisation of paths (optional)
958 * @return bool true if $child is contained within or is $parent 958 * @return bool true if $child is contained within or is $parent
959 */ 959 */
960 function isSubPath($parent, $child, $canonicalise = true) 960 function isSubPath($parent, $child, $canonicalise = true)
961 { 961 {
962 $parentPath = $canonicalise ? realpath($parent) : $parent; 962 $parentPath = $canonicalise ? realpath($parent) : $parent;
963 $childPath = $canonicalise ? realpath($child) : $child; 963 $childPath = $canonicalise ? realpath($child) : $child;
964 return $parentPath && $childPath && substr($childPath,0,strlen($parentPath)) == $parentPath; 964 return $parentPath && $childPath && substr($childPath,0,strlen($parentPath)) == $parentPath;
965 } 965 }
966   966  
967   967  
968 function isInGroup($groups1,$groups2) 968 function isInGroup($groups1,$groups2)
969 { 969 {
970 return (bool) array_intersect(explode(" ",$groups1),explode(" ",$groups2)); 970 return (bool) array_intersect(explode(" ",$groups1),explode(" ",$groups2));
971 } 971 }
972 972
973 } 973 }
974   974  
975   975  
976 ?> 976 ?>