pkgfuncs.inc.php 24.3 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
/**
 * 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
 *
 * @return bool True if the user can delete the comment, otherwise false
 */
Lukas Fleischer's avatar
Lukas Fleischer committed
15
function can_delete_comment($comment_id=0) {
16
	$dbh = DB::connect();
Lukas Fleischer's avatar
Lukas Fleischer committed
17

18
19
	$q = "SELECT UsersID FROM PackageComments ";
	$q.= "WHERE ID = " . intval($comment_id);
canyonknight's avatar
canyonknight committed
20
	$result = $dbh->query($q);
Lukas Fleischer's avatar
Lukas Fleischer committed
21
22
23

	if (!$result) {
		return false;
24
	}
Lukas Fleischer's avatar
Lukas Fleischer committed
25

26
27
28
	$uid = $result->fetch(PDO::FETCH_COLUMN, 0);

	return has_credential(CRED_COMMENT_DELETE, array($uid));
29
}
eric's avatar
eric committed
30

31
32
33
34
35
36
37
38
39
40
/**
 * 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
 *
 * @return bool True if the user can delete the comment, otherwise false
 */
Lukas Fleischer's avatar
Lukas Fleischer committed
41
42
function can_delete_comment_array($comment) {
	return has_credential(CRED_COMMENT_DELETE, array($comment['UsersID']));
43
44
}

45
46
47
48
49
50
51
52
/**
 * 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.
 *
 * @return bool True if the user can submit blacklisted packages, otherwise false
 */
Lukas Fleischer's avatar
Lukas Fleischer committed
53
54
function can_submit_blacklisted() {
	return has_credential(CRED_PKGBASE_SUBMIT_BLACKLISTED);
55
56
}

57
58
59
60
61
62
63
/**
 * 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
 */
64
function pkg_from_name($name="") {
65
	if (!$name) {return NULL;}
66
	$dbh = DB::connect();
67
	$q = "SELECT ID FROM Packages ";
canyonknight's avatar
canyonknight committed
68
69
70
71
72
73
	$q.= "WHERE Name = " . $dbh->quote($name);
	$result = $dbh->query($q);
	if (!$result) {
		return;
	}
	$row = $result->fetch(PDO::FETCH_NUM);
74
75
76
	return $row[0];
}

77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
/**
 * Get licenses for a specific package
 *
 * @param int $pkgid The package to get licenses for
 *
 * @return array All licenses for the package
 */
function pkg_licenses($pkgid) {
	$lics = array();
	$pkgid = intval($pkgid);
	if ($pkgid > 0) {
		$dbh = DB::connect();
		$q = "SELECT l.Name FROM Licenses l ";
		$q.= "INNER JOIN PackageLicenses pl ON pl.LicenseID = l.ID ";
		$q.= "WHERE pl.PackageID = ". $pkgid;
		$result = $dbh->query($q);
		if (!$result) {
			return array();
		}
		while ($row = $result->fetch(PDO::FETCH_COLUMN, 0)) {
			$lics[] = $row;
		}
	}
	return $lics;
}

103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/**
 * Get package groups for a specific package
 *
 * @param int $pkgid The package to get groups for
 *
 * @return array All package groups for the package
 */
function pkg_groups($pkgid) {
	$grps = array();
	$pkgid = intval($pkgid);
	if ($pkgid > 0) {
		$dbh = DB::connect();
		$q = "SELECT g.Name FROM Groups g ";
		$q.= "INNER JOIN PackageGroups pg ON pg.GroupID = g.ID ";
		$q.= "WHERE pg.PackageID = ". $pkgid;
		$result = $dbh->query($q);
		if (!$result) {
			return array();
		}
		while ($row = $result->fetch(PDO::FETCH_COLUMN, 0)) {
			$grps[] = $row;
		}
	}
	return $grps;
}

129
130
131
132
133
134
135
/**
 * Get package dependencies for a specific package
 *
 * @param int $pkgid The package to get dependencies for
 *
 * @return array All package dependencies for the package
 */
