summaryrefslogtreecommitdiff
path: root/apps/um/views
diff options
context:
space:
mode:
Diffstat (limited to 'apps/um/views')
-rw-r--r--apps/um/views/Template.class.php316
-rw-r--r--apps/um/views/includes/header-include.php51
-rw-r--r--apps/um/views/includes/header.php84
-rw-r--r--apps/um/views/pages/auth/badrequest.html.php11
-rw-r--r--apps/um/views/pages/auth/index.html.php12
-rw-r--r--apps/um/views/pages/auth/login.html.php54
-rw-r--r--apps/um/views/pages/auth/logout.html.php6
-rw-r--r--apps/um/views/pages/groups/401.html.php15
-rw-r--r--apps/um/views/pages/http404.html.php16
-rw-r--r--apps/um/views/pages/index.html.php8
-rw-r--r--apps/um/views/pages/messages/401.html.php15
-rw-r--r--apps/um/views/pages/messages/frame.html.php58
-rw-r--r--apps/um/views/pages/messages/index.html.php25
-rw-r--r--apps/um/views/pages/plugins/401.html.php9
-rw-r--r--apps/um/views/pages/plugins/index.html.php42
-rw-r--r--apps/um/views/pages/users/401.html.php15
-rw-r--r--apps/um/views/pages/users/404.html.php10
-rw-r--r--apps/um/views/pages/users/500.html.php15
-rw-r--r--apps/um/views/pages/users/created.html.php18
-rw-r--r--apps/um/views/pages/users/index.csv.php27
-rw-r--r--apps/um/views/pages/users/index.html.php104
-rw-r--r--apps/um/views/pages/users/individual.html.php147
-rw-r--r--apps/um/views/pages/users/individual.json.php27
-rw-r--r--apps/um/views/pages/users/new-locked.html.php9
-rw-r--r--apps/um/views/pages/users/new-logged-in.html.php8
-rw-r--r--apps/um/views/pages/users/new.html.php57
26 files changed, 1159 insertions, 0 deletions
diff --git a/apps/um/views/Template.class.php b/apps/um/views/Template.class.php
new file mode 100644
index 0000000..9d55b75
--- /dev/null
+++ b/apps/um/views/Template.class.php
@@ -0,0 +1,316 @@
+<?php
+require_once('Singleton.class.php');
+require_once('Site.class.php');
+
+require_once('Login.class.php');// used to see if logged in
+require_once('Auth.class.php');// used to get username if we are
+
+class Template extends Singleton {
+ private $indent = 0;
+ private $ret = false;
+
+ public function status($status) {
+ header($_SERVER["SERVER_PROTOCOL"]." $status");
+ header("Status: $status");
+ }
+
+ public function setRet($ret) {
+ $this->ret = $ret;
+ }
+
+ private function tabs() {
+ $str = '';
+ for ($i=0;$i<$this->indent;$i++) { $str .= "\t"; }
+ return $str;
+ }
+
+ private function attr($attr='') {
+ $tags='';
+ if (is_array($attr)) {
+ foreach($attr as $key=>$value) {
+ $tags .= " $key=\"$value\"";
+ }
+ }
+ return $tags;
+ }
+
+ public function tag($tag, $attr='', $content=false) {
+ $tags = $this->attr($attr);
+ $str = $this->tabs()."<$tag$tags";
+ if ($content===false) {
+ $str.= " />";
+ } else {
+ $str.= ">$content</$tag>";
+ }
+ $str.= "\n";
+ if ($this->ret) return $str;
+ echo $str;
+ }
+
+ public function openTag($tag, $attr='') {
+ $tags = $this->attr($attr);
+ $str = $this->tabs()."<$tag$tags>\n";
+ $this->indent++;
+ if ($this->ret) return $str;
+ echo $str;
+ }
+
+ public function closeTag($tag) {
+ $this->indent--;
+ $str = $this->tabs()."</$tag>\n";
+ if ($this->ret) return $str;
+ echo $str;
+ }
+
+ public function text($text) {
+ $str = $this->tabs().$text."\n";
+ if ($this->ret) return $str;
+ echo $str;
+ }
+
+ public function paragraph($text, $attr='', $return=false) {
+ $tabs = $this->tabs();
+ $tags = $this->attr($attr);
+ $str = $tabs."<p$tags>";
+ $str.= wordwrap($text, 78-($this->indent*8), "\n$tabs ");
+ $str.= "</p>\n";
+ if ($this->ret||$return) return $str;
+ echo $str;
+ }
+
+ public function link($target, $text, $return=false) {
+ $ret = $this->ret;
+ $this->ret |= $return;
+ $str = $this->tag('a', array('href'=>$target), $text);
+ $this->ret = $ret;
+ if ($this->ret||$return) return $str;
+ echo $str;
+ }
+ public function url($page) {
+ return Site::getInstance()->baseUrl().$page;
+ }
+
+ public function row($cells) {
+ $str = $this->openTag('tr');
+ foreach ($cells as $cell)
+ $str.= $this->tag('td', array(), $cell);
+ $str.= $this->closeTag('tr');
+ if ($this->ret) return $str;
+ echo $str;
+ }
+ private function css($file, $media) {
+ $str.= $this->tag('link', array('rel'=>"stylesheet",
+ 'type'=>"text/css",
+ 'href'=>$this->url($file),
+ 'media'=>$media));
+ if ($this->ret) return $str;
+ echo $str;
+ }
+ public function header($title) {
+ // username=false if not logged in or not connected to DB
+ $username = Auth::getInstance(Login::isLoggedIn())->getName();
+
+ $ret = $this->ret;
+ $this->ret = true;
+
+ $logged_in = ($username!==false);
+
+ $str = '<?xml version="1.0" encoding="utf-8"?>'."\n";
+ $str.= '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"'."\n";
+ $str.= '"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">'."\n";
+
+ $xmlns = "http://www.w3.org/1999/xhtml";
+ $str.= $this->openTag('html', array('xmlns'=>$xmlns,
+ 'lang'=>"en-us",
+ 'dir'=>"ltr"));
+ $this->indent = 0; // don't indent for the <html> tag
+
+ $str.= $this->openTag('head');
+ $str.= $this->tag('title', array(), htmlspecialchars($title));
+ $str.= $this->css('style.css', 'all');
+ $str.= $this->css('screen.css', 'screen');
+ $str.= $this->css('print.css', 'print');
+ $str.= $this->closeTag('head');
+
+ $body_class = 'logged'.($logged_in?'in':'out');
+ $str.= $this->openTag('body', array('class'=>$body_class));
+
+ $str.= $this->openTag('div', array('class'=>'infobar'));
+ if ($logged_in) {
+ $user = htmlentities($username);
+
+ $str.= $this->link($this->url(''), "Home");
+ $str.= $this->link($this->url("users/$user"),"@$user");
+ $str.= $this->logout_button('Logout');
+ } else {
+ $url=$_SERVER['REQUEST_URI'];
+ $str.= $this->openTag('form',
+ array('action'=>$this->url('auth'),
+ 'method'=>'post'));
+ $str.= $this->tag('input', array('type'=>'hidden',
+ 'name'=>'action',
+ 'value'=>'login'));
+ $str.= $this->tag('input', array('type'=>'hidden',
+ 'name'=>'url',
+ 'value'=>$url));
+ $str.= $this->tag('label',
+ array('for'=>'username'),'Username:');
+ $str.= $this->tag('input', array('type'=>'text',
+ 'name'=>'username',
+ 'id'=>'username'));
+ $str.= $this->tag('label',
+ array('for'=>'password'),'Password:');
+ $str.= $this->tag('input', array('type'=>'password',
+ 'name'=>'password',
+ 'id'=>'password'));
+ $str.= $this->tag('input', array('type'=>'submit',
+ 'value'=>'Login'));
+ $str.= $this->link($this->url("users/new"),'New Account');
+ $str.= $this->closeTag('form');
+ }
+ $str.= $this->closeTag('div');
+
+ $str.= $this->openTag('div',array('class'=>'main'));
+ $str.= $this->openTag('div',array('class'=>'main_sub'));
+
+ $this->ret = $ret;
+ if ($this->ret) return $str;
+ echo $str;
+ }
+
+ public function footer() {
+ $str = $this->closeTag('div');
+ $str.= $this->closeTag('div');
+ $str.= $this->closeTag('body');
+ $str.= $this->closeTag('html');
+
+ if ($this->ret) return $str;
+ echo $str;
+ }
+
+ public function openFieldset($name, $lock=false) {
+ $class = ($lock?' class="readonly"':'');
+ $str = $this->text("<fieldset$class><legend>$name</legend><ul>");
+ $this->indent++;
+ if ($this->ret) return $str;
+ echo $str;
+ }
+
+ public function closeFieldset() {
+ $this->indent--;
+ $str = $this->text("</ul></fieldset>");
+ if ($this->ret) return $str;
+ echo $str;
+ }
+
+ public function input($id, $label, $hint, $html, $tags=null) {
+ if ($tags===null) { $tags=array(); }
+ $str = $this->openTag('li', $tags);
+ $str.= $this->tag('label', array('for'=>$id), $label);
+ $str.= $this->text($html);
+ if (strlen($hint)>0) {
+ $str.=$this->paragraph($hint,
+ Array('class'=>'form_data'));
+ }
+ $str.= $this->closeTag('li');
+ if ($this->ret) return $str;
+ echo $str;
+ }
+
+ private function inputStr($type, $id, $default, $lock) {
+ $value = htmlentities($default);
+ $tag = ($lock?"readonly='readonly' ":'');
+ return "<input type='$type' name='$id' id='$id' value=\"$value\" $tag/>";
+ }
+ public function inputTextArea($id, $label, $hint='', $default='', $lock=FALSE) {
+ $value = htmlentities($default);
+ $tag = ($lock?"readonly='readonly' ":'');
+ return $this->input($id, $label, $hint,
+ "<textarea name='$id' id='$id' $tag>$value</textarea>",
+ array('class'=>'wide'));
+ }
+
+ public function inputText($id, $label, $hint='', $default='', $lock=FALSE) {
+ return $this->input($id, $label, $hint,
+ $this->inputStr('text', $id, $default, $lock));
+ }
+
+ public function inputPassword($id, $label, $hint='', $default='', $lock=FALSE) {
+ return $this->input($id, $label, $hint,
+ $this->inputStr('password', $id, $default, $lock));
+ }
+
+ public function inputNewPassword($id, $label, $default='', $lock=FALSE) {
+ return $this->input($id, $label,
+ "Type the same password twice, to make sure you don't mistype.",
+ $this->inputStr('password', $id, $default, $lock).
+ "\n".$this->tabs()."\t".
+ $this->inputStr('password', $id.'_verify', $default,$lock));
+ }
+ public function inputBool($id, $label, $hint='', $default=FALSE, $lock=FALSE) {
+ $tag = '';
+ if ($lock) $tag.= "readonly='readonly' ";
+ if ($default) $tag.= "checked='checked' ";
+ return $this->input($id, $label, $hint,
+ "<input type='hidden' name='$id' value='false' />".
+ "<input type='checkbox' id='$id' name='$id' value='true' $tag>");
+
+ $attrib = array('type'=>'checkbox',
+ 'id'=>$id,
+ 'name'=>$name.'[]',
+ 'value'=>$value);
+ if ($default) $attrib['checked']='checked';
+ if ($lock ) $attrib['readonly']='readonly';
+
+ $str = $this->openTag('li');
+ $str.= $this->tag('input', $attrib);
+ $str.= $this->tag('label', array('for'=>$id), $label);
+ $str.= $this->closeTag('li');
+
+ if ($this->ret) return $str;
+ echo $str;
+
+ }
+
+ public function inputBoolArray($name, $value, $label, $default=FALSE, $lock=FALSE) {
+ $id = $name.'_'.$value;
+ $attrib = array('type'=>'checkbox',
+ 'id'=>$id,
+ 'name'=>$name.'[]',
+ 'value'=>$value);
+ if ($default) $attrib['checked']='checked';
+ if ($lock ) $attrib['readonly']='readonly';
+
+ $str = $this->openTag('li');
+ $str.= $this->tag('input', $attrib);
+ $str.= $this->tag('label', array('for'=>$id), $label);
+ $str.= $this->closeTag('li');
+
+ if ($this->ret) return $str;
+ echo $str;
+
+ }
+
+ public function inputP($text, $error=false) {
+ $str = $this->openTag('li');
+ $str.=$this->paragraph($text,
+ array('class'=>($error?' error':'')));
+ $str.= $this->closeTag('li');
+ if ($this->ret) return $str;
+ echo $str;
+ }
+
+ public function logout_button($text) {
+ $str = $this->openTag('form',array('action'=>$this->url('auth'),
+ 'method'=>"post",
+ 'style'=>'display:inline'));
+ $str.= $this->tag('input', array('type'=>'hidden',
+ 'name'=>'action',
+ 'value'=>'logout'));
+ $str.= $this->tag('input', array('type'=>'submit',
+ 'value'=>$text));
+ $str.= $this->closeTag('form');
+ if ($this->ret) return $str;
+ echo $str;
+ }
+}
diff --git a/apps/um/views/includes/header-include.php b/apps/um/views/includes/header-include.php
new file mode 100644
index 0000000..3826b3a
--- /dev/null
+++ b/apps/um/views/includes/header-include.php
@@ -0,0 +1,51 @@
+<?php
+function language_attributes() {
+ echo 'dir="ltr" lang="en-US"';
+}
+
+function bloginfo($param) {
+ switch ($param) {
+ case 'charset': echo 'UTF-8'; break;
+ case 'stylesheet_url': echo "/wp/wp-content/themes/kilabytes/style.css"; break;
+ case 'pingback_url': echo 'http://www.mckenzierobotics.org/wp/xmlrpc.php'; break;
+ default: echo ''; break;
+ }
+}
+
+function wp_title($foo, $bar, $baz) {
+ global $_title_;
+ echo $_title_;
+}
+
+function get_bloginfo($foo, $bar) {
+ return false;
+}
+
+function get_template_directory_uri() {
+ return 'http://www.mckenzierobotics.org/wp/wp-content/themes/twentyeleven';
+}
+
+function is_singular() {
+ return false;
+}
+
+function wp_head() {
+ echo '';
+}
+
+global $paged, $page;
+$paged = 0;
+$page = 0;
+
+$username = Auth::getInstance(Login::isLoggedIn())->getName();
+$logged_in = ($username!==false);
+
+$ret = $this->ret;
+$this->ret = true;
+
+function body_class() {
+ $body_class = 'logged'.($logged_in?'in':'out');
+ echo 'class="'+$body_class+'"';
+}
+
+require(dirname(__FILE__)+"/header.php"); \ No newline at end of file
diff --git a/apps/um/views/includes/header.php b/apps/um/views/includes/header.php
new file mode 100644
index 0000000..0a3e161
--- /dev/null
+++ b/apps/um/views/includes/header.php
@@ -0,0 +1,84 @@
+<?php
+function language_attributes() {
+ echo 'dir="ltr" lang="en-US"';
+}
+/**
+ * The Header for our theme.
+ *
+ * Displays all of the <head> section and everything up till <div id="main">
+ *
+ * @package WordPress
+ * @subpackage Twenty_Eleven
+ * @since Twenty Eleven 1.0
+ */
+?><!DOCTYPE html>
+<!--[if IE 6]>
+<html id="ie6" <?php language_attributes(); ?>>
+<![endif]-->
+<!--[if IE 7]>
+<html id="ie7" <?php language_attributes(); ?>>
+<![endif]-->
+<!--[if IE 8]>
+<html id="ie8" <?php language_attributes(); ?>>
+<![endif]-->
+<!--[if !(IE 6) | !(IE 7) | !(IE 8) ]><!-->
+<html <?php language_attributes(); ?>>
+<!--<![endif]-->
+<head>
+<meta charset="<?php bloginfo( 'charset' ); ?>" />
+<meta name="viewport" content="width=device-width" />
+<title><?php
+ /*
+ * Print the <title> tag based on what is being viewed.
+ */
+ global $_title_;
+ echo $_title_;
+ ?></title>
+<link rel="profile" href="http://gmpg.org/xfn/11" />
+<link rel="stylesheet" type="text/css" media="all" href="<?php bloginfo( 'stylesheet_url' ); ?>" />
+<link rel="pingback" href="<?php bloginfo( 'pingback_url' ); ?>" />
+<!--[if lt IE 9]>
+<script src="<?php echo get_template_directory_uri(); ?>/js/html5.js" type="text/javascript"></script>
+<![endif]-->
+<?php
+ /* We add some JavaScript to pages with the comment form
+ * to support sites with threaded comments (when in use).
+ */
+ if ( is_singular() && get_option( 'thread_comments' ) )
+ wp_enqueue_script( 'comment-reply' );
+
+ /* Always have wp_head() just before the closing </head>
+ * tag of your theme, or you will break many plugins, which
+ * generally use this hook to add elements to <head> such
+ * as styles, scripts, and meta tags.
+ */
+ wp_head();
+?>
+</head>
+
+<body <?php body_class(); ?>>
+<div id="page" class="hfeed">
+ <header id="branding" role="banner">
+ <hgroup>
+ <?php $url = esc_url(home_url('/')); ?>
+ <h1 id="team-number"><a href="<?php echo $url;?>">1024</a></h1>
+ <h1 id="team-name"><a href="<?php echo $url;?>" rel="home">Kil-A-Bytes</a></h1>
+ <h2><a href="<?php echo $url;?>">M<span class="lower">c</span>Kenzie Center for Innovation and Technology</a></h2>
+ </hgroup>
+
+ <div class="only-search with-image">
+ <?php get_search_form(); ?>
+ </div>
+
+ <nav id="access" role="navigation">
+ <h3 class="assistive-text"><?php _e( 'Main menu', 'twentyeleven' ); ?></h3>
+ <?php /* Allow screen readers / text browsers to skip the navigation menu and get right to the good stuff. */ ?>
+ <div class="skip-link"><a class="assistive-text" href="#content" title="<?php esc_attr_e( 'Skip to primary content', 'twentyeleven' ); ?>"><?php _e( 'Skip to primary content', 'twentyeleven' ); ?></a></div>
+ <div class="skip-link"><a class="assistive-text" href="#secondary" title="<?php esc_attr_e( 'Skip to secondary content', 'twentyeleven' ); ?>"><?php _e( 'Skip to secondary content', 'twentyeleven' ); ?></a></div>
+ <?php /* Our navigation menu. If one isn't filled out, wp_nav_menu falls back to wp_page_menu. The menu assiged to the primary position is the one used. If none is assigned, the menu with the lowest ID is used. */ ?>
+ <?php wp_nav_menu( array( 'theme_location' => 'primary' ) ); ?>
+ </nav><!-- #access -->
+ </header><!-- #branding -->
+
+
+ <div id="main"> \ No newline at end of file
diff --git a/apps/um/views/pages/auth/badrequest.html.php b/apps/um/views/pages/auth/badrequest.html.php
new file mode 100644
index 0000000..c1fe726
--- /dev/null
+++ b/apps/um/views/pages/auth/badrequest.html.php
@@ -0,0 +1,11 @@
+<?php global $VARS;
+$t = $VARS['template'];
+
+$t->status('400 Bad Request');
+$t->header('Authentication');
+$t->paragraph('The recieved POST request was malformed/invalid. '.
+ 'If you got here from a link, this is a bug; '.
+ 'Let the admin know.'.
+ 'If you got here from outside, then the API is being '.
+ 'used incorrectly.');
+$t->footer();
diff --git a/apps/um/views/pages/auth/index.html.php b/apps/um/views/pages/auth/index.html.php
new file mode 100644
index 0000000..ac80140
--- /dev/null
+++ b/apps/um/views/pages/auth/index.html.php
@@ -0,0 +1,12 @@
+<?php global $VARS;
+$t = $VARS['template'];
+$username = $VARS['username'];
+
+$t->header('Authentication');
+
+$t->openTag('div',array('class'=>'login'));
+$t->text("Logged in as ".htmlentities($username).'.');
+$t->logout_button('Logout');
+$t->closeTag('div');
+
+$t->footer(); \ No newline at end of file
diff --git a/apps/um/views/pages/auth/login.html.php b/apps/um/views/pages/auth/login.html.php
new file mode 100644
index 0000000..4e3e0e6
--- /dev/null
+++ b/apps/um/views/pages/auth/login.html.php
@@ -0,0 +1,54 @@
+<?php global $VARS;
+$t = $VARS['template'];
+$username = $VARS['username'];
+$password = $VARS['password'];
+
+switch ($VARS['login_code']) {
+case 1: $t->status('401 Unauthorized'); break;
+case 2: $t->status('404 Not Found'); break;
+}
+
+$t->header('Authentication');
+
+$t->openTag('form',array('action'=>$t->url('auth'), 'method'=>"post"));
+$t->openFieldset('Login');
+switch ($VARS['login_code']) {
+case -1: break;
+case 0:
+ $t->inputP('Successfully logged in as '.
+ htmlentities($username).'.');
+ if (isset($VARS['url'])) {
+ $url = htmlentities($VARS['url']);
+ $t->inputP($t->link($url,
+ 'Return to the page you were on.',
+ true));
+ }
+ $t->closeFieldset();
+ $t->closeTag('form');
+ return;
+ break;
+case 1:
+ $t->inputP("Password does not match username.",
+ array('class'=>'error'));
+ break;
+case 2:
+ $t->inputP("Username <q>$username</q> does not exist.");
+ $username = '';
+ break;
+}
+$t->inputText( 'username', 'Username:', '', $username);
+$t->inputPassword('password', 'Password:', '', $password);
+$t->openTag('li');
+$t->tag('input', array('type'=>'submit', 'value'=>'Login'));
+$t->closeTag('li');
+$t->closeFieldset();
+$t->tag('input', array('type'=>'hidden',
+ 'name'=>'action',
+ 'value'=>'login'));
+if (isset($VARS['url'])) {
+ $url = htmlentities($VARS['url']);
+ $t->tag('input', array('type'=>'hidden',
+ 'name'=>'url',
+ 'value'=>$url));
+}
+$t->closeTag('form');
diff --git a/apps/um/views/pages/auth/logout.html.php b/apps/um/views/pages/auth/logout.html.php
new file mode 100644
index 0000000..2d00998
--- /dev/null
+++ b/apps/um/views/pages/auth/logout.html.php
@@ -0,0 +1,6 @@
+<?php global $VARS;
+$t = $VARS['template'];
+
+$t->header('Authentication');
+$t->paragraph('Logged out');
+$t->footer();
diff --git a/apps/um/views/pages/groups/401.html.php b/apps/um/views/pages/groups/401.html.php
new file mode 100644
index 0000000..23e3778
--- /dev/null
+++ b/apps/um/views/pages/groups/401.html.php
@@ -0,0 +1,15 @@
+<?php global $VARS;
+$t = $VARS['template'];
+
+$t->status('401 Unauthorized');
+$t->header('Unauthorized');
+$t->tag('h1', array(), "401: Unauthorized");
+if ($VARS['uid']===false) {
+ // Not logged in
+ $t->paragraph('You need to be logged in to view group-data.');
+} else {
+ // Logged in, so the account must not activated
+ $t->paragraph('Your account needs to be activated by an administrator '.
+ 'to group-data.');
+}
+$t->footer();
diff --git a/apps/um/views/pages/http404.html.php b/apps/um/views/pages/http404.html.php
new file mode 100644
index 0000000..730b0ee
--- /dev/null
+++ b/apps/um/views/pages/http404.html.php
@@ -0,0 +1,16 @@
+<?php global $VARS;
+$t = $VARS['template'];
+
+$routed = implode('/', $VARS['routed']);
+$remainder = implode('/', $VARS['remainder']);
+$full = $routed.'/'.$remainder;
+
+$t->status('404 Not Found');
+$t->header('Page Not Found');
+$t->tag('h1',array(),"404: Not Found");
+$t->paragraph("Awe man, the page you requested wasn't found.");
+$t->paragraph('This folder was found: '.
+ '<tt>'.$t->link($t->url($routed), $routed.'/', true).'</tt>');
+$t->paragraph("But this file in it wasn't: ".
+ '<tt>'.$full.'</tt>');
+$t->footer();
diff --git a/apps/um/views/pages/index.html.php b/apps/um/views/pages/index.html.php
new file mode 100644
index 0000000..71b0091
--- /dev/null
+++ b/apps/um/views/pages/index.html.php
@@ -0,0 +1,8 @@
+<?php global $VARS;
+$t = $VARS['template'];
+
+$t->header('Main Page');
+$t->tag('h1', array(), "Message Manager");
+$t->paragraph($t->link($t->url('users/new'),'Register to be on the team', true), array('style'=>'font-size:5em'));
+$t->link($t->url('users'), 'List of all users');
+$t->footer();
diff --git a/apps/um/views/pages/messages/401.html.php b/apps/um/views/pages/messages/401.html.php
new file mode 100644
index 0000000..0b24f80
--- /dev/null
+++ b/apps/um/views/pages/messages/401.html.php
@@ -0,0 +1,15 @@
+<?php global $VARS;
+$t = $VARS['template'];
+
+$t->status('401 Unauthorized');
+$t->header('Unauthorized');
+$t->tag('h1', array(), "401: Unauthorized");
+if ($VARS['uid']===false) {
+ // Not logged in
+ $t->paragraph('You need to be logged in to view messages.');
+} else {
+ // Logged in, so the account must not activated
+ $t->paragraph('Your account needs to be activated by an administrator '.
+ 'to view messages.');
+}
+$t->footer();
diff --git a/apps/um/views/pages/messages/frame.html.php b/apps/um/views/pages/messages/frame.html.php
new file mode 100644
index 0000000..30fc1cc
--- /dev/null
+++ b/apps/um/views/pages/messages/frame.html.php
@@ -0,0 +1,58 @@
+<?php global $VARS;
+$t = $VARS['template'];
+$msg = $VARS['msg'];
+
+function messageLink($id) {
+ if (is_array($id)) { $id = $id[1]; }
+ global $VARS; $t = $VARS['template'];
+
+ $msg = new Message($id);
+ $exists = ($msg?true:false);
+
+ return sprintf('&lt;<a href="%1$s"%2$s>%3$s</a>&gt;',
+ $t->url("messages/$id/"),
+ ($exists?'':' class="http404"'),
+ htmlentities($id));
+}
+function parseMessageIDs($string) {
+ $base = $_SERVER['REQUEST_URL'];
+ $html = preg_replace_callback(
+ '/<([^>]*)>/',
+ 'messageLink',
+ $string);
+ return $html;
+}
+
+$t->header('View Message');
+$t->openTag('table');
+$t->row(array('To:' , htmlentities( $msg->getHeader('to' ))));
+$t->row(array('From:' , htmlentities( $msg->getHeader('from' ))));
+$t->row(array('Subject:' , htmlentities( $msg->getHeader('subject' ))));
+$t->row(array('In-Reply-to:', parseMessageIDs($msg->getHeader('in-reply-to'))));
+$t->row(array('References:' , parseMessageIDs($msg->getHeader('references' ))));
+$t->closeTag('table');
+
+$msg_id = htmlentities($msg->msgid());
+
+$t->openTag('div', array('class'=>'message-body'));
+if ($msg->getMessageBodyPart('html')!==false) {
+ $t->tag('h2', array(), 'HTML');
+ $t->tag('iframe', array('src'=>$t->url("messages/$msg_id/body.html")), '');
+}
+if ($msg->getMessageBodyPart('text')!==false) {
+ $t->tag('h2', array(), 'Plain Text');
+ $t->tag('iframe', array('src'=>$t->url("messages/$msg_id/body.txt")), '');
+}
+$t->closeTag('div');
+$t->tag('h2', array(), 'Attachments');
+$t->openTag('table');
+$attachments = $msg->getAttachments();
+foreach ($attachments as $id => $attachment) {
+ $t->row(array(
+ htmlentities($attachment->getContentType()),
+ $t->link($t->url("$msg_id/attachment/$id"),
+ htmlentities($attachment->getFilename())),
+ ));
+}
+$t->closeTag('table');
+$t->footer();
diff --git a/apps/um/views/pages/messages/index.html.php b/apps/um/views/pages/messages/index.html.php
new file mode 100644
index 0000000..111b6c6
--- /dev/null
+++ b/apps/um/views/pages/messages/index.html.php
@@ -0,0 +1,25 @@
+<?php global $VARS;
+$t = $VARS['template'];
+$messages = $VARS['messages'];
+
+$t->header('Message Index');
+$t->tag('h1', array(), "Message Index");
+
+$t->openTag('table');
+$t->row(array('From','Subject', 'Date'));
+foreach ($messages as $date => $message_array) {
+ foreach ($message_array as $message) {
+ $url = $t->url('messages/'.$message['id'].'/');
+ $subject = htmlentities($message['subject']);
+ $from = htmlentities($message['from']);
+ $date_str = str_replace(' ', '&nbsp;', date('Y-m-d H:i:s',$date));
+ $t->row(array(
+ $t->link($url, $from , true),
+ $t->link($url, $subject , true),
+ $t->link($url, $date_str, true),
+ ));
+ }
+}
+$t->closeTag('table');
+
+$t->footer();
diff --git a/apps/um/views/pages/plugins/401.html.php b/apps/um/views/pages/plugins/401.html.php
new file mode 100644
index 0000000..5b1b222
--- /dev/null
+++ b/apps/um/views/pages/plugins/401.html.php
@@ -0,0 +1,9 @@
+<?php global $VARS;
+$t = $VARS['template'];
+
+$t->status('401 Unauthorized');
+$t->header('Unauthorized');
+$t->tag('h1',array(),"401: Unauthorized");
+$t->paragraph('You need to be logged in as an admin to edit global plugin '.
+ 'settings.');
+$t->footer();
diff --git a/apps/um/views/pages/plugins/index.html.php b/apps/um/views/pages/plugins/index.html.php
new file mode 100644
index 0000000..b182288
--- /dev/null
+++ b/apps/um/views/pages/plugins/index.html.php
@@ -0,0 +1,42 @@
+<?php global $VARS;
+require_once('Database.class.php');
+$t = $VARS['template'];
+$plugins = $VARS['plugins'];
+$db = Database::getInstance();
+
+$t->header('Administrator Plugin Management');
+$t->openTag('form',array('method'=>'post','action'=>$t->url('plugins')));
+
+foreach ($plugins as $plugin) {
+ $t->setRet(true);
+ $props = array('type'=>'checkbox',
+ 'name'=>'plugins[]',
+ 'id'=>'plugins_'.$plugin['name'],
+ 'value'=>$plugin['name']);
+ if ($plugin['active']==true) {
+ $props['checked'] = 'checked';
+ }
+ $box = $t->tag('input', $props);
+ $t->setRet(false);
+ $t->openFieldset($plugin['name'].$box);
+
+ $t->inputP($plugin['description']);
+ foreach ($plugin['config'] as $param => $type) {
+ $name = $plugin['key'].'['.$param.']';
+ $value = $db->getPluginConf($plugin['name'], $param);
+ $hint = "Type: $type";
+ switch ($type) {
+ case 'text':
+ case 'int':
+ $t->inputText( $name, $param, $hint, $value); break;
+ case 'password':
+ $t->inputPassword($name, $param, $hint, $value); break;
+ }
+ }
+ $t->closeFieldset();
+}
+
+$t->tag('input', array('type'=>'submit',
+ 'value'=>'Save/Update'));
+$t->closeTag('form');
+$t->footer();
diff --git a/apps/um/views/pages/users/401.html.php b/apps/um/views/pages/users/401.html.php
new file mode 100644
index 0000000..0a5a1ce
--- /dev/null
+++ b/apps/um/views/pages/users/401.html.php
@@ -0,0 +1,15 @@
+<?php global $VARS;
+$t = $VARS['template'];
+
+$t->status('401 Unauthorized');
+$t->header('Unauthorized');
+$t->tag('h1', array(), "401: Unauthorized");
+if ($VARS['uid']===false) {
+ // Not logged in
+ $t->paragraph('You need to be logged in to view user-data.');
+} else {
+ // Logged in, so the account must not activated
+ $t->paragraph('Your account needs to be activated by an administrator '.
+ 'to view user-data.');
+}
+$t->footer();
diff --git a/apps/um/views/pages/users/404.html.php b/apps/um/views/pages/users/404.html.php
new file mode 100644
index 0000000..00f9dca
--- /dev/null
+++ b/apps/um/views/pages/users/404.html.php
@@ -0,0 +1,10 @@
+<?php global $VARS;
+$t = $VARS['template'];
+$username = $VARS['username'];
+
+$t->status('404 Not Found');
+$t->header('User Not Found');
+$t->tag('h1',array(),"404: Not Found");
+$t->paragraph('No user with the name <q>'.
+ htmlentities($username).'</q> exists.');
+$t->footer();
diff --git a/apps/um/views/pages/users/500.html.php b/apps/um/views/pages/users/500.html.php
new file mode 100644
index 0000000..339fe63
--- /dev/null
+++ b/apps/um/views/pages/users/500.html.php
@@ -0,0 +1,15 @@
+<?php global $VARS;
+require_once('Database.class.php');
+$t = $VARS['template'];
+$db = Database::getInstance();
+
+$t->status('500 Internal Server Error');
+$t->header('Unknown error');
+$t->paragraph("An unknown error was encountered when creating ".
+ "the user. The username appears to be free, and ".
+ "the passwords match, so I'm assuming that the ".
+ "error is on our end. Sorry.");
+$t->paragraph("Here's a dump of the SQL error stack, it may ".
+ "help us find the issue:");
+$t->tag('pre', array(), htmlentities($db->mysql_error()));
+$t->footer();
diff --git a/apps/um/views/pages/users/created.html.php b/apps/um/views/pages/users/created.html.php
new file mode 100644
index 0000000..d3027cc
--- /dev/null
+++ b/apps/um/views/pages/users/created.html.php
@@ -0,0 +1,18 @@
+<?php global $VARS;
+$t = $VARS['template'];
+$username = $VARS['username'];
+
+//$t->status('201 Created');
+header('Location: '.$t->url("users/$username"));
+$t->header('User created');
+/*$t->paragraph("You can go ahead and fill out more of your ".
+ "user information, (click the @username link at ".
+ "the top) but will need to wait for an ".
+ "administrator to approve your account before ".
+ "you can really use the site. Actually, ".
+ "filling your info out might help approval, so ".
+ "that the administrator can more easily see who ".
+ "you are.");
+*/
+$t->tag('h2',array(), $t->link($t->url("users/$username"), 'Go on to step 2'));
+$t->footer();
diff --git a/apps/um/views/pages/users/index.csv.php b/apps/um/views/pages/users/index.csv.php
new file mode 100644
index 0000000..0a69cee
--- /dev/null
+++ b/apps/um/views/pages/users/index.csv.php
@@ -0,0 +1,27 @@
+<?php global $VARS;
+$attribs = $VARS['attribs'];
+$users = $VARS['users'];
+
+function escape($value) {
+ if (is_bool($value)) {
+ return ($value?'true':'false');
+ } else {
+ $chars = "'" . '"' . '\\' . ',';
+ return addcslashes($value, $chars);
+ }
+}
+
+$arr = array();
+foreach ($attribs as $attrib) {
+ $arr[] = escape($attrib['name']);
+}
+echo implode(',', $arr)."\n";
+
+foreach ($users as $user) {
+ $arr = array();
+ foreach ($attribs as $attrib) {
+ $props = $user[$attrib['key']];
+ $arr[] = escape($props['value']);
+ }
+ echo implode(',', $arr)."\n";
+}
diff --git a/apps/um/views/pages/users/index.html.php b/apps/um/views/pages/users/index.html.php
new file mode 100644
index 0000000..159ff76
--- /dev/null
+++ b/apps/um/views/pages/users/index.html.php
@@ -0,0 +1,104 @@
+<?php global $VARS;
+$t = $VARS['template'];
+$attribs = $VARS['attribs'];
+$users = $VARS['users'];
+require_once('Login.class.php');
+
+$t->header('Users');
+
+$t->paragraph($t->link($t->url('users.csv'), "Download this as a spreadsheet.", true));
+
+$t->openTag('form', array('action'=>$t->url('users/index'),
+ 'method'=>'post'));
+
+if (Login::isLoggedIn()) {
+ $t->tag('input', array('type'=>'submit',
+ 'value'=>'Save/Update'));
+}
+
+$t->openTag('table', array('class'=>'sortable', 'id'=>'bar'));
+
+function table_head($attribs, $t) {
+ $t->openTag('tr');
+ foreach ($attribs as $attrib) {
+ switch ($attrib['type']) {
+ case 'bool': $class = 'small'; break;
+ default: $class = ''; break;
+ }
+ $t->tag('th', array('class'=>$class), $attrib['name']);
+ }
+ if (Login::isLoggedIn()) {
+ $t->tag('th', array(), '-');
+ }
+ $t->closeTag('tr');
+}
+
+$t->openTag('thead');
+table_head($attribs, $t);
+$t->closeTag('thead');
+
+$t->openTag('tfoot');
+table_head($attribs, $t);
+$t->closeTag('tfoot');
+
+$t->openTag('tbody');
+
+foreach ($users as $user) {
+ $t->openTag('tr');
+
+ foreach ($attribs as $attrib) {
+ $t->openTag('td');
+
+ $props = $user[$attrib['key']];
+
+ $bool = $attrib['type']=='bool';
+ if ($bool) {
+ $value = $props['value']=='true';
+ } else {
+ $value = $props['value'];
+ }
+ $editable = $props['editable'];
+ $post_key = $props['post_key'];
+
+ $arr = array('name'=>$post_key);
+ if (!$editable) {
+ $arr['readonly'] = 'readonly';
+ if ($bool) $arr['disabled'] = $disabled;
+ }
+ if ($bool) {
+ $t->tag('input', array('type'=>'hidden', 'name'=>$post_key, 'value'=>'false'));
+ if ($value==true) {
+ $arr['checked'] = 'checked';
+ }
+ $arr['value'] = 'true';
+ $arr['type'] = 'checkbox';
+ } else {
+ $t->tag('span', array('class'=>'cell_width'), $value);
+ $arr['value'] = $value;
+ $arr['type'] = 'text';
+ }
+
+ $t->tag('input', array('name'=>'_old['.$arr['name'].']',
+ 'value'=>$arr['value'],
+ 'type'=>'hidden'));
+ $t->tag('input', $arr);
+ $t->closeTag('td');
+ }
+
+ if (Login::isLoggedIn()) {
+ $t->openTag('td');
+ $t->link($t->url('users/'.$user['auth_name']['value']), 'More');
+ $t->closeTag('td');
+ }
+ $t->closeTag('tr');
+}
+
+$t->closeTag('tbody');
+$t->closeTag('table');
+
+if (Login::isLoggedIn()) {
+ $t->tag('input', array('type'=>'submit',
+ 'value'=>'Save/Update'));
+}
+
+$t->footer();
diff --git a/apps/um/views/pages/users/individual.html.php b/apps/um/views/pages/users/individual.html.php
new file mode 100644
index 0000000..39360b7
--- /dev/null
+++ b/apps/um/views/pages/users/individual.html.php
@@ -0,0 +1,147 @@
+<?php global $VARS, $CONTACT_METHODS;
+$t = $VARS['template'];
+$users = $VARS['users'];
+$username = $VARS['username'];
+
+function inputText($user, $key, $label, $hint='') {
+ global $VARS; $t = $VARS['template'];
+ $current_setting = $user->getConf($key);
+ $t->inputText("user_$key", $label, $hint, $current_setting,
+ !$user->canEdit());
+}
+function inputTextarea($user, $key, $label, $hint='') {
+ global $VARS; $t = $VARS['template'];
+ $current_setting = $user->getConf($key);
+ $t->inputTextarea("user_$key", $label, $hint, $current_setting,
+ !$user->canEdit());
+}
+
+function inputBool($user, $key, $label, $hint='') {
+ global $VARS; $t = $VARS['template'];
+ $current_setting = $user->getConf($key)=='true';
+ $t->inputBool("user_$key", $label, $hint, $current_setting,
+ !$user->canEdit());
+}
+
+function inputArray($user, $key, $arr) {
+ global $VARS; $t = $VARS['template'];
+ $defaults = $user->getConfArray($key);
+
+ foreach ($arr as $value => $label) {
+ $t->inputBoolArray($key, $value, $label,
+ in_array($value, $defaults), !$user->canEdit());
+ }
+}
+
+function inputField($user, $arr) {
+ $fieldname = $arr[0];
+ $fieldlabel = $arr[1];
+ $fieldtype = $arr[2];
+
+ switch ($fieldtype) {
+ case 'text':
+ inputText($user, $fieldname, $fieldlabel, '');
+ break;
+ case 'textarea':
+ inputTextarea($user, $fieldname, $fieldlabel, '');
+ break;
+ case 'paragraph':
+ global $VARS; $t = $VARS['template'];
+ $t->inputP($fieldlabel);
+ break;
+ case 'checkbox':
+ inputBool($user, $fieldname, $fieldlabel, '');
+ break;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+if (count($users)>1) {
+ $t->header("Users: $username");
+} else {
+ $t->header("User: $username");
+}
+
+foreach($users as $user) {
+$username = $user->getName();
+
+$t->tag('h1', array(), ($user->canEdit()?'Edit':'View')." User <q>$username</q> (UID: ".$user->getUID().")");
+
+if ($user->canEdit()) {
+ $t->openTag('form', array('method'=>'post',
+ 'action'=>$t->url("users/$username")));
+} else {
+ $t->openTag('form');
+}
+
+$t->openFieldset("Login / Authentication");
+// Username ////////////////////////////////////////////////////////////////////
+if (isset($VARS['changed name']) && !$VARS['changed name']) {
+ $t->inputP("Error setting username to ".
+ "<q>$new_name</q>. This is probably because".
+ " a user with that name already exists.",
+ true);
+}
+$t->inputText('auth_name','Username',
+ "This is the name you use to log in, but it is also a ".
+ "short name that is used in various places, think of it ".
+ "as a sort of <q>Twitter name</q>.",
+ $user->getName(), !$user->canEdit());
+// Password ////////////////////////////////////////////////////////////////////
+if (@$VARS['pw_updated']===true) {
+ $t->inputP('Password successfully updated.');
+}
+if (@$VARS['pw mixmatch']===true) {
+ $t->inputP("Passwords don't match.", true);
+}
+if ($user->canEdit()) $t->inputNewPassword('auth_password','Reset Password');
+////////////////////////////////////////////////////////////////////////////////
+$t->closeFieldset();
+
+$t->openFieldset("Contact");
+// TODO: I should make this a setting for admins to set.
+$hints = array('email'=>
+ "Right now you can only have one email address, ".
+ "but I'm working on making it so you can have ".
+ "multiple.",
+ 'phone'=>
+ "A home phone number isn't much use here because it is ".
+ "used to text-message you (if you enable it), and ".
+ "contact you at competition."
+ );
+$use_arr = array();
+foreach ($CONTACT_METHODS as $method) {
+ inputText($user,
+ $method->addr_slug,
+ ucwords($method->addr_text),
+ $hints[$method->addr_slug]);
+ $use_arr[$method->verb_slug] = ucwords($method->verb_text);
+}
+
+$t->inputP("When I recieve a message, notify me using the following methods:");
+inputArray($user, 'use', $use_arr);
+$t->closeFieldSet();
+
+foreach ($VARS['config_options'] as $groupname=>$options) {
+ $t->openFieldset($groupname);
+ foreach ($options as $option) {
+ inputField($user, $option);
+ }
+ $t->closeFieldset();
+}
+
+$t->openFieldSet('Groups');
+$group_arr = array();
+foreach ($VARS['groups'] as $group_name) {
+ $group_arr[$group_name] = ucwords($group_name);
+}
+inputArray($user, 'groups', $group_arr);
+$t->closeFieldset();
+
+if ($user->canEdit()) {
+ $t->tag('input', array('type'=>'submit', 'value'=>'Save'));
+}
+$t->closeTag('form');
+}
+$t->footer();
diff --git a/apps/um/views/pages/users/individual.json.php b/apps/um/views/pages/users/individual.json.php
new file mode 100644
index 0000000..c3dee50
--- /dev/null
+++ b/apps/um/views/pages/users/individual.json.php
@@ -0,0 +1,27 @@
+<?php global $VARS, $CONTACT_METHODS;
+$t = $VARS['template'];
+$users = $VARS['users'];
+$username = $VARS['username'];
+
+$json = array();
+
+foreach ($users as $user_obj) {
+ $user_json = array();
+ $user_json['username'] = $user_obj->getName();
+ $user_json['uid'] = $user_obj->getUID();
+ foreach ($CONTACT_METHODS as $method) {
+ $field = $method->addr_slug;
+ $user_json[$field] = $user_obj->getConf($field);
+ }
+ foreach ($VARS['config_options'] as $groupname=>$options) {
+ foreach ($options as $option) {
+ $fieldname = $option[0];
+ $fieldlabel = $option[1];
+ $fieldtype = $option[2];
+ $user_json[$fieldname] = $user_obj->getConf($fieldname);
+ }
+ }
+ $json[] = $user_json;
+}
+
+echo json_encode($json); \ No newline at end of file
diff --git a/apps/um/views/pages/users/new-locked.html.php b/apps/um/views/pages/users/new-locked.html.php
new file mode 100644
index 0000000..dc7ad0d
--- /dev/null
+++ b/apps/um/views/pages/users/new-locked.html.php
@@ -0,0 +1,9 @@
+<?php global $VARS;
+$t = $VARS['template'];
+
+$t->status('403 Forbidden');
+$t->header('Create new user');
+
+$t->paragraph("Sorry, new user registration is disabled.");
+
+$t->footer();
diff --git a/apps/um/views/pages/users/new-logged-in.html.php b/apps/um/views/pages/users/new-logged-in.html.php
new file mode 100644
index 0000000..51823fe
--- /dev/null
+++ b/apps/um/views/pages/users/new-logged-in.html.php
@@ -0,0 +1,8 @@
+<?php global $VARS;
+$t = $VARS['template'];
+
+$t->header('Create new user');
+
+$t->paragraph("Dude, you're logged in, what are you doing creating an account?");
+
+$t->footer();
diff --git a/apps/um/views/pages/users/new.html.php b/apps/um/views/pages/users/new.html.php
new file mode 100644
index 0000000..9df376f
--- /dev/null
+++ b/apps/um/views/pages/users/new.html.php
@@ -0,0 +1,57 @@
+<?php global $VARS;
+$t = $VARS['template'];
+
+$t->header('Create new user');
+
+$t->openTag('form', array('method'=>'post',
+ 'action'=>$t->url('users')));
+
+$t->openFieldset("New User: Step 1");
+
+if ($VARS['userlist']) {
+ $t->inputP("If you may have already created a username, please, ".
+ "<em>please</em> check the ".
+ $t->link($t->url('users/'), 'user-list', true).
+ " to find your old username, instead of creating a new ".
+ "user. If you don't like the name, you can log in and ".
+ "change it.");
+}
+
+if (in_array('illegal name', $VARS['errors'])) {
+ $t->inputP("That is a forbidden username.", true);
+}
+if (in_array('user exists', $VARS['errors'])) {
+ $t->inputP("A user with that name already exists.");
+}
+$t->inputText('auth_name','Username',
+ "This is the name you use to log in, but it is also a ".
+ "short name that is used in various places, think of it ".
+ "as a sort of <q>Twitter name</q>.",$VARS['username']);
+
+@$password = $VARS['password1'];
+if (in_array('pw mixmatch', $VARS['errors'])) {
+ $t->inputP("The passwords didn't match.", true);
+ $password = '';
+}
+if (in_array('no pw', $VARS['errors'])) {
+ $t->inputP("You must set a password.", true);
+ $password = '';
+}
+$t->inputNewPassword('auth_password','Password', $password);
+
+if (in_array('no email', $VARS['errors'])) {
+ $t->inputP("You must provide an email address.", true);
+}
+$t->inputText('user_email', 'Email Address',
+ 'This is so that we can contact you. (duh).', $VARS['email']);
+$t->closeFieldset();
+
+foreach ($VARS['antispam_html'] as $html) {
+ echo $html;
+}
+
+$t->tag('input', array('type'=>'submit', 'value'=>'Go on to Step 2'));
+
+$t->closeTag('form');
+
+$t->footer();