acctfuncs.inc.php 25 KB
Newer Older
1
<?php
2

Dan McGee's avatar
Dan McGee committed
3
4
5
6
7
8
9
10
# Helper function- retrieve request param if available, "" otherwise
function in_request($name) {
	if (isset($_REQUEST[$name])) {
		return $_REQUEST[$name];
	}
	return "";
}

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# Format PGP key fingerprint
function html_format_pgp_fingerprint($fingerprint) {
	if (strlen($fingerprint) != 40 || !ctype_xdigit($fingerprint)) {
		return $fingerprint;
	}

	return htmlspecialchars(substr($fingerprint, 0, 4) . " " .
		substr($fingerprint, 4, 4) . " " .
		substr($fingerprint, 8, 4) . " " .
		substr($fingerprint, 12, 4) . " " .
		substr($fingerprint, 16, 4) . "  " .
		substr($fingerprint, 20, 4) . " " .
		substr($fingerprint, 24, 4) . " " .
		substr($fingerprint, 28, 4) . " " .
		substr($fingerprint, 32, 4) . " " .
		substr($fingerprint, 36, 4) . " ", ENT_QUOTES);
}

29
# Display the standard Account form, pass in default values if any
30

eric's avatar
eric committed
31
function display_account_form($UTYPE,$A,$U="",$T="",$S="",
32
			$E="",$P="",$C="",$R="",$L="",$I="",$K="",$UID=0) {
eric's avatar
eric committed
33
	# UTYPE: what user type the form is being displayed for
34
35
36
37
38
39
40
41
42
43
44
	# A: what "form" name to use
	# U: value to display for username
	# T: value to display for account type
	# S: value to display for account suspended
	# E: value to display for email address
	# P: password value
	# C: confirm password value
	# R: value to display for RealName
	# L: value to display for Language preference
	# I: value to display for IRC nick
	# N: new package notify value
eric's avatar
eric committed
45
	# UID: Users.ID value in case form is used for editing
46
47
48

	global $SUPPORTED_LANGS;

49
	print "<form action='account.php' method='post'>\n";
Lukas Fleischer's avatar
Lukas Fleischer committed
50
51
	print "<fieldset>";
	print "<input type='hidden' name='Action' value='".$A."' />\n";
eric's avatar
eric committed
52
	if ($UID) {
Lukas Fleischer's avatar
Lukas Fleischer committed
53
		print "<input type='hidden' name='ID' value='".$UID."' />\n";
eric's avatar
eric committed
54
	}
Lukas Fleischer's avatar
Lukas Fleischer committed
55
	print "</fieldset>";
56
	print "<table>\n";
57
58
59
60
61
	print "<tr><td colspan='2'>&nbsp;</td></tr>\n";

	print "<tr>";
	print "<td align='left'>".__("Username").":</td>";
	print "<td align='left'><input type='text' size='30' maxlength='64'";
Lukas Fleischer's avatar
Lukas Fleischer committed
62
	print " name='U' value='".htmlspecialchars($U,ENT_QUOTES)."' /> (".__("required").")</td>";
63
64
	print "</tr>\n";

65
	# Only TUs or Devs can promote/demote/suspend a user
eric's avatar
eric committed
66
	if ($UTYPE == "Trusted User" || $UTYPE == "Developer") {
67
68
69
		print "<tr>";
		print "<td align='left'>".__("Account Type").":</td>";
		print "<td align='left'><select name=T>\n";
eric's avatar
eric committed
70
71
		print "<option value='1'";
		$T == "User" ? print " selected>" : print ">";
72
		print __("Normal user")."\n";
eric's avatar
eric committed
73
74
75
		print "<option value='2'";
		$T == "Trusted User" ? print " selected>" : print ">";
		print __("Trusted user")."\n";
76
77

		# Only developers can make another account a developer
eric's avatar
eric committed
78
79
80
81
		if ($UTYPE == "Developer") {
			print "<option value='3'";
			$T == "Developer" ? print " selected>" : print ">";
			print __("Developer")."\n";
82
83
84
85
86
87
88
89
		}
		print "</select></td>";
		print "</tr>\n";

		print "<tr>";
		print "<td align='left'>".__("Account Suspended").":</td>";
		print "<td align='left'><input type='checkbox' name='S'";
		if ($S) {
Lukas Fleischer's avatar
Lukas Fleischer committed
90
			print " checked=\"checked\" />";
91
		} else {
Lukas Fleischer's avatar
Lukas Fleischer committed
92
			print " />";
93
94
95
96
97
98
99
		}
		print "</tr>\n";
	}

	print "<tr>";
	print "<td align='left'>".__("Email Address").":</td>";
	print "<td align='left'><input type='text' size='30' maxlength='64'";
Lukas Fleischer's avatar
Lukas Fleischer committed
100
	print " name='E' value='".htmlspecialchars($E,ENT_QUOTES)."' /> (".__("required").")</td>";
101
102
103
104
105
	print "</tr>\n";

	print "<tr>";
	print "<td align='left'>".__("Password").":</td>";
	print "<td align='left'><input type='password' size='30' maxlength='32'";
Lukas Fleischer's avatar
Lukas Fleischer committed
106
	print " name='P' value='".$P."' />";
107
	if ($A != "UpdateAccount") {
108
		print " (".__("required").")";
eric's avatar
eric committed
109
110
	}
	print "</td></tr>\n";
111
112
113
114

	print "<tr>";
	print "<td align='left'>".__("Re-type password").":</td>";
	print "<td align='left'><input type='password' size='30' maxlength='32'";
Lukas Fleischer's avatar
Lukas Fleischer committed
115
	print " name='C' value='".$C."' />";
116
	if ($A != "UpdateAccount") {
117
		print " (".__("required").")";
eric's avatar
eric committed
118
119
	}
	print "</td></tr>\n";
120
121
122
123

	print "<tr>";
	print "<td align='left'>".__("Real Name").":</td>";
	print "<td align='left'><input type='text' size='30' maxlength='32'";
Lukas Fleischer's avatar
Lukas Fleischer committed
124
	print " name='R' value='".htmlspecialchars($R,ENT_QUOTES)."' /></td>";
125
126
127
128
129
	print "</tr>\n";

	print "<tr>";
	print "<td align='left'>".__("IRC Nick").":</td>";
	print "<td align='left'><input type='text' size='30' maxlength='32'";
Lukas Fleischer's avatar
Lukas Fleischer committed
130
	print " name='I' value='".htmlspecialchars($I,ENT_QUOTES)."' /></td>";
131
132
	print "</tr>\n";

133
134
135
136
137
138
	print "<tr>";
	print "<td align='left'>".__("PGP Key Fingerprint").":</td>";
	print "<td align='left'><input type='text' size='30' maxlength='50'";
	print " name='K' value='".html_format_pgp_fingerprint($K)."' /></td>";
	print "</tr>\n";

139
140
141
	print "<tr>";
	print "<td align='left'>".__("Language").":</td>";
	print "<td align='left'><select name=L>\n";
142
143

	reset($SUPPORTED_LANGS);
144
145
146
147
148
149
150
151
152
153
154
155
156
157
	while (list($code, $lang) = each($SUPPORTED_LANGS)) {
		if ($L == $code) {
			print "<option value=".$code." selected> ".$lang."\n";
		} else {
			print "<option value=".$code."> ".$lang."\n";
		}
	}
	print "</select></td>";
	print "</tr>\n";

	print "<tr><td colspan='2'>&nbsp;</td></tr>\n";
	print "<tr>";
	print "<td>&nbsp;</td>";
	print "<td align='left'>";
158

eric's avatar
eric committed
159
	if ($A == "UpdateAccount") {
eric's avatar
eric committed
160
		print "<input type='submit' class='button'";
Lukas Fleischer's avatar
Lukas Fleischer committed
161
		print " value='".__("Update")."' /> &nbsp; ";
162
	} else {
eric's avatar
eric committed
163
		print "<input type='submit' class='button'";
Lukas Fleischer's avatar
Lukas Fleischer committed
164
		print " value='".__("Create")."' /> &nbsp; ";
165
	}
Lukas Fleischer's avatar
Lukas Fleischer committed
166
	print "<input type='reset' class='button' value='".__("Reset")."' />";
167
168
169
170
171
172
173
174
175
176
177
	print "</td>";
	print "</tr>\n";

	print "</table>\n";
	print "</form>\n";
	return;
} # function display_account_form()