136
function pkg_dependencies($pkgid) {
137
	$deps = array();
138
139
	$pkgid = intval($pkgid);
	if ($pkgid > 0) {
140
		$dbh = DB::connect();
141
		$q = "SELECT pd.DepName, dt.Name, pd.DepCondition, p.ID FROM PackageDepends pd ";
Dan McGee's avatar
Dan McGee committed
142
		$q.= "LEFT JOIN Packages p ON pd.DepName = p.Name ";
143
		$q.= "OR SUBSTRING(pd.DepName FROM 1 FOR POSITION(': ' IN pd.DepName) - 1) = p.Name ";
144
		$q.= "LEFT JOIN DependencyTypes dt ON dt.ID = pd.DepTypeID ";
Dan McGee's avatar
Dan McGee committed
145
146
		$q.= "WHERE pd.PackageID = ". $pkgid . " ";
		$q.= "ORDER BY pd.DepName";
canyonknight's avatar
canyonknight committed
147
148
149
150
151
		$result = $dbh->query($q);
		if (!$result) {
			return array();
		}
		while ($row = $result->fetch(PDO::FETCH_NUM)) {
152
153
154
155
156
157
			$deps[] = $row;
		}
	}
	return $deps;
}

158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
/**
 * 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;
}

186
187
188
189
190
191
192
193
194
195
196
197
198
199
/**
 * 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);
}
200

201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
/**
 * 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);
}

216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
/**
 * 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;
}
255

256
257
258
259
260
261
262
/**
 * 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
 */
263
function pkg_required($name="") {
264
	$deps = array();
Dan McGee's avatar
Dan McGee committed
265
	if ($name != "") {
266
		$dbh = DB::connect();
267
		$q = "SELECT DISTINCT p.Name, PackageID FROM PackageDepends pd ";
Dan McGee's avatar
Dan McGee committed
268
		$q.= "JOIN Packages p ON pd.PackageID = p.ID ";
canyonknight's avatar
canyonknight committed
269
		$q.= "WHERE DepName = " . $dbh->quote($name) . " ";
Dan McGee's avatar
Dan McGee committed
270
		$q.= "ORDER BY p.Name";
canyonknight's avatar
canyonknight committed
271
		$result = $dbh->query($q);
272
		if (!$result) {return array();}
canyonknight's avatar
canyonknight committed
273
		while ($row = $result->fetch(PDO::FETCH_NUM)) {
274
275
276
277
278
279
			$deps[] = $row;
		}
	}
	return $deps;
}

280
281
282
283
284
285
286
/**
 * 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
 */
287
function pkg_sources($pkgid) {
288
	$sources = array();
289
290
	$pkgid = intval($pkgid);
	if ($pkgid > 0) {
291
		$dbh = DB::connect();
292
		$q = "SELECT Source FROM PackageSources ";
293
		$q.= "WHERE PackageID = " . $pkgid;
294
		$q.= " ORDER BY Source";
canyonknight's avatar
canyonknight committed
295
296
297
298
299
		$result = $dbh->query($q);
		if (!$result) {
			return array();
		}
		while ($row = $result->fetch(PDO::FETCH_NUM)) {
300
301
302
303
304
305
			$sources[] = $row[0];
		}
	}
	return $sources;
}

306
307
308
309
310
311
312
/**
 * 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
 */
313
function pkg_name_from_id($pkgids) {
314
315
316
	if (is_array($pkgids)) {
		$pkgids = sanitize_ids($pkgids);
		$names = array();
317
		$dbh = DB::connect();
canyonknight's avatar
canyonknight committed
318
319
320
321
322
		$q = "SELECT Name FROM Packages WHERE ID IN (";
		$q.= implode(",", $pkgids) . ")";
		$result = $dbh->query($q);
		if ($result) {
			while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
323
324
325
326
327
328
				$names[] = $row['Name'];
			}
		}
		return $names;
	}
	elseif ($pkgids > 0) {
329
		$dbh = DB::connect();
330
		$q = "SELECT Name FROM Packages WHERE ID = " . $pkgids;
canyonknight's avatar
canyonknight committed
331
332
333
		$result = $dbh->query($q);
		if ($result) {
			$name = $result->fetch(PDO::FETCH_NUM);
334
		}
canyonknight's avatar
canyonknight committed
335
		return $name[0];
336
337
338
	}
	else {
		return NULL;
339
340
341
	}
}

