<?php
/*
* @package LabCMS
* @copyright (c) 2006 Alexander Levin aka Loki (loki_angel@mail.ru)
* @support http://labcms.ru
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*/

class login_profile
{
	public $avatar_width=75;
	public $avatar_height=75;
	public $types=array(	1 => 'gif',
							2 => 'jpg',
							3 => 'png');
	public $use_openid=false;
	public $allow_register=false;
	public $allow_ask_new_pass=false;
	public $activation=false;
	public $default_group=2;
	
	public $providers=array();
	
	public $validation=1;
	
	/*actions*/
	
	function __construct()
	{
		//проверка полей на сервере и на клиенте
		$this->validation=HTML_QuickForm2_Rule::CLIENT_SERVER;

		$this->allow_register=config::get('allow_register');
		$this->use_openid=config::get('use_openid');
		
		$this->allow_ask_new_pass=config::get('allow_ask_new_pass');
		$this->activation=config::get('activation');
		if (config::get('default_group')) $this->default_group=config::get('default_group');
	
		//размер аватары
		if (config::get('avatar_size')) {
			list ($this->avatar_width, $this->avatar_height) = explode('x', config::get('avatar_size'));
			if (intval($this->avatar_width)<=0 || intval($this->avatar_height)<=0) {
				$this->avatar_width=$this->avatar_height=75;
			}
		}
	}
	
	/**
	 * авторизация пользователя по логину и паролю или отправка openid запроса
	 */
	public function login()
	{
		$login_secsess=false;

		$form=$this->_getForm('auth');
		if ($form->validate()) {
			$data=$form->getValue();
			if ($data['login']) {
				$user=User::getUser();
				$user->loadUserDataByLogin($data['login']);
				if ($user->isGuest()) $this->error(_m('Пользователь не найден'));
				elseif (!$user->isPasswordCorrect($data['pass'])) $this->error(_m('Неправильно набран пароль'));
				elseif ($user->isDeleted()) $this->error(_m('Пользователь удален'));
				elseif (!$user->isActivated()) $this->error(_m('Пользователь не активирован'));
				else $login_secsess=true;
			} elseif ($data['openid']) {
				$this->_sendOpenidRequest($data['openid'], $_POST['rememberme'], $_REQUEST['redirect']);
			}
		}

		if ($login_secsess) {
			User::i()->setCurrentUser($user);
			if ($data['rememberme']) User::i()->SetCookieAuth();
			$this->_setLastLoginTime();
			User::i()->update(array('last_ip'=>inet_pton(User::getIP())));
			$helloMsg=sprintf(_m('Привет, %s'), htmlspecialchars(User::i()->login));
			$redirect=(empty($_REQUEST['redirect']))?$_SERVER['REQUEST_URI']:$_REQUEST['redirect'];
			if (config::get('use_ec')) {
				Tpl::i()->assign(array('url'=>$redirect, 'text'=>$helloMsg));
				Tpl::i()->display('login/ec.tpl');
				exit;
			} else {
				refresh($helloMsg, $redirect);
			}
		} else {
			$this->assign('form', $this->_renderForm($form));
		}				
	}
	
	/**
	 * формирование и отправка openID запроса
	 * 
	 * @param string $openid     openID идентификатор
	 * @param boolean $rememberme установить куку авторизации
	 * @param string $redirect   путь редиректа после авторизации
	 * 
	 */
	protected function _sendOpenidRequest($openid, $rememberme=null, $redirect=null)
	{
		$oid=Factory::create('OpenId');
		$oid->returnTo=$oid->getTrustRoot()
						._url(false, 'openid_auth')
						.'?'
						.(!empty($rememberme)?"rememberme=1&":'')
						.(!empty($redirect)?"redirect=".urlencode((string)$redirect):'');
		$oid->SendOpenId($openid);
	}
	