# process form input from a new/edit account form
#
eric's avatar
eric committed
178
function process_account_form($UTYPE,$TYPE,$A,$U="",$T="",$S="",$E="",
179
			$P="",$C="",$R="",$L="",$I="",$K="",$UID=0) {
eric's avatar
eric committed
180
	# UTYPE: The user's account type
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
	# TYPE: either "edit" or "new"
	# A: what parent "form" name to use
	# U: value to display for username
	# T: value to display for account type
	# S: value to display for account suspended
	# E: value to display for email address
	# P: password value
	# C: confirm password value
	# R: value to display for RealName
	# L: value to display for Language preference
	# I: value to display for IRC nick
	# N: new package notify value
	# UID: database Users.ID value

	# error check and process request for a new/modified account
	global $SUPPORTED_LANGS;

198
199
	$dbh = db_connect();

200
	if(isset($_COOKIE['AURSID'])) {
201
		$editor_user = uid_from_sid($_COOKIE['AURSID'], $dbh);
202
203
	}
	else {
204
		$editor_user = null;
205
	}
206

207
	$error = "";
208
	if (empty($E) || empty($U)) {
209
210
		$error = __("Missing a required field.");
	}
211

212
213
214
	if ($TYPE == "new") {
		# they need password fields for this type of action
		#
215
		if (empty($P) || empty($C)) {
216
217
218
219
220
221
222
			$error = __("Missing a required field.");
		}
	} else {
		if (!$UID) {
			$error = __("Missing User ID");
		}
	}
223

224
  if (!$error && !valid_username($U) && !user_is_privileged($editor_user, $dbh))
225
	$error = __("The username is invalid.") . "<ul>\n"
226
			."<li>" . __("It must be between %s and %s characters long",
227
228
			USERNAME_MIN_LEN,  USERNAME_MAX_LEN )
			. "</li>"
229
			. "<li>" . __("Start and end with a letter or number") . "</li>"
230
			. "<li>" . __("Can contain only one period, underscore or hyphen.")
231
232
			. "</li>\n</ul>";

233
234
235
	if (!$error && $P && $C && ($P != $C)) {
		$error = __("Password fields do not match.");
	}
236
	if (!$error && $P != '' && !good_passwd($P))
237
		$error = __("Your password must be at least %s characters.",PASSWD_MIN_LEN);
238

239
240
241
	if (!$error && !valid_email($E)) {
		$error = __("The email address is invalid.");
	}
242
243
244
245
246

	if (!$error && $K != '' && !valid_pgp_fingerprint($K)) {
		$error = __("The PGP key fingerprint is invalid.");
	}

eric's avatar
eric committed
247
248
249
	if ($UTYPE == "Trusted User" && $T == 3) {
		$error = __("A Trusted User cannot assign Developer status.");
	}
250
251
252
253
254
255
256
257
	if (!$error && !array_key_exists($L, $SUPPORTED_LANGS)) {
		$error = __("Language is not currently supported.");
	}
	if (!$error) {
		# check to see if this username is available
		# NOTE: a race condition exists here if we care...
		#
		$q = "SELECT COUNT(*) AS CNT FROM Users ";
258
		$q.= "WHERE Username = '".db_escape_string($U)."'";
eric's avatar
eric committed
259
260
261
		if ($TYPE == "edit") {
			$q.= " AND ID != ".intval($UID);
		}
262
263
264
265
		$result = db_query($q, $dbh);
		if ($result) {
			$row = mysql_fetch_array($result);
			if ($row[0]) {
266
				$error = __("The username, %s%s%s, is already in use.",
Viktor Leonhardt's avatar
Viktor Leonhardt committed
267
					"<b>", htmlspecialchars($U,ENT_QUOTES), "</b>");
268
269
270
271
272
273
274
275
			}
		}
	}
	if (!$error) {
		# check to see if this email address is available
		# NOTE: a race condition exists here if we care...
		#
		$q = "SELECT COUNT(*) AS CNT FROM Users ";
276
		$q.= "WHERE Email = '".db_escape_string($E)."'";
eric's avatar
eric committed
277
278
279
		if ($TYPE == "edit") {
			$q.= " AND ID != ".intval($UID);
		}
280
281
282
283
		$result = db_query($q, $dbh);
		if ($result) {
			$row = mysql_fetch_array($result);
			if ($row[0]) {
284
				$error = __("The address, %s%s%s, is already in use.",
Viktor Leonhardt's avatar
Viktor Leonhardt committed
285
						"<b>", htmlspecialchars($E,ENT_QUOTES), "</b>");
286
287
288
289
290
			}
		}
	}
	if ($error) {
		print "<span class='error'>".$error."</span><br/>\n";
eric's avatar
eric committed
291
		display_account_form($UTYPE, $A, $U, $T, $S, $E, "", "",
292
				$R, $L, $I, $K, $UID);
293
294
295
	} else {
		if ($TYPE == "new") {
			# no errors, go ahead and create the unprivileged user
Denis's avatar
Denis committed
296
297
			$salt = generate_salt();
			$P = salted_hash($P, $salt);
298
			$escaped = array_map('db_escape_string',
299
				array($U, $E, $P, $salt, $R, $L, $I, str_replace(" ", "", $K)));
Denis's avatar
Denis committed
300
301
			$q = "INSERT INTO Users (" .
				"AccountTypeID, Suspended, Username, Email, Passwd, Salt" .
302
				", RealName, LangPreference, IRCNick, PGPKey) " .
303
				"VALUES (1, 0, '" . implode("', '", $escaped) . "')";
304
305
			$result = db_query($q, $dbh);
			if (!$result) {
306
				print __("Error trying to create account, %s%s%s: %s.",
Viktor Leonhardt's avatar
Viktor Leonhardt committed
307
						"<b>", htmlspecialchars($U,ENT_QUOTES), "</b>", mysql_error($dbh));
308
			} else {
309
310
				# account created/modified, tell them so.
				#
311
				print __("The account, %s%s%s, has been successfully created.",
Viktor Leonhardt's avatar
Viktor Leonhardt committed
312
						"<b>", htmlspecialchars($U,ENT_QUOTES), "</b>");
313
314
315
316
317
318
319
				print "<p>\n";
				print __("Click on the Home link above to login.");
				print "</p>\n";
			}

		} else {
			# no errors, go ahead and modify the user account
jchu's avatar
jchu committed
320

321
			$q = "UPDATE Users SET ";
322
			$q.= "Username = '".db_escape_string($U)."'";
eric's avatar
eric committed
323
324
325
326
327
328
329
330
			if ($T) {
				$q.= ", AccountTypeID = ".intval($T);
			}
			if ($S) {
				$q.= ", Suspended = 1";
			} else {
				$q.= ", Suspended = 0";
			}
331
			$q.= ", Email = '".db_escape_string($E)."'";
eric's avatar
eric committed
332
			if ($P) {
Denis's avatar
Denis committed
333
334
335
				$salt = generate_salt();
				$hash = salted_hash($P, $salt);
				$q .= ", Passwd = '$hash', Salt = '$salt'";
eric's avatar
eric committed
336
			}
337
338
339
			$q.= ", RealName = '".db_escape_string($R)."'";
			$q.= ", LangPreference = '".db_escape_string($L)."'";
			$q.= ", IRCNick = '".db_escape_string($I)."'";
340
			$q.= ", PGPKey = '".db_escape_string(str_replace(" ", "", $K))."'";
341
			$q.= " WHERE ID = ".intval($UID);
342
343
			$result = db_query($q, $dbh);
			if (!$result) {
344
				print __("Error trying to modify account, %s%s%s: %s.",
Viktor Leonhardt's avatar
Viktor Leonhardt committed
345
						"<b>", htmlspecialchars($U,ENT_QUOTES), "</b>", mysql_error($dbh));
346
			} else {
347
				print __("The account, %s%s%s, has been successfully modified.",
Viktor Leonhardt's avatar
Viktor Leonhardt committed
348
						"<b>", htmlspecialchars($U,ENT_QUOTES), "</b>");
349
350
351
352
353
354
355
356
357
			}
		}
	}
	return;
}

