source: trunk/include/functions_user.inc.php @ 10860

Last change on this file since 10860 was 10860, checked in by flop25, 13 years ago

feature:1835
better managment if $confinsensitive_case_logon is true, for identification

  • Property svn:eol-style set to LF
File size: 35.7 KB
Line 
1<?php
2// +-----------------------------------------------------------------------+
3// | Piwigo - a PHP based photo gallery                                    |
4// +-----------------------------------------------------------------------+
5// | Copyright(C) 2008-2011 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
24// validate_mail_address:
25//   o verifies whether the given mail address has the
26//     right format. ie someone@domain.com "someone" can contain ".", "-" or
27//     even "_". Exactly as "domain". The extension doesn't have to be
28//     "com". The mail address can also be empty.
29//   o check if address could be empty
30//   o check if address is not used by a other user
31// If the mail address doesn't correspond, an error message is returned.
32//
33function validate_mail_address($user_id, $mail_address)
34{
35  global $conf;
36
37  if (empty($mail_address) and
38      !($conf['obligatory_user_mail_address'] and
39      in_array(script_basename(), array('register', 'profile'))))
40  {
41    return '';
42  }
43
44  $atom   = '[-a-z0-9!#$%&\'*+\\/=?^_`{|}~]';   // before  arobase
45  $domain = '([a-z0-9]([-a-z0-9]*[a-z0-9]+)?)'; // domain name
46  $regex = '/^' . $atom . '+' . '(\.' . $atom . '+)*' . '@' . '(' . $domain . '{1,63}\.)+' . $domain . '{2,63}$/i';
47
48  if ( !preg_match( $regex, $mail_address ) )
49  {
50    return l10n('mail address must be like xxx@yyy.eee (example : jack@altern.org)');
51  }
52
53  if (defined("PHPWG_INSTALLED") and !empty($mail_address))
54  {
55    $query = '
56select count(*)
57from '.USERS_TABLE.'
58where upper('.$conf['user_fields']['email'].') = upper(\''.$mail_address.'\')
59'.(is_numeric($user_id) ? 'and '.$conf['user_fields']['id'].' != \''.$user_id.'\'' : '').'
60;';
61    list($count) = pwg_db_fetch_row(pwg_query($query));
62    if ($count != 0)
63    {
64      return l10n('this email address is already in use');
65    }
66  }
67}
68
69// validate_login_case:
70//   o check if login is not used by a other user
71// If the login doesn't correspond, an error message is returned.
72//
73function validate_login_case($login)
74{
75  global $conf;
76 
77  if (defined("PHPWG_INSTALLED"))
78  {
79    $query = "
80SELECT ".$conf['user_fields']['username']."
81FROM ".USERS_TABLE."
82WHERE LOWER(".stripslashes($conf['user_fields']['username']).") = '".strtolower($login)."'
83;";
84
85    $count = pwg_db_num_rows(pwg_query($query));
86
87    if ($count > 0)
88    {
89      return l10n('this login is already used');
90    }
91  }
92}
93/**
94 * For test on username case sensitivity
95 *
96 * @param : $username typed in by user for identification
97 *
98 * @return : $username found in database
99 *
100 */
101function search_case_username($username)
102{
103  global $conf;
104
105  $username_lo = strtolower($username);
106
107  $SCU_users = array();
108 
109  $q = pwg_query("
110    SELECT ".$conf['user_fields']['username']." AS username
111    FROM `".USERS_TABLE."`;
112  ");
113  while ($r = pwg_db_fetch_assoc($q))
114   $SCU_users[$r['username']] = strtolower($r['username']);
115   // $SCU_users is now an associative table where the key is the account as
116   // registered in the DB, and the value is this same account, in lower case
117   
118  $users_found = array_keys($SCU_users, $username_lo);
119  // $users_found is now a table of which the values are all the accounts
120  // which can be written in lowercase the same way as $username
121  if (count($users_found) != 1) // If ambiguous, don't allow lowercase writing
122   return $username; // but normal writing will work
123  else
124   return $users_found[0];
125}
126function register_user($login, $password, $mail_address,
127  $with_notification = true, $errors = array())
128{
129  global $conf;
130
131  if ($login == '')
132  {
133    array_push($errors, l10n('Please, enter a login'));
134  }
135  if (preg_match('/^.* $/', $login))
136  {
137    array_push($errors, l10n('login mustn\'t end with a space character'));
138  }
139  if (preg_match('/^ .*$/', $login))
140  {
141    array_push($errors, l10n('login mustn\'t start with a space character'));
142  }
143  if (get_userid($login))
144  {
145    array_push($errors, l10n('this login is already used'));
146  }
147  if ($login != strip_tags($login))
148  {
149    array_push($errors, l10n('html tags are not allowed in login'));
150  }
151  $mail_error = validate_mail_address(null, $mail_address);
152  if ('' != $mail_error)
153  {
154    array_push($errors, $mail_error);
155  }
156
157  if ($conf['insensitive_case_logon'] == true)
158  {
159    $login_error = validate_login_case($login);
160    if ($login_error != '')
161    {
162      array_push($errors, $login_error);
163    }
164  }
165
166  $errors = trigger_event('register_user_check',
167              $errors,
168              array(
169                'username'=>$login,
170                'password'=>$password,
171                'email'=>$mail_address,
172              )
173            );
174
175  // if no error until here, registration of the user
176  if (count($errors) == 0)
177  {
178    // what will be the inserted id ?
179    $query = '
180SELECT MAX('.$conf['user_fields']['id'].') + 1
181  FROM '.USERS_TABLE.'
182;';
183    list($next_id) = pwg_db_fetch_row(pwg_query($query));
184
185    $insert =
186      array(
187        $conf['user_fields']['id'] => $next_id,
188        $conf['user_fields']['username'] => pwg_db_real_escape_string($login),
189        $conf['user_fields']['password'] => $conf['pass_convert']($password),
190        $conf['user_fields']['email'] => $mail_address
191        );
192
193    mass_inserts(USERS_TABLE, array_keys($insert), array($insert));
194
195    // Assign by default groups
196    {
197      $query = '
198SELECT id
199  FROM '.GROUPS_TABLE.'
200  WHERE is_default = \''.boolean_to_string(true).'\'
201  ORDER BY id ASC
202;';
203      $result = pwg_query($query);
204
205      $inserts = array();
206      while ($row = pwg_db_fetch_assoc($result))
207      {
208        array_push
209        (
210          $inserts,
211          array
212          (
213            'user_id' => $next_id,
214            'group_id' => $row['id']
215          )
216        );
217      }
218    }
219
220    if (count($inserts) != 0)
221    {
222      mass_inserts(USER_GROUP_TABLE, array('user_id', 'group_id'), $inserts);
223    }
224
225    $override = null;
226    if ($with_notification and $conf['browser_language'])
227    {
228      if ( !get_browser_language($override['language']) )
229        $override=null;
230    }
231    create_user_infos($next_id, $override);
232
233    if ($with_notification and $conf['email_admin_on_new_user'])
234    {
235      include_once(PHPWG_ROOT_PATH.'include/functions_mail.inc.php');
236      $admin_url = get_absolute_root_url()
237                   .'admin.php?page=user_list&username='.$login;
238
239      $keyargs_content = array
240      (
241        get_l10n_args('User: %s', stripslashes($login)),
242        get_l10n_args('Email: %s', $_POST['mail_address']),
243        get_l10n_args('', ''),
244        get_l10n_args('Admin: %s', $admin_url)
245      );
246
247      pwg_mail_notification_admins
248      (
249        get_l10n_args('Registration of %s', stripslashes($login)),
250        $keyargs_content
251      );
252    }
253
254    trigger_action('register_user',
255      array(
256        'id'=>$next_id,
257        'username'=>$login,
258        'email'=>$mail_address,
259       )
260      );
261  }
262
263  return $errors;
264}
265
266function build_user( $user_id, $use_cache )
267{
268  global $conf;
269
270  $user['id'] = $user_id;
271  $user = array_merge( $user, getuserdata($user_id, $use_cache) );
272
273  if ($user['id'] == $conf['guest_id'] and $user['status'] <> 'guest')
274  {
275    $user['status'] = 'guest';
276    $user['internal_status']['guest_must_be_guest'] = true;
277  }
278
279  // Check user theme
280  if (!isset($user['theme_name']))
281  {
282    $user['theme'] = get_default_theme();
283  }
284
285  return $user;
286}
287
288/**
289 * find informations related to the user identifier
290 *
291 * @param int user identifier
292 * @param boolean use_cache
293 * @param array
294 */
295function getuserdata($user_id, $use_cache)
296{
297  global $conf;
298
299  $userdata = array();
300
301  // retrieve basic user data
302  $query = '
303SELECT ';
304  $is_first = true;
305  foreach ($conf['user_fields'] as $pwgfield => $dbfield)
306  {
307    if ($is_first)
308    {
309      $is_first = false;
310    }
311    else
312    {
313      $query.= '
314     , ';
315    }
316    $query.= $dbfield.' AS '.$pwgfield;
317  }
318  $query.= '
319  FROM '.USERS_TABLE.'
320  WHERE '.$conf['user_fields']['id'].' = \''.$user_id.'\'';
321
322  $row = pwg_db_fetch_assoc(pwg_query($query));
323
324  // retrieve user info
325  $query = '
326SELECT
327    ui.*,
328    uc.*,
329    t.name AS theme_name
330  FROM '.USER_INFOS_TABLE.' AS ui
331    LEFT JOIN '.USER_CACHE_TABLE.' AS uc ON ui.user_id = uc.user_id
332    LEFT JOIN '.THEMES_TABLE.' AS t ON t.id = ui.theme
333  WHERE ui.user_id = '.$user_id.'
334;';
335
336  $result = pwg_query($query);
337  $user_infos_row = pwg_db_fetch_assoc($result);
338
339  // retrieve additional user data ?
340  if ($conf['external_authentification'])
341  {
342    $query = '
343SELECT
344    COUNT(1) AS counter,
345  FROM '.USER_INFOS_TABLE.' AS ui
346    LEFT JOIN '.USER_CACHE_TABLE.' AS uc ON ui.user_id = uc.user_id
347    LEFT JOIN '.THEMES_TABLE.' AS t ON t.id = ui.theme
348  WHERE ui.user_id = '.$user_id.'
349  GROUP BY ui.user_id
350;';
351    if (pwg_db_fetch_row(pwg_query($query))!=1)
352    {
353      create_user_infos($user_id);
354   
355      $result = pwg_query($user_info_query);
356      $user_infos_row = pwg_db_fetch_assoc($result);     
357    }
358  }
359
360  // then merge basic + additional user data
361  $row = array_merge($row, $user_infos_row);
362
363  foreach ($row as $key => $value)
364  {
365    if (!is_numeric($key))
366    {
367      // If the field is true or false, the variable is transformed into a
368      // boolean value.
369      if ($value == 'true' or $value == 'false')
370      {
371        $userdata[$key] = get_boolean($value);
372      }
373      else
374      {
375        $userdata[$key] = $value;
376      }
377    }
378  }
379
380  if ($use_cache)
381  {
382    if (!isset($userdata['need_update'])
383        or !is_bool($userdata['need_update'])
384        or $userdata['need_update'] == true)
385    {
386      $userdata['cache_update_time'] = time();
387
388      // Set need update are done
389      $userdata['need_update'] = false;
390
391      $userdata['forbidden_categories'] =
392        calculate_permissions($userdata['id'], $userdata['status']);
393
394      /* now we build the list of forbidden images (this list does not contain
395      images that are not in at least an authorized category)*/
396      $query = '
397SELECT DISTINCT(id)
398  FROM '.IMAGES_TABLE.' INNER JOIN '.IMAGE_CATEGORY_TABLE.' ON id=image_id
399  WHERE category_id NOT IN ('.$userdata['forbidden_categories'].')
400    AND level>'.$userdata['level'];
401      $forbidden_ids = array_from_query($query, 'id');
402
403      if ( empty($forbidden_ids) )
404      {
405        array_push( $forbidden_ids, 0 );
406      }
407      $userdata['image_access_type'] = 'NOT IN'; //TODO maybe later
408      $userdata['image_access_list'] = implode(',',$forbidden_ids);
409
410
411      $query = '
412SELECT COUNT(DISTINCT(image_id)) as total
413  FROM '.IMAGE_CATEGORY_TABLE.'
414  WHERE category_id NOT IN ('.$userdata['forbidden_categories'].')
415    AND image_id '.$userdata['image_access_type'].' ('.$userdata['image_access_list'].')';
416      list($userdata['nb_total_images']) = pwg_db_fetch_row(pwg_query($query));
417
418
419      // now we update user cache categories
420      $user_cache_cats = get_computed_categories($userdata, null);
421      if ( !is_admin($userdata['status']) )
422      { // for non admins we forbid categories with no image (feature 1053)
423        $forbidden_ids = array();
424        foreach ($user_cache_cats as $cat)
425        {
426          if ($cat['count_images']==0)
427          {
428            array_push($forbidden_ids, $cat['cat_id']);
429            unset( $user_cache_cats[$cat['cat_id']] );
430          }
431        }
432        if ( !empty($forbidden_ids) )
433        {
434          if ( empty($userdata['forbidden_categories']) )
435          {
436            $userdata['forbidden_categories'] = implode(',', $forbidden_ids);
437          }
438          else
439          {
440            $userdata['forbidden_categories'] .= ','.implode(',', $forbidden_ids);
441          }
442        }
443      }
444
445      // delete user cache
446      $query = '
447DELETE FROM '.USER_CACHE_CATEGORIES_TABLE.'
448  WHERE user_id = '.$userdata['id'];
449      pwg_query($query);
450
451      mass_inserts
452      (
453        USER_CACHE_CATEGORIES_TABLE,
454        array
455        (
456          'user_id', 'cat_id',
457          'date_last', 'max_date_last', 'nb_images', 'count_images', 'count_categories'
458        ),
459        $user_cache_cats
460      );
461
462
463      // update user cache
464      $query = '
465DELETE FROM '.USER_CACHE_TABLE.'
466  WHERE user_id = '.$userdata['id'];
467      pwg_query($query);
468
469      $query = '
470INSERT INTO '.USER_CACHE_TABLE.'
471  (user_id, need_update, cache_update_time, forbidden_categories, nb_total_images,
472    image_access_type, image_access_list)
473  VALUES
474  ('.$userdata['id'].',\''.boolean_to_string($userdata['need_update']).'\','
475  .$userdata['cache_update_time'].',\''
476  .$userdata['forbidden_categories'].'\','.$userdata['nb_total_images'].',\''
477  .$userdata['image_access_type'].'\',\''.$userdata['image_access_list'].'\')';
478      pwg_query($query);
479    }
480  }
481
482  return $userdata;
483}
484
485/*
486 * deletes favorites of the current user if he's not allowed to see them
487 *
488 * @return void
489 */
490function check_user_favorites()
491{
492  global $user;
493
494  if ($user['forbidden_categories'] == '')
495  {
496    return;
497  }
498
499  // $filter['visible_categories'] and $filter['visible_images']
500  // must be not used because filter <> restriction
501  // retrieving images allowed : belonging to at least one authorized
502  // category
503  $query = '
504SELECT DISTINCT f.image_id
505  FROM '.FAVORITES_TABLE.' AS f INNER JOIN '.IMAGE_CATEGORY_TABLE.' AS ic
506    ON f.image_id = ic.image_id
507  WHERE f.user_id = '.$user['id'].'
508'.get_sql_condition_FandF
509  (
510    array
511      (
512        'forbidden_categories' => 'ic.category_id',
513      ),
514    'AND'
515  ).'
516;';
517  $result = pwg_query($query);
518  $authorizeds = array();
519  while ($row = pwg_db_fetch_assoc($result))
520  {
521    array_push($authorizeds, $row['image_id']);
522  }
523
524  $query = '
525SELECT image_id
526  FROM '.FAVORITES_TABLE.'
527  WHERE user_id = '.$user['id'].'
528;';
529  $result = pwg_query($query);
530  $favorites = array();
531  while ($row = pwg_db_fetch_assoc($result))
532  {
533    array_push($favorites, $row['image_id']);
534  }
535
536  $to_deletes = array_diff($favorites, $authorizeds);
537
538  if (count($to_deletes) > 0)
539  {
540    $query = '
541DELETE FROM '.FAVORITES_TABLE.'
542  WHERE image_id IN ('.implode(',', $to_deletes).')
543    AND user_id = '.$user['id'].'
544;';
545    pwg_query($query);
546  }
547}
548
549/**
550 * calculates the list of forbidden categories for a given user
551 *
552 * Calculation is based on private categories minus categories authorized to
553 * the groups the user belongs to minus the categories directly authorized
554 * to the user. The list contains at least -1 to be compliant with queries
555 * such as "WHERE category_id NOT IN ($forbidden_categories)"
556 *
557 * @param int user_id
558 * @param string user_status
559 * @return string forbidden_categories
560 */
561function calculate_permissions($user_id, $user_status)
562{
563  $private_array = array();
564  $authorized_array = array();
565
566  $query = '
567SELECT id
568  FROM '.CATEGORIES_TABLE.'
569  WHERE status = \'private\'
570;';
571  $result = pwg_query($query);
572  while ($row = pwg_db_fetch_assoc($result))
573  {
574    array_push($private_array, $row['id']);
575  }
576
577  // retrieve category ids directly authorized to the user
578  $query = '
579SELECT cat_id
580  FROM '.USER_ACCESS_TABLE.'
581  WHERE user_id = '.$user_id.'
582;';
583  $authorized_array = array_from_query($query, 'cat_id');
584
585  // retrieve category ids authorized to the groups the user belongs to
586  $query = '
587SELECT cat_id
588  FROM '.USER_GROUP_TABLE.' AS ug INNER JOIN '.GROUP_ACCESS_TABLE.' AS ga
589    ON ug.group_id = ga.group_id
590  WHERE ug.user_id = '.$user_id.'
591;';
592  $authorized_array =
593    array_merge(
594      $authorized_array,
595      array_from_query($query, 'cat_id')
596      );
597
598  // uniquify ids : some private categories might be authorized for the
599  // groups and for the user
600  $authorized_array = array_unique($authorized_array);
601
602  // only unauthorized private categories are forbidden
603  $forbidden_array = array_diff($private_array, $authorized_array);
604
605  // if user is not an admin, locked categories are forbidden
606  if (!is_admin($user_status))
607  {
608    $query = '
609SELECT id
610  FROM '.CATEGORIES_TABLE.'
611  WHERE visible = \'false\'
612;';
613    $result = pwg_query($query);
614    while ($row = pwg_db_fetch_assoc($result))
615    {
616      array_push($forbidden_array, $row['id']);
617    }
618    $forbidden_array = array_unique($forbidden_array);
619  }
620
621  if ( empty($forbidden_array) )
622  {// at least, the list contains 0 value. This category does not exists so
623   // where clauses such as "WHERE category_id NOT IN(0)" will always be
624   // true.
625    array_push($forbidden_array, 0);
626  }
627
628  return implode(',', $forbidden_array);
629}
630
631/**
632 * compute data of categories branches (one branch only)
633 */
634function compute_branch_cat_data(&$cats, &$list_cat_id, &$level, &$ref_level)
635{
636  $date = '';
637  $count_images = 0;
638  $count_categories = 0;
639  do
640  {
641    $cat_id = array_pop($list_cat_id);
642    if (!is_null($cat_id))
643    {
644      // Count images and categories
645      $cats[$cat_id]['count_images'] += $count_images;
646      $cats[$cat_id]['count_categories'] += $count_categories;
647      $count_images = $cats[$cat_id]['count_images'];
648      $count_categories = $cats[$cat_id]['count_categories'] + 1;
649
650      if ((empty($cats[$cat_id]['max_date_last'])) or ($cats[$cat_id]['max_date_last'] < $date))
651      {
652        $cats[$cat_id]['max_date_last'] = $date;
653      }
654      else
655      {
656        $date = $cats[$cat_id]['max_date_last'];
657      }
658      $ref_level = substr_count($cats[$cat_id]['global_rank'], '.') + 1;
659    }
660    else
661    {
662      $ref_level = 0;
663    }
664  } while ($level <= $ref_level);
665
666  // Last cat updating must be added to list for next branch
667  if ($ref_level <> 0)
668  {
669    array_push($list_cat_id, $cat_id);
670  }
671}
672
673/**
674 * compute data of categories branches
675 */
676function compute_categories_data(&$cats)
677{
678  $ref_level = 0;
679  $level = 0;
680  $list_cat_id = array();
681
682  foreach ($cats as $id => $category)
683  {
684    // Compute
685    $level = substr_count($category['global_rank'], '.') + 1;
686    if ($level > $ref_level)
687    {
688      array_push($list_cat_id, $id);
689    }
690    else
691    {
692      compute_branch_cat_data($cats, $list_cat_id, $level, $ref_level);
693      array_push($list_cat_id, $id);
694    }
695    $ref_level = $level;
696  }
697
698  $level = 1;
699  compute_branch_cat_data($cats, $list_cat_id, $level, $ref_level);
700}
701
702/**
703 * get computed array of categories
704 *
705 * @param array userdata
706 * @param int filter_days number of recent days to filter on or null
707 * @return array
708 */
709function get_computed_categories($userdata, $filter_days=null)
710{
711  $query = 'SELECT c.id AS cat_id, global_rank';
712  // Count by date_available to avoid count null
713  $query .= ',
714  MAX(date_available) AS date_last, COUNT(date_available) AS nb_images
715FROM '.CATEGORIES_TABLE.' as c
716  LEFT JOIN '.IMAGE_CATEGORY_TABLE.' AS ic ON ic.category_id = c.id
717  LEFT JOIN '.IMAGES_TABLE.' AS i
718    ON ic.image_id = i.id
719      AND i.level<='.$userdata['level'];
720
721  if ( isset($filter_days) )
722  {
723    $query .= ' AND i.date_available > '.pwg_db_get_recent_period_expression($filter_days);
724  }
725
726  if ( !empty($userdata['forbidden_categories']) )
727  {
728    $query.= '
729  WHERE c.id NOT IN ('.$userdata['forbidden_categories'].')';
730  }
731
732  $query.= '
733  GROUP BY c.id, c.global_rank';
734
735  $result = pwg_query($query);
736
737  $cats = array();
738  while ($row = pwg_db_fetch_assoc($result))
739  {
740    $row['user_id'] = $userdata['id'];
741    $row['count_categories'] = 0;
742    $row['count_images'] = (int)$row['nb_images'];
743    $row['max_date_last'] = $row['date_last'];
744
745    $cats += array($row['cat_id'] => $row);
746  }
747  uasort($cats, 'global_rank_compare');
748
749  compute_categories_data($cats);
750
751  if ( isset($filter_days) )
752  {
753    $cat_tmp = $cats;
754    $cats = array();
755
756    foreach ($cat_tmp as $category)
757    {
758      if (!empty($category['max_date_last']))
759      {
760        // Re-init counters
761        $category['count_categories'] = 0;
762        $category['count_images'] = (int)$category['nb_images'];
763        // Keep category
764        $cats[$category['cat_id']] = $category;
765      }
766    }
767    // Compute a second time
768    compute_categories_data($cats);
769  }
770  return $cats;
771}
772
773/**
774 * returns user identifier thanks to his name, false if not found
775 *
776 * @param string username
777 * @param int user identifier
778 */
779function get_userid($username)
780{
781  global $conf;
782
783  $username = pwg_db_real_escape_string($username);
784
785  $query = '
786SELECT '.$conf['user_fields']['id'].'
787  FROM '.USERS_TABLE.'
788  WHERE '.$conf['user_fields']['username'].' = \''.$username.'\'
789;';
790  $result = pwg_query($query);
791
792  if (pwg_db_num_rows($result) == 0)
793  {
794    return false;
795  }
796  else
797  {
798    list($user_id) = pwg_db_fetch_row($result);
799    return $user_id;
800  }
801}
802
803/**
804 * search an available feed_id
805 *
806 * @return string feed identifier
807 */
808function find_available_feed_id()
809{
810  while (true)
811  {
812    $key = generate_key(50);
813    $query = '
814SELECT COUNT(*)
815  FROM '.USER_FEED_TABLE.'
816  WHERE id = \''.$key.'\'
817;';
818    list($count) = pwg_db_fetch_row(pwg_query($query));
819    if (0 == $count)
820    {
821      return $key;
822    }
823  }
824}
825
826/*
827 * Returns a array with default user value
828 *
829 * @param convert_str allows to convert string value if necessary
830 */
831function get_default_user_info($convert_str = true)
832{
833  global $cache, $conf;
834
835  if (!isset($cache['default_user']))
836  {
837    $query = 'SELECT * FROM '.USER_INFOS_TABLE.
838            ' WHERE user_id = '.$conf['default_user_id'].';';
839
840    $result = pwg_query($query);
841    $cache['default_user'] = pwg_db_fetch_assoc($result);
842
843    if ($cache['default_user'] !== false)
844    {
845      unset($cache['default_user']['user_id']);
846      unset($cache['default_user']['status']);
847      unset($cache['default_user']['registration_date']);
848    }
849  }
850
851  if (is_array($cache['default_user']) and $convert_str)
852  {
853    $default_user = array();
854    foreach ($cache['default_user'] as $name => $value)
855    {
856      // If the field is true or false, the variable is transformed into a
857      // boolean value.
858      if ($value == 'true' or $value == 'false')
859      {
860        $default_user[$name] = get_boolean($value);
861      }
862      else
863      {
864        $default_user[$name] = $value;
865      }
866    }
867    return $default_user;
868  }
869  else
870  {
871    return $cache['default_user'];
872  }
873}
874
875/*
876 * Returns a default user value
877 *
878 * @param value_name: name of value
879 * @param sos_value: value used if don't exist value
880 */
881function get_default_user_value($value_name, $sos_value)
882{
883  $default_user = get_default_user_info(true);
884  if ($default_user === false or empty($default_user[$value_name]))
885  {
886    return $sos_value;
887  }
888  else
889  {
890   return $default_user[$value_name];
891  }
892}
893
894/*
895 * Returns the default template value
896 *
897 */
898function get_default_theme()
899{
900  $theme = get_default_user_value('theme', PHPWG_DEFAULT_TEMPLATE);
901  if (check_theme_installed($theme))
902  {
903    return $theme;
904  }
905 
906  // let's find the first available theme
907  $active_themes = get_pwg_themes();
908  foreach (array_keys(get_pwg_themes()) as $theme_id)
909  {
910    if (check_theme_installed($theme_id))
911    {
912      return $theme_id;
913    }
914  }
915}
916
917/*
918 * Returns the default language value
919 *
920 */
921function get_default_language()
922{
923  return get_default_user_value('language', PHPWG_DEFAULT_LANGUAGE);
924}
925
926/**
927  * Returns true if the browser language value is set into param $lang
928  *
929  */
930function get_browser_language(&$lang)
931{
932  $browser_language = substr(@$_SERVER["HTTP_ACCEPT_LANGUAGE"], 0, 2);
933  foreach (get_languages() as $language_code => $language_name)
934  {
935    if (substr($language_code, 0, 2) == $browser_language)
936    {
937      $lang = $language_code;
938      return true;
939    }
940  }
941  return false;
942}
943
944/**
945 * add user informations based on default values
946 *
947 * @param int user_id / array of user_if
948 * @param array of values used to override default user values
949 */
950function create_user_infos($arg_id, $override_values = null)
951{
952  global $conf;
953
954  if (is_array($arg_id))
955  {
956    $user_ids = $arg_id;
957  }
958  else
959  {
960    $user_ids = array();
961    if (is_numeric($arg_id))
962    {
963      $user_ids[] = $arg_id;
964    }
965  }
966
967  if (!empty($user_ids))
968  {
969    $inserts = array();
970    list($dbnow) = pwg_db_fetch_row(pwg_query('SELECT NOW();'));
971
972    $default_user = get_default_user_info(false);
973    if ($default_user === false)
974    {
975      // Default on structure are used
976      $default_user = array();
977    }
978
979    if (!is_null($override_values))
980    {
981      $default_user = array_merge($default_user, $override_values);
982    }
983
984    foreach ($user_ids as $user_id)
985    {
986      $level= isset($default_user['level']) ? $default_user['level'] : 0;
987      if ($user_id == $conf['webmaster_id'])
988      {
989        $status = 'webmaster';
990        $level = max( $conf['available_permission_levels'] );
991      }
992      else if (($user_id == $conf['guest_id']) or
993               ($user_id == $conf['default_user_id']))
994      {
995        $status = 'guest';
996      }
997      else
998      {
999        $status = 'normal';
1000      }
1001
1002      $insert = array_merge(
1003        $default_user,
1004        array(
1005          'user_id' => $user_id,
1006          'status' => $status,
1007          'registration_date' => $dbnow,
1008          'level' => $level
1009          ));
1010
1011      array_push($inserts, $insert);
1012    }
1013
1014    mass_inserts(USER_INFOS_TABLE, array_keys($inserts[0]), $inserts);
1015  }
1016}
1017
1018/**
1019 * returns the auto login key or false on error
1020 * @param int user_id
1021 * @param time_t time
1022 * @param string [out] username
1023*/
1024function calculate_auto_login_key($user_id, $time, &$username)
1025{
1026  global $conf;
1027  $query = '
1028SELECT '.$conf['user_fields']['username'].' AS username
1029  , '.$conf['user_fields']['password'].' AS password
1030FROM '.USERS_TABLE.'
1031WHERE '.$conf['user_fields']['id'].' = '.$user_id;
1032  $result = pwg_query($query);
1033  if (pwg_db_num_rows($result) > 0)
1034  {
1035    $row = pwg_db_fetch_assoc($result);
1036    $username = stripslashes($row['username']);
1037    $data = $time.stripslashes($row['username']).$row['password'];
1038    $key = base64_encode(
1039      pack('H*', sha1($data))
1040      .hash_hmac('md5', $data, $conf['secret_key'],true)
1041      );
1042    return $key;
1043  }
1044  return false;
1045}
1046
1047/*
1048 * Performs all required actions for user login
1049 * @param int user_id
1050 * @param bool remember_me
1051 * @return void
1052*/
1053function log_user($user_id, $remember_me)
1054{
1055  global $conf, $user;
1056
1057  if ($remember_me and $conf['authorize_remembering'])
1058  {
1059    $now = time();
1060    $key = calculate_auto_login_key($user_id, $now, $username);
1061    if ($key!==false)
1062    {
1063      $cookie = $user_id.'-'.$now.'-'.$key;
1064      if (version_compare(PHP_VERSION, '5.2', '>=') )
1065      {
1066        setcookie($conf['remember_me_name'],
1067            $cookie,
1068            time()+$conf['remember_me_length'],
1069            cookie_path(),ini_get('session.cookie_domain'),ini_get('session.cookie_secure'),
1070            ini_get('session.cookie_httponly')
1071          );
1072      }
1073      else
1074      {
1075        setcookie($conf['remember_me_name'],
1076            $cookie,
1077            time()+$conf['remember_me_length'],
1078            cookie_path(),ini_get('session.cookie_domain'),ini_get('session.cookie_secure')
1079          );
1080      }
1081    }
1082  }
1083  else
1084  { // make sure we clean any remember me ...
1085    setcookie($conf['remember_me_name'], '', 0, cookie_path(),ini_get('session.cookie_domain'));
1086  }
1087  if ( session_id()!="" )
1088  { // we regenerate the session for security reasons
1089    // see http://www.acros.si/papers/session_fixation.pdf
1090    session_regenerate_id(true);
1091  }
1092  else
1093  {
1094    session_start();
1095  }
1096  $_SESSION['pwg_uid'] = (int)$user_id;
1097
1098  $user['id'] = $_SESSION['pwg_uid'];
1099}
1100
1101/*
1102 * Performs auto-connexion when cookie remember_me exists
1103 * @return true/false
1104*/
1105function auto_login() {
1106  global $conf;
1107
1108  if ( isset( $_COOKIE[$conf['remember_me_name']] ) )
1109  {
1110    $cookie = explode('-', stripslashes($_COOKIE[$conf['remember_me_name']]));
1111    if ( count($cookie)===3
1112        and is_numeric(@$cookie[0]) /*user id*/
1113        and is_numeric(@$cookie[1]) /*time*/
1114        and time()-$conf['remember_me_length']<=@$cookie[1]
1115        and time()>=@$cookie[1] /*cookie generated in the past*/ )
1116    {
1117      $key = calculate_auto_login_key( $cookie[0], $cookie[1], $username );
1118      if ($key!==false and $key===$cookie[2])
1119      {
1120        log_user($cookie[0], true);
1121        trigger_action('login_success', stripslashes($username));
1122        return true;
1123      }
1124    }
1125    setcookie($conf['remember_me_name'], '', 0, cookie_path(),ini_get('session.cookie_domain'));
1126  }
1127  return false;
1128}
1129
1130/**
1131 * Tries to login a user given username and password (must be MySql escaped)
1132 * return true on success
1133 */
1134function try_log_user($username, $password, $remember_me)
1135{
1136  global $conf;
1137  // retrieving the encrypted password of the login submitted
1138  $query = '
1139SELECT '.$conf['user_fields']['id'].' AS id,
1140       '.$conf['user_fields']['password'].' AS password
1141  FROM '.USERS_TABLE.'
1142  WHERE '.$conf['user_fields']['username'].' = \''.pwg_db_real_escape_string($username).'\'
1143;';
1144  $row = pwg_db_fetch_assoc(pwg_query($query));
1145  if ($row['password'] == $conf['pass_convert']($password))
1146  {
1147    log_user($row['id'], $remember_me);
1148    trigger_action('login_success', stripslashes($username));
1149    return true;
1150  }
1151  trigger_action('login_failure', stripslashes($username));
1152  return false;
1153}
1154
1155/** Performs all the cleanup on user logout */
1156function logout_user()
1157{
1158  global $conf;
1159  $_SESSION = array();
1160  session_unset();
1161  session_destroy();
1162  setcookie(session_name(),'',0,
1163      ini_get('session.cookie_path'),
1164      ini_get('session.cookie_domain')
1165    );
1166  setcookie($conf['remember_me_name'], '', 0, cookie_path(),ini_get('session.cookie_domain'));
1167}
1168
1169/*
1170 * Return user status used in this library
1171 * @return string
1172*/
1173function get_user_status($user_status)
1174{
1175  global $user;
1176
1177  if (empty($user_status))
1178  {
1179    if (isset($user['status']))
1180    {
1181      $user_status = $user['status'];
1182    }
1183    else
1184    {
1185      // swicth to default value
1186      $user_status = '';
1187    }
1188  }
1189  return $user_status;
1190}
1191
1192/*
1193 * Return access_type definition of user
1194 * Test does with user status
1195 * @return bool
1196*/
1197function get_access_type_status($user_status='')
1198{
1199  global $conf;
1200
1201  switch (get_user_status($user_status))
1202  {
1203    case 'guest':
1204    {
1205      $access_type_status =
1206        ($conf['guest_access'] ? ACCESS_GUEST : ACCESS_FREE);
1207      break;
1208    }
1209    case 'generic':
1210    {
1211      $access_type_status = ACCESS_GUEST;
1212      break;
1213    }
1214    case 'normal':
1215    {
1216      $access_type_status = ACCESS_CLASSIC;
1217      break;
1218    }
1219    case 'admin':
1220    {
1221      $access_type_status = ACCESS_ADMINISTRATOR;
1222      break;
1223    }
1224    case 'webmaster':
1225    {
1226      $access_type_status = ACCESS_WEBMASTER;
1227      break;
1228    }
1229    default:
1230    {
1231      $access_type_status = ACCESS_FREE;
1232      break;
1233    }
1234  }
1235
1236  return $access_type_status;
1237}
1238
1239/*
1240 * Return if user have access to access_type definition
1241 * Test does with user status
1242 * @return bool
1243*/
1244function is_autorize_status($access_type, $user_status = '')
1245{
1246  return (get_access_type_status($user_status) >= $access_type);
1247}
1248
1249/*
1250 * Check if user have access to access_type definition
1251 * Stop action if there are not access
1252 * Test does with user status
1253 * @return none
1254*/
1255function check_status($access_type, $user_status = '')
1256{
1257  if (!is_autorize_status($access_type, $user_status))
1258  {
1259    access_denied();
1260  }
1261}
1262
1263/*
1264 * Return if user is generic
1265 * @return bool
1266*/
1267 function is_generic($user_status = '')
1268{
1269  return get_user_status($user_status) == 'generic';
1270}
1271
1272/*
1273 * Return if user is only a guest
1274 * @return bool
1275*/
1276 function is_a_guest($user_status = '')
1277{
1278  return get_user_status($user_status) == 'guest';
1279}
1280
1281/*
1282 * Return if user is, at least, a classic user
1283 * @return bool
1284*/
1285 function is_classic_user($user_status = '')
1286{
1287  return is_autorize_status(ACCESS_CLASSIC, $user_status);
1288}
1289
1290/*
1291 * Return if user is, at least, an administrator
1292 * @return bool
1293*/
1294 function is_admin($user_status = '')
1295{
1296  return is_autorize_status(ACCESS_ADMINISTRATOR, $user_status);
1297}
1298
1299/*
1300 * Return if user is, at least, a webmaster
1301 * @return bool
1302*/
1303 function is_webmaster($user_status = '')
1304{
1305  return is_autorize_status(ACCESS_WEBMASTER, $user_status);
1306}
1307
1308/*
1309 * Adviser status is depreciated from piwigo 2.2
1310 * @return false
1311*/
1312function is_adviser()
1313{
1314  return false;
1315}
1316
1317/*
1318 * Return if current user can edit/delete/validate a comment
1319 * @param action edit/delete/validate
1320 * @return bool
1321 */
1322function can_manage_comment($action, $comment_author_id)
1323{
1324  global $user, $conf;
1325 
1326  if (is_a_guest())
1327  {
1328    return false;
1329  }
1330 
1331  if (!in_array($action, array('delete','edit', 'validate')))
1332  {
1333    return false;
1334  }
1335
1336  if (is_admin())
1337  {
1338    return true;
1339  }
1340
1341  if ('edit' == $action and $conf['user_can_edit_comment'])
1342  {
1343    if ($comment_author_id == $user['id']) {
1344      return true;
1345    }
1346  }
1347
1348  if ('delete' == $action and $conf['user_can_delete_comment'])
1349  {
1350    if ($comment_author_id == $user['id']) {
1351      return true;
1352    }
1353  }
1354
1355  return false;
1356}
1357
1358/*
1359 * Return mail address as display text
1360 * @return string
1361*/
1362function get_email_address_as_display_text($email_address)
1363{
1364  global $conf;
1365
1366  if (!isset($email_address) or (trim($email_address) == ''))
1367  {
1368    return '';
1369  }
1370  else
1371  {
1372    return $email_address;
1373  }
1374}
1375
1376/*
1377 * Compute sql where condition with restrict and filter data. "FandF" means
1378 * Forbidden and Filters.
1379 *
1380 * @param array condition_fields: read function body
1381 * @param string prefix_condition: prefixes sql if condition is not empty
1382 * @param boolean force_one_condition: use at least "1 = 1"
1383 *
1384 * @return string sql where/conditions
1385 */
1386function get_sql_condition_FandF(
1387  $condition_fields,
1388  $prefix_condition = null,
1389  $force_one_condition = false
1390  )
1391{
1392  global $user, $filter;
1393
1394  $sql_list = array();
1395
1396  foreach ($condition_fields as $condition => $field_name)
1397  {
1398    switch($condition)
1399    {
1400      case 'forbidden_categories':
1401      {
1402        if (!empty($user['forbidden_categories']))
1403        {
1404          $sql_list[] =
1405            $field_name.' NOT IN ('.$user['forbidden_categories'].')';
1406        }
1407        break;
1408      }
1409      case 'visible_categories':
1410      {
1411        if (!empty($filter['visible_categories']))
1412        {
1413          $sql_list[] =
1414            $field_name.' IN ('.$filter['visible_categories'].')';
1415        }
1416        break;
1417      }
1418      case 'visible_images':
1419        if (!empty($filter['visible_images']))
1420        {
1421          $sql_list[] =
1422            $field_name.' IN ('.$filter['visible_images'].')';
1423        }
1424        // note there is no break - visible include forbidden
1425      case 'forbidden_images':
1426        if (
1427            !empty($user['image_access_list'])
1428            or $user['image_access_type']!='NOT IN'
1429            )
1430        {
1431          $table_prefix=null;
1432          if ($field_name=='id')
1433          {
1434            $table_prefix = '';
1435          }
1436          elseif ($field_name=='i.id')
1437          {
1438            $table_prefix = 'i.';
1439          }
1440          if ( isset($table_prefix) )
1441          {
1442            $sql_list[]=$table_prefix.'level<='.$user['level'];
1443          }
1444          else
1445          {
1446            $sql_list[]=$field_name.' '.$user['image_access_type']
1447                .' ('.$user['image_access_list'].')';
1448          }
1449        }
1450        break;
1451      default:
1452      {
1453        die('Unknow condition');
1454        break;
1455      }
1456    }
1457  }
1458
1459  if (count($sql_list) > 0)
1460  {
1461    $sql = '('.implode(' AND ', $sql_list).')';
1462  }
1463  else
1464  {
1465    $sql = $force_one_condition ? '1 = 1' : '';
1466  }
1467
1468  if (isset($prefix_condition) and !empty($sql))
1469  {
1470    $sql = $prefix_condition.' '.$sql;
1471  }
1472
1473  return $sql;
1474}
1475
1476?>
Note: See TracBrowser for help on using the repository browser.