r49339 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r49338‎ | r49339 | r49340 >
Date:12:36, 9 April 2009
Author:tstarling
Status:deferred
Tags:
Comment:
Some files accidentally missing from previous commits
Modified paths:
  • /trunk/extensions/SecurePoll/auth-api.php (added) (history)
  • /trunk/extensions/SecurePoll/includes/Tallier.php (added) (history)
  • /trunk/extensions/SecurePoll/includes/TallyPage.php (added) (history)

Diff [purge]

Index: trunk/extensions/SecurePoll/includes/Tallier.php
@@ -0,0 +1,88 @@
 2+<?php
 3+
 4+abstract class SecurePoll_Tallier {
 5+ var $election;
 6+
 7+ abstract function addRecord( $record );
 8+ abstract function getResult();
 9+
 10+ static function factory( $type, $election ) {
 11+ switch ( $type ) {
 12+ case 'plurality':
 13+ return new SecurePoll_PluralityTallier( $election );
 14+ default:
 15+ throw new MWException( "Invalid tallier type: $type" );
 16+ }
 17+ }
 18+
 19+ function __construct( $election ) {
 20+ $this->election = $election;
 21+ }
 22+}
 23+
 24+/**
 25+ * Tallier that supports choose-one, approval and range voting
 26+ */
 27+class SecurePoll_PluralityTallier extends SecurePoll_Tallier {
 28+ var $tally = array();
 29+
 30+ function __construct( $election ) {
 31+ parent::__construct( $election );
 32+ $questions = $this->election->getQuestions();
 33+ foreach ( $questions as $question ) {
 34+ foreach ( $question->getOptions() as $option ) {
 35+ $this->tally[$question->getId()][$option->getId()] = 0;
 36+ }
 37+ }
 38+ }
 39+
 40+ function addRecord( $record ) {
 41+ $i = 0;
 42+ $ballot = $this->election->getBallot();
 43+ $scores = $ballot->unpackRecord( $record );
 44+ if ( $scores === false ) {
 45+ return false;
 46+ }
 47+ foreach ( $scores as $qid => $questionScores ) {
 48+ if ( !isset( $this->tally[$qid] ) ) {
 49+ wfDebug( __METHOD__.": unknown QID $qid\n" );
 50+ return false;
 51+ }
 52+ foreach ( $questionScores as $oid => $score ) {
 53+ if ( !isset( $this->tally[$qid][$oid] ) ) {
 54+ wfDebug( __METHOD__.": unknown OID $oid\n" );
 55+ return false;
 56+ }
 57+ $this->tally[$qid][$oid] += $score;
 58+ }
 59+ }
 60+ return true;
 61+ }
 62+
 63+ function getResult() {
 64+ global $wgOut;
 65+ $questions = $this->election->getQuestions();
 66+
 67+ // Sort the scores
 68+ foreach ( $this->tally as &$scores ) {
 69+ arsort( $scores );
 70+ }
 71+
 72+ // Show the results
 73+ $s = '';
 74+ foreach ( $questions as $question ) {
 75+ if ( $s !== '' ) {
 76+ $s .= "<hr/>\n";
 77+ }
 78+ $s .= $wgOut->parse( $question->getMessage( 'text' ) ) .
 79+ '<table class="securepoll-result-table" border="1">';
 80+ foreach ( $question->getOptions() as $option ) {
 81+ $s .= '<tr><td>' . $option->getMessage( 'text' ) . "</td>\n" .
 82+ '<td>' . $this->tally[$question->getId()][$option->getId()] . "</td>\n" .
 83+ "</tr>\n";
 84+ }
 85+ $s .= "</table>\n";
 86+ }
 87+ return $s;
 88+ }
 89+}
