<commit_before><?php
// (c) Copyright 2002-2016 by authors of the Tiki Wiki CMS Groupware Project
//
// All Rights Reserved. See copyright.txt for details and a complete list of authors.
// Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details.
// $Id$

class AuthTokens
{
	const SCHEME = 'MD5( CONCAT(tokenId, creation, timeout, entry, parameters, groups) )';
	private $db;
	private $table;
	private $dt;
	private $maxTimeout = 3600;
	private $maxHits = 1;
	public $ok = false;

	public static function build( $prefs )
	{
		return new AuthTokens(
			TikiDb::get(),
			array(
				'maxTimeout' => $prefs['auth_token_access_maxtimeout'],
				'maxHits' => $prefs['auth_token_access_maxhits'],
			)
		);
	}

	function __construct( $db, $options = array(), DateTime $dt = null )
	{
		$this->db = $db;
		$this->table = $this->db->table('tiki_auth_tokens');

		if (is_null($dt)) {
			$this->dt = new DateTime;
		} else {
			$this->dt = $dt;
		}

		if ( isset($options['maxTimeout']) ) {
			$this->maxTimeout = (int) $options['maxTimeout'];
		}

		if ( isset($options['maxHits']) ) {
			$this->maxHits = (int) $options['maxHits'];
		}
	}

	function getToken( $token )
	{
		$data = $this->db->query(
			'SELECT * FROM tiki_auth_tokens WHERE token = ? AND token = ' . self::SCHEME,
			array( $token )
		)->fetchRow();

		return $data;
	}

	function getTokens()
	{
		return $this->table->fetchAll(array(), array(), -1, -1, array('creation' => 'asc'));
	}