	/**
	 * Управление openid пользователя
	 */
	public function OpenId()
	{
		$form=$this->_getForm('ChangeOpenID');
		if ($form->validate()) {
			$data=$form->getValue();
			if ($data['delopenid']) User::i()->deleteOpenID(array_keys($data['delopenid']));
			if ($data['openid']) {
				$oid=Factory::create('OpenId');
				$oid->returnTo=$oid->getTrustRoot()._url(false, 'add_openid');
				$oid->SendOpenId($data['openid']);
			} else refresh('', _url(false, 'openid'));
		}
		
		$this->assign('form', $this->_renderForm($form));
	}
	
	/**
	 * редактирование данных пользователя
	 */
	public function editInfo()
	{
		$form=$this->_getForm('userInfo');
		
		if ($form->validate()) {
			$this->updateUserInfo(User::i()->id, $form->getValue());
		}
		
		$this->assign('form', $this->_renderForm($form));
	}
	
	public function lostPassword()
	{
		$sended=false;
		$form=$this->_getForm('lostPass');
		if ($form->validate()) {
			$data=$form->getValue();
			$sended=$this->sendNewPassword($data['recover_info']);
		}

		if (!$sended) $this->assign('form', $this->_renderForm($form));
	}
	
	
	public function register()
	{
		$form=$this->_getForm('register');
		isNotBot($_POST['login']);
		
		if ($form->validate()) {
			$data=$this->_prepareRegisterData($form->getValue());
			if ($user=$this->_insertUser($data)) {
				if ($user && !$this->activation) {
					User::i()->setCurrentUser($user);
					$this->setMessage('Спасибо за регистрацию!');
				}
			}
		}

		if (!$user) $this->assign('form', $this->_renderForm($form));
	}
	
	public function registerByOpenId()
	{
		$data=$this->getRegisterByOpenIdData();
		if ($data) {
			$form=$this->_getForm('registerByOpenID', $data);
			if ($form->validate()) {
				$data=$form->getValue();
				if ($user=$this->_insertUser($data)) {
					$user->addOpenID($data['openid']);
					if ($user && !$this->activation) {
						User::i()->setCurrentUser($user);
						$this->setMessage('Спасибо за регистрацию!');
					}
				}
			}
			
			if (!$user) $this->assign('form', $this->_renderForm($form));
		}
	}
	
	function authByOpenID()
	{
		
		if (!empty($_GET['openid_mode']) && $this->use_openid) {
			$oid=Factory::create('OpenId');
			$open_id=$oid->CheckAuthByOpenId();
			if (!$open_id) return false;
			$user=User::getUser();
			$user->loadUserDataByOpenId($open_id);
			if ($user->isGuest()) LabCMS::i()->error(sprintf(_m('Пользователь %s не найден'), $open_id), true);
			else {
				User::i()->setCurrentUser($user);
				$this->_setLastLoginTime();
				if (empty($_REQUEST['redirect'])) refresh();
				$this->assign('redirect', $_REQUEST['redirect']);
				$this->assign('login_secsess', true);
			}
		}
	}

	protected function _setLastLoginTime()
	{
		$_SESSION['last_login_time'][User::i()->id]=time();
	}
	
	function reGetCode()
	{
		$form=$this->_getForm('reGetCode');
		$sended=false;
		if ($form->validate()) {
			$data=$form->getValue();
			$sended=$this->_resendActivationCode($data['email']);
		}

		if (!$sended)	$this->assign('form', $this->_renderForm($form));
	}
	
	function changePass()
	{
		$form=$this->_getForm('changePassword');

		if ($form->validate()) {
			$data=$form->getValue();
			if (User::i()->update(array('pass'=>$data['newpass']))) {
				$this->setMessage('Пароль изменен');
			}
		}

		$this->assign('form', $this->_renderForm($form));
	}
	
