user.php

来自「php 开发的内容管理系统」· PHP 代码 · 共 2,044 行 · 第 1/4 页

PHP
2,044
字号
<?php
/**
 * See user.txt
 *
 * @package MediaWiki
 */

# Number of characters in user_token field
define( 'USER_TOKEN_LENGTH', 32 );

# Serialized record version
define( 'MW_USER_VERSION', 3 );

/**
 *
 * @package MediaWiki
 */
class User {
	/*
	 * When adding a new private variable, dont forget to add it to __sleep()
	 */
	/**@{{
	 * @private
	 */
	var $mBlockedby;	//!<
	var $mBlockreason;	//!<
	var $mDataLoaded;	//!<
	var $mEmail;		//!<
	var $mEmailAuthenticated; //!<
	var $mGroups;		//!<
	var $mHash;			//!<
	var $mId;			//!<
	var $mName;			//!<
	var $mNewpassword;	//!<
	var $mNewtalk;		//!<
	var $mOptions;		//!<
	var $mPassword;		//!<
	var $mRealName;		//!<
	var $mRegistration;	//!<
	var $mRights;		//!<
	var $mSkin;			//!<
	var $mToken;		//!<
	var $mTouched;		//!<
	var $mVersion;		//!< serialized version
	/**@}} */

	/** Constructor using User:loadDefaults() */
	function User()	{
		$this->loadDefaults();
		$this->mVersion = MW_USER_VERSION;
	}

	/**
	 * Static factory method
	 * @param string $name Username, validated by Title:newFromText()
	 * @param bool $validate Validate username
	 * @return User
	 * @static
	 */
	function newFromName( $name, $validate = true ) {
		# Force usernames to capital
		global $wgContLang;
// Modified for mediawiki for XOOPS - by D.J.
		//$name = $wgContLang->ucfirst( $name );

		# Clean up name according to title rules
		$t = Title::newFromText( $name );
		if( is_null( $t ) ) {
			return null;
		}

		# Reject various classes of invalid names
		$canonicalName = $t->getText();
		global $wgAuth;
		$canonicalName = $wgAuth->getCanonicalName( $t->getText() );

		if( $validate && !User::isValidUserName( $canonicalName ) ) {
			return null;
		}

		$u = new User();
		$u->setName( $canonicalName );
		$u->setId( $u->idFromName( $canonicalName ) );
		return $u;
	}

	/**
	 * Factory method to fetch whichever use has a given email confirmation code.
	 * This code is generated when an account is created or its e-mail address
	 * has changed.
	 *
	 * If the code is invalid or has expired, returns NULL.
	 *
	 * @param string $code
	 * @return User
	 * @static
	 */
	function newFromConfirmationCode( $code ) {
		$dbr =& wfGetDB( DB_SLAVE );
		$name = $dbr->selectField( 'user', 'user_name', array(
			'user_email_token' => md5( $code ),
			'user_email_token_expires > ' . $dbr->addQuotes( $dbr->timestamp() ),
			) );
		if( is_string( $name ) ) {
			return User::newFromName( $name );
		} else {
			return null;
		}
	}

	/**
	 * Serialze sleep function, for better cache efficiency and avoidance of
	 * silly "incomplete type" errors when skins are cached. The array should
	 * contain names of private variables (see at top of User.php).
	 */
	function __sleep() {
		return array(
'mBlockedby',
'mBlockreason',
'mDataLoaded',
'mEmail',
'mEmailAuthenticated',
'mGroups',
'mHash',
'mId',
'mName',
'mNewpassword',
'mNewtalk',
'mOptions',
'mPassword',
'mRealName',
'mRegistration',
'mRights',
'mToken',
'mTouched',
'mVersion',
);
	}