342
343
344
345
346
347
348
/**
 * 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
 */
349
function pkg_name_is_blacklisted($name) {
350
	$dbh = DB::connect();
canyonknight's avatar
canyonknight committed
351
352
353
	$q = "SELECT COUNT(*) FROM PackageBlacklist ";
	$q.= "WHERE Name = " . $dbh->quote($name);
	$result = $dbh->query($q);
354
355

	if (!$result) return false;
356
	return ($result->fetchColumn() > 0);
357
358
}

359
/**
360
 * Get the package details
361
 *
362
 * @param string $id The package ID to get description for
363
 *
364
365
 * @return array The package's details OR error message
 **/
366
function pkg_get_details($id=0) {
367
	$dbh = DB::connect();
368

369
370
371
372
373
	$q = "SELECT Packages.*, PackageBases.ID AS BaseID, ";
	$q.= "PackageBases.Name AS BaseName, PackageBases.CategoryID, ";
	$q.= "PackageBases.NumVotes, PackageBases.OutOfDateTS, ";
	$q.= "PackageBases.SubmittedTS, PackageBases.ModifiedTS, ";
	$q.= "PackageBases.SubmitterUID, PackageBases.MaintainerUID, ";
374
375
376
377
	$q.= "PackageBases.PackagerUID, PackageCategories.Category, ";
	$q.= "(SELECT COUNT(*) FROM PackageRequests ";
	$q.= " WHERE PackageRequests.PackageBaseID = Packages.PackageBaseID ";
	$q.= " AND PackageRequests.Status = 0) AS RequestCount ";
378
379
380
	$q.= "FROM Packages, PackageBases, PackageCategories ";
	$q.= "WHERE PackageBases.ID = Packages.PackageBaseID ";
	$q.= "AND PackageBases.CategoryID = PackageCategories.ID ";
Loui Chang's avatar
Loui Chang committed
381
	$q.= "AND Packages.ID = " . intval($id);
canyonknight's avatar
canyonknight committed
382
	$result = $dbh->query($q);
eric's avatar
eric committed
383

384
385
	$row = array();

canyonknight's avatar
canyonknight committed
386
	if (!$result) {
387
		$row['error'] = __("Error retrieving package details.");
388
389
	}
	else {
canyonknight's avatar
canyonknight committed
390
		$row = $result->fetch(PDO::FETCH_ASSOC);
eric's avatar
eric committed
391
		if (empty($row)) {
392
			$row['error'] = __("Package details could not be found.");
393
		}
394
395
396
397
398
399
400
401
402
403
404
	}

	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
405
 * @param array $row Package details retrieved by pkg_get_details()
406
407
408
409
 * @param string $SID The session ID of the visitor
 *
 * @return void
 */
410
function pkg_display_details($id=0, $row, $SID="") {
411
412
413
	global $AUR_LOCATION;
	global $USE_VIRTUAL_URLS;

414
	$dbh = DB::connect();
415

416
417
418
419
	if (isset($row['error'])) {
		print "<p>" . $row['error'] . "</p>\n";
	}
	else {
420
421
422
		$base_id = pkgbase_from_pkgid($id);
		$pkgbase_name = pkgbase_name_from_id($base_id);

423
424
425
426
427
428
429
		include('pkg_details.php');

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

Lukas Fleischer's avatar
Lukas Fleischer committed
430
		$limit = isset($_GET['comments']) ? 0 : 10;
431
432
		$include_deleted = has_credential(CRED_COMMENT_VIEW_DELETED);
		$comments = pkgbase_comments($base_id, $limit, $include_deleted);
433
434
		if (!empty($comments)) {
			include('pkg_comments.php');
eric's avatar
eric committed
435
436
437
438
		}
	}
}

Simo Leone's avatar
Simo Leone committed
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
/* 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:
457
 *          values: c - package category
Simo Leone's avatar
Simo Leone committed
458
459
460
461
 *                  n - package name
 *                  v - number of votes
 *                  m - maintainer username
 *    SeB- property that search string (K) represents
Andrea Scarpino's avatar
Andrea Scarpino committed
462
463
 *          values: n  - package name
 *                  nd - package name & description
464
 *                  x  - package name (exact match)
Simo Leone's avatar
Simo Leone committed
465
466
467
468
469
470
471
472
473
474
475
476
477
478
 *                  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
479
 *                     do_Delete - Delete (requires confirm_Delete to be set)
480
481
 *                     do_Notify - Enable notification
 *                     do_UnNotify - Disable notification
Simo Leone's avatar
Simo Leone committed
482
 */
483
function pkg_search_page($SID="") {
484
	$dbh = DB::connect();
Loui Chang's avatar
Loui Chang committed
485

486
487
488
489
	/*
	 * Get commonly used variables.
	 * TODO: Reduce the number of database queries!
	 */
Loui Chang's avatar
Loui Chang committed
490
	if ($SID)
491
		$myuid = uid_from_sid($SID);
492
	$cats = pkgbase_categories($dbh);
Loui Chang's avatar
Loui Chang committed
493

494
	/* Sanitize paging variables. */
Loui Chang's avatar
Loui Chang committed
495
	if (isset($_GET['O'])) {
496
497
		$_GET['O'] = max(intval($_GET['O']), 0);
	} else {
Loui Chang's avatar
Loui Chang committed
498
499
500
501
		$_GET['O'] = 0;
	}

	if (isset($_GET["PP"])) {
502
503
		$_GET["PP"] = bound(intval($_GET["PP"]), 50, 250);
	} else {
504
		$_GET["PP"] = 50;
Loui Chang's avatar
Loui Chang committed
505
506
	}

507
508
509
510
	/*
	 * 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
511

512
	/* Build the package search query. */
513
	$q_select = "SELECT ";
Loui Chang's avatar
Loui Chang committed
514
	if ($SID) {
515
		$q_select .= "CommentNotify.UserID AS Notify,
516
			   PackageVotes.UsersID AS Voted, ";
Loui Chang's avatar
Loui Chang committed
517
	}
518
	$q_select .= "Users.Username AS Maintainer,
Loui Chang's avatar
Loui Chang committed
519
	PackageCategories.Category,
520
	Packages.Name, Packages.Version, Packages.Description,
521
522
	PackageBases.NumVotes, Packages.ID, Packages.PackageBaseID,
	PackageBases.OutOfDateTS ";
Loui Chang's avatar
Loui Chang committed
523

524
	$q_from = "FROM Packages
525
526
	LEFT JOIN PackageBases ON (PackageBases.ID = Packages.PackageBaseID)
	LEFT JOIN Users ON (PackageBases.MaintainerUID = Users.ID)
527
	LEFT JOIN PackageCategories
528
	ON (PackageBases.CategoryID = PackageCategories.ID) ";
Loui Chang's avatar
Loui Chang committed
529
	if ($SID) {
530
		/* This is not needed for the total row count query. */
531
		$q_from_extra = "LEFT JOIN PackageVotes
532
		ON (PackageBases.ID = PackageVotes.PackageBaseID AND PackageVotes.UsersID = $myuid)
Loui Chang's avatar
Loui Chang committed
533
		LEFT JOIN CommentNotify
534
		ON (PackageBases.ID = CommentNotify.PackageBaseID AND CommentNotify.UserID = $myuid) ";
535
536
	} else {
		$q_from_extra = "";
Loui Chang's avatar
Loui Chang committed
537
538
	}

Dan McGee's avatar
Dan McGee committed
539
	$q_where = "WHERE 1 = 1 ";
540
541
542
543
	/*
	 * TODO: Possibly do string matching on category to make request
	 * variable values more sensible.
	 */
544
	if (isset($_GET["C"]) && intval($_GET["C"])) {
Lukas Fleischer's avatar
Lukas Fleischer committed
545
		$q_where .= "AND PackageBases.CategoryID = ".intval($_GET["C"])." ";
Loui Chang's avatar
Loui Chang committed
546
547
	}

548
549
	if (isset($_GET['K'])) {
		if (isset($_GET["SeB"]) && $_GET["SeB"] == "m") {
550
			/* Search by maintainer. */
canyonknight's avatar
canyonknight committed
551
			$q_where .= "AND Users.Username = " . $dbh->quote($_GET['K']) . " ";
Loui Chang's avatar
Loui Chang committed
552
		}
553
		elseif (isset($_GET["SeB"]) && $_GET["SeB"] == "s") {
554
			/* Search by submitter. */
555
			$q_where .= "AND SubmitterUID = " . intval(uid_from_username($_GET['K'])) . " ";
Loui Chang's avatar
Loui Chang committed
556
		}
557
		elseif (isset($_GET["SeB"]) && $_GET["SeB"] == "n") {
558
			/* Search by name. */
canyonknight's avatar
canyonknight committed
559
			$K = "%" . addcslashes($_GET['K'], '%_') . "%";
560
			$q_where .= "AND (Packages.Name LIKE " . $dbh->quote($K) . ") ";
Andrea Scarpino's avatar
Andrea Scarpino committed
561
		}
562
563
564
565
566
567
		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") {
568
			/* Search by name (exact match). */
569
			$q_where .= "AND (Packages.Name = " . $dbh->quote($_GET['K']) . ") ";
570
		}
571
572
573
574
		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
575
		else {
576
			/* Search by name and description (default). */
canyonknight's avatar
canyonknight committed
577
			$K = "%" . addcslashes($_GET['K'], '%_') . "%";
578
			$q_where .= "AND (Packages.Name LIKE " . $dbh->quote($K) . " OR ";
canyonknight's avatar
canyonknight committed
579
			$q_where .= "Description LIKE " . $dbh->quote($K) . ") ";
Loui Chang's avatar
Loui Chang committed
580
581
582
		}
	}

583
	if (isset($_GET["do_Orphans"])) {
584
		$q_where .= "AND MaintainerUID IS NULL ";
Loui Chang's avatar
Loui Chang committed
585
	}
586

587
	if (isset($_GET['outdated'])) {
588
		if ($_GET['outdated'] == 'on') {
589
			$q_where .= "AND OutOfDateTS IS NOT NULL ";
590
591
		}
		elseif ($_GET['outdated'] == 'off') {
592
			$q_where .= "AND OutOfDateTS IS NULL ";
593
		}
594
595
	}

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

598
	$q_sort = "ORDER BY ";
599
600
	$sort_by = isset($_GET["SB"]) ? $_GET["SB"] : '';
	switch ($sort_by) {
Loui Chang's avatar
Loui Chang committed
601
	case 'c':
602
		$q_sort .= "CategoryID " . $order . ", ";
Loui Chang's avatar
Loui Chang committed
603
604
		break;
	case 'v':
605
		$q_sort .= "NumVotes " . $order . ", ";
Loui Chang's avatar
Loui Chang committed
606
		break;
607
608
	case 'w':
		if ($SID) {
609
			$q_sort .= "Voted " . $order . ", ";
610
611
612
613
		}
		break;
	case 'o':
		if ($SID) {
614
			$q_sort .= "Notify " . $order . ", ";
615
616
		}
		break;
Loui Chang's avatar
Loui Chang committed
617
	case 'm':
618
		$q_sort .= "Maintainer " . $order . ", ";
Loui Chang's avatar
Loui Chang committed
619
620
		break;
	case 'a':
621
		$q_sort .= "ModifiedTS " . $order . ", ";
Loui Chang's avatar
Loui Chang committed
622
623
624
625
		break;
	default:
		break;
	}
626
	$q_sort .= " Packages.Name " . $order . " ";
Loui Chang's avatar
Loui Chang committed
627

628
	$q_limit = "LIMIT ".$_GET["PP"]." OFFSET ".$_GET["O"];
629

630
631
	$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
632

canyonknight's avatar
canyonknight committed
633
634
	$result = $dbh->query($q);
	$result_t = $dbh->query($q_total);
635
	if ($result_t) {
canyonknight's avatar
canyonknight committed
636
637
		$row = $result_t->fetch(PDO::FETCH_NUM);
		$total = $row[0];
638
639
640
641
	}
	else {
		$total = 0;
	}
Simo Leone's avatar
Simo Leone committed
642

643
	if ($result && $total > 0) {
644
645
		if (isset($_GET["SO"]) && $_GET["SO"] == "d"){
			$SO_next = "a";
Loui Chang's avatar
Loui Chang committed
646
647
		}
		else {
648
			$SO_next = "d";
Loui Chang's avatar
Loui Chang committed
649
		}
650
	}
Simo Leone's avatar
Simo Leone committed
651

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

655
	/* Calculation of pagination links. */
656
657
658
659
	$per_page = ($_GET['PP'] > 0) ? $_GET['PP'] : 50;
	$current = ceil($first / $per_page);
	$pages = ceil($total / $per_page);
	$templ_pages = array();
660

661
	if ($current > 1) {
662
663
		$templ_pages['&laquo; ' . __('First')] = 0;
		$templ_pages['&lsaquo; ' . __('Previous')] = ($current - 2) * $per_page;
664
	}
665

666
667
	if ($current - 5 > 1)
		$templ_pages["..."] = false;
668

669
670
671
	for ($i = max($current - 5, 1); $i <= min($pages, $current + 5); $i++) {
		$templ_pages[$i] = ($i - 1) * $per_page;
	}
672

673
674
	if ($current + 5 < $pages)
		$templ_pages["... "] = false;
675

676
	if ($current < $pages) {
677
678
		$templ_pages[__('Next') . ' &rsaquo;'] = $current * $per_page;
		$templ_pages[__('Last') . ' &raquo;'] = ($pages - 1) * $per_page;
679
	}
Simo Leone's avatar
Simo Leone committed
680

681
	include('pkg_search_form.php');
682

canyonknight's avatar
canyonknight committed
683
684
685
686
	if ($result) {
		while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
			$searchresults[] = $row;
		}
687
688
	}

