source: tags/2.0.6/include/functions.inc.php @ 27538

Last change on this file since 27538 was 3204, checked in by patdenice, 15 years ago

merge r3203 from trunk to branch 2.0.
Move template class inclusion to common.inc.php.
Add forum link in upgrade page.
Install and upgrade try to configure PHP5.

  • Property svn:eol-style set to LF
  • Property svn:keywords set to Author Date Id Revision
File size: 40.6 KB
Line 
1<?php
2// +-----------------------------------------------------------------------+
3// | Piwigo - a PHP based picture gallery                                  |
4// +-----------------------------------------------------------------------+
5// | Copyright(C) 2008-2009 Piwigo Team                  http://piwigo.org |
6// | Copyright(C) 2003-2008 PhpWebGallery Team    http://phpwebgallery.net |
7// | Copyright(C) 2002-2003 Pierrick LE GALL   http://le-gall.net/pierrick |
8// +-----------------------------------------------------------------------+
9// | This program is free software; you can redistribute it and/or modify  |
10// | it under the terms of the GNU General Public License as published by  |
11// | the Free Software Foundation                                          |
12// |                                                                       |
13// | This program is distributed in the hope that it will be useful, but   |
14// | WITHOUT ANY WARRANTY; without even the implied warranty of            |
15// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      |
16// | General Public License for more details.                              |
17// |                                                                       |
18// | You should have received a copy of the GNU General Public License     |
19// | along with this program; if not, write to the Free Software           |
20// | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
21// | USA.                                                                  |
22// +-----------------------------------------------------------------------+
23
24include_once( PHPWG_ROOT_PATH .'include/functions_user.inc.php' );
25include_once( PHPWG_ROOT_PATH .'include/functions_cookie.inc.php' );
26include_once( PHPWG_ROOT_PATH .'include/functions_session.inc.php' );
27include_once( PHPWG_ROOT_PATH .'include/functions_category.inc.php' );
28include_once( PHPWG_ROOT_PATH .'include/functions_xml.inc.php' );
29include_once( PHPWG_ROOT_PATH .'include/functions_html.inc.php' );
30include_once( PHPWG_ROOT_PATH .'include/functions_tag.inc.php' );
31include_once( PHPWG_ROOT_PATH .'include/functions_url.inc.php' );
32include_once( PHPWG_ROOT_PATH .'include/functions_plugins.inc.php' );
33
34//----------------------------------------------------------- generic functions
35
36/**
37 * returns an array containing the possible values of an enum field
38 *
39 * @param string tablename
40 * @param string fieldname
41 */
42function get_enums($table, $field)
43{
44  // retrieving the properties of the table. Each line represents a field :
45  // columns are 'Field', 'Type'
46  $result = pwg_query('desc '.$table);
47  while ($row = mysql_fetch_array($result))
48  {
49    // we are only interested in the the field given in parameter for the
50    // function
51    if ($row['Field'] == $field)
52    {
53      // retrieving possible values of the enum field
54      // enum('blue','green','black')
55      $options = explode(',', substr($row['Type'], 5, -1));
56      foreach ($options as $i => $option)
57      {
58        $options[$i] = str_replace("'", '',$option);
59      }
60    }
61  }
62  mysql_free_result($result);
63  return $options;
64}
65
66// get_boolean transforms a string to a boolean value. If the string is
67// "false" (case insensitive), then the boolean value false is returned. In
68// any other case, true is returned.
69function get_boolean( $string )
70{
71  $boolean = true;
72  if ( 'false' == strtolower($string) )
73  {
74    $boolean = false;
75  }
76  return $boolean;
77}
78
79/**
80 * returns boolean string 'true' or 'false' if the given var is boolean
81 *
82 * @param mixed $var
83 * @return mixed
84 */
85function boolean_to_string($var)
86{
87  if (is_bool($var))
88  {
89    return $var ? 'true' : 'false';
90  }
91  else
92  {
93    return $var;
94  }
95}
96
97// The function get_moment returns a float value coresponding to the number
98// of seconds since the unix epoch (1st January 1970) and the microseconds
99// are precised : e.g. 1052343429.89276600
100function get_moment()
101{
102  $t1 = explode( ' ', microtime() );
103  $t2 = explode( '.', $t1[0] );
104  $t2 = $t1[1].'.'.$t2[1];
105  return $t2;
106}
107
108// The function get_elapsed_time returns the number of seconds (with 3
109// decimals precision) between the start time and the end time given.
110function get_elapsed_time( $start, $end )
111{
112  return number_format( $end - $start, 3, '.', ' ').' s';
113}
114
115// - The replace_space function replaces space and '-' characters
116//   by their HTML equivalent  &nbsb; and &minus;
117// - The function does not replace characters in HTML tags
118// - This function was created because IE5 does not respect the
119//   CSS "white-space: nowrap;" property unless space and minus
120//   characters are replaced like this function does.
121// - Example :
122//                 <div class="foo">My friend</div>
123//               ( 01234567891111111111222222222233 )
124//               (           0123456789012345678901 )
125// becomes :
126//             <div class="foo">My&nbsp;friend</div>
127function replace_space( $string )
128{
129  //return $string;
130  $return_string = '';
131  // $remaining is the rest of the string where to replace spaces characters
132  $remaining = $string;
133  // $start represents the position of the next '<' character
134  // $end   represents the position of the next '>' character
135  ; // -> 0
136  $end   = strpos ( $remaining, '>' ); // -> 16
137  // as long as a '<' and his friend '>' are found, we loop
138  while ( ($start=strpos( $remaining, '<' )) !==false
139        and ($end=strpos( $remaining, '>' )) !== false )
140  {
141    // $treatment is the part of the string to treat
142    // In the first loop of our example, this variable is empty, but in the
143    // second loop, it equals 'My friend'
144    $treatment = substr ( $remaining, 0, $start );
145    // Replacement of ' ' by his equivalent '&nbsp;'
146    $treatment = str_replace( ' ', '&nbsp;', $treatment );
147    $treatment = str_replace( '-', '&minus;', $treatment );
148    // composing the string to return by adding the treated string and the
149    // following HTML tag -> 'My&nbsp;friend</div>'
150    $return_string.= $treatment.substr( $remaining, $start, $end-$start+1 );
151    // the remaining string is deplaced to the part after the '>' of this
152    // loop
153    $remaining = substr ( $remaining, $end + 1, strlen( $remaining ) );
154  }
155  $treatment = str_replace( ' ', '&nbsp;', $remaining );
156  $treatment = str_replace( '-', '&minus;', $treatment );
157  $return_string.= $treatment;
158
159  return $return_string;
160}
161
162// get_extension returns the part of the string after the last "."
163function get_extension( $filename )
164{
165  return substr( strrchr( $filename, '.' ), 1, strlen ( $filename ) );
166}
167
168// get_filename_wo_extension returns the part of the string before the last
169// ".".
170// get_filename_wo_extension( 'test.tar.gz' ) -> 'test.tar'
171function get_filename_wo_extension( $filename )
172{
173  $pos = strrpos( $filename, '.' );
174  return ($pos===false) ? $filename : substr( $filename, 0, $pos);
175}
176
177/**
178 * returns an array contening sub-directories, excluding ".svn"
179 *
180 * @param string $dir
181 * @return array
182 */
183function get_dirs($directory)
184{
185  $sub_dirs = array();
186  if ($opendir = opendir($directory))
187  {
188    while ($file = readdir($opendir))
189    {
190      if ($file != '.'
191          and $file != '..'
192          and is_dir($directory.'/'.$file)
193          and $file != '.svn')
194      {
195        array_push($sub_dirs, $file);
196      }
197    }
198    closedir($opendir);
199  }
200  return $sub_dirs;
201}
202
203define('MKGETDIR_NONE', 0);
204define('MKGETDIR_RECURSIVE', 1);
205define('MKGETDIR_DIE_ON_ERROR', 2);
206define('MKGETDIR_PROTECT_INDEX', 4);
207define('MKGETDIR_PROTECT_HTACCESS', 8);
208define('MKGETDIR_DEFAULT', 7);
209/**
210 * creates directory if not exists; ensures that directory is writable
211 * @param:
212 *  string $dir
213 *  int $flags combination of MKGETDIR_xxx
214 * @return bool false on error else true
215 */
216function mkgetdir($dir, $flags=MKGETDIR_DEFAULT)
217{
218  if ( !is_dir($dir) )
219  {
220    $umask = umask(0);
221    $mkd = @mkdir($dir, 0755, ($flags&MKGETDIR_RECURSIVE) ? true:false );
222    umask($umask);
223    if ($mkd==false)
224    {
225      !($flags&MKGETDIR_DIE_ON_ERROR) or fatal_error( "$dir ".l10n('no_write_access'));
226      return false;
227    }
228    if( $flags&MKGETDIR_PROTECT_HTACCESS )
229    {
230      $file = $dir.'/.htaccess';
231      file_exists($file) or @file_put_contents( $file, 'deny from all' );
232    }
233    if( $flags&MKGETDIR_PROTECT_INDEX )
234    {
235      $file = $dir.'/index.htm';
236      file_exists($file) or @file_put_contents( $file, 'Not allowed!' );
237    }
238  }
239  if ( !is_writable($dir) )
240  {
241    !($flags&MKGETDIR_DIE_ON_ERROR) or fatal_error( "$dir ".l10n('no_write_access'));
242    return false;
243  }
244  return true;
245}
246
247/**
248 * returns thumbnail directory name of input diretoty name
249 * make thumbnail directory is necessary
250 * set error messages on array messages
251 *
252 * @param:
253 *  string $dirname
254 *  arrayy $errors
255 * @return bool false on error else string directory name
256 */
257function mkget_thumbnail_dir($dirname, &$errors)
258{
259  $tndir = $dirname.'/thumbnail';
260  if (! mkgetdir($tndir, MKGETDIR_NONE) )
261  {
262    array_push($errors,
263          '['.$dirname.'] : '.l10n('no_write_access'));
264    return false;
265  }
266  return $tndir;
267}
268
269/* Returns true if the string appears to be encoded in UTF-8. (from wordpress)
270 * @param string Str
271 */
272function seems_utf8($Str) { # by bmorel at ssi dot fr
273  for ($i=0; $i<strlen($Str); $i++) {
274    if (ord($Str[$i]) < 0x80) continue; # 0bbbbbbb
275    elseif ((ord($Str[$i]) & 0xE0) == 0xC0) $n=1; # 110bbbbb
276    elseif ((ord($Str[$i]) & 0xF0) == 0xE0) $n=2; # 1110bbbb
277    elseif ((ord($Str[$i]) & 0xF8) == 0xF0) $n=3; # 11110bbb
278    elseif ((ord($Str[$i]) & 0xFC) == 0xF8) $n=4; # 111110bb
279    elseif ((ord($Str[$i]) & 0xFE) == 0xFC) $n=5; # 1111110b
280    else return false; # Does not match any model
281    for ($j=0; $j<$n; $j++) { # n bytes matching 10bbbbbb follow ?
282      if ((++$i == strlen($Str)) || ((ord($Str[$i]) & 0xC0) != 0x80))
283      return false;
284    }
285  }
286  return true;
287}
288
289/* Remove accents from a UTF-8 or ISO-859-1 string (from wordpress)
290 * @param string sstring - an UTF-8 or ISO-8859-1 string
291 */
292function remove_accents($string)
293{
294  if ( !preg_match('/[\x80-\xff]/', $string) )
295    return $string;
296
297  if (seems_utf8($string)) {
298    $chars = array(
299    // Decompositions for Latin-1 Supplement
300    chr(195).chr(128) => 'A', chr(195).chr(129) => 'A',
301    chr(195).chr(130) => 'A', chr(195).chr(131) => 'A',
302    chr(195).chr(132) => 'A', chr(195).chr(133) => 'A',
303    chr(195).chr(135) => 'C', chr(195).chr(136) => 'E',
304    chr(195).chr(137) => 'E', chr(195).chr(138) => 'E',
305    chr(195).chr(139) => 'E', chr(195).chr(140) => 'I',
306    chr(195).chr(141) => 'I', chr(195).chr(142) => 'I',
307    chr(195).chr(143) => 'I', chr(195).chr(145) => 'N',
308    chr(195).chr(146) => 'O', chr(195).chr(147) => 'O',
309    chr(195).chr(148) => 'O', chr(195).chr(149) => 'O',
310    chr(195).chr(150) => 'O', chr(195).chr(153) => 'U',
311    chr(195).chr(154) => 'U', chr(195).chr(155) => 'U',
312    chr(195).chr(156) => 'U', chr(195).chr(157) => 'Y',
313    chr(195).chr(159) => 's', chr(195).chr(160) => 'a',
314    chr(195).chr(161) => 'a', chr(195).chr(162) => 'a',
315    chr(195).chr(163) => 'a', chr(195).chr(164) => 'a',
316    chr(195).chr(165) => 'a', chr(195).chr(167) => 'c',
317    chr(195).chr(168) => 'e', chr(195).chr(169) => 'e',
318    chr(195).chr(170) => 'e', chr(195).chr(171) => 'e',
319    chr(195).chr(172) => 'i', chr(195).chr(173) => 'i',
320    chr(195).chr(174) => 'i', chr(195).chr(175) => 'i',
321    chr(195).chr(177) => 'n', chr(195).chr(178) => 'o',
322    chr(195).chr(179) => 'o', chr(195).chr(180) => 'o',
323    chr(195).chr(181) => 'o', chr(195).chr(182) => 'o',
324    chr(195).chr(182) => 'o', chr(195).chr(185) => 'u',
325    chr(195).chr(186) => 'u', chr(195).chr(187) => 'u',
326    chr(195).chr(188) => 'u', chr(195).chr(189) => 'y',
327    chr(195).chr(191) => 'y',
328    // Decompositions for Latin Extended-A
329    chr(196).chr(128) => 'A', chr(196).chr(129) => 'a',
330    chr(196).chr(130) => 'A', chr(196).chr(131) => 'a',
331    chr(196).chr(132) => 'A', chr(196).chr(133) => 'a',
332    chr(196).chr(134) => 'C', chr(196).chr(135) => 'c',
333    chr(196).chr(136) => 'C', chr(196).chr(137) => 'c',
334    chr(196).chr(138) => 'C', chr(196).chr(139) => 'c',
335    chr(196).chr(140) => 'C', chr(196).chr(141) => 'c',
336    chr(196).chr(142) => 'D', chr(196).chr(143) => 'd',
337    chr(196).chr(144) => 'D', chr(196).chr(145) => 'd',
338    chr(196).chr(146) => 'E', chr(196).chr(147) => 'e',
339    chr(196).chr(148) => 'E', chr(196).chr(149) => 'e',
340    chr(196).chr(150) => 'E', chr(196).chr(151) => 'e',
341    chr(196).chr(152) => 'E', chr(196).chr(153) => 'e',
342    chr(196).chr(154) => 'E', chr(196).chr(155) => 'e',
343    chr(196).chr(156) => 'G', chr(196).chr(157) => 'g',
344    chr(196).chr(158) => 'G', chr(196).chr(159) => 'g',
345    chr(196).chr(160) => 'G', chr(196).chr(161) => 'g',
346    chr(196).chr(162) => 'G', chr(196).chr(163) => 'g',
347    chr(196).chr(164) => 'H', chr(196).chr(165) => 'h',
348    chr(196).chr(166) => 'H', chr(196).chr(167) => 'h',
349    chr(196).chr(168) => 'I', chr(196).chr(169) => 'i',
350    chr(196).chr(170) => 'I', chr(196).chr(171) => 'i',
351    chr(196).chr(172) => 'I', chr(196).chr(173) => 'i',
352    chr(196).chr(174) => 'I', chr(196).chr(175) => 'i',
353    chr(196).chr(176) => 'I', chr(196).chr(177) => 'i',
354    chr(196).chr(178) => 'IJ',chr(196).chr(179) => 'ij',
355    chr(196).chr(180) => 'J', chr(196).chr(181) => 'j',
356    chr(196).chr(182) => 'K', chr(196).chr(183) => 'k',
357    chr(196).chr(184) => 'k', chr(196).chr(185) => 'L',
358    chr(196).chr(186) => 'l', chr(196).chr(187) => 'L',
359    chr(196).chr(188) => 'l', chr(196).chr(189) => 'L',
360    chr(196).chr(190) => 'l', chr(196).chr(191) => 'L',
361    chr(197).chr(128) => 'l', chr(197).chr(129) => 'L',
362    chr(197).chr(130) => 'l', chr(197).chr(131) => 'N',
363    chr(197).chr(132) => 'n', chr(197).chr(133) => 'N',
364    chr(197).chr(134) => 'n', chr(197).chr(135) => 'N',
365    chr(197).chr(136) => 'n', chr(197).chr(137) => 'N',
366    chr(197).chr(138) => 'n', chr(197).chr(139) => 'N',
367    chr(197).chr(140) => 'O', chr(197).chr(141) => 'o',
368    chr(197).chr(142) => 'O', chr(197).chr(143) => 'o',
369    chr(197).chr(144) => 'O', chr(197).chr(145) => 'o',
370    chr(197).chr(146) => 'OE',chr(197).chr(147) => 'oe',
371    chr(197).chr(148) => 'R',chr(197).chr(149) => 'r',
372    chr(197).chr(150) => 'R',chr(197).chr(151) => 'r',
373    chr(197).chr(152) => 'R',chr(197).chr(153) => 'r',
374    chr(197).chr(154) => 'S',chr(197).chr(155) => 's',
375    chr(197).chr(156) => 'S',chr(197).chr(157) => 's',
376    chr(197).chr(158) => 'S',chr(197).chr(159) => 's',
377    chr(197).chr(160) => 'S', chr(197).chr(161) => 's',
378    chr(197).chr(162) => 'T', chr(197).chr(163) => 't',
379    chr(197).chr(164) => 'T', chr(197).chr(165) => 't',
380    chr(197).chr(166) => 'T', chr(197).chr(167) => 't',
381    chr(197).chr(168) => 'U', chr(197).chr(169) => 'u',
382    chr(197).chr(170) => 'U', chr(197).chr(171) => 'u',
383    chr(197).chr(172) => 'U', chr(197).chr(173) => 'u',
384    chr(197).chr(174) => 'U', chr(197).chr(175) => 'u',
385    chr(197).chr(176) => 'U', chr(197).chr(177) => 'u',
386    chr(197).chr(178) => 'U', chr(197).chr(179) => 'u',
387    chr(197).chr(180) => 'W', chr(197).chr(181) => 'w',
388    chr(197).chr(182) => 'Y', chr(197).chr(183) => 'y',
389    chr(197).chr(184) => 'Y', chr(197).chr(185) => 'Z',
390    chr(197).chr(186) => 'z', chr(197).chr(187) => 'Z',
391    chr(197).chr(188) => 'z', chr(197).chr(189) => 'Z',
392    chr(197).chr(190) => 'z', chr(197).chr(191) => 's',
393    // Euro Sign
394    chr(226).chr(130).chr(172) => 'E',
395    // GBP (Pound) Sign
396    chr(194).chr(163) => '');
397
398    $string = strtr($string, $chars);
399  } else {
400    // Assume ISO-8859-1 if not UTF-8
401    $chars['in'] = chr(128).chr(131).chr(138).chr(142).chr(154).chr(158)
402      .chr(159).chr(162).chr(165).chr(181).chr(192).chr(193).chr(194)
403      .chr(195).chr(196).chr(197).chr(199).chr(200).chr(201).chr(202)
404      .chr(203).chr(204).chr(205).chr(206).chr(207).chr(209).chr(210)
405      .chr(211).chr(212).chr(213).chr(214).chr(216).chr(217).chr(218)
406      .chr(219).chr(220).chr(221).chr(224).chr(225).chr(226).chr(227)
407      .chr(228).chr(229).chr(231).chr(232).chr(233).chr(234).chr(235)
408      .chr(236).chr(237).chr(238).chr(239).chr(241).chr(242).chr(243)
409      .chr(244).chr(245).chr(246).chr(248).chr(249).chr(250).chr(251)
410      .chr(252).chr(253).chr(255);
411
412    $chars['out'] = "EfSZszYcYuAAAAAACEEEEIIIINOOOOOOUUUUYaaaaaaceeeeiiiinoooooouuuuyy";
413
414    $string = strtr($string, $chars['in'], $chars['out']);
415    $double_chars['in'] = array(chr(140), chr(156), chr(198), chr(208), chr(222), chr(223), chr(230), chr(240), chr(254));
416    $double_chars['out'] = array('OE', 'oe', 'AE', 'DH', 'TH', 'ss', 'ae', 'dh', 'th');
417    $string = str_replace($double_chars['in'], $double_chars['out'], $string);
418  }
419
420  return $string;
421}
422
423/**
424 * simplify a string to insert it into an URL
425 *
426 * @param string
427 * @return string
428 */
429function str2url($str)
430{
431  $str = remove_accents($str);
432  $str = preg_replace('/[^a-z0-9_\s\'\:\/\[\],-]/','',strtolower($str));
433  $str = preg_replace('/[\s\'\:\/\[\],-]+/',' ',trim($str));
434  $res = str_replace(' ','_',$str);
435
436  return $res;
437}
438
439//-------------------------------------------- Piwigo specific functions
440
441/**
442 * returns an array with a list of {language_code => language_name}
443 *
444 * @returns array
445 */
446function get_languages($target_charset = null)
447{
448  if ( empty($target_charset) )
449  {
450    $target_charset = get_pwg_charset();
451  }
452  $target_charset = strtolower($target_charset);
453
454  $dir = opendir(PHPWG_ROOT_PATH.'language');
455  $languages = array();
456
457  while ($file = readdir($dir))
458  {
459    $path = PHPWG_ROOT_PATH.'language/'.$file;
460    if (!is_link($path) and file_exists($path.'/iso.txt'))
461    {
462      list($language_name) = @file($path.'/iso.txt');
463
464      $langdef = explode('.',$file);
465      if (count($langdef)>1) // (langCode,encoding)
466      {
467        $langdef[1] = strtolower($langdef[1]);
468
469        if (
470          $target_charset==$langdef[1]
471         or
472          ($target_charset=='utf-8' and $langdef[1]=='iso-8859-1')
473         or
474          ($target_charset=='iso-8859-1' and
475          in_array( substr($langdef[0],2), array('en','fr','de','es','it','nl')))
476        )
477        {
478          $language_name = convert_charset($language_name,
479              $langdef[1], $target_charset);
480          $languages[ $langdef[0] ] = $language_name;
481        }
482        else
483          continue; // the language encoding is not compatible with our charset
484      }
485      else
486      { // UTF-8
487        $language_name = convert_charset($language_name,
488              'utf-8', $target_charset);
489        $languages[$file] = $language_name;
490      }
491    }
492  }
493  closedir($dir);
494  @asort($languages);
495
496  return $languages;
497}
498
499function pwg_log($image_id = null, $image_type = null)
500{
501  global $conf, $user, $page;
502
503  $do_log = $conf['log'];
504  if (is_admin())
505  {
506    $do_log = $conf['history_admin'];
507  }
508  if (is_a_guest())
509  {
510    $do_log = $conf['history_guest'];
511  }
512
513  $do_log = trigger_event('pwg_log_allowed', $do_log, $image_id, $image_type);
514
515  if (!$do_log)
516  {
517    return false;
518  }
519
520  $tags_string = null;
521  if ('tags'==@$page['section'])
522  {
523    $tags_string = implode(',', $page['tag_ids']);
524  }
525
526  $query = '
527INSERT INTO '.HISTORY_TABLE.'
528  (
529    date,
530    time,
531    user_id,
532    IP,
533    section,
534    category_id,
535    image_id,
536    image_type,
537    tag_ids
538  )
539  VALUES
540  (
541    CURDATE(),
542    CURTIME(),
543    '.$user['id'].',
544    \''.$_SERVER['REMOTE_ADDR'].'\',
545    '.(isset($page['section']) ? "'".$page['section']."'" : 'NULL').',
546    '.(isset($page['category']['id']) ? $page['category']['id'] : 'NULL').',
547    '.(isset($image_id) ? $image_id : 'NULL').',
548    '.(isset($image_type) ? "'".$image_type."'" : 'NULL').',
549    '.(isset($tags_string) ? "'".$tags_string."'" : 'NULL').'
550  )
551;';
552  pwg_query($query);
553
554  return true;
555}
556
557// format_date returns a formatted date for display. The date given in
558// argument must be an american format (2003-09-15). By option, you can show the time.
559// The output is internationalized.
560//
561// format_date( "2003-09-15", true ) -> "Monday 15 September 2003 21:52"
562function format_date($date, $show_time = false)
563{
564  global $lang;
565
566  $ymdhms = array();
567  $tok = strtok( $date, '- :');
568  while ($tok !== false)
569  {
570    $ymdhms[] = $tok;
571    $tok = strtok('- :');
572  }
573
574  if ( count($ymdhms)<3 )
575  {
576    return false;
577  }
578
579  $formated_date = '';
580  // before 1970, Microsoft Windows can't mktime
581  if ($ymdhms[0] >= 1970)
582  {
583    // we ask midday because Windows think it's prior to midnight with a
584    // zero and refuse to work
585    $formated_date.= $lang['day'][date('w', mktime(12,0,0,$ymdhms[1],$ymdhms[2],$ymdhms[0]))];
586  }
587  $formated_date.= ' '.$ymdhms[2];
588  $formated_date.= ' '.$lang['month'][(int)$ymdhms[1]];
589  $formated_date.= ' '.$ymdhms[0];
590  if ($show_time and count($ymdhms)>=5 )
591  {
592    $formated_date.= ' '.$ymdhms[3].':'.$ymdhms[4];
593  }
594  return $formated_date;
595}
596
597function pwg_query($query)
598{
599  global $conf,$page,$debug,$t2;
600
601  $start = get_moment();
602  ($result = mysql_query($query)) or my_error($query, $conf['die_on_sql_error']);
603
604  $time = get_moment() - $start;
605
606  if (!isset($page['count_queries']))
607  {
608    $page['count_queries'] = 0;
609    $page['queries_time'] = 0;
610  }
611
612  $page['count_queries']++;
613  $page['queries_time']+= $time;
614
615  if ($conf['show_queries'])
616  {
617    $output = '';
618    $output.= '<pre>['.$page['count_queries'].'] ';
619    $output.= "\n".$query;
620    $output.= "\n".'(this query time : ';
621    $output.= '<b>'.number_format($time, 3, '.', ' ').' s)</b>';
622    $output.= "\n".'(total SQL time  : ';
623    $output.= number_format($page['queries_time'], 3, '.', ' ').' s)';
624    $output.= "\n".'(total time      : ';
625    $output.= number_format( ($time+$start-$t2), 3, '.', ' ').' s)';
626    if ( $result!=null and preg_match('/\s*SELECT\s+/i',$query) )
627    {
628      $output.= "\n".'(num rows        : ';
629      $output.= mysql_num_rows($result).' )';
630    }
631    elseif ( $result!=null
632      and preg_match('/\s*INSERT|UPDATE|REPLACE|DELETE\s+/i',$query) )
633    {
634      $output.= "\n".'(affected rows   : ';
635      $output.= mysql_affected_rows().' )';
636    }
637    $output.= "</pre>\n";
638
639    $debug .= $output;
640  }
641
642  return $result;
643}
644
645function pwg_debug( $string )
646{
647  global $debug,$t2,$page;
648
649  $now = explode( ' ', microtime() );
650  $now2 = explode( '.', $now[0] );
651  $now2 = $now[1].'.'.$now2[1];
652  $time = number_format( $now2 - $t2, 3, '.', ' ').' s';
653  $debug .= '<p>';
654  $debug.= '['.$time.', ';
655  $debug.= $page['count_queries'].' queries] : '.$string;
656  $debug.= "</p>\n";
657}
658
659/**
660 * Redirects to the given URL (HTTP method)
661 *
662 * Note : once this function called, the execution doesn't go further
663 * (presence of an exit() instruction.
664 *
665 * @param string $url
666 * @return void
667 */
668function redirect_http( $url )
669{
670  if (ob_get_length () !== FALSE)
671  {
672    ob_clean();
673  }
674  // default url is on html format
675  $url = html_entity_decode($url);
676  header('Request-URI: '.$url);
677  header('Content-Location: '.$url);
678  header('Location: '.$url);
679  exit();
680}
681
682/**
683 * Redirects to the given URL (HTML method)
684 *
685 * Note : once this function called, the execution doesn't go further
686 * (presence of an exit() instruction.
687 *
688 * @param string $url
689 * @param string $title_msg
690 * @param integer $refreh_time
691 * @return void
692 */
693function redirect_html( $url , $msg = '', $refresh_time = 0)
694{
695  global $user, $template, $lang_info, $conf, $lang, $t2, $page, $debug;
696
697  if (!isset($lang_info))
698  {
699    $user = build_user( $conf['guest_id'], true);
700    load_language('common.lang');
701    trigger_action('loading_lang');
702    load_language('local.lang', '', array('no_fallback'=>true) );
703    list($tmpl, $thm) = explode('/', get_default_template());
704    $template = new Template(PHPWG_ROOT_PATH.'template/'.$tmpl, $thm);
705  }
706  else
707  {
708    $template = new Template(PHPWG_ROOT_PATH.'template/'.$user['template'], $user['theme']);
709  }
710
711  if (empty($msg))
712  {
713    $msg = nl2br(l10n('redirect_msg'));
714  }
715
716  $refresh = $refresh_time;
717  $url_link = $url;
718  $title = 'redirection';
719
720  $template->set_filenames( array( 'redirect' => 'redirect.tpl' ) );
721
722  include( PHPWG_ROOT_PATH.'include/page_header.php' );
723
724  $template->set_filenames( array( 'redirect' => 'redirect.tpl' ) );
725  $template->assign('REDIRECT_MSG', $msg);
726
727  $template->parse('redirect');
728
729  include( PHPWG_ROOT_PATH.'include/page_tail.php' );
730
731  exit();
732}
733
734/**
735 * Redirects to the given URL (Switch to HTTP method or HTML method)
736 *
737 * Note : once this function called, the execution doesn't go further
738 * (presence of an exit() instruction.
739 *
740 * @param string $url
741 * @param string $title_msg
742 * @param integer $refreh_time
743 * @return void
744 */
745function redirect( $url , $msg = '', $refresh_time = 0)
746{
747  global $conf;
748
749  // with RefeshTime <> 0, only html must be used
750  if ($conf['default_redirect_method']=='http'
751      and $refresh_time==0
752      and !headers_sent()
753    )
754  {
755    redirect_http($url);
756  }
757  else
758  {
759    redirect_html($url, $msg, $refresh_time);
760  }
761}
762
763/**
764 * returns $_SERVER['QUERY_STRING'] whitout keys given in parameters
765 *
766 * @param array $rejects
767 * @param boolean $escape - if true escape & to &amp; (for html)
768 * @returns string
769 */
770function get_query_string_diff($rejects=array(), $escape=true)
771{
772  $query_string = '';
773
774  $str = $_SERVER['QUERY_STRING'];
775  parse_str($str, $vars);
776
777  $is_first = true;
778  foreach ($vars as $key => $value)
779  {
780    if (!in_array($key, $rejects))
781    {
782      $query_string.= $is_first ? '?' : ($escape ? '&amp;' : '&' );
783      $is_first = false;
784      $query_string.= $key.'='.$value;
785    }
786  }
787
788  return $query_string;
789}
790
791function url_is_remote($url)
792{
793  if ( strncmp($url, 'http://', 7)==0
794    or strncmp($url, 'https://', 8)==0 )
795  {
796    return true;
797  }
798  return false;
799}
800
801/**
802 * returns available template/theme
803 */
804function get_pwg_themes()
805{
806  global $conf;
807  $themes = array();
808
809  $template_dir = PHPWG_ROOT_PATH.'template';
810
811  foreach (get_dirs($template_dir) as $template)
812  {
813    foreach (get_dirs($template_dir.'/'.$template.'/theme') as $theme)
814    {
815      if ( ($template.'/'.$theme) != $conf['admin_layout'] )
816      array_push($themes, $template.'/'.$theme);
817    }
818  }
819
820  return $themes;
821}
822
823/* Returns the PATH to the thumbnail to be displayed. If the element does not
824 * have a thumbnail, the default mime image path is returned. The PATH can be
825 * used in the php script, but not sent to the browser.
826 * @param array element_info assoc array containing element info from db
827 * at least 'path', 'tn_ext' and 'id' should be present
828 */
829function get_thumbnail_path($element_info)
830{
831  $path = get_thumbnail_location($element_info);
832  if ( !url_is_remote($path) )
833  {
834    $path = PHPWG_ROOT_PATH.$path;
835  }
836  return $path;
837}
838
839/* Returns the URL of the thumbnail to be displayed. If the element does not
840 * have a thumbnail, the default mime image url is returned. The URL can be
841 * sent to the browser, but not used in the php script.
842 * @param array element_info assoc array containing element info from db
843 * at least 'path', 'tn_ext' and 'id' should be present
844 */
845function get_thumbnail_url($element_info)
846{
847  $path = get_thumbnail_location($element_info);
848  if ( !url_is_remote($path) )
849  {
850    $path = embellish_url(get_root_url().$path);
851  }
852
853  // plugins want another url ?
854  $path = trigger_event('get_thumbnail_url', $path, $element_info);
855  return $path;
856}
857
858/* returns the relative path of the thumnail with regards to to the root
859of piwigo (not the current page!).This function is not intended to be
860called directly from code.*/
861function get_thumbnail_location($element_info)
862{
863  global $conf;
864  if ( !empty( $element_info['tn_ext'] ) )
865  {
866    $path = substr_replace(
867      get_filename_wo_extension($element_info['path']),
868      '/thumbnail/'.$conf['prefix_thumbnail'],
869      strrpos($element_info['path'],'/'),
870      1
871      );
872    $path.= '.'.$element_info['tn_ext'];
873  }
874  else
875  {
876    $path = get_themeconf('mime_icon_dir')
877        .strtolower(get_extension($element_info['path'])).'.png';
878  }
879
880  // plugins want another location ?
881  $path = trigger_event( 'get_thumbnail_location', $path, $element_info);
882  return $path;
883}
884
885/* returns the title of the thumnail */
886function get_thumbnail_title($element_info)
887{
888  // message in title for the thumbnail
889  if (isset($element_info['file']))
890  {
891    $thumbnail_title = $element_info['file'];
892  }
893  else
894  {
895    $thumbnail_title = '';
896  }
897
898  if (!empty($element_info['filesize']))
899  {
900    $thumbnail_title .= ' : '.sprintf(l10n('%d Kb'), $element_info['filesize']);
901  }
902
903  return $thumbnail_title;
904}
905
906// my_error returns (or send to standard output) the message concerning the
907// error occured for the last mysql query.
908function my_error($header, $die)
909{
910  $error = "[mysql error ".mysql_errno().'] '.mysql_error()."\n";
911  $error .= $header;
912
913  if ($die)
914  {
915    fatal_error($error);
916  }
917  echo("<pre>");
918  trigger_error($error, E_USER_WARNING);
919  echo("</pre>");
920}
921
922
923/**
924 * creates an array based on a query, this function is a very common pattern
925 * used here
926 *
927 * @param string $query
928 * @param string $fieldname
929 * @return array
930 */
931function array_from_query($query, $fieldname)
932{
933  $array = array();
934
935  $result = pwg_query($query);
936  while ($row = mysql_fetch_array($result))
937  {
938    array_push($array, $row[$fieldname]);
939  }
940
941  return $array;
942}
943
944/**
945 * fill the current user caddie with given elements, if not already in
946 * caddie
947 *
948 * @param array elements_id
949 */
950function fill_caddie($elements_id)
951{
952  global $user;
953
954  include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
955
956  $query = '
957SELECT element_id
958  FROM '.CADDIE_TABLE.'
959  WHERE user_id = '.$user['id'].'
960;';
961  $in_caddie = array_from_query($query, 'element_id');
962
963  $caddiables = array_diff($elements_id, $in_caddie);
964
965  $datas = array();
966
967  foreach ($caddiables as $caddiable)
968  {
969    array_push($datas, array('element_id' => $caddiable,
970                             'user_id' => $user['id']));
971  }
972
973  if (count($caddiables) > 0)
974  {
975    mass_inserts(CADDIE_TABLE, array('element_id','user_id'), $datas);
976  }
977}
978
979/**
980 * returns the element name from its filename
981 *
982 * @param string filename
983 * @return string name
984 */
985function get_name_from_file($filename)
986{
987  return str_replace('_',' ',get_filename_wo_extension($filename));
988}
989
990/**
991 * returns the corresponding value from $lang if existing. Else, the key is
992 * returned
993 *
994 * @param string key
995 * @return string
996 */
997function l10n($key)
998{
999  global $lang, $conf;
1000
1001  if ($conf['debug_l10n'] and !isset($lang[$key]) and !empty($key))
1002  {
1003    trigger_error('[l10n] language key "'.$key.'" is not defined', E_USER_WARNING);
1004  }
1005
1006  return isset($lang[$key]) ? $lang[$key] : $key;
1007}
1008
1009/**
1010 * returns the prinft value for strings including %d
1011 * return is concorded with decimal value (singular, plural)
1012 *
1013 * @param singular string key
1014 * @param plural string key
1015 * @param decimal value
1016 * @return string
1017 */
1018function l10n_dec($singular_fmt_key, $plural_fmt_key, $decimal)
1019{
1020  global $lang_info;
1021
1022  return
1023    sprintf(
1024      l10n((
1025        (($decimal > 1) or ($decimal == 0 and $lang_info['zero_plural']))
1026          ? $plural_fmt_key
1027          : $singular_fmt_key
1028        )), $decimal);
1029}
1030/*
1031 * returns a single element to use with l10n_args
1032 *
1033 * @param string key: translation key
1034 * @param array/string/../number args:
1035 *   arguments to use on sprintf($key, args)
1036 *   if args is a array, each values are used on sprintf
1037 * @return string
1038 */
1039function get_l10n_args($key, $args)
1040{
1041  if (is_array($args))
1042  {
1043    $key_arg = array_merge(array($key), $args);
1044  }
1045  else
1046  {
1047    $key_arg = array($key,  $args);
1048  }
1049  return array('key_args' => $key_arg);
1050}
1051
1052/*
1053 * returns a string with formated with l10n_args elements
1054 *
1055 * @param element/array $key_args: element or array of l10n_args elements
1056 * @param $sep: if $key_args is array,
1057 *   separator is used when translated l10n_args elements are concated
1058 * @return string
1059 */
1060function l10n_args($key_args, $sep = "\n")
1061{
1062  if (is_array($key_args))
1063  {
1064    foreach ($key_args as $key => $element)
1065    {
1066      if (isset($result))
1067      {
1068        $result .= $sep;
1069      }
1070      else
1071      {
1072        $result = '';
1073      }
1074
1075      if ($key === 'key_args')
1076      {
1077        array_unshift($element, l10n(array_shift($element)));
1078        $result .= call_user_func_array('sprintf', $element);
1079      }
1080      else
1081      {
1082        $result .= l10n_args($element, $sep);
1083      }
1084    }
1085  }
1086  else
1087  {
1088    fatal_error('l10n_args: Invalid arguments');
1089  }
1090
1091  return $result;
1092}
1093
1094/**
1095 * returns the corresponding value from $themeconf if existing. Else, the
1096 * key is returned
1097 *
1098 * @param string key
1099 * @return string
1100 */
1101function get_themeconf($key)
1102{
1103  global $template;
1104
1105  return $template->get_themeconf($key);
1106}
1107
1108/**
1109 * Returns webmaster mail address depending on $conf['webmaster_id']
1110 *
1111 * @return string
1112 */
1113function get_webmaster_mail_address()
1114{
1115  global $conf;
1116
1117  $query = '
1118SELECT '.$conf['user_fields']['email'].'
1119  FROM '.USERS_TABLE.'
1120  WHERE '.$conf['user_fields']['id'].' = '.$conf['webmaster_id'].'
1121;';
1122  list($email) = mysql_fetch_array(pwg_query($query));
1123
1124  return $email;
1125}
1126
1127/**
1128 * Add configuration parameters from database to global $conf array
1129 *
1130 * @return void
1131 */
1132function load_conf_from_db($condition = '')
1133{
1134  global $conf;
1135
1136  $query = '
1137SELECT param, value
1138 FROM '.CONFIG_TABLE.'
1139 '.(!empty($condition) ? 'WHERE '.$condition : '').'
1140;';
1141  $result = pwg_query($query);
1142
1143  if ((mysql_num_rows($result) == 0) and !empty($condition))
1144  {
1145    fatal_error('No configuration data');
1146  }
1147
1148  while ($row = mysql_fetch_array($result))
1149  {
1150    $conf[ $row['param'] ] = isset($row['value']) ? $row['value'] : '';
1151
1152    // If the field is true or false, the variable is transformed into a
1153    // boolean value.
1154    if ($conf[$row['param']] == 'true' or $conf[$row['param']] == 'false')
1155    {
1156      $conf[ $row['param'] ] = get_boolean($conf[ $row['param'] ]);
1157    }
1158  }
1159}
1160
1161/**
1162 * Prepends and appends a string at each value of the given array.
1163 *
1164 * @param array
1165 * @param string prefix to each array values
1166 * @param string suffix to each array values
1167 */
1168function prepend_append_array_items($array, $prepend_str, $append_str)
1169{
1170  array_walk(
1171    $array,
1172    create_function('&$s', '$s = "'.$prepend_str.'".$s."'.$append_str.'";')
1173    );
1174
1175  return $array;
1176}
1177
1178/**
1179 * creates an hashed based on a query, this function is a very common
1180 * pattern used here. Among the selected columns fetched, choose one to be
1181 * the key, another one to be the value.
1182 *
1183 * @param string $query
1184 * @param string $keyname
1185 * @param string $valuename
1186 * @return array
1187 */
1188function simple_hash_from_query($query, $keyname, $valuename)
1189{
1190  $array = array();
1191
1192  $result = pwg_query($query);
1193  while ($row = mysql_fetch_array($result))
1194  {
1195    $array[ $row[$keyname] ] = $row[$valuename];
1196  }
1197
1198  return $array;
1199}
1200
1201/**
1202 * creates an hashed based on a query, this function is a very common
1203 * pattern used here. The key is given as parameter, the value is an associative
1204 * array.
1205 *
1206 * @param string $query
1207 * @param string $keyname
1208 * @return array
1209 */
1210function hash_from_query($query, $keyname)
1211{
1212  $array = array();
1213  $result = pwg_query($query);
1214  while ($row = mysql_fetch_assoc($result))
1215  {
1216    $array[ $row[$keyname] ] = $row;
1217  }
1218  return $array;
1219}
1220
1221/**
1222 * Return basename of the current script
1223 * Lower case convertion is applied on return value
1224 * Return value is without file extention ".php"
1225 *
1226 * @param void
1227 *
1228 * @return script basename
1229 */
1230function script_basename()
1231{
1232  global $conf;
1233
1234  foreach (array('SCRIPT_NAME', 'SCRIPT_FILENAME', 'PHP_SELF') as $value)
1235  {
1236    if (!empty($_SERVER[$value]))
1237    {
1238      $filename = strtolower($_SERVER[$value]);
1239      if ($conf['php_extension_in_urls'] and get_extension($filename)!=='php')
1240        continue;
1241      $basename = basename($filename, '.php');
1242      if (!empty($basename))
1243      {
1244        return $basename;
1245      }
1246    }
1247  }
1248  return '';
1249}
1250
1251/**
1252 * Return value for the current page define on $conf['filter_pages']
1253 * Îf value is not defined, default value are returned
1254 *
1255 * @param value name
1256 *
1257 * @return filter page value
1258 */
1259function get_filter_page_value($value_name)
1260{
1261  global $conf;
1262
1263  $page_name = script_basename();
1264
1265  if (isset($conf['filter_pages'][$page_name][$value_name]))
1266  {
1267    return $conf['filter_pages'][$page_name][$value_name];
1268  }
1269  else if (isset($conf['filter_pages']['default'][$value_name]))
1270  {
1271    return $conf['filter_pages']['default'][$value_name];
1272  }
1273  else
1274  {
1275    return null;
1276  }
1277}
1278
1279/**
1280 * returns the character set of data sent to browsers / received from forms
1281 */
1282function get_pwg_charset()
1283{
1284  defined('PWG_CHARSET') or fatal_error('PWG_CHARSET undefined');
1285  return PWG_CHARSET;
1286}
1287
1288/**
1289 * includes a language file or returns the content of a language file
1290 * availability of the file
1291 *
1292 * in descending order of preference:
1293 *   param language, user language, default language
1294 * Piwigo default language.
1295 *
1296 * @param string filename
1297 * @param string dirname
1298 * @param mixed options can contain
1299 *     language - language to load (if empty uses user language)
1300 *     return - if true the file content is returned otherwise the file is evaluated as php
1301 *     target_charset -
1302 *     no_fallback - the language must be respected
1303 * @return boolean success status or a string if options['return'] is true
1304 */
1305function load_language($filename, $dirname = '',
1306    $options = array() )
1307{
1308  global $user;
1309
1310  if (! @$options['return'] )
1311  {
1312    $filename .= '.php'; //MAYBE to do .. load .po and .mo localization files
1313  }
1314  if (empty($dirname))
1315  {
1316    $dirname = PHPWG_ROOT_PATH;
1317  }
1318  $dirname .= 'language/';
1319
1320  $languages = array();
1321  if ( !empty($options['language']) )
1322  {
1323    $languages[] = $options['language'];
1324  }
1325  if ( !empty($user['language']) )
1326  {
1327    $languages[] = $user['language'];
1328  }
1329  if ( ! @$options['no_fallback'] )
1330  {
1331    if ( defined('PHPWG_INSTALLED') )
1332    {
1333      $languages[] = get_default_language();
1334    }
1335    $languages[] = PHPWG_DEFAULT_LANGUAGE;
1336  }
1337
1338  $languages = array_unique($languages);
1339
1340  if ( empty($options['target_charset']) )
1341  {
1342    $target_charset = get_pwg_charset();
1343  }
1344  else
1345  {
1346    $target_charset = $options['target_charset'];
1347  }
1348  $target_charset = strtolower($target_charset);
1349  $source_charset = '';
1350  $source_file    = '';
1351  foreach ($languages as $language)
1352  {
1353    $dir = $dirname.$language;
1354
1355    if ($target_charset!='utf-8')
1356    {
1357      // exact charset match - no conversion required
1358      $f = $dir.'.'.$target_charset.'/'.$filename;
1359      if (file_exists($f))
1360      {
1361        $source_file = $f;
1362        break;
1363      }
1364    }
1365
1366    // UTF-8 ?
1367    $f = $dir.'/'.$filename;
1368    if (file_exists($f))
1369    {
1370      $source_charset = 'utf-8';
1371      $source_file = $f;
1372      break;
1373    }
1374  }
1375
1376  if ( !empty($source_file) )
1377  {
1378    if (! @$options['return'] )
1379    {
1380      @include($source_file);
1381      $load_lang = @$lang;
1382      $load_lang_info = @$lang_info;
1383
1384      global $lang, $lang_info;
1385      if ( !isset($lang) ) $lang=array();
1386      if ( !isset($lang_info) ) $lang_info=array();
1387
1388      if ( !empty($source_charset) and $source_charset!=$target_charset)
1389      {
1390        if ( is_array($load_lang) )
1391        {
1392          foreach ($load_lang as $k => $v)
1393          {
1394            if ( is_array($v) )
1395            {
1396              $func = create_function('$v', 'return convert_charset($v, "'.$source_charset.'","'.$target_charset.'");' );
1397              $lang[$k] = array_map($func, $v);
1398            }
1399            else
1400              $lang[$k] = convert_charset($v, $source_charset, $target_charset);
1401          }
1402        }
1403        if ( is_array($load_lang_info) )
1404        {
1405          foreach ($load_lang_info as $k => $v)
1406          {
1407            $lang_info[$k] = convert_charset($v, $source_charset, $target_charset);
1408          }
1409        }
1410      }
1411      else
1412      {
1413        $lang = array_merge( $lang, (array)$load_lang );
1414        $lang_info = array_merge( $lang_info, (array)$load_lang_info );
1415      }
1416      return true;
1417    }
1418    else
1419    {
1420      $content = @file_get_contents($source_file);
1421      if ( !empty($source_charset) and $source_charset!=$target_charset)
1422      {
1423        $content = convert_charset($content, $source_charset, $target_charset);
1424      }
1425      return $content;
1426    }
1427  }
1428  return false;
1429}
1430
1431/**
1432 * converts a string from a character set to another character set
1433 * @param string str the string to be converted
1434 * @param string source_charset the character set in which the string is encoded
1435 * @param string dest_charset the destination character set
1436 */
1437function convert_charset($str, $source_charset, $dest_charset)
1438{
1439  if ($source_charset==$dest_charset)
1440    return $str;
1441  if ($source_charset=='iso-8859-1' and $dest_charset=='utf-8')
1442  {
1443    return utf8_encode($str);
1444  }
1445  if ($source_charset=='utf-8' and $dest_charset=='iso-8859-1')
1446  {
1447    return utf8_decode($str);
1448  }
1449  if (function_exists('iconv'))
1450  {
1451    return iconv($source_charset, $dest_charset, $str);
1452  }
1453  if (function_exists('mb_convert_encoding'))
1454  {
1455    return mb_convert_encoding( $str, $dest_charset, $source_charset );
1456  }
1457  return $str; //???
1458}
1459
1460/**
1461 * makes sure a index.htm protects the directory from browser file listing
1462 *
1463 * @param string dir directory
1464 */
1465function secure_directory($dir)
1466{
1467  $file = $dir.'/index.htm';
1468  if (!file_exists($file))
1469  {
1470    @file_put_contents($file, 'Not allowed!');
1471  }
1472}
1473
1474/**
1475 * returns a "secret key" that is to be sent back when a user enters a comment
1476 *
1477 * @param int image_id
1478 */
1479function get_comment_post_key($image_id)
1480{
1481  global $conf;
1482
1483  $time = time();
1484
1485  return sprintf(
1486    '%s:%s',
1487    $time,
1488    hash_hmac(
1489      'md5',
1490      $time.':'.$image_id,
1491      $conf['secret_key']
1492      )
1493    );
1494}
1495?>
Note: See TracBrowser for help on using the repository browser.