Property changes on: trunk/extensions/SecurePoll/includes/Tallier.php
___________________________________________________________________
Name: svn:eol-style
190 + native
Index: trunk/extensions/SecurePoll/includes/TallyPage.php
@@ -0,0 +1,191 @@
 2+<?php
 3+
 4+/**
 5+ * A subpage for tallying votes and producing results
 6+ */
 7+class SecurePoll_TallyPage extends SecurePoll_Page {
 8+ /**
 9+ * Execute the subpage.
 10+ * @param $params array Array of subpage parameters.
 11+ */
 12+ function execute( $params ) {
 13+ global $wgOut, $wgUser, $wgRequest;
 14+
 15+ if ( !count( $params ) ) {
 16+ $wgOut->addWikiMsg( 'securepoll-too-few-params' );
 17+ return;
 18+ }
 19+
 20+ $electionId = intval( $params[0] );
 21+ $this->election = $this->parent->getElection( $electionId );
 22+ if ( !$this->election ) {
 23+ $wgOut->addWikiMsg( 'securepoll-invalid-election', $electionId );
 24+ return;
 25+ }
 26+ $this->initLanguage( $wgUser, $this->election );
 27+ $wgOut->setPageTitle( wfMsg( 'securepoll-tally-title', $this->election->getMessage( 'title' ) ) );
 28+
 29+ if ( !$this->election->isAdmin( $wgUser ) ) {
 30+ $wgOut->addWikiMsg( 'securepoll-need-admin' );
 31+ return;
 32+ }
 33+
 34+ if ( !$this->election->isFinished() ) {
 35+ $wgOut->addWikiMsg( 'securepoll-tally-not-finished' );
 36+ return;
 37+ }
 38+
 39+ $crypt = $this->election->getCrypt();
 40+ if ( $crypt ) {
 41+ if ( !$crypt->canDecrypt() ) {
 42+ $wgOut->addWikiMsg( 'securepoll-tally-no-key' );
 43+ return;
 44+ }
 45+
 46+ if ( $wgRequest->wasPosted() ) {
 47+ if ( $wgRequest->getVal( 'submit_upload' ) ) {
 48+ $this->submitUpload();
 49+ } else {
 50+ $this->submitLocal();
 51+ }
 52+ } else {
 53+ $wgOut->addWikiMsg( 'securepoll-can-decrypt' );
 54+ $this->showLocalForm();
 55+ $this->showUploadForm();
 56+ }
 57+ } else {
 58+ if ( $wgRequest->wasPosted() ) {
 59+ $this->submitLocal();
 60+ } else {
 61+ $this->showLocalForm();
 62+ }
 63+ }
 64+ }
 65+
 66+ /**
 67+ * Show a form which, when submitted, shows a tally for the results in the DB
 68+ */
 69+ function showLocalForm() {
 70+ global $wgOut;
 71+ $wgOut->addHTML(
 72+ Xml::openElement(
 73+ 'form',
 74+ array( 'method' => 'post', 'action' => $this->getTitle()->getLocalUrl() )
 75+ ) .
 76+ "\n" .
 77+ Xml::fieldset(
 78+ wfMsg( 'securepoll-tally-local-legend' ),
 79+ '<div>' .
 80+ Xml::submitButton(
 81+ wfMsg( 'securepoll-tally-local-submit' ),
 82+ array( 'name' => 'submit_local' )
 83+ ) .
 84+ '</div>'
 85+ ) .
 86+ "</form>\n"
 87+ );
 88+ }
 89+
 90+ /**
 91+ * Shows a form for upload of a record produced by the dump subpage.
 92+ */
 93+ function showUploadForm() {
 94+ global $wgOut;
 95+ $wgOut->addHTML(
 96+ Xml::openElement(
 97+ 'form',
 98+ array(
 99+ 'method' => 'post',
 100+ 'action' => $this->getTitle()->getLocalUrl(),
 101+ 'enctype' => 'multipart/form-data'
 102+ )
 103+ ) .
 104+ "\n" .
 105+ Xml::fieldset(
 106+ wfMsg( 'securepoll-tally-upload-legend' ),
 107+ '<div>' .
 108+ Xml::element( 'input', array(
 109+ 'type' => 'file',
 110+ 'name' => 'tally_file',
 111+ 'size' => 40,
 112+ ) ) .
 113+ "</div>\n<div>" .
 114+ Xml::submitButton(
 115+ wfMsg( 'securepoll-tally-upload-submit' ),
 116+ array( 'name' => 'submit_upload' )
 117+ ) .
 118+ "</div>\n"
 119+ ) .
 120+ "</form>\n"
 121+ );
 122+ }
 123+
 124+ /**
 125+ * Show a tally of the local DB
 126+ */
 127+ function submitLocal() {
 128+ global $wgOut;
 129+ $dbr = wfGetDB( DB_SLAVE );
 130+ $res = $dbr->select(
 131+ 'securepoll_votes',
 132+ array( 'vote_record' ),
 133+ array(
 134+ 'vote_election' => $this->election->getId(),
 135+ 'vote_current' => 1,
 136+ 'vote_struck' => 0
 137+ ), __METHOD__
 138+ );
 139+ $crypt = $this->election->getCrypt();
 140+ $tallier = $this->election->getTallier();
 141+ foreach ( $res as $row ) {
 142+ $status = $crypt->decrypt( $row->vote_record );
 143+ if ( !$status->isOK() ) {
 144+ $wgOut->addWikiText( $status->getWikiText() );
 145+ return;
 146+ }
 147+ if ( !$tallier->addRecord( $status->value ) ) {
 148+ $wgOut->addWikiMsg( 'securepoll-tally-error' );
 149+ return;
 150+ }
 151+ }
 152+ $wgOut->addHTML( $tallier->getResult() );
 153+ }
 154+
 155+ /**
 156+ * Show a tally of the results in the uploaded file
 157+ */
 158+ function submitUpload() {
 159+ global $wgOut;
 160+ $crypt = $this->election->getCrypt();
 161+ $tallier = $this->election->getTallier();
 162+ if ( !isset( $_FILES['tally_file'] )
 163+ || !is_uploaded_file( $_FILES['tally_file']['tmp_name'] )
 164+ || !$_FILES['tally_file']['size'] )
 165+ {
 166+ $wgOut->addWikiMsg( 'securepoll-no-upload' );
 167+ return;
 168+ }
 169+
 170+ $fileString = file_get_contents( $_FILES['tally_file']['tmp_name'] );
 171+ $records = StringUtils::explode( "\n\n\n", $fileString );
 172+ foreach ( $records as $encrypted ) {
 173+ if ( trim( $encrypted ) == '' ) {
 174+ continue;
 175+ }
 176+ $status = $crypt->decrypt( $encrypted );
 177+ if ( !$status->isOK() ) {
 178+ $wgOut->addWikiText( $status->getWikiText() );
 179+ return;
 180+ }
 181+ if ( !$tallier->addRecord( $status->value ) ) {
 182+ $wgOut->addWikiMsg( 'securepoll-tally-error' );
 183+ return;
 184+ }
 185+ }
 186+ $wgOut->addHTML( $tallier->getResult() );
 187+ }
 188+
 189+ function getTitle() {
 190+ return $this->parent->getTitle( 'tally/' . $this->election->getId() );
 191+ }
 192+}