	function getGroups( $token, $entry, $parameters )
	{
		// Process deletion of temporary users that are created via tokens
		$usersToDelete = $this->db->fetchAll(
			'SELECT tokenId, userPrefix FROM tiki_auth_tokens
			WHERE (timeout != -1 AND UNIX_TIMESTAMP(creation) + timeout < UNIX_TIMESTAMP()) OR `hits` = 0'
		);

		foreach ($usersToDelete as $del) {
			TikiLib::lib('user')->remove_temporary_user($del['userPrefix'] . $del['tokenId']);
		}

		$this->db->query(
			'DELETE FROM tiki_auth_tokens
			 WHERE (timeout != -1 AND UNIX_TIMESTAMP(creation) + timeout < UNIX_TIMESTAMP()) OR `hits` = 0'
		);

		$data = $this->db->query(
			'SELECT tokenId, entry, parameters, groups, email, createUser, userPrefix FROM tiki_auth_tokens WHERE token = ? AND token = ' . self::SCHEME,
			array( $token )
		)->fetchRow();

		global $prefs, $full, $tikiroot;		// $full defined in route.php
		$smarty = TikiLib::lib('smarty');
		$sefurl = '';

		if ($prefs['feature_sefurl'] === 'y') {
			$sefurl = substr($full, strlen($tikiroot)) . '?' . http_build_query($_GET);
			$sefurlTypeMap = $this->getSefurlTypeMap();

			$smarty->loadPlugin('smarty_modifier_sefurl');
			$sefurl = $tikiroot . smarty_modifier_sefurl($sefurl, $sefurlTypeMap[$_GET[0]]);
		}

		// add an extra conversion to prevent false positives due to former missmatches
		// in cases of "/tikiroot/My Page" vs "/tikiroot/My+Page"
		$entry_no_tikiroot = substr($data['entry'], strlen($tikiroot));
		$entry_encoded_no_tikiroot = urlencode($entry_no_tikiroot);
		$full_entry_encoded = $tikiroot . $entry_encoded_no_tikiroot;
		// entry doesn't match "or" sefurl feature is in use but that also doesn't match
		if ( $data['entry'] != $entry || ($sefurl && $data['entry']  !== $sefurl && $full_entry_encoded !== $sefurl )) {
			return null;
		}

		$registered = (array) json_decode($data['parameters'], true);

		if ( ! $this->allPresent($registered, $parameters) || ! $this->allPresent($parameters, $registered) ) {
			return null;
		}<commit_msg>[FIX] tokens: Fix for token access when using sefurl - iterate through $_GET keys to find primary object key, use that to generate the sefurl, then remove it from the "other" params to be checked - tested with various object types and wiki urls schemes, but not all (thanks Chealer)<commit_after><?php
// (c) Copyright 2002-2016 by authors of the Tiki Wiki CMS Groupware Project
//
// All Rights Reserved. See copyright.txt for details and a complete list of authors.
// Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details.
// $Id$

class AuthTokens
{
	const SCHEME = 'MD5( CONCAT(tokenId, creation, timeout, entry, parameters, groups) )';
	private $db;
	private $table;
	private $dt;
	private $maxTimeout = 3600;
	private $maxHits = 1;
	public $ok = false;

	public static function build( $prefs )
	{
		return new AuthTokens(
			TikiDb::get(),
			array(
				'maxTimeout' => $prefs['auth_token_access_maxtimeout'],
				'maxHits' => $prefs['auth_token_access_maxhits'],
			)
		);
	}

	function __construct( $db, $options = array(), DateTime $dt = null )
	{
		$this->db = $db;
		$this->table = $this->db->table('tiki_auth_tokens');

		if (is_null($dt)) {
			$this->dt = new DateTime;
		} else {
			$this->dt = $dt;
		}

		if ( isset($options['maxTimeout']) ) {
			$this->maxTimeout = (int) $options['maxTimeout'];
		}

		if ( isset($options['maxHits']) ) {
			$this->maxHits = (int) $options['maxHits'];
		}
	}

	function getToken( $token )
	{
		$data = $this->db->query(
			'SELECT * FROM tiki_auth_tokens WHERE token = ? AND token = ' . self::SCHEME,
			array( $token )
		)->fetchRow();

		return $data;
	}

	function getTokens()
	{
		return $this->table->fetchAll(array(), array(), -1, -1, array('creation' => 'asc'));
	}

	function getGroups( $token, $entry, $parameters )
	{
		// Process deletion of temporary users that are created via tokens
		$usersToDelete = $this->db->fetchAll(
			'SELECT tokenId, userPrefix FROM tiki_auth_tokens
			WHERE (timeout != -1 AND UNIX_TIMESTAMP(creation) + timeout < UNIX_TIMESTAMP()) OR `hits` = 0'
		);

		foreach ($usersToDelete as $del) {
			TikiLib::lib('user')->remove_temporary_user($del['userPrefix'] . $del['tokenId']);
		}

		$this->db->query(
			'DELETE FROM tiki_auth_tokens
			 WHERE (timeout != -1 AND UNIX_TIMESTAMP(creation) + timeout < UNIX_TIMESTAMP()) OR `hits` = 0'
		);

		$data = $this->db->query(
			'SELECT tokenId, entry, parameters, groups, email, createUser, userPrefix FROM tiki_auth_tokens WHERE token = ? AND token = ' . self::SCHEME,
			array( $token )
		)->fetchRow();

		global $prefs, $tikiroot;		// $full defined in route.php
		if ($prefs['feature_sefurl'] === 'y') {

			$sefurlTypeMap = $this->getSefurlTypeMap();
			$keys = array_keys($_GET);
			$seftype = '';

			for ($i = 1; $i < count($keys); $i++) {
				$seftype = $sefurlTypeMap[$keys[$i]];
				if ($seftype) {
					$key = $keys[$i];
					// $parameters is compared with the stored $data['parameters'] later
					// but that doesn't include the 'page' or 'fileId' etc param due to sefurl
					unset($parameters[$keys[$i]]);
					break;
				}
			}
			if (empty($key)) {	// missing object type?
				return null;
			}

			TikiLib::lib('smarty')->loadPlugin('smarty_modifier_sefurl');
			$sefurl = $tikiroot . smarty_modifier_sefurl($_GET[$key], $seftype);

			// add an extra conversion to prevent false positives due to url encoding
			// e.g. in cases of "/tikiroot/My Page" vs "/tikiroot/My+Page"
			$entry_no_tikiroot = substr($data['entry'], strlen($tikiroot));
			$entry_encoded_no_tikiroot = urlencode($entry_no_tikiroot);
			$full_entry_encoded = $tikiroot . $entry_encoded_no_tikiroot;

			if ($data['entry']  !== $sefurl && $full_entry_encoded !== $sefurl ) {
				return null;	// entry doesn't match
			}

		} else if ( $data['entry'] != $entry) {
			return null;	// entry doesn't match
		}

		$registered = (array) json_decode($data['parameters'], true);

		if ( ! $this->allPresent($registered, $parameters) || ! $this->allPresent($parameters, $registered) ) {
			return null;
		}
{'fraction_non_alphanumeric': 0.16325445360276522, 'fraction_numerical': 0.005583621377293273, 'mean_word_length': 3.9395929087327644, 'pattern_counts': {'":': 0, '<': 10, '<?xml version=': 0, '>': 59, 'https://': 0, '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': '4641556', 'n_tokens_mistral': 2926, 'n_tokens_neox': 2599, 'n_words': 670}