CSCI 2006 - Spring 2024 - Server-Side ProgrammingLab #10 - User & Sessions (part 2)Solution

Solution

index.php

<?php

date_default_timezone_set('America/Chicago');
session_start();
$date_string = date('Y-m-d H:i');

require('language.php');

$title = '404 Error';
$body = '<h2>404 Error</h2><p>The requested page was not available</p>';

if (!isset($_GET['pg'])) { 
	$_GET['pg'] = 'login'; 
}

switch ($_GET['pg']) {
	case 'logoff':
		unset($_SESSION['user']);
	case 'login':
	case 'promote':
	case 'demote':
		$msg = '';
		if (isset($_POST['newuser'])) {
			/* Create a user account */
			$uinfo = getData('INSERT INTO `User` (`username`,`display`,`passhash`,`type`)'.
				'  VALUES (?, ?, ?, "reg")',[
					$_POST['newuser']['name'],
					$_POST['newuser']['disp'],
					password_hash($_POST['newuser']['pass'],PASSWORD_DEFAULT),
				], false);
			$_POST['user'] = [
				'name'=>$_POST['newuser']['name'],
				'pass'=>$_POST['newuser']['pass'],
			];
		}
		if (isset($_POST['user'])) {
			/* An attempt to login */
			$uinfo = getData('SELECT * FROM `User` WHERE `username`=?', [$_POST['user']['name']]);
			if (isset($uinfo['passhash']) && password_verify($_POST['user']['pass'],$uinfo['passhash'])) {
				unset($uinfo['passhash']);
				$_SESSION['user']=$uinfo;
			} else {
				$msg = 'Login was not successful';
			}
		}

		if (isset($_SESSION['user'])) {
			$title = 'Home';
			$body  = '<h2>Welcome, '.$_SESSION['user']['display'].'</h2>'.
				'<a href="?pg=logoff">Log Off</a>';
			if ($_SESSION['user']['type'] == 'adv' && $_GET['pg'] == 'demote') {
				$rs = getData('UPDATE `User` SET `type`="reg" WHERE `username`=?',
					[$_SESSION['user']['username']],false);
				$_SESSION['user']['type']='reg';
			}

			if ($_SESSION['user']['type'] == 'adv') {
				if (isset($_GET['user']) && $_GET['pg']=='promote') {
					/* Promoting a user */
					$rs = getData('UPDATE `User` SET `type`="adv" WHERE `username`=?',
						[$_GET['user']], false);
					$body .= '<h4>'.$_GET['user'].' was promoted</h4>';
				}

				$body .= '<br><br><a href="?pg=demote">Demote My Account</a>';

				$users = getData('SELECT `username` FROM `User` WHERE `type`="reg"');
				$body .= '<h3>Users available for Promotion</h3>';
				if (count($users) == 0) {
					$body .= '<p>No New Users</p>';
				} else {
					$body .= '<ul>';
					foreach ($users as $u) {
						if (!is_array($u)) { $u = ['username'=>$u]; }
						$body .= '<li>'.
							'<a href="?pg=promote&user='.$u['username'].'">'.$u['username'].'</a>'.
							'</li>';
					}
					$body .= '</ul>';
				}
			}

		} else {
			$title = 'Login';
			$body  = ((strlen($msg)==0)?'':'<h3>'.$msg.'</h3>'). 
				'<form method="POST" action="?">'.
				'<label for="user">Username</label>'.
				'<input id="user" type="text" name="user[name]" />'.
				'<br>'.
				'<label for="pass">Password</label>'.
				'<input id="pass" type="password" name="user[pass]" />'.
				'<br>'.
				'<input type="submit" value="Submit" />'.
				'<br>'.
				'</form>';

			$body .= '<h3>Create an Account</h3>'.
				'<form method="POST" action="?">'.
				'<label for="user">Username</label>'.
				'<input id="user" type="text" name="newuser[name]" />'.
				'<br>'.
				'<label for="disp">Full Name</label>'.
				'<input id="disp" type="text" name="newuser[disp]" />'.
				'<br>'.
				'<label for="pass">Password</label>'.
				'<input id="pass" type="password" name="newuser[pass]" />'.
				'<br>'.
				'<input type="submit" value="Submit" />'.
				'<br>'.
				'</form>';

		}
	default:
		$title = 'Programming Languages';
		$lang = new Language($_GET['pg']);
		if ($lang->isDefined($_SESSION['user']['type']??'any')) {
			$title = $lang->getName();
			$body = $lang->toHTML();
		}
}