	function addOpenID()
	{
		$oid=Factory::create('OpenId');
		
		if ($openid=$oid->CheckAuthByOpenId()) {
			$user=User::getUser();
			$user->loadUserDataByOpenId($openid);
			if ($user->isNotGuest()) {
				if ($user->id!=User::i()->id) $this->error(sprintf(_m('Такой OpenID уже зарегистрирован: %s'), $openid));
				else return $openid;
			} else {
				if (User::i()->addOpenID($openid))	return $openid;
			}
		}
		return false;
	}


	public function activation()
	{
		$user=User::getUser();
		$user->loadUserDataById($_GET['var1']);
	
		if ($user->isNotGuest()) {
			if ($user->status > 0) {
				$this->error(_m('Аккаунт уже был активирован'));
				return false;
			}
	
			if ($user->actkey!=$_GET['var2']) {
				$this->error(_m('Неправильный код активации!'));
				return false;
			} else {
				$user->update(array('status'=>1));
				User::i()->setCurrentUser($user);
				$this->_setLastLoginTime();
				$this->setMessage("Спасибо за активацию!");
				return true;
			}
		} else {
			$this->error(_m('Такой пользователь в базе не числится!'));
			return false;
		}
	}
	
	function sendNewPassword($identy)
	{
		$user=User::getUser();
		$user->loadUserDataByLogin($identy);
		if ($user->isGuest()) $user->loadUserDataByEmail($identy);
		if ($user->isGuest()) return $this->error(_m('Пользователь не найден'));
		if ($user->isDeleted()) return $this->error(_m('Пользователь удален'));
		if (!$user->isActivated()) return $this->error(_m('Пользователь не активирован'));
		
		$retrive = array(
		'id'=>$user->id,
		'login'=>$user->login,
		'email'=>$user->email,
		'key'=>md5($this->_genKey(10))
		);
		
		$user->update(array('actkey'=>$retrive['key']));
		
		$email=array($user->email=>($user->realname?$user->realname:$user->login));
		$mail=Factory::create('Mailer', $email);
		$this->assign("retrive", $retrive);

		$message = Tpl::i()->fetch('login/newpass_mail.tpl');

		$mail->From     = 'robot@'.config::get('core.domain');
		$mail->Subject = _m("Восстановление пароля для сайтa")." ".config::get('core.siteUrl');
		$mail->Body     =  $message;
		$mail->AltBody  =  strip_tags($message);
		if (!$mail->Send()) {
			  $this->error(_m('Ошибка работы почтового робота'));
			  return false;
		}
		
		$mail=parse_url('http://'.$user->email);
		$mail['user']=(strlen($mail['user'])>2)?preg_replace('/^(.).*(.)$/', '\1***\2', $mail['user']):'***';
		
		$this->setMessage(_m('Новый пароль отправлен на почтовый адрес ').$mail['user'].'@'.$mail['host'], false, true);
		return true;
	}
	
	
	function updateUserInfo($user_id, $data)
	{
		if ($data['avatar']['size'])
			if (!$data['avatar']=$this->_addAvatar($data['avatar']['tmp_name'], $user_id)) return;
		if ($data['del_avatar']) $data['avatar']=$this->_removeAvatar($user_id);

		//убираем данные, которые в базе не нужны
		unset($data['del_avatar'], $data['_qf__profile'], $data['token']);
		if (is_array($data['avatar'])) unset($data['avatar']);
		
		$data["website"] = preg_replace('#^https?://#i', '', $data["website"]);
		$data["icq"] = intval($data["icq"])?intval($data["icq"]):null;
		$user=User::getUser();
		$user->loadUserDataById($user_id);
		$user->update($data);// Обновим пользователя

		$this->_setLastLoginTime();

		refresh('', _url(false, 'profile'));

	}
	
	
	protected function _prepareRegisterData($data)
	{
		if ($this->activation) $this->_celeanUnactivatedUsers();
		$data['login']=$data[config::get('core.catcher')];
		unset($data[config::get('core.catcher')]);
		return $data;
	}
	