	/**
	 * Get username given an id.
	 * @param integer $id Database user id
	 * @return string Nickname of a user
	 * @static
	 */
	function whoIs( $id )	{
// Modified for mediawiki for XOOPS - by D.J.

		if(is_object($GLOBALS["xoopsUser"]) && $id == $GLOBALS["xoopsUser"]->getVar("uid")){
			$xoopsuser =& $GLOBALS["xoopsUser"];
		}else{
			$member_handler =& xoops_getHandler("member");
			$xoopsuser =& $member_handler->getUser($id);
		}
		//if(is_object($xoopsuser)) return MEDIAWIKI_USERPREFIX.mediawiki_encoding_xoops2mediawiki($xoopsuser->getVar("uname"));
		if(is_object($xoopsuser)) return mediawiki_username_xoops2mediawiki($xoopsuser->getVar("uname"));
		else return 0;
		
		$dbr =& wfGetDB( DB_SLAVE );
		return $dbr->selectField( 'user', 'user_name', array( 'user_id' => $id ), 'User::whoIs' );
	}

	/**
	 * Get real username given an id.
	 * @param integer $id Database user id
	 * @return string Realname of a user
	 * @static
	 */
	function whoIsReal( $id )	{
// Modified for mediawiki for XOOPS - by D.J.

		if(is_object($GLOBALS["xoopsUser"]) && $id == $GLOBALS["xoopsUser"]->getVar("uid")){
			$xoopsuser =& $GLOBALS["xoopsUser"];
		}else{
			$member_handler =& xoops_getHandler("member");
			$xoopsuser =& $member_handler->getUser($id);
		}
		if(is_object($xoopsuser)) {
			$realname = $xoopsuser->getVar("name")?$xoopsuser->getVar("name"):$xoopsuser->getVar("uname");
			//return MEDIAWIKI_USERPREFIX.mediawiki_encoding_xoops2mediawiki($realname);
			return mediawiki_username_xoops2mediawiki($realname);
		}
		else return 0;
		
		$dbr =& wfGetDB( DB_SLAVE );
		return $dbr->selectField( 'user', 'user_real_name', array( 'user_id' => $id ), 'User::whoIsReal' );
	}

	/**
	 * Get database id given a user name
	 * @param string $name Nickname of a user
	 * @return integer|null Database user id (null: if non existent
	 * @static
	 */
	function idFromName( $name ) {
		$fname = "User::idFromName";

		$nt = Title::newFromText( $name );
		if( is_null( $nt ) ) {
			# Illegal name
			return null;
		}
// Modified for mediawiki for XOOPS - by D.J.
		
		//$name = preg_replace("/^".preg_quote(MEDIAWIKI_USERPREFIX)."/", "", $name);
		$user_handler =& xoops_getHandler("user");
		$xoopsusers = array_keys($user_handler->getObjects(new Criteria("uname", mediawiki_username_mediawiki2xoops($name)), 1));
		if(empty($xoopsusers)) return null;
		else return $xoopsusers[0];
		
		$dbr =& wfGetDB( DB_SLAVE );
		$s = $dbr->selectRow( 'user', array( 'user_id' ), array( 'user_name' => $nt->getText() ), $fname );

		if ( $s === false ) {
			return 0;
		} else {
			return $s->user_id;
		}
	}

	/**
	 * Does the string match an anonymous IPv4 address?
	 *
	 * This function exists for username validation, in order to reject
	 * usernames which are similar in form to IP addresses. Strings such
	 * as 300.300.300.300 will return true because it looks like an IP 
	 * address, despite not being strictly valid.
	 * 
	 * We match \d{1,3}\.\d{1,3}\.\d{1,3}\.xxx as an anonymous IP
	 * address because the usemod software would "cloak" anonymous IP
	 * addresses like this, if we allowed accounts like this to be created
	 * new users could get the old edits of these anonymous users.
	 *
	 * @bug 3631
	 *
	 * @static
	 * @param string $name Nickname of a user
	 * @return bool
	 */
	function isIP( $name ) {
		return preg_match("/^\d{1,3}\.\d{1,3}\.\d{1,3}\.(?:xxx|\d{1,3})$/",$name);
		/*return preg_match("/^
			(?:[01]?\d{1,2}|2(:?[0-4]\d|5[0-5]))\.
			(?:[01]?\d{1,2}|2(:?[0-4]\d|5[0-5]))\.
			(?:[01]?\d{1,2}|2(:?[0-4]\d|5[0-5]))\.
			(?:[01]?\d{1,2}|2(:?[0-4]\d|5[0-5]))
		$/x", $name);*/
	}

