pkgfuncs.inc.php 22.2 KB
Newer Older
1
<?php
2
include_once("config.inc.php");
3
include_once("pkgbasefuncs.inc.php");
eric's avatar
eric committed
4

5
6
7
8
9
10
11
12
13
14
15
16
/**
 * Determine if the user can delete a specific package comment
 *
 * Only the comment submitter, Trusted Users, and Developers can delete
 * comments. This function is used for the backend side of comment deletion.
 *
 * @param string $comment_id The comment ID in the database
 * @param string $atype The account type of the user trying to delete a comment
 * @param string|int $uid The user ID of the individual trying to delete a comment
 *
 * @return bool True if the user can delete the comment, otherwise false
 */
17
function can_delete_comment($comment_id=0, $atype="", $uid=0) {
18
19
20
21
	if (!$uid) {
		/* Unauthenticated users cannot delete anything. */
		return false;
	}
22
	if ($atype == "Trusted User" || $atype == "Developer") {
23
		/* TUs and developers can delete any comment. */
24
		return true;
25
	}
Lukas Fleischer's avatar
Lukas Fleischer committed
26

27
	$dbh = DB::connect();
Lukas Fleischer's avatar
Lukas Fleischer committed
28
29
30

	$q = "SELECT COUNT(*) FROM PackageComments ";
	$q.= "WHERE ID = " . intval($comment_id) . " AND UsersID = " . $uid;
canyonknight's avatar
canyonknight committed
31
	$result = $dbh->query($q);
Lukas Fleischer's avatar
Lukas Fleischer committed
32
33
34

	if (!$result) {
		return false;
35
	}
Lukas Fleischer's avatar
Lukas Fleischer committed
36
37
38

	$row = $result->fetch(PDO::FETCH_NUM);
	return ($row[0] > 0);
39
}
eric's avatar
eric committed
40

41
42
43
44
45
46
47
48
49
50
51
52
/**
 * Determine if the user can delete a specific package comment using an array
 *
 * Only the comment submitter, Trusted Users, and Developers can delete
 * comments. This function is used for the frontend side of comment deletion.
 *
 * @param array $comment All database information relating a specific comment
 * @param string $atype The account type of the user trying to delete a comment
 * @param string|int $uid The user ID of the individual trying to delete a comment
 *
 * @return bool True if the user can delete the comment, otherwise false
 */
53
function can_delete_comment_array($comment, $atype="", $uid=0) {
54
55
56
57
	if (!$uid) {
		/* Unauthenticated users cannot delete anything. */
		return false;
	} elseif ($atype == "Trusted User" || $atype == "Developer") {
58
		/* TUs and developers can delete any comment. */
59
		return true;
60
	} else if ($comment['UsersID'] == $uid) {
61
		/* Users can delete their own comments. */
62
		return true;
63
	}
64
	return false;
65
66
}

67
68
69
70
71
72
73
74
75
76
/**
 * Determine if the visitor can submit blacklisted packages.
 *
 * Only Trusted Users and Developers can delete blacklisted packages. Packages
 * are blacklisted if they are include in the official repositories.
 *
 * @param string $atype The account type of the user
 *
 * @return bool True if the user can submit blacklisted packages, otherwise false
 */
77
function can_submit_blacklisted($atype = "") {
78
	if ($atype == "Trusted User" || $atype == "Developer") {
79
		/* Only TUs and developers can submit blacklisted packages. */
80
		return true;
81
82
	}
	else {
83
		return false;
84
85
86
	}
}

87
88
89
90
91
92
93
/**
 * Check to see if the package name already exists in the database
 *
 * @param string $name The package name to check
 *
 * @return string|void Package name if it already exists
 */
94
function pkg_from_name($name="") {
95
	if (!$name) {return NULL;}
96
	$dbh = DB::connect();
97
	$q = "SELECT ID FROM Packages ";
canyonknight's avatar
canyonknight committed
98
99
100
101
102
103
	$q.= "WHERE Name = " . $dbh->quote($name);
	$result = $dbh->query($q);
	if (!$result) {
		return;
	}
	$row = $result->fetch(PDO::FETCH_NUM);
104
105
106
	return $row[0];
}

107
108
109
110
111
112
113
/**
 * Get package dependencies for a specific package
 *
 * @param int $pkgid The package to get dependencies for
 *
 * @return array All package dependencies for the package
 */