# search existing accounts
#
function search_accounts_form() {
358
	include("search_accounts_form.php");
359
360
361
362
363
364
	return;
}


# search results page
#
eric's avatar
eric committed
365
function search_results_page($UTYPE,$O=0,$SB="",$U="",$T="",
366
		$S="",$E="",$R="",$I="",$K="") {
eric's avatar
eric committed
367
	# UTYPE: what account type the user belongs to
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
	# O: what row offset we're at
	# SB: how to sort the results
	# U: value to display for username
	# T: value to display for account type
	# S: value to display for account suspended
	# E: value to display for email address
	# R: value to display for RealName
	# I: value to display for IRC nick

	$HITS_PER_PAGE = 50;
	if ($O) {
		$OFFSET = intval($O);
	} else {
		$OFFSET = 0;
	}
	if ($OFFSET < 0) {
		$OFFSET = 0;
	}
	$search_vars = array();

	$q = "SELECT Users.*, AccountTypes.AccountType ";
	$q.= "FROM Users, AccountTypes ";
	$q.= "WHERE AccountTypes.ID = Users.AccountTypeID ";
	if ($T == "u") {
		$q.= "AND AccountTypes.ID = 1 ";
		$search_vars[] = "T";
	} elseif ($T == "t") {
		$q.= "AND AccountTypes.ID = 2 ";
		$search_vars[] = "T";
	} elseif ($T == "d") {
		$q.= "AND AccountTypes.ID = 3 ";
		$search_vars[] = "T";
	}
	if ($S) {
		$q.= "AND Users.Suspended = 1 ";
		$search_vars[] = "S";
	}
	if ($U) {
406
		$q.= "AND Username LIKE '%".db_escape_like($U)."%' ";
407
408
409
		$search_vars[] = "U";
	}
	if ($E) {
410
		$q.= "AND Email LIKE '%".db_escape_like($E)."%' ";
411
412
413
		$search_vars[] = "E";
	}
	if ($R) {
414
		$q.= "AND RealName LIKE '%".db_escape_like($R)."%' ";
415
416
417
		$search_vars[] = "R";
	}
	if ($I) {
418
		$q.= "AND IRCNick LIKE '%".db_escape_like($I)."%' ";
419
420
		$search_vars[] = "I";
	}
421
422
423
424
	if ($K) {
		$q.= "AND PGPKey LIKE '%".db_escape_like(str_replace(" ", "", $K))."%' ";
		$search_vars[] = "K";
	}
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
	switch ($SB) {
		case 't':
			$q.= "ORDER BY AccountTypeID, Username ";
			break;
		case 'r':
			$q.= "ORDER BY RealName, AccountTypeID ";
			break;
		case 'i':
			$q.= "ORDER BY IRCNick, AccountTypeID ";
			break;
		case 'v':
			$q.= "ORDER BY LastVoted, Username ";
			break;
		default:
			$q.= "ORDER BY Username, AccountTypeID ";
			break;
	}
	$search_vars[] = "SB";
443
	$q.= "LIMIT " . $HITS_PER_PAGE . " OFFSET " . $OFFSET;
444

445
446
	$dbh = db_connect();

447
448
449
450
451
452
	$result = db_query($q, $dbh);
	if (!$result) {
		print __("No results matched your search criteria.");
	} else {
		$num_rows = mysql_num_rows($result);
		if ($num_rows) {
453
			print "<table class='results'>\n";
Lukas Fleischer's avatar
Lukas Fleischer committed
454
			print "<tr>";
455
456
457
458
459
460
461
462
463
464
465
			print "<th class='header'>";
			print "<span class='f2'>".__("Username")."</span></th>";
			print "<th class='header'>";
			print "<span class='f2'>".__("Type")."</span></th>";
			print "<th class='header'>";
			print "<span class='f2'>".__("Status")."</span></th>";
			print "<th class='header'>";
			print "<span class='f2'>".__("Real Name")."</span></th>";
			print "<th class='header'>";
			print "<span class='f2'>".__("IRC Nick")."</span></th>";
			print "<th class='header'>";
466
467
			print "<span class='f2'>".__("PGP Key Fingerprint")."</span></th>";
			print "<th class='header'>";
468
469
470
471
472
473
474
475
476
477
478
479
480
			print "<span class='f2'>".__("Last Voted")."</span></th>";
			print "<th class='header'>";
			print "<span class='f2'>".__("Edit Account")."</span></th>";
			print "</tr>\n";
			$i = 0;
			while ($row = mysql_fetch_assoc($result)) {
				if ($i % 2) {
					$c = "data1";
				} else {
					$c = "data2";
				}
				print "<tr>";
				print "<td class='".$c."'>";
Lukas Fleischer's avatar
Lukas Fleischer committed
481
				print "<span class='f5'><a href='packages.php?SeB=m&amp;K=".$row["Username"]."'>".$row["Username"]."</a></span></td>";
482
483
484
485
486
487
488
489
490
491
492
				print "<td class='".$c."'>";
				print "<span class='f5'>".$row["AccountType"];
				print "</span></td>";
				print "<td class='".$c."'><span class='f5'>";
				if ($row["Suspended"]) {
					print __("Suspended");
				} else {
					print __("Active");
				}
				print "</span></td>";
				print "<td class='".$c."'><span class='f5'>";
Viktor Leonhardt's avatar
Viktor Leonhardt committed
493
				$row["RealName"] ? print htmlspecialchars($row["RealName"],ENT_QUOTES) : print "&nbsp;";
494
495
				print "</span></td>";
				print "<td class='".$c."'><span class='f5'>";
Viktor Leonhardt's avatar
Viktor Leonhardt committed
496
				$row["IRCNick"] ? print htmlspecialchars($row["IRCNick"],ENT_QUOTES) : print "&nbsp;";
497
498
				print "</span></td>";
				print "<td class='".$c."'><span class='f5'>";
499
500
501
				$row["PGPKey"] ? print html_format_pgp_fingerprint($row["PGPKey"]) : print "&nbsp;";
				print "</span></td>";
				print "<td class='".$c."'><span class='f5'>";
502
				$row["LastVoted"]
503
						? print date("Y-m-d", $row["LastVoted"])
504
505
506
						: print __("Never");
				print "</span></td>";
				print "<td class='".$c."'><span class='f5'>";
eric's avatar
eric committed
507
508
509
510
511
				if ($UTYPE == "Trusted User" && $row["AccountType"] == "Developer") {
					# TUs can't edit devs
					#
					print "&nbsp;</span></td>";
				} else {
Lukas Fleischer's avatar
Lukas Fleischer committed
512
					$edit_url = "account.php?Action=DisplayAccount&amp;ID=".$row["ID"];
eric's avatar
eric committed
513
514
515
					print "<a href='".$edit_url . "'>";
					print "Edit</a></span></td>";
				}
516
517
518
519
520
				print "</tr>\n";
				$i++;
			}
			print "</table>\n";

521
			print "<table class='results'>\n";
522
523
			print "<tr>";
			print "<td align='left'>";
524
			print "<form action='account.php' method='post'>\n";
Lukas Fleischer's avatar
Lukas Fleischer committed
525
526
			print "<fieldset>";
			print "<input type='hidden' name='Action' value='SearchAccounts' />\n";
527
			print "<input type='hidden' name='O'";
Lukas Fleischer's avatar
Lukas Fleischer committed
528
			print " value='".($OFFSET-$HITS_PER_PAGE)."' />\n";
529
530
531
			reset($search_vars);
			while (list($k, $ind) = each($search_vars)) {
				print "<input type='hidden' name='".$ind."'";
Lukas Fleischer's avatar
Lukas Fleischer committed
532
				print " value='".${$ind}."' />\n";
533
			}
eric's avatar
eric committed
534
			print "<input type='submit' class='button'";
Lukas Fleischer's avatar
Lukas Fleischer committed
535
536
			print " value='&lt;-- ".__("Less")."' />";
			print "</fieldset>";
537
538
539
			print "</form>\n";
			print "</td>";
			print "<td align='right'>";
540
			print "<form action='account.php' method='post'>\n";
Lukas Fleischer's avatar
Lukas Fleischer committed
541
542
			print "<fieldset>";
			print "<input type='hidden' name='Action' value='SearchAccounts' />\n";
543
			print "<input type='hidden' name='O'";
Lukas Fleischer's avatar
Lukas Fleischer committed
544
			print " value='".($OFFSET+$HITS_PER_PAGE)."' />\n";
545
546
547
			reset($search_vars);
			while (list($k, $ind) = each($search_vars)) {
				print "<input type='hidden' name='".$ind."'";
Lukas Fleischer's avatar
Lukas Fleischer committed
548
				print " value='".${$ind}."' />\n";
549
			}
eric's avatar
eric committed
550
			print "<input type='submit' class='button'";
Lukas Fleischer's avatar
Lukas Fleischer committed
551
552
			print " value='".__("More")." --&gt;' />";
			print "</fieldset>";
553
554
555
556
557
			print "</form>\n";
			print "</td>";
			print "</tr>\n";
			print "</table>\n";
		} else {
Lukas Fleischer's avatar
Lukas Fleischer committed
558
			print "<p style=\"text-align:center;\">\n";
559
			print __("No more results to display.");
Lukas Fleischer's avatar
Lukas Fleischer committed
560
			print "</p>\n";
561
562
563
564
565
		}
	}
	return;
}

