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

Last change on this file since 11992 was 11992, checked in by plg, 13 years ago

feature 2027 implemented: the "lost password" feature was rewritten.

The algorithm is highly inspired from WordPress :

1) in a single field, you give a username or an email
2) Piwigo sends an email with the activation key
3) the user clicks on the link in the email (with the activation key) and is able to set a new password

The "lost password" feature is no longer limited to "classic" users:
administrators and webmasters can use it too (no need to tell webmasters
that they can only change their password in the database)

  • Property svn:eol-style set to LF
File size: 36.5 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 additional user data ?
325  if ($conf['external_authentification'])
326  {
327    $query = '
328SELECT
329    COUNT(1) AS counter
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  GROUP BY ui.user_id
335;';
336    list($counter) = pwg_db_fetch_row(pwg_query($query));
337    if ($counter != 1)
338    {
339      create_user_infos($user_id);
340    }
341  }
342
343  // retrieve user info
344  $query = '
345SELECT
346    ui.*,
347    uc.*,
348    t.name AS theme_name
349  FROM '.USER_INFOS_TABLE.' AS ui
350    LEFT JOIN '.USER_CACHE_TABLE.' AS uc ON ui.user_id = uc.user_id
351    LEFT JOIN '.THEMES_TABLE.' AS t ON t.id = ui.theme
352  WHERE ui.user_id = '.$user_id.'
353;';
354
355  $result = pwg_query($query);
356  $user_infos_row = pwg_db_fetch_assoc($result);
357
358  // then merge basic + additional user data
359  $row = array_merge($row, $user_infos_row);
360
361  foreach ($row as $key => $value)
362  {
363    if (!is_numeric($key))
364    {
365      // If the field is true or false, the variable is transformed into a
366      // boolean value.
367      if ($value == 'true' or $value == 'false')
368      {
369        $userdata[$key] = get_boolean($value);
370      }
371      else
372      {
373        $userdata[$key] = $value;
374      }
375    }
376  }
377
378  if ($use_cache)
379  {
380    if (!isset($userdata['need_update'])
381        or !is_bool($userdata['need_update'])
382        or $userdata['need_update'] == true)
383    {
384      $userdata['cache_update_time'] = time();
385
386      // Set need update are done
387      $userdata['need_update'] = false;
388
389      $userdata['forbidden_categories'] =
390        calculate_permissions($userdata['id'], $userdata['status']);
391
392      /* now we build the list of forbidden images (this list does not contain
393      images that are not in at least an authorized category)*/
394      $query = '
395SELECT DISTINCT(id)
396  FROM '.IMAGES_TABLE.' INNER JOIN '.IMAGE_CATEGORY_TABLE.' ON id=image_id
397  WHERE category_id NOT IN ('.$userdata['forbidden_categories'].')
398    AND level>'.$userdata['level'];
399      $forbidden_ids = array_from_query($query, 'id');
400
401      if ( empty($forbidden_ids) )
402      {
403        array_push( $forbidden_ids, 0 );
404      }
405      $userdata['image_access_type'] = 'NOT IN'; //TODO maybe later
406      $userdata['image_access_list'] = implode(',',$forbidden_ids);
407
408
409      $query = '
410SELECT COUNT(DISTINCT(image_id)) as total
411  FROM '.IMAGE_CATEGORY_TABLE.'
412  WHERE category_id NOT IN ('.$userdata['forbidden_categories'].')
413    AND image_id '.$userdata['image_access_type'].' ('.$userdata['image_access_list'].')';
414      list($userdata['nb_total_images']) = pwg_db_fetch_row(pwg_query($query));
415
416
417      // now we update user cache categories
418      $user_cache_cats = get_computed_categories($userdata, null);
419      if ( !is_admin($userdata['status']) )
420      { // for non admins we forbid categories with no image (feature 1053)
421        $forbidden_ids = array();
422        foreach ($user_cache_cats as $cat)
423        {
424          if ($cat['count_images']==0)
425          {
426            array_push($forbidden_ids, $cat['cat_id']);
427            unset( $user_cache_cats[$cat['cat_id']] );
428          }
429        }
430        if ( !empty($forbidden_ids) )
431        {
432          if ( empty($userdata['forbidden_categories']) )
433          {
434            $userdata['forbidden_categories'] = implode(',', $forbidden_ids);
435          }
436          else
437          {
438            $userdata['forbidden_categories'] .= ','.implode(',', $forbidden_ids);
439          }
440        }
441      }
442
443      // delete user cache
444      $query = '
445DELETE FROM '.USER_CACHE_CATEGORIES_TABLE.'
446  WHERE user_id = '.$userdata['id'];
447      pwg_query($query);
448
449      mass_inserts
450      (
451        USER_CACHE_CATEGORIES_TABLE,
452        array
453        (
454          'user_id', 'cat_id',
455          'date_last', 'max_date_last', 'nb_images', 'count_images', 'count_categories'
456        ),
457        $user_cache_cats
458      );
459
460
461      // update user cache
462      $query = '
463DELETE FROM '.USER_CACHE_TABLE.'
464  WHERE user_id = '.$userdata['id'];
465      pwg_query($query);
466
467      $query = '
468INSERT INTO '.USER_CACHE_TABLE.'
469  (user_id, need_update, cache_update_time, forbidden_categories, nb_total_images,
470    image_access_type, image_access_list)
471  VALUES
472  ('.$userdata['id'].',\''.boolean_to_string($userdata['need_update']).'\','
473  .$userdata['cache_update_time'].',\''
474  .$userdata['forbidden_categories'].'\','.$userdata['nb_total_images'].',\''
475  .$userdata['image_access_type'].'\',\''.$userdata['image_access_list'].'\')';
476      pwg_query($query);
477    }
478  }
479
480  return $userdata;
481}
482
483/*
484 * deletes favorites of the current user if he's not allowed to see them
485 *
486 * @return void
487 */
488function check_user_favorites()
489{
490  global $user;
491
492  if ($user['forbidden_categories'] == '')
493  {
494    return;
495  }
496
497  // $filter['visible_categories'] and $filter['visible_images']
498  // must be not used because filter <> restriction
499  // retrieving images allowed : belonging to at least one authorized
500  // category
501  $query = '
502SELECT DISTINCT f.image_id
503  FROM '.FAVORITES_TABLE.' AS f INNER JOIN '.IMAGE_CATEGORY_TABLE.' AS ic
504    ON f.image_id = ic.image_id
505  WHERE f.user_id = '.$user['id'].'
506'.get_sql_condition_FandF
507  (
508    array
509      (
510        'forbidden_categories' => 'ic.category_id',
511      ),
512    'AND'
513  ).'
514;';
515  $result = pwg_query($query);
516  $authorizeds = array();
517  while ($row = pwg_db_fetch_assoc($result))
518  {
519    array_push($authorizeds, $row['image_id']);
520  }
521
522  $query = '
523SELECT image_id
524  FROM '.FAVORITES_TABLE.'
525  WHERE user_id = '.$user['id'].'
526;';
527  $result = pwg_query($query);
528  $favorites = array();
529  while ($row = pwg_db_fetch_assoc($result))
530  {
531    array_push($favorites, $row['image_id']);
532  }
533
534  $to_deletes = array_diff($favorites, $authorizeds);
535
536  if (count($to_deletes) > 0)
537  {
538    $query = '
539DELETE FROM '.FAVORITES_TABLE.'
540  WHERE image_id IN ('.implode(',', $to_deletes).')
541    AND user_id = '.$user['id'].'
542;';
543    pwg_query($query);
544  }
545}
546
547/**
548 * calculates the list of forbidden categories for a given user
549 *
550 * Calculation is based on private categories minus categories authorized to
551 * the groups the user belongs to minus the categories directly authorized
552 * to the user. The list contains at least -1 to be compliant with queries
553 * such as "WHERE category_id NOT IN ($forbidden_categories)"
554 *
555 * @param int user_id
556 * @param string user_status
557 * @return string forbidden_categories
558 */
559function calculate_permissions($user_id, $user_status)
560{
561  $private_array = array();
562  $authorized_array = array();
563
564  $query = '
565SELECT id
566  FROM '.CATEGORIES_TABLE.'
567  WHERE status = \'private\'
568;';
569  $result = pwg_query($query);
570  while ($row = pwg_db_fetch_assoc($result))
571  {
572    array_push($private_array, $row['id']);
573  }
574
575  // retrieve category ids directly authorized to the user
576  $query = '
577SELECT cat_id
578  FROM '.USER_ACCESS_TABLE.'
579  WHERE user_id = '.$user_id.'
580;';
581  $authorized_array = array_from_query($query, 'cat_id');
582
583  // retrieve category ids authorized to the groups the user belongs to
584  $query = '
585SELECT cat_id
586  FROM '.USER_GROUP_TABLE.' AS ug INNER JOIN '.GROUP_ACCESS_TABLE.' AS ga
587    ON ug.group_id = ga.group_id
588  WHERE ug.user_id = '.$user_id.'
589;';
590  $authorized_array =
591    array_merge(
592      $authorized_array,
593      array_from_query($query, 'cat_id')
594      );
595
596  // uniquify ids : some private categories might be authorized for the
597  // groups and for the user
598  $authorized_array = array_unique($authorized_array);
599
600  // only unauthorized private categories are forbidden
601  $forbidden_array = array_diff($private_array, $authorized_array);
602
603  // if user is not an admin, locked categories are forbidden
604  if (!is_admin($user_status))
605  {
606    $query = '
607SELECT id
608  FROM '.CATEGORIES_TABLE.'
609  WHERE visible = \'false\'
610;';
611    $result = pwg_query($query);
612    while ($row = pwg_db_fetch_assoc($result))
613    {
614      array_push($forbidden_array, $row['id']);
615    }
616    $forbidden_array = array_unique($forbidden_array);
617  }
618
619  if ( empty($forbidden_array) )
620  {// at least, the list contains 0 value. This category does not exists so
621   // where clauses such as "WHERE category_id NOT IN(0)" will always be
622   // true.
623    array_push($forbidden_array, 0);
624  }
625
626  return implode(',', $forbidden_array);
627}
628
629/**
630 * compute data of categories branches (one branch only)
631 */
632function compute_branch_cat_data(&$cats, &$list_cat_id, &$level, &$ref_level)
633{
634  $date = '';
635  $count_images = 0;
636  $count_categories = 0;
637  do
638  {
639    $cat_id = array_pop($list_cat_id);
640    if (!is_null($cat_id))
641    {
642      // Count images and categories
643      $cats[$cat_id]['count_images'] += $count_images;
644      $cats[$cat_id]['count_categories'] += $count_categories;
645      $count_images = $cats[$cat_id]['count_images'];
646      $count_categories = $cats[$cat_id]['count_categories'] + 1;
647
648      if ((empty($cats[$cat_id]['max_date_last'])) or ($cats[$cat_id]['max_date_last'] < $date))
649      {
650        $cats[$cat_id]['max_date_last'] = $date;
651      }
652      else
653      {
654        $date = $cats[$cat_id]['max_date_last'];
655      }
656      $ref_level = substr_count($cats[$cat_id]['global_rank'], '.') + 1;
657    }
658    else
659    {
660      $ref_level = 0;
661    }
662  } while ($level <= $ref_level);
663
664  // Last cat updating must be added to list for next branch
665  if ($ref_level <> 0)
666  {
667    array_push($list_cat_id, $cat_id);
668  }
669}
670
671/**
672 * compute data of categories branches
673 */
674function compute_categories_data(&$cats)
675{
676  $ref_level = 0;
677  $level = 0;
678  $list_cat_id = array();
679
680  foreach ($cats as $id => $category)
681  {
682    // Compute
683    $level = substr_count($category['global_rank'], '.') + 1;
684    if ($level > $ref_level)
685    {
686      array_push($list_cat_id, $id);
687    }
688    else
689    {
690      compute_branch_cat_data($cats, $list_cat_id, $level, $ref_level);
691      array_push($list_cat_id, $id);
692    }
693    $ref_level = $level;
694  }
695
696  $level = 1;
697  compute_branch_cat_data($cats, $list_cat_id, $level, $ref_level);
698}
699
700/**
701 * get computed array of categories
702 *
703 * @param array userdata
704 * @param int filter_days number of recent days to filter on or null
705 * @return array
706 */
707function get_computed_categories($userdata, $filter_days=null)
708{
709  $query = 'SELECT c.id AS cat_id, global_rank';
710  // Count by date_available to avoid count null
711  $query .= ',
712  MAX(date_available) AS date_last, COUNT(date_available) AS nb_images
713FROM '.CATEGORIES_TABLE.' as c
714  LEFT JOIN '.IMAGE_CATEGORY_TABLE.' AS ic ON ic.category_id = c.id
715  LEFT JOIN '.IMAGES_TABLE.' AS i
716    ON ic.image_id = i.id
717      AND i.level<='.$userdata['level'];
718
719  if ( isset($filter_days) )
720  {
721    $query .= ' AND i.date_available > '.pwg_db_get_recent_period_expression($filter_days);
722  }
723
724  if ( !empty($userdata['forbidden_categories']) )
725  {
726    $query.= '
727  WHERE c.id NOT IN ('.$userdata['forbidden_categories'].')';
728  }
729
730  $query.= '
731  GROUP BY c.id, c.global_rank';
732
733  $result = pwg_query($query);
734
735  $cats = array();
736  while ($row = pwg_db_fetch_assoc($result))
737  {
738    $row['user_id'] = $userdata['id'];
739    $row['count_categories'] = 0;
740    $row['count_images'] = (int)$row['nb_images'];
741    $row['max_date_last'] = $row['date_last'];
742
743    $cats += array($row['cat_id'] => $row);
744  }
745  uasort($cats, 'global_rank_compare');
746
747  compute_categories_data($cats);
748
749  if ( isset($filter_days) )
750  {
751    $cat_tmp = $cats;
752    $cats = array();
753
754    foreach ($cat_tmp as $category)
755    {
756      if (!empty($category['max_date_last']))
757      {
758        // Re-init counters
759        $category['count_categories'] = 0;
760        $category['count_images'] = (int)$category['nb_images'];
761        // Keep category
762        $cats[$category['cat_id']] = $category;
763      }
764    }
765    // Compute a second time
766    compute_categories_data($cats);
767  }
768  return $cats;
769}
770
771/**
772 * returns user identifier thanks to his name, false if not found
773 *
774 * @param string username
775 * @param int user identifier
776 */
777function get_userid($username)
778{
779  global $conf;
780
781  $username = pwg_db_real_escape_string($username);
782
783  $query = '
784SELECT '.$conf['user_fields']['id'].'
785  FROM '.USERS_TABLE.'
786  WHERE '.$conf['user_fields']['username'].' = \''.$username.'\'
787;';
788  $result = pwg_query($query);
789
790  if (pwg_db_num_rows($result) == 0)
791  {
792    return false;
793  }
794  else
795  {
796    list($user_id) = pwg_db_fetch_row($result);
797    return $user_id;
798  }
799}
800
801function get_userid_by_email($email)
802{
803  global $conf;
804
805  $email = pwg_db_real_escape_string($email);
806 
807  $query = '
808SELECT
809    '.$conf['user_fields']['id'].'
810  FROM '.USERS_TABLE.'
811  WHERE UPPER('.$conf['user_fields']['email'].') = UPPER(\''.$email.'\')
812;';
813  $result = pwg_query($query);
814
815  if (pwg_db_num_rows($result) == 0)
816  {
817    return false;
818  }
819  else
820  {
821    list($user_id) = pwg_db_fetch_row($result);
822    return $user_id;
823  }
824}
825
826/**
827 * search an available feed_id
828 *
829 * @return string feed identifier
830 */
831function find_available_feed_id()
832{
833  while (true)
834  {
835    $key = generate_key(50);
836    $query = '
837SELECT COUNT(*)
838  FROM '.USER_FEED_TABLE.'
839  WHERE id = \''.$key.'\'
840;';
841    list($count) = pwg_db_fetch_row(pwg_query($query));
842    if (0 == $count)
843    {
844      return $key;
845    }
846  }
847}
848
849/*
850 * Returns a array with default user value
851 *
852 * @param convert_str allows to convert string value if necessary
853 */
854function get_default_user_info($convert_str = true)
855{
856  global $cache, $conf;
857
858  if (!isset($cache['default_user']))
859  {
860    $query = 'SELECT * FROM '.USER_INFOS_TABLE.
861            ' WHERE user_id = '.$conf['default_user_id'].';';
862
863    $result = pwg_query($query);
864    $cache['default_user'] = pwg_db_fetch_assoc($result);
865
866    if ($cache['default_user'] !== false)
867    {
868      unset($cache['default_user']['user_id']);
869      unset($cache['default_user']['status']);
870      unset($cache['default_user']['registration_date']);
871    }
872  }
873
874  if (is_array($cache['default_user']) and $convert_str)
875  {
876    $default_user = array();
877    foreach ($cache['default_user'] as $name => $value)
878    {
879      // If the field is true or false, the variable is transformed into a
880      // boolean value.
881      if ($value == 'true' or $value == 'false')
882      {
883        $default_user[$name] = get_boolean($value);
884      }
885      else
886      {
887        $default_user[$name] = $value;
888      }
889    }
890    return $default_user;
891  }
892  else
893  {
894    return $cache['default_user'];
895  }
896}
897
898/*
899 * Returns a default user value
900 *
901 * @param value_name: name of value
902 * @param sos_value: value used if don't exist value
903 */
904function get_default_user_value($value_name, $sos_value)
905{
906  $default_user = get_default_user_info(true);
907  if ($default_user === false or empty($default_user[$value_name]))
908  {
909    return $sos_value;
910  }
911  else
912  {
913   return $default_user[$value_name];
914  }
915}
916
917/*
918 * Returns the default template value
919 *
920 */
921function get_default_theme()
922{
923  $theme = get_default_user_value('theme', PHPWG_DEFAULT_TEMPLATE);
924  if (check_theme_installed($theme))
925  {
926    return $theme;
927  }
928 
929  // let's find the first available theme
930  $active_themes = get_pwg_themes();
931  foreach (array_keys(get_pwg_themes()) as $theme_id)
932  {
933    if (check_theme_installed($theme_id))
934    {
935      return $theme_id;
936    }
937  }
938}
939
940/*
941 * Returns the default language value
942 *
943 */
944function get_default_language()
945{
946  return get_default_user_value('language', PHPWG_DEFAULT_LANGUAGE);
947}
948
949/**
950  * Returns true if the browser language value is set into param $lang
951  *
952  */
953function get_browser_language(&$lang)
954{
955  $browser_language = substr(@$_SERVER["HTTP_ACCEPT_LANGUAGE"], 0, 2);
956  foreach (get_languages() as $language_code => $language_name)
957  {
958    if (substr($language_code, 0, 2) == $browser_language)
959    {
960      $lang = $language_code;
961      return true;
962    }
963  }
964  return false;
965}
966
967/**
968 * add user informations based on default values
969 *
970 * @param int user_id / array of user_if
971 * @param array of values used to override default user values
972 */
973function create_user_infos($arg_id, $override_values = null)
974{
975  global $conf;
976
977  if (is_array($arg_id))
978  {
979    $user_ids = $arg_id;
980  }
981  else
982  {
983    $user_ids = array();
984    if (is_numeric($arg_id))
985    {
986      $user_ids[] = $arg_id;
987    }
988  }
989
990  if (!empty($user_ids))
991  {
992    $inserts = array();
993    list($dbnow) = pwg_db_fetch_row(pwg_query('SELECT NOW();'));
994
995    $default_user = get_default_user_info(false);
996    if ($default_user === false)
997    {
998      // Default on structure are used
999      $default_user = array();
1000    }
1001
1002    if (!is_null($override_values))
1003    {
1004      $default_user = array_merge($default_user, $override_values);
1005    }
1006
1007    foreach ($user_ids as $user_id)
1008    {
1009      $level= isset($default_user['level']) ? $default_user['level'] : 0;
1010      if ($user_id == $conf['webmaster_id'])
1011      {
1012        $status = 'webmaster';
1013        $level = max( $conf['available_permission_levels'] );
1014      }
1015      else if (($user_id == $conf['guest_id']) or
1016               ($user_id == $conf['default_user_id']))
1017      {
1018        $status = 'guest';
1019      }
1020      else
1021      {
1022        $status = 'normal';
1023      }
1024
1025      $insert = array_merge(
1026        $default_user,
1027        array(
1028          'user_id' => $user_id,
1029          'status' => $status,
1030          'registration_date' => $dbnow,
1031          'level' => $level
1032          ));
1033
1034      array_push($inserts, $insert);
1035    }
1036
1037    mass_inserts(USER_INFOS_TABLE, array_keys($inserts[0]), $inserts);
1038  }
1039}
1040
1041/**
1042 * returns the auto login key or false on error
1043 * @param int user_id
1044 * @param time_t time
1045 * @param string [out] username
1046*/
1047function calculate_auto_login_key($user_id, $time, &$username)
1048{
1049  global $conf;
1050  $query = '
1051SELECT '.$conf['user_fields']['username'].' AS username
1052  , '.$conf['user_fields']['password'].' AS password
1053FROM '.USERS_TABLE.'
1054WHERE '.$conf['user_fields']['id'].' = '.$user_id;
1055  $result = pwg_query($query);
1056  if (pwg_db_num_rows($result) > 0)
1057  {
1058    $row = pwg_db_fetch_assoc($result);
1059    $username = stripslashes($row['username']);
1060    $data = $time.$user_id.$username;
1061    $key = base64_encode( hash_hmac('sha1', $data, $conf['secret_key'].$row['password'],true) );
1062    return $key;
1063  }
1064  return false;
1065}
1066
1067/*
1068 * Performs all required actions for user login
1069 * @param int user_id
1070 * @param bool remember_me
1071 * @return void
1072*/
1073function log_user($user_id, $remember_me)
1074{
1075  global $conf, $user;
1076
1077  if ($remember_me and $conf['authorize_remembering'])
1078  {
1079    $now = time();
1080    $key = calculate_auto_login_key($user_id, $now, $username);
1081    if ($key!==false)
1082    {
1083      $cookie = $user_id.'-'.$now.'-'.$key;
1084      if (version_compare(PHP_VERSION, '5.2', '>=') )
1085      {
1086        setcookie($conf['remember_me_name'],
1087            $cookie,
1088            time()+$conf['remember_me_length'],
1089            cookie_path(),ini_get('session.cookie_domain'),ini_get('session.cookie_secure'),
1090            ini_get('session.cookie_httponly')
1091          );
1092      }
1093      else
1094      {
1095        setcookie($conf['remember_me_name'],
1096            $cookie,
1097            time()+$conf['remember_me_length'],
1098            cookie_path(),ini_get('session.cookie_domain'),ini_get('session.cookie_secure')
1099          );
1100      }
1101    }
1102  }
1103  else
1104  { // make sure we clean any remember me ...
1105    setcookie($conf['remember_me_name'], '', 0, cookie_path(),ini_get('session.cookie_domain'));
1106  }
1107  if ( session_id()!="" )
1108  { // we regenerate the session for security reasons
1109    // see http://www.acros.si/papers/session_fixation.pdf
1110    session_regenerate_id(true);
1111  }
1112  else
1113  {
1114    session_start();
1115  }
1116  $_SESSION['pwg_uid'] = (int)$user_id;
1117
1118  $user['id'] = $_SESSION['pwg_uid'];
1119}
1120
1121/*
1122 * Performs auto-connexion when cookie remember_me exists
1123 * @return true/false
1124*/
1125function auto_login() {
1126  global $conf;
1127
1128  if ( isset( $_COOKIE[$conf['remember_me_name']] ) )
1129  {
1130    $cookie = explode('-', stripslashes($_COOKIE[$conf['remember_me_name']]));
1131    if ( count($cookie)===3
1132        and is_numeric(@$cookie[0]) /*user id*/
1133        and is_numeric(@$cookie[1]) /*time*/
1134        and time()-$conf['remember_me_length']<=@$cookie[1]
1135        and time()>=@$cookie[1] /*cookie generated in the past*/ )
1136    {
1137      $key = calculate_auto_login_key( $cookie[0], $cookie[1], $username );
1138      if ($key!==false and $key===$cookie[2])
1139      {
1140        log_user($cookie[0], true);
1141        trigger_action('login_success', stripslashes($username));
1142        return true;
1143      }
1144    }
1145    setcookie($conf['remember_me_name'], '', 0, cookie_path(),ini_get('session.cookie_domain'));
1146  }
1147  return false;
1148}
1149
1150/**
1151 * Tries to login a user given username and password (must be MySql escaped)
1152 * return true on success
1153 */
1154function try_log_user($username, $password, $remember_me)
1155{
1156  // we force the session table to be clean
1157  pwg_session_gc();
1158 
1159  global $conf;
1160  // retrieving the encrypted password of the login submitted
1161  $query = '
1162SELECT '.$conf['user_fields']['id'].' AS id,
1163       '.$conf['user_fields']['password'].' AS password
1164  FROM '.USERS_TABLE.'
1165  WHERE '.$conf['user_fields']['username'].' = \''.pwg_db_real_escape_string($username).'\'
1166;';
1167  $row = pwg_db_fetch_assoc(pwg_query($query));
1168  if ($row['password'] == $conf['pass_convert']($password))
1169  {
1170    log_user($row['id'], $remember_me);
1171    trigger_action('login_success', stripslashes($username));
1172    return true;
1173  }
1174  trigger_action('login_failure', stripslashes($username));
1175  return false;
1176}
1177
1178/** Performs all the cleanup on user logout */
1179function logout_user()
1180{
1181  global $conf;
1182  $_SESSION = array();
1183  session_unset();
1184  session_destroy();
1185  setcookie(session_name(),'',0,
1186      ini_get('session.cookie_path'),
1187      ini_get('session.cookie_domain')
1188    );
1189  setcookie($conf['remember_me_name'], '', 0, cookie_path(),ini_get('session.cookie_domain'));
1190}
1191
1192/*
1193 * Return user status used in this library
1194 * @return string
1195*/
1196function get_user_status($user_status)
1197{
1198  global $user;
1199
1200  if (empty($user_status))
1201  {
1202    if (isset($user['status']))
1203    {
1204      $user_status = $user['status'];
1205    }
1206    else
1207    {
1208      // swicth to default value
1209      $user_status = '';
1210    }
1211  }
1212  return $user_status;
1213}
1214
1215/*
1216 * Return access_type definition of user
1217 * Test does with user status
1218 * @return bool
1219*/
1220function get_access_type_status($user_status='')
1221{
1222  global $conf;
1223
1224  switch (get_user_status($user_status))
1225  {
1226    case 'guest':
1227    {
1228      $access_type_status =
1229        ($conf['guest_access'] ? ACCESS_GUEST : ACCESS_FREE);
1230      break;
1231    }
1232    case 'generic':
1233    {
1234      $access_type_status = ACCESS_GUEST;
1235      break;
1236    }
1237    case 'normal':
1238    {
1239      $access_type_status = ACCESS_CLASSIC;
1240      break;
1241    }
1242    case 'admin':
1243    {
1244      $access_type_status = ACCESS_ADMINISTRATOR;
1245      break;
1246    }
1247    case 'webmaster':
1248    {
1249      $access_type_status = ACCESS_WEBMASTER;
1250      break;
1251    }
1252    default:
1253    {
1254      $access_type_status = ACCESS_FREE;
1255      break;
1256    }
1257  }
1258
1259  return $access_type_status;
1260}
1261
1262/*
1263 * Return if user have access to access_type definition
1264 * Test does with user status
1265 * @return bool
1266*/
1267function is_autorize_status($access_type, $user_status = '')
1268{
1269  return (get_access_type_status($user_status) >= $access_type);
1270}
1271
1272/*
1273 * Check if user have access to access_type definition
1274 * Stop action if there are not access
1275 * Test does with user status
1276 * @return none
1277*/
1278function check_status($access_type, $user_status = '')
1279{
1280  if (!is_autorize_status($access_type, $user_status))
1281  {
1282    access_denied();
1283  }
1284}
1285
1286/*
1287 * Return if user is generic
1288 * @return bool
1289*/
1290 function is_generic($user_status = '')
1291{
1292  return get_user_status($user_status) == 'generic';
1293}
1294
1295/*
1296 * Return if user is only a guest
1297 * @return bool
1298*/
1299 function is_a_guest($user_status = '')
1300{
1301  return get_user_status($user_status) == 'guest';
1302}
1303
1304/*
1305 * Return if user is, at least, a classic user
1306 * @return bool
1307*/
1308 function is_classic_user($user_status = '')
1309{
1310  return is_autorize_status(ACCESS_CLASSIC, $user_status);
1311}
1312
1313/*
1314 * Return if user is, at least, an administrator
1315 * @return bool
1316*/
1317 function is_admin($user_status = '')
1318{
1319  return is_autorize_status(ACCESS_ADMINISTRATOR, $user_status);
1320}
1321
1322/*
1323 * Return if user is, at least, a webmaster
1324 * @return bool
1325*/
1326 function is_webmaster($user_status = '')
1327{
1328  return is_autorize_status(ACCESS_WEBMASTER, $user_status);
1329}
1330
1331/*
1332 * Adviser status is depreciated from piwigo 2.2
1333 * @return false
1334*/
1335function is_adviser()
1336{
1337  trigger_error('call to obsolete function is_adviser', E_USER_WARNING);
1338  return false;
1339}
1340
1341/*
1342 * Return if current user can edit/delete/validate a comment
1343 * @param action edit/delete/validate
1344 * @return bool
1345 */
1346function can_manage_comment($action, $comment_author_id)
1347{
1348  global $user, $conf;
1349 
1350  if (is_a_guest())
1351  {
1352    return false;
1353  }
1354 
1355  if (!in_array($action, array('delete','edit', 'validate')))
1356  {
1357    return false;
1358  }
1359
1360  if (is_admin())
1361  {
1362    return true;
1363  }
1364
1365  if ('edit' == $action and $conf['user_can_edit_comment'])
1366  {
1367    if ($comment_author_id == $user['id']) {
1368      return true;
1369    }
1370  }
1371
1372  if ('delete' == $action and $conf['user_can_delete_comment'])
1373  {
1374    if ($comment_author_id == $user['id']) {
1375      return true;
1376    }
1377  }
1378
1379  return false;
1380}
1381
1382/*
1383 * Return mail address as display text
1384 * @return string
1385*/
1386function get_email_address_as_display_text($email_address)
1387{
1388  global $conf;
1389
1390  if (!isset($email_address) or (trim($email_address) == ''))
1391  {
1392    return '';
1393  }
1394  else
1395  {
1396    return $email_address;
1397  }
1398}
1399
1400/*
1401 * Compute sql where condition with restrict and filter data. "FandF" means
1402 * Forbidden and Filters.
1403 *
1404 * @param array condition_fields: read function body
1405 * @param string prefix_condition: prefixes sql if condition is not empty
1406 * @param boolean force_one_condition: use at least "1 = 1"
1407 *
1408 * @return string sql where/conditions
1409 */
1410function get_sql_condition_FandF(
1411  $condition_fields,
1412  $prefix_condition = null,
1413  $force_one_condition = false
1414  )
1415{
1416  global $user, $filter;
1417
1418  $sql_list = array();
1419
1420  foreach ($condition_fields as $condition => $field_name)
1421  {
1422    switch($condition)
1423    {
1424      case 'forbidden_categories':
1425      {
1426        if (!empty($user['forbidden_categories']))
1427        {
1428          $sql_list[] =
1429            $field_name.' NOT IN ('.$user['forbidden_categories'].')';
1430        }
1431        break;
1432      }
1433      case 'visible_categories':
1434      {
1435        if (!empty($filter['visible_categories']))
1436        {
1437          $sql_list[] =
1438            $field_name.' IN ('.$filter['visible_categories'].')';
1439        }
1440        break;
1441      }
1442      case 'visible_images':
1443        if (!empty($filter['visible_images']))
1444        {
1445          $sql_list[] =
1446            $field_name.' IN ('.$filter['visible_images'].')';
1447        }
1448        // note there is no break - visible include forbidden
1449      case 'forbidden_images':
1450        if (
1451            !empty($user['image_access_list'])
1452            or $user['image_access_type']!='NOT IN'
1453            )
1454        {
1455          $table_prefix=null;
1456          if ($field_name=='id')
1457          {
1458            $table_prefix = '';
1459          }
1460          elseif ($field_name=='i.id')
1461          {
1462            $table_prefix = 'i.';
1463          }
1464          if ( isset($table_prefix) )
1465          {
1466            $sql_list[]=$table_prefix.'level<='.$user['level'];
1467          }
1468          else
1469          {
1470            $sql_list[]=$field_name.' '.$user['image_access_type']
1471                .' ('.$user['image_access_list'].')';
1472          }
1473        }
1474        break;
1475      default:
1476      {
1477        die('Unknow condition');
1478        break;
1479      }
1480    }
1481  }
1482
1483  if (count($sql_list) > 0)
1484  {
1485    $sql = '('.implode(' AND ', $sql_list).')';
1486  }
1487  else
1488  {
1489    $sql = $force_one_condition ? '1 = 1' : '';
1490  }
1491
1492  if (isset($prefix_condition) and !empty($sql))
1493  {
1494    $sql = $prefix_condition.' '.$sql;
1495  }
1496
1497  return $sql;
1498}
1499
1500/**
1501 * search an available activation_key
1502 *
1503 * @return string
1504 */
1505function get_user_activation_key()
1506{
1507  while (true)
1508  {
1509    $key = generate_key(20);
1510    $query = '
1511SELECT COUNT(*)
1512  FROM '.USER_INFOS_TABLE.'
1513  WHERE activation_key = \''.$key.'\'
1514;';
1515    list($count) = pwg_db_fetch_row(pwg_query($query));
1516    if (0 == $count)
1517    {
1518      return $key;
1519    }
1520  }
1521}
1522
1523?>
Note: See TracBrowser for help on using the repository browser.