114
function pkg_dependencies($pkgid) {
115
	$deps = array();
116
117
	$pkgid = intval($pkgid);
	if ($pkgid > 0) {
118
		$dbh = DB::connect();
119
		$q = "SELECT pd.DepName, dt.Name, pd.DepCondition, p.ID FROM PackageDepends pd ";
Dan McGee's avatar
Dan McGee committed
120
		$q.= "LEFT JOIN Packages p ON pd.DepName = p.Name ";
121
		$q.= "LEFT JOIN DependencyTypes dt ON dt.ID = pd.DepTypeID ";
Dan McGee's avatar
Dan McGee committed
122
123
		$q.= "WHERE pd.PackageID = ". $pkgid . " ";
		$q.= "ORDER BY pd.DepName";
canyonknight's avatar
canyonknight committed
124
125
126
127
128
		$result = $dbh->query($q);
		if (!$result) {
			return array();
		}
		while ($row = $result->fetch(PDO::FETCH_NUM)) {
129
130
131
132
133
134
			$deps[] = $row;
		}
	}
	return $deps;
}

135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/**
 * Get package relations for a specific package
 *
 * @param int $pkgid The package to get relations for
 *
 * @return array All package relations for the package
 */
function pkg_relations($pkgid) {
	$rels = array();
	$pkgid = intval($pkgid);
	if ($pkgid > 0) {
		$dbh = DB::connect();
		$q = "SELECT pr.RelName, rt.Name, pr.RelCondition, p.ID FROM PackageRelations pr ";
		$q.= "LEFT JOIN Packages p ON pr.RelName = p.Name ";
		$q.= "LEFT JOIN RelationTypes rt ON rt.ID = pr.RelTypeID ";
		$q.= "WHERE pr.PackageID = ". $pkgid . " ";
		$q.= "ORDER BY pr.RelName";
		$result = $dbh->query($q);
		if (!$result) {
			return array();
		}
		while ($row = $result->fetch(PDO::FETCH_NUM)) {
			$rels[] = $row;
		}
	}
	return $rels;
}

163
164
165
166
167
168
169
170
171
172
173
174
175
176
/**
 * Get the ID of a dependency type given its name
 *
 * @param string $name The name of the dependency type
 *
 * @return int The ID of the dependency type
 */
function pkg_dependency_type_id_from_name($name) {
	$dbh = DB::connect();
	$q = "SELECT ID FROM DependencyTypes WHERE Name = ";
	$q.= $dbh->quote($name);
	$result = $dbh->query($q);
	return $result->fetch(PDO::FETCH_COLUMN, 0);
}
177

178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
/**
 * Get the ID of a relation type given its name
 *
 * @param string $name The name of the relation type
 *
 * @return int The ID of the relation type
 */
function pkg_relation_type_id_from_name($name) {
	$dbh = DB::connect();
	$q = "SELECT ID FROM RelationTypes WHERE Name = ";
	$q.= $dbh->quote($name);
	$result = $dbh->query($q);
	return $result->fetch(PDO::FETCH_COLUMN, 0);
}

193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
/**
 * Get the HTML code to display a package dependency link
 *
 * @param string $name The name of the dependency
 * @param string $type The name of the dependency type
 * @param string $cond The package dependency condition string
 * @param int $pkg_id The package of the package to display the dependency for
 *
 * @return string The HTML code of the label to display
 */
function pkg_depend_link($name, $type, $cond, $pkg_id) {
	if ($type == 'optdepends' && strpos($name, ':') !== false) {
		$tokens = explode(':', $name, 2);
		$name = $tokens[0];
		$desc = $tokens[1];
	} else {
		$desc = '(unknown)';
	}

	$link = '<a href="';
	if (is_null($pkg_id)) {
		$link .= 'https://www.archlinux.org/packages/?q=' . urlencode($name);
	} else {
		$link .= htmlspecialchars(get_pkg_uri($name), ENT_QUOTES);
	}
	$link .= '" title="' . __('View packages details for') .' ' . htmlspecialchars($name) . '">';
	$link .= htmlspecialchars($name) . '</a>';
	$link .= htmlspecialchars($cond);

	if ($type == 'makedepends') {
		$link .= ' <em>(make)</em>';
	} elseif ($type == 'checkdepends') {
		$link .= ' <em>(check)</em>';
	} elseif ($type == 'optdepends') {
		$link .= ' <em>(optional) &ndash; ' . htmlspecialchars($desc) . ' </em>';
	}

	return $link;
}
232

