changeset 0:8019b357cc03

Initial import.
author Matti Hamalainen <ccr@tnsp.org>
date Tue, 04 Dec 2012 19:07:18 +0200
parents
children e2cbadeb4c7b
files admin.inc.php ajax.php attendees.inc.php compos.inc.php event.inc.php example.sqlite3 img/2012.png img/compo_screen_1024x768.png img/compo_screen_640x480.png img/fap.png img/fapsm.png img/kallo.png img/kulli.png img/pillu.png img/runkkari.png img/runkkari2.png index.php keygen.php login.php logout.inc.php mconfig.inc.php.example msite.inc.php news.inc.php register.inc.php results.inc.php vote.inc.php
diffstat 26 files changed, 2043 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/admin.inc.php	Tue Dec 04 19:07:18 2012 +0200
@@ -0,0 +1,452 @@
+<?
+// Check if sessions are enabled
+if (!stChkSetting("admpass"))
+{
+  echo "<h1>Oh noes, admin configuration not done!</h1>\n".
+  "<p>Better go and prod that, so you get to use the fine admin interface.</p>\n";
+  $authState = "error";
+}
+else
+if (stAuthSession())
+{
+  $authState = "ok";
+}
+else
+{
+  // Perform authentication if we are not in session already
+  echo "<h1>Party admin login</h1>\n".
+    "<p>Please use illegal telepathy over HTTP to provide a password to enter the party administration systembolaget.</p>\n".
+    "<form name=\"admlogin\" action=\"login.php\" method=\"post\">\n".
+    stGetFormHiddenInput("mode", "check")."\n".
+    stGetFormHiddenInput("goto", $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"])."\n".
+    stGetFormPasswordInput("admpass", "pass", "")."\n".
+    " <input type=\"submit\" value=\" Login \" />\n".
+    "</form>\n";
+
+  $authState = "login";
+}
+
+if ($authState == "ok")
+{
+?>
+<script type="text/javascript">
+function statusMsg(msg)
+{
+  document.getElementById("nstatus").innerHTML = msg;
+}
+
+
+function strtrim(str)
+{
+  if (!str || str == null)
+    return "";
+  return str.replace(/^\s+|\s+$/g,'')
+}
+
+
+function strencode(str)
+{
+  return encodeURIComponent(escape(str));
+}
+
+
+function createXMLRequest()
+{
+  var req;
+  if (window.XMLHttpRequest)
+  {
+    // Modern browsers
+    req = new XMLHttpRequest();
+  }
+  else
+  {
+    // Old IE versions
+    req = new ActiveXObject("Microsoft.XMLHTTP");
+  }
+  return req;
+}
+
+
+function sendPOSTRequest(params, success, failure)
+{
+  var req = createXMLRequest();
+  req.open("POST", "ajax.php", true);
+  req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
+  req.setRequestHeader("Content-length", params.length);
+  req.setRequestHeader("Connection", "close");
+
+  req.onreadystatechange = function()
+  {
+    if (req.readyState == 4)
+    {
+      if (req.status == 404)
+      {
+        window.location = "logout";
+      }
+      else
+      if (req.status == 200)
+      {
+        success(req.responseText);
+        statusMsg(req.statusText);
+      }
+      else
+      {
+        if (failure)
+        {
+          failure(req.status, req.statusText, req.responseText);
+        }
+        else
+        {
+          statusMsg("["+req.status+" - "+req.statusText+"] "+ req.responseText);
+        }
+      }
+    }
+  }
+  req.send(params);
+}
+
+
+function makePostArgs(fields, fprefix, fsuffix)
+{
+  var res = [];
+  for (var id in fields)
+  {
+    var elem = document.getElementById(fprefix + id + fsuffix);
+    if (!elem)
+    {
+      alert("No such DOM element '"+ id +"'.");
+      return "";
+    }
+
+    switch (fields[id])
+    {
+      case 0:
+      case 1:
+        {
+          var str = strtrim(elem.value);
+          if (fields[id] == 1 && str == "")
+          {
+            alert("One or more of the fields are empty.");
+            return "";
+          }
+          res.push(id+"="+strencode(str));
+        }
+        break;
+
+      case 2:
+        res.push(id+"="+parseInt(elem.value));
+        break;
+
+      case 3:
+        res.push(id+"="+(elem.checked ? "1" : "0"));
+        break;
+
+    }
+  }
+  return res.join("&");
+}
+
+
+function refreshItems(id,name,msgname)
+{
+  var msuccess = function(txt)
+  {
+    var nitem = document.getElementById(id);
+    nitem.innerHTML = txt;
+  }
+
+  sendPOSTRequest("action=get&type="+name, msuccess);
+}
+
+
+function deleteItem(id,prefix,type,func,dsc)
+{
+  var msuccess = function(txt)
+  {
+    var item = document.getElementById(prefix+id);
+    item.style.display = "none";
+    setTimeout(func, 550);
+  }
+
+  if (confirm("Are you sure you want to delete "+dsc+" #"+id+"?"))
+  {
+    sendPOSTRequest("action=delete&type="+type+"&id="+id, msuccess);
+  }
+}
+
+
+function refreshNews()
+{
+  refreshItems("nnews", "news", "News list");
+}
+
+
+function refreshAttendees()
+{
+  refreshItems("nattendees", "attendees", "Attendees list");
+}
+
+
+function refreshDump()
+{
+  var msuccess = function(txt)
+  {
+    var nitem = document.getElementById("ndump");
+    nitem.innerHTML = txt;
+  }
+
+  sendPOSTRequest("action=dump&type=attendees", msuccess);
+}
+
+
+function refreshCompos()
+{
+  refreshItems("ncompos", "compos", "Compo list");
+}
+
+
+function refreshEntries()
+{
+  refreshItems("nentries", "entries", "Entry list");
+}
+
+
+function refreshVoters()
+{
+  refreshItems("nvoters", "voters", "Voters list");
+}
+
+
+function addNews()
+{
+  var args = makePostArgs({"title":1,"text":1,"author":1}, "nn", "");
+
+  var msuccess = function(txt)
+  {
+    setTimeout("refreshNews();", 550);
+  }
+
+  sendPOSTRequest(
+    "action=add&type=news&"+args,
+    msuccess);
+  return false;
+}
+
+
+function deleteNews(id)
+{
+  deleteItem(id, "news", "news", "refreshNews();", "news item");
+}
+
+
+function deleteAttendee(id)
+{
+  deleteItem(id, "attendee", "attendees", "refreshAttendees();", "attendee");
+}
+
+
+function updateAttendee(id)
+{
+  var args = makePostArgs({"oneliner":0,"email":0}, "at", id);
+
+  sendPOSTRequest("action=update&type=attendees&id="+id+"&"+args);
+}
+
+
+function addCompo()
+{
+  var args = makePostArgs({"name":1, "description":1}, "nc", "");
+
+  var msuccess = function(txt)
+  {
+    setTimeout("refreshCompos();", 550);
+  }
+
+  sendPOSTRequest("action=add&type=compo&"+args, msuccess);
+  return false;
+}
+
+
+function updateCompo(id)
+{
+  var args = makePostArgs({"name":1, "description":1, "enabled":3}, "co", id);
+
+  sendPOSTRequest("action=update&type=compo&id="+id+"&"+args);
+}
+
+
+function addEntry(id)
+{
+  var args = makePostArgs({"name":1, "author":1}, "ne", id);
+
+  var msuccess = function(txt)
+  {
+    setTimeout("refreshEntries();", 550);
+  }
+
+  sendPOSTRequest("action=add&type=entry&compo_id="+id+"&"+args, msuccess);
+  return false;
+}
+
+
+function updateEntry(id)
+{
+  var args = makePostArgs({"name":1, "author":1}, "en", id);
+
+  sendPOSTRequest(
+    "action=update&type=entry&id="+id+"&"+args);
+}
+
+
+function deleteEntry(id)
+{
+  deleteItem(id, "entry", "entries", "refreshEntries();", "entry");
+}
+
+
+function updateVoter(id)
+{
+  var args = makePostArgs({"enabled":3, "name":0}, "vo", id);
+
+  sendPOSTRequest("action=update&type=voter&id="+id+"&"+args);
+}
+
+
+var registeredTabs = Object();
+
+
+function updateTabList()
+{
+  var item = document.getElementById("pageTabs");
+  var str = "";
+  for (var id in registeredTabs)
+  {
+    str += "<a href=\"#\" onClick=\"switchActiveTab('"+
+      id+"')\">"+registeredTabs[id]+"</a>";
+  }
+  
+  str += "<a class=\"admin\" href=\"logout\">Logout</a>";
+  
+  item.innerHTML = str;
+}
+
+
+function registerTab(id, name)
+{
+  registeredTabs[id] = name;
+}
+
+
+function refreshTabs()
+{
+  for (var id in registeredTabs)
+  {
+    setTimeout("refresh"+ registeredTabs[id] +"();", 10);
+  }
+}
+
+
+function switchActiveTab(tab)
+{
+  for (var id in registeredTabs)
+  {
+    var ob = document.getElementById(id);
+    if (ob)
+    {
+      ob.style.display = (tab == id) ? "block" : "none";
+      if (tab == id)
+      {
+        setTimeout("refresh"+ registeredTabs[id] +"();", 10);
+      }
+    }
+  }
+}
+</script>
+
+<div id="nstatus">
+-
+</div>
+
+<div id="pageTabs">
+</div>
+
+<!-- ========================== -->
+
+<div id="ntab0">
+
+<form method="post" action="" onsubmit="return addNews()">
+ <input id="nntitle" type="text" size="40" /><br />
+ <textarea id="nntext" rows="5" cols="60"></textarea><br />
+ <input id="nnauthor" type="text" value="orgaz" />
+ <input id="nnadd" type="submit" value=" Add post " />
+ <input type="button" value=" Clear " onClick="this.form.reset()" />
+</form>
+
+<hr />
+
+<div id="nnews">
+</div>
+</div>
+
+<!-- ========================== -->
+
+<div id="ntab1">
+<div id="nattendees">
+</div>
+</div>
+
+<!-- ========================== -->
+
+<div id="ntab2">
+<div id="ndump">
+</div>
+</div>
+
+<!-- ========================== -->
+
+<div id="ntab3">
+
+<form method="post" action="" onsubmit="return addCompo()">
+ <input id="ncname" type="text" size="64" /><br />
+ <textarea id="ncdescription" rows="5" cols="60"></textarea><br />
+ <input id="nccompo" type="submit" value=" Add compo " />
+ <input type="button" value=" Clear " onClick="this.form.reset()" />
+</form>
+
+<hr />
+<div id="ncompos">
+</div>
+</div>
+
+<!-- ========================== -->
+
+<div id="ntab4">
+<div id="nentries">
+</div>
+</div>
+
+<!-- ========================== -->
+
+<div id="ntab5">
+<p>
+Key entries can only be generated via the shell-utility 'keygen'.
+</p>
+<div id="nvoters">
+</div>
+</div>
+
+<!-- ========================== -->
+
+<script type="text/javascript">
+registerTab("ntab0", "News");
+registerTab("ntab1", "Attendees");
+registerTab("ntab2", "Dump");
+registerTab("ntab3", "Compos");
+registerTab("ntab4", "Entries");
+registerTab("ntab5", "Voters");
+updateTabList();
+switchActiveTab("ntab0");
+</script>
+<?
+}
+?>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ajax.php	Tue Dec 04 19:07:18 2012 +0200
@@ -0,0 +1,358 @@
+<?
+require "mconfig.inc.php";
+require "msite.inc.php";
+
+// Check if we are allowed to execute
+if (!stCheckHTTPS() || !stAuthSession())
+{
+  header("Status: 404 Not Found");
+  exit;
+}
+
+header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
+header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
+
+
+// Open PDO database connection
+if (!stConnectSQLDB())
+  die("Could not connect to SQL database.");
+
+
+function setStatus($val, $msg)
+{
+  global $statusSet;
+  if (!$statusSet)
+  {
+    header("Status: ".$val." ".$msg);
+  }
+  $statusSet = TRUE;
+}
+
+
+function execSQLCond($sql, $okmsg)
+{
+  if (($res = stExecSQL($sql)) !== FALSE)
+  {
+    if ($okmsg != "")
+      setStatus(200, $okmsg);
+    return $res;
+  }
+  else
+  {
+    setStatus(900, "Error in SQL execution.");
+    return FALSE;
+  }
+}
+
+
+// XMLHttp responses
+$action = "ERROR";
+if (stChkRequestItem("action") && stChkRequestItem("type"))
+{
+  $action = $_REQUEST["action"];
+  $type = $_REQUEST["type"];
+}
+
+
+switch ($action)
+{
+  case "dump":
+    if (($res = execSQLCond(
+      "SELECT * FROM attendees WHERE email NOT NULL AND email != '' ORDER BY regtime DESC",
+      "Dump OK.")) !== FALSE)
+    {
+      $out1 = array();
+      $out2 = array();
+
+      foreach ($res as $item)
+      {
+        $out1[] = $item["name"]." &lt;".$item["email"]."&gt;";
+        $out2[] = $item["email"];
+      }
+
+      echo "<br /><hr />".
+        implode(", ", $out1)."<br /><hr /><br />".
+        implode("<br />", $out1)."<br /><hr /><br />".
+        implode(", ", $out2)."<br /><hr /><br />".
+        implode("<br />", $out2)."<br /><hr />";
+      
+    }
+    break;
+
+  case "get":
+    switch ($type)
+    {
+      case "news":
+        $sql = "SELECT * FROM news ORDER BY utime DESC";
+        break;
+
+      case "attendees":
+        $sql = "SELECT * FROM attendees ORDER BY regtime DESC";
+        break;
+
+      case "compos":
+        $sql = "SELECT * FROM compos ORDER BY id DESC";
+        break;
+      
+      case "entries":
+        stGetCompoList(TRUE);
+        
+        foreach ($compos as $id => $compo)
+        {
+          echo
+            "<form>\n".
+            " <table class=\"misc\">\n".
+            "  <tr>\n".
+            "   <th colspan=\"3\">".chentities($compo["name"])."</th>\n".
+            "  </tr>\n".
+            "  <tr>\n".
+            "   <th>Title</th>\n".
+            "   <th>Author</th>\n".
+            "   <th>Actions</th>\n".
+            "  </tr>\n";
+
+          $prefix = "en";
+          foreach ($compo["entries"] as $eid => $entry)
+          {
+            echo
+              "  <tr id=\"entry".$eid."\">\n".
+              "   <td>".stGetFormTextInput(40, 64, "name", $eid, "en", $entry["name"])."</td>\n".
+              "   <td>".stGetFormTextInput(40, 64, "author", $eid, "en", $entry["author"])."</td>\n".
+              "   <td>".
+              stGetFormButtonInput("update", $eid, $prefix, " Update ", "updateEntry(".$eid.")").
+              stGetFormButtonInput("delete", $eid, $prefix, " Delete ", "deleteEntry(".$eid.")").
+              "</td>\n".
+              "  </tr>\n";
+          }
+          $prefix = "ne";
+          echo
+            "  <tr>\n".
+            "   <td>".stGetFormTextInput(40, 64, "name", $id, "ne", "")."</td>\n".
+            "   <td>".stGetFormTextInput(40, 64, "author", $id, "ne", "")."</td>\n".
+            "   <td>".stGetFormButtonInput("add", $id, $prefix, " Add new ", "addEntry(".$id.")")."</td>\n".
+            "  </tr>\n".
+            " </table>\n".
+            "</form>\n";
+        }
+        break;
+      
+      case "voters":
+        $sql = "SELECT * FROM voters ORDER BY id ASC";
+    }
+    
+    if (isset($sql) && ($res = execSQLCond($sql, "")) !== FALSE)
+    {
+      if ($type == "news")
+      {
+        foreach ($res as $item)
+        {
+          $id = $item["id"];
+          stPrintNewsItem($item,
+            "<br />".
+            "  <button class=\"button\" id=\"ndel".$id.
+            "\" type=\"button\" onclick=\"deleteNews(".$id.
+            ")\">Delete</button>\n"
+            );
+        }
+      }
+      else
+      if ($type == "attendees")
+      {
+        echo
+        "<table class=\"attendees\">\n".
+        " <tr>\n".
+        "  <th>Name</th>\n".
+        "  <th class=\"groups\">Group(s)</th>\n".
+        "  <th class=\"regtime\">Registered</th>\n".
+        "  <th class=\"oneliner\">Oneliner</th>\n".
+        "  <th class=\"email\">E-mail</th>\n".
+        "  <th>Actions</th>\n".
+        " </tr>\n";
+        $row = 0;
+        foreach ($res as $item)
+          stPrintAttendee($item, $row++, TRUE);
+        echo "</table>\n";
+      }
+      else
+      if ($type == "compos")
+      {
+        foreach ($res as $item)
+        {
+          $id = $item["id"];
+          $prefix = "co";
+          echo
+          "<div id=\"compo".$id."\">\n".
+          "<h2>#".$id." - ".chentities($item["name"])."</h2>\n".
+          stGetFormTextInput(40, 64, "name", $id, $prefix, $item["name"])."\n".
+          stGetFormCheckBoxInput("enabled", $id, $prefix, $item["enabled"], "Enabled")."<br />\n".
+          stGetFormTextArea(5, 60, "description", $id, $prefix, $item["description"])."\n<br />\n".
+          stGetFormButtonInput("update", $id, $prefix, " Update ", "updateCompo(".$id.")")."\n".
+          "</div>\n".
+          "<hr />\n";
+        }
+      }
+      else
+      if ($type == "voters")
+      {
+        echo
+        "<table class=\"misc\">\n".
+        " <tr>\n".
+        "  <th style=\"width: 5%; text-align: center;\">#</th>\n".
+        "  <th style=\"\">Vote key</th>\n".
+        "  <th style=\"\">Name</th>\n".
+        "  <th style=\"width: 5%; text-align: center;\">Active</th>\n".
+        " </tr>\n";
+        $row = 0;
+        foreach ($res as $item)
+        {
+          $id = $item["id"];
+          $prefix = "vo";
+          echo
+          " <tr>\n".
+          " <tr class=\"".($row % 2 == 1 ? "rodd" : "reven")."\" id=\"voter".$id."\">\n".
+          "  <td>".sprintf("%04d", $id)."</td>\n".
+          "  <td>".chentities($item["key"])."</td>\n".
+          "  <td>".stGetFormTextInput(40, 64, "name", $id, $prefix, $item["name"],
+          "onBlur=\"updateVoter(".$id.")\" autocomplete=\"off\"")."</td>\n".
+          "  <td>".stGetFormCheckBoxInput("enabled", $id, $prefix, $item["enabled"], "Active",
+          "onClick=\"updateVoter(".$id.")\"")."</td>\n".
+          " </tr>\n";
+          $row++;
+        }
+        echo "</table>\n";
+      }
+    }
+    break;
+
+  case "delete":
+    if (stChkRequestItem("id"))
+    {
+      $id = intval(stGetRequestItem("id"));
+
+      if ($type == "news")
+        $sql = stPrepareSQL("DELETE FROM news WHERE id=%d AND persist=0", $id);
+      else
+      if ($type == "attendees")
+        $sql = stPrepareSQL("DELETE FROM attendees WHERE id=%d", $id);
+      else
+      if ($type == "entries")
+        $sql = stPrepareSQL("DELETE FROM entries WHERE id=%d", $id);
+
+      execSQLCond($sql, "OK, ".$type." item ".$id." deleted.");
+    }
+    else
+      setStatus(901, "No ID specified.");
+    break;
+
+  case "add":
+    if ($type == "news" && stChkRequestItem("text") && stChkRequestItem("author") && stChkRequestItem("title"))
+    {
+      $sql = stPrepareSQL(
+        "INSERT INTO news (utime,title,text,author) VALUES (%d,%S,%Q,%S)",
+        time(), "title", "text", "author");
+
+      execSQLCond($sql, "OK, news item added.");
+    }
+    else
+    if ($type == "compo" && stChkRequestItem("name") && stChkRequestItem("description"))
+    {
+      $sql = stPrepareSQL(
+        "INSERT INTO compos (name,description,enabled) VALUES (%S,%Q,0)",
+        "name", "description", 0);
+
+      execSQLCond($sql, "OK, compo added.");
+    }
+    else
+    if ($type == "entry" && stChkRequestItem("name") && stChkRequestItem("author") && stChkRequestItem("compo_id"))
+    {
+      $sql = stPrepareSQL(
+        "INSERT INTO entries (name,author,compo_id) VALUES (%S,%Q,%D)",
+        "name", "author", "compo_id");
+
+      execSQLCond($sql, "OK, entry added.");
+    }
+    else
+      setStatus(902, "No data.");
+    break;
+
+  case "update":
+    if ($type == "attendees" && stChkRequestItem("id") &&
+      stChkRequestItem("email") && stChkRequestItem("oneliner"))
+    {
+      $sql = stPrepareSQLUpdate("attendees",
+        "WHERE id=".intval(stGetRequestItem("id")),
+        array(
+          "email" => "S",
+          "oneliner" => "S",
+        ));
+
+      execSQLCond($sql, "OK, attendee updated.");
+    }
+    else
+    if ($type == "news" && stChkRequestItem("id") &&
+      stChkRequestItem("text") && stChkRequestItem("author") &&
+      stChkRequestItem("title"))
+    {
+      $sql = stPrepareSQLUpdate("news",
+        "WHERE id=".intval(stGetRequestItem("id")),
+        array(
+          "title" => "S",
+          "text" => "Q",
+          "author" => "S"
+        ));
+
+      execSQLCond($sql, "OK, news item updated.");
+    }
+    else
+    if ($type == "compo" && stChkRequestItem("id") &&
+      stChkRequestItem("name") && stChkRequestItem("description") &&
+      stChkRequestItem("enabled"))
+    {
+      $sql = stPrepareSQLUpdate("compos",
+        "WHERE id=".intval(stGetRequestItem("id")),
+        array(
+          "name" => "S",
+          "description" => "Q",
+          "enabled" => "B",
+        ));
+
+      execSQLCond($sql, "OK, compo updated.");
+    }
+    else
+    if ($type == "voter" && stChkRequestItem("id") &&
+      stChkRequestItem("name") && stChkRequestItem("enabled"))
+    {
+      $sql = stPrepareSQLUpdate("voters",
+        "WHERE id=".intval(stGetRequestItem("id")),
+        array(
+          "name" => "S",
+          "enabled" => "B",
+        ));
+
+      execSQLCond($sql, "OK, voter updated.");
+    }
+    else
+    if ($type == "entry" && stChkRequestItem("id") &&
+      stChkRequestItem("compo_id") && stChkRequestItem("name") &&
+      stChkRequestItem("author"))
+    {
+      $sql = stPrepareSQLUpdate("entries",
+        "WHERE id=".intval(stGetRequestItem("id").
+        " AND compo_id=".intval(stGetRequestItem("compo_id"))),
+        array(
+          "name" => "S",
+          "author" => "S",
+        ));
+
+      execSQLCond($sql, "OK, voter updated.");
+    }
+    else
+      setStatus(902, "No data.");
+    break;
+
+  default:
+    setStatus(404, "Not Found");
+    break;
+}
+
+?>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/attendees.inc.php	Tue Dec 04 19:07:18 2012 +0200
@@ -0,0 +1,41 @@
+<?
+if (stChkSetting("allowRegister"))
+{
+?>
+<div class="reglink">
+To register, use <a href="register">this form</a>.
+</div>
+<?
+}
+
+//echo "<h1>Current attendees</h1>\n";
+$maxAttendees = stGetSetting("maxAttendees", 20);
+$numAttendees = 0;
+if (($res = $db->query("SELECT COUNT(*) FROM attendees")) !== FALSE)
+  $numAttendees = $res->fetchColumn();
+
+echo "<p>Total of <b>".$numAttendees.
+ "</b> people registered to attend (<b>".
+ $maxAttendees."</b> max).</p>\n";
+
+?>
+<table class="attendees">
+ <tr>
+  <th class="name">Name</th>
+  <th class="groups">Group(s)</th>
+  <th class="regtime">Registered</th>
+  <th class="oneliner">Oneliner</th>
+ </tr>
+<?
+$index = $numAttendees;
+$row = 0;
+if (($res = stExecSQL("SELECT * FROM attendees ORDER BY regtime DESC")) !== FALSE)
+{
+  foreach ($res as $item)
+  {
+    stPrintAttendee($item, $row++, FALSE, ($index > $maxAttendees) ? " overbooked" : "");
+    $index--;
+  }
+}
+?>
+</table>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/compos.inc.php	Tue Dec 04 19:07:18 2012 +0200
@@ -0,0 +1,31 @@
+<h1>General</h1>
+<p class="notice">
+YOU <b>MUST</b> HAVE AT LEAST ONE ENTRY TO COMPETITIONS IF YOU COME TO THE PARTY.
+</p>
+
+<p class="note">
+If there are enough entries, then AGA/OCS/ECS demos will be run in separate compos.
+<br />
+Remote entries are welcome!
+</p>
+
+<p>
+The compo machine will be an <b>A1200 with an 060/50 and lots of
+RAM</b>. An <b>A500 1.3 512k/512k</b> will also be available if your
+prod is not AGA compatible.
+</p>
+
+<h1>Compos</h1>
+<?
+if (($res = stExecSQL("SELECT * FROM compos WHERE enabled<>0 ORDER BY id ASC")) !== FALSE)
+{
+  foreach ($res as $item)
+  {
+    echo
+    "<div id=\"compo".$item["id"]."\">\n".
+    "<h2>".chentities($item["name"])."</h2>\n".
+    stConvertCompoDesc($item["description"]).
+    "</div>\n";
+  }
+}
+?>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/event.inc.php	Tue Dec 04 19:07:18 2012 +0200
@@ -0,0 +1,25 @@
+<h1>Event program &amp; schedule</h1>
+<ul>
+ <li><b>Aegis</b> of DSS and FAG will be performing a DJ gig.</li>
+ <li>.. and possible additional live acts. More info to come.</li>
+</ul>
+
+<h2>Friday 30.11.</h2>
+<ul>
+ <li><b>18:00</b> - <i>Doors open</i>.</li>
+ <li><b>22:00</b> - DJ set by Aegis.</li>
+</ul>
+
+<h2>Saturday 1.12.</h2>
+<ul>
+ <li><b>14:00</b> - Deadline for remote entries.</li>
+ <li><b>18:00</b> - Deadline for the entries delivered on location.</li>
+ <li><b>20:00</b> - Competitions start.</li>
+</ul>
+
+Competition schedule and voting deadline will depend on number of entries.
+
+<h2>Sunday 2.12.</h2>
+<ul>
+ <li><b>12:00</b> - Party over?</li>
+</ul>
Binary file example.sqlite3 has changed
Binary file img/2012.png has changed
Binary file img/compo_screen_1024x768.png has changed
Binary file img/compo_screen_640x480.png has changed
Binary file img/fap.png has changed
Binary file img/fapsm.png has changed
Binary file img/kallo.png has changed
Binary file img/kulli.png has changed
Binary file img/pillu.png has changed
Binary file img/runkkari.png has changed
Binary file img/runkkari2.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/index.php	Tue Dec 04 19:07:18 2012 +0200
@@ -0,0 +1,60 @@
+<?php
+require "mconfig.inc.php";
+require "msite.inc.php";
+require "mcommon.inc.php";
+
+// Switch to https first, if needed
+if (!stCheckHTTPS())
+{
+  header("Location: https://".$_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"]);
+  exit;
+}
+
+if (isset($_SERVER["REQUEST_URI"]) &&
+  array_key_exists($_SERVER["REQUEST_URI"], $securePages))
+{
+  header("Cache-Control: private");
+  header("Cache-Control: must-revalidate");
+  header("Cache-Control: ".($securePages[$_SERVER["REQUEST_URI"]] ? "no-store" : "no-cache"));
+}
+
+printPageHeader($pageTitle,
+  " <meta http-equiv=\"Pragma\" content=\"no-cache\" />");
+
+if (!stConnectSQLDB())
+{
+  printPageFooter();
+  exit;
+}
+
+?>
+<div id="headerbox">
+ <div id="header">
+  <a href="news"><img src="img/fapsm.png" alt="Finnish Amiga Party 2012" class="logo" /></a>
+  <div id="date">30.11. - 2.12.2012<br />Helsinki, Finland<br />@ old location<br />Entry 15 EUR + prod</div>
+ </div>
+ <div id="menu">
+  <a href="news">News</a>
+  <a href="compos">Compos</a>
+  <a href="event">Event</a>
+  <a href="attendees">Attendees</a>
+<?
+if (0 && chkSetting("allowVoting"))
+echo "  <a href=\"vote\">Vote</a>\n";
+?>
+ </div>
+</div>
+
+<div id="maincontent">
+<div>
+<?
+$pageName = isset($_GET["p"]) ? $_GET["p"] : "news";
+$pageFilename = basename($pageName).".inc.php";
+if (file_exists($pageFilename))
+  include($pageFilename);
+?>
+</div>
+</div>
+<?
+printPageFooter();
+?>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/keygen.php	Tue Dec 04 19:07:18 2012 +0200
@@ -0,0 +1,139 @@
+#!/usr/bin/php
+<?
+require "mconfig.inc.php";
+require "msite.inc.php";
+
+$keyChars = "abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ123456789";
+$maxItems = 4;
+$maxRows  = 25;
+
+function garg($index)
+{
+  global $argc, $argv;
+  if ($index < $argc)
+    return strtolower($argv[$index]);
+  else
+    return FALSE;
+}
+
+function gSQLError($sql)
+{
+  global $db;
+  echo "Error executing SQL query: ".implode("; ", $db->errorInfo())." in statement \"".$sql."\"\n";
+  exit;
+}
+
+if ($argc < 2)
+{
+  echo "Usage: ".$argv[0]." <mode> [args]\n".
+  "Where mode is one of following:\n".
+  "\n".
+  "  generate <#>    Generate # MORE vote keys. If previously\n".
+  "                  generated keys exist, # keys will be added.\n".
+  "\n".
+  "  print [all]     Print list of list of UNactive keys\n".
+  "                  (unless 'all' option is specified)\n".
+  "\n";
+  exit;
+}
+
+if (!stConnectSQLDB())
+  die("Could not connect to SQL database.\n");
+
+switch (substr(garg(1), 0, 2))
+{
+  case "ge":
+    // Check arguments for sanity
+    if (($num = garg(2)) === FALSE)
+    {
+      echo "No number of keys specified.\n";
+      exit;
+    }
+
+    if ($num < 1 || $num > 1000)
+    {
+      echo "Invalid number of keys.\n";
+      exit;
+    }
+
+    echo "Generating keys ..";
+    for ($i = 0; $i < $num; )
+    {
+      echo ".";
+      
+      // Generate one keycode
+      $key = "";
+      for ($n = 0; $n < stGetSetting("votekeylen", 8); $n++)
+        $key .= $keyChars[rand() % strlen($keyChars)];
+
+      // Check if it already exists, to avoid duplicates
+      $sql = stPrepareSQL("SELECT * FROM voters WHERE key=%s", $key);
+      if (($res = @$db->query($sql)) !== FALSE)
+      {
+        if ($res->fetchColumn() === FALSE)
+        {
+          // Nope, add into database
+          $sql = stPrepareSQL(
+            "INSERT INTO voters (key,name,enabled) VALUES (%s,'',0)",
+            $key);
+
+          if (($res = $db->query($sql)) === FALSE)
+            gSQLError($sql);
+
+          $i++;
+        }
+      }
+      else
+      {
+        gSQLError($sql);
+      }
+    }
+    echo "\nGenerated ".$i." new keys.\n";
+    break;
+  
+  case "pr":
+    // Print keys
+    $all = garg(2) == "all";
+    $sql = "SELECT * FROM voters ".($all ? "" : "WHERE enabled=0 ")."ORDER BY id ASC";
+    if (($res = @$db->query($sql)) !== FALSE)
+    {
+      $rows = 0;
+      $nitem = 0;
+      $total = 0;
+
+      foreach ($res as $item)
+      {
+        $total++;
+        printf("%s%04d  -  %8s",
+          $item["enabled"] ? "*" : " ",
+          $item["id"], $item["key"]);
+
+        if (++$nitem >= $maxItems)
+        {
+          $nitem = 0;
+          echo "\n";
+
+          if (++$rows % $maxRows == 0)
+            echo "\f\n";
+        }
+        else
+          echo " | ";
+      }
+
+      if ($nitem > 0)
+        echo "\n";
+
+      echo "Total of ".$total." ".($all ? "keys (all printed)" : "unactive keys")."\n";
+    }
+    else
+    {
+      gSQLError($sql);
+    }
+    break;
+  
+  default:
+    echo "Unknown operating mode '".garg(1)."'.\n";
+    break;
+}
+
+?>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/login.php	Tue Dec 04 19:07:18 2012 +0200
@@ -0,0 +1,10 @@
+<?
+require "mconfig.inc.php";
+require "msite.inc.php";
+
+if (stChkRequestItem("admpass") &&
+  stGetRequestItem("admpass") == stGetSetting("admpass", FALSE))
+  stStartSession();
+
+header("Location: https://".stGetRequestItem("goto"));
+?>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/logout.inc.php	Tue Dec 04 19:07:18 2012 +0200
@@ -0,0 +1,11 @@
+<?
+if (stEndSession())
+{
+  echo "<h1>Logged out</h1>\n".
+  "<p>Have a nice day.</p>\n";
+}
+else
+{
+  header("Location: admin");
+}
+?>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mconfig.inc.php.example	Tue Dec 04 19:07:18 2012 +0200
@@ -0,0 +1,31 @@
+<?
+// Site configuration
+$siteSettings = array(
+  "allowRegister" => false,
+  "allowVoting" => TRUE,
+  "showResults" => TRUE,
+  "showAuthors" => TRUE,
+  "maxAttendees" => 60,
+
+  "admpass" => "supreme",
+  "dbfilename" => "fap.sqlite3",
+
+  "votekeylen" => 8,
+);
+
+
+$securePages = array(
+  "/fap2012/admin" => true,
+  "/fap2012/register" => true,
+  "/fap2012/vote" => false,
+);
+
+$pageTitle = "Finnish Amiga Party 2012";
+$pageCharset = "utf-8";
+$pageCSS = "fap.css";
+
+$specURLs = array(
+  "irc" => array("irc://#fap2012@ircnet", "#fap2012 @ IRCNet"),
+);
+
+?>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/msite.inc.php	Tue Dec 04 19:07:18 2012 +0200
@@ -0,0 +1,465 @@
+<?
+//
+// Nothing to touch after this, mostly
+//
+$errorSet = FALSE;
+$errorMsg = "";
+
+function stError($msg)
+{
+  global $errorSet, $errorMsg;
+  $errorSet = TRUE;
+  $errorMsg .= "<li>".$msg."</li>\n";
+}
+
+
+function stCheckHTTPS()
+{
+  return isset($_SERVER["HTTPS"]) && ($_SERVER["HTTPS"] != "" && $_SERVER["HTTPS"] != "off");
+}
+
+
+function stAuthSession()
+{
+  if (@session_start() === TRUE && isset($_SESSION["admpass"]) &&
+      $_SESSION["admpass"] == stGetSetting("admpass", FALSE))
+  {
+    // Check for session expiration
+    if (!isset($_SESSION["expires"]) || $_SESSION["expires"] < time())
+      return FALSE;
+
+    // Add more time to expiration
+    $_SESSION["expires"] = time() + stGetSetting("admtimeout", 5 * 60);
+    return TRUE;
+  }
+  else
+    return FALSE;
+}
+
+
+function stStartSession()
+{
+  if (@session_start() === TRUE)
+  {
+    $_SESSION["admpass"] = stGetSetting("admpass", FALSE);
+    $_SESSION["expires"] = time() + stGetSetting("admtimeout", 5 * 60);
+    return TRUE;
+  }
+  else
+    return FALSE;
+}
+
+
+function stEndSession()
+{
+  $ok = stAuthSession();
+  $_SESSION = array();
+  if (ini_get("session.use_cookies"))
+  {
+    $params = session_get_cookie_params();
+    setcookie(session_name(), "", time() - 242000,
+      $params["path"], $params["domain"],
+      $params["secure"], $params["httponly"]
+    );
+  }
+  @session_destroy();
+  return $ok;
+}
+
+
+function stGetSetting($name, $default)
+{
+  global $siteSettings;
+  if (isset($siteSettings[$name]))
+    return $siteSettings[$name];
+  else
+    return $default;
+}
+
+
+function stChkSetting($name)
+{
+  global $siteSettings;
+  return isset($siteSettings[$name]) && $siteSettings[$name];
+}
+
+
+function stSpecURL($id)
+{
+  global $specURLs;
+  if (isset($specURLs[$id]))
+    return "<a href=\"".$specURLs[$id][0]."\">".$specURLs[$id][1]."</a>";
+  else
+    return "";
+}
+
+
+function stPrintSpecURL($id)
+{
+  echo stSpecURL($id);
+}
+
+
+function dhentities($str)
+{
+  return str_replace(array("&lt;","&gt;"), array("<", ">"), htmlentities($str, ENT_NOQUOTES, "UTF-8"));
+}
+
+
+function chentities($str)
+{
+  return htmlentities($str, ENT_NOQUOTES, "UTF-8");
+}
+
+
+function stGetFormCheckBoxInput($name, $id, $prefix, $checked, $label, $extra = "")
+{
+  return
+    "<input ".$extra." type=\"checkbox\" id=\"".$prefix.$name.$id."\" ".
+    "name=\"".$prefix.$name.$id."\" ".($checked ? "checked=\"checked\" " : "")." />".
+    "<label for=\"".$prefix.$name.$id."\">".$label."</label>";
+}
+
+
+function stGetFormButtonInput($name, $id, $prefix, $label, $onclick = "")
+{
+  return
+    "<input type=\"button\" id=\"".$prefix.$name.$id."\" ".
+    "name=\"".$name."\" value=\"".$label."\" ".
+    ($onclick != "" ? "onClick=\"".$onclick."\"" : "")." />";
+}
+
+
+function stGetFormTextArea($rows, $cols, $name, $id, $prefix, $value, $extra = "")
+{
+  return
+    "<textarea ".$extra." id=\"".$prefix.$name.$id."\" ".
+    "name=\"".$name."\" rows=\"".$rows."\" cols=\"".$cols."\">".
+    (isset($value) ? chentities($value) : "").
+    "</textarea>";
+}
+
+
+function stGetFormTextInput($size, $len, $name, $id, $prefix, $value, $extra = "")
+{
+  return
+    "<input ".$extra." type=\"text\" id=\"".$prefix.$name.$id."\" ".
+    "name=\"".$name."\" size=\"".$size."\" maxlength=\"".$len."\"".
+    (isset($value) ? " value=\"".chentities($value)."\"" : "").
+    " />";
+}
+
+
+function stGetFormPasswordInput($name, $id, $prefix)
+{
+  return
+    "<input type=\"password\" id=\"".$prefix.$name.$id.
+    "\" name=\"".$name."\" />";
+}
+
+
+function stGetFormHiddenInput($name, $value)
+{
+  return "<input type=\"hidden\" name=\"".$name."\" value=\"".chentities($value)."\" />";
+}
+
+
+function stGetTDEditTextItem($edit, $size, $len, $name, $id, $prefix, $value, $extra = "")
+{
+  return
+    "<td class=\"".$name."\">".
+    ($edit ? stGetFormTextInput($size, $len, $name, $id, $prefix, $value, $extra) : chentities($value)).
+    "</td>";
+}
+
+
+function stPrintFormTextInput($text1, $text2, $size, $len, $name, $extra="")
+{
+  echo "  <tr><th>".chentities($text1)."</th><td>".
+    stGetFormTextInput($size, $len, $name, "", "", $_REQUEST[$name], $extra).
+    "</td><td>".chentities($text2)."</td></tr>\n";
+}
+
+
+function stPrintFormHiddenInput($name, $value)
+{
+  echo " ".stGetFormHiddenInput($name, $value)."\n";
+}
+
+
+function stPrintAttendee($item, $row, $edit, $eclass = "")
+{
+  $id = $item["id"];
+  $prefix = "at";
+  echo "  ".
+    "<tr class=\"".($row % 2 == 1 ? "rodd" : "reven").$eclass."\" id=\"attendee".$id."\">".
+    stGetTDEditTextItem(FALSE, 20, 40, "name", $id, $prefix, $item["name"]).
+    stGetTDEditTextItem(FALSE, 20, 40, "groups", $id, $prefix, $item["groups"]).
+    "<td class=\"regtime\">".date("d M Y / H:i", $item["regtime"])."</td>".
+    stGetTDEditTextItem($edit, 30, 64, "oneliner", $id, $prefix, $item["oneliner"], "autocomplete=\"off\"");
+
+  if ($edit)
+  {
+    echo
+      stGetTDEditTextItem($edit, 20, 40, "email", $id, $prefix, $item["email"], "autocomplete=\"off\"").
+      "<td>".
+      "<button class=\"button\" id=\"atupd".$id."\" type=\"button\" onclick=\"updateAttendee(".$id.")\">Update</button>".
+      "<button class=\"button\" id=\"atdel".$id."\" type=\"button\" onclick=\"deleteAttendee(".$id.")\">Delete</button>".
+      "</td>";
+  }
+
+  echo "</tr>\n";
+}
+
+
+function stPrintNewsItem($item, $edit = "")
+{
+  echo
+  "<div class=\"newsitem\" id=\"news".$item["id"]."\">\n".
+  "  <h2>".chentities($item["title"])."</h2>\n".
+  "  <div class=\"text\">".dhentities($item["text"])."</div>\n".
+  "  <div class=\"sig\">-- ".chentities($item["author"])."<br />".
+    date("d M Y / H:i", $item["utime"]).
+    $edit."</div>\n".
+  "</div>\n";
+}
+
+
+function stChkDataItem($name)
+{
+  return !isset($_REQUEST[$name]) || strlen(trim($_REQUEST[$name])) < 1;
+}
+
+
+function stChkRequestItem($name)
+{
+  return isset($_REQUEST[$name]);
+}
+
+
+function stGetRequestItem($name, $default = "")
+{
+  return isset($_REQUEST[$name]) ? trim($_REQUEST[$name]) : $default;
+}
+
+
+function stGetDRequestItem($name, $default = "")
+{
+  return trim(urldecode(stGetRequestItem($name, $default)));
+}
+
+
+function stLogSQLError($sql)
+{
+  global $db;
+  error_log("SQL error ".implode("; ", $db->errorInfo())." in statement \"".$sql."\"");
+}
+
+
+function stConnectSQLDB()
+{
+  global $db;
+  try {
+    $db = new PDO("sqlite:".stGetSetting("dbfilename", FALSE));
+  }
+  catch (PDOException $e) {
+    error_log("Could not connect to SQL database: ".$e->getMessage().".");
+    return FALSE;
+  }
+  return TRUE;
+}
+
+
+function stGetSQLParam($type, $value)
+{
+  global $db;
+  switch ($type)
+  {
+    case "d":
+      return intval($value);
+
+    case "s":
+      return $db->quote($value);
+
+    case "D":
+      return intval(stGetRequestItem($value));
+
+    case "S":
+      return $db->quote(stGetDRequestItem($value));
+
+    case "Q":
+      return $db->quote(stripslashes(stGetDRequestItem($value)));
+
+    case "B":
+      return intval(stGetRequestItem($value)) ? 1 : 0;
+  }
+}
+
+
+function stPrepareSQL()
+{
+  $argc = func_num_args();
+  $argv = func_get_args();
+  if ($argc < 1)
+  {
+    error_log("Invalid stPrepareSQL() call, no arguments!");
+    return FALSE;
+  }
+  
+  $fmt = $argv[0];
+  $len = strlen($fmt);
+  $sql = "";
+  $argn = 1;
+  $pos = 0;
+  while ($pos < $len)
+  {
+    if ($fmt[$pos] == "%")
+    {
+      if ($argn < $argc)
+        $sql .= stGetSQLParam($fmt[++$pos], $argv[$argn++]);
+      else
+      {
+        error_log("Invalid SQL statement format string '".$fmt.
+          "', not enough parameters specified (".$argn." of ".$argc.")");
+        return FALSE;
+      }
+    }
+    else
+      $sql .= $fmt[$pos];
+    $pos++;
+  }
+  
+  return $sql;
+}
+
+
+function stPrepareSQLUpdate($table, $cond, $pairs)
+{
+  $sql = array();
+  foreach ($pairs as $name => $attr)
+  {
+    $sql[] = $name."=".stGetSQLParam($attr, $name);
+  }
+  return
+    "UPDATE ".$table." SET ".implode(",", $sql).
+    ($cond != "" ? " ".$cond : "");
+}
+
+
+function stExecSQL($sql)
+{
+  global $db;
+  if (($res = $db->query($sql)) !== FALSE)
+    return $res;
+  else
+  {
+    stLogSQLError($sql);
+    stError("Oh noes! SQL error #23!");
+    return FALSE;
+  }
+}
+
+
+function stFetchSQL($sql)
+{
+  global $db;
+  if (($res = $db->query($sql)) !== FALSE)
+  {
+    return $res->fetch();
+  }
+  else
+  {
+    stLogSQLError($sql);
+    stError("Oh noes! SQL error #31!");
+    return FALSE;
+  }
+}
+
+
+function stFetchSQLColumn($sql, $column = 0)
+{
+  global $db;
+  if (($res = $db->query($sql)) !== FALSE)
+  {
+    return $res->fetchColumn($column);
+  }
+  else
+  {
+    stLogSQLError($sql);
+    stError("Oh noes! SQL error #81!");
+    return FALSE;
+  }
+}
+
+
+function stGetCompoList($all)
+{
+  global $compos;
+
+  // Get entries and competitions into an array structure
+  $sql = "SELECT * FROM compos ".($all ? "" :"WHERE enabled<>0 ")."ORDER BY name DESC";
+  foreach (stExecSQL($sql) as $compo)
+  {
+    $id = $compo["id"];
+
+    $compos[$compo["id"]] = array(
+      "name" => $compo["name"],
+      "entries" => array()
+    );
+
+    $sql = stPrepareSQL("SELECT * FROM entries WHERE compo_id=%d", $id);
+    foreach (stExecSQL($sql) as $entry)
+    {
+      $compos[$id]["entries"][$entry["id"]] = $entry;
+    }
+  }
+}
+
+
+function stConvSwitchMode(&$str, &$mode, $newMode)
+{
+  if ($newMode != $mode)
+  {
+    if ($mode != "")
+      $str .= "\n</".$mode.">\n";
+
+    $mode = $newMode;
+
+    if ($mode != "")
+      $str .= "<".$mode.">\n";
+  }
+}
+
+
+function stConvertCompoDesc($desc)
+{
+  global $stDescConversion;
+  $str = "";
+  $mode = "";
+
+  foreach (explode("\n", $desc) as $line)
+  {
+    if (preg_match("/^\s*\s*\*(.+)$/", $line, $m))
+    {
+      stConvSwitchMode($str, $mode, "ol");
+      $str .= "<li>".$m[1]."</li>\n";
+    }
+    else
+    if (preg_match("/^\s*-\s*(.+)$/", $line, $m))
+    {
+      stConvSwitchMode($str, $mode, "ul");
+      $str .= "<li>".$m[1]."</li>\n";
+    }
+    else
+    {
+      stConvSwitchMode($str, $mode, "p");
+      $str .= $line;
+    }
+  }
+
+  stConvSwitchMode($str, $mode, "");
+
+  return $str;
+}
+
+?>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/news.inc.php	Tue Dec 04 19:07:18 2012 +0200
@@ -0,0 +1,24 @@
+<div style="text-align: center;">
+<img src="img/fap.png" alt="FAP" />
+<!--
+<br />
+<img src="img/2012.png" alt="2012" />
+<p>
+Organized by Finnish Amiga Group
+</p>
+-->
+<p>
+Pure Amiga demoscene party, all traditional Amiga compos and purely Amiga-oriented program.
+<br />
+<span class="notice">
+YOU <b>MUST</b> HAVE AT LEAST ONE ENTRY TO COMPETITIONS IF YOU COME TO THE PARTY.
+</span>
+</p>
+</div>
+<?
+if (($res = stExecSQL("SELECT * FROM news ORDER BY utime DESC")) !== FALSE)
+{
+  foreach ($res as $item)
+    stPrintNewsItem($item);
+}
+?>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/register.inc.php	Tue Dec 04 19:07:18 2012 +0200
@@ -0,0 +1,176 @@
+<?
+$mode = stGetRequestItem("mode", "start");
+
+$botCheckIDs = "aBcdefghIjklmnopqrsTuvxyz0123456";
+$botCheckOPs = "bit";
+$botCheckROPs = "+-*";
+
+
+function stPrintFormData($button, $mode = "start")
+{
+  echo
+  "<form name=\"register\" action=\"register\" method=\"post\">\n".
+  " <input type=\"submit\" value=\"".chentities($button)."\" />\n";
+
+  stPrintFormHiddenInput("mode", $mode);
+  
+  foreach (array("name", "groups", "email", "oneliner", "hash", "botcheck") as $name)
+    stPrintFormHiddenInput($name, stGetRequestItem($name));
+
+  echo "</form>\n";
+}
+
+
+function intValueToHash($val)
+{
+  global $botCheckIDs;
+  $str = "";
+  do
+  {
+    $str = $botCheckIDs[$val & 31].$str;
+    $val >>= 5;
+  }
+  while ($val > 0);
+  return $str;
+}
+
+
+function intHashToValue($hash)
+{
+  global $botCheckIDs;
+  for ($val = 0, $i = 0; $i < strlen($hash); $i++)
+  {
+    $val *= 32;
+    $n = strpos($botCheckIDs, $hash[$i]);
+    if ($n !== FALSE)
+      $val += $n;
+    else
+      return -2;
+  }
+  return $val;
+}
+
+
+function splitHash($hash)
+{
+  global $botCheckOPs;
+  return preg_split("/([".$botCheckOPs."])/", $hash, -1, PREG_SPLIT_DELIM_CAPTURE);
+}
+
+
+function hashToCheckStr($hash)
+{
+  global $botCheckOPs, $botCheckROPs;
+  $out = "";
+  
+  foreach (splitHash($hash) as $val)
+  {
+    $i = strpos($botCheckOPs, $val);
+    if ($i !== FALSE)
+      $out .= " ".$botCheckROPs[$i]." ";
+    else
+      $out .= intHashToValue($val);
+  }
+  return $out;
+}
+
+
+function hashToAnswer($hash)
+{
+  eval("\$res = ".hashToCheckStr($hash).";");
+  return $res;
+}
+
+// Check if registration is enabled
+if (!stChkSetting("allowRegister"))
+{
+?>
+<h1>Sorry, registration disabled!</h1>
+<p>
+Registration to the event is not available at this time.
+</p>
+<?
+}
+else
+if ($mode == "start")
+{
+  $botCheckHash =
+    intValueToHash(rand(1,5)).
+    $botCheckOPs[rand(0,2)].
+    intValueToHash(rand(1,5)).
+    $botCheckOPs[rand(0,2)].
+    intValueToHash(5 * rand(1,5));
+
+?>
+<h1>Registration</h1>
+
+<form name="register" action="register" method="post">
+ <input type="hidden" name="mode" value="check">
+ <input type="hidden" name="hash" value="<? echo $botCheckHash ?>">
+ <table>
+<?
+stPrintFormTextInput("Handle:", "(elite)", 30, 30, "name");
+stPrintFormTextInput("Group(s):", "(elite crew^supahmen)", 40, 64, "groups");
+stPrintFormTextInput("E-mail:", "(to be informed of location etc)", 40, 64, "email");
+stPrintFormTextInput("Oneliner:", "(whatever)", 64, 64, "oneliner");
+stPrintFormTextInput(hashToCheckStr($botCheckHash)." = ", "(I.Q. / robot check".
+//" [".hashToAnswer($botCheckHash)."]".
+")", 20, 20, "botcheck");
+?>
+  <tr><td colspan="2"></td><td><input type="submit" value="Register" /></td></tr>
+ </table>
+</form>
+<p>
+Only your <b>handle</b> and the answer to the botcheck are strictly required. If you plan on joining the IRC channel
+(<? stPrintSpecURL("irc") ?>) or staying up to date by other means,
+<b>e-mail</b> is not required either.
+</p>
+
+<?
+}
+else
+if ($mode == "check")
+{
+  if (stChkDataItem("name") || strlen(stGetRequestItem("name")) < 3)
+    stError("Handle / name not given, or too short.");
+
+  if (stChkDataItem("hash"))
+    stError("Invalid data.");
+
+  $hash = stGetRequestItem("hash");
+  $answer = stGetRequestItem("botcheck");
+  if (hashToAnswer($hash) != intval($answer))
+    stError("Incorrect answer to I.Q. / bot check.");
+
+  if ($errorSet)
+  {
+    echo "<p>Following errors occured:</p>\n".
+    "<ul>\n".$errorMsg."</ul>\n";
+    stPrintFormData("Go back");
+  }
+  else
+  {
+    $sql = stPrepareSQL(
+      "INSERT INTO attendees (regtime,name,groups,oneliner,email) VALUES (%d,%S,%S,%S,%S)",
+      time(), "name", "groups", "oneliner", "email");
+
+    if (stExecSQL($sql) !== FALSE)
+    {
+      echo "<h1>Registration successful</h1>\n";
+      echo "<p>Now go make a demo about it!</p>\n";
+      if (stChkDataItem("email"))
+      {
+        echo "<h2>By the way ...</h2>".
+        "<p>As you did not specify an e-mail contact address, you'll have to get updates ".
+        "and information about the location (if you don't already know it) by ".
+        "some other means (<b>".stSpecURL("irc").", for example.</b>)</p>";
+      }
+    }
+    else
+    {
+      echo "<h1>An error occured.</h1>\n";
+      echo "<p>Oh noes! SQL error happenstance!</p>";
+    }
+  }
+}
+?>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/results.inc.php	Tue Dec 04 19:07:18 2012 +0200
@@ -0,0 +1,37 @@
+<?
+echo "<h1>Results</h1>\n";
+
+if (($res = stExecSQL("SELECT * FROM compos ORDER BY name DESC")) !== FALSE)
+foreach ($res as $compo)
+{
+  $sql =
+    "SELECT DISTINCT SUM(votes.value) AS votesum,entries.*,votes.* ".
+    "FROM entries LEFT JOIN votes ON entries.id=votes.entry_id ".
+    "WHERE entries.compo_id=".$compo["id"]." ORDER BY ".
+    ($showResults ? "entries.id" : "votesum")." ASC";
+
+  echo "<h2>".$compo["name"]."</h2>\n".
+  "<table class=\"attendees\" style=\"width: 80%;\">\n".
+  " <tr>\n".
+  "  <th style=\"width: 1%;\">#</th>\n".
+  "  <th style=\"width: 3%;\">Points</th>\n".
+  "  <th>Name</th>\n".
+  "  <th>Author</th>\n".
+  " </tr>\n";
+
+  $index = 1;
+  if (($fres = stExecSQL($sql)) !== FALSE)
+  foreach ($fres as $entry)
+  {
+    echo
+      "<tr>".
+      "<td>".($showResults ? "#".$index : "")."</td>".
+      "<td>".($showResults ? $entry["votesum"] : "?")."</td>".
+      "<td>".chentities($entry["name"])."</td>".
+      "<td>".($showAuthors ? chentities($entry["author"]) : "-")."</td>".
+      "</tr>\n";
+  }
+
+  echo "</table>\n";
+}
+?>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vote.inc.php	Tue Dec 04 19:07:18 2012 +0200
@@ -0,0 +1,183 @@
+<?
+$mode = stGetRequestItem("mode", "start");
+
+stGetCompoList(FALSE);
+
+
+function stPrintFormData($button, $mode = "start")
+{
+  global $compos;
+
+  echo
+  "<form name=\"vote\" action=\"vote\" method=\"post\">\n".
+  " <input type=\"submit\" value=\"".chentities($button)."\" />\n";
+
+  stPrintFormHiddenInput("mode", $mode);
+  stPrintFormHiddenInput("key", stGetRequestItem("key"));
+
+  foreach ($compos as $id => $compo)
+  {
+    foreach ($compo["entries"] as $eid => $entry)
+    {
+      stPrintFormHiddenInput("entry".$eid, stGetRequestItem("entry".$eid));
+    }
+  }
+
+  echo "</form>\n";
+}
+
+
+// Check if voting is enabled
+if (!stChkSetting("allowVoting"))
+{
+?>
+<h1>Sorry, voting disabled!</h1>
+<p>
+Voting functionality not available at this time.
+</p>
+<?
+}
+else
+if ($mode == "start")
+{
+?>
+<h1>Way Too Simple Vote System</h1>
+
+<form name="vote" action="vote" method="post">
+ <input type="hidden" name="mode" value="check">
+ <table class="misc">
+<?
+stPrintFormTextInput("Vote key:", "(that series of characters)", 30, 30, "key", "autocomplete=\"off\"");
+echo "</table>\n";
+
+foreach ($compos as $id => $compo)
+if (count($compo["entries"]) > 0)
+{
+  echo
+    " <table class=\"misc\">\n".
+    "  <tr><th colspan=\"3\">".chentities($compo["name"])."</th></tr>\n".
+    "  <tr>\n".
+    "   <th>Title</th>\n".
+    "   <th>Author</th>\n".
+    "   <th>Actions</th>\n".
+    "  </tr>\n";
+
+  foreach ($compo["entries"] as $eid => $entry)
+  {
+    echo
+      "  <tr>\n".
+      "   <td>".$entry["name"]."</td>\n".
+      "   <td>".$entry["author"]."</td>\n".
+      "   <td>\n";
+
+    for ($i = stGetSetting("voteMin", -2); $i <= stGetSetting("voteMax", 2); $i++)
+    {
+      $name = "entry".$eid;
+      $checked = stChkRequestItem($name) ? stGetRequestItem($name) : 0;
+      echo
+      "    <input type=\"radio\" name=\"".$name."\" ".
+      ($i == $checked ? "checked=\"checked\" " : "").
+      "value=\"".$i."\"><label for=\"".$name."\">".$i."</label>\n";
+    }
+
+    echo
+      "   </td>\n".
+      "  </tr>\n";
+  }
+  echo
+    " </table>\n";
+}
+?>
+ <input type="submit" value="Vote!" /><br />
+</form>
+<?
+}
+else
+if ($mode == "check")
+{
+  // Check received data
+  if (stChkDataItem("key") ||
+    strlen(stGetRequestItem("key")) != stGetSetting("votekeylen", 8))
+  {
+    stError("Invalid or empty vote key, please check.");
+  }
+  else
+  {
+    // Check if the key exists and is active
+    $sql = stPrepareSQL(
+      "SELECT * FROM voters WHERE key=%S AND enabled<>0",
+      "key");
+
+    if (($voter = stFetchSQL($sql)) === FALSE)
+      stError("Vote key does not exist, perhaps you typed it incorrectly?");
+  }
+
+  // Check the submitted vote values
+  foreach ($compos as $id => $compo)
+  if (count($compo["entries"]) > 0)
+  {
+    foreach ($compo["entries"] as $eid => $entry)
+    {
+      $vote = stGetRequestItem("entry".$eid);
+      if ($vote < stGetSetting("voteMin", -2) || $vote > stGetSetting("voteMax", 2))
+      {
+        stError("One or more vote value was out of bounds. Trying to cheat, eh?");
+        break;
+      }
+    }
+  }
+
+  // Ookkay...
+  if ($errorSet)
+  {
+    echo "<p>Following errors occured:</p>\n".
+    "<ul>\n".$errorMsg."</ul>\n";
+    stPrintFormData("Go back");
+  }
+  else
+  {
+    foreach ($compos as $id => $compo)
+    if (count($compo["entries"]) > 0)
+    {
+      foreach ($compo["entries"] as $eid => $entry)
+      {
+        $vote = stGetRequestItem("entry".$eid);
+        $sql = stPrepareSQL("SELECT id FROM votes WHERE voter_id=%d AND entry_id=%d",
+          $voter["id"], $eid);
+          
+        if (stFetchSQLColumn($sql) === false)
+        {
+          $sql = stPrepareSQL(
+            "INSERT INTO votes (voter_id,entry_id,value) VALUES (%d,%d,%d)",
+            $voter["id"], $eid, $vote);
+
+          if (stExecSQL($sql) === false)
+            break;
+        }
+        else
+        {
+          $sql = stPrepareSQL(
+            "UPDATE votes SET value=%d WHERE voter_id=%d AND entry_id=%d",
+            $vote, $voter["id"], $eid);
+
+          if (stExecSQL($sql) === false)
+            break;
+        }
+      }
+    }
+
+    if ($errorSet)
+    {
+      echo "<h1>An error occured.</h1>\n";
+      echo "<p>Following errors occured:</p>\n".
+      "<ul>\n".$errorMsg."</ul>\n";
+      stPrintFormData("Go back");
+    }
+    else
+    {
+      echo "<h1>Voting successful</h1>\n";
+      echo "<p>Now go FAP some more! Or whatever.</p>\n";
+    }
+  }
+}
+?>
\ No newline at end of file