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

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