233
234
235
236
237
238
239
/**
 * Determine packages that depend on a package
 *
 * @param string $name The package name for the dependency search
 *
 * @return array All packages that depend on the specified package name
 */
240
function pkg_required($name="") {
241
	$deps = array();
Dan McGee's avatar
Dan McGee committed
242
	if ($name != "") {
243
		$dbh = DB::connect();
244
		$q = "SELECT DISTINCT p.Name, PackageID FROM PackageDepends pd ";
Dan McGee's avatar
Dan McGee committed
245
		$q.= "JOIN Packages p ON pd.PackageID = p.ID ";
canyonknight's avatar
canyonknight committed
246
		$q.= "WHERE DepName = " . $dbh->quote($name) . " ";
Dan McGee's avatar
Dan McGee committed
247
		$q.= "ORDER BY p.Name";
canyonknight's avatar
canyonknight committed
248
		$result = $dbh->query($q);
249
		if (!$result) {return array();}
canyonknight's avatar
canyonknight committed
250
		while ($row = $result->fetch(PDO::FETCH_NUM)) {
251
252
253
254
255
256
			$deps[] = $row;
		}
	}
	return $deps;
}

257
258
259
260
261
262
263
/**
 * Get all package sources for a specific package
 *
 * @param string $pkgid The package ID to get the sources for
 *
 * @return array All sources associated with a specific package
 */
264
function pkg_sources($pkgid) {
265
	$sources = array();
266
267
	$pkgid = intval($pkgid);
	if ($pkgid > 0) {
268
		$dbh = DB::connect();
269
		$q = "SELECT Source FROM PackageSources ";
270
		$q.= "WHERE PackageID = " . $pkgid;
271
		$q.= " ORDER BY Source";
canyonknight's avatar
canyonknight committed
272
273
274
275
276
		$result = $dbh->query($q);
		if (!$result) {
			return array();
		}
		while ($row = $result->fetch(PDO::FETCH_NUM)) {
277
278
279
280
281
282
			$sources[] = $row[0];
		}
	}
	return $sources;
}

283
284
285
286
287
288
289
/**
 * Determine package names from package IDs
 *
 * @param string|array $pkgids The package IDs to get names for
 *
 * @return array|string All names if multiple package IDs, otherwise package name
 */
290
function pkg_name_from_id($pkgids) {
291
292
293
	if (is_array($pkgids)) {
		$pkgids = sanitize_ids($pkgids);
		$names = array();
294
		$dbh = DB::connect();
canyonknight's avatar
canyonknight committed
295
296
297
298
299
		$q = "SELECT Name FROM Packages WHERE ID IN (";
		$q.= implode(",", $pkgids) . ")";
		$result = $dbh->query($q);
		if ($result) {
			while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
300
301
302
303
304
305
				$names[] = $row['Name'];
			}
		}
		return $names;
	}
	elseif ($pkgids > 0) {
306
		$dbh = DB::connect();
307
		$q = "SELECT Name FROM Packages WHERE ID = " . $pkgids;
canyonknight's avatar
canyonknight committed
308
309
310
		$result = $dbh->query($q);
		if ($result) {
			$name = $result->fetch(PDO::FETCH_NUM);
311
		}
canyonknight's avatar
canyonknight committed
312
		return $name[0];
313
314
315
	}
	else {
		return NULL;
316
317
318
	}
}

319
320
321
322
323
324
325
/**
 * Determine if a package name is on the database blacklist
 *
 * @param string $name The package name to check
 *
 * @return bool True if the name is blacklisted, otherwise false
 */
326
function pkg_name_is_blacklisted($name) {
327
	$dbh = DB::connect();
canyonknight's avatar
canyonknight committed
328
329
330
	$q = "SELECT COUNT(*) FROM PackageBlacklist ";
	$q.= "WHERE Name = " . $dbh->quote($name);
	$result = $dbh->query($q);
331
332

	if (!$result) return false;
333
	return ($result->fetchColumn() > 0);
334
335
}

336
/**
337
 * Get the package details
338
 *
339
 * @param string $id The package ID to get description for
340
 *
341
342
 * @return array The package's details OR error message
 **/
