Migrate all DB code to use PDO
[aur.git] / web / lib / aur.inc.php
blobd26bdf2ef510a4cf188d5c7c22678677a512a9e2
1 <?php
2 set_include_path(get_include_path() . PATH_SEPARATOR . '../lib' . PATH_SEPARATOR . '../template');
3 header('Content-Type: text/html; charset=utf-8');
4 header('Cache-Control: no-cache, must-revalidate');
5 header('Expires: Tue, 11 Oct 1988 22:00:00 GMT'); // quite a special day
6 header('Pragma: no-cache');
8 date_default_timezone_set('UTC');
10 include_once('translator.inc.php');
11 set_lang();
13 include_once("config.inc.php");
14 include_once("routing.inc.php");
15 include_once("version.inc.php");
16 include_once("acctfuncs.inc.php");
17 include_once("cachefuncs.inc.php");
19 # see if the visitor is already logged in
21 function check_sid($dbh=NULL) {
22 global $_COOKIE;
23 global $LOGIN_TIMEOUT;
25 if (isset($_COOKIE["AURSID"])) {
26 $failed = 0;
27 # the visitor is logged in, try and update the session
29 if(!$dbh) {
30 $dbh = db_connect();
32 $q = "SELECT LastUpdateTS, UNIX_TIMESTAMP() FROM Sessions ";
33 $q.= "WHERE SessionID = " . $dbh->quote($_COOKIE["AURSID"]);
34 $result = $dbh->query($q);
35 $row = $result->fetch(PDO::FETCH_NUM);
37 if (!$row[0]) {
38 # Invalid SessionID - hacker alert!
40 $failed = 1;
41 } else {
42 $last_update = $row[0];
43 if ($last_update + $LOGIN_TIMEOUT <= $row[1]) {
44 $failed = 2;
48 if ($failed == 1) {
49 # clear out the hacker's cookie, and send them to a naughty page
50 # why do you have to be so harsh on these people!?
52 setcookie("AURSID", "", 1, "/", null, !empty($_SERVER['HTTPS']), true);
53 unset($_COOKIE['AURSID']);
54 } elseif ($failed == 2) {
55 # session id timeout was reached and they must login again.
57 delete_session_id($_COOKIE["AURSID"], $dbh);
59 setcookie("AURSID", "", 1, "/", null, !empty($_SERVER['HTTPS']), true);
60 unset($_COOKIE['AURSID']);
61 } else {
62 # still logged in and haven't reached the timeout, go ahead
63 # and update the idle timestamp
65 # Only update the timestamp if it is less than the
66 # current time plus $LOGIN_TIMEOUT.
68 # This keeps 'remembered' sessions from being
69 # overwritten.
70 if ($last_update < time() + $LOGIN_TIMEOUT) {
71 $q = "UPDATE Sessions SET LastUpdateTS = UNIX_TIMESTAMP() ";
72 $q.= "WHERE SessionID = " . $dbh->quote($_COOKIE["AURSID"]);
73 $dbh->exec($q);
77 return;
80 # Verify the supplied token matches the expected token for POST forms
82 function check_token() {
83 if (isset($_POST['token'])) {
84 return ($_POST['token'] == $_COOKIE['AURSID']);
85 } else {
86 return false;
90 # verify that an email address looks like it is legitimate
92 function valid_email($addy) {
93 // check against RFC 3696
94 if (filter_var($addy, FILTER_VALIDATE_EMAIL) === false) {
95 return false;
98 // check dns for mx, a, aaaa records
99 list($local, $domain) = explode('@', $addy);
100 if (!(checkdnsrr($domain, 'MX') || checkdnsrr($domain, 'A') || checkdnsrr($domain, 'AAAA'))) {
101 return false;
104 return true;
107 # generate a (hopefully) unique session id
109 function new_sid() {
110 return md5($_SERVER['REMOTE_ADDR'] . uniqid(mt_rand(), true));
114 # obtain the username if given their Users.ID
116 function username_from_id($id="", $dbh=NULL) {
117 if (!$id) {
118 return "";
120 if(!$dbh) {
121 $dbh = db_connect();
123 $q = "SELECT Username FROM Users WHERE ID = " . $dbh->quote($id);
124 $result = $dbh->query($q);
125 if (!$result) {
126 return "None";
128 $row = $result->fetch(PDO::FETCH_NUM);
130 return $row[0];
134 # obtain the username if given their current SID
136 function username_from_sid($sid="", $dbh=NULL) {
137 if (!$sid) {
138 return "";
140 if(!$dbh) {
141 $dbh = db_connect();
143 $q = "SELECT Username ";
144 $q.= "FROM Users, Sessions ";
145 $q.= "WHERE Users.ID = Sessions.UsersID ";
146 $q.= "AND Sessions.SessionID = " . $dbh->quote($sid);
147 $result = $dbh->query($q);
148 if (!$result) {
149 return "";
151 $row = $result->fetch(PDO::FETCH_NUM);
153 return $row[0];
156 # obtain the email address if given their current SID
158 function email_from_sid($sid="", $dbh=NULL) {
159 if (!$sid) {
160 return "";
162 if(!$dbh) {
163 $dbh = db_connect();
165 $q = "SELECT Email ";
166 $q.= "FROM Users, Sessions ";
167 $q.= "WHERE Users.ID = Sessions.UsersID ";
168 $q.= "AND Sessions.SessionID = " . $dbh->quote($sid);
169 $result = $dbh->query($q);
170 if (!$result) {
171 return "";
173 $row = $result->fetch(PDO::FETCH_NUM);
175 return $row[0];
178 # obtain the account type if given their current SID
179 # Return either "", "User", "Trusted User", "Developer"
181 function account_from_sid($sid="", $dbh=NULL) {
182 if (!$sid) {
183 return "";
185 if(!$dbh) {
186 $dbh = db_connect();
188 $q = "SELECT AccountType ";
189 $q.= "FROM Users, AccountTypes, Sessions ";
190 $q.= "WHERE Users.ID = Sessions.UsersID ";
191 $q.= "AND AccountTypes.ID = Users.AccountTypeID ";
192 $q.= "AND Sessions.SessionID = " . $dbh->quote($sid);
193 $result = $dbh->query($q);
194 if (!$result) {
195 return "";
197 $row = $result->fetch(PDO::FETCH_NUM);
199 return $row[0];
202 # obtain the Users.ID if given their current SID
204 function uid_from_sid($sid="", $dbh=NULL) {
205 if (!$sid) {
206 return "";
208 if(!$dbh) {
209 $dbh = db_connect();
211 $q = "SELECT Users.ID ";
212 $q.= "FROM Users, Sessions ";
213 $q.= "WHERE Users.ID = Sessions.UsersID ";
214 $q.= "AND Sessions.SessionID = " . $dbh->quote($sid);
215 $result = $dbh->query($q);
216 if (!$result) {
217 return 0;
219 $row = $result->fetch(PDO::FETCH_NUM);
221 return $row[0];
224 # connect to the database
226 function db_connect() {
227 try {
228 $dbh = new PDO(AUR_db_DSN_prefix . ":" . AUR_db_host . ";dbname=" . AUR_db_name, AUR_db_user, AUR_db_pass);
230 catch (PDOException $e) {
231 echo "Error - Could not connect to AUR database: " . $e->getMessage();
234 $dbh->exec("SET NAMES 'utf8' COLLATE 'utf8_general_ci';");
236 return $dbh;
239 # common header
241 function html_header($title="") {
242 global $LANG;
243 global $SUPPORTED_LANGS;
245 $title = htmlspecialchars($title, ENT_QUOTES);
247 include('header.php');
248 return;
252 # common footer
254 function html_footer($ver="") {
255 include('footer.php');
256 return;
259 # check to see if the user can submit a package
261 function can_submit_pkg($name="", $sid="", $dbh=NULL) {
262 if (!$name || !$sid) {return 0;}
263 if(!$dbh) {
264 $dbh = db_connect();
266 $q = "SELECT MaintainerUID ";
267 $q.= "FROM Packages WHERE Name = " . $dbh->quote($name);
268 $result = $dbh->query($q);
269 $row = $result->fetch(PDO::FETCH_NUM);
271 if (!$row[0]) {
272 return 1;
274 $my_uid = uid_from_sid($sid, $dbh);
276 if ($row[0] === NULL || $row[0] == $my_uid) {
277 return 1;
280 return 0;
283 # recursive delete directory
285 function rm_tree($dirname) {
286 if (empty($dirname) || !is_dir($dirname)) return;
288 foreach (scandir($dirname) as $item) {
289 if ($item != '.' && $item != '..') {
290 $path = $dirname . '/' . $item;
291 if (is_file($path) || is_link($path)) {
292 unlink($path);
294 else {
295 rm_tree($path);
300 rmdir($dirname);
302 return;
305 # Recursive chmod to set group write permissions
307 function chmod_group($path) {
308 if (!is_dir($path))
309 return chmod($path, 0664);
311 $d = dir($path);
312 while ($f = $d->read()) {
313 if ($f != '.' && $f != '..') {
314 $fullpath = $path.'/'.$f;
315 if (is_link($fullpath))
316 continue;
317 elseif (!is_dir($fullpath)) {
318 if (!chmod($fullpath, 0664))
319 return FALSE;
321 elseif(!chmod_group($fullpath))
322 return FALSE;
325 $d->close();
327 if(chmod($path, 0775))
328 return TRUE;
329 else
330 return FALSE;
333 # obtain the uid given a Users.Username
335 function uid_from_username($username="", $dbh=NULL) {
336 if (!$username) {
337 return "";
339 if(!$dbh) {
340 $dbh = db_connect();
342 $q = "SELECT ID FROM Users WHERE Username = " . $dbh->quote($username);
343 $result = $dbh->query($q);
344 if (!$result) {
345 return "None";
347 $row = $result->fetch(PDO::FETCH_NUM);
349 return $row[0];
352 # obtain the uid given a Users.Email
354 function uid_from_email($email="", $dbh=NULL) {
355 if (!$email) {
356 return "";
358 if(!$dbh) {
359 $dbh = db_connect();
361 $q = "SELECT ID FROM Users WHERE Email = " . $dbh->quote($email);
362 $result = $dbh->query($q);
363 if (!$result) {
364 return "None";
366 $row = $result->fetch(PDO::FETCH_NUM);
368 return $row[0];
371 # check user privileges
373 function check_user_privileges() {
374 $type = account_from_sid($_COOKIE['AURSID']);
375 return ($type == 'Trusted User' || $type == 'Developer');
379 * Generate clean url with edited/added user values
381 * Makes a clean string of variables for use in URLs based on current $_GET and
382 * list of values to edit/add to that. Any empty variables are discarded.
384 * ex. print "http://example.com/test.php?" . mkurl("foo=bar&bar=baz")
386 * @param string $append string of variables and values formatted as in URLs
387 * ex. mkurl("foo=bar&bar=baz")
388 * @return string clean string of variables to append to URL, urlencoded
390 function mkurl($append) {
391 $get = $_GET;
392 $append = explode('&', $append);
393 $uservars = array();
394 $out = '';
396 foreach ($append as $i) {
397 $ex = explode('=', $i);
398 $uservars[$ex[0]] = $ex[1];
401 foreach ($uservars as $k => $v) { $get[$k] = $v; }
403 foreach ($get as $k => $v) {
404 if ($v !== '') {
405 $out .= '&amp;' . urlencode($k) . '=' . urlencode($v);
409 return substr($out, 5);
412 function get_salt($user_id, $dbh=NULL) {
413 if(!$dbh) {
414 $dbh = db_connect();
416 $q = "SELECT Salt FROM Users WHERE ID = " . $user_id;
417 $result = $dbh->query($q);
418 if ($result) {
419 $row = $result->fetch(PDO::FETCH_NUM);
420 return $row[0];
422 return;
425 function save_salt($user_id, $passwd, $dbh=NULL) {
426 if(!$dbh) {
427 $dbh = db_connect();
429 $salt = generate_salt();
430 $hash = salted_hash($passwd, $salt);
431 $q = "UPDATE Users SET Salt = " . $dbh->quote($salt) . ", ";
432 $q.= "Passwd = " . $dbh->quote($hash) . " WHERE ID = " . $user_id;
433 $result = $dbh->exec($q);
436 function generate_salt() {
437 return md5(uniqid(mt_rand(), true));
440 function salted_hash($passwd, $salt) {
441 if (strlen($salt) != 32) {
442 trigger_error('Salt does not look like an md5 hash', E_USER_WARNING);
444 return md5($salt . $passwd);
447 function parse_comment($comment) {
448 $url_pattern = '/(\b(?:https?|ftp):\/\/[\w\/\#~:.?+=&%@!\-;,]+?' .
449 '(?=[.:?\-;,]*(?:[^\w\/\#~:.?+=&%@!\-;,]|$)))/iS';
451 $matches = preg_split($url_pattern, $comment, -1,
452 PREG_SPLIT_DELIM_CAPTURE);
454 $html = '';
455 for ($i = 0; $i < count($matches); $i++) {
456 if ($i % 2) {
457 # convert links
458 $html .= '<a href="' . htmlspecialchars($matches[$i]) .
459 '">' . htmlspecialchars($matches[$i]) . '</a>';
461 else {
462 # convert everything else
463 $html .= nl2br(htmlspecialchars($matches[$i]));
467 return $html;
470 function begin_atomic_commit($dbh=NULL) {
471 if(!$dbh) {
472 $dbh = db_connect();
474 $dbh->beginTransaction();
477 function end_atomic_commit($dbh=NULL) {
478 if(!$dbh) {
479 $dbh = db_connect();
481 $dbh->commit();
484 function last_insert_id($dbh=NULL) {
485 if(!$dbh) {
486 $dbh = db_connect();
488 return $dbh->lastInsertId();
491 function latest_pkgs($numpkgs, $dbh=NULL) {
492 if(!$dbh) {
493 $dbh = db_connect();
496 $q = "SELECT * FROM Packages ";
497 $q.= "ORDER BY SubmittedTS DESC ";
498 $q.= "LIMIT " .intval($numpkgs);
499 $result = $dbh->query($q);
501 if ($result) {
502 while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
503 $packages[] = $row;
507 return $packages;