1 <?php
2
3 $version = "3.0";
4
5 require('DB.php');
6
7 $dbhandle = "sqlite:////home/crux/public_html/local/portdb.db";
8
9 function nospam($mail) {
10 $mail = preg_replace("/\@/", " at ", $mail);
11 $mail = preg_replace("/\./", " dot ", $mail);
12 return htmlspecialchars($mail);
13 }
14
15 function sanitize($str) {
16 return $str;
17 }
18
19 function localrepo($name) {
20 if (is_dir("/home/crux/git-to-rsync-working-copy/crux-".$version."/{$name}")) {
21 return "http://crux.nu/ports/crux-".$version."/{$name}/";
22 }
23 else {
24 return "";
25 }
26 }
27
28 class Repo
29 {
30 public $name;
31 public $maintainer;
32 public $type;
33 public $url;
34 public $count;
35
36 function __construct($row) {
37 $this->name = trim($row["collname"]);
38 $this->maintainer = trim($row["maintainer"]);
39 $this->type = trim($row["colltype"]);
40 $this->url = trim($row["url"]);
41 $this->count = trim($row["tot"]);
42 }
43
44 function toHTML() {
45 return "<td><a href=\"?a=repo&q={$this->name}\">{$this->name}</a></td>
46 <td>{$this->count}</td>
47 <td><a href=\"?a=getup&q={$this->name}\">{$this->type}</a></td>
48 <td>{$this->nospam()}</td>
49 <td>{$this->urlToHTML()}</td>";
50 }
51
52 function toXML() {
53 return "<repo>
54 <name>{$this->name}</name>
55 <maintainer>{$this->nospam()}</maintainer>
56 <type>{$this->type}</type>
57 <url>{$this->url}</url>
58 <ports>{$this->count}</ports>
59 </repo>";
60 }
61
62 function urlToHTML() {
63 if ($this->type == "httpup") {
64 return "<a href=\"{$this->url}\">{$this->url}</a>";
65 }
66 else {
67 return $this->url;
68 }
69 }
70
71 function nospam() {
72 return nospam($this->maintainer);
73 }
74 }
75
76 class Port
77 {
78 public $name;
79 public $repo;
80
81 function __construct($row) {
82 $this->name = trim($row["portname"]);
83 $this->repo = new Repo($row);
84 }
85
86 function toXML() {
87 return "<port>
88 <name>{$this->name}</name>
89 <repo>{$this->repo->name}</repo>
90 {$this->filesToXML()}
91 <command>{$this->downloadCommand()}</command>
92 </port>";
93
94 }
95
96 function toHTML() {
97 return "<td>{$this->name}</td>
98 <td><a href=\"?a=repo&q={$this->repo->name}\">{$this->repo->name}</a></td>
99 <td>{$this->filesToHTML()}</td>
100 <td>{$this->downloadCommand()}</td>";
101 }
102
103 function filesToXML() {
104 $xml = "";
105 if ($this->repo->type == "httpup") {
106 $base_url = "{$this->repo->url}";
107 }
108 else {
109 $base_url = localrepo($this->repo->name);
110 }
111 if ($base_url != "") {
112 $base_url = chop($base_url, "/");
113 $xml = "<files>";
114 $xml .= "<pkgfile>{$base_url}/{$this->name}/Pkgfile</pkgfile>";
115 $xml .= "<footprint>{$base_url}/{$this->name}/.footprint</footprint>";
116 $xml .= "<md5sum>{$base_url}/{$this->name}/.md5sum</md5sum>";
117 $xml .= "</files>";
118 }
119 return $xml;
120 }
121
122 function filesToHTML() {
123 $html = "";
124 if ($this->repo->type == "httpup") {
125 $base_url = "{$this->repo->url}";
126 }
127 else {
128 $base_url = localrepo($this->repo->name);
129 }
130 if ($base_url != "") {
131 $base_url = chop($base_url, "/");
132 $html = "<a href=\"{$base_url}/{$this->name}/Pkgfile\">P</a> ";
133 $html .= "<a href=\"{$base_url}/{$this->name}/.footprint\">F</a> ";
134 $html .= "<a href=\"{$base_url}/{$this->name}/.md5sum\">M</a>";
135 }
136 return $html;
137 }
138
139 function downloadCommand() {
140 switch ($this->repo->type) {
141 case "httpup":
142 return "httpup sync {$this->repo->url}#{$this->name} {$this->name}";
143 case "rsync":
144 return "rsync -aqz {$this->repo->url}{$this->name}/ {$this->name}";
145 default:
146 return "unknown repo type";
147 }
148 }
149 }
150
151 class Duplicate
152 {
153 public $name;
154 public $count;
155
156 function __construct($row) {
157 $this->name = $row["portname"];
158 $this->count = $row["dup"];
159 }
160
161 function toHTML() {
162 return "<td>{$this->name}</td>
163 <td>Found <a href=\"?a=search&q={$this->name}&s=true\">{$this->count} in repository</a></td>";
164 }
165
166 function toXML() {
167 return "<duplicate>
168 <name>{$this->name}</name>
169 <count>{$this->count}</count>
170 </duplicate>";
171 }
172 }
173
174 class PortDb
175 {
176 public $db;
177 public $last_result;
178
179 function __construct($dbhandle) {
180 $this->db =& DB::connect($dbhandle);
181 if (DB::isError($this->db)) die ("Can not connect to database");
182 $this->db->setFetchMode(DB_FETCHMODE_ASSOC);
183 }
184
185 function lazy_programmer() {
186 die("LAZY PROGRAMMER ERROR");
187 }
188
189 function getQuery() {
190 try {
191 $sth = $this->db->prepare($this->sql);
192 $args = func_get_args();
193 $res = $this->db->execute($sth, $args);
194 if (DB::isError($res)) die ($res->getUserInfo());
195 $this->last_result = array();
196 while ($row =& $res->fetchRow()) {
197 array_push($this->last_result, $row);
198 }
199 return $this->last_result;
200 }
201 catch (Exception $exception) {
202 die($exception->getMessage());
203 }
204 }
205
206 function doQuery() {
207 $this->lazy_programmer();
208 }
209
210 function htmlHeader() {
211 return file_get_contents("header.html");
212 }
213
214 function htmlFooter() {
215 return file_get_contents("footer.html");
216 }
217
218 function toHTML($start, $headers, $items) {
219 $html = $this->htmlHeader();
220 $html .= $start;
221 $html .= "<table class=\"listing\">";
222 $html .= "<thead><tr>";
223 foreach ($headers as $header) {
224 $html .= "<th>{$header}</th>";
225 }
226 $html .= "</tr></thead>";
227 foreach ($items as $item) {
228 $html .= "<tr>" . $item->toHTML() . "</tr>";
229 }
230 $html .= "</table>";
231 $html .= $this->htmlFooter();
232 return $html;
233 }
234
235 function toXML($root, $items) {
236 header("Content-type: text/xml");
237 $xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
238 $xml .= "<{$root}>";
239 foreach ($items as $item) {
240 $xml .= $item->toXML();
241 }
242 $xml .= "</{$root}>";
243 return $xml;
244 }
245 }
246
247 class RepoList extends PortDb
248 {
249 public $sql = 'select collname,maintainer,colltype,url,count(*) as tot from collections
250 join ports on collection=collname
251 group by collname order by collections.collid';
252
253 function doQuery() {
254 $rows = $this->getQuery();
255 $repos = array();
256 foreach($rows as $row) {
257 $repo = new Repo($row);
258 array_push($repos, $repo);
259 }
260 return $repos;
261 }
262
263 function toXML($repos) {
264 return parent::toXML("repos", $repos);
265 }
266
267 function toHTML($repos) {
268 $start = "<h2>Overview of available repositories</h2>";
269 $headers = array("Repo Name", "# ports", "Type", "Maintainer", "Repo URL");
270 return parent::toHtml($start, $headers, $repos);
271 }
272 }
273
274 class PortList extends PortDb
275 {
276 public $sql = "select ports.portname as portname,
277 collections.collname as collname,
278 collections.maintainer as maintainer,
279 collections.colltype as colltype,
280 collections.url as url
281 from ports join collections on collection=collname
282 where collection = ? order by portname";
283
284 function doQuery($repo) {
285 $rows = $this->getQuery($repo);
286 $ports = array();
287 foreach ($rows as $row) {
288 $port = new Port($row);
289 array_push($ports, $port);
290 }
291 return $ports;
292 }
293
294 function toXML($ports) {
295 return parent::toXML("ports", $ports);
296 }
297
298 function toHTML($ports) {
299 $repo = $ports[0]->repo->name;
300 $start = "<h2>Ports in repository $repo <a href=\"?a=getup&q={$repo}\">(get sync file)</a></h2>";
301 $headers = array("Port","Collection","Files","Download command");
302 return parent::toHTML($start, $headers, $ports);
303 }
304 }
305
306 class SearchList extends PortList
307 {
308 public $strict = false;
309 public $query = '';
310 public $sql;
311
312 function __construct($dbhandle, $strict) {
313 parent::__construct($dbhandle);
314 if ($strict == "true") $this->strict = true;
315 $sql = "select ports.portname as portname,
316 collections.collname as collname,
317 collections.maintainer as maintainer,
318 collections.colltype as colltype,
319 collections.url as url
320 from ports join collections on collection=collname ";
321 if ($this->strict) {
322 $this->sql = $sql . "where portname=? ";
323 }
324 else {
325 $this->sql = $sql . "where portname like ? ";
326 }
327 $this->sql .= "order by portname, collection";
328 }
329
330 function htmlHeader() {
331 $html = parent::htmlHeader();
332 $html .= '<h2>Simple port search</h2>
333 <p>Search for ports by name</p>
334 <form name="searchform" method="get" action="'.getenv("SCRIPT_NAME").'">
335 <input name="q" value="'.$this->query.'" />
336 <input type="hidden" name="a" value="search" />
337 <input value="search" type="submit" />
338 </form>';
339 return $html;
340 }
341
342 function doQuery($query) {
343 $this->query = $query;
344 if ($query) {
345 if (! $this->strict) $query = "%{$query}%";
346 return parent::doQuery($query);
347 }
348 return array();
349 }
350
351 function toHTML($ports) {
352 if ($this->query) {
353 $start = ""; #<h2>Search results for '{$this->query}'</h2>";
354 $headers = array("Port","Collection","Files","Download command");
355 return PortDb::toHTML($start, $headers, $ports);
356 }
357 return $this->htmlHeader() . $this->htmlFooter();
358 }
359 }
360
361 class DuplicateList extends PortDb
362 {
363 public $sql = "select portname, count(*) as dup
364 from ports group by portname
365 having dup>1
366 order by dup desc";
367
368 function doQuery() {
369 $rows = $this->getQuery();
370 $dups = array();
371 foreach ($rows as $row) {
372 $dup = new Duplicate($row);
373 array_push($dups, $dup);
374 }
375 return $dups;
376 }
377
378 function toHTML($duplicates) {
379 $start = "<h2>List of duplicate ports</h2>";
380 $headers = array("Port", "# of duplicates");
381 return parent::toHTML($start, $headers, $duplicates);
382 }
383
384 function toXML($duplicates) {
385 return parent::toXML("duplicates",$duplicates);
386 }
387 }
388
389 class RegisterPage
390 {
391 function toHTML() {
392 return PortDb::htmlHeader() . $this->contents() . PortDb::htmlFooter();
393 }
394
395 function contents() {
396 return file_get_contents("register.html");
397 }
398 }
399
400 class GetUp extends PortDb
401 {
402 public $sql = "select collname,maintainer,colltype,url
403 from collections where collname=?";
404 public $repo;
405
406 function doQuery($repo) {
407 $rows = $this->getQuery($repo);
408 if (count($rows) != 1) die ("Could not generate file");
409 return new Repo($rows[0]);
410 }
411
412 function toHTML($repo) {
413 header('Content-type: text/plain');
414 header('Content-Disposition: attachment; filename="'.$repo->name.".".$repo->type.'"');
415 $html = "# Collection ".$repo->name. ", by ".$repo->nospam()."\n";
416 $html .= "# File generated by the CRUX portdb http://crux.nu/portdb/"."\n\n";
417 if ($repo->type == "httpup") {
418 $html .= "ROOT_DIR=/usr/ports/" . $repo->name."\n";
419 $html .= "URL=" . $repo->url."\n";
420 } else {
421 $ar = explode('::', $repo->url);
422 $html .= "host=" . $ar[0]."\n";
423 $html .= "collection=" . $ar[1]."\n";
424 $html .= "destination=/usr/ports/" . $repo->name."\n";
425 }
426 return $html;
427 }
428
429 function toXML($repo) {
430 return $this->toHTML($repo);
431 }
432 }
433
434 $action = sanitize($_GET['a']);
435 $query = sanitize($_GET['q']);
436 $format = sanitize($_GET['f']);
437 $strict = sanitize($_GET['s']);
438
439 switch ($action) {
440 case "repo":
441 $portdb = new PortList($dbhandle);
442 break;
443 case "search":
444 $portdb = new SearchList($dbhandle,$strict);
445 break;
446 case "dups":
447 $portdb = new DuplicateList($dbhandle);
448 break;
449 case "getup":
450 $portdb = new GetUp($dbhandle);
451 break;
452 case "register":
453 $portdb = new RegisterPage();
454 echo $portdb->toHTML();
455 exit;
456 default:
457 $portdb = new RepoList($dbhandle);
458 }
459
460 $result = $portdb->doQuery($query);
461
462 switch ($format) {
463 case "xml":
464 echo $portdb->toXML($result);
465 break;
466 default:
467 echo $portdb->toHTML($result);
468 }
469 ?>
|