343
function pkg_get_details($id=0) {
344
	$dbh = DB::connect();
345

346
347
348
349
350
351
352
353
	$q = "SELECT Packages.*, PackageBases.Name AS BaseName, ";
	$q.= "PackageBases.CategoryID, PackageBases.NumVotes, ";
	$q.= "PackageBases.OutOfDateTS, PackageBases.SubmittedTS, ";
	$q.= "PackageBases.ModifiedTS, PackageBases.SubmitterUID, ";
	$q.= "PackageBases.MaintainerUID, PackageCategories.Category ";
	$q.= "FROM Packages, PackageBases, PackageCategories ";
	$q.= "WHERE PackageBases.ID = Packages.PackageBaseID ";
	$q.= "AND PackageBases.CategoryID = PackageCategories.ID ";
Loui Chang's avatar
Loui Chang committed
354
	$q.= "AND Packages.ID = " . intval($id);
canyonknight's avatar
canyonknight committed
355
	$result = $dbh->query($q);
eric's avatar
eric committed
356

357
358
	$row = array();

canyonknight's avatar
canyonknight committed
359
	if (!$result) {
360
		$row['error'] = __("Error retrieving package details.");
361
362
	}
	else {
canyonknight's avatar
canyonknight committed
363
		$row = $result->fetch(PDO::FETCH_ASSOC);
eric's avatar
eric committed
364
		if (empty($row)) {
365
			$row['error'] = __("Package details could not be found.");
366
		}
367
368
369
370
371
372
373
374
375
376
377
	}

	return $row;
}

/**
 * Display the package details page
 *
 * @global string $AUR_LOCATION The AUR's URL used for notification e-mails
 * @global bool $USE_VIRTUAL_URLS True if using URL rewriting, otherwise false
 * @param string $id The package ID to get details page for
378
 * @param array $row Package details retrieved by pkg_get_details()
379
380
381
382
 * @param string $SID The session ID of the visitor
 *
 * @return void
 */
383
function pkg_display_details($id=0, $row, $SID="") {
384
385
386
	global $AUR_LOCATION;
	global $USE_VIRTUAL_URLS;

387
	$dbh = DB::connect();
388

389
390
391
392
	if (isset($row['error'])) {
		print "<p>" . $row['error'] . "</p>\n";
	}
	else {
393
394
395
		$base_id = pkgbase_from_pkgid($id);
		$pkgbase_name = pkgbase_name_from_id($base_id);

396
397
398
399
400
401
402
		include('pkg_details.php');

		if ($SID) {
			include('actions_form.php');
			include('pkg_comment_form.php');
		}

Lukas Fleischer's avatar
Lukas Fleischer committed
403
404
		$limit = isset($_GET['comments']) ? 0 : 10;
		$comments = pkgbase_comments($base_id, $limit);
405
406
		if (!empty($comments)) {
			include('pkg_comments.php');
eric's avatar
eric committed
407
408
409
410
		}
	}
}

Simo Leone's avatar
Simo Leone committed
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
/* pkg_search_page(SID)
 * outputs the body of search/search results page
 *
 * parameters:
 *  SID - current Session ID
 * preconditions:
 *  package search page has been accessed
 *  request variables have not been sanitized
 *
 *  request vars:
 *    O  - starting result number
 *    PP - number of search hits per page
 *    C  - package category ID number
 *    K  - package search string
 *    SO - search hit sort order:
 *          values: a - ascending
 *                  d - descending
 *    SB - sort search hits by:
429
 *          values: c - package category
Simo Leone's avatar
Simo Leone committed
430
431
432
433
 *                  n - package name
 *                  v - number of votes
 *                  m - maintainer username
 *    SeB- property that search string (K) represents
Andrea Scarpino's avatar
Andrea Scarpino committed
434
435
 *          values: n  - package name
 *                  nd - package name & description
436
 *                  x  - package name (exact match)
Simo Leone's avatar
Simo Leone committed
437
438
439
440
441
442
443
444
445
446
447
448
449
450
 *                  m  - package maintainer's username
 *                  s  - package submitter's username
 *    do_Orphans    - boolean. whether to search packages
 *                     without a maintainer
 *
 *
 *    These two are actually handled in packages.php.
 *
 *    IDs- integer array of ticked packages' IDs
 *    action - action to be taken on ticked packages
 *             values: do_Flag   - Flag out-of-date
 *                     do_UnFlag - Remove out-of-date flag
 *                     do_Adopt  - Adopt
 *                     do_Disown - Disown
451
 *                     do_Delete - Delete (requires confirm_Delete to be set)
452
453
 *                     do_Notify - Enable notification
 *                     do_UnNotify - Disable notification
Simo Leone's avatar
Simo Leone committed
454
 */
