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

Last change on this file since 6873 was 6873, checked in by rvelices, 14 years ago

feature 1845 : be able to delete photos added through ftp synchronization

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