source: trunk/include/functions.inc.php @ 6060

Revision 6060, 41.5 KB checked in by plg, 10 years ago (diff)

bug 1063 fixed: avoid error when adding a tag in chinese or russian characters.
In any language where the str2url would return an empty string. The behavior
doesn't change for european characters.

rvelices warned me about the many issues we might encounter with copy/paste of
the URL and required url_encode/url_decode BUT after many tests (Linux with
Firefox 3.0/Google Chrome 5, MacOS 10.6 with Firefox/Safari, WindowsXP with
IE6/Firefox) I've found 0 problem, even with the most error prone mode
$conftag_url_style = 'tag'

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