455
function pkg_search_page($SID="") {
456
	$dbh = DB::connect();
Loui Chang's avatar
Loui Chang committed
457

458
459
460
461
	/*
	 * Get commonly used variables.
	 * TODO: Reduce the number of database queries!
	 */
Loui Chang's avatar
Loui Chang committed
462
	if ($SID)
463
		$myuid = uid_from_sid($SID);
464
	$cats = pkgbase_categories($dbh);
Loui Chang's avatar
Loui Chang committed
465

466
	/* Sanitize paging variables. */
Loui Chang's avatar
Loui Chang committed
467
468
469
470
471
472
473
474
475
476
477
	if (isset($_GET['O'])) {
		$_GET['O'] = intval($_GET['O']);
		if ($_GET['O'] < 0)
			$_GET['O'] = 0;
	}
	else {
		$_GET['O'] = 0;
	}

	if (isset($_GET["PP"])) {
		$_GET["PP"] = intval($_GET["PP"]);
478
479
480
481
		if ($_GET["PP"] < 50)
			$_GET["PP"] = 50;
		else if ($_GET["PP"] > 250)
			$_GET["PP"] = 250;
Loui Chang's avatar
Loui Chang committed
482
483
	}
	else {
484
		$_GET["PP"] = 50;
Loui Chang's avatar
Loui Chang committed
485
486
	}

487
488
489
490
	/*
	 * FIXME: Pull out DB-related code. All of it! This one's worth a
	 * choco-chip cookie, one of those nice big soft ones.
	 */
Loui Chang's avatar
Loui Chang committed
491

492
	/* Build the package search query. */
493
	$q_select = "SELECT ";
Loui Chang's avatar
Loui Chang committed
494
	if ($SID) {
495
		$q_select .= "CommentNotify.UserID AS Notify,
496
			   PackageVotes.UsersID AS Voted, ";
Loui Chang's avatar
Loui Chang committed
497
	}
498
	$q_select .= "Users.Username AS Maintainer,
Loui Chang's avatar
Loui Chang committed
499
	PackageCategories.Category,
500
	Packages.Name, Packages.Version, Packages.Description,
501
502
	PackageBases.NumVotes, Packages.ID, Packages.PackageBaseID,
	PackageBases.OutOfDateTS ";
Loui Chang's avatar
Loui Chang committed
503

504
	$q_from = "FROM Packages
505
506
	LEFT JOIN PackageBases ON (PackageBases.ID = Packages.PackageBaseID)
	LEFT JOIN Users ON (PackageBases.MaintainerUID = Users.ID)
507
	LEFT JOIN PackageCategories
508
	ON (PackageBases.CategoryID = PackageCategories.ID) ";
Loui Chang's avatar
Loui Chang committed
509
	if ($SID) {
510
		/* This is not needed for the total row count query. */
511
		$q_from_extra = "LEFT JOIN PackageVotes
512
		ON (PackageBases.ID = PackageVotes.PackageBaseID AND PackageVotes.UsersID = $myuid)
Loui Chang's avatar
Loui Chang committed
513
		LEFT JOIN CommentNotify
514
		ON (PackageBases.ID = CommentNotify.PackageBaseID AND CommentNotify.UserID = $myuid) ";
515
516
	} else {
		$q_from_extra = "";
Loui Chang's avatar
Loui Chang committed
517
518
	}

Dan McGee's avatar
Dan McGee committed
519
	$q_where = "WHERE 1 = 1 ";
520
521
522
523
	/*
	 * TODO: Possibly do string matching on category to make request
	 * variable values more sensible.
	 */
524
	if (isset($_GET["C"]) && intval($_GET["C"])) {
Lukas Fleischer's avatar
Lukas Fleischer committed
525
		$q_where .= "AND PackageBases.CategoryID = ".intval($_GET["C"])." ";
Loui Chang's avatar
Loui Chang committed
526
527
	}

528
529
	if (isset($_GET['K'])) {
		if (isset($_GET["SeB"]) && $_GET["SeB"] == "m") {
530
			/* Search by maintainer. */
canyonknight's avatar
canyonknight committed
531
			$q_where .= "AND Users.Username = " . $dbh->quote($_GET['K']) . " ";
Loui Chang's avatar
Loui Chang committed
532
		}
533
		elseif (isset($_GET["SeB"]) && $_GET["SeB"] == "s") {
534
			/* Search by submitter. */
535
			$q_where .= "AND SubmitterUID = ".uid_from_username($_GET['K'])." ";
Loui Chang's avatar
Loui Chang committed
536
		}
537
		elseif (isset($_GET["SeB"]) && $_GET["SeB"] == "n") {
538
			/* Search by name. */
canyonknight's avatar
canyonknight committed
539
			$K = "%" . addcslashes($_GET['K'], '%_') . "%";
540
			$q_where .= "AND (Packages.Name LIKE " . $dbh->quote($K) . ") ";
Andrea Scarpino's avatar
Andrea Scarpino committed
541
		}
542
543
544
545
546
547
		elseif (isset($_GET["SeB"]) && $_GET["SeB"] == "b") {
			/* Search by package base name. */
			$K = "%" . addcslashes($_GET['K'], '%_') . "%";
			$q_where .= "AND (PackageBases.Name LIKE " . $dbh->quote($K) . ") ";
		}
		elseif (isset($_GET["SeB"]) && $_GET["SeB"] == "N") {
548
			/* Search by name (exact match). */
549
			$q_where .= "AND (Packages.Name = " . $dbh->quote($_GET['K']) . ") ";
550
		}
551
552
553
554
		elseif (isset($_GET["SeB"]) && $_GET["SeB"] == "B") {
			/* Search by package base name (exact match). */
			$q_where .= "AND (PackageBases.Name = " . $dbh->quote($_GET['K']) . ") ";
		}
Loui Chang's avatar
Loui Chang committed
555
		else {
556
			/* Search by name and description (default). */
canyonknight's avatar
canyonknight committed
557
			$K = "%" . addcslashes($_GET['K'], '%_') . "%";
558
			$q_where .= "AND (Packages.Name LIKE " . $dbh->quote($K) . " OR ";
canyonknight's avatar
canyonknight committed
559
			$q_where .= "Description LIKE " . $dbh->quote($K) . ") ";
Loui Chang's avatar
Loui Chang committed
560
561
562
		}
	}

563
	if (isset($_GET["do_Orphans"])) {
564
		$q_where .= "AND MaintainerUID IS NULL ";
Loui Chang's avatar
Loui Chang committed
565
	}
566

567
	if (isset($_GET['outdated'])) {
568
		if ($_GET['outdated'] == 'on') {
569
			$q_where .= "AND OutOfDateTS IS NOT NULL ";
570
571
		}
		elseif ($_GET['outdated'] == 'off') {
572
			$q_where .= "AND OutOfDateTS IS NULL ";
573
		}
574
575
	}

576
	$order = (isset($_GET["SO"]) && $_GET["SO"] == 'd') ? 'DESC' : 'ASC';
Loui Chang's avatar
Loui Chang committed
577

578
	$q_sort = "ORDER BY ";
579
580
	$sort_by = isset($_GET["SB"]) ? $_GET["SB"] : '';
	switch ($sort_by) {
Loui Chang's avatar
Loui Chang committed
581
	case 'c':
582
		$q_sort .= "CategoryID " . $order . ", ";
Loui Chang's avatar
Loui Chang committed
583
584
		break;
	case 'v':
585
		$q_sort .= "NumVotes " . $order . ", ";
Loui Chang's avatar
Loui Chang committed
586
		break;
587
588
	case 'w':
		if ($SID) {
589
			$q_sort .= "Voted " . $order . ", ";
590
591
592
593
		}
		break;
	case 'o':
		if ($SID) {
594
			$q_sort .= "Notify " . $order . ", ";
595
596
		}
		break;
Loui Chang's avatar
Loui Chang committed
597
	case 'm':
598
		$q_sort .= "Maintainer " . $order . ", ";
Loui Chang's avatar
Loui Chang committed
599
600
		break;
	case 'a':
601
		$q_sort .= "ModifiedTS " . $order . ", ";
Loui Chang's avatar
Loui Chang committed
602
603
604
605
		break;
	default:
		break;
	}
606
	$q_sort .= " Packages.Name " . $order . " ";
Loui Chang's avatar
Loui Chang committed
607

608
	$q_limit = "LIMIT ".$_GET["PP"]." OFFSET ".$_GET["O"];
609

610
611
	$q = $q_select . $q_from . $q_from_extra . $q_where . $q_sort . $q_limit;
	$q_total = "SELECT COUNT(*) " . $q_from . $q_where;
Loui Chang's avatar
Loui Chang committed
612

canyonknight's avatar
canyonknight committed
613
614
	$result = $dbh->query($q);
	$result_t = $dbh->query($q_total);
615
	if ($result_t) {
canyonknight's avatar
canyonknight committed
616
617
		$row = $result_t->fetch(PDO::FETCH_NUM);
		$total = $row[0];
618
619
620
621
	}
	else {
		$total = 0;
	}
Simo Leone's avatar
Simo Leone committed
622

623
	if ($result && $total > 0) {
624
625
		if (isset($_GET["SO"]) && $_GET["SO"] == "d"){
			$SO_next = "a";
Loui Chang's avatar
Loui Chang committed
626
627
		}
		else {
628
			$SO_next = "d";
Loui Chang's avatar
Loui Chang committed
629
		}
630
	}
Simo Leone's avatar
Simo Leone committed
631

632
	/* Calculate the results to use. */
Loui Chang's avatar
Loui Chang committed
633
	$first = $_GET['O'] + 1;
Simo Leone's avatar
Simo Leone committed
634

635
	/* Calculation of pagination links. */
636
637
638
639
	$per_page = ($_GET['PP'] > 0) ? $_GET['PP'] : 50;
	$current = ceil($first / $per_page);
	$pages = ceil($total / $per_page);
	$templ_pages = array();
640

641
	if ($current > 1) {
642
643
		$templ_pages['&laquo; ' . __('First')] = 0;
		$templ_pages['&lsaquo; ' . __('Previous')] = ($current - 2) * $per_page;
644
	}
645

646
647
	if ($current - 5 > 1)
		$templ_pages["..."] = false;
648

649
650
651
	for ($i = max($current - 5, 1); $i <= min($pages, $current + 5); $i++) {
		$templ_pages[$i] = ($i - 1) * $per_page;
	}
652

653
654
	if ($current + 5 < $pages)
		$templ_pages["... "] = false;
655

656
	if ($current < $pages) {
657
658
		$templ_pages[__('Next') . ' &rsaquo;'] = $current * $per_page;
		$templ_pages[__('Last') . ' &raquo;'] = ($pages - 1) * $per_page;
659
	}
Simo Leone's avatar
Simo Leone committed
660

661
	include('pkg_search_form.php');
662

canyonknight's avatar
canyonknight committed
663
664
665
666
	if ($result) {
		while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
			$searchresults[] = $row;
		}
667
668
	}

