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

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

Bug 1328 : improve check function

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