$allLangs = Language::getAllLanguages($_SESSION['user']['type']??'any');
$nav = '';
foreach ($allLangs as $key=>$disp) {
	$nav .= '<a href="?pg='.$key.'" class="'.(($_GET['pg']==$key)?'currentPage':'').'">'.$disp.'</a>';
}

?>
<!DOCTYPE html>
<html>
<head>
  <title><?php echo $title; ?></title>
  <link rel="stylesheet" href="/style.css" type="text/css" media="all">
</head>
<body>
  <header>
    <h1><a style="color:inherit" href="?">Programming Languages</a></h1>
    <nav><?php echo $nav; ?></nav>
  </header>
  <main>
  <?php echo $body; ?>
  </main>
  <script type="text/javascript" src="/theme/prism.js"></script>
  <footer>
    &copy;<?php echo $date_string; ?> - General Websites Inc.
  </footer>
</body>
</html>

language.php

<?php

function getData($query,$args=[],$hasResult=true) {
        $DB = 'csci2006_languages';
        $USER = 'csci2006';
        $PASS = '9TfP4lxsxH1szKuA';

        try {
                $pdo = new PDO("mysql:host=localhost;dbname={$DB}",$USER,$PASS);
                $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
	
		$rs = $pdo->prepare($query,[PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL]);
        	$rs->setFetchMode(PDO::FETCH_NAMED);
		$rs->execute($args);

		$data = [];
		if ($hasResult) {
			while ($row = $rs->fetch()) {
				$data[] = $row;
			}
		}

		unset($DB);
		unset($USER);
		unset($PASS);
		unset($rs);
		unset($pdo);

		if (count($data) == 1 && isset($data[0])) {
			return $data[0];
		}
		return $data;
        } catch (PDOException $e) {
		echo '<h2>Database Error</h2>';
		echo '<pre>'.$e->getMessage().'</pre>';
		echo '<pre>QUERY: '.$query.'</pre>';
		echo '<pre>ARGS: '.var_export($args,true).'</pre>';
                die();
        }
}


class Language {
	private $data = [];

	public function __construct($key) {
		$this->data = getData('SELECT *'.
			' FROM `language`'.
			' WHERE `language_slug`=?',
			[$key]);
		if (count($this->data) > 0) {
			$this->data['desc'] = getData('SELECT `desc_paragraph`'.
				' FROM `description`'.
				' WHERE `desc_lang`=?'.
				' ORDER BY `desc_ordinal`',
				[$this->data['lang_id']]);
		} else {
			$this->data = null;
		}
	}

	public function isDefined($level) {
		if ($this->data !== null) {
			switch ($level) {
			case 'adv': return in_array($this->data['user_type'],['adv','reg','any']);
			case 'reg': return in_array($this->data['user_type'],[      'reg','any']);
			case 'any': return $this->data['user_type']=='any';
			}
		}
		return false;
	}

	public function getName() {
		return $this->data['language_name'];
	}

	public function toHTML() {
		$html = '';
		foreach ($this->data['desc'] as $line) {
			$html .= '<p>'.$line['desc_paragraph'].'</p>';
		}
		$html .= '<h2>Example</h2>'.
			'<pre class="language-'.$this->data['language_highlighter'].' line-numbers"><code class="language-'.$this->data['language_highlighter'].'">'.
			htmlentities($this->data['language_example']).
			'</code></pre>';
		return $html;
	}

	public static function getAllLanguages($level) {
		$data = getData('SELECT `language_slug`, `language_name`, `user_type`'.
			' FROM `language`'.
			' ORDER BY `language_name`');
		$rs = [];
		foreach ($data as $info) {
			switch ($info['user_type']) {
			case 'adv':
				if ($level != 'adv') { break; }
			case 'reg':
				if ($level != 'adv' && $level != 'reg') { break; }
			case 'any':
				$rs[$info['language_slug']] = $info['language_name'];
			}
		}
		return $rs;
	}
}

?>
Go To Live Site