<?php
/**
* @version	$Id: users_tag_processor.php 15152 2012-03-04 09:26:24Z alex $
* @package	In-Portal
* @copyright	Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license      GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/

	defined('FULL_PATH') or die('restricted access!');

	class UsersTagProcessor extends kDBTagProcessor
	{
		function LogoutLink($params)
		{
			$pass = Array('pass' => 'all,m,u', 'u_event' => 'OnLogout', 'm_cat_id' => 0);
			$logout_template = $this->SelectParam($params, 'template,t');
			return $this->Application->HREF($logout_template, '', $pass);
		}

		function RegistrationEnabled($params)
		{
			return $this->Application->ConfigValue('User_Allow_New') != 2;
		}

		function SuggestRegister($params)
		{
			return !$this->Application->LoggedIn() && !$this->Application->ConfigValue('Comm_RequireLoginBeforeCheckout') && $this->RegistrationEnabled($params);
		}

		function ConfirmPasswordLink($params)
		{
			$user = $this->Application->recallObject($this->Prefix . '.email-to');
			/* @var $user UsersItem */

			$code = $this->getCachedCode();
			$user->SetDBField('PwResetConfirm', $code);
			$user->SetDBField('PwRequestTime_date', adodb_mktime());
			$user->SetDBField('PwRequestTime_time', adodb_mktime());

			if ( $user->GetChangedFields() ) {
				// tag is called 2 times within USER.PWDC email event, so don't update user record twice
				$user->Update();
			}

		    $params['user_key'] = $code;

		    if ( !$this->SelectParam($params, 'template,t') ) {
		    	$params['template'] = $this->Application->GetVar('reset_confirm_template');
		    }

		    return $this->Application->ProcessParsedTag('m', 'Link', $params);
		}

		/**
		 * Generates & caches code for password confirmation link
		 *
		 * @return string
		 */
		function getCachedCode()
		{
			static $code = null;

			if ( !isset($code) ) {
				$code = md5($this->GenerateCode());
			}

			return $code;
		}

		function GenerateCode()
		{
			list($usec, $sec) = explode(" ",microtime());

			$id_part_1 = substr($usec, 4, 4);
			$id_part_2 = mt_rand(1,9);
			$id_part_3 = substr($sec, 6, 4);
			$digit_one = substr($id_part_1, 0, 1);

			if ($digit_one == 0) {
				$digit_one = mt_rand(1,9);
				$id_part_1 = preg_replace('/^0/', '', $id_part_1);
				$id_part_1=$digit_one.$id_part_1;
			}

			return $id_part_1.$id_part_2.$id_part_3;
		}

		function TestCodeIsValid($params)
		{
			$user_helper = $this->Application->recallObject('UserHelper');
			/* @var $user_helper UserHelper */

			$code_type = isset($params['code_type']) ? $params['code_type'] : 'forgot_password';
			$expiration_timeout = isset($params['expiration_timeout']) ? $params['expiration_timeout'] : null;
			$user_id = $user_helper->validateUserCode($this->Application->GetVar('user_key'), $code_type, $expiration_timeout);

			if ( !is_numeric($user_id) ) {
				// used for error reporting only -> rewrite code + theme (by Alex)
		     	$object = $this->getObject( Array('skip_autoload' => true) ); // TODO: change theme too
				/* @var $object UsersItem */

				$object->SetError('PwResetConfirm', $user_id, $this->_getUserCodeErrorMsg($user_id, $code_type, $params));

				return false;
			}

			return true;
		}

		/**
		 * Tries to restore user email
		 *
		 * @param Array $params
		 * @return bool
		 * @access protected
		 */
		protected function RestoreEmail($params)
		{
			$user_helper = $this->Application->recallObject('UserHelper');
			/* @var $user_helper UserHelper */

			$hash = $this->Application->GetVar('hash');
			$error_code = $user_helper->restoreEmail($hash);

			if ( $error_code ) {
				// used for error reporting only -> rewrite code + theme (by Alex)
				$object = $this->getObject(Array ('skip_autoload' => true)); // TODO: change theme too
				/* @var $object UsersItem */

				$object->SetError('PwResetConfirm', 'restore', $params[$error_code]);

				return false;
			}

			return true;
		}

		/**
		 * Returns error message set by given code type
		 *
		 * @param string $error_code
		 * @param string $code_type
		 * @param Array $params
		 * @return string
		 */
		function _getUserCodeErrorMsg($error_code, $code_type, $params)
		{
			$error_messages = Array (
				'forgot_password' => Array (
					'code_is_not_valid' => 'lu_code_is_not_valid',
					'code_expired' => 'lu_code_expired',
				),

				'activation' => Array (
					'code_is_not_valid' => 'lu_error_ActivationCodeNotValid',
					'code_expired' => 'lu_error_ActivationCodeExpired',
				),

				'verify_email' => Array (
					'code_is_not_valid' => 'lu_error_VerificationCodeNotValid',
					'code_expired' => 'lu_error_VerificationCodeExpired',
				),
			);

			if ($code_type == 'custom') {
				// custom error messages are given directly in tag
				$error_messages[$code_type] = Array (
					'code_is_not_valid' => $params['error_invalid'],
					'code_expired' => $params['error_expired'],
				);
			}

			return $error_messages[$code_type][$error_code];
		}

		/**
		 * Returns site administrator email
		 *
		 * @param Array $params
		 * @return string
		 */
		function SiteAdminEmail($params)
		{
			return $this->Application->ConfigValue('DefaultEmailSender');
		}

		/**
		 * Returns login name of user
		 *
		 * @param Array $params
		 * @return string
		 * @access protected
		 */
		protected function LoginName($params)
		{
			$object = $this->getObject($params);
			/* @var $object UsersItem */

			return $object->GetID() != USER_ROOT ? $object->GetDBField('Username') : 'root';
		}

		function CookieUsername($params)
		{
			$items_info = $this->Application->GetVar( $this->getPrefixSpecial(true) );

			if ( $items_info !== false ) {
				return $items_info[USER_GUEST][ $params['field'] ];
			}

			$username = $this->Application->GetVar('save_username'); // from cookie

			if ($username == 'super-root') {
				$username = 'root';
			}

			return $username === false ? '' : $username;
		}

		/**
		 * Checks if user have one of required permissions
		 *
		 * @param Array $params
		 * @return bool
		 */
		function HasPermission($params)
		{
			$perm_helper = $this->Application->recallObject('PermissionsHelper');
			/* @var $perm_helper kPermissionsHelper */

			return $perm_helper->TagPermissionCheck($params);
		}

		/**
		 * Returns link to user public profile
		 *
		 * @param Array $params
		 * @return string
		 */
		function ProfileLink($params)
		{
			$object = $this->getObject($params);
			$params['user_id'] = $object->GetID();

			return $this->Application->ProcessParsedTag('m', 'Link', $params);
		}

		function ImageSrc($params)
		{
			list ($ret, $tag_processed) = $this->processAggregatedTag('ImageSrc', $params, $this->getPrefixSpecial());
			return $tag_processed ? $ret : false;
		}

		function LoggedIn($params)
		{
			static $loggedin_status = Array ();

			$object = $this->getObject($params);
			/* @var $object kDBList */

			if (!isset($loggedin_status[$this->Special])) {
				$user_ids = $object->GetCol($object->IDField);
				$sql = 'SELECT LastAccessed, '.$object->IDField.'
						FROM '.TABLE_PREFIX.'UserSessions
						WHERE (PortalUserId IN ('.implode(',', $user_ids).'))';
				$loggedin_status[$this->Special] = $this->Conn->GetCol($sql, $object->IDField);
			}

			return isset($loggedin_status[$this->Special][$object->GetID()]);
		}

		/**
		 * Prints user activation link
		 *
		 * @param Array $params
		 * @return string
		 */
		function ActivationLink($params)
		{
			$object = $this->getObject($params);
			/* @var $object kDBItem */

			$code = $this->getCachedCode();
			$object->SetDBField('PwResetConfirm', $code);
			$object->SetDBField('PwRequestTime_date', adodb_mktime());
			$object->SetDBField('PwRequestTime_time', adodb_mktime());
			$object->Update();

		    $params['user_key'] = $code;

		    return $this->Application->ProcessParsedTag('m', 'Link', $params);
		}

		/**
		 * Returns link to revert e-mail change in user record
		 *
		 * @param Array $params
		 * @return string
		 * @access protected
		 */
		protected function UndoEmailChangeLink($params)
		{
			$params['hash'] = $this->Application->Parser->GetParam('hash');

			if ( !$this->SelectParam($params, 'template,t') ) {
				$params['template'] = $this->Application->GetVar('undo_email_template');
			}

			return $this->Application->ProcessParsedTag('m', 'Link', $params);
		}

		/**
		 * Activates user using given code
		 *
		 * @param Array $params
		 * @return string
		 * @access protected
		 */
		protected function ActivateUser($params)
		{
			$this->_updateAndLogin(Array ('Status' => STATUS_ACTIVE, 'EmailVerified' => 1));

			return '';
		}

		/**
		 * Marks user e-mail as verified using given code
		 *
		 * @param Array $params
		 * @return string
		 * @access protected
		 */
		protected function MarkUserEmailAsVerified($params)
		{
			$this->_updateAndLogin(Array ('EmailVerified' => 1));

			return '';
		}

		/**
		 * Activates user using given code
		 *
		 * @param Array $fields_hash
		 * @return void
		 * @access protected
		 */
		protected function _updateAndLogin($fields_hash)
		{
			$user_helper = $this->Application->recallObject('UserHelper');
			/* @var $user_helper UserHelper */

			$user = $this->Application->recallObject($this->Prefix . '.activate', null, Array ('skip_autoload' => true));
			/* @var $user UsersItem */


			$user->Load(trim($this->Application->GetVar('user_key')), 'PwResetConfirm');

			if ( !$user->isLoaded() ) {
				return ;
			}

			$user->SetFieldsFromHash($fields_hash);
			$user->SetDBField('PwResetConfirm', '');
			$user->SetDBField('PwRequestTime_date', NULL);
			$user->SetDBField('PwRequestTime_time', NULL);
			$user->Update();

			$login_user =& $user_helper->getUserObject();
			$login_user->Load( $user->GetID() );

			if ( ($login_user->GetDBField('Status') == STATUS_ACTIVE) && $user_helper->checkLoginPermission() ) {
	    		$user_helper->loginUserById( $login_user->GetID() );
			}
		}
	}