689
690
	include('pkg_search_results.php');

Loui Chang's avatar
Loui Chang committed
691
	return;
eric's avatar
eric committed
692
693
}

694
695
696
697
698
699
700
/**
 * 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
701
702
703
704
705
function current_action($action) {
	return (isset($_POST['action']) && $_POST['action'] == $action) ||
		isset($_POST[$action]);
}

706
/**
707
708
709
710
711
 * Determine if sent IDs are valid integers
 *
 * @param array $ids IDs to validate
 *
 * @return array All sent IDs that are valid integers
712
713
714
715
716
717
718
719
720
721
722
723
 */
function sanitize_ids($ids) {
	$new_ids = array();
	foreach ($ids as $id) {
		$id = intval($id);
		if ($id > 0) {
			$new_ids[] = $id;
		}
	}
	return $new_ids;
}

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

745
746
747
748
/**
 * Add a dependency for a specific package to the database
 *
 * @param int $pkgid The package ID to add the dependency for
749
 * @param string $type The type of dependency to add
750
751
752
753
754
 * @param string $depname The name of the dependency to add
 * @param string $depcondition The  type of dependency for the package
 *
 * @return void
 */
755
function pkg_add_dep($pkgid, $type, $depname, $depcondition) {
756
	$dbh = DB::connect();
757
758
759
760
761
762
	$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
763
	$dbh->exec($q);
canyonknight's avatar
canyonknight committed
764
765
}

