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

Last change on this file since 6315 was 6315, checked in by plg, 15 years ago

merge r6312 from branch 2.1 to trunk

bug 1684 fixed: the test to check availability of the user_infos line was
wrong. I had changed the old db_num_rows > 0 because it was not working with
SQLite. As suggested by nicolas, let's use a simpler trick "count(1)" in the
query itself, this way it should work with any database engine.

I've also removed the while (true) (ugly infinite loop, with a condition for
exit) that was producing an infinite loop for Piwigo installations with 2.0
database model and 2.1 code (before launching upgrade.php)

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