My friend // ( 01234567891111111111222222222233 ) // ( 0123456789012345678901 ) // becomes : //
'; $debug.= '['.$time.', '; $debug.= $page['count_queries'].' queries] : '.$string; $debug.= "
\n"; } /** * Redirects to the given URL (HTTP method) * * Note : once this function called, the execution doesn't go further * (presence of an exit() instruction. * * @param string $url * @return void */ function redirect_http( $url ) { if (ob_get_length () !== FALSE) { ob_clean(); } // default url is on html format $url = html_entity_decode($url); header('Request-URI: '.$url); header('Content-Location: '.$url); header('Location: '.$url); exit(); } /** * Redirects to the given URL (HTML method) * * Note : once this function called, the execution doesn't go further * (presence of an exit() instruction. * * @param string $url * @param string $title_msg * @param integer $refreh_time * @return void */ function redirect_html( $url , $msg = '', $refresh_time = 0) { global $user, $template, $lang_info, $conf, $lang, $t2, $page, $debug; if (!isset($lang_info) || !isset($template) ) { $user = build_user( $conf['guest_id'], true); load_language('common.lang'); trigger_action('loading_lang'); load_language('lang', PHPWG_ROOT_PATH.PWG_LOCAL_DIR, array('no_fallback'=>true, 'local'=>true) ); $template = new Template(PHPWG_ROOT_PATH.'themes', get_default_theme()); } elseif (defined('IN_ADMIN') and IN_ADMIN) { $template = new Template(PHPWG_ROOT_PATH.'themes', get_default_theme()); } if (empty($msg)) { $msg = nl2br(l10n('Redirection...')); } $refresh = $refresh_time; $url_link = $url; $title = 'redirection'; $template->set_filenames( array( 'redirect' => 'redirect.tpl' ) ); include( PHPWG_ROOT_PATH.'include/page_header.php' ); $template->set_filenames( array( 'redirect' => 'redirect.tpl' ) ); $template->assign('REDIRECT_MSG', $msg); $template->parse('redirect'); include( PHPWG_ROOT_PATH.'include/page_tail.php' ); exit(); } /** * Redirects to the given URL (Switch to HTTP method or HTML method) * * Note : once this function called, the execution doesn't go further * (presence of an exit() instruction. * * @param string $url * @param string $title_msg * @param integer $refreh_time * @return void */ function redirect( $url , $msg = '', $refresh_time = 0) { global $conf; // with RefeshTime <> 0, only html must be used if ($conf['default_redirect_method']=='http' and $refresh_time==0 and !headers_sent() ) { redirect_http($url); } else { redirect_html($url, $msg, $refresh_time); } } /** * returns $_SERVER['QUERY_STRING'] whitout keys given in parameters * * @param array $rejects * @param boolean $escape - if true escape & to & (for html) * @returns string */ function get_query_string_diff($rejects=array(), $escape=true) { if (empty($_SERVER['QUERY_STRING'])) { return ''; } parse_str($_SERVER['QUERY_STRING'], $vars); $vars = array_diff_key($vars, array_flip($rejects)); return '?' . http_build_query($vars, '', $escape ? '&' : '&'); } /** * returns true if the url is absolute (begins with http) * @param string $url * @returns boolean */ function url_is_remote($url) { if ( strncmp($url, 'http://', 7)==0 or strncmp($url, 'https://', 8)==0 ) { return true; } return false; } /** * returns available themes */ function get_pwg_themes($show_mobile=false) { global $conf; $themes = array(); $query = ' SELECT id, name FROM '.THEMES_TABLE.' ORDER BY name ASC ;'; $result = pwg_query($query); while ($row = pwg_db_fetch_assoc($result)) { if ($row['id'] == $conf['mobile_theme']) { if (!$show_mobile) { continue; } $row['name'] .= ' ('.l10n('Mobile').')'; } if (check_theme_installed($row['id'])) { $themes[ $row['id'] ] = $row['name']; } } // plugins want remove some themes based on user status maybe? $themes = trigger_event('get_pwg_themes', $themes); return $themes; } function check_theme_installed($theme_id) { global $conf; return file_exists($conf['themes_dir'].'/'.$theme_id.'/'.'themeconf.inc.php'); } /** Transforms an original path to its pwg representative */ function original_to_representative($path, $representative_ext) { $pos = strrpos($path, '/'); $path = substr_replace($path, 'pwg_representative/', $pos+1, 0); $pos = strrpos($path, '.'); return substr_replace($path, $representative_ext, $pos+1); } /** * @param element_info array containing element information from db; * at least 'id', 'path' should be present */ function get_element_path($element_info) { $path = $element_info['path']; if ( !url_is_remote($path) ) { $path = PHPWG_ROOT_PATH.$path; } return $path; } /** * fill the current user caddie with given elements, if not already in * caddie * * @param array elements_id */ function fill_caddie($elements_id) { global $user; $query = ' SELECT element_id FROM '.CADDIE_TABLE.' WHERE user_id = '.$user['id'].' ;'; $in_caddie = array_from_query($query, 'element_id'); $caddiables = array_diff($elements_id, $in_caddie); $datas = array(); foreach ($caddiables as $caddiable) { $datas[] = array( 'element_id' => $caddiable, 'user_id' => $user['id'], ); } if (count($caddiables) > 0) { mass_inserts(CADDIE_TABLE, array('element_id','user_id'), $datas); } } /** * returns the element name from its filename * * @param string filename * @return string name */ function get_name_from_file($filename) { return str_replace('_',' ',get_filename_wo_extension($filename)); } /** * translation function * returns the corresponding value from $lang if existing, else the key is returned * if more than one parameter is provided sprintf is applied * @param string $key * @param mixed $args,... optional arguments * @return string */ function l10n($key) { global $lang, $conf; if ( ($val=@$lang[$key]) == null) { if ($conf['debug_l10n'] and !isset($lang[$key]) and !empty($key)) { trigger_error('[l10n] language key "'. $key .'" not defined', E_USER_WARNING); } $val = $key; } if (func_num_args() > 1) { $args = func_get_args(); $val = vsprintf($val, array_slice($args, 1)); } return $val; } /** * returns the printf value for strings including %d * return is concorded with decimal value (singular, plural) * * @param singular string key * @param plural string key * @param decimal value * @return string */ function l10n_dec($singular_fmt_key, $plural_fmt_key, $decimal) { global $lang_info; return sprintf( l10n(( (($decimal > 1) or ($decimal == 0 and $lang_info['zero_plural'])) ? $plural_fmt_key : $singular_fmt_key )), $decimal); } /* * returns a single element to use with l10n_args * * @param string key: translation key * @param mixed args: arguments to use on sprintf($key, args) * if args is a array, each values are used on sprintf * @return string */ function get_l10n_args($key, $args) { if (is_array($args)) { $key_arg = array_merge(array($key), $args); } else { $key_arg = array($key, $args); } return array('key_args' => $key_arg); } /* * returns a string formated with l10n elements * * @param array $key_args: l10n_args element or array of l10n_args elements * @param string $sep: used when translated elements are concatened * @return string */ function l10n_args($key_args, $sep = "\n") { if (is_array($key_args)) { foreach ($key_args as $key => $element) { if (isset($result)) { $result .= $sep; } else { $result = ''; } if ($key === 'key_args') { array_unshift($element, l10n(array_shift($element))); // translate the key $result .= call_user_func_array('sprintf', $element); } else { $result .= l10n_args($element, $sep); } } } else { fatal_error('l10n_args: Invalid arguments'); } return $result; } /** * returns the corresponding value from $themeconf if existing. Else, the * key is returned * * @param string key * @return string */ function get_themeconf($key) { global $template; return $template->get_themeconf($key); } /** * Returns webmaster mail address depending on $conf['webmaster_id'] * * @return string */ function get_webmaster_mail_address() { global $conf; $query = ' SELECT '.$conf['user_fields']['email'].' FROM '.USERS_TABLE.' WHERE '.$conf['user_fields']['id'].' = '.$conf['webmaster_id'].' ;'; list($email) = pwg_db_fetch_row(pwg_query($query)); $email = trigger_event('get_webmaster_mail_address', $email); return $email; } /** * Add configuration parameters from database to global $conf array * * @return void */ function load_conf_from_db($condition = '') { global $conf; $query = ' SELECT param, value FROM '.CONFIG_TABLE.' '.(!empty($condition) ? 'WHERE '.$condition : '').' ;'; $result = pwg_query($query); if ((pwg_db_num_rows($result) == 0) and !empty($condition)) { fatal_error('No configuration data'); } while ($row = pwg_db_fetch_assoc($result)) { $val = isset($row['value']) ? $row['value'] : ''; // If the field is true or false, the variable is transformed into a boolean value. if ($val == 'true') { $val = true; } elseif ($val == 'false') { $val = false; } $conf[ $row['param'] ] = $val; } trigger_action('load_conf', $condition); } /** * Add or update a config parameter * @param string $param * @param string $value */ function conf_update_param($param, $value) { $query = ' SELECT param, value FROM '.CONFIG_TABLE.' WHERE param = \''.$param.'\' ;'; $params = array_from_query($query, 'param'); if (count($params) == 0) { $query = ' INSERT INTO '.CONFIG_TABLE.' (param, value) VALUES(\''.$param.'\', \''.$value.'\') ;'; pwg_query($query); } else { $query = ' UPDATE '.CONFIG_TABLE.' SET value = \''.$value.'\' WHERE param = \''.$param.'\' ;'; pwg_query($query); } } /** * Delete on or more config parameters * @since 2.6 * @param string|string[] $params */ function conf_delete_param($params) { global $conf; if (!is_array($params)) { $params = array($params); } if (empty($params)) { return; } $query = ' DELETE FROM '.CONFIG_TABLE.' WHERE param IN(\''. implode('\',\'', $params) .'\') ;'; pwg_query($query); foreach ($params as $param) { unset($conf[$param]); } } /** * Prepends and appends a string at each value of the given array. * * @param array * @param string prefix to each array values * @param string suffix to each array values */ function prepend_append_array_items($array, $prepend_str, $append_str) { array_walk( $array, create_function('&$s', '$s = "'.$prepend_str.'".$s."'.$append_str.'";') ); return $array; } /** * creates an hashed based on a query, this function is a very common * pattern used here. Among the selected columns fetched, choose one to be * the key, another one to be the value. * * @param string $query * @param string $keyname * @param string $valuename * @return array */ function simple_hash_from_query($query, $keyname, $valuename) { $array = array(); $result = pwg_query($query); while ($row = pwg_db_fetch_assoc($result)) { $array[ $row[$keyname] ] = $row[$valuename]; } return $array; } /** * creates an hashed based on a query, this function is a very common * pattern used here. The key is given as parameter, the value is an associative * array. * * @param string $query * @param string $keyname * @return array */ function hash_from_query($query, $keyname) { $array = array(); $result = pwg_query($query); while ($row = pwg_db_fetch_assoc($result)) { $array[ $row[$keyname] ] = $row; } return $array; } /** * Return basename of the current script * Lower case convertion is applied on return value * Return value is without file extention ".php" * * @param void * * @return script basename */ function script_basename() { global $conf; foreach (array('SCRIPT_NAME', 'SCRIPT_FILENAME', 'PHP_SELF') as $value) { if (!empty($_SERVER[$value])) { $filename = strtolower($_SERVER[$value]); if ($conf['php_extension_in_urls'] and get_extension($filename)!=='php') continue; $basename = basename($filename, '.php'); if (!empty($basename)) { return $basename; } } } return ''; } /** * Return value for the current page define on $conf['filter_pages'] * Îf value is not defined, default value are returned * * @param value name * * @return filter page value */ function get_filter_page_value($value_name) { global $conf; $page_name = script_basename(); if (isset($conf['filter_pages'][$page_name][$value_name])) { return $conf['filter_pages'][$page_name][$value_name]; } else if (isset($conf['filter_pages']['default'][$value_name])) { return $conf['filter_pages']['default'][$value_name]; } else { return null; } } /** * returns the character set of data sent to browsers / received from forms */ function get_pwg_charset() { $pwg_charset = 'utf-8'; if (defined('PWG_CHARSET')) { $pwg_charset = PWG_CHARSET; } return $pwg_charset; } /** * includes a language file or returns the content of a language file * availability of the file * * in descending order of preference: * param language, user language, default language * Piwigo default language. * * @param string filename * @param string dirname * @param mixed options can contain * language - language to load (if empty uses user language) * return - if true the file content is returned otherwise the file is evaluated as php * target_charset - * no_fallback - the language must be respected * local - if true, get local language file * @return boolean success status or a string if options['return'] is true */ function load_language($filename, $dirname = '', $options = array() ) { global $user, $language_files; if ( !empty($dirname) and !empty($filename) ) { if ( empty($language_files[$dirname]) or !in_array($filename,$language_files[$dirname]) ) { $language_files[$dirname][] = $filename; } } if (! @$options['return'] ) { $filename .= '.php'; //MAYBE to do .. load .po and .mo localization files } if (empty($dirname)) { $dirname = PHPWG_ROOT_PATH; } $dirname .= 'language/'; $languages = array(); if ( !empty($options['language']) ) { $languages[] = $options['language']; } if ( !empty($user['language']) ) { $languages[] = $user['language']; } if ( ! @$options['no_fallback'] ) { if ( defined('PHPWG_INSTALLED') ) { $languages[] = get_default_language(); } $languages[] = PHPWG_DEFAULT_LANGUAGE; } $languages = array_unique($languages); /*Note: target charset is always utf-8 if ( empty($options['target_charset']) ) { $target_charset = get_pwg_charset(); } else { $target_charset = $options['target_charset']; } $target_charset = strtolower($target_charset);*/ $source_file = ''; $selected_language = ''; foreach ($languages as $language) { $f = @$options['local'] ? $dirname.$language.'.'.$filename: $dirname.$language.'/'.$filename; if (file_exists($f)) { $selected_language = $language; $source_file = $f; break; } } if ( !empty($source_file) ) { if (! @$options['return'] ) { @include($source_file); $load_lang = @$lang; $load_lang_info = @$lang_info; global $lang, $lang_info; if ( !isset($lang) ) $lang=array(); if ( !isset($lang_info) ) $lang_info=array(); $parent_language = !empty($load_lang_info['parent']) ? $load_lang_info['parent'] : ( !empty($lang_info['parent']) ? $lang_info['parent'] : null ); if (!empty($parent_language)) { @include(str_replace($selected_language, $parent_language, $source_file)); } /* Note: target charset is always utf-8 if ( 'utf-8'!=$target_charset) { if ( is_array($load_lang) ) { foreach ($load_lang as $k => $v) { if ( is_array($v) ) { $func = create_function('$v', 'return convert_charset($v, "utf-8", "'.$target_charset.'");' ); $lang[$k] = array_map($func, $v); } else $lang[$k] = convert_charset($v, 'utf-8', $target_charset); } } if ( is_array($load_lang_info) ) { foreach ($load_lang_info as $k => $v) { $lang_info[$k] = convert_charset($v, 'utf-8', $target_charset); } } } else {*/ $lang = array_merge( $lang, (array)$load_lang ); $lang_info = array_merge( $lang_info, (array)$load_lang_info ); //} return true; } else { $content = @file_get_contents($source_file); //Note: target charset is always utf-8 $content = convert_charset($content, 'utf-8', $target_charset); return $content; } } return false; } /** * converts a string from a character set to another character set * @param string str the string to be converted * @param string source_charset the character set in which the string is encoded * @param string dest_charset the destination character set */ function convert_charset($str, $source_charset, $dest_charset) { if ($source_charset==$dest_charset) return $str; if ($source_charset=='iso-8859-1' and $dest_charset=='utf-8') { return utf8_encode($str); } if ($source_charset=='utf-8' and $dest_charset=='iso-8859-1') { return utf8_decode($str); } if (function_exists('iconv')) { return iconv($source_charset, $dest_charset, $str); } if (function_exists('mb_convert_encoding')) { return mb_convert_encoding( $str, $dest_charset, $source_charset ); } return $str; //??? } /** * makes sure a index.htm protects the directory from browser file listing * * @param string dir directory */ function secure_directory($dir) { $file = $dir.'/index.htm'; if (!file_exists($file)) { @file_put_contents($file, 'Not allowed!'); } } /** * returns a "secret key" that is to be sent back when a user posts a form * * @param int valid_after_seconds - key validity start time from now */ function get_ephemeral_key($valid_after_seconds, $aditionnal_data_to_hash = '') { global $conf; $time = round(microtime(true), 1); return $time.':'.$valid_after_seconds.':' .hash_hmac( 'md5', $time.substr($_SERVER['REMOTE_ADDR'],0,5).$valid_after_seconds.$aditionnal_data_to_hash, $conf['secret_key']); } function verify_ephemeral_key($key, $aditionnal_data_to_hash = '') { global $conf; $time = microtime(true); $key = explode( ':', @$key ); if ( count($key)!=3 or $key[0]>$time-(float)$key[1] // page must have been retrieved more than X sec ago or $key[0]<$time-3600 // 60 minutes expiration or hash_hmac( 'md5', $key[0].substr($_SERVER['REMOTE_ADDR'],0,5).$key[1].$aditionnal_data_to_hash, $conf['secret_key'] ) != $key[2] ) { return false; } return true; } /** * return an array which will be sent to template to display navigation bar */ function create_navigation_bar($url, $nb_element, $start, $nb_element_page, $clean_url = false, $param_name='start') { global $conf; $navbar = array(); $pages_around = $conf['paginate_pages_around']; $start_str = $clean_url ? '/'.$param_name.'-' : (strpos($url, '?')===false ? '?':'&').$param_name.'='; if (!isset($start) or !is_numeric($start) or (is_numeric($start) and $start < 0)) { $start = 0; } // navigation bar useful only if more than one page to display ! if ($nb_element > $nb_element_page) { $url_start = $url.$start_str; $cur_page = $navbar['CURRENT_PAGE'] = $start / $nb_element_page + 1; $maximum = ceil($nb_element / $nb_element_page); $start = $nb_element_page * round( $start / $nb_element_page ); $previous = $start - $nb_element_page; $next = $start + $nb_element_page; $last = ($maximum - 1) * $nb_element_page; // link to first page and previous page? if ($cur_page != 1) { $navbar['URL_FIRST'] = $url; $navbar['URL_PREV'] = $previous > 0 ? $url_start.$previous : $url; } // link on next page and last page? if ($cur_page != $maximum) { $navbar['URL_NEXT'] = $url_start.($next < $last ? $next : $last); $navbar['URL_LAST'] = $url_start.$last; } // pages to display $navbar['pages'] = array(); $navbar['pages'][1] = $url; for ($i = max( floor($cur_page) - $pages_around , 2), $stop = min( ceil($cur_page) + $pages_around + 1, $maximum); $i < $stop; $i++) { $navbar['pages'][$i] = $url.$start_str.(($i - 1) * $nb_element_page); } $navbar['pages'][$maximum] = $url_start.$last; $navbar['NB_PAGE']=$maximum; } return $navbar; } /** * return an array which will be sent to template to display recent icon */ function get_icon($date, $is_child_date = false) { global $cache, $user; if (empty($date)) { return false; } if (!isset($cache['get_icon']['title'])) { $cache['get_icon']['title'] = l10n( 'photos posted during the last %d days', $user['recent_period'] ); } $icon = array( 'TITLE' => $cache['get_icon']['title'], 'IS_CHILD_DATE' => $is_child_date, ); if (isset($cache['get_icon'][$date])) { return $cache['get_icon'][$date] ? $icon : array(); } if (!isset($cache['get_icon']['sql_recent_date'])) { // Use MySql date in order to standardize all recent "actions/queries" $cache['get_icon']['sql_recent_date'] = pwg_db_get_recent_period($user['recent_period']); } $cache['get_icon'][$date] = $date > $cache['get_icon']['sql_recent_date']; return $cache['get_icon'][$date] ? $icon : array(); } /** * check token comming from form posted or get params to prevent csrf attacks * if pwg_token is empty action doesn't require token * else pwg_token is compare to server token * * @return void access denied if token given is not equal to server token */ function check_pwg_token() { if (!empty($_REQUEST['pwg_token'])) { if (get_pwg_token() != $_REQUEST['pwg_token']) { access_denied(); } } else bad_request('missing token'); } function get_pwg_token() { global $conf; return hash_hmac('md5', session_id(), $conf['secret_key']); } /* * breaks the script execution if the given value doesn't match the given * pattern. This should happen only during hacking attempts. * * @param string param_name * @param array param_array * @param boolean is_array * @param string pattern * @param boolean mandatory * * @return void */ function check_input_parameter($param_name, $param_array, $is_array, $pattern, $mandatory=false) { $param_value = null; if (isset($param_array[$param_name])) { $param_value = $param_array[$param_name]; } // it's ok if the input parameter is null if (empty($param_value)) { if ($mandatory) { fatal_error('[Hacking attempt] the input parameter "'.$param_name.'" is not valid'); } return true; } if ($is_array) { if (!is_array($param_value)) { fatal_error('[Hacking attempt] the input parameter "'.$param_name.'" should be an array'); } foreach ($param_value as $item_to_check) { if (!preg_match($pattern, $item_to_check)) { fatal_error('[Hacking attempt] an item is not valid in input parameter "'.$param_name.'"'); } } } else { if (!preg_match($pattern, $param_value)) { fatal_error('[Hacking attempt] the input parameter "'.$param_name.'" is not valid'); } } } function get_privacy_level_options() { global $conf; $options = array(); $label = ''; foreach (array_reverse($conf['available_permission_levels']) as $level) { if (0 == $level) { $label = l10n('Everybody'); } else { if (strlen($label)) { $label .= ', '; } $label .= l10n( sprintf('Level %d', $level) ); } $options[$level] = $label; } return $options; } /** * return the branch from the version. For example version 2.2.4 is for branch 2.2 */ function get_branch_from_version($version) { return implode('.', array_slice(explode('.', $version), 0, 2)); } /** * return the device type: mobile, tablet or desktop */ function get_device() { $device = pwg_get_session_var('device'); if (is_null($device)) { include_once(PHPWG_ROOT_PATH.'include/mdetect.php'); $uagent_obj = new uagent_info(); if ($uagent_obj->DetectSmartphone()) { $device = 'mobile'; } elseif ($uagent_obj->DetectTierTablet()) { $device = 'tablet'; } else { $device = 'desktop'; } pwg_set_session_var('device', $device); } return $device; } /** * return true if mobile theme should be loaded */ function mobile_theme() { global $conf; if (empty($conf['mobile_theme'])) { return false; } if (isset($_GET['mobile'])) { $is_mobile_theme = get_boolean($_GET['mobile']); pwg_set_session_var('mobile_theme', $is_mobile_theme); } else { $is_mobile_theme = pwg_get_session_var('mobile_theme'); } if (is_null($is_mobile_theme)) { $is_mobile_theme = (get_device() == 'mobile'); pwg_set_session_var('mobile_theme', $is_mobile_theme); } return $is_mobile_theme; } /** * check url format */ function url_check_format($url) { if (version_compare(PHP_VERSION, '5.2.0') >= 0) { return filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED | FILTER_FLAG_HOST_REQUIRED)!==false; } else { // http://mathiasbynens.be/demo/url-regex @imme_emosol return (bool)preg_match('@^https?://(-\.)?([^\s/?\.#-]+\.?)+(/[^\s]*)?$@iS', $url); } } /** * check email format */ function email_check_format($mail_address) { if (version_compare(PHP_VERSION, '5.2.0') >= 0) { return filter_var($mail_address, FILTER_VALIDATE_EMAIL)!==false; } else { $atom = '[-a-z0-9!#$%&\'*+\\/=?^_`{|}~]'; // before arobase $domain = '([a-z0-9]([-a-z0-9]*[a-z0-9]+)?)'; // domain name $regex = '/^' . $atom . '+' . '(\.' . $atom . '+)*' . '@' . '(' . $domain . '{1,63}\.)+' . $domain . '{2,63}$/i'; return (bool)preg_match($regex, $mail_address); } } /** returns the number of available comments for the connected user */ function get_nb_available_comments() { global $user; if (!isset($user['nb_available_comments'])) { $where = array(); if ( !is_admin() ) $where[] = 'validated=\'true\''; $where[] = get_sql_condition_FandF ( array ( 'forbidden_categories' => 'category_id', 'visible_categories' => 'category_id', 'visible_images' => 'ic.image_id' ), '', true ); $query = ' SELECT COUNT(DISTINCT(com.id)) FROM '.IMAGE_CATEGORY_TABLE.' AS ic INNER JOIN '.COMMENTS_TABLE.' AS com ON ic.image_id = com.image_id WHERE '.implode(' AND ', $where); list($user['nb_available_comments']) = pwg_db_fetch_row(pwg_query($query)); single_update(USER_CACHE_TABLE, array('nb_available_comments'=>$user['nb_available_comments']), array('user_id'=>$user['id']) ); } return $user['nb_available_comments']; } ?>