566
567
# Display non-editable account info
#
568
function display_account_info($U="", $T="", $E="", $R="", $I="", $K="", $LV="") {
569
570
571
572
573
	# U: value to display for username
	# T: value to display for account type
	# E: value to display for email address
	# R: value to display for RealName
	# I: value to display for IRC nick
574
	# LV: value to display for last voted
575
576
577

	global $SUPPORTED_LANGS;

578
	print "<table>\n";
579
580
581
582
583
584
585
586
	print "  <tr>\n";
	print "    <td colspan='2'>&nbsp;</td>\n";
	print "  </tr>\n";

	print "  <tr>\n";
	print "    <td align='left'>".__("Username").":</td>\n";
	print "    <td align='left'>".$U."</td>\n";
	print "  </tr>\n";
587

588
589
590
591
592
593
594
	print "  <tr>\n";
	print "    <td align='left'>".__("Account Type").":</td>\n";
	print "    <td align='left'>";
	if ($T == "User") {
		print __("User");
	} elseif ($T == "Trusted User") {
		print __("Trusted User");
595
	} elseif ($T == "Developer") {
596
597
		print __("Developer");
	}
Lukas Fleischer's avatar
Lukas Fleischer committed
598
599
	print "    </td>\n";
	print "  </tr>\n";
600

601
602
	print "  <tr>\n";
	print "    <td align='left'>".__("Email Address").":</td>\n";
Viktor Leonhardt's avatar
Viktor Leonhardt committed
603
	print "    <td align='left'><a href='mailto:".htmlspecialchars($E,ENT_QUOTES)."'>".htmlspecialchars($E,ENT_QUOTES)."</a></td>\n";
604
605
606
607
	print "  </tr>\n";

	print "  <tr>\n";
	print "    <td align='left'>".__("Real Name").":</td>\n";
Viktor Leonhardt's avatar
Viktor Leonhardt committed
608
	print "    <td align='left'>".htmlspecialchars($R,ENT_QUOTES)."</td>\n";
609
610
611
612
	print "  </tr>\n";

	print "  <tr>\n";
	print "    <td align='left'>".__("IRC Nick").":</td>\n";
Viktor Leonhardt's avatar
Viktor Leonhardt committed
613
	print "    <td align='left'>".htmlspecialchars($I,ENT_QUOTES)."</td>\n";
614
615
	print "  </tr>\n";

616
617
618
619
620
	print "  <tr>\n";
	print "    <td align='left'>".__("PGP Key Fingerprint").":</td>\n";
	print "    <td align='left'>".html_format_pgp_fingerprint($K)."</td>\n";
	print "  </tr>\n";

621
622
623
624
625
626
627
	print "  <tr>\n";
	print "    <td align='left'>".__("Last Voted").":</td>\n";
	print "    <td align='left'>";
	print $LV ? date("Y-m-d", $LV) : __("Never");
	print "</td>\n";
	print "  </tr>\n";

628
	print "  <tr>\n";
Lukas Fleischer's avatar
Lukas Fleischer committed
629
	print "    <td colspan='2'><a href='packages.php?K=".$U."&amp;SeB=m'>".__("View this user's packages")."</a></td>\n";
630
631
	print "  </tr>\n";

632
633
634
635
	print "</table>\n";
	return;
}

