<commit_before><?php
/**
 * Improved version of BasicAuth.
 * Login/password retrieved from DB table
 * Functionality of password recovery and new user registration is included.
 * 
 * Passwords could be stored as plain text or sha1 hash. By default they are encrypted.
 * If you do not want them to be encrypted - use Auth::setEncrypted(false)
 * 
 * If you want to use password recovery feature:
 * - add a link to password recovery page: Auth::addPwdRecoveryLink()
 * - specify a page name to password recovery in your config.php
 * 
 * If you want to use register feature:
 * - create a page with the user registration data
 * - add a link to login form: Auth::addRegisterLink()
 * - specify register page in your config.php
 * 
 * Created on 04.07.2006 by *Camper* (<EMAIL>)
 */
class DBAuth extends BasicAuth{
    public $dq;
    private $name_field;
    private $pass_field;
    private $email_field;
    private $secure = true;
    private $can_register = false;
    private $show_lost_password = false;

	function init(){
		parent::init();
		$this->api->addHook('pre-exec',array($this,'check'));
		//process recovery and register
		if($this->api->page==$this->api->getConfig('auth/register_page')){
			$this->api->addHook('post-init', array($this, 'processRegister'));
		}
		if($this->api->page==$this->api->getConfig('auth/pwd_recovery/page')){
			$this->api->addHook('post-init', array($this, 'processRecovery'));
			//$this->processRecovery();
		}
	}
	function processRegister(){
		$p=$this->add('Page');
        $p->template->loadTemplate('empty');
		$p->add('page_'.$this->api->getConfig('auth/register_page'), null, 'Content');
		$p->downCall('render');
		echo $p->template->render();
		exit;
	}
	function processRecovery(){
		$p=$this->add('Page');
		$p->template->loadTemplate('empty');
		if($_GET['key']){
			//user clicked link in e-mail
			$this->api->stickyGET('rp');
			$this->api->stickyGET('key');
			$id=$_GET['rp'];
			$key=$_GET['key'];
	   		$row=$this->api->db->getHash("select * from ".$this->api->getConfig('auth/pwd_recovery/table').
	    			" where id=$id and changed=0");
	    	//looking for the key in DB and checking expiration dts
	   		$db_key=sha1($row['id'].$row['email'].strtotime($row['expire']));
	   		$can_change=$db_key==$key&&strtotime($row['expire'])>time();
	    	if($can_change){
	    		//displaying changepass form
	    		$username=$this->api->db->getOne("select $this->name_field from ".
	    			$this->dq->args['table']." where id=".$row['user_id']);
	    		
				$form=$p->frame('Content', "Change password for $username")->add('Form', null, 'content');
				$form
					->addField('hidden', 'rp_id')
					->addField('password', 'password', '<PASSWORD>')
						->validateField('strlen($this->get(\'password\'))>=6', 'Password is too short')
					->addField('password', '<PASSWORD>', '<PASSWORD>')
						//TODO validation does not work
						->validateField('$this->get(\'password2\')==$this->get(\'password\')', 
						'Confirmation differs from password')
					->addField('checkbox', 'send', 'Send me new password by e-mail')
			
					->addSubmit('Change')
				;
				if(isset($_REQUEST['rp']))$form->set('rp_id', $_REQUEST['rp']);
				if($form->isSubmitted()){
					//getting a user id
					$user_id=$this->api->db->getOne("select user_id from ".
						$this->api->getConfig('auth/pwd_recovery/table').
						" where id = ".$form->get('rp_id'));
					//changing password
					$this->api->db->query("update ".$this->dq->args['table']." set ".$this->pass_field.
						" = '".$this->encrypt($form->get('password')).
							"' where id = $user_id");
					//storing info about changes
					$this->api->db->query("update ".$this->api->getConfig('auth/pwd_recovery/table').
							" set changed=1, changed_dts=SYSDATE()" .
							" where id=".$form->get('rp_id'));
					$p->add('Text', null, 'Content')->set('<center>Password changed succefully</center>');
					if($form->get('send')=='Y')$this->sendPassword($user_id, $form->get('password'));
					unset($this->api->sticky_get_arguments['rp']);
					unset($this->api->sticky_get_arguments['key']);
					$p->add('Text', 'back', 'Content')->set("<div align=center><a href=".
						$this->api->getDestinationURL('Index').">Back to main page</a></div>");
				}
	    	}else{
	    		//denial page
				unset($this->api->sticky_get_arguments['rp']);
				unset($this->api->sticky_get_arguments['key']);
	    		$p->frame('Content', 'Request error')->add('Text', null, 'content')
	    			->set("Sorry, this page is not valid. Activation period might have been expired." .
	    			" <a href=".
					$this->api->getDestinationURL($this->api->getConfig('auth/pwd_recovery/page')).
					">Click here</a> if You want to repeat Your request.");
				$p->add('Text', 'back', 'Content')->set("<div align=center><a href=".
					$this->api->getDestinationURL('Index').">Back to main page</a></div>");
	    	}
		}else{
			//displaying a form with username for password recovery
			$form=$p->frame('Content', 'Password recovery')->add('Form', 'pwd_recovery_form', 'content');
			$form
				->addComment('To restore Your password please enter a username specified at registration')
				->addField('line', 'username', 'Username')
				
				->addSubmit('Submit')
			;
			if($form->isSubmitted()){
				$user=$this->api->db->getHash("select id, $this->name_field, $this->email_field from ".DTP.
					$this->dq->args['table']." where $this->name_field='".
					$form->get('username')."'");
				if(sizeof($user)!=0){
					//generating and sending e-mail
					$this->sendChangeLink($user['id'], $user[$this->name_field], $user[$this->email_field]);
					$p->add('Text', null, 'Content')->set("<div align=center>An e-mail with instruction " .
						"to restore password has been sent" .
						" to user '".$form->get('username')."'</div>");
					$p->add('Text', 'back', 'Content')->set("<div align=center><a href=".
						$this->api->getDestinationURL('Index').">Back to main page</a></div>");
				}else{
					throw new BaseException("User with a name you specified have not been found. Please try again");
				}
			}
		}
		$p->downCall('render');
		echo $p->template->render();
		exit;
	}
	function sendPassword($user_id, $password){
		//TODO make template based
		$server=$_SERVER['SERVER_NAME'];
		$address=$this->api->db->getOne("select $this->email_field from ".$this->dq->args['table'].
			" where id=".$user_id);
		//combining a message
		$msg="This is $server password recovery subsystem.\n\nHere is your new password : " .
			$password;
		$subj="Your password has changed";
		$from="noreply@$server";
		$headers = "From: $from \n";
		//$headers .= "Return-Path: <".$this->owner->settings['return_path'].">\n";
		//$headers .= "To: $to \n"; 
		$headers .= "MIME-Version: 1.0 \n"; 
		//$headers .= "Content-Type: text/plain; charset=KOI8-R; format=flowed Content-Transfer-Encoding: 8bit " .
		//		"\n"; 
		$headers .= "X-Mailer: PHP script "; 
		
		mail($address, $subj, $msg, $headers);
	}
	protected function sendChangeLink($user_id, $username, $address){
		//TODO make template based
		//adding a DB record with a key to a change password page
		$table=DTP.$this->api->getConfig('auth/pwd_recovery/table');
		$expire=time()+$this->api->getConfig('auth/pwd_recovery/timeout', 15)*60;
		$this->api->db->query("insert into $table (user_id, email, expire) values($user_id, '$address', " .
				"'".date('Y-m-d H:i:s', $expire)."')");
		$id=mysql_insert_id();
		$server=$_SERVER['SERVER_NAME'];
		//combining a message
		$msg="This is $server password recovery subsystem.\n\nWe recieved the request " .
				" to change the password for the user '$username'. To change your password " .
				"click the link below. REMEMBER: this link is actual for a period of ".
				$this->api->getConfig('auth/pwd_recovery/timeout', 15)." minutes only. If you do not change the password " .
				"during this period, you will have to make a new change request.\n\n".
				"http://".$server.dirname($_SERVER['PHP_SELF'])."/".
				$this->api->getDestinationURL(null, array('rp'=>$id, 'key'=>sha1($id.$address.$expire)));
		$subj="Password recovery";
		$from="noreply@$server";
		$headers = "From: $from \n";
		//$headers .= "Return-Path: <".$this->owner->settings['return_path'].">\n";
		//$headers .= "To: $to \n"; 
		$headers .= "MIME-Version: 1.0 \n"; 
		//$headers .= "Content-Type: text/plain; charset=KOI8-R; format=flowed Content-Transfer-Encoding: 8bit " .
		//		"\n"; 
		$headers .= "X-Mailer: PHP script "; 
		
		mail($address, $subj, $msg, $headers);
	}
	function setEncrypted($secure=true){
		$this->secure=$secure;
		return $this;
	}
	function setPassword($password){
		return false;
	}
    function setSource($table,$login='login',$password='password',$email='email'){
    	$this->name_field = $login;
    	$this->pass_field = $password;
    	$this->email_field = $email;
        $this->dq=$this->api->db->dsql()
            ->table($table)
            ->field($this->name_field)
            ->field($this->pass_field);
        return $this;
    }
    function verifyCredintals($user,$password){
    	$data=$this->dq->where($this->name_field, $user)->do_getHash();
    	return(sizeof($data)>0&&($data[$this->pass_field]==$password||$data[$this->pass_field]==sha1($password)));
    }
	private function encrypt($str){
		return $this->secure?sha1($str):$str;
	}
    function loggedIn(){
    	parent::loggedIn();
    	$this->info=array_merge($this->info, $this->dq->do_getHash());
        $this->memorize('info',$this->info);
    }
	function showLoginForm(){
		$p=parent::showLoginForm();
		if($this->can_register){
			$this->form->add('RegisterLink', null, 'form_body');
		}
		if($this->show_lost_password){
			$this->form->add('PwdRecoveryLink', null, 'form_body');
		}
		return $p;
	}
	function addRegisterLink(){
		$this->can_register=true;
		return $this;
	}
	function addPwdRecoveryLink(){
		$this->show_lost_password=true;
		return $this;
	}
}
class RegisterLink extends Text{
	function init(){
		parent::init();
		$this->set('<tr><td align=left><a href='.
			$this->api->getDestinationURL($this->api->getConfig('auth/register_page')).'>Register</a></td><td></td></tr>');
	}
}
class PwdRecoveryLink extends Text{
	function init(){
		parent::init();
		$this->set('<tr><td align=left><a href='.
			$this->api->getDestinationURL($this->api->getConfig('auth/pwd_recovery/page')).
			'>Lost password</a></td><td></td></tr>');
	}
}
<commit_msg>DBAuth seems to be comleted. See https://btarea.com/gateway/mediawiki/index.php/DBAuth for changes and detailed info<commit_after><?php
/**
 * Improved version of BasicAuth.
 * Login/password retrieved from DB table
 * Functionality of password recovery and new user registration is included.
 * 
 * Passwords could be stored as plain text or sha1 hash. By default they are encrypted.
 * If you do not want them to be encrypted - use Auth::setEncrypted(false)
 * 
 * If you want to use password recovery feature:
 * - create a fake page for password recovery (it is needed!)
 * - add a link to password recovery page: Auth::addPwdRecoveryLink()
 * - specify a page name to password recovery in your config.php ($config['auth']['pwd_recovery']['page'])
 * - specify a table name which will be used for password recovery process ($config['auth']['pwd_recovery']['table'])
 *   This table structure is:
 *   CREATE TABLE pwd_recovery_request (
 *     id int(11) unsigned NOT NULL auto_increment,
 *     user_id int(11) unsigned NOT NULL default '0',
 *     email varchar(32) NOT NULL default '',
 *     expire datetime default NULL,
 *     changed int(1) default '0',
 *     changed_dts datetime default NULL,
 *     PRIMARY KEY  (`id`)
 *     ) ENGINE=MyISAM
 * - specify a period in minutes in which link to recovery will be actual ($config['auth']['pwd_recovery']['timeout'])
 * 
 * If you want to use register feature:
 * - create a page with the user registration data
 * - add a link to login form: Auth::addRegisterLink()
 * - specify register page in your config.php
 * 
 * Created on 04.07.2006 by *Camper* (<EMAIL>)
 */