669
670
	include('pkg_search_results.php');

Loui Chang's avatar
Loui Chang committed
671
	return;
eric's avatar
eric committed
672
673
}

674
675
676
677
678
679
680
/**
 * Determine if a POST string has been sent by a visitor
 *
 * @param string $action String to check has been sent via POST
 *
 * @return bool True if the POST string was used, otherwise false
 */
Dan McGee's avatar
Dan McGee committed
681
682
683
684
685
function current_action($action) {
	return (isset($_POST['action']) && $_POST['action'] == $action) ||
		isset($_POST[$action]);
}

686
/**
687
688
689
690
691
 * Determine if sent IDs are valid integers
 *
 * @param array $ids IDs to validate
 *
 * @return array All sent IDs that are valid integers
692
693
694
695
696
697
698
699
700
701
702
703
 */
function sanitize_ids($ids) {
	$new_ids = array();
	foreach ($ids as $id) {
		$id = intval($id);
		if ($id > 0) {
			$new_ids[] = $id;
		}
	}
	return $new_ids;
}

704
705
706
707
708
709
710
/**
 * Get all package information in the database for a specific package
 *
 * @param string $pkgname The name of the package to get details for
 *
 * @return array All package details for a specific package
 */
711
function pkg_details_by_name($pkgname) {
712
	$dbh = DB::connect();
713
714
715
716
717
718
719
720
	$q = "SELECT Packages.*, PackageBases.Name AS BaseName, ";
	$q.= "PackageBases.CategoryID, PackageBases.NumVotes, ";
	$q.= "PackageBases.OutOfDateTS, PackageBases.SubmittedTS, ";
	$q.= "PackageBases.ModifiedTS, PackageBases.SubmitterUID, ";
	$q.= "PackageBases.MaintainerUID FROM Packages ";
	$q.= "INNER JOIN PackageBases ";
	$q.= "ON PackageBases.ID = Packages.PackageBaseID WHERE ";
	$q.= "Packages.Name = " . $dbh->quote($pkgname);
canyonknight's avatar
canyonknight committed
721
	$result = $dbh->query($q);
canyonknight's avatar
canyonknight committed
722
	if ($result) {
canyonknight's avatar
canyonknight committed
723
		$row = $result->fetch(PDO::FETCH_ASSOC);
canyonknight's avatar
canyonknight committed
724
	}
canyonknight's avatar
canyonknight committed
725
	return $row;
canyonknight's avatar
canyonknight committed
726
727
}