636
637
638
639
640
/*
 * Returns SID (Session ID) and error (error message) in an array
 * SID of 0 means login failed.
 */
function try_login() {
641
	global $MAX_SESSIONS_PER_USER, $PERSISTENT_COOKIE_TIMEOUT;
642

Loui Chang's avatar
Loui Chang committed
643
	$login_error = "";
644
645
646
647
	$new_sid = "";
	$userID = null;

	if ( isset($_REQUEST['user']) || isset($_REQUEST['passwd']) ) {
648
649
		$dbh = db_connect();
		$userID = valid_user($_REQUEST['user'], $dbh);
650

651
		if ( user_suspended($userID, $dbh) ) {
652
653
654
			$login_error = "Account Suspended.";
		}
		elseif ( $userID && isset($_REQUEST['passwd'])
655
		  && valid_passwd($userID, $_REQUEST['passwd'], $dbh) ) {
656
657
658
659
660
661
662

			$logged_in = 0;
			$num_tries = 0;

			# Account looks good.  Generate a SID and store it.

			while (!$logged_in && $num_tries < 5) {
663
664
665
666
667
				if ($MAX_SESSIONS_PER_USER) {
					# Delete all user sessions except the
					# last ($MAX_SESSIONS_PER_USER - 1).
					$q = "DELETE s.* FROM Sessions s ";
					$q.= "LEFT JOIN (SELECT SessionID FROM Sessions ";
668
					$q.= "WHERE UsersId = " . $userID . " ";
669
670
671
					$q.= "ORDER BY LastUpdateTS DESC ";
					$q.= "LIMIT " . ($MAX_SESSIONS_PER_USER - 1) . ") q ";
					$q.= "ON s.SessionID = q.SessionID ";
672
					$q.= "WHERE s.UsersId = " . $userID . " ";
673
674
675
676
					$q.= "AND q.SessionID IS NULL;";
					db_query($q, $dbh);
				}

677
678
				$new_sid = new_sid();
				$q = "INSERT INTO Sessions (UsersID, SessionID, LastUpdateTS)"
679
				  ." VALUES (" . $userID . ", '" . $new_sid . "', UNIX_TIMESTAMP())";
680
				$result = db_query($q, $dbh);
681

682
683
684
685
686
				# Query will fail if $new_sid is not unique
				if ($result) {
					$logged_in = 1;
					break;
				}
687

688
				$num_tries++;
689
			}
690

691
			if ($logged_in) {
692
693
694
				$q = "UPDATE Users SET LastLogin = UNIX_TIMESTAMP() ";
				$q.= "WHERE ID = '$userID'";
				db_query($q, $dbh);
695

696
				# set our SID cookie
Dan McGee's avatar
Dan McGee committed
697
698
				if (isset($_POST['remember_me']) &&
					$_POST['remember_me'] == "on") {
699
					# Set cookies for 30 days.
700
					$cookie_time = time() + $PERSISTENT_COOKIE_TIMEOUT;
701
702
703
704
705
706

					# Set session for 30 days.
					$q = "UPDATE Sessions SET LastUpdateTS = $cookie_time ";
					$q.= "WHERE SessionID = '$new_sid'";
					db_query($q, $dbh);
				}
707
708
				else
					$cookie_time = 0;
709

710
				setcookie("AURSID", $new_sid, $cookie_time, "/", null, !empty($_SERVER['HTTPS']), true);
711
				header("Location: " . $_SERVER['PHP_SELF'].'?'.$_SERVER['QUERY_STRING']);
712
713
714
715
716
717
718
719
				$login_error = "";

			}
			else {
				$login_error = "Error trying to generate session id.";
			}
		}
		else {
720
			$login_error = __("Bad username or password.");
721
722
723
724
725
726
727
728
729
730
731
732
733
734
		}
	}
	return array('SID' => $new_sid, 'error' => $login_error);
}