class DBAuth extends BasicAuth{
    public $dq;
    private $name_field;
    private $pass_field;
    private $email_field;
    private $secure = true;
    private $can_register = false;
    private $show_lost_password = false;

	function init(){
		parent::init();
		$this->api->addHook('pre-exec',array($this,'check'));
		//process recovery and register
		if($this->api->page==$this->api->getConfig('auth/register_page')){
			$this->api->addHook('post-init', array($this, 'processRegister'));
		}
		if($this->api->page==$this->api->getConfig('auth/pwd_recovery/page')){
			$this->api->addHook('post-init', array($this, 'processRecovery'));
			//$this->processRecovery();
		}
	}
	function processRegister(){
		$p=$this->add('Page');
        $p->template->loadTemplate('empty');
		$p->add('page_'.$this->api->getConfig('auth/register_page'), null, 'Content');
		$p->downCall('render');
		echo $p->template->render();
		exit;
	}
	function processRecovery(){
		$p=$this->add('Page');
		$p->template->loadTemplate('empty');
		if($_GET['key']){
			//user clicked link in e-mail
			$this->api->stickyGET('rp');
			$this->api->stickyGET('key');
			$id=$_GET['rp'];
			$key=$_GET['key'];
	   		$row=$this->api->db->getHash("select * from ".$this->api->getConfig('auth/pwd_recovery/table').
	    			" where id=$id and changed=0");
	    	//looking for the key in DB and checking expiration dts
	   		$db_key=sha1($row['id'].$row['email'].strtotime($row['expire']));
	   		$can_change=$db_key==$key&&strtotime($row['expire'])>time();
	    	if($can_change){
	    		//displaying changepass form
	    		$username=$this->api->db->getOne("select $this->name_field from ".
	    			$this->dq->args['table']." where id=".$row['user_id']);
	    		
				$form=$p->frame('Content', "Change password for $username")->add('Form', null, 'content');
				$form
					->addField('hidden', 'rp_id')
					->addField('password', 'password', '<PASSWORD>')
						->validateField('strlen($this->get())>=6', 'Password is too short')
					->addField('password', '<PASSWORD>', '<PASSWORD>')
						//TODO validation does not work
						->validateField('$this->get()==$this->owner->get(\'password\')', 
						'Confirmation differs from password')
					->addField('checkbox', 'send', 'Send me new password by e-mail')
			
					->addSubmit('Change')
				;
				if(isset($_REQUEST['rp']))$form->set('rp_id', $_REQUEST['rp']);
				if($form->isSubmitted()){
					//getting a user id
					$user_id=$this->api->db->getOne("select user_id from ".
						$this->api->getConfig('auth/pwd_recovery/table').
						" where id = ".$form->get('rp_id'));
					//changing password
					$this->api->db->query("update ".$this->dq->args['table']." set ".$this->pass_field.
						" = '".$this->encrypt($form->get('password')).
							"' where id = $user_id");
					//storing info about changes
					$this->api->db->query("update ".$this->api->getConfig('auth/pwd_recovery/table').
							" set changed=1, changed_dts=SYSDATE()" .
							" where id=".$form->get('rp_id'));
					$p->add('Text', null, 'Content')->set('<center>Password changed succefully</center>');
					if($form->get('send')=='Y')$this->sendPassword($user_id, $form->get('password'));
					unset($this->api->sticky_get_arguments['rp']);
					unset($this->api->sticky_get_arguments['key']);
				}
	    	}else{
	    		//denial page
				unset($this->api->sticky_get_arguments['rp']);
				unset($this->api->sticky_get_arguments['key']);
	    		$p->frame('Content', 'Request error')->add('Text', null, 'content')
	    			->set("Sorry, this page is not valid. Activation period might have been expired." .
	    			" <a href=".
					$this->api->getDestinationURL($this->api->getConfig('auth/pwd_recovery/page')).
					">Click here</a> if You want to repeat Your request.");
	    	}
		}else{
			//displaying a form with username for password recovery
			$form=$p->frame('Content', 'Password recovery')->add('Form', 'pwd_recovery_form', 'content');
			$form
				->addComment('To restore Your password please enter a username specified at registration')
				->addField('line', 'username', 'Username')
				
				->addSubmit('Submit')
			;
			if($form->isSubmitted()){
				$user=$this->api->db->getHash("select id, $this->name_field, $this->email_field from ".DTP.
					$this->dq->args['table']." where $this->name_field='".
					$form->get('username')."'");
				if(sizeof($user)!=0){
					//generating and sending e-mail
					$this->sendChangeLink($user['id'], $user[$this->name_field], $user[$this->email_field]);
					$p->add('Text', null, 'Content')->set("<div align=center>An e-mail with instruction " .
						"to restore password has been sent" .
						" to user '".$form->get('username')."'</div>");
				}else{
					throw new BaseException("User with a name you specified have not been found. Please try again");
				}
			}
		}
		$p->add('Text', 'back', 'Content')->set("<div align=center><a href=".
			$this->api->getDestinationURL('Index').">Back to main page</a></div>");
		$p->downCall('render');
		echo $p->template->render();
		exit;
	}
	protected function sendPassword($user_id, $password){
		//TODO make template based
		$server=$_SERVER['SERVER_NAME'];
		$address=$this->api->db->getOne("select $this->email_field from ".$this->dq->args['table'].
			" where id=".$user_id);
		//combining a message
		$msg="This is $server password recovery subsystem.\n\nHere is your new password : " .
			$password;
		$subj="Your password has changed";
		$from="noreply@$server";
		$headers = "From: $from \n";
		//$headers .= "Return-Path: <".$this->owner->settings['return_path'].">\n";
		//$headers .= "To: $to \n"; 
		$headers .= "MIME-Version: 1.0 \n"; 
		//$headers .= "Content-Type: text/plain; charset=KOI8-R; format=flowed Content-Transfer-Encoding: 8bit " .
		//		"\n"; 
		$headers .= "X-Mailer: PHP script "; 
		
		mail($address, $subj, $msg, $headers);
	}
	protected function sendChangeLink($user_id, $username, $address){
		//TODO make template based
		//adding a DB record with a key to a change password page
		$table=DTP.$this->api->getConfig('auth/pwd_recovery/table');
		$expire=time()+$this->api->getConfig('auth/pwd_recovery/timeout', 15)*60;
		$this->api->db->query("insert into $table (user_id, email, expire) values($user_id, '$address', " .
				"'".date('Y-m-d H:i:s', $expire)."')");
		$id=mysql_insert_id();
		$server=$_SERVER['SERVER_NAME'];
		//combining a message
		$msg="This is $server password recovery subsystem.\n\nWe recieved the request " .
				" to change the password for the user '$username'. To change your password " .
				"click the link below. REMEMBER: this link is actual for a period of ".
				$this->api->getConfig('auth/pwd_recovery/timeout', 15)." minutes only. If you do not change the password " .
				"during this period, you will have to make a new change request.\n\n".
				"http://".$server.dirname($_SERVER['PHP_SELF'])."/".
				$this->api->getDestinationURL(null, array('rp'=>$id, 'key'=>sha1($id.$address.$expire)));
		$subj="Password recovery";
		$from="noreply@$server";
		$headers = "From: $from \n";
		//$headers .= "Return-Path: <".$this->owner->settings['return_path'].">\n";
		//$headers .= "To: $to \n"; 
		$headers .= "MIME-Version: 1.0 \n"; 
		//$headers .= "Content-Type: text/plain; charset=KOI8-R; format=flowed Content-Transfer-Encoding: 8bit " .
		//		"\n"; 
		$headers .= "X-Mailer: PHP script "; 
		
		mail($address, $subj, $msg, $headers);
	}
	function setEncrypted($secure=true){
		$this->secure=$secure;
		return $this;
	}
	function setPassword($password){
		return false;
	}
    function setSource($table,$login='login',$password='password',$email='email'){
    	$this->name_field = $login;
    	$this->pass_field = $password;
    	$this->email_field = $email;
        $this->dq=$this->api->db->dsql()
            ->table($table)
            ->field($this->name_field)
            ->field($this->pass_field);
        return $this;
    }
    function verifyCredintals($user,$password){
    	$data=$this->dq->where($this->name_field, $user)->do_getHash();
    	return(sizeof($data)>0&&($data[$this->pass_field]==$password||$data[$this->pass_field]==sha1($password)));
    }
	private function encrypt($str){
		return $this->secure?sha1($str):$str;
	}
    function loggedIn(){
    	parent::loggedIn();
    	$this->info=array_merge($this->info, $this->dq->do_getHash());
        $this->memorize('info',$this->info);
    }
	function showLoginForm(){
		$p=parent::showLoginForm();
		if($this->can_register){
			$this->form->add('RegisterLink', null, 'form_body');
		}
		if($this->show_lost_password){
			$this->form->add('PwdRecoveryLink', null, 'form_body');
		}
		return $p;
	}
	function addRegisterLink(){
		$this->can_register=true;
		return $this;
	}
	function addPwdRecoveryLink(){
		$this->show_lost_password=true;
		return $this;
	}
}
class RegisterLink extends Text{
	function init(){
		parent::init();
		$this->set('<tr><td align=left><a href='.
			$this->api->getDestinationURL($this->api->getConfig('auth/register_page')).'>Register</a></td><td></td></tr>');
	}
}
class PwdRecoveryLink extends Text{
	function init(){
		parent::init();
		$this->set('<tr><td align=left><a href='.
			$this->api->getDestinationURL($this->api->getConfig('auth/pwd_recovery/page')).
			'>Lost password</a></td><td></td></tr>');
	}
}

{'fraction_non_alphanumeric': 0.20005496015388843, 'fraction_numerical': 0.0033892094897865713, 'mean_word_length': 3.471636289166496, 'pattern_counts': {'":': 0, '<': 77, '<?xml version=': 0, '>': 472, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5124490', 'n_tokens_mistral': 8100, 'n_tokens_neox': 7084, 'n_words': 1499}