users
[ class tree: users ] [ index: users ] [ all elements ]

Source for file RoleUser.php

Documentation is available at RoleUser.php

  1. <?php
  2. /**
  3.  * Lib for user administration, roles and permissions
  4.  * This lib uses pear so the constructor requieres
  5.  * a pear DB object
  6.  
  7.  * Copyright (c) 2004 bitweaver.org
  8.  * Copyright (c) 2003 tikwiki.org
  9.  * Copyright (c) 2002-2003, Luis Argerich, Garland Foster, Eduardo Polidor, et. al.
  10.  * All Rights Reserved. See below for details and a complete list of authors.
  11.  * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See http://www.gnu.org/copyleft/lesser.html for details
  12.  *
  13.  * @package users
  14.  */
  15.  
  16. /**
  17.  * required setup
  18.  */
  19. require_onceLIBERTY_PKG_PATH.'LibertyMime.php' );
  20. require_onceUSERS_PKG_PATH.'users_lib.php' );
  21.  
  22. define'AVATAR_TYPE_CENTRALIZED''c' );
  23. define'AVATAR_TYPE_USER_DB''u' );
  24. define'AVATAR_TYPE_LIBRARY''l' );
  25.  
  26. // Column sizes for users_users table
  27. define'REAL_NAME_COL_SIZE'64 );
  28.  
  29. define'BITUSER_CONTENT_TYPE_GUID''bituser' );
  30.  
  31. // some  definitions for helping with authentication
  32. define"USER_VALID");
  33. define"SERVER_ERROR"-);
  34. define"PASSWORD_INCORRECT"-);
  35. define"USER_NOT_FOUND"-);
  36. define"ACCOUNT_DISABLED"-);
  37.  
  38. /**
  39.  * Class that holds all information for a given user
  40.  *
  41.  * @author   spider <spider@steelsun.com>
  42.  * @package  users
  43.  * @subpackage  BitUser
  44.  */
  45. class BitUser extends LibertyMime {
  46.     var $mUserId;
  47.     var $mUsername;
  48.     var $mRoles;
  49.     var $mTicket;
  50.     var $mAuth;
  51.  
  52.     /**
  53.      * Constructor - will automatically load all relevant data if passed a user string
  54.      *
  55.      * @access public
  56.      * @author Christian Fowler <spider@viovio.com>
  57.      * @return returnString 
  58.      */
  59.     function BitUser$pUserId=NULL$pContentId=NULL {
  60.         parent::__construct();
  61.         $this->mContentTypeGuid = BITUSER_CONTENT_TYPE_GUID;
  62.         $this->registerContentType(
  63.             BITUSER_CONTENT_TYPE_GUIDarray(
  64.                 'content_type_guid'   => BITUSER_CONTENT_TYPE_GUID,
  65.                 'content_name'        => 'User Information',
  66.                 'content_name_plural' => 'User Information',
  67.                 'handler_class'       => 'BitUser',
  68.                 'handler_package'     => 'users',
  69.                 'handler_file'        => 'RoleUser.php',
  70.                 'maintainer_url'      => 'http://www.bitweaver.org'
  71.             )
  72.         );
  73.         $this->mUserId = @$this->verifyId$pUserId $pUserId NULL);
  74.         $this->mContentId = $pContentId;
  75.     }
  76.  
  77.     public function getCacheKey({
  78.         $siteCookie static::getSiteCookieName();
  79.         if$this->isRegistered(&& !empty$_COOKIE[$siteCookie) ) 
  80.             return $_COOKIE[$siteCookie];
  81.         else {
  82.             return ANONYMOUS_USER_ID;
  83.         }
  84.     }
  85.  
  86.     public static function isCacheableClass({
  87.         return false;
  88.     }
  89.  
  90.     /**
  91.      * Determines if a user object is cacheable. Out of paranoia, admin's are never cached.
  92.      * @return boolean if object can be cached
  93.      */
  94.     public function isCacheableObject({
  95.         return parent::isCacheableObject(&& !$this->isAdmin();
  96.     }
  97.  
  98.     /**
  99.      * Validate inbound sort_mode parameter
  100.      * @return array of fields which are valid sorts
  101.      */
  102.     public static function getSortModeFields({
  103.         $fields parent::getSortModeFields();
  104.         $fields['map_position';
  105.         return $fields;
  106.     }
  107.  
  108.     /**
  109.      * load - loads all settings & preferences for this user
  110.      *
  111.      * @param boolean $pFull Load additional user data like
  112.      * @param string $pUserName User login name
  113.      * @access public
  114.      * @author Chrstian Fowler <spider@steelsun.com>
  115.      * @return returnString 
  116.      */
  117.     function load$pFull=FALSE$pUserName=NULL {
  118.         global $gBitSystem;
  119.         $this->mInfo = NULL;
  120.         ifisset$this->mUserId ) ) {
  121.             $whereSql "WHERE uu.`user_id`=?";
  122.             $bindVars array$this->mUserId );
  123.         elseifisset$this->mContentId ) ) {
  124.             $whereSql "WHERE uu.`content_id`=?";
  125.             $bindVars array$this->mContentId );
  126.         elseif!empty$pUserName ) ) {
  127.             $whereSql "WHERE uu.`login`=?";
  128.             $bindVars array$pUserName );
  129.         }
  130.         ifisset$whereSql ) ) {
  131.             $fullSelect '';
  132.             $fullJoin '';
  133.             if$pFull {
  134.                 $fullSelect ' , lc.* ';
  135.                 $fullJoin " LEFT OUTER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON ( uu.`content_id`=lc.`content_id` )";
  136.                 $this->getServicesSql'content_load_sql_function'$fullSelect$fullJoin$whereSql$bindVars );
  137.             }
  138.             // uu.`user_id` AS `uu_user_id` is last and aliases to avoid possible column name collisions
  139.             $query "
  140.                 SELECT uu.*,
  141.                         lf_ava.`file_name` AS `avatar_file_name`,  la_ava.`attachment_id` AS `avatar_attachment_id`, lf_ava.`mime_type` AS `avatar_mime_type`,
  142.                         lf_por.`file_name` AS `portrait_file_name`, ta_por.`attachment_id` AS `portrait_attachment_id`, lf_por.`mime_type` AS `portrait_mime_type`,
  143.                         lf_logo.`file_name` AS `logo_file_name`, ta_logo.`attachment_id` AS `logo_attachment_id`, lf_logo.`mime_type` AS `logo_mime_type`
  144.                       $fullSelect, uu.`user_id` AS `uu_user_id`
  145.                 FROM `".BIT_DB_PREFIX."users_users` uu
  146.                     LEFT OUTER JOIN `".BIT_DB_PREFIX."liberty_attachments` la_ava ON ( uu.`avatar_attachment_id`=la_ava.`attachment_id` )
  147.                     LEFT OUTER JOIN `".BIT_DB_PREFIX."liberty_files` lf_ava ON ( lf_ava.`file_id`=la_ava.`foreign_id` )
  148.                     LEFT OUTER JOIN `".BIT_DB_PREFIX."liberty_attachments` ta_por ON ( uu.`portrait_attachment_id`=ta_por.`attachment_id` )
  149.                     LEFT OUTER JOIN `".BIT_DB_PREFIX."liberty_files` lf_por ON ( lf_por.`file_id`=ta_por.`foreign_id` )
  150.                     LEFT OUTER JOIN `".BIT_DB_PREFIX."liberty_attachments` ta_logo ON ( uu.`logo_attachment_id`=ta_logo.`attachment_id` )
  151.                     LEFT OUTER JOIN `".BIT_DB_PREFIX."liberty_files` lf_logo ON ( lf_logo.`file_id`=ta_logo.`foreign_id` )
  152.                     $fullJoin
  153.                 $whereSql";
  154.             if(( $result $this->mDb->query$query$bindVars )) && $result->numRows() ) {
  155.                 $this->mInfo = $result->fetchRow();
  156.                 $this->mInfo['user']          $this->mInfo['login'];
  157.                 $this->mInfo['valid']         @$this->verifyId$this->mInfo['uu_user_id');
  158.                 $this->mInfo['user_id']       $this->mInfo['uu_user_id'];
  159.                 $this->mInfo['is_registered'$this->isRegistered();
  160.                 foreacharray'portrait''avatar''logo' as $img {
  161.                     $this->mInfo[$img.'_path']   $this->getSourceFilearray'user_id'=>$this->getField'user_id' )'package'=>liberty_mime_get_storage_sub_dir_namearray'mime_type' => $this->getField$img.'_mime_type' )'name' =>  $this->getField$img.'_file_name' ) ) )'file_name' => basename$this->mInfo[$img.'_file_name')'sub_dir' =>  $this->getField$img.'_attachment_id' )'mime_type' => $this->getField$img.'_mime_type' ) ) );
  162.                     $this->mInfo[$img.'_url']    liberty_fetch_thumbnail_urlarray'source_file'=>$this->mInfo[$img.'_path']'size' => 'small''mime_image' => FALSE ));
  163.                 }
  164.  
  165.                 // break the real name into first and last name using the last space as the beginning of the last name
  166.                 // for people who really want to use first and last name fields
  167.                 ifpreg_match'/ /'$this->mInfo['real_name') ) {
  168.                     $this->mInfo['first_name'substr$this->mInfo['real_name']0strrpos($this->mInfo['real_name']' ') );
  169.                     $this->mInfo['last_name'substr$this->mInfo['real_name']strrpos($this->mInfo['real_name']' ')+);
  170.                 }else{
  171.                     // no spaces assign the real name to the first name
  172.                     $this->mInfo['first_name'$this->mInfo['real_name'];
  173.                 }
  174.  
  175.                 $this->mUserId    = $this->mInfo['uu_user_id'];
  176.                 $this->mContentId = $this->mInfo['content_id'];
  177.                 $this->mUsername  = $this->mInfo['login'];
  178.                 // a few random security conscious unset's - SPIDER
  179.                 unset$this->mInfo['user_password');
  180.                 unset$this->mInfo['hash');
  181.  
  182.                 $this->loadPreferences();
  183.                 // Load attachments
  184.                 LibertyMime::load();
  185.                 if$this->getPreference'users_country' ) ) {
  186.                     $this->setPreference'flag'$this->getPreference'users_country' ) );
  187.                     $this->setPreference'users_country'str_replace'_'' '$this->getPreference'users_country' ) ) );
  188.                 }
  189.                 if$pFull {
  190.                     $this->mInfo['real_name'trim$this->mInfo['real_name');
  191.                     $this->mInfo['display_name'(
  192.                         !empty$this->mInfo['real_name'$this->mInfo['real_name':
  193.                         !empty$this->mUsername$this->mUsername :
  194.                         !empty$this->mInfo['email'substr$this->mInfo['email']0strpos$this->mInfo['email'],'@' )) :
  195.                         $this->mUserId )))
  196.                     );
  197.                     //print("displayName: ".$this->mInfo['display_name']);
  198.                     $this->defaults();
  199.                     $this->mInfo['publicEmail'scramble_email$this->mInfo['email']$this->getPreference'users_email_display' $this->getPreference'users_email_display' NULL ) );
  200.                 }
  201.                 $this->mTicket = substrmd5session_id($this->mUserId )020 );
  202.             else {
  203.                 $this->mUserId = NULL;
  204.             }
  205.         }
  206.         if!$gBitSystem->isFeatureActive'i18n_browser_languages' ) ) {
  207.             global $gBitLanguage$gBitUser;
  208.             //change language only if if logged user is this user
  209.             //otherwise it's just logged user (lang A) watching other user's page (lang B) and don't change
  210.             if$this->mUserId && $this->mUserId != ANONYMOUS_USER_ID && $gBitUser === $this{
  211.                 $gBitLanguage->mLanguage $this->getPreference'bitlanguage'$gBitLanguage->mLanguage );
  212.             elseifisset$_SESSION['bitlanguage')) {
  213.                 // users not logged that change the preference
  214.                 $gBitLanguage->mLanguage $_SESSION['bitlanguage'];
  215.             }
  216.         }
  217.         return$this->isValid() );
  218.     }
  219.  
  220.     /**
  221.      * defaults set a default set of preferences in mPrefs for new users
  222.      *
  223.      * @access public
  224.      * @return void 
  225.      */
  226.     function defaults({
  227.         global $gBitSystem$gBitThemes$gBitLanguage;
  228.         if!$this->getPreference'users_information' ) ) {
  229.             $this->setPreference'users_information''public' );
  230.         }
  231.         if!$this->getPreference'messages_allow_messages' ) ) {
  232.             $this->setPreference'messages_allow_messages''y' );
  233.         }
  234.         if!$this->getPreference'site_display_utc' ) ) {
  235.             $this->setPreference'site_display_utc''Local' );
  236.         }
  237. /*
  238.  * site_display_timezone is not used for 'Local' time display so daylight saving offset is not available
  239.  * both of these should pick up the 'site default' values
  240.         if( !$this->getPreference( 'site_display_timezone' ) ) {
  241.             $this->setPreference( 'site_display_timezone', 'UTC' );
  242.         }
  243.  */
  244.          if!$this->getPreference'bitlanguage' ) ) {
  245.             $this->setPreference'bitlanguage'$gBitLanguage->mLanguage );
  246.         }
  247.         if!$this->getPreference'theme' ) ) {
  248.             $this->setPreference'theme'$gBitThemes->getStyle() );
  249.         }
  250.     }
  251.  
  252.     /**
  253.      * verify store hash
  254.      *
  255.      * @param array $pParamHash Data to be verified
  256.      * @access public
  257.      * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  258.      */
  259.     function verify&$pParamHash {
  260.         global $gBitSystem;
  261.  
  262.         trim_array$pParamHash );
  263.  
  264.         // DO NOT REMOVE - to allow specific setting of the user_id during the first store.
  265.         // used by ROOT_USER_ID or ANONYMOUS_USER_ID during install.
  266.         if@$this->verifyId$pParamHash['user_id') ) {
  267.             $pParamHash['user_store']['user_id'$pParamHash['user_id'];
  268.         }
  269.         // require login
  270.         if!empty$pParamHash['login'&& $pParamHash['login'!= $this->getField'login' ) ) {
  271.             $pParamHash['login'strip_tags($pParamHash['login']);
  272.             if$this->userExistsarray'login' => $pParamHash['login') ) ) {
  273.                 $this->mErrors['login''The username "'.$pParamHash['login'].'" is already in use';
  274.             elseifpreg_match'/[^A-Za-z0-9_.-]/'$pParamHash["login") ) {
  275.                 $this->mErrors['login'tra"Your username can only contain numbers, characters, underscores and hyphens." );
  276.             else {
  277.                 // LOWER CASE all logins
  278.                 $pParamHash['login'strtolower$pParamHash['login');
  279.                 $pParamHash['user_store']['login'$pParamHash['login'];
  280.             }
  281.         }
  282.         // some people really like using first and last names
  283.         // push them into real_name
  284.         if!empty$pParamHash['first_name') ) {
  285.             $pParamHash['real_name'$pParamHash['first_name'];
  286.         }
  287.         if!empty$pParamHash['last_name') ) {
  288.             $pParamHash['real_name'!empty$pParamHash['real_name')?$pParamHash['real_name']." ":'';
  289.             $pParamHash['real_name'.= $pParamHash['last_name'];
  290.         }
  291.         // real_name
  292.         if!empty$pParamHash['real_name') ) {
  293.             $pParamHash['user_store']['real_name'substrstrip_tags($pParamHash['real_name'])064 );
  294.         }
  295.         // require email
  296.         if!empty$pParamHash['email') ) {
  297.             // LOWER CASE all emails
  298.             $pParamHash['email'strtolower$pParamHash['email');
  299.             if$emailResult $this->verifyEmail$pParamHash['email'$this->mErrors) ) {
  300.                 $pParamHash['verified_email'($emailResult === true);
  301.             }
  302.         }
  303.         // check some new user requirements
  304.         if!$this->isRegistered() ) {
  305.             ifempty$pParamHash['login') ) {
  306.                 // choose a login based on the username in the email
  307.                 ifempty($pParamHash['email']) ){
  308.                     // obviously if they didnt enter an email address we cant help them out
  309.                     $this->mErrors['email'tra'You must enter your email address' );
  310.                 }else{
  311.                     $loginBase preg_replace'/[^A-Za-z0-9_]/'''substr$pParamHash['email']0strpos$pParamHash['email']'@' ) ) );
  312.                     $login $loginBase;
  313.                     do {
  314.                         if$loginTaken $this->userExistsarray'login' => $login ) ) ) {
  315.                             $login $loginBase.rand(100,999);
  316.                         }
  317.                     while$loginTaken );
  318.                     $pParamHash['login'$login;
  319.                 }
  320.             }
  321.             ifempty$pParamHash['registration_date') ) {
  322.                 $pParamHash['registration_date'date"U" );
  323.             }
  324.             $pParamHash['user_store']['registration_date'$pParamHash['registration_date'];
  325.  
  326.             if!empty$pParamHash['email'&& empty($this->mErrors['email']) ) {
  327.                 $pParamHash['user_store']['email'substr$pParamHash['email']0200 ;
  328.             }elseifempty($pParamHash['email']) ){
  329.                 $this->mErrors['email'tra'You must enter your email address' );
  330.             }
  331.  
  332.             if$gBitSystem->isFeatureActive'users_validate_user' ) ) {
  333.                 $pParamHash['user_store']['provpass'md5(BitSystem::genPass());
  334.                 $pParamHash['pass_due'0;
  335.             elseifempty$pParamHash['password') ) {
  336.                 $this->mErrors['password'tra'Your password should be at least '.$gBitSystem->getConfig'users_min_pass_length').' characters long' );
  337.             }
  338.         elseif$this->isValid() ) {
  339.             // Prevent losing user info on save
  340.             ifempty$pParamHash['edit') ) {
  341.                 $pParamHash['edit'$this->mInfo['data'];
  342.             }
  343.         }
  344.  
  345.         ifisset$pParamHash['password') ) {
  346.             ifisset$pParamHash["password2"&& $pParamHash["password"!= $pParamHash["password2"{
  347.                 $passwordErrors['password2'tra("The passwords didn't match");
  348.             }
  349.             if( ( !$this->isValid(|| isset$pParamHash['password') ) && $error $this->verifyPasswordFormat$pParamHash['password') ) {
  350.                 $passwordErrors['password'$error;
  351.             }
  352.             if!empty$passwordErrors ) ) {
  353.                 $this->mErrors = array_merge$this->mErrors,$passwordErrors );
  354.             else {
  355.                 // Generate a unique hash
  356.                 //$pParamHash['user_store']['hash'] = md5( strtolower( (!empty($pParamHash['login'])?$pParamHash['login']:'') ).$pPassword.$pParamHash['email'] );
  357.                 $pParamHash['user_store']['hash'md5$pParamHash['password');
  358.                 $now $gBitSystem->getUTCTime();
  359.                 // set password due date
  360.                 // if no pass_due and no user_pass_due value user will never have to update the password
  361.                 ifempty$pParamHash['pass_due'&& $gBitSystem->getConfig('users_pass_due') ) {
  362.                     // renew password according to config value
  363.                     $pParamHash['user_store']['pass_due'$now (60 60 24 $gBitSystem->getConfig('users_pass_due') );
  364.                 elseif!empty$pParamHash['pass_due') ) {
  365.                     // renew password only next half year ;)
  366.                     $pParamHash['user_store']['pass_due'$now (60 60 24 $pParamHash['pass_due']);
  367.                 }
  368.                 if$gBitSystem->isFeatureActive'users_clear_passwords' || !empty$pParamHash['user_store']['provpass') ) {
  369.                     $pParamHash['user_store']['user_password'$pParamHash['password'];
  370.                 }
  371.             }
  372.         }
  373.  
  374.         // if we have an error we get them all by checking parent classes for additional errors
  375.         ifcount$this->mErrors ){
  376.             parent::verify$pParamHash );
  377.         }
  378.  
  379.         return count($this->mErrors== );
  380.     }
  381.  
  382.     /**
  383.      * answerCaptcha
  384.      *
  385.      * Determine if the submitted answer for the captcha is valid
  386.      */
  387.     function answerCaptcha$pParamHash {
  388.         global $gBitSystem;
  389.         // require catpcha
  390.         // novalidation is set to yes if a user confirms his email is correct after tiki fails to validate it
  391.         if$gBitSystem->isFeatureActive'users_random_number_reg' ) ) {
  392.             if( ( empty$pParamHash['novalidation'|| $pParamHash['novalidation'!= 'yes' )
  393.                 &&!isset$_SESSION['captcha'|| $_SESSION['captcha'!= md5$pParamHash['captcha') ) )
  394.             {
  395.                 $this->mErrors['captcha'"Wrong Answer";
  396.             }
  397.         }
  398.  
  399.         if$gBitSystem->isFeatureActive'users_register_recaptcha' && (empty$pParamHash['novalidation'|| $pParamHash['novalidation'!= 'yes') ) {
  400.             require_onceUSERS_PKG_PATH.'classes/recaptchalib.php' );
  401.             if!empty$pParamHash["recaptcha_challenge_field"&& !empty$pParamHash["recaptcha_response_field") ) {
  402.                 $resp recaptcha_check_answer $gBitSystem->getConfig'users_register_recaptcha_private_key' )$_SERVER["REMOTE_ADDR"]$pParamHash["recaptcha_challenge_field"]$pParamHash["recaptcha_response_field");
  403.                 if!$resp->is_valid {
  404.                     $this->mErrors['recaptcha'$resp->error;
  405.                 }
  406.             else {
  407.                 $this->mErrors['recaptcha''Wrong Answer';
  408.             }
  409.         }
  410.  
  411.         if$gBitSystem->isFeatureActive'users_register_smcaptcha' && (empty$pParamHash['novalidation'|| $pParamHash['novalidation'!= 'yes') ) {
  412.             require_onceUSERS_PKG_PATH.'classes/solvemedialib.php' );
  413.             if!empty$pParamHash['adcopy_challenge'&& !empty$pParamHash['adcopy_response') ) {
  414.                 $solvemediaResponse solvemedia_check_answer($gBitSystem->getConfig'users_register_smcaptcha_v_key' )$_SERVER["REMOTE_ADDR"]$pParamHash["adcopy_challenge"]$pParamHash["adcopy_response"]$gBitSystem->getConfig'users_register_smcaptcha_h_key' ) );
  415.                 if!$solvemediaResponse->is_valid {
  416.                     $this->mErrors['smcaptcha'$solvemediaResponse->error;
  417.                 }
  418.             else {
  419.                 $this->mErrors['smcaptcha''Wrong Answer';
  420.             }
  421.         }
  422.  
  423.         return count($this->mErrors== );
  424.     }
  425.  
  426.     /**
  427.      * preRegisterVerify
  428.      *
  429.      * A collection of values to verify before a user can register
  430.      * Separated from BitUser::verify so that import verification can
  431.      * be processed with less rigor than user submitted requests
  432.      */
  433.     function preRegisterVerify&$pParamHash {
  434.         global $gBitSystem;
  435.  
  436.         $this->answerCaptcha$pParamHash );
  437.  
  438.         // require passcode
  439.         if$gBitSystem->isFeatureActive'users_register_require_passcode' ) ) {
  440.             if$pParamHash["passcode"!= $gBitSystem->getConfig"users_register_passcode",md5$this->genPass() ) ) ) {
  441.                 $this->mErrors['passcode''Wrong passcode! You need to know the passcode to register at this site';
  442.             }
  443.         }
  444.         return count($this->mErrors== );
  445.     }
  446.  
  447.     /**
  448.      * verifyPasswordFormat
  449.      *
  450.      * @param array $pPassword 
  451.      * @param array $pPassword2 
  452.      * @access public
  453.      * @return FALSE on success, Error string on failure
  454.      */
  455.     function verifyPasswordFormat$pPassword$pPassword2=NULL {
  456.         global $gBitSystem;
  457.  
  458.         $minPassword $gBitSystem->getConfig'users_min_pass_length');
  459.         ifstrlen$pPassword $minPassword {
  460.             return tra'Your password should be at least '.$minPassword.' characters long' ));
  461.         }
  462.         if!empty$pPassword2 && $pPassword != $pPassword2 {
  463.             returntra'The passwords do not match' ));
  464.         }
  465.         if$gBitSystem->isFeatureActive'users_pass_chr_num' && !preg_match_all"/[0-9]+/",$pPassword,$foo || !preg_match_all"/[A-Za-z]+/",$pPassword,$foo ))) {
  466.             return tra'Password must contain both letters and numbers' ));
  467.         }
  468.  
  469.         return FALSE;
  470.     }
  471.  
  472.     /**
  473.      * getSmtpResponse
  474.      *
  475.      * @param array $pConnect 
  476.      * @access public
  477.      * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  478.      */
  479.     function getSmtpResponse&$pConnect {
  480.         $out "";
  481.         while{
  482.             $work fgets$pConnect1024 );
  483.             $out .= $work;
  484.             if!preg_match'/^\d\d\d-/',$work )) {
  485.                 break;
  486.             }
  487.         }
  488.         return $out;
  489.     }
  490.  
  491.     /**
  492.      * verifyEmail
  493.      *
  494.      * @param array $pEmail 
  495.      * @return TRUE on success, FALSE on failure, or -1 if verifyMX had a connection failure - mErrors will contain reason for failure
  496.      */
  497.     public function verifyEmail$pEmail &$pErrors {
  498.         global $gBitSystem;
  499.  
  500.         // check for existing user first, so root@localhost doesn't get attempted to re-register
  501.         if!empty$this && is_object$this && $this->userExistsarray'email' => $pEmail ) ) ) {
  502.             $pErrors['email''The email address "'.$pEmail.'" has already been registered.';
  503.         // during install we have some <user>@localhost as email address. we won't cause problems on those
  504.         elseif$pEmail == 'root@localhost' || $pEmail == 'guest@localhost' {
  505.             // nothing to do
  506.         elseif!validate_email_syntax$pEmail ) ) {
  507.             $pErrors['email''The email address "'.$pEmail.'" is invalid.';
  508.         elseif$gBitSystem->isFeatureActive'users_validate_email' ) ) {
  509.             $mxErrors;
  510.             $ret $this->verifyMX$pEmail$mxErrors ;
  511.             if ($ret === false)    {
  512.                 bit_error_log('INVALID EMAIL : '.$pEmail.' by '$_SERVER['REMOTE_ADDR'.' for '$mxErrors['email']);
  513.                 $pErrors array_merge$pErrors$mxErrors );
  514.             }
  515.         }
  516.  
  517.         if!isset$ret ) ) {
  518.             $ret count$pErrors == )  ;
  519.         }
  520.  
  521.         return $ret;
  522.     }
  523.  
  524.     /**
  525.      * verifyAnonEmail
  526.      *
  527.      * @param array $pEmail 
  528.      * @return TRUE on success, FALSE on failure, or -1 if verifyMX had a connection failure - mErrors will contain reason for failure
  529.      */
  530.     public static function verifyAnonEmail$pEmail &$pErrors {
  531.         global $gBitSystem;
  532.  
  533.         // check for existing user first, so root@localhost doesn't get attempted to re-register
  534.         if$pEmail == 'root@localhost' || $pEmail == 'guest@localhost' {
  535.             // nothing to do
  536.         elseif!validate_email_syntax$pEmail ) ) {
  537.             $pErrors['email''The email address "'.$pEmail.'" is invalid.';
  538.         }
  539.  
  540.         if!isset$ret ) ) {
  541.             $ret count$pErrors == )  ;
  542.         }
  543.  
  544.         return $ret;
  545.     }
  546.  
  547.     /**
  548.      * verifyMX
  549.      *
  550.      * @param array $pEmail 
  551.      * @param array $pValidate 
  552.      * @access public
  553.      * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  554.      */
  555.     function verifyMX$pEmail&$pErrors {
  556.  
  557.         global $gBitSystem$gDebug;
  558.  
  559.         $HTTP_HOST=$_SERVER['SERVER_NAME'];
  560.         $ret false;
  561.  
  562.         ifvalidate_email_syntax$pEmail ) ){
  563.             list $Username$domain preg_split ("/@/",$pEmail);
  564.             //checkdnsrr will check to see if there are any MX records for the domain
  565.             if!is_windows(and checkdnsrr $domain"MX" ) )  {
  566.                 bitdebug"Confirmation : MX record for {$domain} exists.);
  567.  
  568.                 $MXWeights array();
  569.  
  570.                 getmxrr $domain$MXHost$MXWeights );
  571.                 $hosts array();
  572.  
  573.                 //create an array that combines the MXWeights with their associated hosts
  574.                 for$i 0$i count$MXHost )$i++ {
  575.                     $hosts[$MXHost[$i]] $MXWeights[$i];
  576.                 }
  577.  
  578.                 //sorts the hosts by weight
  579.                 asort($hosts);
  580.  
  581.                 if!empty($hosts)) {    //hosts shouldn't be empty here, since we passed the checkdnsrr check, but the server COULD have died between the first and second check.
  582.                     $Connect '' ;
  583.                     foreach ($hosts as $host=>$priority){
  584.  
  585.                         $Connect @fsockopen $host25$errNo$errStr10 )// 10 second timeout to open each MX server, seems adequate to me, increase as necessary
  586.                         // Success in fsockopen
  587.  
  588.                         if$Connect {
  589.                             bitdebug"Connection succeeded to {$host} SMTP.);
  590.  
  591.  
  592.                             stream_set_timeout$Connect30 );
  593.                             $out $this->getSmtpResponse$Connect );
  594.  
  595.                             // Judgment is that a service preparing to begin a transaction will send a 220 string after a succesful handshake
  596.                             ifpreg_match "/^220/"$out ) ) {
  597.                                 // Inform client's reaching to server who connect.
  598.                                 if$gBitSystem->hasValidSenderEmail() ) {
  599.                                     $senderEmail $gBitSystem->getConfig'site_sender_email' );
  600.                                     fputs$Connect"HELO $HTTP_HOST\r\n);
  601.                                     bitdebug"Run : HELO $HTTP_HOST);
  602.                                     // Receive server's answering cord.
  603.                                     $out $this->getSmtpResponse$Connect );
  604.  
  605.                                     // Inform sender's address to server.
  606.                                     fputs $Connect"MAIL FROM: <{$senderEmail}>\r\n);
  607.                                     bitdebug"Run : MAIL FROM: &lt;{$senderEmail}&gt;);
  608.                                     // Receive server's answering cord.
  609.                                     $from $this->getSmtpResponse$Connect );
  610.  
  611.                                     // Inform listener's address to server.
  612.                                     fputs $Connect"RCPT TO: <{$pEmail}>\r\n);
  613.                                     bitdebug"Run : RCPT TO: &lt;{$pEmail}&gt;);
  614.                                     // Receive server's answering cord.
  615.                                     $to $this->getSmtpResponse$Connect );
  616.  
  617.                                     // Finish connection.
  618.                                     fputs$Connect"QUIT\r\n" );
  619.                                     bitdebug"Run : QUIT" );
  620.                                     fclose$Connect );
  621.  
  622.                                     //Checks if we received a 250 OK from the server. If we did not, the server is telling us that this address is not a valid mailbox.
  623.                                     if!preg_match "/^250/"$from || !preg_match "/^250/"$to && !preg_match"/Please use your ISP relay/"$to ))) {
  624.                                         $pErrors['email']   $pEmail." is not recognized by the mail server. Try double checking the address for typos." ;
  625.                                         bit_error_log("INVALID EMAIL : ".$pEmail." SMTP FROM : ".$from." SMTP TO: ".$to);
  626.                                         $ret false;
  627.                                         break//break out of foreach and fall through to the end of function
  628.                                     }else{
  629.                                         $ret true;//address has been verified by the server, no more checking necessary
  630.                                         break;
  631.                                     }
  632.                                 }
  633.                             elseifpreg_match "/^420/"$out ) ) {
  634.                                 // Yahoo has a bad, bad habit of issuing 420's
  635.                                 bit_error_log("UNKNOWN EMAIL : ".$pEmail." SMTP response: ".$out);
  636.                                 $ret true;
  637.                             else {
  638.                                 $pErrors['email''Connection rejected by MX server';
  639.                                 bit_error_log("INVALID EMAIL : ".$pEmail." SMTP response: ".$out);
  640.                                 $ret false;
  641.                             }
  642.                         else {
  643.                             //fsockopen failed
  644.                             if(!$gBitSystem->getConfig('users_validate_email_role'))//will ONLY stuff mErrors if you have not set a default role for verifiable emails, otherwise this is not a game breaking case
  645.                                 $pErrors['email'"One or more mail servers not responding";
  646.                             }
  647.                             $ret = -1//-1 implies ambiguity, MX servers found, but unable to be reached.
  648.                         }
  649.                     }
  650.                 }else{
  651.                     $pErrors['email'"Mail server not found";
  652.                     $ret false;
  653.                 }
  654.             else {
  655.                 $pErrors['email'"Mail server not found";
  656.                 $ret false;
  657.             }
  658.         else {
  659.             $pErrors['email'"Invalid email syntax";
  660.             $ret false;
  661.         }
  662.         return $ret;
  663.     }
  664.  
  665.     /**
  666.      * register - will handle everything necessary for registering a user and sending appropriate emails, etc.
  667.      *
  668.      * @access public
  669.      * @author Christian Fowler<spider@viovio.com>
  670.      * @return TRUE on success, FALSE on failure
  671.      */
  672.     function register&$pParamHash$pNotifyRegistrant=TRUE {
  673.         global $notificationlib$gBitSmarty$gBitSystem;
  674.         $ret FALSE;
  675.         if!empty$_FILES['user_portrait_file'&& empty$_FILES['user_avatar_file') ) {
  676.             $pParamHash['user_auto_avatar'TRUE;
  677.         }
  678.         if$this->verify$pParamHash )) {
  679.             for$i 0$i BaseAuth::getAuthMethodCount()$i++ {
  680.                 $instance BaseAuth::init$i );
  681.                 if$instance && $instance->canManageAuth() ) {
  682.                     if$userId $instance->createUser$pParamHash )) {
  683.                         $this->mUserId = $userId;
  684.                         break;
  685.                     else {
  686.                         $this->mErrors = array_merge$this->mErrors$instance->mErrors );
  687.                         return FALSE;
  688.                     }
  689.                 }
  690.             }
  691.  
  692.             if!empty$pParamHash['verified_email'&& $pParamHash['verified_email'&& $gBitSystem->getConfig('users_validate_email_role') ) {
  693.                 RolePermUser::addUserToRole$this->mUserId$gBitSystem->getConfig('users_validate_email_role') );
  694.             }
  695.  
  696.             $this->mLogs['register''New user registered.';
  697.             $ret TRUE;
  698.  
  699.             $this->loadFALSE$pParamHash['login');
  700.  
  701.             require_onceKERNEL_PKG_PATH.'notification_lib.php' );
  702.             $notificationlib->post_new_user_event$pParamHash['login');
  703.  
  704.             // set local time zone as default when registering
  705.             $this->storePreference'site_display_utc''Local' );
  706.  
  707.             if!empty$_REQUEST['CUSTOM') ) {
  708.                 foreach$_REQUEST['CUSTOM'as $field=>$value {
  709.                     $this->storePreference$field$value );
  710.                 }
  711.             }
  712.  
  713.             // Handle optional user preferences that may be collected during registration
  714.             if!empty$pParamHash['prefs') ) {
  715.                 foreacharray_keys$pParamHash['prefs'as $key {
  716.                     $this->storePreference$key$pParamHash['prefs'][$key);
  717.                 }
  718.             }
  719.  
  720.             // Send notification
  721.             if$pNotifyRegistrant {
  722.                 $siteName $gBitSystem->getConfig('site_title'$_SERVER['HTTP_HOST');
  723.                 $gBitSmarty->assign'siteName',$_SERVER["SERVER_NAME");
  724.                 $gBitSmarty->assign'mail_site',$_SERVER["SERVER_NAME");
  725.                 $gBitSmarty->assign'mail_user',$pParamHash['login');
  726.                 if$gBitSystem->isFeatureActive'users_validate_user' ) ) {
  727.                     // $apass = addslashes(substr(md5($gBitSystem->genPass()),0,25));
  728.                     $apass $pParamHash['user_store']['provpass'];
  729.                     $foo  parse_url$_SERVER["REQUEST_URI");
  730.                     $foo1 str_replace"register""confirm"$foo["path");
  731.                     $machine httpPrefix().$foo1;
  732.  
  733.                     // Send the mail
  734.                     $gBitSmarty->assign'msg',tra'You will receive an email with information to login for the first time into this site' ));
  735.                     $gBitSmarty->assign'mail_machine',$machine );
  736.                     $gBitSmarty->assign'mailUserId',$this->mUserId );
  737.                     $gBitSmarty->assign'mailProvPass',$apass );
  738.                     $mail_data $gBitSmarty->fetch'bitpackage:users/user_validation_mail.tpl' );
  739.                     mail$pParamHash["email"]$siteName.' - '.tra'Your registration information' )$mail_data"From: ".$gBitSystem->getConfig('site_sender_email')."\nContent-type: text/plain;charset=utf-8\n" );
  740.                     $gBitSmarty->assign'showmsg''y' );
  741.  
  742.                     $this->mLogs['confirm''Validation email sent.';
  743.                 elseif$gBitSystem->isFeatureActive'send_welcome_email' ) ) {
  744.                     // Send the welcome mail
  745.                     $gBitSmarty->assign'mailPassword',$pParamHash['password');
  746.                     $gBitSmarty->assign'mailEmail',$pParamHash['email');
  747.                     $mail_data $gBitSmarty->fetch'bitpackage:users/welcome_mail.tpl' );
  748.                     mail$pParamHash["email"]tra'Welcome to' ).' '.$siteName$mail_data"From: ".$gBitSystem->getConfig'site_sender_email' )."\nContent-type: text/plain;charset=utf-8\n" );
  749.  
  750.                     $this->mLogs['welcome''Welcome email sent.';
  751.                 }
  752.             }
  753.             $logHash['action_log']['title'$pParamHash['login'];
  754.             $this->storeActionLog$logHash );
  755.         }
  756.         return$ret );
  757.     }
  758.  
  759.     /**
  760.      * verifyCaptcha
  761.      *
  762.      * @param array $pCaptcha 
  763.      * @access public
  764.      * @return TRUE on success, FALSE on failure
  765.      */
  766.     function verifyCaptcha$pCaptcha NULL {
  767.         if$this->hasPermission'p_users_bypass_captcha' || !empty$_SESSION['captcha_verified'&& $_SESSION['captcha_verified'=== TRUE ) ) {
  768.             return TRUE;
  769.         else {
  770.             ifempty$pCaptcha || empty$_SESSION['captcha'|| $_SESSION['captcha'!= md5$pCaptcha ) ) {
  771.                 return FALSE;
  772.             else {
  773.                 $_SESSION['captcha_verified'TRUE;
  774.                 return TRUE;
  775.             }
  776.         }
  777.     }
  778.  
  779.  
  780.     /**
  781.      * store
  782.      *
  783.      * @param array $pParamHash 
  784.      * @access public
  785.      * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  786.      */
  787.     function store&$pParamHash {
  788.         if$this->verify$pParamHash ) ) {
  789.             $this->mDb->StartTrans();
  790.             $pParamHash['content_type_guid'BITUSER_CONTENT_TYPE_GUID;
  791.  
  792.             if!empty$pParamHash['user_store'&& count$pParamHash['user_store') ) {
  793.                 if$this->isValid() ) {
  794.                     $userId array "user_id" => $this->mUserId );
  795.                     $result $this->mDb->associateUpdateBIT_DB_PREFIX.'users_users'$pParamHash['user_store']$userId );
  796.                 else {
  797.                     ifempty$pParamHash['user_store']['user_id') ) {
  798.                         $pParamHash['user_store']['user_id'$this->mDb->GenID'users_users_user_id_seq' );
  799.                     }
  800.                     $this->mUserId = $pParamHash['user_store']['user_id'];
  801.                     $result $this->mDb->associateInsertBIT_DB_PREFIX.'users_users'$pParamHash['user_store');
  802.                 }
  803.             }
  804.  
  805.             // Prevent liberty from assuming ANONYMOUS_USER_ID while storing
  806.             $pParamHash['user_id'$this->mUserId;
  807.             // Don't let LA snarf these now so we can do extra things.
  808.             $pParamHash['_files_override'array();
  809.             ifLibertyMime::store$pParamHash ) ) {
  810.  
  811.                 ifempty$this->mInfo['content_id'|| ($pParamHash['content_id'!= $this->mInfo['content_id']) ) {
  812.                     $query "UPDATE `".BIT_DB_PREFIX."users_users` SET `content_id`=? WHERE `user_id`=?";
  813.                     $result $this->mDb->query$queryarray$pParamHash['content_id']$this->mUserId ) );
  814.                     $this->mInfo['content_id'$pParamHash['content_id'];
  815.                 }
  816.             }
  817.  
  818.             $this->mDb->CompleteTrans();
  819.  
  820.             $this->loadTRUE );
  821.         }
  822.         returncount$this->mErrors == );
  823.     }
  824.  
  825.     /**
  826.      * Imports a user record from csv file
  827.      * This is a admin specific function
  828.      *
  829.      * @param $pParamHash an array with user data
  830.      * @return TRUE if import succeed
  831.      ***/
  832.     function importUser&$pParamHash {
  833.         global $gBitUser;
  834.  
  835.         if$gBitUser->hasPermission'p_users_admin' ) ) {
  836.             return FALSE;
  837.         }
  838.         if$this->verifyUserImport$pParamHash ) ) {
  839.             $this->mDb->StartTrans();
  840.             $pParamHash['content_type_guid'BITUSER_CONTENT_TYPE_GUID;
  841.             if!empty$pParamHash['user_store'&& count$pParamHash['user_store') ) {
  842.                 // lookup and asign the default role for user
  843.                 $defaultRoles RolePermUser::getDefaultRole();
  844.                 if!empty$defaultRoles ) ) {
  845.                     $pParamHash['user_store']['default_role_id'key$defaultRoles );
  846.                 }
  847.                 if$this->isValid() ) {
  848.                     $userId array "user_id" => $this->mUserId );
  849.                     $result $this->mDb->associateUpdateBIT_DB_PREFIX.'users_users'$pParamHash['user_store']$userId );
  850.                 else {
  851.                     ifempty$pParamHash['user_store']['user_id') ) {
  852.                         $pParamHash['user_store']['user_id'$this->mDb->GenID'users_users_user_id_seq' );
  853.                     }
  854.                     $this->mUserId = $pParamHash['user_store']['user_id'];
  855.                     $result $this->mDb->associateInsertBIT_DB_PREFIX.'users_users'$pParamHash['user_store');
  856.                 }
  857.                 // make sure user is added into the default role map
  858.                 if!empty$pParamHash['user_store']['default_role_id') ) {
  859.                     RolePermUser::addUserToRole$pParamHash['user_store']['user_id'],$pParamHash['user_store']['default_role_id');
  860.                 }
  861.  
  862.             }
  863.             // Prevent liberty from assuming ANONYMOUS_USER_ID while storing
  864.             $pParamHash['user_id'$this->mUserId;
  865.             ifLibertyContent::store$pParamHash )) {
  866.                 ifempty$this->mInfo['content_id'|| $pParamHash['content_id'!= $this->mInfo['content_id')  {
  867.                     $query "UPDATE `".BIT_DB_PREFIX."users_users` SET `content_id`=? WHERE `user_id`=?";
  868.                     $result $this->mDb->query$queryarray$pParamHash['content_id']$this->mUserId ) );
  869.                     $this->mInfo['content_id'$pParamHash['content_id'];
  870.                 }
  871.             }
  872.  
  873.             $this->mDb->CompleteTrans();
  874.  
  875.             // store any uploaded images
  876.             $this->storeImages$pParamHash );
  877.  
  878.             $this->loadTRUE );
  879.         }
  880.         returncount$this->mErrors == );
  881.     }
  882.  
  883.     /**
  884.      * Verify and validate the data when
  885.      * importing a user record from csv file
  886.      * This is a admin specific function
  887.      *
  888.      * @param $pParamHash an array with user data
  889.      * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  890.      ***/
  891.     function verifyUserImport&$pParamHash {
  892.         global $gBitSystem$gBitUser;
  893.  
  894.         if$gBitUser->hasPermission'p_users_admin' ) ) {
  895.             return FALSE;
  896.         }
  897.  
  898.         trim_array$pParamHash );
  899.  
  900.         // perhaps someone is importing users and *knows* what they are doing
  901.         if@$this->verifyId$pParamHash['user_id') ) {
  902.             // only import user_id if it doesn't exist or overwrite is set.
  903.             if!$this->userExistsarray'user_id' => $pParamHash['user_id') ) || !empty$_REQUEST['overwrite') ) {
  904.                 $pParamHash['user_store']['user_id'$pParamHash['user_id'];
  905.             else {
  906.                 unset$pParamHash['user_id');
  907.             }
  908.         }
  909.         if!empty$pParamHash['login') ) {
  910.             $ret $this->userExistsarray'login' => $pParamHash['login') );
  911.             if!empty$ret ) ) {
  912.                 // On batch import admin can overwrite existing user, so don't error if set
  913.                 // however, prevent overwrite of a mix of user records
  914.                 if!empty$_REQUEST['overwrite'&& (!isset($pParamHash['user_store']['user_id']|| $pParamHash['user_store']['user_id'== $ret ) ) {
  915.                     $pParamHash['user_id'$ret;
  916.                     $pParamHash['user_store']['user_id'$pParamHash['user_id'];
  917.                 else {
  918.                     $this->mErrors['login''The username "'.$pParamHash['login'].'" is already in use';
  919.                 }
  920.             elseifpreg_match'/[^A-Za-z0-9_.-]/'$pParamHash["login") ) {
  921.                 $this->mErrors['login'tra"Your username can only contain numbers, characters, underscores and hyphens." );
  922.             }
  923.  
  924.             if!isset($this->mErrors['login']) ) {
  925.                 // LOWER CASE all logins
  926.                 $pParamHash['login'strtolower($pParamHash['login']);
  927.                 $pParamHash['user_store']['login'$pParamHash['login'];
  928.             }
  929.         else {
  930.             $this->mErrors['login''Value for username is missing';
  931.         }
  932.         if!empty$pParamHash['real_name') ) {
  933.             $pParamHash['user_store']['real_name'substr$pParamHash['real_name']064 );
  934.         }
  935.         if!empty$pParamHash['email') ) {
  936.             // LOWER CASE all emails admin_verify_email
  937.             $pParamHash['email'strtolower$pParamHash['email');
  938.             ifvalidate_email_syntax$pParamHash['email') ) {
  939.                 $ret $this->userExistsarray'email' => $pParamHash['email') );
  940.                 if!empty($ret) ) {
  941.                     if!empty$_REQUEST['overwrite'&& (!isset($pParamHash['user_store']['user_id']|| $pParamHash['user_store']['user_id'== $ret ) ) {
  942.                         $pParamHash['user_id'$ret;
  943.                         $pParamHash['user_store']['user_id'$pParamHash['user_id'];
  944.                     else {
  945.                         $this->mErrors['email''The email address "'.$pParamHash['email'].'" has already been registered.';
  946.                     }
  947.                 }
  948.                 if!empty$_REQUEST['admin_verify_email') ) {
  949.                     if!$this->verifyMX$pParamHash['email') ) {
  950.                         $this->mErrors['email''Cannot find a valid mail server';
  951.                     }
  952.                 }
  953.                 if!isset($this->mErrors['email']) ) {
  954.                     $pParamHash['user_store']['email'strtolowersubstr$pParamHash['email']0200 ) );
  955.                 }
  956.             else {
  957.                 $this->mErrors['email''The email address "'.$pParamHash['email'].'" has an invalid syntax.';
  958.             }
  959.         else {
  960.             $this->mErrors['email'tra'You must enter your email address' );
  961.         }
  962.  
  963.         // check some new user requirements
  964.         if!$this->isRegistered() ) {
  965.             ifisset($pParamHash['user_store']['user_id']&& !empty$_REQUEST['overwrite') ) {
  966.                 $this->mUserId = $this->userExistsarray'user_id' => $pParamHash['user_store']['user_id') );
  967.             }
  968.             ifempty$pParamHash['registration_date') ) {
  969.                 $pParamHash['registration_date'date"U" );
  970.             }
  971.             $pParamHash['user_store']['registration_date'$pParamHash['registration_date'];
  972.  
  973.             if!empty($pParamHash['hash') ) {
  974.                 unset$pParamHash['password');
  975.                 if($gBitSystem->isFeatureActive'users_clear_passwords' ) ) {
  976.                     $this->mErrors['password'tra'You cannot import a password hash when setting to stor password in plan text is set.' );
  977.                 elseifstrlen$pParamHash['hash'<> 32 {
  978.                     $this->mErrors['password'tra'When importing a MD5 password hash it needto have a length of 32 bytes.' );
  979.                 }
  980.             else {
  981.                 if!empty$_REQUEST['admin_verify_user') ) {
  982.                     $pParamHash['user_store']['provpass'md5(BitSystem::genPass());
  983.                     $pParamHash['user_store']['hash''';
  984.                     $pParamHash['pass_due'0;
  985.                     unset$pParamHash['password');
  986.                 elseifempty($pParamHash['password') ) {
  987.                     $pParamHash['password'$gBitSystem->genPass();
  988.                 }
  989.             }
  990.         elseif$this->isValid() ) {
  991.             // Prevent loosing user info on save
  992.             ifempty$pParamHash['edit') ) {
  993.                 $pParamHash['edit'$this->mInfo['data'];
  994.             }
  995.         }
  996.  
  997.         ifisset$pParamHash['password') ) {
  998.             if (!$this->isValid(|| isset($pParamHash['password']) ) {
  999.                 $passswordError $this->verifyPasswordFormat$pParamHash['password');
  1000.             }
  1001.             if!empty$passswordError ) ) {
  1002.                 $this->mErrors['password'$passswordError;
  1003.             else {
  1004.                 // Generate a unique hash
  1005.                 //$pParamHash['user_store']['hash'] = md5( strtolower( (!empty($pParamHash['login'])?$pParamHash['login']:'') ).$pPassword.$pParamHash['email'] );
  1006.                 $pParamHash['user_store']['hash'md5$pParamHash['password');
  1007.                 $now $gBitSystem->getUTCTime();
  1008.                 if!isset$pParamHash['pass_due'&& $gBitSystem->getConfig('users_pass_due') ) {
  1009.                     $pParamHash['user_store']['pass_due'$now (60 60 24 $gBitSystem->getConfig('users_pass_due') );
  1010.                 elseifisset$pParamHash['pass_due') ) {
  1011.                     // renew password only next half year ;)
  1012.                     $pParamHash['user_store']['pass_due'$now (60 60 24 $pParamHash['pass_due']);
  1013.                 }
  1014.                 if$gBitSystem->isFeatureActive'users_clear_passwords' ) ) {
  1015.                     $pParamHash['user_store']['user_password'$pParamHash['password'];
  1016.                 else {
  1017.                     $pParamHash['user_store']['user_password''';
  1018.                 }
  1019.             }
  1020.         elseif!empty$pParamHash['hash')) {
  1021.             $pParamHash['user_store']['hash'$pParamHash['hash'];
  1022.             $now $gBitSystem->getUTCTime();
  1023.             if!isset$pParamHash['pass_due'&& $gBitSystem->getConfig'users_pass_due' )) {
  1024.                 $pParamHash['user_store']['pass_due'$now 60 60 24 $gBitSystem->getConfig'users_pass_due' ));
  1025.             elseifisset$pParamHash['pass_due') ) {
  1026.                 // renew password only next half year ;)
  1027.                 $pParamHash['user_store']['pass_due'$now 60 60 24 $pParamHash['pass_due');
  1028.             }
  1029.         }
  1030.         return count$this->mErrors == );
  1031.     }
  1032.  
  1033.     /**
  1034.      * expunge removes user and associated private data
  1035.      *
  1036.      * @access public
  1037.      * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  1038.      */
  1039.     function expunge$pExpungeContent NULL {
  1040.         global $gBitSystem;
  1041.         $this->mDb->StartTrans();
  1042.  
  1043.         if!empty$pExpungeContent ) ) {
  1044.             if$pExpungeContent == 'all' {
  1045.                 if$userContent $this->mDb->getAssoc"SELECT content_id, content_type_guid FROM `".BIT_DB_PREFIX."liberty_content` WHERE `user_id`=? AND `content_type_guid` != 'bituser'"array$this->mUserId ) ) ) {
  1046.                     foreach$userContent as $contentId=>$contentTypeGuid {
  1047.                         if$delContent LibertyBase::getLibertyObject$contentId$contentTypeGuid ) ) {
  1048.                             $delContent->expunge();
  1049.                         }
  1050.                     }
  1051.                 }
  1052.             }
  1053.         }
  1054.  
  1055.         if$this->mUserId != ANONYMOUS_USER_ID {
  1056.             $this->purgeImage'avatar' );
  1057.             $this->purgeImage'portrait' );
  1058.             $this->purgeImage'logo' );
  1059.             $this->invokeServices'users_expunge_function' );
  1060.             $userTables array(
  1061.                 'users_cnxn',
  1062.                 'users_watches',
  1063.                 'users_favorites_map',
  1064.                 'users_users',
  1065.             );
  1066.             foreach$userTables as $table {
  1067.                 $query "DELETE FROM `".BIT_DB_PREFIX.$table."` WHERE `user_id` = ?";
  1068.                 $result $this->mDb->query$queryarray$this->mUserId ) );
  1069.             }
  1070.  
  1071.             parent::expunge();
  1072.  
  1073.             $logHash['action_log']['title'$this->mInfo['login'];
  1074.             $this->mLogs['user_del''User deleted';
  1075.             $this->storeActionLog$logHash );
  1076.             $this->mDb->CompleteTrans();
  1077.             return TRUE;
  1078.         else {
  1079.             $this->mDb->RollbackTrans();
  1080.             $gBitSystem->fatalErrortra'The anonymous user cannot be deleted' ) );
  1081.         }
  1082.     }
  1083.  
  1084.     // {{{ ==================== Sessions and logging in and out methods ====================
  1085.     /**
  1086.      * updateSession
  1087.      *
  1088.      * @param array $pSessionId 
  1089.      * @access public
  1090.      * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  1091.      */
  1092.     function updateSession$pSessionId {
  1093.         global $gLightWeightScan;
  1094.         if !$this->isDatabaseValid() ) return true;
  1095.         global $gBitSystem$gBitUser;
  1096.         $update['last_get'$gBitSystem->getUTCTime();
  1097.         $update['current_view'$_SERVER['SCRIPT_NAME'];
  1098.  
  1099.         ifempty$gLightWeightScan ) ) {
  1100.             $row $this->mDb->getRow"SELECT `last_get`, `connect_time`, `get_count`, `user_agent`, `current_view` FROM `".BIT_DB_PREFIX."users_cnxn` WHERE `cookie`=? "array$pSessionId ) );
  1101.             if$gBitUser->isRegistered() ) {
  1102.                 $update['user_id'$gBitUser->mUserId;
  1103.             }
  1104.             if$row {
  1105.                 ifempty$row['ip'|| $row['ip'!= $_SERVER['REMOTE_ADDR'{
  1106.                     $update['ip'$_SERVER['REMOTE_ADDR'];
  1107.                 }
  1108.                 if!empty$_SERVER['HTTP_USER_AGENT'&& (empty$row['user_agent'|| $row['user_agent'!= $_SERVER['HTTP_USER_AGENT']) ) {
  1109.                     $update['user_agent'= (string)substr$_SERVER['HTTP_USER_AGENT']0128 );
  1110.                 }
  1111.                 $update['get_count'$row['get_count'1;
  1112.                 $ret $this->mDb->associateUpdateBIT_DB_PREFIX.'users_cnxn'$updatearray'cookie' => $pSessionId ) );
  1113.             else {
  1114.                 if$this->isRegistered() ) {
  1115.                     $update['user_id'$this->mUserId;
  1116.                     $update['ip'$_SERVER['REMOTE_ADDR'];
  1117.                     // truncate length & cast substr to (string) to prevent insert fatals if substr returns false
  1118.                     $update['user_agent'= (string)substr$_SERVER['HTTP_USER_AGENT']0128 );
  1119.                     $update['get_count'1;
  1120.                     $update['connect_time'$update['last_get'];
  1121.                     $update['cookie'$pSessionId;
  1122.                     $result $this->mDb->associateInsertBIT_DB_PREFIX.'users_cnxn'$update );
  1123.                 }
  1124.             }
  1125.             // Delete old connections nightly during the hour of 3 am
  1126.             // This needs moving to an event that is known to happen
  1127.             ifdate'H' == '03' && date'i' &&  date'i' {
  1128.                 // Default to 30 days history
  1129.                 $oldy $update['last_get'($gBitSystem->getConfig'users_cnxn_history_days'30 24 60 60);
  1130.                 $query "DELETE from `".BIT_DB_PREFIX."users_cnxn` where `connect_time` < ?";
  1131.                 $result $this->mDb->query($queryarray($oldy));
  1132.             }
  1133.         }
  1134.         return true;
  1135.     }
  1136.  
  1137.     /**
  1138.      * countSessions
  1139.      *
  1140.      * @param array $pActive 
  1141.      * @access public
  1142.      * @return count of sessions
  1143.      */
  1144.     function countSessions$pActive FALSE {
  1145.         $query "SELECT COUNT(*) FROM `".BIT_DB_PREFIX."users_cnxn`";
  1146.         if$pActive {
  1147.             $query .=" WHERE `cookie` IS NOT NULL";
  1148.         }
  1149.         return $this->mDb->getOne$query,array() );
  1150.     }
  1151.  
  1152.     /**
  1153.      * logout
  1154.      *
  1155.      * @access public
  1156.      * @return void 
  1157.      */
  1158.     function logout({
  1159.         // This must come first
  1160.         $this->clearFromCache();
  1161.  
  1162.         $this->sendSessionCookieFALSE );
  1163.  
  1164.         session_destroy();
  1165.         $this->mUserId = NULL;
  1166.         // ensure Guest default page is loaded if required
  1167.         $this->mInfo['default_role_id'= -1;
  1168.     }
  1169.  
  1170.     function sendSessionCookie$pCookie=TRUE {
  1171.         global $gBitSystem;
  1172.  
  1173.         $siteCookie static::getSiteCookieName();
  1174.         $cookieTime 0;
  1175.         $cookiePath BIT_ROOT_URL;
  1176.         $cookieDomain '';
  1177.  
  1178.         if$pCookie === TRUE {
  1179.             $pCookie session_id();
  1180.         elseif$pCookie==FALSE {
  1181.             $pCookie ''// unset the cookie, eg logout
  1182.             if!empty$_COOKIE[$siteCookie) ) {
  1183.                 $this->mDb->query"UPDATE `".BIT_DB_PREFIX."users_cnxn` SET `cookie`=NULL WHERE `cookie`=?"array$_COOKIE[$siteCookie) );
  1184.                 unset$_COOKIE[$siteCookie);
  1185.             }
  1186.         }
  1187.  
  1188.         if!empty$pCookie ) ) {
  1189.             // Now if the remember me feature is on and the user checked the user_remember_me checkbox then ...
  1190.             if$gBitSystem->isFeatureActive'users_remember_me' && isset$_REQUEST['rme'&& $_REQUEST['rme'== 'on' {
  1191.                 $cookieTime = (int)time(+ (int)$gBitSystem->getConfig'users_remember_time'86400 ));
  1192.                 $cookiePath $gBitSystem->getConfig'cookie_path'$cookiePath );
  1193.                 $cookieDomain $gBitSystem->getConfig'cookie_domain'$cookieDomain );
  1194.             }
  1195.         }
  1196.         setcookie$siteCookie$pCookie$cookieTime $cookiePath$cookieDomain );
  1197.         $_COOKIE[$siteCookie$pCookie;
  1198.     }
  1199.  
  1200.     public static function getSiteCookieName({
  1201.         global $gBitSystem;
  1202.  
  1203.         $cookie_site strtolowerpreg_replace"/[^a-zA-Z0-9]/"""$gBitSystem->getConfig'site_title''bitweaver' )));
  1204.         return'bit-user-'.$cookie_site );
  1205.     }
  1206.  
  1207.     /**
  1208.      * verifyTicket
  1209.      *
  1210.      * @param array $pFatalOnError 
  1211.      * @param array $pForceCheck 
  1212.      * @access public
  1213.      * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  1214.      */
  1215.     function verifyTicket$pFatalOnError=TRUE$pForceCheck=TRUE {
  1216.         global $gBitSystem$gBitUser;
  1217.         $ret FALSE;
  1218.         if$pForceCheck == TRUE || !empty$_REQUEST['tk') ) {
  1219.             ifempty$_REQUEST['tk'|| (!($ret $_REQUEST['tk'== $this->mTicket && $pFatalOnError) ) {
  1220.                 $userString $gBitUser->isRegistered("\nUSER ID: ".$gBitUser->mUserId.' ( '.$gBitUser->getField'email' ).' ) ' '';
  1221.                 error_logtra"Security Violation" )."$userString ".$_SERVER['REMOTE_ADDR']."\nURI: $_SERVER[REQUEST_URI] \nREFERER: $_SERVER[HTTP_REFERER] );
  1222.                 $gBitSystem->fatalErrortra"Security Violation" ));
  1223.             }
  1224.         }
  1225.         return $ret;
  1226.     }
  1227.     // }}}
  1228.  
  1229.     // {{{ ==================== Banning ====================
  1230.     /**
  1231.      * ban sets the user account status to -201 suspended
  1232.      *
  1233.      * @access public
  1234.      * @return TRUE on success, Display error message on failure
  1235.      */
  1236.     function ban(){
  1237.         global $gBitSystem;
  1238.         if$this->mUserId == ANONYMOUS_USER_ID || $this->mUserId == ROOT_USER_ID || $this->isAdmin()) {
  1239.             $gBitSystem->fatalErrortra'You cannot ban the user' )." ".$this->mInfo['login');
  1240.         else {
  1241.             $this->storeStatus-201 );
  1242.             return TRUE;
  1243.         }
  1244.     }
  1245.  
  1246.     /**
  1247.      * ban unban the user
  1248.      *
  1249.      * @access public
  1250.      * @return TRUE on success
  1251.      */
  1252.     function unban(){
  1253.         global $gBitSystem;
  1254.         $this->storeStatus50 );
  1255.         return TRUE;
  1256.     }
  1257.     // }}}
  1258.  
  1259.     /**
  1260.      * genPass generate random password
  1261.      *
  1262.      * @param array $pLength Length of final password
  1263.      * @access public
  1264.      * @return password 
  1265.      */
  1266.     function genPass$pLength=NULL {
  1267.         global $gBitSystem;
  1268.         $vocales "AaEeIiOoUu13580";
  1269.         $consonantes "BbCcDdFfGgHhJjKkLlMmNnPpQqRrSsTtVvWwXxYyZz24679";
  1270.         $ret '';
  1271.         ifempty$pLength || !is_numeric$pLength ) ) {
  1272.             $pLength $gBitSystem->getConfig'users_min_pass_length');
  1273.         }
  1274.         for$i 0$i $pLength$i++ {
  1275.             if$i {
  1276.                 $ret .= $vocales{rand0strlen$vocales )};
  1277.             else {
  1278.                 $ret .= $consonantes{rand0strlen$consonantes )};
  1279.             }
  1280.         }
  1281.         return $ret;
  1282.     }
  1283.  
  1284.     /**
  1285.      * generateChallenge
  1286.      *
  1287.      * @access public
  1288.      * @return md5 string
  1289.      */
  1290.     function generateChallenge({
  1291.         returnmd5BitSystem::genPass() ));
  1292.     }
  1293.  
  1294.     /**
  1295.      * login
  1296.      *
  1297.      * @param array $pLogin 
  1298.      * @param array $pPassword 
  1299.      * @param array $pChallenge 
  1300.      * @param array $pResponse 
  1301.      * @access public
  1302.      * @return URL the user should be sent to after login
  1303.      */
  1304.     function login$pLogin$pPassword$pChallenge=NULL$pResponse=NULL {
  1305.         global $gBitSystem;
  1306.         $isvalid false;
  1307.  
  1308.         $loginCol strpos$pLogin'@' 'email' 'login';
  1309.  
  1310.         $this->mDb->StartTrans();
  1311.         // Verify user is valid
  1312.         if$this->validate$pLogin$pPassword$pChallenge$pResponse )) {
  1313.             $userInfo $this->getUserInfoarray$loginCol => $pLogin ));
  1314.  
  1315.             // If the password is valid but it is due then force the user to change the password by
  1316.             // sending the user to the new password change screen without letting him use
  1317.             // The user must re-nter the old password so no secutiry risk here
  1318.             if$this->isPasswordDue() ) {
  1319.                 // Redirect the user to the screen where he must change his password.
  1320.                 // Note that the user is not logged in he's just validated to change his password
  1321.                 // The user must re-enter his old password so no secutiry risk involved
  1322.                 $url USERS_PKG_URL.'change_password.php?user_id='.$userInfo['user_id'];
  1323.  
  1324.             elseif$userInfo['user_id'!= ANONYMOUS_USER_ID {
  1325.                 // User is valid and not due to change pass..
  1326.                 $this->mUserId = $userInfo['user_id'];
  1327.                 $this->load();
  1328.                 $this->loadPermissionsTRUE );
  1329.  
  1330.                 // set post-login url
  1331.                 // if role home is set for this user we get that
  1332.                 // default to general post-login
  1333.                 // @see BitSystem::getIndexPage
  1334.                 $indexType 'my_page';
  1335.                 // getHomeRole is RolePermUser method
  1336.                 ifmethod_exists$this'getHomeRole' &&
  1337.                     (( @$this->verifyId$this->mInfo['default_role_id'&& $role_home $this->getHomeRole$this->mInfo['default_role_id') ) ) ||
  1338.                     $gBitSystem->getConfig'default_home_role' && $role_home $this->getHomeRole$gBitSystem->getConfig'default_home_role' ) ) ) )) ){
  1339.                     $indexType 'role_home';
  1340.                 }
  1341.  
  1342.                 $url = isset($_SESSION['loginfrom']$_SESSION['loginfrom'$gBitSystem->getIndexPage$indexType );
  1343.                 unset$_SESSION['loginfrom');
  1344.  
  1345.                 $sessionId session_id();
  1346.                 $this->sendSessionCookie$sessionId );
  1347.                 $this->updateSession$sessionId );
  1348.             }
  1349.         else {
  1350.             // before we give up lets see if the user exists and if the password is expired
  1351.             $query "select `email`, `user_id`, `user_password` from `".BIT_DB_PREFIX."users_users` where " $this->mDb->convertBinary()" $loginCol = ?";
  1352.             $result $this->mDb->getRow$queryarray$pLogin ) );
  1353.             if!empty$result['user_id'&& $this->isPasswordDue$result['user_id') ) {
  1354.                 // user needs email password reset so send it and let them know
  1355.                 $url USERS_PKG_URL.'remind_password.php?remind=y&required=y&username='.$pLogin;
  1356.             }else{
  1357.                 $this->mUserId = ANONYMOUS_USER_ID;
  1358.                 unset$this->mInfo );
  1359.                 $this->mErrors['login'tra'Invalid username or password' );
  1360.                 $url USERS_PKG_URL.'login.php?error=' urlencode$this->mErrors['login');
  1361.             }
  1362.         }
  1363.         $this->mDb->CompleteTrans();
  1364.  
  1365.         // check for HTTPS mode and redirect back to non-ssl when not requested, or a  SSL login was forced
  1366.         ifisset$_SERVER['HTTPS'&& strtolower$_SERVER['HTTPS'== 'on' {
  1367.             $refererSsl = isset$_SERVER['HTTP_REFERER'&& substr$_SERVER['HTTP_REFERER']0== 'https';
  1368.             if( ($gBitSystem->getConfig'site_https_login_required' && !$refererSsl) ) {
  1369.                 // start setting up the URL redirect without SSL
  1370.                 $prefix 'http://' $gBitSystem->getConfig'site_http_domain'$_SERVER['HTTP_HOST');
  1371.  
  1372.                 // add port to prefix if needed
  1373.                 $port   $gBitSystem->getConfig'site_http_port'80 );
  1374.                 if$port != 80 {
  1375.                     $prefix .= ':'.$port;
  1376.                 }
  1377.                 $prefix .= $gBitSystem->getConfig'site_http_prefix'BIT_ROOT_URL );
  1378.                 ifstrrpos$prefix'/' == (strlen$prefix )  1) ) {
  1379.                     $prefix substr$prefix0strlen$prefix );
  1380.                 }
  1381.                 // join prefix and URL
  1382.                 $url $prefix.$url;
  1383.             }
  1384.         }
  1385.         return$url );
  1386.     }
  1387.  
  1388.     /**
  1389.      * validate
  1390.      *
  1391.      * @param array $pUser 
  1392.      * @param array $pPass 
  1393.      * @param array $pChallenge 
  1394.      * @param array $pResponse 
  1395.      * @access public
  1396.      * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  1397.      * @todo rewrite this mess. this is horrible stuff. - xing - Thursday Oct 16, 2008   09:47:20 CEST
  1398.      */
  1399.     function validate$pUser$pPass$pChallenge$pResponse {
  1400.         global $gBitSystem;
  1401.         // these will help us keep tabs of what is going on
  1402.         $authValid $authPresent FALSE;
  1403.         $createAuth $gBitSystem->getConfig"users_create_user_auth""n" == "y" );
  1404.  
  1405.         for$i 0$i BaseAuth::getAuthMethodCount()$i++ {
  1406.             $instance BaseAuth::init$i );
  1407.             if$instance {
  1408.                 $result $instance->validate$pUser$pPass$pChallenge$pResponse );
  1409.                 switch$result {
  1410.                     case USER_VALID:
  1411.                         unset($this->mErrors['login']);
  1412.                         $authPresent TRUE;
  1413.                         $authValid TRUE;
  1414.                         break;
  1415.                     case PASSWORD_INCORRECT:
  1416.                         // this mErrors assignment is CRUCIAL so that bit auth fails properly. DO NOT FUCK WITH THIS unless you know what you are doing and have checked with me first. XOXOX - spiderr
  1417.                         // This might have broken other auth, but at this point, bw auth was TOTALLY busted. If you need to fix, please come find me.
  1418.                         $this->mErrors['login''Password incorrect';
  1419.                         $authPresent TRUE;
  1420.                         break;
  1421.                     case USER_NOT_FOUND:
  1422.                         break;
  1423.                 }
  1424.  
  1425.                 if$authValid {
  1426.                     ifempty$instance->mInfo['email')) {
  1427.                         $instance->mInfo['email'$pUser;
  1428.                     }
  1429.  
  1430.                     //If we're given a user_id then the user is already in the database:
  1431.                     if!empty$instance->mInfo['user_id')) {
  1432.                         $this->mUserId = $instance->mInfo['user_id'];
  1433.  
  1434.                     //Is the user already in the database:
  1435.                     elseif$this->mDb->getOne"SELECT COUNT(*) FROM `".BIT_DB_PREFIX."users_users` WHERE `login` = ?"array$instance->mLogin )) {
  1436.                         // Update Details
  1437.                         $authUserInfo array(
  1438.                             'login'     => $instance->mInfo['login'],
  1439.                             'password'  => $instance->mInfo['password'],
  1440.                             'real_name' => $instance->mInfo['real_name'],
  1441.                             'email'     => $instance->mInfo['email']
  1442.                         );
  1443.                         $userInfo $this->getUserInfoarray'login' => $pUser ));
  1444.                         $this->mUserId = $userInfo['user_id'];
  1445.                         $this->store$authUserInfo );
  1446.                         $this->mErrors = array();
  1447.  
  1448.                     else {
  1449.                         $authUserInfo array(
  1450.                             'login'     => $instance->mInfo['login'],
  1451.                             'password'  => $instance->mInfo['password'],
  1452.                             'real_name' => $instance->mInfo['real_name'],
  1453.                             'email'     => $instance->mInfo['email']
  1454.                         );
  1455.                         // TODO somehow, mUserId gets set to -1 at this point - no idea how
  1456.                         // set to NULL to prevent overwriting Guest user - wolff_borg
  1457.                         $this->mUserId = NULL;
  1458.                         $this->store$authUserInfo );
  1459.                     }
  1460.  
  1461.                     if$createAuth && $i {
  1462.                         // if the user was logged into this system and we should progate users down other auth methods
  1463.                         for$j $i$i >= 0$j-- {
  1464.                             $probMethodName $gBitSystem->getConfig"users_auth_method_$j"$default );
  1465.                             if!empty$probMethodName )) {
  1466.                                 $probInstance BaseAuth::init$probMethodName );
  1467.                                 if$probInstance && $probInstance->canManageAuth() ) {
  1468.                                     $result $probInstance->validate$pUser$pPass$pChallenge$pResponse );
  1469.                                     if$result == USER_VALID || $result == PASSWORD_INCORRECT {
  1470.                                         // see if we can create a new account
  1471.                                         $userattr $instance->getUserData();
  1472.                                         ifempty$userattr['login')) {
  1473.                                             $userattr['login'$pUser;
  1474.                                         }
  1475.                                         ifempty$userattr['password')) {
  1476.                                             $userattr['password'$pPass;
  1477.                                         }
  1478.                                         $probInstance->createUser$userattr );
  1479.                                     }
  1480.                                 }
  1481.                                 $this->mErrors = array_merge$this->mErrors$probInstance->mErrors );
  1482.                             }
  1483.                         }
  1484.                     }
  1485.                     $this->mAuth = $instance;
  1486.                     break;
  1487.                 }
  1488.                 $this->mErrors = array_merge$this->mErrors,$instance->mErrors );
  1489.             }
  1490.         }
  1491.         if$this->mUserId != ANONYMOUS_USER_ID {
  1492.             $this->load();
  1493.             //on first time login we run the users registation service
  1494.             if$this->mInfo['last_login'== NULL {
  1495.                 $this->invokeServices'users_register_function' );
  1496.             }
  1497.             $this->updateLastLogin$this->mUserId );
  1498.         }
  1499.         returncount$this->mErrors == );
  1500.     }
  1501.  
  1502.     /**
  1503.      * updateLastLogin
  1504.      *
  1505.      * @param array $pUserId 
  1506.      * @access public
  1507.      * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  1508.      */
  1509.     function updateLastLogin$pUserId {
  1510.         $ret FALSE;
  1511.         if@$this->verifyId$pUserId ) ) {
  1512.             global $gBitSystem;
  1513.             $query "UPDATE `".BIT_DB_PREFIX."users_users` SET `last_login` = `current_login`, `current_login` = ? WHERE `user_id` = ?";
  1514.             $result $this->mDb->query$queryarray$gBitSystem->getUTCTime()$pUserId ));
  1515.             $ret TRUE;
  1516.         }
  1517.         return $ret;
  1518.     }
  1519.  
  1520.     /**
  1521.      * confirmRegistration
  1522.      *
  1523.      * @param array $pUserId 
  1524.      * @param array $pProvpass 
  1525.      * @access public
  1526.      * @return registered user, empty array on failure
  1527.      */
  1528.     function confirmRegistration$pUserId$pProvpass {
  1529.         global $gBitSystem;
  1530.         $query "
  1531.             SELECT `user_id`, `provpass`, `user_password`, `login`, `email` FROM `".BIT_DB_PREFIX."users_users`
  1532.             WHERE `user_id`=? AND `provpass`=? AND ( `provpass_expires` IS NULL OR `provpass_expires` > ?)";
  1533.         return$this->mDb->getRow$queryarray$pUserId$pProvpass$gBitSystem->getUTCTime() )));
  1534.     }
  1535.  
  1536.     /**
  1537.      * changeUserEmail
  1538.      *
  1539.      * @param array $pUserId 
  1540.      * @param array $pEmail 
  1541.      * @access public
  1542.      * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  1543.      */
  1544.     function changeUserEmail$pUserId$pEmail {
  1545.         if!validate_email_syntax$pEmail ) ) {
  1546.             $this->mErrors['bad_mail'tra"The email address provided does not have recognised valid syntax." );
  1547.         elseif$this->userExistsarray'email' => $pEmail ))) {
  1548.             $this->mErrors['duplicate_mail'tra"The email address you selected already exists." );
  1549.         else {
  1550.             $query "UPDATE `".BIT_DB_PREFIX."users_users` SET `email`=? WHERE `user_id`=?";
  1551.             $result $this->mDb->query$queryarray$pEmail$pUserId ) );
  1552.             $query "UPDATE `".BIT_DB_PREFIX."users_watches` SET `email`=? WHERE `user_id`=?";
  1553.             $result $this->mDb->query$queryarray$pEmail$pUserId ) );
  1554.  
  1555.             // update value in hash
  1556.             $this->mInfo['email'$pEmail;
  1557.         }
  1558.         returncount$this->mErrors == );
  1559.     }
  1560.  
  1561.     /**
  1562.      * lookupHomepage
  1563.      *
  1564.      * @param array $iHomepage 
  1565.      * @access public
  1566.      * @return user_id that can be used to point to users homepage
  1567.      */
  1568.     function lookupHomepage$iHomepage {
  1569.         $ret NULL;
  1570.         if@$this->verifyId$iHomepage )) {
  1571.             // iHomepage is the user_id for the user...
  1572.             $key 'user_id';
  1573.             // force to proper integer to get things like "007." to properly query
  1574.             $iHomepage = (integer)$iHomepage;
  1575.         elseifsubstr$iHomepage0== 'mailto:' {
  1576.             // iHomepage is the email address of the user...
  1577.             $key 'email';
  1578.         else {
  1579.             // iHomepage is the 'login' of the user...
  1580.             $key 'login';
  1581.         }
  1582.         $tmpUser $this->getUserInfoarray$key => $iHomepage ));
  1583.         if@$this->verifyId$tmpUser['user_id')) {
  1584.             $ret $tmpUser['user_id'];
  1585.         }
  1586.         return $ret;
  1587.     }
  1588.  
  1589.     /**
  1590.      * getUserPreference
  1591.      *
  1592.      * @param array $pPrefName 
  1593.      * @param array $pPrefDefault 
  1594.      * @param array $pUserId 
  1595.      * @access public
  1596.      * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  1597.      */
  1598.     static function getUserPreference$pPrefName$pPrefDefault$pUserId {
  1599.         // Alternate to LibertyContent::getPreference when all you have is a user_id and a pref_name, and you need a value...
  1600.         global $gBitDb;
  1601.         $ret NULL;
  1602.  
  1603.         ifBitBase::verifyId$pUserId ) ) {
  1604.             $query "
  1605.                 SELECT lcp.`pref_value` FROM `".BIT_DB_PREFIX."liberty_content_prefs` lcp INNER JOIN `".BIT_DB_PREFIX."users_users` uu ON (lcp.`content_id`=uu.`content_id`)
  1606.                 WHERE uu.`user_id` = ? AND lcp.`pref_name` = ?";
  1607.             if!$ret $gBitDb->getOne$queryarray$pUserId$pPrefName ))) {
  1608.                 $ret $pPrefDefault;
  1609.             }
  1610.         }
  1611.         return $ret;
  1612.     }
  1613.  
  1614.     /**
  1615.      * getUserInfo will fetch the user info of a given user
  1616.      *
  1617.      * @param array $pUserMixed hash key can be any column in users_users table e.g.: 'login', 'user_id', 'email', 'content_id'
  1618.      * @access public
  1619.      * @return user info on success, NULL on failure
  1620.      */
  1621.     function getUserInfo$pUserMixed {
  1622.         $ret NULL;
  1623.         ifis_array$pUserMixed ) ) {
  1624.             if$val =  current$pUserMixed ) ) {
  1625.                 if!is_numeric$val ) ) {
  1626.                     $col "UPPER( uu.`".key$pUserMixed )."` ) ";
  1627.                     $val strtoupper$val );
  1628.                 else {
  1629.                     $col " uu.`".key$pUserMixed )."` ";
  1630.                     if$val 0x1FFFFFFF {
  1631.                         // 32 bit overflow, set to zero to avoid fatal error in databases with 32 bit signed integer columns
  1632.                         $val 0;
  1633.                     }
  1634.                 }
  1635.                 $query "SELECT  uu.* FROM `".BIT_DB_PREFIX."users_users` uu LEFT OUTER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON (lc.`content_id`=uu.`content_id`) WHERE $col = ?";
  1636.                 $ret $this->mDb->getRow$queryarray$val ));
  1637.             }
  1638.         }
  1639.         return $ret;
  1640.     }
  1641.  
  1642.     /**
  1643.      * isUserPublic Determine if an arbitrary user can be viewed by non-permissioned users.
  1644.      *
  1645.      * @param array $pUserId user_id of user to query visibility, if NULL will use this object
  1646.      * @access public
  1647.      * @return boolean if user is publically visible
  1648.      */
  1649.     function isUserPrivate$pUserId=NULL {
  1650.         $infoPref NULL;
  1651.         ifBitBase::verifyId$pUserId ) ) {
  1652.             $infoPref BitUser::getUserPreference'users_information'NULL$pUserId );
  1653.         elseifisset$this && $this->isValid() ) {
  1654.             $infoPref $this->getPreference'users_information' );
  1655.         }
  1656.  
  1657.         return $infoPref == 'private';
  1658.     }
  1659.  
  1660.     /**
  1661.      * getByHash get user from cookie hash
  1662.      *
  1663.      * @param array $pHash 
  1664.      * @access public
  1665.      * @return user info
  1666.      */
  1667.     function getUserIdFromCookieHash$pHash {
  1668.         $query "SELECT `user_id` FROM `".BIT_DB_PREFIX."users_cnxn` WHERE `cookie` = ?";
  1669.         return $this->mDb->getOne$queryarray$pHash ));
  1670.     }
  1671.  
  1672.     /**
  1673.      * isPasswordDue work out if a user has to change their password
  1674.      *
  1675.      * @access public
  1676.      * @return TRUE when the password is due, FALSE if it isn't, NULL when no due time is set
  1677.      * @note NULL password due means *no* expiration
  1678.      */
  1679.     function isPasswordDue$pUserId NULL {
  1680.         global $gBitSystem;
  1681.         $ret FALSE;
  1682.         ifempty$pUserId&& $this->isRegistered() ) {
  1683.             $pUserId $this->mUserId;
  1684.         }
  1685.         if!empty$pUserId ) ){
  1686.             // get user_id to avoid NULL and zero confusion
  1687.             $query "
  1688.                 SELECT `user_id`, `pass_due`
  1689.                 FROM `".BIT_DB_PREFIX."users_users`
  1690.                 WHERE `pass_due` IS NOT NULL AND `user_id`=? ";
  1691.             $due $this->mDb->getRow$queryarray$pUserId ) );
  1692.             if@$this->verifyId$due['user_id'&& !empty$due['pass_due') ) {
  1693.                 $ret $due['pass_due'<= $gBitSystem->getUTCTime();
  1694.             }
  1695.         }
  1696.         return $ret;
  1697.     }
  1698.  
  1699.     /**
  1700.      * createTempPassword
  1701.      *
  1702.      * @param array $pLogin 
  1703.      * @param array $pPass 
  1704.      * @access public
  1705.      * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  1706.      */
  1707.     function createTempPassword$pLogin$pPass {
  1708.         global $gBitSystem;
  1709.         $ret array'''' );
  1710.  
  1711.         ifempty$pLogin ) ) {
  1712.             $pLogin $this->getField'email' );
  1713.         }
  1714.  
  1715.         if!empty$pLogin )) {
  1716.             $pass BitSystem::genPass();
  1717.             $provpass md5$pass );
  1718.             $loginCol strpos$pLogin'@' 'email' 'login';
  1719.  
  1720.             #temp passwords good for 3 days -- prob should be an config option
  1721.             $passDue $gBitSystem->getUTCTime(60 60 24 );
  1722.             $query "UPDATE `".BIT_DB_PREFIX."users_users` SET `provpass` = ?, `provpass_expires` = ? WHERE `".$loginCol."` = ?";
  1723.             $result $this->mDb->query$queryarray$provpass$passDue$pLogin ));
  1724.             $ret array$pass$provpass );
  1725.         }
  1726.         return $ret;
  1727.     }
  1728.  
  1729.     /**
  1730.      * storePassword
  1731.      *
  1732.      * @param array $pPass 
  1733.      * @param array $pLogin 
  1734.      * @access public
  1735.      * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  1736.      */
  1737.     function storePassword$pPass$pLogin=NULL {
  1738.         global $gBitSystem;
  1739.         $ret FALSE;
  1740.  
  1741.         ifempty$pLogin ) ) {
  1742.             $pLogin $this->getField'email' );
  1743.         }
  1744.  
  1745.         if!empty$pLogin )) {
  1746.             $ret TRUE;
  1747.             $hash md5$pPass );
  1748.             // if renew password config is set then set - otherwise set null to respect no pass due
  1749.             $passDue NULL;
  1750.             if$gBitSystem->getConfig('users_pass_due') ) {
  1751.                 $now $gBitSystem->getUTCTime();;
  1752.                 // renew password according to config value
  1753.                 $passDue $now 60 60 24 $gBitSystem->getConfig'users_pass_due' ));
  1754.             }
  1755.             if!$gBitSystem->isFeatureActive'users_clear_passwords' )) {
  1756.                 $pPass NULL;
  1757.             }
  1758.             $loginCol strpos$pLogin'@' 'email' 'login';
  1759.             $query "UPDATE `".BIT_DB_PREFIX."users_users` SET `provpass`= NULL, `provpass_expires` = NULL,`hash`=? ,`user_password`=? ,`pass_due`=? WHERE `".$loginCol."`=?";
  1760.             $result $this->mDb->query$queryarray$hash$pPass$passDue$pLogin ));
  1761.         }
  1762.         return $ret;
  1763.     }
  1764.  
  1765.     /**
  1766.      * getUserActivity
  1767.      *
  1768.      * @param array $pListHash 
  1769.      * @access public
  1770.      * @return array of users and what they have been up to
  1771.      */
  1772.     function getUserActivity&$pListHash {
  1773.         $bindVars array();
  1774.         ifempty$pListHash['sort_mode') ) {
  1775.             $pListHash['sort_mode''last_get_desc';
  1776.         }
  1777.         LibertyContent::prepGetList$pListHash );
  1778.  
  1779.         $whereSql '';
  1780.         if!empty$pListHash['last_get') ) {
  1781.             $whereSql .= ' AND uc.`last_get` > ? ';
  1782.             $bindVars[time($pListHash['last_get'];
  1783.         }
  1784.  
  1785.         if@BitBase::verifyId$pListHash['user_id') ) {
  1786.             $whereSql .= ' AND uc.`user_id` = ? ';
  1787.             $bindVars[$pListHash['user_id'];
  1788.         }
  1789.  
  1790.         if!empty$pListHash['ip') ) {
  1791.             $ips split','$pListHash['ip');
  1792.             $whereSql .= ' AND ( ';
  1793.             do {
  1794.                 $ip array_pop$ips );
  1795.                 $whereSql .= ' uc.`ip` = ? ';
  1796.                 $bindVars[$ip;
  1797.                 if!empty$ips ) ) {
  1798.                     $whereSql .= ' OR ';
  1799.                 }
  1800.             while$ips );
  1801.             $whereSql .= ' ) ';
  1802.         }
  1803.  
  1804.         if!empty$pListHash['online') ) {
  1805.             $whereSql .= ' AND uc.`cookie` IS NOT NULL ';
  1806.         }
  1807.  
  1808.         $query "
  1809.             SELECT DISTINCT uc.`user_id`, `login`, `real_name`, `connect_time`, `ip`, `user_agent`, `last_get`, uu.`content_id`
  1810.             FROM `".BIT_DB_PREFIX."users_cnxn` uc
  1811.                 INNER JOIN `".BIT_DB_PREFIX."users_users` uu ON (uc.`user_id` = uu.`user_id`)
  1812.             WHERE uc.`user_id` IS NOT NULL $whereSql
  1813.             ORDER BY ".$this->mDb->convertSortmode$pListHash['sort_mode');
  1814.         $result $this->mDb->query$query$bindVars$pListHash['max_records']$pListHash['offset');
  1815.         $ret array();
  1816.         while$res $result->fetchRow() ) {
  1817.             $res['users_information'=     $this->getPreference'users_information''public'$res['content_id');
  1818.             $ret[$res;
  1819.         }
  1820.  
  1821.         $countSql "
  1822.             SELECT COUNT( uc.`user_id` )
  1823.             FROM `".BIT_DB_PREFIX."users_cnxn` uc
  1824.                 INNER JOIN `".BIT_DB_PREFIX."users_users` uu ON (uc.`user_id` = uu.`user_id`)
  1825.             WHERE uc.`user_id` IS NOT NULL $whereSql";
  1826.         $pListHash['cant'$this->mDb->GetOne$countSql$bindVars );
  1827.         $this->postGetList$pListHash );
  1828.         return $ret;
  1829.     }
  1830.  
  1831.     /**
  1832.      * getUserDomain
  1833.      *
  1834.      * @param array $pLogin 
  1835.      * @access public
  1836.      * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  1837.      */
  1838.     function getUserDomain$pLogin {
  1839.         $ret array();
  1840.         if$pLogin == $this->getField'login' && $this->getPreference'domain_style' ) ) {
  1841.             $ret $this->mInfo;
  1842.             $ret['style'$this->getPreference'domain_style' );
  1843.         else {
  1844.             $sql "
  1845.                 SELECT uu.*, lcp.`pref_value` AS `style`
  1846.                 FROM `".BIT_DB_PREFIX."users_users` uu
  1847.                     INNER JOIN `".BIT_DB_PREFIX."liberty_content_prefs` lcp ON( uu.`content_id` = lcp.`content_id` )
  1848.                 WHERE uu.`login` = ? AND lcp.`pref_name` = ?";
  1849.             $ret $this->mDb->getRow$sql,  array$pLogin'domain_style' ) );
  1850.         }
  1851.         return$ret );
  1852.     }
  1853.  
  1854.     /**
  1855.      * getDomain
  1856.      *
  1857.      * @param array $pContentId 
  1858.      * @access public
  1859.      * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  1860.      */
  1861.     function getDomain$pContentId {
  1862.         $ret array();
  1863.         if$this->verifyId$pContentId ) ) {
  1864.             $ret['content_id'$pContentId;
  1865.             $ret['style'$this->mDb->getOne"SELECT `pref_value` FROM `".BIT_DB_PREFIX."liberty_content_prefs` WHERE `content_id`=? AND `pref_name`=?"array$pContentId'domain_style' ));
  1866.         }
  1867.         return$ret );
  1868.     }
  1869.  
  1870.     /**
  1871.      * canCustomizeTheme check if a user can customise their theme
  1872.      *
  1873.      * @access public
  1874.      * @return TRUE on success, FALSE on failure
  1875.      */
  1876.     function canCustomizeTheme({
  1877.         global $gBitSystem;
  1878.         return$this->hasPermission'p_tidbits_custom_home_theme' || $gBitSystem->getConfig'users_themes' == 'y' || $gBitSystem->getConfig'users_themes' == 'h' || $gBitSystem->getConfig'users_themes' == 'u' );
  1879.     }
  1880.  
  1881.     /**
  1882.      * canCustomizeLayout  check if a user can customise their layout
  1883.      *
  1884.      * @access public
  1885.      * @return TRUE on success, FALSE on failure
  1886.      */
  1887.     function canCustomizeLayout({
  1888.         global $gBitSystem;
  1889.         return$this->hasPermission'p_tidbits_custom_home_layout' || $gBitSystem->getConfig'users_layouts' == 'y' || $gBitSystem->getConfig'users_layouts' == 'h' || $gBitSystem->getConfig'users_layouts' == 'u' );
  1890.     }
  1891.  
  1892.  
  1893.  
  1894.     // {{{ ==================== image and file functions ====================
  1895.     /**
  1896.      * getThumbnailUrl
  1897.      *
  1898.      * @param string $pSize 
  1899.      * @param array $pInfoHash 
  1900.      * @access public
  1901.      * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  1902.      */
  1903.     function getThumbnailUrl$pSize 'small'$pInfoHash NULL$pSecondaryId NULL$pDefault=TRUE {
  1904.         $ret '';
  1905.         if$pInfoHash {
  1906.             // do some stuff if we are passed a hash-o-crap, not implemented currently
  1907.         elseif$this->isValid() ) {
  1908.             $ret $this->getField'avatar_url' );
  1909.         }
  1910.         return $ret;
  1911.     }
  1912.  
  1913.     /**
  1914.      * storeImages will store any user images - please note that uploaded files have to be in predefined keys in $_FILES
  1915.      *     $_FILES['user_portrait_file']
  1916.      *     $_FILES['user_auto_avatar']
  1917.      *     $_FILES['user_logo_file']
  1918.      *
  1919.      * @param array $pParamHash array of options
  1920.      * @param boolean $pParamHash['user_auto_avatar'] automatically create avatar from portrait
  1921.      * @access public
  1922.      * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  1923.      */
  1924.     function storeImages$pParamHash {
  1925.         ifisset$_FILES['user_portrait_file'&& is_uploaded_file$_FILES['user_portrait_file']['tmp_name'&& $_FILES['user_portrait_file']['size'{
  1926.             $portraitHash                          $pParamHash;
  1927.             $portraitHash['user_id']               $this->mUserId;
  1928.             $portraitHash['content_id']            $this->mContentId;
  1929.             $portraitHash['upload']                $_FILES['user_portrait_file'];
  1930.             $portraitHash['upload']['source_file'$_FILES['user_portrait_file']['tmp_name'];
  1931.             $this->storePortrait$portraitHash!empty$portraitHash['user_auto_avatar'));
  1932.         }
  1933.  
  1934.         ifisset$_FILES['user_avatar_file'&& is_uploaded_file$_FILES['user_avatar_file']['tmp_name'&& $_FILES['user_avatar_file']['size'{
  1935.             $avatarHash                          $pParamHash;
  1936.             $avatarHash['user_id']               $this->mUserId;
  1937.             $avatarHash['content_id']            $this->mContentId;
  1938.             $avatarHash['upload']                $_FILES['user_avatar_file'];
  1939.             $avatarHash['upload']['source_file'$_FILES['user_avatar_file']['tmp_name'];
  1940.             $this->storeAvatar$avatarHash );
  1941.         }
  1942.  
  1943.         ifisset$_FILES['user_logo_file'&& is_uploaded_file$_FILES['user_logo_file']['tmp_name'&& $_FILES['user_logo_file']['size'{
  1944.             $logoHash                          $pParamHash;
  1945.             $logoHash['user_id']               $this->mUserId;
  1946.             $logoHash['content_id']            $this->mContentId;
  1947.             $logoHash['upload']                $_FILES['user_logo_file'];
  1948.             $logoHash['upload']['source_file'$_FILES['user_logo_file']['tmp_name'];
  1949.             $this->storeLogo$logoHash );
  1950.         }
  1951.     }
  1952.  
  1953.     /**
  1954.      * storePortrait
  1955.      *
  1956.      * @param array $pStorageHash 
  1957.      * @param array $pGenerateAvatar 
  1958.      * @access public
  1959.      * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  1960.      */
  1961.     function storePortrait&$pStorageHash$pGenerateAvatar FALSE {
  1962.         if$this->isValid(&& count$pStorageHash )) {
  1963.             // make a copy before the uploaded file disappears
  1964.             if$pGenerateAvatar {
  1965.                 $avatarHash $pStorageHash;
  1966.                 $avatarHash['upload']['tmp_name'$pStorageHash['upload']['tmp_name'].'.av';
  1967.                 copy$pStorageHash['upload']['tmp_name']$pStorageHash['upload']['tmp_name'].'.av' );
  1968.             }
  1969.  
  1970.             if$this->storeUserImage$pStorageHash'portrait' && $pGenerateAvatar {
  1971.                 $this->storeAvatar$avatarHash );
  1972.                 // nuke copy of image
  1973.                 @unlink$pStorageHash['upload']['tmp_name'].'.av' );
  1974.             }
  1975.         }
  1976.  
  1977.         returncount$this->mErrors == );
  1978.     }
  1979.  
  1980.     /**
  1981.      * storeAvatar
  1982.      *
  1983.      * @param array $pStorageHash 
  1984.      * @access public
  1985.      * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  1986.      */
  1987.     function storeAvatar&$pStorageHash {
  1988.         return$this->storeUserImage$pStorageHash'avatar' ));
  1989.     }
  1990.  
  1991.     /**
  1992.      * storeLogo
  1993.      *
  1994.      * @param array $pStorageHash 
  1995.      * @access public
  1996.      * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  1997.      */
  1998.     function storeLogo&$pStorageHash {
  1999.         return$this->storeUserImage$pStorageHash'logo' ));
  2000.     }
  2001.  
  2002.     /**
  2003.      * storeUserImage
  2004.      *
  2005.      * @param array $pStorageHash 
  2006.      * @param string $pType 
  2007.      * @access public
  2008.      * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  2009.      */
  2010.     function storeUserImage&$pStorageHash$pType 'portrait' {
  2011.         if$this->isValid(&& count$pStorageHash ) ) {
  2012.             // don't do the content thing
  2013.             $pStorageHash['skip_content_store'TRUE;
  2014.  
  2015.             // setup the hash for central storage functions
  2016.             $pStorageHash['no_perm_check'TRUE;
  2017.             $pStorageHash['_files_override'][$pType$pStorageHash['upload'];
  2018.             $pStorageHash['_files_override'][$pType]['max_width']     constantstrtoupper$pType )."_MAX_DIM" );
  2019.             $pStorageHash['_files_override'][$pType]['max_height']    constantstrtoupper$pType )."_MAX_DIM" );
  2020.             $pStorageHash['_files_override'][$pType]['attachment_id'!empty$this->mInfo["{$pType}_attachment_id"$this->mInfo["{$pType}_attachment_id"NULL;
  2021.             $pStorageHash['_files_override'][$pType]['user_id']       $this->mUserId;
  2022.             ifLibertyMime::store$pStorageHash )) {
  2023.                 $file $pStorageHash['upload_store']['files'][$pType];
  2024.                 ifempty$this->mInfo["{$pType}_attachment_id"|| $this->mInfo["{$pType}_attachment_id"!= $file['attachment_id'{
  2025.                     $query "UPDATE `".BIT_DB_PREFIX."users_users` SET `{$pType}_attachment_id` = ? WHERE `user_id`=?";
  2026.                     $result $this->mDb->query$queryarray$file['attachment_id']$this->mUserId ) );
  2027.                     $this->mInfo["{$pType}_attachment_id"$file['attachment_id'];
  2028.                     $pStorageHash["{$pType}_file_name"$file['upload']['dest_branch'];
  2029.                 }
  2030.             else {
  2031.                 $this->mErrors["{$pType}_file"'File '.$pStorageHash['upload_store']['files'][$pType]['name'].' could not be stored.';
  2032.             }
  2033.         }
  2034.         returncount$this->mErrors == );
  2035.     }
  2036.  
  2037.     /**
  2038.      * purgeImage
  2039.      *
  2040.      * @param array $pType 
  2041.      * @access public
  2042.      * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  2043.      */
  2044.     function purgeImage$pType {
  2045.         if$this->isValid(&& @$this->verifyId$this->mInfo[$pType.'_attachment_id') ) {
  2046.             $this->mDb->StartTrans();
  2047.             $query "UPDATE `".BIT_DB_PREFIX."users_users` SET `".$pType."_attachment_id` = NULL WHERE `user_id`=?";
  2048.             $result $this->mDb->query$queryarray$this->mUserId ) );
  2049.             if$this->expungeAttachment$this->getField$pType.'_attachment_id' ) ) ) {
  2050.                 unset$this->mInfo[$pType.'_file_name');
  2051.                 unset$this->mInfo[$pType.'_attachment_id');
  2052.                 unset$this->mInfo[$pType.'_url');
  2053.             }
  2054.             $this->mDb->CompleteTrans();
  2055.             return TRUE;
  2056.         }
  2057.     }
  2058.  
  2059.     /**
  2060.      * purgePortrait
  2061.      *
  2062.      * @access public
  2063.      * @return TRUE on success, FALSE on failure
  2064.      */
  2065.     function purgePortrait({
  2066.         return $this->purgeImage'portrait' );
  2067.     }
  2068.  
  2069.  
  2070.     /**
  2071.      * purgeAvatar
  2072.      *
  2073.      * @access public
  2074.      * @return TRUE on success, FALSE on failure
  2075.      */
  2076.     function purgeAvatar({
  2077.         return $this->purgeImage'avatar' );
  2078.     }
  2079.  
  2080.  
  2081.     /**
  2082.      * purgeLogo
  2083.      *
  2084.      * @access public
  2085.      * @return TRUE on success, FALSE on failure
  2086.      */
  2087.     function purgeLogo({
  2088.         return $this->purgeImage'logo' );
  2089.     }
  2090.     // }}}
  2091.  
  2092.     // {{{ ==================== Watches ====================
  2093.     // TODO: clean up all watch functions. these are old and messy. - xing - Thursday Oct 16, 2008   11:07:55 CEST
  2094.     /**
  2095.      * storeWatch
  2096.      *
  2097.      * @param array $pEvent 
  2098.      * @param array $pObject 
  2099.      * @param array $pType 
  2100.      * @param array $pTitle 
  2101.      * @param array $pUrl 
  2102.      * @access public
  2103.      * @return TRUE on success, FALSE on failure
  2104.      */
  2105.     function storeWatch$pEvent$pObject$pType$pTitle$pUrl {
  2106.         global $userlib;
  2107.         if$this->isValid() ) {
  2108.             $hash md5uniqid'.' ));
  2109.             $query "DELETE FROM `".BIT_DB_PREFIX."users_watches` WHERE `user_id`=? AND `event`=? AND `object`=?";
  2110.             $this->mDb->query($query,array$this->mUserId$pEvent$pObject ) );
  2111.             $query "INSERT INTO `".BIT_DB_PREFIX."users_watches`(`user_id` ,`event` ,`object` , `email`, `hash`, `watch_type`, `title`, `url`) VALUES(?,?,?,?,?,?,?,?)";
  2112.             $this->mDb->query$queryarray$this->mUserId$pEvent$pObject$this->mInfo['email']$hash$pType$pTitle$pUrl ) );
  2113.             return TRUE;
  2114.         }
  2115.     }
  2116.  
  2117.     /**
  2118.      * getWatches
  2119.      *
  2120.      * @param string $pEvent 
  2121.      * @access public
  2122.      * @return TRUE on success, FALSE on failure
  2123.      */
  2124.     function getWatches$pEvent '' {
  2125.         $ret NULL;
  2126.         if$this->isValid() ) {
  2127.             $mid '';
  2128.             $bindvars=array$this->mUserId );
  2129.             if ($pEvent{
  2130.                 $mid " and `event`=? ";
  2131.                 $bindvars[]=$pEvent;
  2132.             }
  2133.  
  2134.             $query "select * from `".BIT_DB_PREFIX."users_watches` where `user_id`=? $mid";
  2135.             $result $this->mDb->query($query,$bindvars);
  2136.             $ret array();
  2137.  
  2138.             while ($res $result->fetchRow()) {
  2139.                 $ret[$res;
  2140.             }
  2141.         }
  2142.         return $ret;
  2143.     }
  2144.  
  2145.     /**
  2146.      * getEventWatches
  2147.      *
  2148.      * @param array $pEvent 
  2149.      * @param array $object 
  2150.      * @access public
  2151.      * @return TRUE on success, FALSE on failure
  2152.      */
  2153.     function getEventWatches$pEvent$pObject {
  2154.         $ret NULL;
  2155.         if$this->isValid() ) {
  2156.             $query "SELECT * FROM `".BIT_DB_PREFIX."users_watches` WHERE `user_id`=? AND `event`=? AND `object`=?";
  2157.             $result $this->mDb->query($query,array$this->mUserId$pEvent$pObject ) );
  2158.             if $result->numRows() ) {
  2159.                 $ret $result->fetchRow();
  2160.             }
  2161.         }
  2162.         return $ret;
  2163.     }
  2164.  
  2165.     /**
  2166.      * get_event_watches
  2167.      *
  2168.      * @param array $pEvent 
  2169.      * @param array $pObject 
  2170.      * @access public
  2171.      * @return TRUE on success, FALSE on failure
  2172.      */
  2173.     function get_event_watches$pEvent$pObject {
  2174.         $ret array();
  2175.  
  2176.         $query "select * from `".BIT_DB_PREFIX."users_watches` tw INNER JOIN `".BIT_DB_PREFIX."users_users` uu ON ( tw.`user_id`=uu.`user_id` )  where `event`=? and `object`=?";
  2177.         $result $this->mDb->query$query,array$pEvent,$pObject ));
  2178.  
  2179.         if!$result->numRows() ) {
  2180.             return $ret;
  2181.         }
  2182.  
  2183.         while ($res $result->fetchRow()) {
  2184.             $ret[$res;
  2185.         }
  2186.  
  2187.         return $ret;
  2188.     }
  2189.  
  2190.     /**
  2191.      * remove_user_watch_by_hash
  2192.      *
  2193.      * @param array $pHash 
  2194.      * @access public
  2195.      * @return TRUE on success, FALSE on failure
  2196.      */
  2197.     function remove_user_watch_by_hash$pHash {
  2198.         $query "DELETE FROM `".BIT_DB_PREFIX."users_watches` WHERE `hash`=?";
  2199.         $this->mDb->query$query,array$pHash ));
  2200.     }
  2201.  
  2202.     /**
  2203.      * expungeWatch
  2204.      *
  2205.      * @param array $pEvent 
  2206.      * @param array $pObject 
  2207.      * @access public
  2208.      * @return TRUE on success, FALSE on failure
  2209.      */
  2210.     function expungeWatch$pEvent$pObject {
  2211.         if$this->isValid() ) {
  2212.             $query "DELETE FROM `".BIT_DB_PREFIX."users_watches` WHERE `user_id`=? AND `event`=? AND `object`=?";
  2213.             $this->mDb->query$queryarray$this->mUserId$pEvent$pObject ));
  2214.         }
  2215.     }
  2216.  
  2217.     /**
  2218.      * get_watches_events
  2219.      *
  2220.      * @access public
  2221.      * @return TRUE on success, FALSE on failure
  2222.      */
  2223.     function get_watches_events({
  2224.         $query "select distinct `event` from `".BIT_DB_PREFIX."users_watches`";
  2225.         $result $this->mDb->query($query,array());
  2226.         $ret array();
  2227.         while ($res $result->fetchRow()) {
  2228.             $ret[$res['event'];
  2229.         }
  2230.         return $ret;
  2231.     }
  2232.     // }}}
  2233.  
  2234.     /**
  2235.      * getUserAttachments
  2236.      *
  2237.      * @param array $pListHash 
  2238.      * @access public
  2239.      * @return list of attachments
  2240.      */
  2241.     function getUserAttachments&$pListHash {
  2242.         $pListHash['user_id'$this->mUserId;
  2243.         $mime new LibertyMime();
  2244.         return $mime->getAttachmentList$pListHash );
  2245.     }
  2246.  
  2247.     // {{{ ==================== Favorites ====================
  2248.     /**
  2249.      * storeFavorite
  2250.      *
  2251.      * @param array $pContentId 
  2252.      * @access public
  2253.      * @return TRUE on success, FALSE on failure
  2254.      */
  2255.     function storeFavorite$pContentId {
  2256.         $ret FALSE;
  2257.         if$this->isValid(&& $this->verifyId$pContentId )) {
  2258.             if!$this->hasFavorite$pContentId ) ){
  2259.                 $this->mDb->query"INSERT INTO `".BIT_DB_PREFIX."users_favorites_map` ( `user_id`, `favorite_content_id` ) VALUES (?,?)"array$this->mUserId$pContentId ) );
  2260.             }
  2261.             $ret TRUE;
  2262.         }
  2263.         return$ret );
  2264.     }
  2265.  
  2266.     function expungeFavorite$pContentId {
  2267.         $ret FALSE;
  2268.         if$this->isValid(&& $this->verifyId$pContentId ) ) {
  2269.             $this->mDb->query"DELETE FROM `".BIT_DB_PREFIX."users_favorites_map` WHERE `user_id`=? AND `favorite_content_id`=?"array$this->mUserId$pContentId ) );
  2270.             $ret TRUE;
  2271.         }
  2272.         return$ret );
  2273.     }
  2274.  
  2275.     function hasFavorite$pContentId {
  2276.         $ret FALSE;
  2277.         $rslt $this->mDb->getOne"SELECT `favorite_content_id` FROM `".BIT_DB_PREFIX."users_favorites_map` WHERE `user_id`=? AND `favorite_content_id`=?"array$this->mUserId$pContentId ) );
  2278.         if!is_null$rslt ) ){
  2279.             $ret TRUE;
  2280.         }
  2281.         return $ret;
  2282.     }
  2283.  
  2284.     /**
  2285.      * getFavorites
  2286.      *
  2287.      * @see LibertyContent::getContentList
  2288.      * @return Array of content data
  2289.      */
  2290.     function getFavorites(){
  2291.         $ret NULL;
  2292.         if$this->isRegistered() ){
  2293.             $listHash['user_favs'TRUE;
  2294.             $listHash['order_table''ufm.';
  2295.             $listHash['sort_mode''map_position_desc';
  2296.             $ret $this->getContentList$listHash );
  2297.         }
  2298.         return $ret;
  2299.     }
  2300.     // }}}
  2301.  
  2302.     /**
  2303.      * getUserId
  2304.      *
  2305.      * @access public
  2306.      * @return user id of currently loaded user
  2307.      */
  2308.     function getUserId({
  2309.         return$this->isValid($this->mUserId : ANONYMOUS_USER_ID );
  2310.     }
  2311.  
  2312.     /**
  2313.      * getDisplayUrl
  2314.      *
  2315.      * @param array $pUserName 
  2316.      * @param array $pMixed 
  2317.      * @access public
  2318.      * @return URL to users homepage
  2319.      */
  2320.     public static function getDisplayUrlFromHash&$pParamHash {
  2321.         iffunction_exists'override_user_url' ) ) {
  2322.             $ret override_user_url$pParamHash );
  2323.         else {
  2324.             global $gBitSystem;
  2325.  
  2326.             $rewrite_tag $gBitSystem->isFeatureActive'pretty_urls_extended' 'view/':'';
  2327.  
  2328.             if ($gBitSystem->isFeatureActive'pretty_urls' )
  2329.             || $gBitSystem->isFeatureActive'pretty_urls_extended' ) ) {
  2330.                 $ret =  USERS_PKG_URL $rewrite_tag;
  2331.                 $ret .= urlencode$pParamHash['login');
  2332.             else {
  2333.                 $ret =  USERS_PKG_URL 'index.php?home=';
  2334.                 $ret .= urlencode$pParamHash['login');
  2335.             }
  2336.         }
  2337.         return $ret;
  2338.     }
  2339.  
  2340.     /**
  2341.      * getDisplayLink
  2342.      *
  2343.      * @param array $pUserName 
  2344.      * @param array $pDisplayHash 
  2345.      * @access public
  2346.      * @return get a link to the the users homepage
  2347.      */
  2348.     public function getDisplayLink$pLinkText=NULL$pMixed=NULL$pAnchor=NULL {
  2349.         return BitUser::getDisplayNameFromHashTRUE$pMixed );
  2350.     }
  2351.  
  2352.     /**
  2353.      * getTitle
  2354.      *
  2355.      * @param array $pHash 
  2356.      * @access public
  2357.      * @return get the users display name
  2358.      */
  2359.     public function getTitle$pHash NULL$pDefault=TRUE {
  2360.         ifempty$pHash && $this && $this->isValid() ) {
  2361.             $pHash $this->mInfo;
  2362.         }
  2363.         return BitUser::getDisplayNameFromHashFALSE$pHash );
  2364.     }
  2365.  
  2366.     /**
  2367.      * Get user information for a particular user
  2368.      *
  2369.      * @param pUseLink return the information in the form of a url that links to the users information page
  2370.      * @param pHash todo - need explanation on how to use this...
  2371.      * @return display name or link to user information page
  2372.      ***/
  2373.     public static function getDisplayNameFromHash$pUseLink=FALSE$pHash {
  2374.         global $gBitSystem$gBitUser;
  2375.         if!empty$pHash )) {
  2376.             if!empty$pHash['real_name'&& $gBitSystem->getConfig'users_display_name''real_name' == 'real_name' {
  2377.                 $displayName $pHash['real_name'];
  2378.             elseif!empty$pHash['user')) {
  2379.                 $displayName $pHash['user'];
  2380.             elseif!empty$pHash['login')) {
  2381.                 $displayName $pHash['login'];
  2382.             elseif!empty$pHash['email')) {
  2383.                 $displayName substr$pHash['email']0strpos$pHash['email']'@' ));
  2384.             else {
  2385.                 $displayName $pHash['user_id'];
  2386.             }
  2387.  
  2388.             if!empty$pHash['user')) {
  2389.                 $iHomepage $pHash['user'];
  2390.             elseif!empty$pHash['login')) {
  2391.                 // user of 'login' is deprecated and eventually should go away!
  2392.                 $iHomepage $pHash['login'];
  2393.             elseifBitBase::verifyId$pHash['user_id')) {
  2394.                 $iHomepage $pHash['user_id'];
  2395.             elseif!empty$pHash['email')) {
  2396.                 $iHomepage $pHash['email'];
  2397.             else {
  2398.                 // this won't work right now, we need to alter userslib::interpret_home() to interpret a real name
  2399.                 $iHomepage $pHash['real_name'];
  2400.             }
  2401.             ifempty$pHash['users_information') ) {
  2402.                 $pHash['users_information'$gBitSystem->mDb->getOne"SELECT pref_value FROM liberty_content_prefs lcp INNER JOIN users_users uu ON (lcp.content_id=uu.content_id) WHERE uu.login=? AND pref_name='users_information'"array$pHash['login')1NULL86400 );
  2403.             }
  2404.  
  2405.             if$pUseLink && $gBitUser->hasPermission'p_users_view_user_homepage' && (empty$pHash['users_information'|| $pHash['users_information'== 'public') ) {
  2406.                 $ret '<a class="username" title="'.!empty$pHash['link_title'$pHash['link_title'tra'Profile for' ).' '.htmlspecialchars$displayName ))
  2407.                     .'" href="'.BitUser::getDisplayUrlFromHash$pHash ).'">'
  2408.                     . htmlspecialcharsisset$pHash['link_label'$pHash['link_label'$displayName )
  2409.                     .'</a>';
  2410.             else {
  2411.                 $ret htmlspecialchars$displayName );
  2412.             }
  2413.         else {
  2414.             $ret tra"Anonymous" );
  2415.         }
  2416.  
  2417.         return $ret;
  2418.     }
  2419.  
  2420.     /**
  2421.      * Get user information for a particular user
  2422.      *
  2423.      * @param pUseLink return the information in the form of a url that links to the users information page
  2424.      * @param pHash todo - need explanation on how to use this...
  2425.      * @return display name or link to user information page
  2426.      ***/
  2427.     function getDisplayName$pUseLink=FALSE$pHash=NULL {
  2428.         $ret NULL;
  2429.         ifempty$pHash && !empty$this && !empty$this->mInfo )) {
  2430.             $pHash &$this->mInfo;
  2431.         }
  2432.         return self::getDisplayNameFromHash$pUseLink$pHash );
  2433.     }
  2434.  
  2435.     /**
  2436.      * getRenderFile Returns include file that will
  2437.      *
  2438.      * @access public
  2439.      * @return the fully specified path to file to be included
  2440.      */
  2441.     function getRenderFile({
  2442.         return USERS_PKG_PATH."display_bituser_inc.php";
  2443.     }
  2444.  
  2445.     /**
  2446.      * getSelectionList get a list of users that can be used in dropdown lists in forms to choose from
  2447.      *
  2448.      * @access public
  2449.      * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  2450.      */
  2451.     function getSelectionList({
  2452.         $query "
  2453.             SELECT uu.`user_id`, uu.`login`, uu.`real_name`
  2454.             FROM `".BIT_DB_PREFIX."users_users` uu
  2455.             ORDER BY uu.`login`";
  2456.         $result $this->mDb->query$query );
  2457.         $ret array();
  2458.         while$res $result->fetchRow()) {
  2459.             $ret[$res['user_id']] $res['login'].(( !empty$res['real_name'&& $res['real_name'!= $res['login'' - '.$res['real_name''' );
  2460.         }
  2461.  
  2462.         return $ret;
  2463.     }
  2464.  
  2465.     /**
  2466.      * getList get a list of users
  2467.      *
  2468.      * @param array $pParamHash 
  2469.      * @access public
  2470.      * @return array of users
  2471.      */
  2472.     function getList&$pParamHash {
  2473.         global $gBitSystem$gBitUser;
  2474.         ifempty$pParamHash['sort_mode')) {
  2475.             $pParamHash['sort_mode''registration_date_desc';
  2476.         }
  2477.  
  2478.         LibertyContent::prepGetList$pParamHash );
  2479.  
  2480.         $selectSql $joinSql $whereSql '';
  2481.         $bindVars array();
  2482.         array_push$bindVars'bituser' );
  2483.         $this->getServicesSql'content_list_sql_function'$selectSql$joinSql$whereSql$bindVarsNULL$pParamHash );
  2484.  
  2485.         // limit search to users with a specific language
  2486.         if!empty$pParamHash['lang_code') ) {
  2487.             $joinSql .= " INNER JOIN `".BIT_DB_PREFIX."liberty_content_prefs` lcp ON ( lcp.`content_id`=uu.`content_id` AND lcp.`pref_name`='bitlanguage' )";
  2488.             $whereSql .= " AND lcp.`pref_value`=? ";
  2489.             $bindVars[$pParamHash['lang_code'];
  2490.         }
  2491.  
  2492.         if!$gBitUser->hasPermission'p_users_admin' ) ) {
  2493.             $joinSql .= " LEFT OUTER JOIN `".BIT_DB_PREFIX."liberty_content_prefs` lcp2 ON ( lcp2.`content_id`=uu.`content_id` AND lcp2.`pref_name`='users_information' )";
  2494.             $whereSql .= " AND (lcp2.`pref_value` IS NULL OR lcp2.`pref_value`='public')";
  2495.         }
  2496.  
  2497.         // limit search to users with a specific IP
  2498.         if!empty$pParamHash['ip') ) {
  2499.             $joinSql .= " LEFT OUTER JOIN `".BIT_DB_PREFIX."users_cnxn` uc ON ( uu.`user_id`=uc.`user_id`) ";
  2500.             $ips explode','$pParamHash['ip');
  2501.             $whereSql .= ' AND ( ';
  2502.             do {
  2503.                 $ip array_pop$ips );
  2504.                 ifstrpos$ip'%' ) ) {
  2505.                     $whereSql .= " uc.`ip` LIKE ? ";
  2506.                 else {
  2507.                     $whereSql .= " uc.`ip`=? ";
  2508.                 }
  2509.                 $bindVars[$ip;
  2510.                 if!empty$ips ) ) {
  2511.                     $whereSql .= ' OR ';
  2512.                 }
  2513.             while$ips );
  2514.             $whereSql .= ' ) ';
  2515.         }
  2516.  
  2517.         // limit to registrations over a time period like 'YYYY-MM-DD' or 'Y \Week W' or anything convertible by SQLDate
  2518.         if!empty$pParamHash['period') ) {
  2519.             $sqlPeriod $this->mDb->SQLDate$this->mDb->getPeriodFormat$pParamHash['period')$this->mDb->SQLIntToTimestamp'registration_date' ));
  2520.             $whereSql .= ' AND '.$sqlPeriod.'=?';
  2521.             $bindVars[$pParamHash['timeframe'];
  2522.         }
  2523.  
  2524.         // lets search for a user
  2525.         if $pParamHash['find'{
  2526.             $whereSql .= " AND ( UPPER( uu.`login` ) LIKE ? OR UPPER( uu.`real_name` ) LIKE ? OR UPPER( uu.`email` ) LIKE ? ) ";
  2527.             $bindVars['%'.strtoupper$pParamHash['find').'%';
  2528.             $bindVars['%'.strtoupper$pParamHash['find').'%';
  2529.             $bindVars['%'.strtoupper$pParamHash['find').'%';
  2530.         }
  2531.  
  2532.         if$gBitSystem->isPackageActive'stats' ) ) {
  2533.             $joinSql .= " LEFT OUTER JOIN `".BIT_DB_PREFIX."stats_referer_users_map` srum ON (srum.`user_id`=uu.`user_id`)
  2534.                           LEFT OUTER JOIN `".BIT_DB_PREFIX."stats_referer_urls` sru ON (srum.`referer_url_id`=sru.`referer_url_id`)";
  2535.             $selectSql .= ", sru.`referer_url`";
  2536.             if!empty$pParamHash['referer') ) {
  2537.                 if$pParamHash['referer'== 'none' {
  2538.                     $whereSql .= " AND `referer_url` IS NULL";
  2539.                 else {
  2540.                     $whereSql .= " AND `referer_url` LIKE ?";
  2541.                     $bindVars['%'.strtolower$pParamHash['find').'%';
  2542.                 }
  2543.             }
  2544.         }
  2545.  
  2546.         // Return an array of users indicating name, email, last changed pages, versions, last_login
  2547.         $query "
  2548.             SELECT uu.*, lc.`content_status_id`, lf_ava.`file_name` AS `avatar_file_name`, lf_ava.`mime_type` AS `avatar_mime_type`, la_ava.`attachment_id` AS `avatar_attachment_id` $selectSql
  2549.             FROM `".BIT_DB_PREFIX."users_users` uu
  2550.                 INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON (uu.`content_id`=lc.`content_id`)
  2551.                 $joinSql
  2552.                 LEFT OUTER JOIN `".BIT_DB_PREFIX."liberty_content_hits` lch ON ( lc.`content_id` = lch.`content_id` )
  2553.                 LEFT OUTER JOIN `".BIT_DB_PREFIX."liberty_attachments` la_ava ON ( uu.`avatar_attachment_id`=la_ava.`attachment_id` )
  2554.                 LEFT OUTER JOIN `".BIT_DB_PREFIX."liberty_files` lf_ava ON ( lf_ava.`file_id`=la_ava.`foreign_id` )
  2555.             WHERE lc.`content_type_guid` = ? $whereSql ORDER BY ".$this->mDb->convertSortmode$pParamHash['sort_mode');
  2556.         $result $this->mDb->query$query$bindVars$pParamHash['max_records']$pParamHash['offset');
  2557.  
  2558.         $ret array();
  2559.         while$res $result->fetchRow() ) {
  2560.             // Used for pulling out dead/empty/spam accounts
  2561.             ifisset$pParamHash['max_content_count'&& is_numeric$pParamHash['max_content_count') ) {
  2562.                 $contentCount $this->mDb->getOne"SELECT COUNT(*) FROM  `".BIT_DB_PREFIX."liberty_content` lc INNER JOIN `".BIT_DB_PREFIX."users_users` uu ON ( lc.`user_id`=uu.`user_id` ) WHERE uu.`user_id`=? AND `content_type_guid` != 'bituser'"array$res['user_id') );
  2563.                 if$contentCount >  $pParamHash['max_content_count'{
  2564.                     continue;
  2565.                 }
  2566.             }
  2567.  
  2568.             // Used for pulling out non-idle accounts or pigs
  2569.             ifisset$pParamHash['min_content_count'&& is_numeric$pParamHash['min_content_count') ) {
  2570.                 $contentCount $this->mDb->getOne"SELECT COUNT(*) FROM  `".BIT_DB_PREFIX."liberty_content` lc INNER JOIN `".BIT_DB_PREFIX."users_users` uu ON ( lc.`user_id`=uu.`user_id` ) WHERE uu.`user_id`=? AND `content_type_guid` != 'bituser'"array$res['user_id') );
  2571.                 if$contentCount <  $pParamHash['min_content_count'{
  2572.                     continue;
  2573.                 }
  2574.             }
  2575.  
  2576.             if!empty$res['referer_url')) {
  2577.                 if $gBitSystem->isPackageActive('stats') ) {
  2578.                     $res['short_referer_url'stats_referer_display_short($res['referer_url']);
  2579.                 }
  2580.             }
  2581.             if!empty$res['avatar_file_name')) {
  2582.                 $res['avatar_url'$this->getSourceUrlarray'attachment_id'=>$res['avatar_attachment_id']'mime_type'=>$res['avatar_mime_type']'file_name'=>$res['avatar_file_name') );
  2583.                 $res['thumbnail_url'liberty_fetch_thumbnail_urlarray(
  2584.                     'source_file' => $this->getSourceFilearray'sub_dir'=>$res['avatar_attachment_id']'user_id' => $res['user_id']'file_name'=>$res['avatar_file_name']'mime_type'=>$res['avatar_mime_type']'package'=>liberty_mime_get_storage_sub_dir_namearray'mime_type'=>$res['avatar_mime_type']'name'=>$res['avatar_file_name') ) ) ),
  2585.                     'file_name' => $res['avatar_url'],
  2586.                     // TODO: Make this a preference
  2587.                     'size'         => 'avatar'
  2588.                 ));
  2589.             }
  2590.             $res["roles"$this->getRoles$res['user_id');
  2591.             $ret[$res['user_id']] $res;
  2592.         }
  2593.         $retval array();
  2594.  
  2595.         $query "
  2596.             SELECT COUNT(*) FROM `".BIT_DB_PREFIX."users_users` uu
  2597.                 INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON (uu.`content_id`=lc.`content_id`) $joinSql
  2598.             WHERE lc.`content_type_guid` = ? $whereSql";
  2599.         $pParamHash["cant"$this->mDb->getOne$query$bindVars );
  2600.  
  2601.         LibertyContent::postGetList$pParamHash );
  2602.  
  2603.         return $ret;
  2604.     }
  2605.  
  2606.     /**
  2607.      * getRoles
  2608.      *
  2609.      * @param array $pUserId 
  2610.      * @param array $pForceRefresh 
  2611.      * @access public
  2612.      * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  2613.      */
  2614.     function getRoles$pUserId=NULL$pForceRefresh FALSE {
  2615.         $pUserId !empty$pUserId $pUserId $this->mUserId;
  2616.         if!isset$this->cUserRoles[$pUserId|| $pForceRefresh {
  2617.             $query "
  2618.                 SELECT ur.`role_id`, ur.`role_name`, ur.`user_id` as role_owner_user_id
  2619.                 FROM `".BIT_DB_PREFIX."users_roles_map` urm INNER JOIN `".BIT_DB_PREFIX."users_roles` ur ON (ur.`role_id`=urm.`role_id`)
  2620.                 WHERE urm.`user_id`=? OR urm.`role_id`=".ANONYMOUS_TEAM_ID;
  2621.             $ret $this->mDb->getAssoc$queryarray(( int )$pUserId ));
  2622.             if$ret {
  2623.                 foreacharray_keys$ret as $roleId {
  2624.                     $res array();
  2625.                     foreach$res as $key=>$val{
  2626.                         $ret[$keyarray'role_name' => $val );
  2627.                     }
  2628.                 }
  2629.             }
  2630.             // cache it
  2631.             $this->cUserRoles[$pUserId$ret;
  2632.             return $ret;
  2633.         else {
  2634.             return $this->cUserRoles[$pUserId];
  2635.         }
  2636.     }
  2637.  
  2638.     /**
  2639.      * isValid
  2640.      *
  2641.      * @access public
  2642.      * @return TRUE if user is loaded
  2643.      */
  2644.     function isValid({
  2645.         return $this->verifyId$this->mUserId ) );
  2646.     }
  2647.  
  2648.     /**
  2649.      * isAdmin "PURE VIRTUAL BASE FUNCTION";
  2650.      *
  2651.      * @access public
  2652.      * @return FALSE 
  2653.      */
  2654.     function isAdmin({
  2655.         return FALSE;
  2656.     }
  2657.  
  2658.     /**
  2659.      * isRegistered
  2660.      *
  2661.      * @access public
  2662.      * @return TRUE if user is registered, FALSE otherwise
  2663.      */
  2664.     function isRegistered({
  2665.         return $this->mUserId > ANONYMOUS_USER_ID );
  2666.     }
  2667.  
  2668.     /**
  2669.      * verifyRegistered
  2670.      *
  2671.      * @access public
  2672.      * @return TRUE if user is registered, otherwise a login dialog is displayed
  2673.      */
  2674.     function verifyRegistered$pMsg "" {
  2675.         global $gBitSystem;
  2676.         if!$this->isRegistered() ) {
  2677.             $gBitSystem->fatalPermission""$pMsg );
  2678.         }
  2679.         return TRUE;
  2680.     }
  2681.  
  2682.     /**
  2683.      * userExists
  2684.      *
  2685.      * @param array $pUserMixed 
  2686.      * @access public
  2687.      * @return TRUE on success, FALSE on failure
  2688.      */
  2689.     function userExists$pUserMixed {
  2690.         $ret FALSE;
  2691.         if is_array$pUserMixed ) ) {
  2692.             if$cur current$pUserMixed ) ) {
  2693.                 ifis_numeric$cur ) ) {
  2694.                     $conditionSql " `".key$pUserMixed )."` ";
  2695.                 else {
  2696.                     $conditionSql " UPPER(`".key$pUserMixed )."`)";
  2697.                 }
  2698.                 $query "SELECT `user_id` FROM `".BIT_DB_PREFIX."users_users` WHERE $conditionSql = ?";
  2699.                 $ret $this->mDb->getOne$queryarraystrtoupper$cur ) ) );
  2700.             }
  2701.         }
  2702.         return $ret;
  2703.     }
  2704.  
  2705.     /**
  2706.      * Create an export hash from the data
  2707.      *
  2708.      * @access public
  2709.      * @return export data
  2710.      */
  2711.     function exportHash({
  2712.         global $gBitSystem;
  2713.         $ret array();
  2714.         if$this->isValid() ) {
  2715.             $ret array(
  2716.                 'user_id'         => $this->mUserId,
  2717.                 'content_id'     => $this->mContentId,
  2718.                 'real_name'     => $this->getField'real_name' ),
  2719.                 'email'             => $this->getField'email' ),
  2720.                 'uri'            => $this->getDisplayUri(),
  2721.                 'registration_date'     => dateDateTime::W3C$this->getField('registration_date') ),
  2722.                 'last_login' => dateDateTime::W3C$this->getField('last_login') ),
  2723.             );
  2724.             $ret['content_count'get_user_content_count$this->mUserId );
  2725.             if$gBitSystem->isPackageActive'stats' ) ) {
  2726.                 $ret['referer'$this->mDb->getOne"SELECT sru.`referer_url` FROM `".BIT_DB_PREFIX."stats_referer_urls` sru INNER JOIN `".BIT_DB_PREFIX."stats_referer_users_map` srum ON (srum.`referer_url_id`=sru.`referer_url_id`) WHERE `user_id`=?"$this->mUserId );
  2727.             }
  2728.             $ret['ips'implode','$this->mDb->getCol"SELECT DISTINCT(`ip`) FROM `".BIT_DB_PREFIX."users_cnxn` uc WHERE `user_id`=?"$this->mUserId ) );
  2729.         }
  2730.         return $ret;
  2731.     }
  2732.  
  2733.     /**
  2734.      * userCollection
  2735.      *
  2736.      * @param array $pInput 
  2737.      * @param array $pReturn 
  2738.      * @access public
  2739.      * @return $pReturn 
  2740.      */
  2741.     public static function userCollection$pInput&$pReturn {
  2742.         global $gQueryUserId;
  2743.  
  2744.         ifempty$pReturn['user_id')) {
  2745.             if!empty$gQueryUserId )) {
  2746.                 $pReturn['user_id'$gQueryUserId;
  2747.             elseifisset$pInput['user_id') ) {
  2748.                 $pReturn['user_id'$pInput['user_id'];
  2749.             }
  2750.         }
  2751.         if@BitBase::verifyId$pInput['role_id') ) {
  2752.             $pReturn['role_id'$pInput['role_id'];
  2753.         }
  2754.         return;
  2755.     }
  2756.  
  2757.     public static function getUserObject$pUserId {
  2758.         global $gBitSystem;
  2759.         $userClass $gBitSystem->getConfig'user_class''BitPermUser' );
  2760.         if$ret new $userClass$pUserId ) ) {
  2761.             $ret->load();
  2762.         }
  2763.         return $ret;
  2764.     }
  2765. }
  2766.  
  2767. function get_user_content_count$pUserId {
  2768.     global $gBitDb;
  2769.     ifBitBase::verifyId$pUserId ) ) {
  2770.         return $gBitDb->getOne"SELECT COUNT(`content_id`) FROM `".BIT_DB_PREFIX."liberty_content` lc WHERE lc.`content_type_guid`!='bituser' AND lc.`user_id`=?"array$pUserId ) );
  2771.     }
  2772. }
  2773.  
  2774.  
  2775. // {{{ ==================== Services ====================
  2776. function users_favs_content_list_sql&$pObject$pParamHash=NULL ){
  2777.     $ret array();
  2778.     if!empty$pParamHash['user_favs') ){
  2779.         // $ret['select_sql'] = "";
  2780.         $ret['join_sql'" INNER JOIN `".BIT_DB_PREFIX."users_favorites_map` ufm ON ( ufm.`favorite_content_id`=lc.`content_id` )";
  2781.         $ret['where_sql'" AND ufm.`user_id` = ?";
  2782.         $ret['bind_vars'][$pObject->mUserId;
  2783.     }
  2784.     return $ret;
  2785. }
  2786.  
  2787. function users_collection_sql&$pObject$pParamHash=NULL ){
  2788.     $ret array();
  2789.     if!empty$pParamHash['role_id'and BitBase::verifyId$pParamHash['role_id') ){
  2790.         // $ret['select_sql'] = "";
  2791.         $ret['join_sql'" INNER JOIN `".BIT_DB_PREFIX."users_roles_map` urm ON (ugm.`user_id`=uu.`user_id`)";
  2792.         $ret['where_sql'' AND urm.`role_id` = ? ';
  2793.         $ret['bind_vars'][$pParamHash['role_id'];
  2794.     }
  2795.     return $ret;
  2796. }
  2797. // }}}
  2798.  
  2799. /* vim: :set fdm=marker : */

Documentation generated on Wed, 29 Jul 2015 13:57:25 +0000 by phpDocumentor 1.5.0-lsces