	protected function _insertUser($data)
	{
		$row["login"]=preg_replace('/\s+/', ' ', trim($data['login']));
		$row["email"]=trim($data['email']);
		$row['group_id']=$this->default_group;
		$row['pass']=$data['pass'];
		
		if ($this->activation) $row["actkey"] = $this->_genKey(12);
		else $row['status']=1;
		
		$user=User::getUser();
		$info=$user->add($row);
		if ($info) {
			if ($this->activation) $this->_sendActivationCode($info);
			return $user;
		}
	}
	
	
	public function getRegisterByOpenIdData()
	{
		$data=array();
		if ($_SERVER['REQUEST_METHOD']=='GET' && $this->use_openid) {
			$oid=Factory::create('OpenId');
			$openIdData=$oid->CheckAuthByOpenId($oid->getReturnTo());
			if ($openIdData) $_SESSION['register_code']=md5(rand()*rand());
			if (is_array($openIdData)) {
				return array(	'login'=>$openIdData['nickname'],
								'email'=>$openIdData['email'],
								'openid'=>$openIdData['openid']);
			} elseif ($openIdData) {
				return array('openid'=>$openIdData, 'register_code'=>$_SESSION['register_code']);
			} else {
				$this->error(_m('Не удалось получить от сервера корректный ответ'));
				return false;
			}
		}
		return true;
	}

	
	public function deleteAccount($user_id)
	{
		$user=User::getUser();
		$user->loadUserDataById($user_id);
		return $user->update(array('status'=>-1));
	}
	
	protected function _addAvatar($file, $user_id)
	{
		if (!is_dir(LAB_PATH_ROOT.'/storage/Image/avatars/')) {
			if (!mkdir(LAB_PATH_ROOT.'/storage/Image/avatars/', 0777, true)) {
				return LabCMS::i()->error(
					sprintf(
						_m('Не могу создать каталог %s'),
						'/storage/Image/avatars/'
					),
					true
				);
			}
		}
		$size=getimagesize($file);
		
		$img=Factory::create('Image_Resize');
		$img->file=$file;
		$img->width=$this->avatar_width;
		$img->height=$this->avatar_height;
		$img->crop=true;
		$img->file_dest=LAB_PATH_ROOT.'/storage/Image/avatars/'.$user_id.'.'.$this->types[$size[2]];
		if ($img->go()) return $size[2];
		return LabCMS::i()->error(_m('Не удалось загрузить изображение'));;
	}
	
	
	protected function _removeAvatar($user_id)
	{
		$avatars=glob(LAB_PATH_ROOT.'/storage/Image/avatars/'.$user_id.'.*');
		if ($avatars[0]) unlink($avatars[0]);
		return 0;
	}
	
