length bits, exploding the getRepoForUrl bit
authorpaulr <me@pjr.cc>
Tue, 26 Jul 2011 16:43:46 +0000 (02:43 +1000)
committerpaulr <me@pjr.cc>
Tue, 26 Jul 2011 16:43:46 +0000 (02:43 +1000)
plugins/repo.php

index 2584f3d..31a257f 100644 (file)
@@ -61,9 +61,214 @@ class GLCASRepo {
         *    - if a range request was made, send the range once available
         *    - if range not available, sleep for 5 and check again.
         * 
-        * 
+        * I dont want to code this from scratch, but i probably need to
         */
+       function getRepoForUrlNew($url)
+       {
+               $xurl = split("[/,]", $url);
+               
+               // first get the config         
+               $uconf = unserialize($this->config->getConfigVar("repodata"));
+               $repostore = $this->config->getConfigVar("storagelocation");
+               
+               // preset matched to -1
+               $matched = -1;
+               
+               // first we check for /repo/repoid as a url
+               $startat = 0;
+               if($xurl[0] == "repo") {
+                       $repid = $xurl[1];
+                       error_log("trying to get repo for repoid, $repid");
+                       if(isset($uconf[$repid])) {
+                               $matched = ((int)($repid));
+                               error_log("set matched, $matched, $repid");
+                               $startat +=2;
+                       }
+               }
+               
+               // now check for a prefix match
+               $prematch = false;
+               if($matched < 0) foreach($uconf as $key => $var) {
+                       $pre = $var["prefix"];
+                       
+                       if($pre!="") {
+                               //echo "Checking pre $pre against ".$xurl[0]."\n";
+                               if(strcasecmp($pre, $xurl[0])==0) {
+                                       //echo "Matched pre\n";
+                                       $prematch = true;
+                                       $startat++;
+                               }
+                       }
+               }
+               
+               // next, check for a short url match
+               if($matched < 0) foreach($uconf as $key => $var) {
+                       // if we matched a pre, then we check against the second url component
+                       
+                       $short = $var["shorturl"];
+                       
+                       if($short!="") {
+                               //echo "Checking short $short against ".$xurl[$startat]."\n";
+                               if(strcasecmp($xurl[$startat], $short)==0) {
+                                       //echo "Matched\n";
+                                       $matched = $key;
+                                       $startat++;
+                               }
+                       }
+               }
+               
+               // TODO: this deterministic bit
+               // so far nothing has matched - what this next bit needs to do is try and "Determine" a repo from url
+               // for eg, if a user gets /fedora/x86_64/os we need to return something appropriate
+               if($matched < 0) {
+                       echo "No such repo<br>";
+                       header("HTTP/1.0 404 Not Found");
+                       return;
+               }
+               
+               
+               // something was matched, so now we reconstruct the file component of the url
+               $file = "/";
+               if(count($xurl) > $startat) for($i=$startat; $i < count($xurl); $i++) {
+                       $file .= "/".$xurl[$i];
+               }
+               
+               // so, the ultimate url for the file we need is:
+               $actualfile = "$repostore/$matched/$file";
+               error_log("Atcualfile is $actualfile");
+               
+               // if its a directory, lets do a print
+               if(is_dir($actualfile)) {
+                       $this->printDir($actualfile, $file, $url);
+                       return;
+               }
+               
+               // check if the file exists and serve it up
+               if(file_exists($actualfile)) {
+                       $this->serveUpFile($actualFile, $matched);
+                       return;
+               } else {
+                       // the file does not exist, we now need to go into "download" mode
+                       $remoteurl = $uconf[$matched]["url"]."/$file";
+                       $this->downloadAndServe($actualFile, $matched, $remoteurl);
+                       return;
+               }
+       }
        
+       function serveUpFile($filename, $repoid)
+       {
+               $uconf = unserialize($this->config->getConfigVar("repodata"));
+               $repostore = $this->config->getConfigVar("storagelocation");
+               
+               // figure out the range header garbage that centos/redhat send
+               if(isset($_SERVER["HTTP_RANGE"])) {
+                       // we're using ranges - screw you stupid installer
+                       $pr_range = preg_split("/[:\-, ]+/", $_SERVER["HTTP_RANGE"]);
+                       
+                       // cut up ranges
+                       $rangestart = $pr_range[1];
+                       $rangelength = $pr_range[2] - $pr_range[1] +1;
+                       $rangestr = $pr_range[1]."-".$pr_range[2];
+                       error_log("going ranges at $rangestart, $rangelength,".$rangesa[1].",".$rangesb[0]);
+                       
+                       // now spit some headers
+                       header("HTTP/1.1 206 Partial Content");
+                       header("Content-Length: ".$rangelength);
+                       header("Content-Range: bytes $rangesstr/".filesize($actualfile));
+                       
+                       // determine mime type
+                       $type = mime_content_type($actualfile);
+                       
+                       // set mime type header
+                       header("Content-type: $type");
+                       
+                       // open the local file (TODO: error check)
+                       $localfile = fopen($actualfile, "r");
+                       fseek($localfile, $rangestart, SEEK_SET);
+                       
+                       // read in the data, god i hope its not big
+                       $data = fread($localfile, $rangelength);
+                       
+                       // lastly, send data
+                       echo $data;
+                       flush();
+                       
+                       // and close the file
+                       fclose($localfile);
+                       return;
+               } else {
+
+                       // we're not using range's - good on you installer thingy
+                       header("Content-Length: ".filesize($actualfile));
+
+                       // set the mime type header
+                       $type = mime_content_type($actualfile);
+                       header("Content-type: $type");
+                       
+                       // open the local file                  
+                       $localfile = fopen($actualfile, "r");
+                       
+                       // iterate over its length, send 8k at a time
+                       while(!feof($localfile)) {
+                               // read and send data
+                               $data = fread($localfile, 8192);
+                               echo $data;
+                               
+                               // flush so the client sees the data
+                               flush();
+                       }
+                       
+                       // close the file
+                       fclose($localfile);
+                       return;
+               }               
+       }
+       
+       // TODO: this is the function im working on
+       function downloadAndServe($filename, $repoid, $remoteurl)
+       {
+               $uconf = unserialize($this->config->getConfigVar("repodata"));
+               $repostore = $this->config->getConfigVar("storagelocation");
+               
+               // this is the tricky one for ranges.
+               
+               // check if a download exists
+               if(file_exists("$actualfile.tmp.data.deleteme")) {
+                       // a download exists, does it still work
+                       $localtmpfh = fopen("$actualfile.tmp.data.deleteme", "r");
+                       $lockres = flock($localtmpfh, LOCK_EX|LOCK_NB);
+                       if(!$lockres) {
+                               error_log("flock did fail, all is right with the world a download is in progress");
+                       } else {
+                               unlink("$actualfile.tmp.data.deleteme");
+                               unlink("$actualfile.tmp.data.deleteme.size");
+                       }
+               }
+
+               
+               $localfile = fopen($actualfile.".tmp.data.deleteme", "w");                              
+               $localsizefile = fopen($actualfile.".tmp.data.deleteme.size", "w");
+               
+               
+               // get the headers from the remote request and use them to hurt people
+               foreach($http_response_header as $key => $val) {
+                       if(preg_match("/HTTP.*30[1-9].*/", $val)) {
+                               error_log("got a 30x, must be a directory");
+                               mkdir($actualfile);
+                               header("Location: ".$_SERVER["REQUEST_URI"]."/");
+                               return;
+                       }
+                       // get content length form upstream and print
+                       if(preg_match("/^Content-Length:.*/", $val)) {
+                               $clen = $val;
+                               header($val);
+                       }
+                       // get content type from upstream and print
+                       if(preg_match("/^Content-Type:.*/", $val)) {
+                               header($val);   
+                       }
+               }
+       }
        
        // this is a nightmare
        function getRepoForUrl($url)