source: trunk/admin/include/functions.php @ 4493

Last change on this file since 4493 was 4493, checked in by nikrou, 14 years ago

Bug 1328 : improve check function

  • Property svn:eol-style set to LF
File size: 43.3 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(PHPWG_ROOT_PATH.'admin/include/functions_metadata.php');
25
26/**
27 * check token comming from form posted or get params to prevent csrf attacks
28 * if pwg_token is empty action doesn't require token
29 * else pwg_token is compare to server token
30 *
31 * @return void access denied if token given is not equal to server token
32 */
33function check_token()
34{
35  global $conf;
36
37  $valid_token = hash_hmac('md5', session_id(), $conf['secret_key']);
38  $given_token = null;
39
40  if (!empty($_POST['pwg_token']))
41  {
42    $given_token = $_POST['pwg_token'];
43  }
44  elseif (!empty($_GET['pwg_token']))
45  {
46    $given_token = $_GET['pwg_token'];
47  }
48  if ($given_token != $valid_token)
49  {
50    access_denied();   
51  }
52}
53
54// The function delete_site deletes a site and call the function
55// delete_categories for each primary category of the site
56function delete_site( $id )
57{
58  // destruction of the categories of the site
59  $query = '
60SELECT id
61  FROM '.CATEGORIES_TABLE.'
62  WHERE site_id = '.$id.'
63;';
64  $result = pwg_query($query);
65  $category_ids = array();
66  while ($row = pwg_db_fetch_assoc($result))
67  {
68    array_push($category_ids, $row['id']);
69  }
70  delete_categories($category_ids);
71
72  // destruction of the site
73  $query = '
74DELETE FROM '.SITES_TABLE.'
75  WHERE id = '.$id.'
76;';
77  pwg_query($query);
78}
79
80
81// The function delete_categories deletes the categories identified by the
82// (numeric) key of the array $ids. It also deletes (in the database) :
83//    - all the elements of the category (delete_elements, see further)
84//    - all the links between elements and this category
85//    - all the restrictions linked to the category
86// The function works recursively.
87function delete_categories($ids)
88{
89  if (count($ids) == 0)
90  {
91    return;
92  }
93
94  // add sub-category ids to the given ids : if a category is deleted, all
95  // sub-categories must be so
96  $ids = get_subcat_ids($ids);
97
98  // destruction of all the related elements
99  $query = '
100SELECT id
101  FROM '.IMAGES_TABLE.'
102  WHERE storage_category_id IN (
103'.wordwrap(implode(', ', $ids), 80, "\n").')
104;';
105  $result = pwg_query($query);
106  $element_ids = array();
107  while ($row = pwg_db_fetch_assoc($result))
108  {
109    array_push($element_ids, $row['id']);
110  }
111  delete_elements($element_ids);
112
113  // destruction of the links between images and this category
114  $query = '
115DELETE FROM '.IMAGE_CATEGORY_TABLE.'
116  WHERE category_id IN (
117'.wordwrap(implode(', ', $ids), 80, "\n").')
118;';
119  pwg_query($query);
120
121  // destruction of the access linked to the category
122  $query = '
123DELETE FROM '.USER_ACCESS_TABLE.'
124  WHERE cat_id IN (
125'.wordwrap(implode(', ', $ids), 80, "\n").')
126;';
127  pwg_query($query);
128
129  $query = '
130DELETE FROM '.GROUP_ACCESS_TABLE.'
131  WHERE cat_id IN (
132'.wordwrap(implode(', ', $ids), 80, "\n").')
133;';
134  pwg_query($query);
135
136  // destruction of the category
137  $query = '
138DELETE FROM '.CATEGORIES_TABLE.'
139  WHERE id IN (
140'.wordwrap(implode(', ', $ids), 80, "\n").')
141;';
142  pwg_query($query);
143
144  $query='
145DELETE FROM '.OLD_PERMALINKS_TABLE.'
146  WHERE cat_id IN ('.implode(',',$ids).')';
147  pwg_query($query);
148
149  $query='
150DELETE FROM '.USER_CACHE_CATEGORIES_TABLE.'
151  WHERE cat_id IN ('.implode(',',$ids).')';
152  pwg_query($query);
153
154  trigger_action('delete_categories', $ids);
155}
156
157// The function delete_elements deletes the elements identified by the
158// (numeric) values of the array $ids. It also deletes (in the database) :
159//    - all the comments related to elements
160//    - all the links between categories and elements
161//    - all the favorites associated to elements
162function delete_elements($ids, $physical_deletion=false)
163{
164  if (count($ids) == 0)
165  {
166    return;
167  }
168  trigger_action('begin_delete_elements', $ids);
169
170  if ($physical_deletion)
171  {
172    include_once(PHPWG_ROOT_PATH.'include/functions_picture.inc.php');
173
174    // we can currently delete physically only photo with no
175    // storage_category_id (added via pLoader)
176    //
177    // we assume that the element is a photo, with no representative
178    $query = '
179SELECT
180    id,
181    path,
182    tn_ext,
183    has_high
184  FROM '.IMAGES_TABLE.'
185  WHERE id IN ('.implode(',', $ids).')
186    AND storage_category_id IS NULL
187;';
188    $result = pwg_query($query);
189    while ($row = pwg_db_fetch_assoc($result))
190    {
191      $file_path = $row['path'];
192      $thumbnail_path = get_thumbnail_path($row);
193      $high_path = null;
194      if (isset($row['has_high']) and get_boolean($row['has_high']))
195      {
196        $high_path = get_high_path($row);
197      }
198
199      foreach (array($file_path, $thumbnail_path, $high_path) as $path)
200      {
201        if (isset($path) and is_file($path) and !unlink($path))
202        {
203          die('"'.$path.'" cannot be removed');
204        }
205      }
206    }
207  }
208
209  // destruction of the comments on the image
210  $query = '
211DELETE FROM '.COMMENTS_TABLE.'
212  WHERE image_id IN (
213'.wordwrap(implode(', ', $ids), 80, "\n").')
214;';
215  pwg_query($query);
216
217  // destruction of the links between images and this category
218  $query = '
219DELETE FROM '.IMAGE_CATEGORY_TABLE.'
220  WHERE image_id IN (
221'.wordwrap(implode(', ', $ids), 80, "\n").')
222;';
223  pwg_query($query);
224
225  // destruction of the links between images and tags
226  $query = '
227DELETE FROM '.IMAGE_TAG_TABLE.'
228  WHERE image_id IN (
229'.wordwrap(implode(', ', $ids), 80, "\n").')
230;';
231  pwg_query($query);
232
233  // destruction of the favorites associated with the picture
234  $query = '
235DELETE FROM '.FAVORITES_TABLE.'
236  WHERE image_id IN (
237'.wordwrap(implode(', ', $ids), 80, "\n").')
238;';
239  pwg_query($query);
240
241  // destruction of the rates associated to this element
242  $query = '
243DELETE FROM '.RATE_TABLE.'
244  WHERE element_id IN (
245'.wordwrap(implode(', ', $ids), 80, "\n").')
246;';
247  pwg_query($query);
248
249  // destruction of the rates associated to this element
250  $query = '
251DELETE FROM '.CADDIE_TABLE.'
252  WHERE element_id IN (
253'.wordwrap(implode(', ', $ids), 80, "\n").')
254;';
255  pwg_query($query);
256
257  // destruction of the image
258  $query = '
259DELETE FROM '.IMAGES_TABLE.'
260  WHERE id IN (
261'.wordwrap(implode(', ', $ids), 80, "\n").')
262;';
263  pwg_query($query);
264
265  trigger_action('delete_elements', $ids);
266}
267
268// The delete_user function delete a user identified by the $user_id
269// It also deletes :
270//     - all the access linked to this user
271//     - all the links to any group
272//     - all the favorites linked to this user
273//     - calculated permissions linked to the user
274//     - all datas about notifications for the user
275function delete_user($user_id)
276{
277  global $conf;
278  $tables = array(
279    // destruction of the access linked to the user
280    USER_ACCESS_TABLE,
281    // destruction of data notification by mail for this user
282    USER_MAIL_NOTIFICATION_TABLE,
283    // destruction of data RSS notification for this user
284    USER_FEED_TABLE,
285    // deletion of calculated permissions linked to the user
286    USER_CACHE_TABLE,
287    // deletion of computed cache data linked to the user
288    USER_CACHE_CATEGORIES_TABLE,
289    // destruction of the group links for this user
290    USER_GROUP_TABLE,
291    // destruction of the favorites associated with the user
292    FAVORITES_TABLE,
293    // destruction of the caddie associated with the user
294    CADDIE_TABLE,
295    // deletion of piwigo specific informations
296    USER_INFOS_TABLE,
297    );
298
299  foreach ($tables as $table)
300  {
301    $query = '
302DELETE FROM '.$table.'
303  WHERE user_id = '.$user_id.'
304;';
305    pwg_query($query);
306  }
307
308  // destruction of the user
309  $query = '
310DELETE FROM '.SESSIONS_TABLE.'
311  WHERE data LIKE "pwg_uid|i:'.(int)$user_id.';%"
312;';
313  pwg_query($query);
314
315  // destruction of the user
316  $query = '
317DELETE FROM '.USERS_TABLE.'
318  WHERE '.$conf['user_fields']['id'].' = '.$user_id.'
319;';
320  pwg_query($query);
321
322  trigger_action('delete_user', $user_id);
323}
324
325/**
326 * Verifies that the representative picture really exists in the db and
327 * picks up a random represantive if possible and based on config.
328 *
329 * @param mixed category id
330 * @returns void
331 */
332function update_category($ids = 'all')
333{
334  global $conf;
335
336  if ($ids=='all')
337  {
338    $where_cats = '1=1';
339  }
340  elseif ( !is_array($ids) )
341  {
342    $where_cats = '%s='.$ids;
343  }
344  else
345  {
346    if (count($ids) == 0)
347    {
348      return false;
349    }
350    $where_cats = '%s IN('.wordwrap(implode(', ', $ids), 120, "\n").')';
351  }
352
353  // find all categories where the setted representative is not possible :
354  // the picture does not exist
355  $query = '
356SELECT DISTINCT c.id
357  FROM '.CATEGORIES_TABLE.' AS c LEFT JOIN '.IMAGES_TABLE.' AS i
358    ON c.representative_picture_id = i.id
359  WHERE representative_picture_id IS NOT NULL
360    AND '.sprintf($where_cats, 'c.id').'
361    AND i.id IS NULL
362;';
363  $wrong_representant = array_from_query($query, 'id');
364
365  if (count($wrong_representant) > 0)
366  {
367    $query = '
368UPDATE '.CATEGORIES_TABLE.'
369  SET representative_picture_id = NULL
370  WHERE id IN ('.wordwrap(implode(', ', $wrong_representant), 120, "\n").')
371;';
372    pwg_query($query);
373  }
374
375  if (!$conf['allow_random_representative'])
376  {
377    // If the random representant is not allowed, we need to find
378    // categories with elements and with no representant. Those categories
379    // must be added to the list of categories to set to a random
380    // representant.
381    $query = '
382SELECT DISTINCT id
383  FROM '.CATEGORIES_TABLE.' INNER JOIN '.IMAGE_CATEGORY_TABLE.'
384    ON id = category_id
385  WHERE representative_picture_id IS NULL
386    AND '.sprintf($where_cats, 'category_id').'
387;';
388    $to_rand = array_from_query($query, 'id');
389    if (count($to_rand) > 0)
390    {
391      set_random_representant($to_rand);
392    }
393  }
394}
395
396/**
397 * returns an array containing sub-directories which can be a category,
398 * recursive by default
399 *
400 * directories nammed "thumbnail", "pwg_high" or "pwg_representative" are
401 * omitted
402 *
403 * @param string $basedir
404 * @return array
405 */
406function get_fs_directories($path, $recursive = true)
407{
408  $dirs = array();
409
410  if (is_dir($path))
411  {
412    if ($contents = opendir($path))
413    {
414      while (($node = readdir($contents)) !== false)
415      {
416        if (is_dir($path.'/'.$node)
417            and $node != '.'
418            and $node != '..'
419            and $node != '.svn'
420            and $node != 'thumbnail'
421            and $node != 'pwg_high'
422            and $node != 'pwg_representative')
423        {
424          array_push($dirs, $path.'/'.$node);
425          if ($recursive)
426          {
427            $dirs = array_merge($dirs, get_fs_directories($path.'/'.$node));
428          }
429        }
430      }
431      closedir($contents);
432    }
433  }
434
435  return $dirs;
436}
437
438/**
439 * order categories (update categories.rank and global_rank database fields)
440 * so that rank field are consecutive integers starting at 1 for each child
441 * @return void
442 */
443function update_global_rank()
444{
445  $query = '
446SELECT id, id_uppercat, uppercats, rank, global_rank
447  FROM '.CATEGORIES_TABLE.'
448  ORDER BY id_uppercat,rank,name';
449
450  $cat_map = array();
451
452  $current_rank = 0;
453  $current_uppercat = '';
454
455  $result = pwg_query($query);
456  while ($row = pwg_db_fetch_assoc($result))
457  {
458    if ($row['id_uppercat'] != $current_uppercat)
459    {
460      $current_rank = 0;
461      $current_uppercat = $row['id_uppercat'];
462    }
463    ++$current_rank;
464    $cat =
465      array(
466        'rank' =>        $current_rank,
467        'rank_changed' =>$current_rank!=$row['rank'],
468        'global_rank' => $row['global_rank'],
469        'uppercats' =>   $row['uppercats'],
470        );
471    $cat_map[ $row['id'] ] = $cat;
472  }
473
474  $datas = array();
475
476  foreach( $cat_map as $id=>$cat )
477  {
478    $new_global_rank = preg_replace(
479          '/(\d+)/e',
480          "\$cat_map['$1']['rank']",
481          str_replace(',', '.', $cat['uppercats'] )
482          );
483    if ( $cat['rank_changed']
484      or $new_global_rank!=$cat['global_rank']
485      )
486    {
487      $datas[] = array(
488          'id' => $id,
489          'rank' => $cat['rank'],
490          'global_rank' => $new_global_rank,
491        );
492    }
493  }
494
495  mass_updates(
496    CATEGORIES_TABLE,
497    array(
498      'primary' => array('id'),
499      'update'  => array('rank', 'global_rank')
500      ),
501    $datas
502    );
503  return count($datas);
504}
505
506/**
507 * change the visible property on a set of categories
508 *
509 * @param array categories
510 * @param string value
511 * @return void
512 */
513function set_cat_visible($categories, $value)
514{
515  if (!in_array($value, array('true', 'false')))
516  {
517    trigger_error("set_cat_visible invalid param $value", E_USER_WARNING);
518    return false;
519  }
520
521  // unlocking a category => all its parent categories become unlocked
522  if ($value == 'true')
523  {
524    $uppercats = get_uppercat_ids($categories);
525    $query = '
526UPDATE '.CATEGORIES_TABLE.'
527  SET visible = \'true\'
528  WHERE id IN ('.implode(',', $uppercats).')';
529    pwg_query($query);
530  }
531  // locking a category   => all its child categories become locked
532  if ($value == 'false')
533  {
534    $subcats = get_subcat_ids($categories);
535    $query = '
536UPDATE '.CATEGORIES_TABLE.'
537  SET visible = \'false\'
538  WHERE id IN ('.implode(',', $subcats).')';
539    pwg_query($query);
540  }
541}
542
543/**
544 * change the status property on a set of categories : private or public
545 *
546 * @param array categories
547 * @param string value
548 * @return void
549 */
550function set_cat_status($categories, $value)
551{
552  if (!in_array($value, array('public', 'private')))
553  {
554    trigger_error("set_cat_status invalid param $value", E_USER_WARNING);
555    return false;
556  }
557
558  // make public a category => all its parent categories become public
559  if ($value == 'public')
560  {
561    $uppercats = get_uppercat_ids($categories);
562    $query = '
563UPDATE '.CATEGORIES_TABLE.'
564  SET status = \'public\'
565  WHERE id IN ('.implode(',', $uppercats).')
566;';
567    pwg_query($query);
568  }
569  // make a category private => all its child categories become private
570  if ($value == 'private')
571  {
572    $subcats = get_subcat_ids($categories);
573    $query = '
574UPDATE '.CATEGORIES_TABLE.'
575  SET status = \'private\'
576  WHERE id IN ('.implode(',', $subcats).')';
577    pwg_query($query);
578  }
579}
580
581/**
582 * returns all uppercats category ids of the given category ids
583 *
584 * @param array cat_ids
585 * @return array
586 */
587function get_uppercat_ids($cat_ids)
588{
589  if (!is_array($cat_ids) or count($cat_ids) < 1)
590  {
591    return array();
592  }
593
594  $uppercats = array();
595
596  $query = '
597SELECT uppercats
598  FROM '.CATEGORIES_TABLE.'
599  WHERE id IN ('.implode(',', $cat_ids).')
600;';
601  $result = pwg_query($query);
602  while ($row = pwg_db_fetch_assoc($result))
603  {
604    $uppercats = array_merge($uppercats,
605                             explode(',', $row['uppercats']));
606  }
607  $uppercats = array_unique($uppercats);
608
609  return $uppercats;
610}
611
612/**
613 * set a new random representant to the categories
614 *
615 * @param array categories
616 */
617function set_random_representant($categories)
618{
619  $datas = array();
620  foreach ($categories as $category_id)
621  {
622    $query = '
623SELECT image_id
624  FROM '.IMAGE_CATEGORY_TABLE.'
625  WHERE category_id = '.$category_id.'
626  ORDER BY '.DB_RANDOM_FUNCTION.'()
627  LIMIT 1
628;';
629    list($representative) = pwg_db_fetch_row(pwg_query($query));
630
631    array_push(
632      $datas,
633      array(
634        'id' => $category_id,
635        'representative_picture_id' => $representative,
636        )
637      );
638  }
639
640  mass_updates(
641    CATEGORIES_TABLE,
642    array(
643      'primary' => array('id'),
644      'update' => array('representative_picture_id')
645      ),
646    $datas
647    );
648}
649
650/**
651 * returns the fulldir for each given category id
652 *
653 * @param array cat_ids
654 * @return array
655 */
656function get_fulldirs($cat_ids)
657{
658  if (count($cat_ids) == 0)
659  {
660    return array();
661  }
662
663  // caching directories of existing categories
664  $query = '
665SELECT id, dir
666  FROM '.CATEGORIES_TABLE.'
667  WHERE dir IS NOT NULL
668;';
669  $cat_dirs = simple_hash_from_query($query, 'id', 'dir');
670
671  // caching galleries_url
672  $query = '
673SELECT id, galleries_url
674  FROM '.SITES_TABLE.'
675;';
676  $galleries_url = simple_hash_from_query($query, 'id', 'galleries_url');
677
678  // categories : id, site_id, uppercats
679  $categories = array();
680
681  $query = '
682SELECT id, uppercats, site_id
683  FROM '.CATEGORIES_TABLE.'
684  WHERE dir IS NOT NULL
685    AND id IN (
686'.wordwrap(implode(', ', $cat_ids), 80, "\n").')
687;';
688  $result = pwg_query($query);
689  while ($row = pwg_db_fetch_assoc($result))
690  {
691    array_push($categories, $row);
692  }
693
694  // filling $cat_fulldirs
695  $cat_fulldirs = array();
696  foreach ($categories as $category)
697  {
698    $uppercats = str_replace(',', '/', $category['uppercats']);
699    $cat_fulldirs[$category['id']] = $galleries_url[$category['site_id']];
700    $cat_fulldirs[$category['id']].= preg_replace('/(\d+)/e',
701                                                  "\$cat_dirs['$1']",
702                                                  $uppercats);
703  }
704
705  return $cat_fulldirs;
706}
707
708/**
709 * returns an array with all file system files according to
710 * $conf['file_ext']
711 *
712 * @param string $path
713 * @param bool recursive
714 * @return array
715 */
716function get_fs($path, $recursive = true)
717{
718  global $conf;
719
720  // because isset is faster than in_array...
721  if (!isset($conf['flip_picture_ext']))
722  {
723    $conf['flip_picture_ext'] = array_flip($conf['picture_ext']);
724  }
725  if (!isset($conf['flip_file_ext']))
726  {
727    $conf['flip_file_ext'] = array_flip($conf['file_ext']);
728  }
729
730  $fs['elements'] = array();
731  $fs['thumbnails'] = array();
732  $fs['representatives'] = array();
733  $subdirs = array();
734
735  if (is_dir($path))
736  {
737    if ($contents = opendir($path))
738    {
739      while (($node = readdir($contents)) !== false)
740      {
741        if (is_file($path.'/'.$node))
742        {
743          $extension = get_extension($node);
744
745//          if (in_array($extension, $conf['picture_ext']))
746          if (isset($conf['flip_picture_ext'][$extension]))
747          {
748            if (basename($path) == 'thumbnail')
749            {
750              array_push($fs['thumbnails'], $path.'/'.$node);
751            }
752            else if (basename($path) == 'pwg_representative')
753            {
754              array_push($fs['representatives'], $path.'/'.$node);
755            }
756            else
757            {
758              array_push($fs['elements'], $path.'/'.$node);
759            }
760          }
761//          else if (in_array($extension, $conf['file_ext']))
762          else if (isset($conf['flip_file_ext'][$extension]))
763          {
764            array_push($fs['elements'], $path.'/'.$node);
765          }
766        }
767        else if (is_dir($path.'/'.$node)
768                 and $node != '.'
769                 and $node != '..'
770                 and $node != 'pwg_high'
771                 and $recursive)
772        {
773          array_push($subdirs, $node);
774        }
775      }
776    }
777    closedir($contents);
778
779    foreach ($subdirs as $subdir)
780    {
781      $tmp_fs = get_fs($path.'/'.$subdir);
782
783      $fs['elements']        = array_merge($fs['elements'],
784                                           $tmp_fs['elements']);
785
786      $fs['thumbnails']      = array_merge($fs['thumbnails'],
787                                           $tmp_fs['thumbnails']);
788
789      $fs['representatives'] = array_merge($fs['representatives'],
790                                           $tmp_fs['representatives']);
791    }
792  }
793  return $fs;
794}
795
796/**
797 * stupidly returns the current microsecond since Unix epoch
798 */
799function micro_seconds()
800{
801  $t1 = explode(' ', microtime());
802  $t2 = explode('.', $t1[0]);
803  $t2 = $t1[1].substr($t2[1], 0, 6);
804  return $t2;
805}
806
807/**
808 * synchronize base users list and related users list
809 *
810 * compares and synchronizes base users table (USERS_TABLE) with its child
811 * tables (USER_INFOS_TABLE, USER_ACCESS, USER_CACHE, USER_GROUP) : each
812 * base user must be present in child tables, users in child tables not
813 * present in base table must be deleted.
814 *
815 * @return void
816 */
817function sync_users()
818{
819  global $conf;
820
821  $query = '
822SELECT '.$conf['user_fields']['id'].' AS id
823  FROM '.USERS_TABLE.'
824;';
825  $base_users = array_from_query($query, 'id');
826
827  $query = '
828SELECT user_id
829  FROM '.USER_INFOS_TABLE.'
830;';
831  $infos_users = array_from_query($query, 'user_id');
832
833  // users present in $base_users and not in $infos_users must be added
834  $to_create = array_diff($base_users, $infos_users);
835
836  if (count($to_create) > 0)
837  {
838    create_user_infos($to_create);
839  }
840
841  // users present in user related tables must be present in the base user
842  // table
843  $tables = array(
844    USER_MAIL_NOTIFICATION_TABLE,
845    USER_FEED_TABLE,
846    USER_INFOS_TABLE,
847    USER_ACCESS_TABLE,
848    USER_CACHE_TABLE,
849    USER_CACHE_CATEGORIES_TABLE,
850    USER_GROUP_TABLE
851    );
852
853  foreach ($tables as $table)
854  {
855    $query = '
856SELECT DISTINCT user_id
857  FROM '.$table.'
858;';
859    $to_delete = array_diff(
860      array_from_query($query, 'user_id'),
861      $base_users
862      );
863
864    if (count($to_delete) > 0)
865    {
866      $query = '
867DELETE
868  FROM '.$table.'
869  WHERE user_id in ('.implode(',', $to_delete).')
870;';
871      pwg_query($query);
872    }
873  }
874}
875
876/**
877 * updates categories.uppercats field based on categories.id +
878 * categories.id_uppercat
879 *
880 * @return void
881 */
882function update_uppercats()
883{
884  $query = '
885SELECT id, id_uppercat, uppercats
886  FROM '.CATEGORIES_TABLE.'
887;';
888  $cat_map = hash_from_query($query, 'id');
889
890  $datas = array();
891  foreach ($cat_map as $id => $cat)
892  {
893    $upper_list = array();
894
895    $uppercat = $id;
896    while ($uppercat)
897    {
898      array_push($upper_list, $uppercat);
899      $uppercat = $cat_map[$uppercat]['id_uppercat'];
900    }
901
902    $new_uppercats = implode(',', array_reverse($upper_list));
903    if ($new_uppercats != $cat['uppercats'])
904    {
905      array_push(
906        $datas,
907        array(
908          'id' => $id,
909          'uppercats' => $new_uppercats
910          )
911        );
912    }
913  }
914  $fields = array('primary' => array('id'), 'update' => array('uppercats'));
915  mass_updates(CATEGORIES_TABLE, $fields, $datas);
916}
917
918/**
919 * update images.path field
920 *
921 * @return void
922 */
923function update_path()
924{
925  $query = '
926SELECT DISTINCT(storage_category_id)
927  FROM '.IMAGES_TABLE.'
928  WHERE storage_category_id IS NOT NULL
929;';
930  $cat_ids = array_from_query($query, 'storage_category_id');
931  $fulldirs = get_fulldirs($cat_ids);
932
933  foreach ($cat_ids as $cat_id)
934  {
935    $query = '
936UPDATE '.IMAGES_TABLE.'
937  SET path = CONCAT(\''.$fulldirs[$cat_id].'\',\'/\',file)
938  WHERE storage_category_id = '.$cat_id.'
939;';
940    pwg_query($query);
941  }
942}
943
944/**
945 * update images.average_rate field
946 * param int $element_id optional, otherwise applies to all
947 * @return void
948 */
949function update_average_rate( $element_id=-1 )
950{
951  $query = '
952SELECT element_id,
953       ROUND(AVG(rate),2) AS average_rate
954  FROM '.RATE_TABLE;
955  if ( $element_id != -1 )
956  {
957    $query .= ' WHERE element_id=' . $element_id;
958  }
959  $query .= ' GROUP BY element_id;';
960
961  $result = pwg_query($query);
962
963  $datas = array();
964
965  while ($row = pwg_db_fetch_assoc($result))
966  {
967    array_push(
968      $datas,
969      array(
970        'id' => $row['element_id'],
971        'average_rate' => $row['average_rate']
972        )
973      );
974  }
975
976  mass_updates(
977    IMAGES_TABLE,
978    array(
979      'primary' => array('id'),
980      'update' => array('average_rate')
981      ),
982    $datas
983    );
984
985  $query='
986SELECT id FROM '.IMAGES_TABLE .'
987  LEFT JOIN '.RATE_TABLE.' ON id=element_id
988  WHERE element_id IS NULL AND average_rate IS NOT NULL';
989  if ( $element_id != -1 )
990  {
991    $query .= ' AND id=' . $element_id;
992  }
993  $to_update = array_from_query( $query, 'id');
994
995  if ( !empty($to_update) )
996  {
997    $query='
998UPDATE '.IMAGES_TABLE .'
999  SET average_rate=NULL
1000  WHERE id IN (' . implode(',',$to_update) . ')';
1001    pwg_query($query);
1002  }
1003}
1004
1005/**
1006 * change the parent category of the given categories. The categories are
1007 * supposed virtual.
1008 *
1009 * @param array category identifiers
1010 * @param int parent category identifier
1011 * @return void
1012 */
1013function move_categories($category_ids, $new_parent = -1)
1014{
1015  global $page;
1016
1017  if (count($category_ids) == 0)
1018  {
1019    return;
1020  }
1021
1022  $new_parent = $new_parent < 1 ? 'NULL' : $new_parent;
1023
1024  $categories = array();
1025
1026  $query = '
1027SELECT id, id_uppercat, status, uppercats
1028  FROM '.CATEGORIES_TABLE.'
1029  WHERE id IN ('.implode(',', $category_ids).')
1030;';
1031  $result = pwg_query($query);
1032  while ($row = pwg_db_fetch_assoc($result))
1033  {
1034    $categories[$row['id']] =
1035      array(
1036        'parent' => empty($row['id_uppercat']) ? 'NULL' : $row['id_uppercat'],
1037        'status' => $row['status'],
1038        'uppercats' => $row['uppercats']
1039        );
1040  }
1041
1042  // is the movement possible? The movement is impossible if you try to move
1043  // a category in a sub-category or itself
1044  if ('NULL' != $new_parent)
1045  {
1046    $query = '
1047SELECT uppercats
1048  FROM '.CATEGORIES_TABLE.'
1049  WHERE id = '.$new_parent.'
1050;';
1051    list($new_parent_uppercats) = pwg_db_fetch_row(pwg_query($query));
1052
1053    foreach ($categories as $category)
1054    {
1055      // technically, you can't move a category with uppercats 12,125,13,14
1056      // into a new parent category with uppercats 12,125,13,14,24
1057      if (preg_match('/^'.$category['uppercats'].',/', $new_parent_uppercats))
1058      {
1059        array_push(
1060          $page['errors'],
1061          l10n('You cannot move a category in its own sub category')
1062          );
1063        return;
1064      }
1065    }
1066  }
1067
1068  $tables =
1069    array(
1070      USER_ACCESS_TABLE => 'user_id',
1071      GROUP_ACCESS_TABLE => 'group_id'
1072      );
1073
1074  $query = '
1075UPDATE '.CATEGORIES_TABLE.'
1076  SET id_uppercat = '.$new_parent.'
1077  WHERE id IN ('.implode(',', $category_ids).')
1078;';
1079  pwg_query($query);
1080
1081  update_uppercats();
1082  update_global_rank();
1083
1084  // status and related permissions management
1085  if ('NULL' == $new_parent)
1086  {
1087    $parent_status = 'public';
1088  }
1089  else
1090  {
1091    $query = '
1092SELECT status
1093  FROM '.CATEGORIES_TABLE.'
1094  WHERE id = '.$new_parent.'
1095;';
1096    list($parent_status) = pwg_db_fetch_row(pwg_query($query));
1097  }
1098
1099  if ('private' == $parent_status)
1100  {
1101    foreach ($categories as $cat_id => $category)
1102    {
1103      switch ($category['status'])
1104      {
1105        case 'public' :
1106        {
1107          set_cat_status(array($cat_id), 'private');
1108          break;
1109        }
1110        case 'private' :
1111        {
1112          $subcats = get_subcat_ids(array($cat_id));
1113
1114          foreach ($tables as $table => $field)
1115          {
1116            $query = '
1117SELECT '.$field.'
1118  FROM '.$table.'
1119  WHERE cat_id = '.$cat_id.'
1120;';
1121            $category_access = array_from_query($query, $field);
1122
1123            $query = '
1124SELECT '.$field.'
1125  FROM '.$table.'
1126  WHERE cat_id = '.$new_parent.'
1127;';
1128            $parent_access = array_from_query($query, $field);
1129
1130            $to_delete = array_diff($parent_access, $category_access);
1131
1132            if (count($to_delete) > 0)
1133            {
1134              $query = '
1135DELETE FROM '.$table.'
1136  WHERE '.$field.' IN ('.implode(',', $to_delete).')
1137    AND cat_id IN ('.implode(',', $subcats).')
1138;';
1139              pwg_query($query);
1140            }
1141          }
1142          break;
1143        }
1144      }
1145    }
1146  }
1147
1148  array_push(
1149    $page['infos'],
1150    l10n_dec(
1151      '%d category moved', '%d categories moved',
1152      count($categories)
1153      )
1154    );
1155}
1156
1157/**
1158 * create a virtual category
1159 *
1160 * @param string category name
1161 * @param int parent category id
1162 * @return array with ('info' and 'id') or ('error') key
1163 */
1164function create_virtual_category($category_name, $parent_id=null)
1165{
1166  global $conf;
1167
1168  // is the given category name only containing blank spaces ?
1169  if (preg_match('/^\s*$/', $category_name))
1170  {
1171    return array('error' => l10n('cat_error_name'));
1172  }
1173
1174  $parent_id = !empty($parent_id) ? $parent_id : 'NULL';
1175
1176  $query = '
1177SELECT MAX(rank)
1178  FROM '.CATEGORIES_TABLE.'
1179  WHERE id_uppercat '.(is_numeric($parent_id) ? '= '.$parent_id : 'IS NULL').'
1180;';
1181  list($current_rank) = pwg_db_fetch_row(pwg_query($query));
1182
1183  $insert = array(
1184    'name' => $category_name,
1185    'rank' => ++$current_rank,
1186    'commentable' => boolean_to_string($conf['newcat_default_commentable']),
1187    'uploadable' => 'false',
1188    );
1189
1190  if ($parent_id != 'NULL')
1191  {
1192    $query = '
1193SELECT id, uppercats, global_rank, visible, status
1194  FROM '.CATEGORIES_TABLE.'
1195  WHERE id = '.$parent_id.'
1196;';
1197    $parent = pwg_db_fetch_assoc(pwg_query($query));
1198
1199    $insert['id_uppercat'] = $parent['id'];
1200    $insert['global_rank'] = $parent['global_rank'].'.'.$insert['rank'];
1201
1202    // at creation, must a category be visible or not ? Warning : if the
1203    // parent category is invisible, the category is automatically create
1204    // invisible. (invisible = locked)
1205    if ('false' == $parent['visible'])
1206    {
1207      $insert['visible'] = 'false';
1208    }
1209    else
1210    {
1211      $insert['visible'] = boolean_to_string($conf['newcat_default_visible']);
1212    }
1213
1214    // at creation, must a category be public or private ? Warning : if the
1215    // parent category is private, the category is automatically create
1216    // private.
1217    if ('private' == $parent['status'])
1218    {
1219      $insert['status'] = 'private';
1220    }
1221    else
1222    {
1223      $insert['status'] = $conf['newcat_default_status'];
1224    }
1225  }
1226  else
1227  {
1228    $insert['visible'] = boolean_to_string($conf['newcat_default_visible']);
1229    $insert['status'] = $conf['newcat_default_status'];
1230    $insert['global_rank'] = $insert['rank'];
1231  }
1232
1233  // we have then to add the virtual category
1234  mass_inserts(
1235    CATEGORIES_TABLE,
1236    array(
1237      'site_id', 'name', 'id_uppercat', 'rank', 'commentable',
1238      'uploadable', 'visible', 'status', 'global_rank',
1239      ),
1240    array($insert)
1241    );
1242
1243  $inserted_id = pwg_db_insert_id();
1244
1245  $query = '
1246UPDATE
1247  '.CATEGORIES_TABLE.'
1248  SET uppercats = \''.
1249    (isset($parent) ? $parent{'uppercats'}.',' : '').
1250    $inserted_id.
1251    '\'
1252  WHERE id = '.$inserted_id.'
1253;';
1254  pwg_query($query);
1255
1256  return array(
1257    'info' => l10n('cat_virtual_added'),
1258    'id'   => $inserted_id,
1259    );
1260}
1261
1262/**
1263 * Set tags to an image. Warning: given tags are all tags associated to the
1264 * image, not additionnal tags.
1265 *
1266 * @param array tag ids
1267 * @param int image id
1268 * @return void
1269 */
1270function set_tags($tags, $image_id)
1271{
1272  $query = '
1273DELETE
1274  FROM '.IMAGE_TAG_TABLE.'
1275  WHERE image_id = '.$image_id.'
1276;';
1277  pwg_query($query);
1278
1279  if (count($tags) > 0)
1280  {
1281    $inserts = array();
1282    foreach ($tags as $tag_id)
1283    {
1284      array_push(
1285        $inserts,
1286        array(
1287          'tag_id' => $tag_id,
1288          'image_id' => $image_id
1289          )
1290        );
1291    }
1292    mass_inserts(
1293      IMAGE_TAG_TABLE,
1294      array_keys($inserts[0]),
1295      $inserts
1296      );
1297  }
1298}
1299
1300/**
1301 * Add new tags to a set of images.
1302 *
1303 * @param array tag ids
1304 * @param array image ids
1305 * @return void
1306 */
1307function add_tags($tags, $images)
1308{
1309  if (count($tags) == 0 or count($tags) == 0)
1310  {
1311    return;
1312  }
1313
1314  // we can't insert twice the same {image_id,tag_id} so we must first
1315  // delete lines we'll insert later
1316  $query = '
1317DELETE
1318  FROM '.IMAGE_TAG_TABLE.'
1319  WHERE image_id IN ('.implode(',', $images).')
1320    AND tag_id IN ('.implode(',', $tags).')
1321;';
1322  pwg_query($query);
1323
1324  $inserts = array();
1325  foreach ($images as $image_id)
1326  {
1327    foreach ($tags as $tag_id)
1328    {
1329      array_push(
1330        $inserts,
1331        array(
1332          'image_id' => $image_id,
1333          'tag_id' => $tag_id,
1334          )
1335        );
1336    }
1337  }
1338  mass_inserts(
1339    IMAGE_TAG_TABLE,
1340    array_keys($inserts[0]),
1341    $inserts
1342    );
1343}
1344
1345function tag_id_from_tag_name($tag_name)
1346{
1347  global $page;
1348
1349  $tag_name = trim($tag_name);
1350  if (isset($page['tag_id_from_tag_name_cache'][$tag_name]))
1351  {
1352    return $page['tag_id_from_tag_name_cache'][$tag_name];
1353  }
1354
1355  // does the tag already exists?
1356  $query = '
1357SELECT id
1358  FROM '.TAGS_TABLE.'
1359  WHERE name = \''.$tag_name.'\'
1360;';
1361  $existing_tags = array_from_query($query, 'id');
1362
1363  if (count($existing_tags) == 0)
1364  {
1365    mass_inserts(
1366      TAGS_TABLE,
1367      array('name', 'url_name'),
1368      array(
1369        array(
1370          'name' => $tag_name,
1371          'url_name' => str2url($tag_name),
1372          )
1373        )
1374      );
1375
1376    $page['tag_id_from_tag_name_cache'][$tag_name] = pwg_db_insert_id();
1377  }
1378  else
1379  {
1380    $page['tag_id_from_tag_name_cache'][$tag_name] = $existing_tags[0];
1381  }
1382
1383  return $page['tag_id_from_tag_name_cache'][$tag_name];
1384}
1385
1386function set_tags_of($tags_of)
1387{
1388  if (count($tags_of) > 0)
1389  {
1390    $query = '
1391DELETE
1392  FROM '.IMAGE_TAG_TABLE.'
1393  WHERE image_id IN ('.implode(',', array_keys($tags_of)).')
1394;';
1395    pwg_query($query);
1396
1397    $inserts = array();
1398
1399    foreach ($tags_of as $image_id => $tag_ids)
1400    {
1401      foreach ($tag_ids as $tag_id)
1402      {
1403        array_push(
1404          $inserts,
1405          array(
1406            'image_id' => $image_id,
1407            'tag_id' => $tag_id,
1408            )
1409          );
1410      }
1411    }
1412
1413    mass_inserts(
1414      IMAGE_TAG_TABLE,
1415      array_keys($inserts[0]),
1416      $inserts
1417      );
1418  }
1419}
1420
1421/**
1422 * Associate a list of images to a list of categories.
1423 *
1424 * The function will not duplicate links
1425 *
1426 * @param array images
1427 * @param array categories
1428 * @return void
1429 */
1430function associate_images_to_categories($images, $categories)
1431{
1432  if (count($images) == 0
1433      or count($categories) == 0)
1434  {
1435    return false;
1436  }
1437
1438  $query = '
1439DELETE
1440  FROM '.IMAGE_CATEGORY_TABLE.'
1441  WHERE image_id IN ('.implode(',', $images).')
1442    AND category_id IN ('.implode(',', $categories).')
1443;';
1444  pwg_query($query);
1445
1446  $inserts = array();
1447  foreach ($categories as $category_id)
1448  {
1449    foreach ($images as $image_id)
1450    {
1451      array_push(
1452        $inserts,
1453        array(
1454          'image_id' => $image_id,
1455          'category_id' => $category_id,
1456          )
1457        );
1458    }
1459  }
1460
1461  mass_inserts(
1462    IMAGE_CATEGORY_TABLE,
1463    array_keys($inserts[0]),
1464    $inserts
1465    );
1466
1467  update_category($categories);
1468}
1469
1470/**
1471 * Associate images associated to a list of source categories to a list of
1472 * destination categories.
1473 *
1474 * @param array sources
1475 * @param array destinations
1476 * @return void
1477 */
1478function associate_categories_to_categories($sources, $destinations)
1479{
1480  if (count($sources) == 0)
1481  {
1482    return false;
1483  }
1484
1485  $query = '
1486SELECT image_id
1487  FROM '.IMAGE_CATEGORY_TABLE.'
1488  WHERE category_id IN ('.implode(',', $sources).')
1489;';
1490  $images = array_from_query($query, 'image_id');
1491
1492  associate_images_to_categories($images, $destinations);
1493}
1494
1495/**
1496 * Refer main Piwigo URLs (currently PHPWG_DOMAIN domain)
1497 *
1498 * @param void
1499 * @return array like $conf['links']
1500 */
1501function pwg_URL()
1502{
1503  $urls = array(
1504    'HOME'       => 'http://'.PHPWG_DOMAIN,
1505    'WIKI'       => 'http://'.PHPWG_DOMAIN.'/doc',
1506    'DEMO'       => 'http://'.PHPWG_DOMAIN.'/demo',
1507    'FORUM'      => 'http://'.PHPWG_DOMAIN.'/forum',
1508    'BUGS'       => 'http://'.PHPWG_DOMAIN.'/bugs',
1509    'EXTENSIONS' => 'http://'.PHPWG_DOMAIN.'/ext',
1510    );
1511  return $urls;
1512}
1513
1514/**
1515 * Invalidates cahed data (permissions and category counts) for all users.
1516 */
1517function invalidate_user_cache($full = true)
1518{
1519  if ($full)
1520  {
1521    $query = '
1522TRUNCATE TABLE '.USER_CACHE_CATEGORIES_TABLE.';';
1523    pwg_query($query);
1524    $query = '
1525TRUNCATE TABLE '.USER_CACHE_TABLE.';';
1526    pwg_query($query);
1527  }
1528  else
1529  {
1530    $query = '
1531UPDATE '.USER_CACHE_TABLE.'
1532  SET need_update = \'true\';';
1533    pwg_query($query);
1534  }
1535  trigger_action('invalidate_user_cache', $full);
1536}
1537
1538/**
1539 * adds the caracter set to a create table sql query.
1540 * all CREATE TABLE queries must call this function
1541 * @param string query - the sql query
1542 */
1543function create_table_add_character_set($query)
1544{
1545  defined('DB_CHARSET') or fatal_error('create_table_add_character_set DB_CHARSET undefined');
1546  if ('DB_CHARSET'!='')
1547  {
1548    if ( version_compare(mysql_get_server_info(), '4.1.0', '<') )
1549    {
1550      return $query;
1551    }
1552    $charset_collate = " DEFAULT CHARACTER SET ".DB_CHARSET;
1553    if (DB_COLLATE!='')
1554    {
1555      $charset_collate .= " COLLATE ".DB_COLLATE;
1556    }
1557    if ( is_array($query) )
1558    {
1559      foreach( $query as $id=>$q)
1560      {
1561        $q=trim($q);
1562        $q=trim($q, ';');
1563        if (preg_match('/^CREATE\s+TABLE/i',$q))
1564        {
1565          $q.=$charset_collate;
1566        }
1567        $q .= ';';
1568        $query[$id] = $q;
1569      }
1570    }
1571    else
1572    {
1573      $query=trim($query);
1574      $query=trim($query, ';');
1575      if (preg_match('/^CREATE\s+TABLE/i',$query))
1576      {
1577        $query.=$charset_collate;
1578      }
1579      $query .= ';';
1580    }
1581  }
1582  return $query;
1583}
1584
1585/**
1586 * Returns array use on template with html_options method
1587 * @param Min and Max access to use
1588 * @return array of user access level
1589 */
1590function get_user_access_level_html_options($MinLevelAccess = ACCESS_FREE, $MaxLevelAccess = ACCESS_CLOSED)
1591{
1592  $tpl_options = array();
1593  for ($level = $MinLevelAccess; $level <= $MaxLevelAccess; $level++)
1594  {
1595    $tpl_options[$level] = l10n(sprintf('ACCESS_%d', $level));
1596  }
1597  return $tpl_options;
1598}
1599
1600/**
1601 * returns a list of templates currently available in template-extension
1602 * Each .tpl file is extracted from template-extension.
1603 * @return array
1604 */
1605function get_extents($start='')
1606{
1607  if ($start == '') { $start = './template-extension'; }
1608  $dir = opendir($start);
1609  $extents = array();
1610
1611  while (($file = readdir($dir)) !== false)
1612  {
1613    if ( $file == '.' or $file == '..' or $file == '.svn') continue;
1614    $path = $start . '/' . $file;
1615    if (is_dir($path))
1616    {
1617      $extents = array_merge($extents, get_extents($path));
1618    }
1619    elseif ( !is_link($path) and file_exists($path)
1620            and get_extension($path) == 'tpl' )
1621    {
1622      $extents[] = substr($path, 21);
1623    }
1624  }
1625  return $extents;
1626}
1627
1628function create_tag($tag_name)
1629{
1630  // does the tag already exists?
1631  $query = '
1632SELECT id
1633  FROM '.TAGS_TABLE.'
1634  WHERE name = \''.$tag_name.'\'
1635;';
1636  $existing_tags = array_from_query($query, 'id');
1637
1638  if (count($existing_tags) == 0)
1639  {
1640    mass_inserts(
1641      TAGS_TABLE,
1642      array('name', 'url_name'),
1643      array(
1644        array(
1645          'name' => $tag_name,
1646          'url_name' => str2url($tag_name),
1647          )
1648        )
1649      );
1650
1651    $inserted_id = pwg_db_insert_id();
1652
1653    return array(
1654      'info' => sprintf(
1655        l10n('Tag "%s" was added'),
1656        stripslashes($tag_name)
1657        ),
1658      'id' => $inserted_id,
1659      );
1660  }
1661  else
1662  {
1663    return array(
1664      'error' => sprintf(
1665        l10n('Tag "%s" already exists'),
1666        stripslashes($tag_name)
1667        )
1668      );
1669  }
1670}
1671
1672/**
1673 * Is the category accessible to the (Admin) user ?
1674 *
1675 * Note : if the user is not authorized to see this category, category jump
1676 * will be replaced by admin cat_modify page
1677 *
1678 * @param int category id to verify
1679 * @return bool
1680 */
1681function cat_admin_access($category_id)
1682{
1683  global $user;
1684
1685  // $filter['visible_categories'] and $filter['visible_images']
1686  // are not used because it's not necessary (filter <> restriction)
1687  if (in_array($category_id, explode(',', $user['forbidden_categories'])))
1688  {
1689    return false;
1690  }
1691  return true;
1692}
1693
1694/**
1695 * Retrieve data from external URL
1696 *
1697 * @param string $src: URL
1698 * @param global $dest: can be a file ressource or string
1699 * @return bool
1700 */
1701function fetchRemote($src, &$dest, $user_agent='Piwigo', $step=0)
1702{
1703  // Try to retrieve data from local file?
1704  if (!url_is_remote($src))
1705  {
1706    $content = @file_get_contents($src);
1707    if ($content !== false)
1708    {
1709      is_resource($dest) ? @fwrite($dest, $content) : $dest = $content;
1710      return true;
1711    }
1712    else
1713    {
1714      return false;
1715    }
1716  }
1717
1718  // After 3 redirections, return false
1719  if ($step > 3) return false;
1720
1721  // Initialize $dest
1722  is_resource($dest) or $dest = '';
1723
1724  // Try curl to read remote file
1725  if (function_exists('curl_init'))
1726  {
1727    $ch = @curl_init();
1728    @curl_setopt($ch, CURLOPT_URL, $src);
1729    @curl_setopt($ch, CURLOPT_HEADER, 1);
1730    @curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
1731    @curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
1732    $content = @curl_exec($ch);
1733    $header_length = @curl_getinfo($ch, CURLINFO_HEADER_SIZE);
1734    $status = @curl_getinfo($ch, CURLINFO_HTTP_CODE);
1735    @curl_close($ch);
1736    if ($content !== false and $status >= 200 and $status < 400)
1737    {
1738      if (preg_match('/Location:\s+?(.+)/', substr($content, 0, $header_length), $m))
1739      {
1740        return fetchRemote($m[1], $dest, $user_agent, $step+1);
1741      }
1742      $content = substr($content, $header_length);
1743      is_resource($dest) ? @fwrite($dest, $content) : $dest = $content;
1744      return true;
1745    }
1746  }
1747
1748  // Try file_get_contents to read remote file
1749  if (ini_get('allow_url_fopen'))
1750  {
1751    $content = @file_get_contents($src);
1752    if ($content !== false)
1753    {
1754      is_resource($dest) ? @fwrite($dest, $content) : $dest = $content;
1755      return true;
1756    }
1757  }
1758
1759  // Try fsockopen to read remote file
1760  $src = parse_url($src);
1761  $host = $src['host'];
1762  $path = isset($src['path']) ? $src['path'] : '/';
1763  $path .= isset($src['query']) ? '?'.$src['query'] : '';
1764
1765  if (($s = @fsockopen($host,80,$errno,$errstr,5)) === false)
1766  {
1767    return false;
1768  }
1769
1770  fwrite($s,
1771    "GET ".$path." HTTP/1.0\r\n"
1772    ."Host: ".$host."\r\n"
1773    ."User-Agent: ".$user_agent."\r\n"
1774    ."Accept: */*\r\n"
1775    ."\r\n"
1776  );
1777
1778  $i = 0;
1779  $in_content = false;
1780  while (!feof($s))
1781  {
1782    $line = fgets($s);
1783
1784    if (rtrim($line,"\r\n") == '' && !$in_content)
1785    {
1786      $in_content = true;
1787      $i++;
1788      continue;
1789    }
1790    if ($i == 0)
1791    {
1792      if (!preg_match('/HTTP\/(\\d\\.\\d)\\s*(\\d+)\\s*(.*)/',rtrim($line,"\r\n"), $m))
1793      {
1794        fclose($s);
1795        return false;
1796      }
1797      $status = (integer) $m[2];
1798      if ($status < 200 || $status >= 400)
1799      {
1800        fclose($s);
1801        return false;
1802      }
1803    }
1804    if (!$in_content)
1805    {
1806      if (preg_match('/Location:\s+?(.+)$/',rtrim($line,"\r\n"),$m))
1807      {
1808        fclose($s);
1809        return fetchRemote(trim($m[1]),$dest,$user_agent,$step+1);
1810      }
1811      $i++;
1812      continue;
1813    }
1814    is_resource($dest) ? @fwrite($dest, $line) : $dest .= $line;
1815    $i++;
1816  }
1817  fclose($s);
1818  return true;
1819}
1820
1821
1822/**
1823 * returns the groupname corresponding to the given group identifier if
1824 * exists
1825 *
1826 * @param int group_id
1827 * @return mixed
1828 */
1829function get_groupname($group_id)
1830{
1831  $query = '
1832SELECT name
1833  FROM '.GROUPS_TABLE.'
1834  WHERE id = '.intval($group_id).'
1835;';
1836  $result = pwg_query($query);
1837  if (pwg_db_num_rows($result) > 0)
1838  {
1839    list($groupname) = pwg_db_fetch_row($result);
1840  }
1841  else
1842  {
1843    return false;
1844  }
1845
1846  return $groupname;
1847}
1848
1849/**
1850 * returns the username corresponding to the given user identifier if exists
1851 *
1852 * @param int user_id
1853 * @return mixed
1854 */
1855function get_username($user_id)
1856{
1857  global $conf;
1858
1859  $query = '
1860SELECT '.$conf['user_fields']['username'].'
1861  FROM '.USERS_TABLE.'
1862  WHERE '.$conf['user_fields']['id'].' = '.intval($user_id).'
1863;';
1864  $result = pwg_query($query);
1865  if (pwg_db_num_rows($result) > 0)
1866  {
1867    list($username) = pwg_db_fetch_row($result);
1868  }
1869  else
1870  {
1871    return false;
1872  }
1873
1874  return stripslashes($username);
1875}
1876
1877function get_newsletter_subscribe_base_url($language) {
1878  $subscribe_domain = 'piwigo.org';
1879
1880  $domain_of = array(
1881    'fr_FR' => 'fr.piwigo.org',
1882    'it_IT' => 'it.piwigo.org',
1883    'de_DE' => 'de.piwigo.org',
1884    'es_ES' => 'es.piwigo.org',
1885    );
1886
1887  if (isset($domain_of[$language])) {
1888    $subscribe_domain = $domain_of[$language];
1889  }
1890
1891  return 'http://'.$subscribe_domain.'/announcement/subscribe/';
1892}
1893?>
Note: See TracBrowser for help on using the repository browser.