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

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

Feature 1255 : improve sql
Replace in queries LIMIT N,M by LIMIT N OFFSET M

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