/*
 * Only checks if the name itself is valid
 * Longer or equal to USERNAME_MIN_LEN
 * Shorter or equal to USERNAME_MAX_LEN
 * Starts and ends with a letter or number
 * Contains at most ONE dot, hyphen, or underscore
 * Returns the username if it is valid
 * Returns nothing if it isn't valid
 */
735
function valid_username($user) {
736
	if (!empty($user)) {
737

738
739
740
		#Is username at not too short or too long?
		if ( strlen($user) >= USERNAME_MIN_LEN &&
		  strlen($user) <= USERNAME_MAX_LEN ) {
741

742
			$user = strtolower($user);
743
			# Does username:
744
745
746
747
748
749
750
751
752
			# start and end with a letter or number
			# contain only letters and numbers,
			#  and at most has one dash, period, or underscore
			if ( preg_match("/^[a-z0-9]+[.\-_]?[a-z0-9]+$/", $user) ) {
				#All is good return the username
				return $user;
			}
		}
	}
753

754
755
756
757
758
759
760
	return;
}

/*
 * Checks if the username is valid and if it exists in the database
 * Returns the username ID or nothing
 */
761
function valid_user($user, $dbh) {
762
763
764
	/*	if ( $user = valid_username($user) ) { */
	if ( $user ) {
		$q = "SELECT ID FROM Users WHERE Username = '"
765
			. db_escape_string($user). "'";
766

767
		$result = db_query($q, $dbh);
768
		# Is the username in the database?
769
770
771
		if ($result) {
			$row = mysql_fetch_row($result);
			return $row[0];
772
773
774
775
776
		}
	}
	return;
}

