source: branches/2.1/include/functions_user.inc.php @ 7744

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

Bug 1760 fixed : Avoid session fixation
After connection, session id is changed using session_regenerate_id
but without removing old session. Passing param true makes the job

Merge from trunk

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