From 92127a03c74a5651294ae9f0198d536862fb5f5e Mon Sep 17 00:00:00 2001 From: paulr Date: Wed, 27 Jul 2011 02:43:46 +1000 Subject: [PATCH] length bits, exploding the getRepoForUrl bit --- plugins/repo.php | 207 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 206 insertions(+), 1 deletions(-) diff --git a/plugins/repo.php b/plugins/repo.php index 2584f3d..31a257f 100644 --- a/plugins/repo.php +++ b/plugins/repo.php @@ -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
"; + 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) -- 1.7.0.4