728
729
730
/**
 * Add package information to the database for a specific package
 *
731
 * @param int $base_id ID of the package base
732
733
734
735
736
 * @param string $pkgname Name of the new package
 * @param string $license License of the new package
 * @param string $pkgver Version of the new package
 * @param string $pkgdesc Description of the new package
 * @param string $pkgurl Upstream URL for the new package
737
738
739
 *
 * @return int ID of the new package
 */
740
function pkg_create($base_id, $pkgname, $license, $pkgver, $pkgdesc, $pkgurl) {
741
742
743
744
745
746
747
748
749
750
	$dbh = DB::connect();
	$q = sprintf("INSERT INTO Packages (PackageBaseID, Name, License, " .
		"Version, Description, URL) VALUES (%d, %s, %s, %s, %s, %s)",
		$base_id, $dbh->quote($pkgname), $dbh->quote($license),
		$dbh->quote($pkgver), $dbh->quote($pkgdesc),
		$dbh->quote($pkgurl));
	$dbh->exec($q);
	return $dbh->lastInsertId();
}

751
752
753
754
/**
 * Add a dependency for a specific package to the database
 *
 * @param int $pkgid The package ID to add the dependency for
755
 * @param string $type The type of dependency to add
756
757
758
759
760
 * @param string $depname The name of the dependency to add
 * @param string $depcondition The  type of dependency for the package
 *
 * @return void
 */
