diff --git a/ChangeLog b/ChangeLog
index 8148b2a..2e485c0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2005-10-24  Vincent Untz  <vuntz@gnome.org>
+
+	* configure.in:
+	* foundation.gnome.org/Makefile.am:
+	* foundation.gnome.org/vote/*: add anonymous voting scripts
+
 2005-10-20  Vincent Untz  <vuntz@gnome.org>
 
 	* foundation.gnome.org/index.wml:
diff --git a/configure.in b/configure.in
index 441190e..a6b41b0 100644
--- a/configure.in
+++ b/configure.in
@@ -37,4 +37,6 @@ foundation.gnome.org/news/Makefile
 foundation.gnome.org/referenda/Makefile
 foundation.gnome.org/referenda/2004-10/Makefile
 foundation.gnome.org/referenda/2005-10/Makefile
+foundation.gnome.org/vote/Makefile
+foundation.gnome.org/vote/include/Makefile
 ])
diff --git a/foundation.gnome.org/Makefile.am b/foundation.gnome.org/Makefile.am
index 5e30c0b..6af96bd 100644
--- a/foundation.gnome.org/Makefile.am
+++ b/foundation.gnome.org/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = about contact elections img legal licensing membership news referenda finance
+SUBDIRS = about contact elections img legal licensing membership news referenda finance vote
 
 urlpath = 
 
diff --git a/foundation.gnome.org/vote/.cvsignore b/foundation.gnome.org/vote/.cvsignore
new file mode 100644
index 0000000..2d2f331
--- /dev/null
+++ b/foundation.gnome.org/vote/.cvsignore
@@ -0,0 +1,6 @@
+index.php
+results.php
+votes.php
+vote.php
+Makefile.in
+Makefile
diff --git a/foundation.gnome.org/vote/Makefile.am b/foundation.gnome.org/vote/Makefile.am
new file mode 100644
index 0000000..428ed08
--- /dev/null
+++ b/foundation.gnome.org/vote/Makefile.am
@@ -0,0 +1,14 @@
+SUBDIRS = include
+
+urlpath = /vote
+ 
+page_SCRIPTS = \
+        index.php	\
+        results.php	\
+        votes.php	\
+	vote.php
+
+page_DATA = \
+	vote.css
+
+include $(top_srcdir)/rules.common
diff --git a/foundation.gnome.org/vote/include/.cvsignore b/foundation.gnome.org/vote/include/.cvsignore
new file mode 100644
index 0000000..3dda729
--- /dev/null
+++ b/foundation.gnome.org/vote/include/.cvsignore
@@ -0,0 +1,2 @@
+Makefile.in
+Makefile
diff --git a/foundation.gnome.org/vote/include/Makefile.am b/foundation.gnome.org/vote/include/Makefile.am
new file mode 100644
index 0000000..e2a5bcd
--- /dev/null
+++ b/foundation.gnome.org/vote/include/Makefile.am
@@ -0,0 +1,14 @@
+SUBDIRS = 
+
+urlpath = /vote/include
+ 
+page_SCRIPTS =
+
+page_DATA = \
+	election-sql.php	\
+	step1-login.php		\
+	step2-choose.php	\
+	step3-confirm.php	\
+	step4-commit.php
+
+include $(top_srcdir)/rules.common
diff --git a/foundation.gnome.org/vote/include/election-sql.php b/foundation.gnome.org/vote/include/election-sql.php
new file mode 100644
index 0000000..7eaaa53
--- /dev/null
+++ b/foundation.gnome.org/vote/include/election-sql.php
@@ -0,0 +1,385 @@
+<?php
+
+require_once ("/home/admin/secret/anonvoting");
+
+$elections_table = "elections";
+$options_table = "election_options";
+$anon_tokens_table = "election_anon_tokens";
+$tokens_table = "election_tokens";
+$votes_table = "election_votes";
+$members_table = "foundation_members";
+
+function elec_sql_open () {
+  global $mysql_host;
+  global $mysql_user;
+  global $mysql_password;
+  global $mysql_db;
+
+    $handle = mysql_connect ("$mysql_host", "$mysql_user", "$mysql_password");
+    if (!$handle) {
+      return FALSE;
+    }
+
+    $select_base = mysql_select_db ($mysql_database, $handle); 
+    if (!$select_base) {
+      elec_sql_close ($handle);
+      return FALSE;
+    }
+
+    return $handle;
+}
+
+function elec_sql_close ($handle) {
+    if ($handle === FALSE)
+      return;
+
+    mysql_close ($handle);
+}
+
+function elec_sql_start_transaction ($handle) {
+  if ($handle === FALSE)
+    return FALSE;
+
+  $result = mysql_query ("START TRANSACTION", $handle);
+
+  return ($result !== FALSE);
+}
+
+function elec_sql_commit ($handle) {
+  if ($handle === FALSE)
+    return FALSE;
+
+  $result = mysql_query ("COMMIT", $handle);
+
+  return ($result !== FALSE);
+}
+
+function elec_sql_rollback ($handle) {
+  if ($handle === FALSE)
+    return FALSE;
+
+  $result = mysql_query ("ROLLBACK", $handle);
+
+  return ($result !== FALSE);
+}
+
+function elec_get_by_date_desc_with_where ($handle, $where = "") {
+  global $elections_table;
+
+  if ($handle === FALSE)
+    return FALSE;
+
+  $query = "SELECT * FROM " . $elections_table;
+  if (isset ($where) && $where != "") {
+    $query .= " " . $where;
+  }
+  $query .= " ORDER BY voting_start desc";
+
+  $result = mysql_query ($query, $handle);
+
+  if (!$result) {
+    $retval = FALSE;
+  } else {
+    $result_array = array ();
+    while ($buffer = mysql_fetch_assoc ($result)) {
+      $result_array[] = $buffer;
+    }
+    $retval = $result_array;
+  }
+
+  return $retval;
+}
+
+function elec_get_current_by_date_desc ($handle) {
+  $gmdate = gmdate ("Y-m-d H:i:s");
+  $where = "WHERE '".$gmdate."' >= voting_start AND '".$gmdate."' <= voting_end";
+  return elec_get_by_date_desc_with_where ($handle, $where);
+}
+
+function elec_get_previous_by_date_desc ($handle) {
+  $gmdate = gmdate ("Y-m-d H:i:s");
+  $where = "WHERE '".$gmdate."' > voting_start AND '".$gmdate."' > voting_end";
+  return elec_get_by_date_desc_with_where ($handle, $where);
+}
+
+function elec_verify_email_token ($handle, $election_id, $email, $token) {
+  global $tokens_table;
+  global $members_table;
+
+  if ($handle === FALSE)
+    return FALSE;
+
+  $escaped_election_id = mysql_real_escape_string ($election_id, $handle);
+  $escaped_email = mysql_real_escape_string ($email, $handle);
+  $escaped_token = mysql_real_escape_string ($token, $handle);
+
+  $query = "SELECT COUNT(*) FROM " . $tokens_table . " AS tt, " . $members_table . " AS mt";
+  $query .= " WHERE tt.election_id = '".$escaped_election_id."'";
+  $query .= " AND tt.token = '".$escaped_token."'";
+  $query .= " AND tt.member_id = mt.id";
+  $query .= " AND mt.email = '".$escaped_email."'";
+
+  $result = mysql_query ($query, $handle);
+  if (!$result)
+    return FALSE;
+
+  return (mysql_result ($result, 0, 0) == 1);
+}
+
+function elec_options_get ($handle, $election_id) {
+  global $options_table;
+
+  if ($handle === FALSE)
+    return FALSE;
+
+  $escaped_election_id = mysql_real_escape_string ($election_id, $handle);
+
+  $query = "SELECT * FROM " . $options_table;
+  $query .= " WHERE election_id = '".$escaped_election_id."'";
+
+  $result = mysql_query ($query, $handle);
+
+  if (!$result) {
+    $retval = FALSE;
+  } else {
+    $result_array = array ();
+    while ($buffer = mysql_fetch_assoc ($result)) {
+      $result_array[] = $buffer;
+    }
+    $retval = $result_array;
+  }
+
+  return $retval;
+}
+
+function elec_verify_elections ($options_nb, $options) {
+  if ($options_nb === FALSE || $options === FALSE)
+    return FALSE;
+
+  if ($options_nb < 1)
+    return FALSE;
+
+  if (count ($options) < $options_nb || count ($options) <= 1)
+    return FALSE;
+
+  return TRUE;
+}
+
+function elec_get_election ($handle, $election_id) {
+  global $elections_table;
+
+  if ($handle === FALSE)
+    return FALSE;
+
+  $escaped_election_id = mysql_real_escape_string ($election_id, $handle);
+
+  $query = "SELECT * FROM " . $elections_table;
+  $query .= " WHERE id = '".$escaped_election_id."'";
+
+  $result = mysql_query ($query, $handle);
+
+  if (!$result)
+    return FALSE;
+
+  return mysql_fetch_assoc ($result);
+}
+
+function elec_election_is_current ($election) {
+  $gmdate = gmdate ("Y-m-d H:i:s");
+  return ($gmdate >= $election["voting_start"] && $gmdate <= $election["voting_end"]);
+}
+
+function elec_election_has_ended ($election) {
+  $gmdate = gmdate ("Y-m-d H:i:s");
+  return ($gmdate > $election["voting_start"] && $gmdate > $election["voting_end"]);
+}
+
+function elec_election_get_type ($election) {
+  if ($election["type"] == "1")
+    return "referendum";
+  else
+    return "election";
+}
+
+function elec_vote_get_votes_from_post ($options) {
+  $votes_array = array ();
+
+  foreach ($options as $option) {
+    $name = "vote".$option["id"];
+    if (isset ($_POST[$name]) && $_POST[$name] != "") {
+      array_push ($votes_array, $option["id"]);
+    }
+  }
+
+  return $votes_array;
+}
+
+function elec_verify_vote_is_valid ($options_nb, $options, $vote, $votes_array) {
+  if ($options_nb == 1)
+    return "";
+
+  if (count ($votes_array) > $options_nb) {
+    return "you chose ".count ($votes_array)." answers, while you can't choose more than ".$options_nb." answers.";
+  }
+  
+  return "";
+}
+
+function elec_insert_new_anon_token ($handle, $election_id, $anon_token) {
+  global $anon_tokens_table;
+
+  if ($handle === FALSE)
+    return FALSE;
+
+  $escaped_election_id = mysql_real_escape_string ($election_id, $handle);
+  $escaped_anon_token = mysql_real_escape_string ($anon_token, $handle);
+
+  $query = "SELECT COUNT(*) FROM " . $anon_tokens_table;
+  $query .= " WHERE anon_token = '".$escaped_anon_token."'";
+
+  $result = mysql_query ($query, $handle);
+  if (!$result)
+    return FALSE;
+
+  if (mysql_result ($result, 0, 0) != 0)
+    return FALSE;
+
+  $query = "INSERT INTO " . $anon_tokens_table . " (anon_token, election_id)";
+  $query .= " VALUES ('".$escaped_anon_token."', '".$escaped_election_id."')";
+
+  $result = mysql_query ($query, $handle);
+  if (!$result)
+    return FALSE;
+
+  return mysql_insert_id ($handle);
+}
+
+function elec_insert_new_vote ($handle, $anon_token_id, $vote) {
+  global $votes_table;
+
+  if ($handle === FALSE)
+    return FALSE;
+
+  $escaped_vote = mysql_real_escape_string ($vote, $handle);
+  $escaped_anon_token_id = mysql_real_escape_string ($anon_token_id, $handle);
+
+  $query = "INSERT INTO " . $votes_table . " (option_id, anon_id)";
+  $query .= " VALUES ('".$escaped_vote."', '".$escaped_anon_token_id."')";
+
+  $result = mysql_query ($query, $handle);
+  if (!$result)
+    return FALSE;
+
+  return TRUE;
+}
+
+function elec_sql_remove_token ($handle, $election_id, $email, $token) {
+  global $members_table;
+  global $tokens_table;
+
+  if ($handle === FALSE)
+    return FALSE;
+
+  $escaped_election_id = mysql_real_escape_string ($election_id, $handle);
+  $escaped_email = mysql_real_escape_string ($email, $handle);
+  $escaped_token = mysql_real_escape_string ($token, $handle);
+
+  $query = "DELETE FROM " . $tokens_table;
+  $query .= " USING ". $tokens_table . " AS tt, " . $members_table . " AS mt";
+  $query .= " WHERE tt.election_id = '".$escaped_election_id."'";
+  $query .= " AND tt.token = '".$escaped_token."'";
+  $query .= " AND tt.member_id = mt.id";
+  $query .= " AND mt.email = '".$escaped_email."'";
+
+  $result = mysql_query ($query, $handle);
+  if (!$result)
+    return FALSE;
+
+  return TRUE;
+}
+
+function elec_get_anon_tokens_for_election ($handle, $election_id) {
+  global $anon_tokens_table;
+
+  if ($handle === FALSE)
+    return FALSE;
+
+  $escaped_election_id = mysql_real_escape_string ($election_id, $handle);
+
+  $query = "SELECT * FROM " . $anon_tokens_table;
+  $query .= " WHERE election_id = '".$escaped_election_id."'";
+  $query .= " ORDER BY anon_token";
+
+  $result = mysql_query ($query, $handle);
+
+  if (!$result) {
+    $retval = FALSE;
+  } else {
+    $result_array = array ();
+    while ($buffer = mysql_fetch_assoc ($result)) {
+      $result_array[] = $buffer;
+    }
+    $retval = $result_array;
+  }
+
+  return $retval;
+}
+
+function elec_get_results_election ($handle, $election_id) {
+  global $anon_tokens_table;
+  global $votes_table;
+
+  if ($handle === FALSE)
+    return FALSE;
+
+  $escaped_election_id = mysql_real_escape_string ($election_id, $handle);
+
+  $query = "SELECT option_id, COUNT(option_id) AS total_option FROM " . $anon_tokens_table . " AS att, " . $votes_table . " AS vt";
+  $query .= " WHERE att.election_id = '".$escaped_election_id."'";
+  $query .= " AND att.id = vt.anon_id";
+  $query .= " GROUP BY option_id";
+  $query .= " ORDER BY total_option DESC";
+
+  $result = mysql_query ($query, $handle);
+
+  if (!$result) {
+    $retval = FALSE;
+  } else {
+    $result_array = array ();
+    while ($buffer = mysql_fetch_assoc ($result)) {
+      $result_array[] = $buffer;
+    }
+    $retval = $result_array;
+  }
+
+  return $retval;
+}
+
+function elec_get_votes_for_anon_token ($handle, $anon_token_id) {
+  global $votes_table;
+
+  if ($handle === FALSE)
+    return FALSE;
+
+  $escaped_anon_token_id = mysql_real_escape_string ($anon_token_id, $handle);
+
+  $query = "SELECT option_id FROM " . $votes_table;
+  $query .= " WHERE anon_id = '".$escaped_anon_token_id."'";
+  $query .= " ORDER BY option_id";
+
+  $result = mysql_query ($query, $handle);
+
+  if (!$result) {
+    $retval = FALSE;
+  } else {
+    $result_array = array ();
+    while ($buffer = mysql_fetch_assoc ($result)) {
+      $result_array[] = $buffer["option_id"];
+    }
+    $retval = $result_array;
+  }
+
+  return $retval;
+}
+
+?>
diff --git a/foundation.gnome.org/vote/include/step1-login.php b/foundation.gnome.org/vote/include/step1-login.php
new file mode 100644
index 0000000..82c629f
--- /dev/null
+++ b/foundation.gnome.org/vote/include/step1-login.php
@@ -0,0 +1,19 @@
+<?php
+
+function step1_do () {
+  global $email;
+  global $token;
+
+  $result = "<h2>Step 1/4 - Login</h2>\n";
+
+  $result .= "<p>Please login using the informations that was sent to you in a ballot by e-mail.</p>\n";
+
+  $result .= "<div class=\"votedata\">\n";
+  $result .= "<p><label for=\"email\">E-mail: </label><input type=\"text\" name=\"email\" value=\"".htmlspecialchars ($email)."\" /></p>\n";
+  $result .= "<p><label for=\"token\">Vote token: </label><input type=\"text\" name=\"token\" value=\"".htmlspecialchars ($token)."\" /></p>\n";
+  $result .= "</div>\n";
+
+  return $result;
+}
+
+?>
diff --git a/foundation.gnome.org/vote/include/step2-choose.php b/foundation.gnome.org/vote/include/step2-choose.php
new file mode 100644
index 0000000..5603b27
--- /dev/null
+++ b/foundation.gnome.org/vote/include/step2-choose.php
@@ -0,0 +1,49 @@
+<?php
+
+function step2_do () {
+  global $election;
+  global $options_nb;
+  global $options;
+  global $vote;
+  global $votes_array;
+
+  $result = "<h2>Step 2/4 - Choose your vote</h2>\n";
+
+  $result .= "<p><strong>".$election["question"]."</strong></p>\n";
+  $result .= "<p>Possible answers:</p>\n";
+
+  $result .= "<div class=\"votedata\">\n";
+  if ($options_nb == 1) {
+    $result .= "<p>\n";
+    foreach ($options as $option) {
+      $checked = "";
+      if ($option["id"] == $vote) {
+        $checked = " checked=\"checked\"";
+      }
+
+      $result .= "<input type=\"radio\" name=\"vote\" value=\"".$option["id"]."\"".$checked."> ".$option["option"]."<br />\n";
+    }
+    $result .= "</p>\n";
+
+  } else {
+
+    $result .= "<p>\n";
+    foreach ($options as $option) {
+      $checked = "";
+      if (in_array ($option["id"], $votes_array)) {
+        $checked = " checked=\"checked\"";
+      }
+
+      $result .= "<input type=\"checkbox\" name=\"vote".$option["id"]."\"".$checked."> ".$option["option"]."<br />\n";
+    }
+    $result .= "</p>\n";
+
+  }
+  $result .= "</div>\n";
+  if ($options_nb > 1)
+    $result .= "<p><em>You can choose up to ".$options_nb." answers.</em></p>\n";
+
+  return $result;
+}
+
+?>
diff --git a/foundation.gnome.org/vote/include/step3-confirm.php b/foundation.gnome.org/vote/include/step3-confirm.php
new file mode 100644
index 0000000..f8af55e
--- /dev/null
+++ b/foundation.gnome.org/vote/include/step3-confirm.php
@@ -0,0 +1,68 @@
+<?php
+
+function step3_do () {
+  global $election;
+  global $options_nb;
+  global $options;
+  global $vote;
+  global $votes_array;
+
+  $result = "<h2>Step 3/4 - Confirm your vote</h2>\n";
+
+  $result .= "<p><strong>".$election["question"]."</strong></p>\n";
+  if (($options_nb == 1 && $vote < 0) ||
+      ($options_nb > 1 && count ($votes_array) >= 1)) {
+    $result .= "<p>You choose to vote for:</p>\n";
+
+    $result .= "<div class=\"votedata\">\n";
+    if ($options_nb == 1) {
+
+      $option = null;
+      foreach ($options as $opt) {
+        if ($opt["id"] == $vote) {
+          $option = $opt;
+          break;
+        }
+      }
+      if ($option != null)
+        $result .= "<p>".$option["option"]."</p>\n";
+      else {
+        $result .= "<p>Unknown vote: ".$vote."</p>\n";
+        $error .= "There was an unkown vote: ".$vote."<br />\n";
+      }
+
+    } else {
+
+      $result .= "<ul>\n";
+      foreach ($votes_array as $vote) {
+        $found = FALSE;
+        foreach ($options as $option) {
+          if ($option["id"] == $vote) {
+            $result .= "<li>".$option["option"]."</li>\n";
+            $found = TRUE;
+            break;
+          }
+        }
+
+        if (!$found) {
+          $result .= "<li>Unknown vote: ".$vote."</li>\n";
+          $error .= "There was an unkown vote: ".$vote."<br />\n";
+        }
+      }
+      $result .= "</ul>\n";
+
+    }
+    $result .= "</div>\n";
+
+  } else {
+    $result .= "<div class=\"votedata\">\n";
+    $result .= "<p>You choose to vote for none of the possible answers.</p>\n";
+    $result .= "</div>\n";
+  }
+
+  $result .= "<p>To confirm this vote, please continue to the next step.</p>\n";
+
+  return $result;
+}
+
+?>
diff --git a/foundation.gnome.org/vote/include/step4-commit.php b/foundation.gnome.org/vote/include/step4-commit.php
new file mode 100644
index 0000000..51101ed
--- /dev/null
+++ b/foundation.gnome.org/vote/include/step4-commit.php
@@ -0,0 +1,114 @@
+<?php
+
+require_once ("include/election-sql.php");
+
+// Shamelessly stolen from:
+//    http://www.php.net/manual/en/function.mt-rand.php#55013
+//
+//
+// Returns a random code of the specified length, containing characters that
+// are equally likely to be any of the digits, uppercase letters, or  lowercase
+// letters.
+//
+// The default length of 10 provides 839299365868340224 (62^10) possible codes.
+//
+// NOTE: Do not call wt_srand().  It is handled automatically in PHP 4.2.0 and
+//       above and any additional calls are likely to DECREASE the randomness.
+////
+function randomCode ($length=10){
+   $retVal = "";
+   while(strlen($retVal) < $length){
+       $nextChar = mt_rand(0, 61); // 10 digits + 26 uppercase + 26 lowercase = 62 chars
+       if(($nextChar >=10) && ($nextChar < 36)){ // uppercase letters
+           $nextChar -= 10; // bases the number at 0 instead of 10
+           $nextChar = chr($nextChar + 65); // ord('A') == 65
+       } else if($nextChar >= 36){ // lowercase letters
+           $nextChar -= 36; // bases the number at 0 instead of 36
+           $nextChar = chr($nextChar + 97); // ord('a') == 97
+       } else { // 0-9
+           $nextChar = chr($nextChar + 48); // ord('0') == 48
+       }
+       $retVal .= $nextChar;
+   }
+   return $retVal;
+}
+
+function step4_do () {
+  global $error;
+  global $handle;
+  global $election_id;
+  global $options_nb;
+  global $vote;
+  global $votes_array;
+  global $email;
+  global $token;
+
+  $result = "";
+
+  $res = elec_sql_start_transaction ($handle);
+  if (!$res) {
+    $error .= "Can not start a SQL transaction for the vote.<br />\n";
+    return $result;
+  }
+
+  $i = 0;
+  do {
+    $anon_token = randomCode (32);
+    $anon_token_id = elec_insert_new_anon_token ($handle, $election_id, $anon_token);
+    $i++;
+  } while ($anon_token_id === FALSE && $i < 10);
+
+  if ($anon_token_id === FALSE) {
+    elec_sql_rollback ($handle);
+    $error .= "Can not create an anonymous token.<br />\n";
+    return $result;
+  }
+
+  if ($options_nb == 1) {
+
+    $res = elec_insert_new_vote ($handle, $anon_token_id, $vote);
+
+    if (!$res) {
+      elec_sql_rollback ($handle);
+      $error .= "Can not insert a vote.<br />\n";
+      return $result;
+    }
+
+  } else {
+
+    foreach ($votes_array as $vote) {
+      $res = elec_insert_new_vote ($handle, $anon_token_id, $vote);
+
+      if (!$res) {
+        elec_sql_rollback ($handle);
+        $error .= "Can not insert a vote.<br />\n";
+        return $result;
+      }
+    }
+
+  }
+
+  $res = elec_sql_remove_token ($handle, $election_id, $email, $token);
+
+  if (!$res) {
+    elec_sql_rollback ($handle);
+    $error .= "Can not remove temporary token.<br />\n";
+    return $result;
+  }
+
+  $res = elec_sql_commit ($handle);
+  if (!$res) {
+    $error .= "Can not commit the vote.<br />\n";
+    return $result;
+  }
+
+  $result .= "<h2>Step 4/4 - Keep your anonymous token</h2>\n";
+  $result .= "<h3>Your vote has been received.</h3>\n";
+  $result .= "<p>Please write this anonymous token somewhere:</p>\n";
+  $result .= "<div class=\"votedata\"><p><strong>".$anon_token."</strong></p></div>\n";
+  $result .= "<p>This anonymous token will enable you to verify your vote when the preliminary results will be published. Nobody, even the Membership and Elections Committee, except you knows that this token is associated with you and only you will be able to verify your vote. It is not possible to request this anonymous token later.</p>\n";
+
+  return $result;
+}
+
+?>
diff --git a/foundation.gnome.org/vote/index.wml b/foundation.gnome.org/vote/index.wml
new file mode 100644
index 0000000..128067e
--- /dev/null
+++ b/foundation.gnome.org/vote/index.wml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html>
+
+  <head>
+    <link rel="stylesheet" type="text/css" href="vote.css" />
+    <title>The GNOME Foundation - Votes</title>
+    <meta name="cvsdate" content="$Date$" />
+  </head>
+
+  <body>
+<?php
+require_once ("include/election-sql.php");
+?>
+
+<h1>GNOME Foundation Voting System</h1>
+
+<p>Welcome to the anonymous voting system of the GNOME Foundation. This system is maintained by the Membership and Elections Committee, which can be reached at <a href="mailto:elections@gnome.org">elections@gnome.org</a>.</p>
+
+
+<?php
+$handle = elec_sql_open ();
+if ($handle === FALSE) {
+  echo "<div class=\"error\">Can not open the database.</div>\n";
+  $current_elections = array ();
+  $previous_elections = array ();
+} else {
+  $current_elections = elec_get_current_by_date_desc ($handle);
+  $previous_elections = elec_get_previous_by_date_desc ($handle);
+  elec_sql_close ($handle);
+}
+
+if (count ($current_elections) > 0) {
+?>
+
+<h2>Current elections &amp; referenda</h2>
+
+<p>Please click on one of the following links in order to vote for the corresponding election or referendum.</p>
+
+<ul>
+<?php
+	foreach ($current_elections as $election) {
+    echo "  <li><a href=\"vote.php?election_id=".$election["id"]."\">".$election["name"]."</a></li>\n";
+	}
+?>
+</ul>
+<?php
+}
+
+if (count ($previous_elections) > 0) {
+?>
+
+<h2>Archives of previous elections &amp; referenda</h2>
+
+<p>Please click on one of the following links in order to see the results for the corresponding election or referendum.</p>
+
+<ul>
+<?php
+	foreach ($previous_elections as $election) {
+    echo "  <li><a href=\"results.php?election_id=".$election["id"]."\">".$election["name"]."</a></li>\n";
+	}
+?>
+</ul>
+<?php
+}
+?>
diff --git a/foundation.gnome.org/vote/results.wml b/foundation.gnome.org/vote/results.wml
new file mode 100644
index 0000000..c341e4d
--- /dev/null
+++ b/foundation.gnome.org/vote/results.wml
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html>
+
+  <head>
+    <link rel="stylesheet" type="text/css" href="vote.css" />
+    <title>The GNOME Foundation - Votes</title>
+    <meta name="cvsdate" content="$Date$" />
+  </head>
+
+  <body>
+<?php
+require_once ("include/election-sql.php");
+
+$display = TRUE;
+$error = "";
+
+$handle = elec_sql_open ();
+if ($handle === FALSE) {
+  $error .= "Can not open the database.<br />\n";
+  $display = FALSE;
+}
+
+if ($display && isset ($_GET["election_id"]) && is_numeric ($_GET["election_id"]))
+  $election_id = $_GET["election_id"];
+else {
+  $election_id = -1;
+  $error .= "Please choose an election/referendum on this <a href=\"./\">list</a>.<br />\n";
+  $display = FALSE;
+}
+
+if ($display && $election_id >= 0) {
+  $election = elec_get_election ($handle, $election_id);
+  if ($election === FALSE) {
+    $error .= "The specified election/referendum does not exist.<br />\n";
+    $display = FALSE;
+  } else if (!elec_election_has_ended ($election)) {
+    $error .= "The voting period for the specified ".elec_election_get_type ($election)." starts on ".$election["voting_start"]." (UTC) and ends on ".$election["voting_end"]." (UTC). It is not possible to see the results now.<br />\n";
+    $display = FALSE;
+  }
+}
+
+if (isset ($election) && $election !== FALSE) {
+  echo "<h1>Results for the ".$election["name"]."</h1>\n";
+}
+
+if ($display) {
+  $anon_tokens = elec_get_anon_tokens_for_election ($handle, $election_id);
+  if ($anon_tokens === FALSE) {
+    $error .= "Can not get the anonymous tokens for this ".elec_election_get_type ($election).".\n";
+    $display = FALSE;
+  }
+}
+
+if ($display) {
+  $results = elec_get_results_election ($handle, $election_id);
+  if ($results === FALSE) {
+    $error .= "Can not get the results for this ".elec_election_get_type ($election).".\n";
+    $display = FALSE;
+  }
+}
+
+if ($display) {
+  $options = elec_options_get ($handle, $election_id);
+  if ($options === FALSE) {
+    $error .= "The ".elec_election_get_type ($election)." is not properly set up.\n";
+    $display = FALSE;
+  }
+}
+
+if ($display) {
+  $nb_voters = count ($anon_tokens);
+
+  $automatic_results = array ();
+
+  echo "<p>Please note that these results are automatically calculated and are thus not the official results.</p>\n";
+
+  echo "<p><strong>".$election["question"]."</strong></p>";
+  echo "<p>".$nb_voters." members voted for this ".elec_election_get_type ($election).". The repartition of the votes is:</p>\n";
+
+  echo "<div class=\"votedata\">\n";
+  foreach ($results as $result) {
+    $found = FALSE;
+    foreach ($options as $option) {
+      if ($option["id"] == $result["option_id"]) {
+        echo "<em>".$option["option"]."</em> (<strong>".$result["total_option"]."</strong> votes)<br />\n";
+        $automatic_results[] = $option["option"];
+        $found = TRUE;
+        break;
+      }
+    }
+
+    if (!$found) {
+      echo "<em>Unknown value (".$result["option_id"].")</em> (<strong>".$result["total_option"]."</strong> votes)<br />\n";
+      $automatic_results[] = "Unknown value (".$result["option_id"].")";
+      $error .= "There was an unkown vote: ".$result["option_id"]."<br />\n";
+    }
+  }
+  echo "</div>\n";
+
+  echo "<p>The automatic result of this ".elec_election_get_type ($election)." is thus:</p>\n";
+  echo "<div class=\"votedata\">\n";
+  for ($i = 0; $i < $election["options_nb"]; $i++) {
+    echo "<em>".$automatic_results[$i]."</em><br />\n";
+  }
+  echo "</div>\n";
+
+  echo "<p>Please look at the <a href=\"votes.php?election_id=".$election_id."\">list of all votes</a> and verify that your vote is correct.</p>\n";
+}
+
+if (isset ($error) && $error != "") {
+  echo "<div class=\"error\">".$error."</div>\n";;
+  echo "<p>If you don't understand the error, you should probably contact the Membership and Elections Committee, which can be reached at <a href=\"mailto:elections@gnome.org\">elections@gnome.org</a>.</p>\n";
+}
+
+if (isset ($handle))
+  elec_sql_close ($handle);
+
+?>
diff --git a/foundation.gnome.org/vote/vote.css b/foundation.gnome.org/vote/vote.css
new file mode 100644
index 0000000..96a053e
--- /dev/null
+++ b/foundation.gnome.org/vote/vote.css
@@ -0,0 +1,54 @@
+div.error {
+  font-style: italic;
+  font-weight: bold;
+  color: red;
+}
+
+div.votedata {
+  margin-left: 2em;
+}
+
+label {
+  font-weight: bold;
+  font-size: 0.85em;
+}
+
+input[type=text] {
+  border-color: #ccc;
+  border-style: solid;
+  border-width: 1px;
+  background-color: #eee;
+  margin: 0.1em 0 0.1em 0;
+  padding-left: 0.2em;
+  padding-right: 0.2em;
+  font-size : 1em;
+}
+
+table.detailedvotes {
+  margin-left:auto;
+  margin-right:auto;
+  border-collapse: collapse;
+}
+
+table.detailedvotes th, table.detailedvotes td {
+  border: 1px solid #333;
+  padding: 0.1em 0.5em 0.1em 0.5em;
+  vertical-align: top;
+}
+
+table.detailedvotes th {
+  text-align: center;
+  background-color: #222;
+  color: #fff;
+  font-weight: bold;
+}
+
+table.detailedvotes tr.colorA {
+  background-color: #eee;
+  color: #000;
+}
+
+table.detailedvotes tr.colorB {
+  background-color: #888;
+  color: #fff;
+}
diff --git a/foundation.gnome.org/vote/vote.wml b/foundation.gnome.org/vote/vote.wml
new file mode 100644
index 0000000..bb7085c
--- /dev/null
+++ b/foundation.gnome.org/vote/vote.wml
@@ -0,0 +1,175 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html>
+
+  <head>
+    <link rel="stylesheet" type="text/css" href="vote.css" />
+    <title>The GNOME Foundation - Votes</title>
+    <meta name="cvsdate" content="$Date$" />
+  </head>
+
+  <body>
+<?php
+require_once ("include/election-sql.php");
+
+$max_step = 4;
+
+if (!isset ($_POST["step"])) {
+  $step = 1;
+} else {
+  $step = $_POST["step"];
+}
+
+if ($step > $max_step || $step < 1) {
+  $step = 1;
+}
+
+$result = "";
+$error = "";
+
+$handle = elec_sql_open ();
+if ($handle === FALSE) {
+  $error .= "Can not open the database.<br />\n";
+  $step = 0;
+}
+
+$election_id = -1;
+if ($step == 1) {
+  if (isset ($_GET["election_id"]) && is_numeric ($_GET["election_id"]))
+    $election_id = $_GET["election_id"];
+} else if ($step >= 1) {
+  if (isset ($_POST["election_id"]) && is_numeric ($_POST["election_id"]))
+    $election_id = $_POST["election_id"];
+}
+
+if ($election_id == -1) {
+  $error .= "Please choose an election/referendum on this <a href=\"./\">list</a>.<br />\n";
+  $step = 0;
+} else {
+  $election = elec_get_election ($handle, $election_id);
+  if ($election === FALSE) {
+    $error .= "The specified election/referendum does not exist.<br />\n";
+    $step = 0;
+  } else if (!elec_election_is_current ($election)) {
+    $error .= "The voting period for the specified ".elec_election_get_type ($election)." starts on ".$election["voting_start"]." (UTC) and ends on ".$election["voting_end"]." (UTC). It is not possible to vote now.<br />\n";
+    $step = 0;
+  }
+}
+
+
+if ($step > 1) {
+  $email = "";
+  $token = "";
+  if (isset ($_POST["email"]) && isset ($_POST["token"])) {
+    $email = $_POST["email"];
+    $token = $_POST["token"];
+  }
+
+  if (!elec_verify_email_token ($handle, $election_id, $email, $token)) {
+    $step = 1;
+    $error .= "The e-mail address and token you gave do not match an existing voter.<br />\n";
+  } else {
+
+    $options_nb = $election["options_nb"];
+    $options = elec_options_get ($handle, $election_id);
+
+    if (!elec_verify_elections ($options_nb, $options)) {
+      $error .= "The ".elec_election_get_type ($election)." is not properly set up.\n";
+      $step = 0;
+    }
+
+  }
+}
+
+if (isset ($election) && $election !== FALSE) {
+  echo "<h1>".$election["name"]."</h1>\n";
+}
+
+if ($step >= 2) {
+  if ($options_nb == 1) {
+    $votes_array = array ();
+
+    if (isset ($_POST["vote"]))
+      $vote = $_POST["vote"];
+    else
+      $vote = -1;
+
+  } else {
+
+    $votes_array = elec_vote_get_votes_from_post ($options);
+    $vote = -1;
+  }
+
+  $res = elec_verify_vote_is_valid ($options_nb, $options, $vote, $votes_array);
+  
+  if ($res != "") {
+    $error .= "The vote you made is not valid: ".$res."<br />\n";
+    $step = 2;
+  }
+}
+
+if ($step == 4) {
+  /* vote has been confirmed */
+  require ("include/step4-commit.php");
+
+  $result = step4_do ();
+} else if ($step == 3) {
+  /* confirm vote */
+  require ("include/step3-confirm.php");
+
+  $result = step3_do ();
+} else if ($step == 2) {
+  /* choose vote */
+  require ("include/step2-choose.php");
+
+  $result = step2_do ();
+} else if ($step == 1) {
+  /* login */
+  require ("include/step1-login.php");
+
+  $result = step1_do ();
+} else {
+  if (!isset ($error) || $error == "")
+    $error = "Unknown error.<br />\n";
+}
+
+if (isset ($handle))
+  elec_sql_close ($handle);
+
+if (isset ($error) && $error != "") {
+  echo "<div class=\"error\">".$error."</div>\n";;
+  echo "<p>If you don't understand the error, you should probably contact the Membership and Elections Committee, which can be reached at <a href=\"mailto:elections@gnome.org\">elections@gnome.org</a>.</p>\n";
+}
+
+if ($step != $max_step && $step >= 1) {
+  echo "<form action=\"".$_SERVER['PHP_SELF']."\" method=\"post\">\n";
+}
+
+echo $result;
+
+if ($step != $max_step && $step >= 1) {
+  if ($step > 1) {
+    echo "  <input type=\"hidden\" name=\"email\" value=\"".$email."\">\n";
+    echo "  <input type=\"hidden\" name=\"token\" value=\"".$token."\">\n";
+  }
+  if ($step > 2) {
+    if ($options_nb == 1)
+      echo "  <input type=\"hidden\" name=\"vote\" value=\"".$vote."\">\n";
+    else {
+      foreach ($options as $option) {
+        $name = "vote".$option["id"];
+        if (in_array ($option["id"], $votes_array))
+          $value = "on";
+        else
+          $value = "";
+
+        echo "  <input type=\"hidden\" name=\"".$name."\" value=\"".$value."\">\n";
+      }
+    }
+  }
+  echo "  <input type=\"hidden\" name=\"election_id\" value=\"".$election_id."\">\n";
+  echo "  <input type=\"hidden\" name=\"step\" value=\"".($step + 1)."\">\n";
+  echo "  <input type=\"submit\" value=\"Continue to next step\">\n";
+  echo "</form>\n";
+}
+?>
diff --git a/foundation.gnome.org/vote/votes.wml b/foundation.gnome.org/vote/votes.wml
new file mode 100644
index 0000000..8e2a736
--- /dev/null
+++ b/foundation.gnome.org/vote/votes.wml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html>
+
+  <head>
+    <link rel="stylesheet" type="text/css" href="vote.css" />
+    <title>The GNOME Foundation - Votes</title>
+    <meta name="cvsdate" content="$Date$" />
+  </head>
+
+  <body>
+<?php
+require_once ("include/election-sql.php");
+
+$display = TRUE;
+$error = "";
+
+$handle = elec_sql_open ();
+if ($handle === FALSE) {
+  $error .= "Can not open the database.<br />\n";
+  $display = FALSE;
+}
+
+if ($display && isset ($_GET["election_id"]) && is_numeric ($_GET["election_id"]))
+  $election_id = $_GET["election_id"];
+else {
+  $election_id = -1;
+  $error .= "Please choose an election/referendum on this <a href=\"./\">list</a>.<br />\n";
+  $display = FALSE;
+}
+
+if ($display && $election_id >= 0) {
+  $election = elec_get_election ($handle, $election_id);
+  if ($election === FALSE) {
+    $error .= "The specified election/referendum does not exist.<br />\n";
+    $display = FALSE;
+  } else if (!elec_election_has_ended ($election)) {
+    $error .= "The voting period for the specified ".elec_election_get_type ($election)." starts on ".$election["voting_start"]." (UTC) and ends on ".$election["voting_end"]." (UTC). It is not possible to see the results now.<br />\n";
+    $display = FALSE;
+  }
+}
+
+if (isset ($election) && $election !== FALSE) {
+  echo "<h1>Detailed votes for the ".$election["name"]."</h1>\n";
+}
+
+if ($display) {
+  $anon_tokens = elec_get_anon_tokens_for_election ($handle, $election_id);
+  if ($anon_tokens === FALSE) {
+    $error .= "Can not get the anonymous tokens for this ".elec_election_get_type ($election).".\n";
+    $display = FALSE;
+  }
+}
+
+if ($display) {
+  $options = elec_options_get ($handle, $election_id);
+  if ($options === FALSE) {
+    $error .= "The ".elec_election_get_type ($election)." is not properly set up.\n";
+    $display = FALSE;
+  }
+}
+
+if ($display) {
+  $options_name = array ();
+  foreach ($options as $option) {
+    $options_name[$option["id"]] = $option["option"];
+  }
+
+  echo "<p>Please look at the <a href=\"results.php?election_id=".$election_id."\">automatic results</a> to have a summary of the votes.</p>\n";
+
+  echo "<p>Please note that these results are automatically calculated and are thus not the official results.</p>\n";
+
+  echo "<p><strong>".$election["question"]."</strong></p>\n";
+
+  echo "<table class=\"detailedvotes\">\n<tr><th>Anonymous token</th><th>Vote(s)</th></tr>\n";
+  $color = TRUE;
+  foreach ($anon_tokens as $anon_token) {
+    $votes = elec_get_votes_for_anon_token ($handle, $anon_token["id"]);
+    if ($color)
+      $class = "colorA";
+    else
+      $class = "colorB";
+
+    echo "<tr class=\"".$class."\">\n";
+    echo "<td>".$anon_token["anon_token"]."</td>\n";
+
+    echo "<td>";
+
+    if ($votes === FALSE) {
+      echo "Can not access votes<br />for this anonymous token.";
+      $error .= "Can not get votes for anonymous token ".$anon_token["anon_token"]."<br />\n";
+    } else if (count ($votes) == 0) {
+      echo "This member chose to vote for<br />none of the possible options.";
+    } else {
+      foreach ($votes as $vote) {
+        if (array_key_exists ($vote, $options_name))
+          echo "<em>".$options_name[$vote]."</em><br />\n";
+        else {
+          echo "<em>Unknown value (".$vote.")</em><br />\n";
+          $error .= "There was an unkown vote for anonymous token ".$anon_token["anon_token"].": ".$vote."<br />\n";
+        }
+      }
+    }
+
+    echo "</td>\n";
+
+    echo "</tr>\n";
+    $color = !$color;
+  }
+  echo "</table>\n";
+}
+
+if (isset ($error) && $error != "") {
+  echo "<div class=\"error\">".$error."</div>\n";;
+  echo "<p>If you don't understand the error, you should probably contact the Membership and Elections Committee, which can be reached at <a href=\"mailto:elections@gnome.org\">elections@gnome.org</a>.</p>\n";
+}
+
+if (isset ($handle))
+  elec_sql_close ($handle);
+
+?>