	/**
	 * Is the input a valid username?
	 *
	 * Checks if the input is a valid username, we don't want an empty string,
	 * an IP address, anything that containins slashes (would mess up subpages),
	 * is longer than the maximum allowed username size or doesn't begin with
	 * a capital letter.
	 *
	 * @param string $name
	 * @return bool
	 * @static
	 */
	function isValidUserName( $name ) {
		global $wgContLang, $wgMaxNameChars;

// Modified for mediawiki for XOOPS - by D.J.
		if ( $name == ''
		|| User::isIP( $name )
		|| strpos( $name, '/' ) !== false
		|| strlen( $name ) > $wgMaxNameChars
		//|| $name != $wgContLang->ucfirst( $name ) 
		)
			return false;

		// Ensure that the name can't be misresolved as a different title,
		// such as with extra namespace keys at the start.
		$parsed = Title::newFromText( $name );
		if( is_null( $parsed )
			|| $parsed->getNamespace()
			|| strcmp( $name, $parsed->getPrefixedText() ) )
			return false;
		
		// Check an additional blacklist of troublemaker characters.
		// Should these be merged into the title char list?
		$unicodeBlacklist = '/[' .
			'\x{0080}-\x{009f}' . # iso-8859-1 control chars
			'\x{00a0}' .          # non-breaking space
			'\x{2000}-\x{200f}' . # various whitespace
			'\x{2028}-\x{202f}' . # breaks and control chars
			'\x{3000}' .          # ideographic space
			'\x{e000}-\x{f8ff}' . # private use
			']/u';
		if( preg_match( $unicodeBlacklist, $name ) ) {
			return false;
		}
		
		return true;
	}

	/**
	 * Is the input a valid password?
	 *
	 * @param string $password
	 * @return bool
	 * @static
	 */
	function isValidPassword( $password ) {
		global $wgMinimalPasswordLength;
		return strlen( $password ) >= $wgMinimalPasswordLength;
	}

	/**
	 * Does the string match roughly an email address ?
	 *
	 * There used to be a regular expression here, it got removed because it
	 * rejected valid addresses. Actually just check if there is '@' somewhere
	 * in the given address.
	 *
	 * @todo Check for RFC 2822 compilance
	 * @bug 959
	 *
	 * @param string $addr email address
	 * @static
	 * @return bool
	 */
	function isValidEmailAddr ( $addr ) {
		return ( trim( $addr ) != '' ) &&
			(false !== strpos( $addr, '@' ) );
	}

	/**
	 * Count the number of edits of a user
	 *
	 * @param int $uid The user ID to check
	 * @return int
	 */
	function edits( $uid ) {
		$fname = 'User::edits';

		$dbr =& wfGetDB( DB_SLAVE );
		return $dbr->selectField(
			'revision', 'count(*)',
			array( 'rev_user' => $uid ),
			$fname
		);
	}

	/**
	 * probably return a random password
	 * @return string probably a random password
	 * @static
	 * @todo Check what is doing really [AV]
	 */
	function randomPassword() {
		global $wgMinimalPasswordLength;
		$pwchars = 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz';
		$l = strlen( $pwchars ) - 1;

		$pwlength = max( 7, $wgMinimalPasswordLength );
		$digit = mt_rand(0, $pwlength - 1);
		$np = '';
		for ( $i = 0; $i < $pwlength; $i++ ) {
			$np .= $i == $digit ? chr( mt_rand(48, 57) ) : $pwchars{ mt_rand(0, $l)};
		}
		return $np;
	}

