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

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

Bug 1328 add function to check token

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