8a523774cf4010cbaee2582c1e16783e5855a1ef
[lhc/web/wiklou.git] / includes / SpecialBoardvote.php
1 <?php
2
3 function wfSpecialBoardvote( $par = "" ) {
4 global $wgRequest, $wgBoardVoteDB;
5
6 $form = new BoardVoteForm( $wgRequest, $wgBoardVoteDB );
7 if ( $par ) {
8 $form->mAction = $par;
9 }
10
11 $form->execute();
12 }
13
14 class BoardVoteForm {
15 var $mPosted, $mContributing, $mVolunteer, $mDBname, $mUserDays, $mUserEdits;
16 var $mHasVoted, $mAction, $mUserKey;
17
18 function BoardVoteForm( &$request, $dbName ) {
19 global $wgUser, $wgDBname, $wgInputEncoding;
20
21 $this->mUserKey = iconv( $wgInputEncoding, "UTF-8", $wgUser->getName() ) . "@$wgDBname";
22 $this->mPosted = $request->wasPosted();
23 $this->mContributing = $request->getInt( "contributing" );
24 $this->mVolunteer = $request->getInt( "volunteer" );
25 $this->mDBname = $dbName;
26 $this->mHasVoted = $this->hasVoted( $wgUser );
27 $this->mAction = $request->getText( "action" );
28 }
29
30 function execute() {
31 global $wgUser;
32 if ( $this->mAction == "list" ) {
33 $this->displayList();
34 } elseif ( $this->mAction == "dump" ) {
35 $this->dump();
36 } elseif( $this->mAction == "vote" ) {
37 if ( !$wgUser->getID() ) {
38 $this->notLoggedIn();
39 } else {
40 $this->getQualifications( $wgUser );
41 if ( $this->mUserDays < 90 ) {
42 $this->notQualified();
43 } elseif ( $this->mPosted ) {
44 $this->logVote();
45 } else {
46 $this->displayVote();
47 }
48 }
49 } else {
50 $this->displayEntry();
51 }
52 }
53
54 function displayEntry() {
55 global $wgOut;
56 $wgOut->addWikiText( wfMsg( "boardvote_entry" ) );
57 }
58
59 function hasVoted( &$user ) {
60 global $wgDBname;
61 $row = wfGetArray( $this->mDBname . ".vote", array( "1" ),
62 array( "vote_key" => $this->mUserKey ), "BoardVoteForm::getUserVote" );
63 if ( $row === false ) {
64 return false;
65 } else {
66 return true;
67 }
68 }
69
70 function logVote() {
71 global $wgUser, $wgDBname, $wgIP, $wgOut;
72 $now = wfTimestampNow();
73 $record = $this->encrypt( $this->mContributing, $this->mVolunteer );
74 $db = $this->mDBname;
75
76 # Add vote to log
77 wfInsertArray( "$db.log", array(
78 "log_user" => $wgUser->getID(),
79 "log_user_text" => $wgUser->getName(),
80 "log_user_key" => $this->mUserKey,
81 "log_wiki" => $wgDBname,
82 "log_edits" => $this->mUserEdits,
83 "log_days" => $this->mUserDays,
84 "log_record" => $record,
85 "log_ip" => $wgIP,
86 "log_xff" => @$_SERVER['HTTP_X_FORWARDED_FOR'],
87 "log_ua" => $_SERVER['HTTP_USER_AGENT'],
88 "log_timestamp" => $now
89 ));
90
91 # Record vote in non-duplicating vote table
92 $sql = "REPLACE INTO $db.vote (vote_key,vote_record) " .
93 "VALUES ('". wfStrencode( $this->mUserKey ) . "','" . wfStrencode( $record ) . "')";
94 wfQuery( $sql, DB_WRITE );
95
96 $wgOut->addWikiText( wfMsg( "boardvote_entered", $record ) );
97 }
98
99 function displayVote() {
100 global $wgContributingCandidates, $wgVolunteerCandidates, $wgOut;
101
102 $thisTitle = Title::makeTitle( NS_SPECIAL, "Boardvote" );
103 $action = $thisTitle->getLocalURL( "action=vote" );
104 if ( $this->mHasVoted ) {
105 $intro = wfMsg( "boardvote_intro_change" );
106 } else {
107 $intro = wfMsg( "boardvote_intro" );
108 }
109 $contributing = wfMsg( "boardvote_contributing" );
110 $volunteer = wfMsg( "boardvote_volunteer" );
111 $ok = wfMsg( "ok" );
112
113 $candidatesV = $candidatesC = array();
114 foreach( $wgContributingCandidates as $i => $candidate ) {
115 $candidatesC[] = array( $i, $candidate );
116 }
117 foreach ( $wgVolunteerCandidates as $i => $candidate ) {
118 $candidatesV[] = array( $i, $candidate );
119 }
120
121 srand ((float)microtime()*1000000);
122 shuffle( $candidatesC );
123 shuffle( $candidatesV );
124
125 $text = "
126 $intro
127 <form name=\"boardvote\" id=\"boardvote\" method=\"post\" action=\"$action\">
128 <table border='0'><tr><td colspan=2>
129 <h2>$contributing</h2>
130 </td></tr>";
131 $text .= $this->voteEntry( -1, wfMsg( "boardvote_abstain" ), "contributing" );
132 foreach ( $candidatesC as $candidate ) {
133 $text .= $this->voteEntry( $candidate[0], $candidate[1], "contributing" );
134 }
135 $text .= "
136 <tr><td colspan=2>
137 <h2>$volunteer</h2></td></tr>";
138 $text .= $this->voteEntry( -1, wfMsg( "boardvote_abstain" ), "volunteer" );
139 foreach ( $candidatesV as $candidate ) {
140 $text .= $this->voteEntry( $candidate[0], $candidate[1], "volunteer" );
141 }
142
143 $text .= "<tr><td>&nbsp;</td><td>
144 <input name=\"submit\" type=\"submit\" value=\"$ok\">
145 </td></tr></table></form>";
146 $text .= wfMsg( "boardvote_footer" );
147 $wgOut->addHTML( $text );
148 }
149
150 function voteEntry( $index, $candidate, $name ) {
151 if ( $index == -1 ) {
152 $checked = " CHECKED";
153 } else {
154 $checked = "";
155 }
156
157 return "
158 <tr><td align=\"right\">
159 <input type=\"radio\" name=\"$name\" value=\"$index\"$checked>
160 </td><td align=\"left\">
161 $candidate
162 </td></tr>";
163 }
164
165 function notLoggedIn() {
166 global $wgOut;
167 $wgOut->addWikiText( wfMsg( "boardvote_notloggedin" ) );
168 }
169
170 function notQualified() {
171 global $wgOut;
172 $wgOut->addWikiText( wfMsg( "boardvote_notqualified", $this->mUserDays ) );
173 }
174
175 function encrypt( $contributing, $volunteer ) {
176 global $wgVolunteerCandidates, $wgContributingCandidates;
177 global $wgGPGCommand, $wgGPGRecipient, $wgGPGHomedir;
178 $file = @fopen( "/dev/urandom", "r" );
179 if ( $file ) {
180 $salt = implode( "", unpack( "H*", fread( $file, 64 ) ));
181 fclose( $file );
182 } else {
183 $salt = Parser::getRandomString() . Parser::getRandomString();
184 }
185 $record =
186 "Contributing: $contributing (" .$wgContributingCandidates[$contributing] . ")\n" .
187 "Volunteer: $volunteer (" . $wgVolunteerCandidates[$volunteer] . ")\n" .
188 "Salt: $salt\n";
189 # Get file names
190 $input = tempnam( "/tmp", "gpg_" );
191 $output = tempnam( "/tmp", "gpg_" );
192
193 # Write unencrypted record
194 $file = fopen( $input, "w" );
195 fwrite( $file, $record );
196 fclose( $file );
197
198 # Call GPG
199 $command = wfEscapeShellArg( $wgGPGCommand ) . " --batch --yes -ear " .
200 wfEscapeShellArg( $wgGPGRecipient ) . " -o " . wfEscapeShellArg( $output );
201 if ( $wgGPGHomedir ) {
202 $command .= " --homedir " . wfEscapeShellArg( $wgGPGHomedir );
203 }
204 $command .= " " . wfEscapeShellArg( $input );
205
206 shell_exec( $command );
207
208 # Read result
209 $result = file_get_contents( $output );
210
211 # Delete temporary files
212 unlink( $input );
213 unlink( $output );
214
215 return $result;
216 }
217
218 function getQualifications( &$user ) {
219 $id = $user->getID();
220 if ( !$id ) {
221 $this->mUserDays = 0;
222 $this->mUserEdits = 0;
223 return;
224 }
225
226 # Count contributions and find earliest edit
227 # First cur
228 $sql = "SELECT COUNT(*) as n, MIN(cur_timestamp) as t FROM cur WHERE cur_user=$id";
229 $res = wfQuery( $sql, DB_READ, "BoardVoteForm::getQualifications" );
230 $cur = wfFetchObject( $res );
231 wfFreeResult( $res );
232
233 # If the user has stacks of contributions, don't check old as well
234 $now = time();
235 if ( is_null( $cur->t ) ) {
236 $signup = $now;
237 } else {
238 $signup = wfTimestamp2Unix( $cur->t );
239 }
240
241 $days = ($now - $signup) / 86400;
242 if ( $cur->n > 400 && $days > 180 ) {
243 $this->mUserDays = 0x7fffffff;
244 $this->mUserEdits = 0x7fffffff;
245 return;
246 }
247
248 # Now check old
249 $sql = "SELECT COUNT(*) as n, MIN(old_timestamp) as t FROM old WHERE old_user=$id";
250 $res = wfQuery( $sql, DB_READ, "BoardVoteForm::getQualifications" );
251 $old = wfFetchObject( $res );
252 wfFreeResult( $res );
253
254 if ( !is_null( $old->t ) ) {
255 $signup = min( wfTimestamp2Unix( $old->t ), $signup );
256 }
257 $this->mUserDays = (int)(($now - $signup) / 86400);
258 $this->mUserEdits = $cur->n + $old->n;
259 }
260
261 function displayList() {
262 global $wgOut, $wgOutputEncoding, $wgLang, $wgUser;
263 $sql = "SELECT log_timestamp,log_user_key FROM {$this->mDBname}.log";
264 $res = wfQuery( $sql, DB_READ, "BoardVoteForm::list" );
265 if ( wfNumRows( $res ) == 0 ) {
266 $wgOut->addWikiText( wfMsg( "boardvote_novotes" ) );
267 return;
268 }
269 $thisTitle = Title::makeTitle( NS_SPECIAL, "Boardvote" );
270 $sk = $wgUser->getSkin();
271 $dumpLink = $sk->makeKnownLinkObj( $thisTitle, wfMsg( "boardvote_dumplink" ), "action=dump" );
272
273 $intro = wfMsg( "boardvote_listintro", $dumpLink );
274 $hTime = wfMsg( "boardvote_time" );
275 $hUser = wfMsg( "boardvote_user" );
276 $hContributing = wfMsg( "boardvote_contributing" );
277 $hVolunteer = wfMsg( "boardvote_volunteer" );
278
279 $s = "$intro <table border=0><tr><th>
280 $hTime
281 </th><th>
282 $hUser
283 </th></tr>";
284
285 while ( $row = wfFetchObject( $res ) ) {
286 if ( $wgOutputEncoding != "utf-8" ) {
287 $user = wfUtf8ToHTML( $row->log_user_key );
288 } else {
289 $user = $row->log_user_key;
290 }
291 $time = $wgLang->timeanddate( $row->log_timestamp );
292 $s .= "<tr><td>
293 $time
294 </td><td>
295 $user
296 </td></tr>";
297 }
298 $s .= "</table>";
299 $wgOut->addHTML( $s );
300 }
301
302 function dump() {
303 global $wgOut, $wgOutputEncoding, $wgLang, $wgUser;
304
305 $userRights = $wgUser->getRights();
306 if ( in_array( "boardvote", $userRights ) ) {
307 $admin = true;
308 } else {
309 $admin = false;
310 }
311
312 $sql = "SELECT * FROM {$this->mDBname}.log";
313 $res = wfQuery( $sql, DB_READ, "BoardVoteForm::list" );
314 if ( wfNumRows( $res ) == 0 ) {
315 $wgOut->addWikiText( wfMsg( "boardvote_novotes" ) );
316 return;
317 }
318 $s = "<table border=1>";
319 if ( $admin ) {
320 $s .= wfMsg( "boardvote_dumpheader" );
321 }
322
323 while ( $row = wfFetchObject( $res ) ) {
324 if ( $wgOutputEncoding != "utf-8" ) {
325 $user = wfUtf8ToHTML( $row->log_user_key );
326 } else {
327 $user = $row->log_user_key;
328 }
329 $time = $wgLang->timeanddate( $row->log_timestamp );
330 $record = nl2br( $row->log_record );
331 if ( $admin ) {
332 $edits = $row->log_edits == 0x7fffffff ? "many" : $row->log_edits;
333 $days = $row->log_days == 0x7fffffff ? "many" : $row->log_days;
334 $s .= "<tr><td>
335 $time
336 </td><td>
337 $user
338 </td><td>
339 $edits
340 </td><td>
341 $days
342 </td><td>
343 {$row->log_ip}
344 </td><td>
345 {$row->log_ua}
346 </td><td>
347 $record
348 </td></tr>";
349 } else {
350 $s .= "<tr><td>$time</td><td>$user</td><td>$record</td></tr>";
351 }
352 }
353 $s .= "</table>";
354 $wgOut->addHTML( $s );
355 }
356 }
357 ?>