766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
/**
 * 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);
}

787
788
789
790
791
792
793
794
/**
 * 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
 */
795
function pkg_add_src($pkgid, $pkgsrc) {
796
	$dbh = DB::connect();
canyonknight's avatar
canyonknight committed
797
	$q = "INSERT INTO PackageSources (PackageID, Source) VALUES (";
canyonknight's avatar
canyonknight committed
798
	$q .= $pkgid . ", " . $dbh->quote($pkgsrc) . ")";
canyonknight's avatar
canyonknight committed
799

canyonknight's avatar
canyonknight committed
800
	$dbh->exec($q);
canyonknight's avatar
canyonknight committed
801
}
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844

/**
 * Creates a new group and returns its ID
 *
 * If the groups already exists, the ID of the already existing group is
 * returned.
 *
 * @param string $name The name of the group to create
 *
 * @return int The ID of the group
 */
function pkg_create_group($name) {
	$dbh = DB::connect();
	$q = sprintf("SELECT ID FROM Groups WHERE Name = %s", $dbh->quote($name));
	$result = $dbh->query($q);
	if ($result) {
		$grpid = $result->fetch(PDO::FETCH_COLUMN, 0);
		if ($grpid > 0) {
			return $grpid;
		}
	}

	$q = sprintf("INSERT INTO Groups (Name) VALUES (%s)", $dbh->quote($name));
	$dbh->exec($q);
	return $dbh->lastInsertId();
}