	public function retrivePassword()
	{
		if ($_GET['var1'] && $_GET['var2']) {
			$user=User::getUser();
			$user->loadUserDataById($_GET['var1']);
			if ($user->isNotGuest() && $user->actkey && $user->actkey==$_GET['var2']) {
				$data=array('actkey'=>'');
				$user->update($data);
				User::i()->setCurrentUser($user);
				$this->_setLastLoginTime();
				refresh('', _url(false, 'change_pass'));
				return true;
			}
		}
		$this->error(_m('Неверный код активации!'));
		return false;
	}
	
	
	protected function _sendActivationCode($data)
	{
		$this->assign('reg', $data);
		
		if (Tpl::i()->templateExists(LabCMS::i()->getModuleName().'/activation_mail.tpl'))
			$mess = Tpl::i()->fetch(LabCMS::i()->getModuleName().'/activation_mail.tpl');
		else
			$mess = Tpl::i()->fetch('login/activation_mail.tpl');
		
		$mail=Factory::create('Mailer', array($data["email"]=>$data["login"]));
		$mail->From     = 'robot@'.config::get('core.domain');
		$mail->FromName = "Robot";
		$mail->Subject = _m('Регистрация на ').config::get('core.domain');
		$mail->Body    = $mess;
		$mail->AltBody = strip_tags($mess);
		if ($mail->Send()) {
			$this->setMessage(
				sprintf(
					_m('На адрес %s отправленно сообщение со ссылкой для подтверждения регистрации.'),
					$data["email"]
				), false, true
			);
			$mail->ClearAddresses();
			return true;
		}
		$mail->ClearAddresses();
		$this->error(_m('Ошибка работы почтового робота'));
		return false;
		
	}
	
	
	protected function _resendActivationCode($email)
	{
		$data=Db::i()->selectRow(
			"SELECT login, realname, user_id, email, actkey, `status`, user_id as id
			FROM ?_users WHERE email=?",
			trim($email)
		);
		if (!$data) $this->error(_m('Такой адрес в базе не зарегистрирован'));
		elseif ($data['status']!=0) $this->error(_m('Этот аккаунт уже активирован'));
		else return $this->_sendActivationCode($data);
		return false;
	}
	
	
	protected function _celeanUnactivatedUsers()
	{
		Db::i()->query("DELETE FROM ?_users WHERE register_date<NOW()-INTERVAL 7 DAY AND `status`=0 AND user_id!=-1");
	}
	
	protected function _genKey($int)
	{
		$key = '';
			$alpha = array("a","b","c","d","e","f","g","h","i","g","k","l","m","n","o","p","q","r","s","t",
			"u","v","w","x","y","z","A","B","C","D","E","F","G","H","I","G","K","L","M","N","O","P","Q","R",
			"S","Y","U","V","W","X","Y","Z","1","2","3","4","5","6","7","8","9","0");
		for ($i=0;$i < $int;$i++) {
			$key .= $alpha[rand(0, count($alpha))];
		}
		return $key;
	}
	
	
	static function IsLoginExists($login)
	{
		if (User::i()->isLoginExists($login)) return false;
		return true;
	}

	
	protected function setRedirect($redirect='', $time=0)
	{
		if (!$redirect) $redirect=$_SERVER['REQUEST_URI'];
		$this->assign('redirect', '<meta http-equiv="refresh" content="'.$time.';url='.htmlspecialchars($redirect).'" />');
	}
	
	protected function _setUserLogged($user_id)
	{
		$info=Db::i()->selectRow("SELECT user_id, group_id FROM ?_users WHERE user_id=?", $user_id);
	}
	
	public function assign($var, $val)
	{
		Tpl::i()->assign($var, $val);
	}
	
	public function setMessage($text, $html=false, $lang=false)
	{
		LabCMS::i()->setMessage($text, $html, $lang);
	}
	
	public function error($text)
	{
		LabCMS::i()->error(_m($text));
	}
	
	function getUserIdByOpenId($openid)
	{
		return Db::i()->selectCell("SELECT user_id FROM ?_openid WHERE openid=?", $openid);
	}
	
	protected function _getForm($form)
	{
		if (!isset($this->form) || !$this->form) $this->form=Factory::create('login.forms');
		$this->form->validation=$this->validation;
		$this->form->avatar_width=$this->avatar_width;
		$this->form->avatar_height=$this->avatar_height;
		$this->form->use_openid=$this->use_openid;
		
		$this->form->types=$this->types;
		
		$args = func_get_args();
        array_shift($args);

		return call_user_func_array(array($this->form, $form), $args);
	}

	protected function _renderForm($form)
	{
		$renderer = HTML_QuickForm2_Renderer::factory(config::get('core.form_renderer'));
		$renderer=$form->render($renderer);
		LabCMS::i()->skins[LabCMS::i()->getSkin()]['js']=
			LabCMS::i()->skins[LabCMS::i()->getSkin()]['js']
			+$renderer->getJSLibs(false, false);
		return $renderer;
	}
}