777
function good_passwd($passwd) {
778
779
780
781
782
783
784
785
786
	if ( strlen($passwd) >= PASSWD_MIN_LEN ) {
		return true;
	}
	return false;
}

/* Verifies that the password is correct for the userID specified.
 * Returns true or false
 */
787
function valid_passwd($userID, $passwd, $dbh) {
788
	if ( strlen($passwd) > 0 ) {
Denis's avatar
Denis committed
789
790
791
792
793
		# get salt for this user
		$salt = get_salt($userID);
		if ($salt) {
			# use salt
			$passwd_q = "SELECT ID FROM Users" .
794
				" WHERE ID = " . $userID  . " AND Passwd = '" .
Denis's avatar
Denis committed
795
				salted_hash($passwd, $salt) . "'";
796
797
798
799
800
801
			$result = db_query($passwd_q, $dbh);
			if ($result) {
				$passwd_result = mysql_fetch_row($result);
				if ($passwd_result[0]) {
					return true;
				}
Denis's avatar
Denis committed
802
803
804
805
			}
		} else {
			# check without salt
			$nosalt_q = "SELECT ID FROM Users".
806
				" WHERE ID = " . $userID .
Denis's avatar
Denis committed
807
				" AND Passwd = '" . md5($passwd) . "'";
808
809
810
811
812
813
814
815
816
817
818
			$result = db_query($nosalt_q, $dbh);
			if ($result) {
				$nosalt_row = mysql_fetch_row($result);
				if ($nosalt_row[0]) {
					# password correct, but salt it first
					if (!save_salt($userID, $passwd)) {
						trigger_error("Unable to salt user's password;" .
							" ID " . $userID, E_USER_WARNING);
						return false;
					}
					return true;
Denis's avatar
Denis committed
819
820
				}
			}
821
822
823
824
825
		}
	}
	return false;
}

