f794c29496f6aa3a03faf9264e0eb8cf88804625
[glcas.git] / plugins / repo.php
1 <?php
2 $URL_HANDLERS["*"] = "GLCASRepo";
3 global $CRON_CLASSES;
4 $CRON_CLASSES["GLCASRepo"] = "GLCASRepo";
5
6 class GLCASRepo {
7         function __construct($config)
8         {
9                 $this->config = $config;
10                 if($this->config->getConfigVar("storagelocation") == false) {
11                         global $WEB_ROOT_FS;
12                         $storloc = "$WEB_ROOT_FS/../var/glcas/cache/";
13                         if(!file_exists($storloc)) mkdir($storloc);
14                         $this->config->setConfigVar("storagelocation", realpath($storloc));
15                         $this->config->saveConfig();
16                         error_log("set storage location, $storloc");
17                 }
18         }
19         
20         function cron()
21         {
22                 //echo "<pre>";
23                 $uconf = unserialize($this->config->getConfigVar("repodata"));
24                 $repostore = $this->config->getConfigVar("storagelocation");
25                 //print_r($uconf);
26                 //echo "</pre>";
27                 
28                 foreach($uconf as $rkey => $repo) {
29                         echo "Repo $rkey: ".$repo["desc"]."<br>";
30                         if(!isset($repo["expiretime"])) {
31                                 echo " - Expire time not set, setting to 2 days by default<br>";
32                                 $uconf[$rkey]["expiretime"] = 2;
33                                 $repo["expiretime"] = 2;
34                                 $this->config->setConfigVar("repodata", serialize($uconf));
35                                 $this->config->saveConfig();                            
36                         }
37                         
38                         if(!isset($repo["repotype"])) {
39                                 echo "<font color=\"red\">Repo type not set for repo, setting to yum</font><br>";
40                                 $uconf[$rkey]["repotype"] = "YUM";
41                                 $this->config->setConfigVar("repodata", serialize($uconf));
42                                 $this->config->saveConfig();                            
43                         } else if($repo["repotype"] == "YUM") {
44                                 if(file_exists("$repostore/$rkey/repodata/repoupdate.lock")) {
45                                         echo " - <font color=\"red\">Repo locked for update</font><br>";
46                                         
47                                 }
48                                 
49                                 // we still do this next bit, even if its locked because it may be a stray file
50                                 echo " - Expire time is ".$repo["expiretime"]." days, checking repo<br>";
51                                 error_log("checking $repostore/$rkey/repodata/repomd.xml");
52                                 $tdiff = time() - filemtime("$repostore/$rkey/repodata/repomd.xml");
53                                 $maxtdiff = $repo["expiretime"] * 24 * 3600;
54                                 if($tdiff > $maxtdiff) {
55                                         echo " - <font color=\"green\">updating repo</font><br>";
56                                         $this->updateRepo($rkey);
57                                 } else {
58                                         echo " - not updating repo<br>";
59                                 }
60                         } else if($repo["repotype"] == "APT") {
61                                 if(file_exists("$repostore/$rkey/update.lock")) {
62                                         echo " - <font color=\"red\">Repo locaked for update</font><br>";
63                                 }
64                                 echo " - Expire time is ".$repo["expiretime"]." days, checking repo<br>";
65                                 $maxtdiff = $repo["expiretime"] * 24 * 3600;
66                                 // now we check for outdated release files
67                                 $dh = opendir("$repostore/$rkey/dists/");
68                                 $needsupdate = false;
69                                 while(($fn = readdir($dh))!==false) {
70                                         if($fn != "." && $fn != "..") {
71                                                 if(file_exists("$repostore/$rkey/dists/$fn/Release")) {
72                                                         $tdiff = time() -  filemtime("$repostore/$rkey/dists/$fn/Release");
73                                                         if($tdiff > $maxtdiff) $needsupdate = true;
74                                                 }
75                                         }
76                                 }
77                                 if($needsupdate) {
78                                         echo " - Spawn updater<br>";
79                                         $this->updateRepo($rkey);
80                                 } else {
81                                         echo " - Up to date<br>";
82                                 }
83                         }
84                 }
85         }
86
87         function go($url)
88         {
89                 error_log("repo:go called");
90
91                 // figure out what we're doing
92                 switch($url) {
93                         case "list":
94                                 GLCASpageBuilder($this, "body");
95                                 break;
96                         default:
97                                 $this->getRepoForUrl($url);
98                 }
99         }
100
101         function body($url)
102         {
103                 // this is how this will work
104                 //$this->decodeUrl();
105                 if(strncasecmp("list", $url, 4)==0) {
106                         echo "i am the repo list";
107                         return;
108                 }
109                 echo "i am the repo, $url";
110         }
111
112
113         // TODO: rework this function
114         /*
115         * What i need to do is have a downloader function
116         * that can cope with lots of different shit
117         * but thats a pipe dream
118         *
119         * what *THIS* function needs to do is
120         * 1) figure out the repo
121         * 2) figure out the file in the repo
122         * 2.1) if its a directory, go to print directory
123         * 3) if the file exists, give it to the user (if a range is specified give the user the range)
124         * 4) if the file does not exist
125         *    - check if a tmp file exists
126         *    - attempt to get an exclusive flock
127         *    - if flock fails, donwload in progress
128         *    - if flock succeeds, truncate file and re-start download
129         *    - if a range request was made, send the range once available
130         *    - if range not available, sleep for 5 and check again.
131         *
132         * I dont want to code this from scratch, but i probably need to
133         */
134         function getRepoForUrl($url)
135         {
136                 $xurl = split("[/,]", $url);
137
138                 // first get the config
139                 $uconf = unserialize($this->config->getConfigVar("repodata"));
140                 $repostore = $this->config->getConfigVar("storagelocation");
141
142                 // preset matched to -1
143                 $matched = -1;
144
145                 // first we check for /repo/repoid as a url
146                 $startat = 0;
147                 if($xurl[0] == "repo") {
148                         $repid = $xurl[1];
149                         error_log("trying to get repo for repoid, $repid");
150                         if(isset($uconf[$repid])) {
151                                 $matched = ((int)($repid));
152                                 error_log("set matched, $matched, $repid");
153                                 $startat +=2;
154                         }
155                 }
156
157                 // now check for a prefix match
158                 $prematch = false;
159                 if($matched < 0) foreach($uconf as $key => $var) {
160                         $pre = $var["prefix"];
161                                 
162                         if($pre!="") {
163                                 //echo "Checking pre $pre against ".$xurl[0]."\n";
164                                 if(strcasecmp($pre, $xurl[0])==0) {
165                                         //echo "Matched pre\n";
166                                         $prematch = true;
167                                         $startat++;
168                                 }
169                         }
170                 }
171
172                 // next, check for a short url match
173                 if($matched < 0) foreach($uconf as $key => $var) {
174                         // if we matched a pre, then we check against the second url component
175                                 
176                         $short = $var["shorturl"];
177                                 
178                         if($short!="") {
179                                 //echo "Checking short $short against ".$xurl[$startat]."\n";
180                                 if(strcasecmp($xurl[$startat], $short)==0) {
181                                         //echo "Matched\n";
182                                         $matched = $key;
183                                         $startat++;
184                                 }
185                         }
186                 }
187
188                 // TODO: this deterministic bit
189                 // so far nothing has matched - what this next bit needs to do is try and "Determine" a repo from url
190                 // for eg, if a user gets /fedora/x86_64/os we need to return something appropriate
191                 if($matched < 0) {
192                         echo "No such repo<br>";
193                         header("HTTP/1.0 404 Not Found");
194                         return;
195                 }
196                 
197
198
199                 // something was matched, so now we reconstruct the file component of the url
200                 $file = "/";
201                 if(count($xurl) > $startat) for($i=$startat; $i < count($xurl); $i++) {
202                         $file .= "/".$xurl[$i];
203                 }
204
205                 // so, the ultimate url for the file we need is:
206                 $actualfile = "$repostore/$matched/$file";
207                 error_log("Atcualfile is $actualfile");
208                 
209                 // now check for a block in that repo
210                 if(isset($uconf[$matched]["blocklist"])) {
211                         foreach($uconf[$matched]["blocklist"] as $blockers) {
212                                 $rfile = ltrim($file, "/");
213                                 error_log("checking $blockers against $rfile");
214                                 if(preg_match("/$blockers/", $rfile) > 0) {
215                                         error_log("should block");
216                                         header("HTTP/1.0 404 Not Found");
217                                         return;
218                                 }
219                         }
220                 }
221                 
222                 // if its a directory, lets do a print
223                 if(is_dir($actualfile)) {
224                         $this->printDir($actualfile, $file, $url);
225                         return;
226                 }
227
228                 // check if the file exists and serve it up
229                 if(file_exists($actualfile) && !file_exists("$actualfile.size")) {
230                         $this->serveUpFile($actualfile, $matched);
231                         return;
232                 } else {
233                         // the file does not exist, we now need to go into "download" mode
234                         $remoteurl = $uconf[$matched]["url"]."/$file";
235                         $this->downloadAndServe($actualfile, $matched, $remoteurl);
236                         return;
237                 }
238         }
239
240         function serveUpFile($actualfile, $repoid)
241         {
242                 $uconf = unserialize($this->config->getConfigVar("repodata"));
243                 $repostore = $this->config->getConfigVar("storagelocation");
244
245                 // figure out the range header garbage that centos/redhat send
246                 if(isset($_SERVER["HTTP_RANGE"])) {
247                         // we're using ranges - screw you stupid installer
248                         $pr_range = preg_split("/[:\-=, ]+/", $_SERVER["HTTP_RANGE"]);
249                                 
250                         // cut up ranges
251                         $rangestart = $pr_range[1];
252                         $rangelength = $pr_range[2] - $pr_range[1] +1;
253                         $rangestr = $pr_range[1]."-".$pr_range[2];
254                         error_log("going ranges at $rangestart, $rangelength,".$rangesa[1].",".$rangesb[0]);
255                                 
256                         // now spit some headers
257                         header("HTTP/1.1 206 Partial Content");
258                         header("Content-Length: ".$rangelength);
259                                 
260
261                         header("Content-Range: bytes $rangestr/".filesize($actualfile));
262                                 
263                         // determine mime type
264                         $type = mime_content_type($actualfile);
265                                 
266                         // set mime type header
267                         header("Content-type: $type");
268                                 
269                         // open the local file (TODO: error check)
270                         $localfile = fopen($actualfile, "r");
271                         fseek($localfile, $rangestart, SEEK_SET);
272                                 
273                         // read in the data, god i hope its not big
274                         $data = fread($localfile, $rangelength);
275                                 
276                         // lastly, send data
277                         echo $data;
278                         flush();
279                                 
280                         // and close the file
281                         fclose($localfile);
282                         return;
283                 } else {
284
285                         // we're not using range's - good on you installer thingy
286                         header("Content-Length: ".filesize($actualfile));
287
288                         // set the mime type header
289                         $type = mime_content_type($actualfile);
290                         header("Content-type: $type");
291                                 
292                         // open the local file
293                         $localfile = fopen($actualfile, "r");
294                         if(!$localfile) {
295                                 error_log("normal upload went barf");
296                                 return;
297                         }
298                                 
299                         // iterate over its length, send 8k at a time
300                         while(!feof($localfile)) {
301                                 // read and send data
302                                 $data = fread($localfile, 32768);
303                                 echo $data;
304
305                                 // flush so the client sees the data
306                                 flush();
307                         }
308                                 
309                         // close the file
310                         fclose($localfile);
311                         return;
312                 }
313         }
314
315         // TODO: this is the function im working on
316         // the alternative to this function is that if a file is in the process of being
317         // downloaded, we simply serve from upstream... not a good idea tho unless we create
318         // a local proxy right here - this function is a race condition waiting to be had
319         // lets hope its a good one!
320         function downloadAndServe($filename, $repoid, $remoteurl)
321         {
322
323                 $this->startDownload($filename, $remoteurl);
324
325                 // give the proc a minute to get going
326                 sleep(2);
327                 clearstatcache();
328
329                 // get the configurations we need
330                 $uconf = unserialize($this->config->getConfigVar("repodata"));
331                 $repostore = $this->config->getConfigVar("storagelocation");
332
333
334
335                 // determine if we're ranged
336                 $ranged = false;
337                 $rangestart = 0;
338                 $rangelength = 0;
339                 $rangestr="";
340                 if(isset($_SERVER["HTTP_RANGE"])) {
341                         // we're using ranges - screw you stupid installer
342                                 
343                         $pr_range = preg_split("/[:\-=, ]+/", $_SERVER["HTTP_RANGE"]);
344                         error_log("got range ".$_SERVER["HTTP_RANGE"]." and ".print_r($pr_range, true));
345                                 
346                         // cut up ranges
347                         $rangestart = $pr_range[1];
348                         $rangelength = $pr_range[2] - $pr_range[1] +1;
349                         $rangestr = $pr_range[1]."-".$pr_range[2];
350                         error_log("going ranges at $rangestart, $rangelength, $rangestr");
351                         $ranged = true;
352                 }
353
354                 // open the local files
355
356                 // now, lets determine what state we're in
357                 // we're either - getting and sending
358                 // watching and sending
359                 // or a range (Getting and sending)
360                 // or a range (watching and sending)
361                 // TODO: it may be advicable to start the download as a seperate cli process rather then something goin on here
362                 // so it definitely cant be interrupted.
363                 
364                 // check for a 404 file and wait 2 if it exists - i should really check the timestamp for an updated
365                 // file, but thats too much effort for now: TODO: check timestamp on 404 file
366                 $slept = 0;
367                 while(!file_exists("$filename")) {
368                         clearstatcache();
369                         sleep(1);
370                         $slept += 1;
371                         error_log("Sleeping waiting for file");
372                         
373                         // if 404 file exists, we wait much less time
374                         if(file_exists("$filename.404") && $slept > 2) {
375                                 header("HTTP/1.0 404 Not Found");
376                                 return;
377                         }
378                         if($slept > 10) {
379                                 header("HTTP/1.0 404 Not Found");
380                                 return;
381                         } 
382                 }
383                 
384                 clearstatcache();
385                 if(is_dir($filename)) {
386                         
387                         header("Location: ".$_SERVER["REQUEST_URI"]."/");
388                         return;
389                 }
390                         
391
392                 // first, getting and sending - this is easy.
393                 if (!$ranged) {
394                                 
395                         $localfile = fopen($filename, "r");
396                                 
397                         // this is where the fun starts - but this one isnt too bad.
398                         error_log("OTHERDOWNLOAD: im another downloader, please work");
399                         if(file_exists("$filename.size")) $fsize = file_get_contents("$filename.size");
400                         else $fsize = filesize($filename);
401                         header("Content-Length: $fsize");
402                         $sgotten = 0;
403                         while(!feof($localfile)) {
404                                 $data = fread($localfile, 2048);
405                                 if(!$data) {
406                                         error_log("dollardata is pair shaped");
407                                 } else {
408                                         $sgotten += strlen($data);
409                                         if($sgotten > $fsize) {
410                                                 error_log("went plop at sgotten, $sgotten, $fsize");
411                                                 return;
412                                         }
413                                         echo $data;
414                                         flush();
415                                 }
416                         }
417                         fclose($localfile);
418                                 
419                         // need to think about this in pseudo code.
420                         // 1. close the file and wait for it to get to $sgotten + 2048 or $fsize
421                         $cursize = filesize($filename);                         
422                                 
423                         $upload_finished = false;
424                         while(!$upload_finished) {
425                                 while($cursize < $fsize && $cursize < ($sgotten+2048)) {
426                                         clearstatcache();
427                                         error_log("OTHERDOWNLOAD: halt, $cursize, $sgotten, $fsize");
428                                         // sleep until the the filesize is greater then what we're up to, or until the file is finished
429                                         sleep(1);
430                                         $cursize = filesize($filename);
431                                 }
432
433                                 error_log("OTHERDOWNLOAD: continue, $sgotten, $fsize");
434                                 // reopen local file - if it stopped existing, we need to deal with that
435                                 $localfile = fopen($filename, "r");
436
437                                 // UG, we need to ff, how could i forget that
438                                 fseek($localfile, $sgotten);
439
440                                 if(!$localfile) {
441                                         error_log("OTHERDOWNLOAD: something went plop");
442                                         return;
443                                 }
444
445                                 // now loop on the file until we have it at an eof
446                                 while(!feof($localfile)) {
447                                         $data = fread($localfile, 512);
448                                         if(!$data) {
449                                                 error_log("OTHERDOWNLOAD: dollar data went plop");
450                                         } else {
451                                                 $sgotten += strlen($data);
452                                                 echo $data;
453                                                 flush();
454                                         }
455                                 }
456                                 fclose($localfile);
457
458                                 if($sgotten >= $fsize) {
459                                         if($sgotten > $fsize) error_log("OTHERDOWNLOADER: finished but $sgotten, $fsize doesnt make senze");
460                                         $upload_finished = true;
461                                 }
462                                 // and we're done
463
464                         }
465                         error_log("OTHERDOWNLOADER: done with");
466                                 
467                         return;
468
469
470                                 
471                                 
472                         // Next painful bit
473                 } else {
474                         // and here too, yay, someone else is doing the
475                         // download, but we're the retards getting a range
476                         $sgotten = 0;
477                                 
478                         $sgatlen = $rangestart+$rangelength;
479                                 
480                         // the problem is here
481                         error_log("Downloader: going ranged as other");
482                         clearstatcache();
483                         if(file_exists($filename.".tmp.data.deleteme.size")) $contentlen = file_get_contents($filename.".tmp.data.deleteme.size");
484                         else $contentlen = filesize($filename);
485                         $contenttype = mime_content_type($filename);
486                         header("HTTP/1.1 206 Partial Content");
487                         header("Content-Length: $rangelength");
488                         header("Content-Range: bytes $rangestr/$contentlen");
489                         $contenttype = "Content-Type: application/x-rpm";
490                         
491                         error_log("$contenttype");
492                         header("$contenttype");
493                         
494                         
495                         clearstatcache();
496                                 
497                                 
498                         // first we wait until the file reaches $rangestart
499                         while(filesize("$filename") < $rangestart) {
500                                 sleep(1);
501                         }
502                                 
503                         // then we open the file and ff to rangestart
504                         $localfile = fopen($filename, "r");
505                         fseek($localfile, $rangestart);
506                                 
507                         $sgotten = 0;
508                         // need to think about this in pseudo code.
509                         // 1. close the file and wait for it to get to $sgotten + 2048 or $fsize
510                         $cursize = filesize($filename);
511                                 
512                                 
513                         $upload_finished = false;
514                         while(!$upload_finished) {
515                                 while($cursize < $sgatlen && $cursize < ($sgotten+2048)) {
516                                         clearstatcache();
517                                         error_log("OTHERDOWNLOAD: halt, $cursize, $sgotten, $contentlen");
518                                         // sleep until the the filesize is greater then what we're up to, or until the file is finished
519                                         sleep(1);
520                                         $cursize = filesize($filename);
521                                 }
522
523                                 error_log("OTHERDOWNLOAD: continue, $sgotten, $contentlen");
524                                 // reopen local file - if it stopped existing, we need to deal with that
525                                 $localfile = fopen($filename, "r");
526
527                                 // UG, we need to ff, how could i forget that
528                                 fseek($localfile, $sgotten+$rangestart);
529
530                                 if(!$localfile) {
531                                         error_log("OTHERDOWNLOAD: something went plop");
532                                         return;
533                                 }
534
535                                 // now loop on the file until we have it at sgatlen
536                                 while(!feof($localfile) && $sgotten < $rangelength) {
537                                         $left = $rangelength - $sgotten;
538                                         if($left > 512) $lenget = 512;
539                                         else $lenget = $left;
540                                         $data = fread($localfile, $lenget);
541                                         if(!$data) {
542                                                 error_log("OTHERDOWNLOAD: dollar data went plop");
543                                         } else {
544                                                 $sgotten += strlen($data);
545                                                 echo $data;
546                                                 flush();
547                                         }
548                                 }
549                                 fclose($localfile);
550
551                                 if($sgotten >= $rangelength) {
552                                         if($sgotten > $rangelength) error_log("OTHERDOWNLOADER: finished but $sgotten, $fsize doesnt make senze");
553                                         $upload_finished = true;
554                                 }
555                                 // and we're done
556
557                         }
558                         error_log("OTHERDOWNLOADER: done with");
559                                 
560                         return;
561                                 
562                 }
563
564
565                 return;
566         }
567
568         function startDownload($file, $url)
569         {
570                 
571                 error_log("background downloader, start");
572                 global $WEB_ROOT_FS, $URL_HANDLERS, $BASE_URL;
573                 if(file_exists("$WEB_ROOT_FS/../bin/downloadfile.php")) {
574                         $scall = "/usr/bin/php $WEB_ROOT_FS/../bin/downloadfile.php '$url' '$file' > /tmp/dllog 2>&1 &";
575                         system($scall);
576                 } else {
577                         error_log("cant find download helper... dieing");
578                 }
579         }
580
581         // this is a nightmare
582
583
584         function printDir($dir, $localfile, $baseurl)
585         {
586                 $localfile = preg_replace("/\/\/+/", "/", $localfile);
587                 $uri = $_SERVER["REQUEST_URI"];
588                 $content = "";
589                 if(is_dir($dir)) {
590                         $content .= "<html><head><title>Index of $localfile</title></head><body><h1>Index of $localfile</h1>";
591                         $content .= "<table>";
592                         $dh = opendir($dir);
593                         $dirn = 0;
594                         $filen = 0;
595                         while(($file = readdir($dh))!==false) {
596                                 if($file != "." && $file != "..") {
597                                         if(is_dir("$dir/$file")) {
598                                                 $dirlist[$dirn++] = "$file";
599                                         } else {
600                                                 $filelist[$filen++] = "$file";
601                                         }
602                                 }
603                         }
604                         if(isset($dirlist)) {
605                                 sort($dirlist);
606                                 foreach($dirlist as $dirs) {
607                                         $icon = "/icons/folder.png";
608                                         $content .= "<tr><td><img src=\"$icon\"></td><td><a href=\"$uri/$dirs\">$dirs</a></td><td></td></tr>";
609                                 }
610                         }
611                         if(isset($filelist)) {
612                                 sort($filelist);
613                                 foreach($filelist as $files) {
614                                         $fsize = filesize("$dir/$files");
615                                         $icon = "/icons/text.png";
616                                         $content .= "<tr><td><img src=\"$icon\"></td><td><a href=\"$uri/$files\">$files</a></td><td>$fsize</td></tr>";
617                                 }                               
618                         }
619                         $content .= "</table></body></html>";
620                                 
621                         GLCASpageBuilder(null, null, $content);
622                                 
623                 } else return false;
624         }
625         
626         function getRepoDetailsApt($url)
627         {
628                 $action1 = $url."/dists";
629                 
630                 // we just want to make sure it exists really
631                 error_log("in repo details apt for $url");
632                 if(!glcas_isRemoteDir($action1)) {
633                         //echo "I cant find any valid APT dists's at $url<br>";
634                         return false;
635                 }
636                 
637                 // ok, now scan for ubuntu dists as
638                 $kos = getKnownOSList();
639                 
640                 $repos = 0;
641                 $existing_repo["isrepo"] = true;
642                 foreach($kos["apt"] as $key => $val) {
643                         //echo "<br>$key, $val<br>";
644                         //echo "now check, $action1/$key";
645                         if(glcas_isRemoteDir($action1."/$key")) {
646                                 $existing_repos["knownrepo"][$repos]["name"] = $key;
647                                 //echo "Found Distro $val<br>";
648                                 if(glcas_fileExists($action1."/$key/Contents-amd64.gz")) $existing_repos["knownrepo"][$repos]["amd64"] = true;
649                                 else $existing_repos["knownrepo"][$repos]["amd64"] = false;
650                                 if(glcas_fileExists($action1."/$key/Contents-i386.gz")) $existing_repos["knownrepo"][$repos]["i386"] = true;
651                                 else $existing_repos["knownrepo"][$repos]["i386"] = false;
652                                 $repos++;
653                                 
654                         }
655                 }
656                 $existing_repos["nrepos"] = $repos;
657                 
658                 // TODO: these need to be "calculated"
659                 $existing_repos["distros"] = "Ubuntu, Debian";
660                 $existing_repos["versions"] = "8.04LTS, 9.10, 10.04LTS, 10.10, 11.04, 11.10";
661                 $existing_repos["arch"] = "x86_64, i386";
662                 
663                 
664                 return $existing_repos;
665
666         }
667
668         function getRepoDetailsYum($url, $ismirrorlist=false)
669         {
670                 $actionurl = $url."/repodata/repomd.xml";
671
672                 error_log("Getting for action of $actionurl");
673
674                 $ld = file_get_contents($actionurl);
675
676                 // so here we try and get what this repository provides (os, version, arch), for yum this
677                 // should come straight off the url... i.e. centos/6.0/os/x86_64/ (centos, 6.0, base os, 64bit arch)
678
679                 if(!$ld) return false;
680
681                 // ok, now we tokenize the url and try and guess at the content
682                 $spurl = explode("/", $url);
683
684                 // first, find the OS
685                 $kos = getKnownOSList();
686                 $glt["OS"] = "unknown";
687                 $glt["verison"] = "unknown";
688                 $glt["arch"] = "unknown";
689                 $glt["other"] = "unknown";
690                 foreach($spurl as $comp) {
691                                 
692                         // find a name
693                         foreach($kos["os"]["short"] as $kosname => $koslong) {
694                                 //error_log("Comparing $kosname and $koslong with $comp");
695                                 if(strcasecmp($kosname, $comp) == 0) {
696                                         //error_log("got $kosname, $koslong for $comp in $url");
697                                         //echo "<pre>inone\n"; print_r($koslong); echo "</pre>";
698                                         $glt["OS"] = $koslong;
699                                 }
700                         }
701                                 
702                         // find a version, we assume its going to be something [numbers] and a . (optional)
703                         if(preg_match("/^[0-9.]+$/", $comp)>0) {
704                                 //error_log("version match of $comp");
705                                 $glt["version"] = $comp;
706                         }
707                                 
708                         // now architecture, this can be either i?86 or x86_64 - can also be arm or otherwise, but lets just go with this for now
709                         foreach($kos["arch"] as $archinter => $archname ) {
710                                 //error_log("Comparing $archinter, $archname with $comp");
711                                 if(strcasecmp($archname, $comp) == 0) {
712                                         //error_log("arch match of $archname with $comp");
713                                         $glt["arch"] = $archname;
714                                 }
715                         }
716                                 
717                         // other is a bt harder, we really have to guess at this one
718                         if(strcasecmp("os", $comp) == 0) $glt["other"] = "OS";
719                         if(strcasecmp("update", $comp) == 0) $glt["other"] = "Updates";
720                         if(strcasecmp("updates", $comp) == 0) $glt["other"] = "Updates";
721                         if(strcasecmp("everything", $comp) == 0) $glt["other"] = "OS";
722                 }
723
724                         
725                 return $glt;
726         }
727
728         function deleteRepo($rkey)
729         {
730                 $uconf = $this->config->getConfigVar("repodata");
731                 $repostore = $this->config->getConfigVar("storagelocation");
732
733                 if($uconf !== false) {
734                         $conf = unserialize($uconf);
735                         foreach($conf as $key => $vla) {
736                                 if($key == $rkey) {
737                                         unset($conf["$rkey"]);
738                                         $nconf = serialize($conf);
739                                         system("rm -rf $repostore/$key");
740                                         error_log("remove repo as $rkey");
741                                         $this->config->setConfigVar("repodata", $nconf);
742                                         $this->config->saveConfig();
743                                 }
744                         }
745                 }
746         }
747
748         function addRepo($desc, $os, $version, $arch, $other, $shorturl, $prefix, $repurl, $repotype, $init, $expiretime, $blocklist=null)
749         {
750                 $uconf = $this->config->getConfigVar("repodata");
751
752                 $cs["desc"] = $desc;
753                 $cs["os"] = $os;
754                 $cs["version"] = $version;
755                 $cs["arch"] = $arch;
756                 $cs["other"] = $other;
757                 $cs["shorturl"] = $shorturl;
758                 $cs["prefix"] = $prefix;
759                 $cs["url"] = $repurl;
760                 $cs["repotype"] = $repotype;
761                 $cs["expiretime"] = $expiretime;
762                 if($blocklist != null) {
763                         $cs["blocklist"] = $blocklist;
764                 }
765
766
767                 $ckey = 0;
768                 if($uconf !== false) {
769                         $conf = unserialize($uconf);
770                         foreach($conf as $key => $val) {
771                                 $ckey = $key;
772                         }
773                         $ckey++;
774                 }
775
776                 $conf[$ckey] = $cs;
777
778                 $nconf = serialize($conf);
779
780                 error_log("add repo as $ckey");
781                 $this->config->setConfigVar("repodata", $nconf);
782                 $this->config->saveConfig();
783
784                 // now create the base structure in the repo
785                 $repostore = $this->config->getConfigVar("storagelocation");
786
787
788                 // now call update repo
789                 if($init) $this->updateRepoYum($ckey);
790         }
791
792         function updateRepo($repokey)
793         {
794                 // we only do yum yet
795                 $repod = $this->getRepo($repokey);
796                 
797                 error_log("in update repo");
798
799                 if($repod["repotype"] == "YUM") $this->updateRepoYum($repokey);
800                 if($repod["repotype"] == "APT") $this->updateRepoApt($repokey);
801         }
802         
803         function updateRepoApt($repokey)
804         {
805                 $repostore = $this->config->getConfigVar("storagelocation");
806
807                 $repod = $this->getRepo($repokey);
808
809                 $repourl = $repod["url"];
810
811                 if(!file_exists("$repostore/$repokey")) {
812                         mkdir("$repostore/$repokey");
813                 }
814                 
815                 if(!file_exists("$repostore/$repokey/dists/")) {
816                         mkdir("$repostore/$repokey/dists/");
817                         // no point trying to update if we have no dists directory
818                         return;
819                 }
820                 
821
822                 error_log("background apt repo update, start");
823                 global $WEB_ROOT_FS, $URL_HANDLERS, $BASE_URL;
824                 if(file_exists("$WEB_ROOT_FS/../bin/downloadfile.php")) {
825                         $scall = "/usr/bin/php $WEB_ROOT_FS/../bin/updateaptrepo.php '$repourl' '$repostore/$repokey/' > /tmp/updateaptrepo.$repokey.log 2>&1 &";
826                         system($scall);
827                 } else {
828                         error_log("cant find download apt helper... dieing");
829                 }
830         }
831
832         function updateRepoYum($repokey)
833         {
834                 $repostore = $this->config->getConfigVar("storagelocation");
835
836                 $repod = $this->getRepo($repokey);
837
838                 $repourl = $repod["url"];
839
840                 if(!file_exists("$repostore/$repokey")) {
841                         mkdir("$repostore/$repokey");
842                 }
843
844                 if(!file_exists("$repostore/$repokey/repodata")) {
845                         mkdir("$repostore/$repokey/repodata");
846                 }
847                 
848                 error_log("background yum repo update, start");
849                 global $WEB_ROOT_FS, $URL_HANDLERS, $BASE_URL;
850                 if(file_exists("$WEB_ROOT_FS/../bin/downloadfile.php")) {
851                         $scall = "/usr/bin/php $WEB_ROOT_FS/../bin/updateyumrepo.php '$repourl' '$repostore/$repokey/' > /tmp/updateyumrepo.$repokey.log 2>&1 &";
852                         system($scall);
853                 } else {
854                         error_log("cant find download yum helper... dieing");
855                 }
856                 
857
858                 //ignore_user_abort(true);
859         }
860
861         function getRepo($id)
862         {
863                 $uconf = $this->config->getConfigVar("repodata");
864                 if($uconf !== false) {
865                         $lconf = unserialize($uconf);
866                         return $lconf[$id];
867                 } else return false;
868
869         }
870
871         function getRepos()
872         {
873                 $uconf = $this->config->getConfigVar("repodata");
874                 if($uconf !== false) {
875                         return unserialize($uconf);
876                 } else return false;
877
878         }
879
880         private $config;
881 }
882
883 ?>