/**
 * Add a package to a group
 *
 * @param int $pkgid The package ID of the package to add
 * @param int $grpid The group ID of the group to add the package to
 *
 * @return void
 */
function pkg_add_grp($pkgid, $grpid) {
	$dbh = DB::connect();
	$q = sprintf("INSERT INTO PackageGroups (PackageID, GroupID) VALUES (%d, %d)",
		$pkgid,
		$grpid
	);
	$dbh->exec($q);
}
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887

/**
 * Creates a new license and returns its ID
 *
 * If the license already exists, the ID of the already existing license is
 * returned.
 *
 * @param string $name The name of the license to create
 *
 * @return int The ID of the license
 */
function pkg_create_license($name) {
	$dbh = DB::connect();
	$q = sprintf("SELECT ID FROM Licenses WHERE Name = %s", $dbh->quote($name));
	$result = $dbh->query($q);
	if ($result) {
		$licid = $result->fetch(PDO::FETCH_COLUMN, 0);
		if ($licid > 0) {
			return $licid;
		}
	}

	$q = sprintf("INSERT INTO Licenses (Name) VALUES (%s)", $dbh->quote($name));
	$dbh->exec($q);
	return $dbh->lastInsertId();
}

/**
 * Add a license to a package
 *
 * @param int $pkgid The package ID of the package
 * @param int $grpid The ID of the license to add
 *
 * @return void
 */
function pkg_add_lic($pkgid, $licid) {
	$dbh = DB::connect();
	$q = sprintf("INSERT INTO PackageLicenses (PackageID, LicenseID) VALUES (%d, %d)",
		$pkgid,
		$licid
	);
	$dbh->exec($q);
}
888
889
890
891
892
893
894
895
896
897
898

/**
 * Determine package information for latest package
 *
 * @param int $numpkgs Number of packages to get information on
 *
 * @return array $packages Package info for the specified number of recent packages
 */
function latest_pkgs($numpkgs) {
	$dbh = DB::connect();

Lukas Fleischer's avatar
Lukas Fleischer committed
899
900
	$q = "SELECT Packages.*, MaintainerUID, SubmittedTS ";
	$q.= "FROM Packages LEFT JOIN PackageBases ON ";
901
	$q.= "PackageBases.ID = Packages.PackageBaseID ";
902
	$q.= "ORDER BY SubmittedTS DESC ";
903
	$q.= "LIMIT " . intval($numpkgs);
904
905
	$result = $dbh->query($q);

906
	$packages = array();
907
908
909
910
911
912
913
914
	if ($result) {
		while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
			$packages[] = $row;
		}
	}

	return $packages;
}