Property changes on: trunk/extensions/SecurePoll/includes/TallyPage.php
___________________________________________________________________
Name: svn:eol-style
1193 + native
Index: trunk/extensions/SecurePoll/auth-api.php
@@ -0,0 +1,42 @@
 2+<?php
 3+
 4+$IP = getenv( 'MW_INSTALL_PATH' );
 5+if ( strval( $IP ) === '' ) {
 6+ $IP = dirname( __FILE__ ).'/../..';
 7+}
 8+if ( !file_exists( "$IP/includes/WebStart.php" ) ) {
 9+ $IP .= '/phase3';
 10+}
 11+chdir( $IP );
 12+
 13+require( "$IP/includes/WebStart.php" );
 14+
 15+if ( !class_exists( 'SecurePoll_RemoteMWAuth' ) ) {
 16+ header( 'HTTP/1.1 500 Internal Server Error' );
 17+ echo "SecurePoll is disabled.\n";
 18+ exit( 1 );
 19+}
 20+wfLoadExtensionMessages( 'SecurePoll' );
 21+
 22+header( 'Content-Type: application/vnd.php.serialized; charset=utf-8' );
 23+
 24+$token = $wgRequest->getVal( 'token' );
 25+$id = $wgRequest->getInt( 'id' );
 26+if ( is_null( $token ) || !$id ) {
 27+ echo serialize( Status::newFatal( 'securepoll-api-invalid-params' ) );
 28+ exit;
 29+}
 30+
 31+$user = User::newFromId( $id );
 32+if ( !$user ) {
 33+ echo serialize( Status::newFatal( 'securepoll-api-no-user' ) );
 34+ exit;
 35+}
 36+$token2 = SecurePoll_RemoteMWAuth::encodeToken( $user->getToken() );
 37+if ( $token2 !== $token ) {
 38+ echo serialize( Status::newFatal( 'securepoll-api-token-mismatch' ) );
 39+ exit;
 40+}
 41+$status = Status::newGood( SecurePoll_LocalAuth::getUserParams( $user ) );
 42+echo serialize( $status );
 43+
Property changes on: trunk/extensions/SecurePoll/auth-api.php
___________________________________________________________________
Name: svn:eol-style
144 + native

Status & tagging log