<?php
/* QuizSession base class
 *
 * Copyright (C) 2007 - 2019 Robert Bienert
 * <https://freihoch2.de/opensource/QuizSession/>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
 */

require_once(dirname(__FILE__) . '/string-lib.php');
#require_once(dirname(__FILE__) . '/random-lib.php');
require_once(dirname(__FILE__) . '/config.php');	// may be changed

class QuizSession {
	var $_sid;	// Session-ID
	var $_qid;	// Quiz-ID
	var $_stored;	// Session already saved?
	var $_db;	// database handle
	var $_term1 = 'NULL';
	var $_term2 = 'NULL';

	function __construct() {
		$this->tidySessions();

		$this->newID();
		$this->_qid = mt_rand(1, $this->_getMaxQuizId());
		#$this->_qid = random_int32(1, $this->_getMaxQuizId());

		$this->_stored = false;
	}

	function newID() {
		$ip = isset($_SERVER['HTTP_X_FORWARDED_FOR']) ?
			$_SERVER['HTTP_X_FORWARDED_FOR'] :
			$_SERVER['REMOTE_ADDR'];

		// preparing the time aspect
		$msec = strtok(microtime(), ' ');
		$sec = strtok(' ');

		/* The session ID consists of:
		 * a random integer (32 bit)
		 * the clients port number (16 bit)
		 * a combination of time() and the microseconds (64 bit)
		 * the ip address (32 bit)
		 * => number of 144 bit that will be md5'ed
		 */
		$this->_sid = md5(pack('iSd',
					mt_rand(),
					#random_int32(),
					$_SERVER['REMOTE_PORT'],
					$msec * $sec)
				. ip2int($ip));
	}

	function id() {
		return $this->_sid;
	}

	function tidySessions() {
		global $connect;

		$q = $connect->query('DELETE FROM quiz_db_quiz_master ' .
				'WHERE session_date < ' .
				'DATE_SUB(NOW(), INTERVAL 7 DAY)');

		if ($connect->errno)
			trigger_error($connect->error, E_USER_ERROR);
	}

	function displayCode() {
		global $connect;

		$q = $connect->prepare('SELECT question FROM ' . QDTP .
			'quiz WHERE id=?');
		$q->bind_param('i', $this->_qid);
		$q->execute();
		$r = $q->get_result()->fetch_array();

		if (! $this->_stored) {
			$this->_term1 = mt_rand(0, 10);
			$this->_term2 = mt_rand(0, 10);

			$this->store();
		}

		if (strpos($r['question'], '$d1') !== FALSE) {
			$r['question'] = prepareString($r['question'],
						'$d',
						array($this->_term1,
							$this->_term2));
		}

		return '<label>' . htmlspecialchars($r['question']) .
			'? <input type="text" name="qs_answer" ' .
			'size="10" /></label>' . "\n" .
			'<input type="hidden" name="qs_id" value="' .
			$this->_sid . '" />' . "\n";
	}

	function display() {
		echo $this->displayCode();
	}

	function store() {
		global $connect;

		if ($this->_stored)
			return;

		$q = $connect->prepare('INSERT INTO '.QDTP.'quiz_master ' .
			'(session_id, session_date, quiz_id, term1, term2) ' .
			'VALUES (?, NOW(), ?,?,?)');
		$q->bind_param('siss', $this->_sid, $this->_qid,
					$this->_term1, $this->_term2);
		$q->execute();

		if ($q->errno)
			trigger_error($q->error, E_USER_ERROR);

		$this->_stored = true;
	}

	function _getMaxQuizId() {
		global $connect;

		$q = $connect->query('SELECT COUNT(id) AS n FROM '.QDTP.'quiz');

		$r = $q->fetch_array();

		return $r['n'];
	}
}