2 $URL_HANDLERS["*"] = "GLCASRepo";
6 function __construct($config)
8 $this->config = $config;
9 if($this->config->getConfigVar("storagelocation") == false) {
11 $storloc = "$WEB_ROOT_FS/../var/glcas/cache/";
12 if(!file_exists($storloc)) mkdir($storloc);
13 $this->config->setConfigVar("storagelocation", realpath($storloc));
14 $this->config->saveConfig();
15 error_log("set storage location, $storloc");
21 error_log("repo:go called");
23 // figure out what we're doing
26 GLCASpageBuilder($this, "body");
29 $this->getRepoForUrl($url);
35 // this is how this will work
37 if(strncasecmp("list", $url, 4)==0) {
38 echo "i am the repo list";
41 echo "i am the repo, $url";
45 // TODO: rework this function
47 * What i need to do is have a downloader function
48 * that can cope with lots of different shit
49 * but thats a pipe dream
51 * what *THIS* function needs to do is
52 * 1) figure out the repo
53 * 2) figure out the file in the repo
54 * 2.1) if its a directory, go to print directory
55 * 3) if the file exists, give it to the user (if a range is specified give the user the range)
56 * 4) if the file does not exist
57 * - check if a tmp file exists
58 * - attempt to get an exclusive flock
59 * - if flock fails, donwload in progress
60 * - if flock succeeds, truncate file and re-start download
61 * - if a range request was made, send the range once available
62 * - if range not available, sleep for 5 and check again.
68 // this is a nightmare
69 function getRepoForUrl($url)
71 // the way we breakdown a url is to explode it
72 $xurl = split("[/,]", $url);
74 // we first check if [0] is a prefix
75 // if now, we check for it being a shorturl (lets just do that for now)
76 $uconf = unserialize($this->config->getConfigVar("repodata"));
77 $repostore = $this->config->getConfigVar("storagelocation");
81 // first we check for /repo/repoid as a url
83 if($xurl[0] == "repo") {
85 error_log("trying to get repo for repoid, $repid");
86 if(isset($uconf[$repid])) {
87 $matched = ((int)($repid));
88 error_log("set matched, $matched, $repid");
95 if($matched < 0) foreach($uconf as $key => $var) {
96 $pre = $var["prefix"];
99 //echo "Checking pre $pre against ".$xurl[0]."\n";
100 if(strcasecmp($pre, $xurl[0])==0) {
101 //echo "Matched pre\n";
109 if($matched < 0) foreach($uconf as $key => $var) {
110 // if we matched a pre, then we check against the second url component
112 $short = $var["shorturl"];
115 //echo "Checking short $short against ".$xurl[$startat]."\n";
116 if(strcasecmp($xurl[$startat], $short)==0) {
125 echo "No such repo<br>";
130 // now we find an actual file
132 if(count($xurl) > $startat) for($i=$startat; $i < count($xurl); $i++) {
133 $file .= "/".$xurl[$i];
136 // now we want to find repostore/$matched/$file;
137 $actualfile = "$repostore/$matched/$file";
138 error_log("Atcualfile is $actualfile");
139 //echo "Start file for $actualfile\n";
141 // first check any directories in $file are in existence
142 $splfile = explode("/", $file);
143 if(count($splfile) > 1) {
144 $tomake = "$repostore/$matched/";
145 for($i = 0; $i < count($splfile)-1; $i++) {
146 $tomake .= "/".$splfile[$i];
147 //error_log("making directory $tomake");
148 if(!is_dir($tomake)) mkdir($tomake);
152 $reqhead = print_r($_REQUEST, true);
153 $sevhead = print_r($_SERVER, true);
155 error_log("req $reqhead");
156 error_log("sev $sevhead");
161 if(isset($_SERVER["HTTP_RANGE"])) {
163 $rangesa = explode("=", $_SERVER["HTTP_RANGE"]);
164 $rangesb = explode(",", $rangesa[1]);
165 $rangesstr = $rangesb[0];
166 $ranges = explode("-", $rangesb[0]);
167 $rangestart = $ranges[0];
168 $rangelength = $ranges[1] - $ranges[0] +1;
169 error_log("going ranges at $rangestart, $rangelength,".$rangesa[1].",".$rangesb[0]);
172 // i have to support http_range cause REDHAT/CENTOS IS annoying as all hell. christ, why do this?
173 if(is_file($actualfile)) {
174 // file is stored locally, away we go
175 if($rangelength != -1) {
176 header("HTTP/1.1 206 Partial Content");
177 header("Content-Length: ".$rangelength);
178 header("Content-Range: bytes $rangesstr/".filesize($actualfile));
179 //header("Content-Length: ".filesize($actualfile));
181 header("Content-Length: ".filesize($actualfile));
183 $type = mime_content_type($actualfile);
184 header("Content-type: $type");
185 $localfile = fopen($actualfile, "r");
186 if($rangestart!=-1) fseek($localfile, $rangestart, SEEK_SET);
187 while(!feof($localfile)) {
188 // cant make this high cause centos is crap
189 if($rangelength!=-1) {
190 $data = fread($localfile, $rangelength);
191 error_log("data size was ".strlen($data));
193 $data = fread($localfile, 2048);
199 if($rangelength!=-1) {
205 } else if(is_dir($actualfile)) {
206 //echo "in dir for $actualfile\n";
207 // here we print the contents of the directory
208 $this->printDir($actualfile, $file, $url);
211 //echo "in getcheck\n";
212 $remotefile = $uconf[$matched]["url"]."/$file";
214 // TODO: i should get remote contents with fopen/fread/fwrite as
215 // it should be more memory conservative and we can push to the end client
217 ignore_user_abort(true);
218 $rf = fopen($remotefile, "r");
219 error_log("attempting to get remote file $remotefile");
222 // hopefully this works. if we get a 30x message, it means we tried to get a directory
223 // i cant think of another way of dealing with it - but this is UGLY
224 // also get content length and content type
226 foreach($http_response_header as $key => $val) {
227 if(preg_match("/HTTP.*30[1-9].*/", $val)) {
228 error_log("got a 30x, must be a directory");
230 header("Location: ".$_SERVER["REQUEST_URI"]."/");
233 // get content length form upstream and print
234 if(preg_match("/^Content-Length:.*/", $val)) {
238 // get content type from upstream and print
239 if(preg_match("/^Content-Type:.*/", $val)) {
243 //error_log("repsonse: $http_response_header");
246 header("HTTP/1.0 404 Not Found");
248 $localfile = fopen($actualfile.".tmp.data.deleteme", "w");
249 $localsizefile = fopen($actualfile.".tmp.data.deleteme.size", "w");
250 fwrite($localsizefile, "$clen");
251 fclose($localsizefile);
253 $data = fread($rf, 8192);
255 fwrite($localfile, $data);
260 rename($actualfile.".tmp.data.deleteme", $actualfile);
261 //error_log("got actualfile, tried to save as $actualfile, did it work?");
265 //echo "got ".$file." for $url which is $actualfile\n";
267 //echo "</html></pre>";
270 function printDir($dir, $localfile, $baseurl)
272 $localfile = preg_replace("/\/\/+/", "/", $localfile);
273 $uri = $_SERVER["REQUEST_URI"];
276 $content .= "<html><head><title>Index of $localfile</title></head><body><h1>Index of $localfile</h1>";
277 $content .= "<table>";
279 while(($file = readdir($dh))!==false) {
280 if($file != "." && $file != "..") $content .= "<tr><td><a href=\"$uri/$file\">$file</a></td></tr>";
282 $content .= "</table></body></html>";
284 GLCASpageBuilder(null, null, $content);
289 function getRepoDetailsYum($url, $ismirrorlist=false)
291 $actionurl = $url."/repodata/repomd.xml";
293 error_log("Getting for action of $actionurl");
295 $ld = file_get_contents($actionurl);
297 // so here we try and get what this repository provides (os, version, arch), for yum this
298 // should come straight off the url... i.e. centos/6.0/os/x86_64/ (centos, 6.0, base os, 64bit arch)
300 if(!$ld) return false;
302 // ok, now we tokenize the url and try and guess at the content
303 $spurl = explode("/", $url);
305 // first, find the OS
306 $kos = getKnownOSList();
307 $glt["OS"] = "unknown";
308 $glt["verison"] = "unknown";
309 $glt["arch"] = "unknown";
310 $glt["other"] = "unknown";
311 foreach($spurl as $comp) {
314 foreach($kos["os"]["short"] as $kosname => $koslong) {
315 //error_log("Comparing $kosname and $koslong with $comp");
316 if(strcasecmp($kosname, $comp) == 0) {
317 //error_log("got $kosname, $koslong for $comp in $url");
318 //echo "<pre>inone\n"; print_r($koslong); echo "</pre>";
319 $glt["OS"] = $koslong;
323 // find a version, we assume its going to be something [numbers] and a . (optional)
324 if(preg_match("/^[0-9.]+$/", $comp)>0) {
325 //error_log("version match of $comp");
326 $glt["version"] = $comp;
329 // 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
330 foreach($kos["arch"] as $archinter => $archname ) {
331 //error_log("Comparing $archinter, $archname with $comp");
332 if(strcasecmp($archname, $comp) == 0) {
333 //error_log("arch match of $archname with $comp");
334 $glt["arch"] = $archname;
338 // other is a bt harder, we really have to guess at this one
339 if(strcasecmp("os", $comp) == 0) $glt["other"] = "OS";
340 if(strcasecmp("update", $comp) == 0) $glt["other"] = "Updates";
341 if(strcasecmp("updates", $comp) == 0) $glt["other"] = "Updates";
342 if(strcasecmp("everything", $comp) == 0) $glt["other"] = "OS";
349 function deleteRepo($rkey)
351 $uconf = $this->config->getConfigVar("repodata");
352 $repostore = $this->config->getConfigVar("storagelocation");
354 if($uconf !== false) {
355 $conf = unserialize($uconf);
356 foreach($conf as $key => $vla) {
358 unset($conf["$rkey"]);
359 $nconf = serialize($conf);
360 system("rm -rf $repostore/$key");
361 error_log("remove repo as $rkey");
362 $this->config->setConfigVar("repodata", $nconf);
363 $this->config->saveConfig();
369 function addRepo($desc, $os, $version, $arch, $other, $shorturl, $prefix, $repurl, $repotype, $init)
371 $uconf = $this->config->getConfigVar("repodata");
375 $cs["version"] = $version;
377 $cs["other"] = $other;
378 $cs["shorturl"] = $shorturl;
379 $cs["prefix"] = $prefix;
380 $cs["url"] = $repurl;
381 $cs["repotype"] = $repotype;
385 if($uconf !== false) {
386 $conf = unserialize($uconf);
387 foreach($conf as $key => $val) {
395 $nconf = serialize($conf);
397 error_log("add repo as $ckey");
398 $this->config->setConfigVar("repodata", $nconf);
399 $this->config->saveConfig();
401 // now create the base structure in the repo
402 $repostore = $this->config->getConfigVar("storagelocation");
405 // now call update repo
406 if($init) $this->updateRepoYum($ckey);
409 function updateRepo($repokey)
411 // we only do yum yet
412 $this->updateRepoYum($repokey);
415 function updateRepoYum($repokey)
417 $repostore = $this->config->getConfigVar("storagelocation");
419 $repod = $this->getRepo($repokey);
421 $repourl = $repod["url"];
423 if(!file_exists("$repostore/$repokey")) {
424 mkdir("$repostore/$repokey");
427 if(!file_exists("$repostore/$repokey/repodata")) {
428 mkdir("$repostore/$repokey/repodata");
431 //ignore_user_abort(true);
432 $actionurl = "$repourl/repodata/repomd.xml";
433 $repomdxml = file_get_contents($actionurl);
434 file_put_contents("$repostore/$repokey/repodata/repomd.xml", $repomdxml);
436 $xml = simplexml_load_file("$repostore/$repokey/repodata/repomd.xml");
439 foreach($xml as $key => $var) {
440 //echo "for key $key has:\n";
443 $fileloc = $var->location["href"];
444 if(!file_exists("$repostore/$repokey/$fileloc")) {
445 error_log("getting $fileloc for $repokey on $repourl");
446 $dlfile = file_get_contents("$repourl/$fileloc");
447 file_put_contents("$repostore/$repokey/$fileloc", $dlfile);
449 error_log("Not getting $fileloc because we already have it");
455 function getRepo($id)
457 $uconf = $this->config->getConfigVar("repodata");
458 if($uconf !== false) {
459 $lconf = unserialize($uconf);
467 $uconf = $this->config->getConfigVar("repodata");
468 if($uconf !== false) {
469 return unserialize($uconf);