826
827
828
/*
 * Checks if the PGP key fingerprint is valid (must be 40 hexadecimal digits).
 */
829
function valid_pgp_fingerprint($fingerprint) {
830
831
832
833
	$fingerprint = str_replace(" ", "", $fingerprint);
	return (strlen($fingerprint) == 40 && ctype_xdigit($fingerprint));
}

834
835
836
/*
 * Is the user account suspended?
 */
837
function user_suspended($id, $dbh) {
elij's avatar
elij committed
838
839
840
	if (!$id) {
		return false;
	}
841
	$q = "SELECT Suspended FROM Users WHERE ID = " . $id;
842
843
844
845
846
847
	$result = db_query($q, $dbh);
	if ($result) {
		$row = mysql_fetch_row($result);
		if ($result[0] == 1 ) {
			return true;
		}
848
849
850
851
852
853
854
	}
	return false;
}

/*
 * This should be expanded to return something
 */
855
function user_delete($id, $dbh) {
856
	$q = "DELETE FROM Users WHERE ID = " . $id;
857
	db_query($q, $dbh);
858
859
860
861
862
863
864
	return;
}

/*
 * A different way of determining a user's privileges
 * rather than account_from_sid()
 */
865
function user_is_privileged($id, $dbh) {
866
	$q = "SELECT AccountTypeID FROM Users WHERE ID = " . $id;
867
868
869
870
871
872
	$result = db_query($q, $dbh);
	if ($result) {
		$row = mysql_fetch_row($result);
		if( $result[0] > 1) {
			return $result[0];
		}
873
	}
874
875
876
877
	return 0;

}

878
# Clear out old expired sessions.
879
function clear_expired_sessions( $dbh ) {
880
881
	global $LOGIN_TIMEOUT;

882
	$q = "DELETE FROM Sessions WHERE LastUpdateTS < (UNIX_TIMESTAMP() - $LOGIN_TIMEOUT)";
883
884
885
886
	db_query($q, $dbh);

	return;
}
887