	/**
	 * Set properties to default
	 * Used at construction. It will load per language default settings only
	 * if we have an available language object.
	 */
	function loadDefaults() {
		static $n=0;
		$n++;
		$fname = 'User::loadDefaults' . $n;
		wfProfileIn( $fname );

		global $wgCookiePrefix;
		global $wgNamespacesToBeSearchedDefault;

		$this->mId = 0;
		$this->mNewtalk = -1;
		$this->mName = false;
		$this->mRealName = $this->mEmail = '';
		$this->mEmailAuthenticated = null;
		$this->mPassword = $this->mNewpassword = '';
		$this->mRights = array();
		$this->mGroups = array();
		$this->mOptions = User::getDefaultOptions();

		foreach( $wgNamespacesToBeSearchedDefault as $nsnum => $val ) {
			$this->mOptions['searchNs'.$nsnum] = $val;
		}
		unset( $this->mSkin );
		$this->mDataLoaded = false;
		$this->mBlockedby = -1; # Unset
		$this->setToken(); # Random
		$this->mHash = false;

		if ( isset( $_COOKIE[$wgCookiePrefix.'LoggedOut'] ) ) {
			$this->mTouched = wfTimestamp( TS_MW, $_COOKIE[$wgCookiePrefix.'LoggedOut'] );
		}
		else {
			$this->mTouched = '0'; # Allow any pages to be cached
		}

		$this->mRegistration = wfTimestamp( TS_MW );

		wfProfileOut( $fname );
	}

	/**
	 * Combine the language default options with any site-specific options
	 * and add the default language variants.
	 *
	 * @return array
	 * @static
	 * @private
	 */
	function getDefaultOptions() {
		/**
		 * Site defaults will override the global/language defaults
		 */
		global $wgContLang, $wgDefaultUserOptions;
		$defOpt = $wgDefaultUserOptions + $wgContLang->getDefaultUserOptions();

		/**
		 * default language setting
		 */
		$variant = $wgContLang->getPreferredVariant();
		$defOpt['variant'] = $variant;
		$defOpt['language'] = $variant;

		return $defOpt;
	}

	/**
	 * Get a given default option value.
	 *
	 * @param string $opt
	 * @return string
	 * @static
	 * @public
	 */
	function getDefaultOption( $opt ) {
		$defOpts = User::getDefaultOptions();
		if( isset( $defOpts[$opt] ) ) {
			return $defOpts[$opt];
		} else {
			return '';
		}
	}

	/**
	 * Get blocking information
	 * @private
	 * @param bool $bFromSlave Specify whether to check slave or master. To improve performance,
	 *  non-critical checks are done against slaves. Check when actually saving should be done against
	 *  master.
	 */
	function getBlockedStatus( $bFromSlave = true ) {
		global $wgEnableSorbs, $wgProxyWhitelist;

		if ( -1 != $this->mBlockedby ) {
			wfDebug( "User::getBlockedStatus: already loaded.\n" );
			return;
		}

		$fname = 'User::getBlockedStatus';
		wfProfileIn( $fname );
		wfDebug( "$fname: checking...\n" );

		$this->mBlockedby = 0;
		$ip = wfGetIP();

		# User/IP blocking
		$block = new Block();
		$block->fromMaster( !$bFromSlave );
		if ( $block->load( $ip , $this->mId ) ) {
			wfDebug( "$fname: Found block.\n" );
			$this->mBlockedby = $block->mBy;
			$this->mBlockreason = $block->mReason;
			if ( $this->isLoggedIn() ) {
				$this->spreadBlock();
			}
		} else {
			wfDebug( "$fname: No block.\n" );
		}

		# Proxy blocking
		# FIXME ? proxyunbannable is to deprecate the old isSysop()
		if ( !$this->isAllowed('proxyunbannable') && !in_array( $ip, $wgProxyWhitelist ) ) {

			# Local list
			if ( wfIsLocallyBlockedProxy( $ip ) ) {
				$this->mBlockedby = wfMsg( 'proxyblocker' );
				$this->mBlockreason = wfMsg( 'proxyblockreason' );
			}

			# DNSBL
			if ( !$this->mBlockedby && $wgEnableSorbs && !$this->getID() ) {
				if ( $this->inSorbsBlacklist( $ip ) ) {
					$this->mBlockedby = wfMsg( 'sorbs' );
					$this->mBlockreason = wfMsg( 'sorbsreason' );
				}
			}
		}

		# Extensions
		wfRunHooks( 'GetBlockedStatus', array( &$this ) );

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?