761
function pkg_add_dep($pkgid, $type, $depname, $depcondition) {
762
	$dbh = DB::connect();
763
764
765
766
767
768
	$q = sprintf("INSERT INTO PackageDepends (PackageID, DepTypeID, DepName, DepCondition) VALUES (%d, %d, %s, %s)",
		$pkgid,
		pkg_dependency_type_id_from_name($type),
		$dbh->quote($depname),
		$dbh->quote($depcondition)
	);
canyonknight's avatar
canyonknight committed
769
	$dbh->exec($q);
canyonknight's avatar
canyonknight committed
770
771
}

772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
/**
 * Add a relation for a specific package to the database
 *
 * @param int $pkgid The package ID to add the relation for
 * @param string $type The type of relation to add
 * @param string $relname The name of the relation to add
 * @param string $relcondition The version requirement of the relation
 *
 * @return void
 */
function pkg_add_rel($pkgid, $type, $relname, $relcondition) {
	$dbh = DB::connect();
	$q = sprintf("INSERT INTO PackageRelations (PackageID, RelTypeID, RelName, RelCondition) VALUES (%d, %d, %s, %s)",
		$pkgid,
		pkg_relation_type_id_from_name($type),
		$dbh->quote($relname),
		$dbh->quote($relcondition)
	);
	$dbh->exec($q);
}

793
794
795
796
797
798
799
800
/**
 * Add a source for a specific package to the database
 *
 * @param int $pkgid The package ID to add the source for
 * @param string $pkgsrc The package source to add to the database
 *
 * @return void
 */
801
function pkg_add_src($pkgid, $pkgsrc) {
802
	$dbh = DB::connect();
canyonknight's avatar
canyonknight committed
803
	$q = "INSERT INTO PackageSources (PackageID, Source) VALUES (";
canyonknight's avatar
canyonknight committed
804
	$q .= $pkgid . ", " . $dbh->quote($pkgsrc) . ")";
canyonknight's avatar
canyonknight committed
805

canyonknight's avatar
canyonknight committed
806
	$dbh->exec($q);
canyonknight's avatar
canyonknight committed
807
}