I updated a centos machine from this code... you ripper, it works!
[glcas.git] / plugins / repo.php
index fea1c4f..a703429 100644 (file)
@@ -6,17 +6,195 @@ class GLCASRepo {
        function __construct($config)
        {
                $this->config = $config;
+               if($this->config->getConfigVar("storagelocation") == false) {
+                       global $WEB_ROOT_FS;
+                       $storloc = "$WEB_ROOT_FS/../var/glcas/cache/";
+                       if(!file_exists($storloc)) mkdir($storloc);
+                       $this->config->setConfigVar("storagelocation", realpath($storloc));
+                       $this->config->saveConfig();
+                       error_log("set storage location, $storloc");
+               }
        }
        
        function go($url)
        {
                error_log("repo:go called");
-               GLCASpageBuilder($this, "body");
+               
+               // figure out what we're doing 
+               switch($url) {
+                       case "list":
+                               GLCASpageBuilder($this, "body");
+                               break;
+                       default:
+                               $this->getRepoForUrl($url);
+               }
        }
        
        function body($url)
        {
-               echo "for the repo, i am the repo $url";
+               // this is how this will work
+               //$this->decodeUrl();
+               if(strncasecmp("list", $url, 4)==0) {
+                       echo "i am the repo list";
+                       return;
+               }
+               echo "i am the repo, $url";
+       }
+       
+       function getRepoForUrl($url)
+       {
+               // the way we breakdown a url is to explode it
+               $xurl = split("[/,]", $url);
+               
+               // we first check if [0] is a prefix
+               // if now, we check for it being a shorturl (lets just do that for now)
+               $uconf = unserialize($this->config->getConfigVar("repodata"));
+               $repostore = $this->config->getConfigVar("storagelocation");
+               
+               $matched = -1;
+               $startat = 0;
+               $prematch = false;
+               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++;
+                               }
+                       }
+               }
+               
+               
+               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++;
+                               }
+                       }
+               }
+               
+               if($matched > -1) {
+                       //echo "Match on $key\n";
+               }
+               
+               
+               // now we find an actual file
+               $file = "/";
+               if(count($xurl) > $startat) for($i=$startat; $i < count($xurl); $i++) {
+                       $file .= "/".$xurl[$i];
+               }
+               
+               // now we want to find repostore/$matched/$file;
+               $actualfile = "$repostore/$matched/$file";
+               //echo "Start file for $actualfile\n";
+               
+               // first check any directories in $file are in existence
+               $splfile = explode("/", $file);
+               if(count($splfile) > 1) {
+                       $tomake = "$repostore/$matched/";
+                       for($i = 0; $i < count($splfile)-1; $i++) {
+                               $tomake .= "/".$splfile[$i];
+                               //error_log("making directory $tomake");
+                               if(!is_dir($tomake)) mkdir($tomake);
+                       }
+               }
+               
+               
+               if(is_file($actualfile)) {
+                       // file is stored locally, away we go
+                       header("Content-Length: ".filesize($actualfile));
+                       $type = mime_content_type($actualfile);
+                       header("Content-type: $type");
+                       $localfile = fopen($actualfile, "r");
+                       while(!feof($localfile)) {
+                               $data = fread($localfile, 16384);
+                               echo $data;
+                               flush();
+                       }
+                       fclose($localfile);
+               } else if(is_dir($actualfile)) {
+                       //echo "in dir for $actualfile\n";
+                       // here we print the contents of the directory
+                       $this->printDir($actualfile, $file, $url);
+               } else {
+                       // ok, get the file
+                       //echo "in getcheck\n";
+                       $remotefile = $uconf[$matched]["url"]."/$file";
+                       
+                       // TODO: i should get remote contents with fopen/fread/fwrite as
+                       // it should be more memory conservative and we can push to the end client
+                       // straight away
+                       $rf = fopen($remotefile, "r");
+                       error_log("attempting to get remote file $remotefile");
+
+                       
+                       // hopefully this works. if we get a 30x message, it means we tried to get a directory
+                       // i cant think of another way of dealing with it - but this is UGLY
+                       // also get content length and content type
+                       $clen = 0;
+                       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)) {
+                                       header($val);
+                               }
+                               // get content type from upstream and print
+                               if(preg_match("/^Content-Type:.*/", $val)) {
+                                       header($val);   
+                               }
+                       }
+                       //error_log("repsonse: $http_response_header");
+                       if(!$rf) {
+                               // return 404
+                               header("HTTP/1.0 404 Not Found");
+                       } else {
+                               $localfile = fopen($actualfile.".tmp.data.deleteme", "w");                              
+                               while(!feof($rf)) {
+                                       $data = fread($rf, 8192);
+                                       echo $data;
+                                       fwrite($localfile, $data);
+                                       flush();
+                               }
+                               fclose($localfile);
+                               fclose($rf);
+                               rename($actualfile.".tmp.data.deleteme", $actualfile);
+                               error_log("got actualfile, tried to save as $actualfile, did it work?");
+                       }
+               }
+               
+               //echo "got ".$file." for $url which is $actualfile\n";
+               
+               //echo "</html></pre>";
+       }
+       
+       function printDir($dir, $localfile, $baseurl)
+       {
+               $uri = $_SERVER["REQUEST_URI"];
+               if(is_dir($dir)) {
+                       echo "<html><head><title>Index of $localfile</title></head><body><h1>Index of $localfile</h1>";
+                       echo "<table>";
+                       $dh = opendir($dir);
+                       while(($file = readdir($dh))!==false) {
+                               if($file != "." && $file != "..") echo "<tr><td><a href=\"$uri/$file\">$file</a></td></tr>";
+                       }
+                       echo "</table></body></html>";
+                       
+               } else return false;
        }
        
        function getRepoDetailsYum($url, $ismirrorlist=false)
@@ -32,13 +210,177 @@ class GLCASRepo {
                
                if(!$ld) return false;
                
-               $glt["OS"] = "Fedora";
-               $glt["version"] = "15";
-               $glt["arch"] = "x86_64";
+               // ok, now we tokenize the url and try and guess at the content
+               $spurl = explode("/", $url);
                
+               // first, find the OS
+               $kos = getKnownOSList();
+               $glt["OS"] = "unknown";
+               $glt["verison"] = "unknown";
+               $glt["arch"] = "unknown";
+               $glt["other"] = "unknown";
+               foreach($spurl as $comp) {
+                       
+                       // find a name
+                       foreach($kos["os"]["short"] as $kosname => $koslong) {
+                               //error_log("Comparing $kosname and $koslong with $comp");
+                               if(strcasecmp($kosname, $comp) == 0) {
+                                       //error_log("got $kosname, $koslong for $comp in $url");
+                                       //echo "<pre>inone\n"; print_r($koslong); echo "</pre>";
+                                       $glt["OS"] = $koslong;
+                               }
+                       }
+                       
+                       // find a version, we assume its going to be something [numbers] and a . (optional)
+                       if(preg_match("/^[0-9.]+$/", $comp)>0) {
+                               error_log("version match of $comp");
+                               $glt["version"] = $comp;
+                       }
+                       
+                       // 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
+                       foreach($kos["arch"] as $archinter => $archname ) {
+                               //error_log("Comparing $archinter, $archname with $comp");
+                               if(strcasecmp($archname, $comp) == 0) {
+                                       error_log("arch match of $archname with $comp");
+                                       $glt["arch"] = $archname;
+                               }
+                       }
+                       
+                       // other is a bt harder, we really have to guess at this one
+                       if(strcasecmp("os", $comp) == 0) $glt["other"] = "OS";
+                       if(strcasecmp("update", $comp) == 0) $glt["other"] = "Updates";
+                       if(strcasecmp("updates", $comp) == 0) $glt["other"] = "Updates";
+                       if(strcasecmp("everything", $comp) == 0) $glt["other"] = "OS";
+               }
+               
+                       
                return $glt;
        }
        
+       function deleteRepo($rkey)
+       {
+               $uconf = $this->config->getConfigVar("repodata");
+               $repostore = $this->config->getConfigVar("storagelocation");
+               
+               if($uconf !== false) {
+                       $conf = unserialize($uconf);
+                       foreach($conf as $key => $vla) {
+                               if($key == $rkey) {
+                                       unset($conf["$rkey"]);
+                                       $nconf = serialize($conf);
+                                       system("rm -rf $repostore/$key");
+                                       error_log("remove repo as $rkey");
+                                       $this->config->setConfigVar("repodata", $nconf);
+                                       $this->config->saveConfig();
+                               }
+                       }
+               }
+       }
+       
+       function addRepo($desc, $os, $version, $arch, $other, $shorturl, $prefix, $repurl, $repotype, $init)
+       {
+               $uconf = $this->config->getConfigVar("repodata");
+               
+               $cs["desc"] = $desc;
+               $cs["os"] = $os;
+               $cs["version"] = $version;
+               $cs["arch"] = $arch;
+               $cs["other"] = $other;
+               $cs["shorturl"] = $shorturl;
+               $cs["prefix"] = $prefix;
+               $cs["url"] = $repurl;
+               $cs["repotype"] = $repotype;
+               
+               
+               $ckey = 0;
+               if($uconf !== false) {
+                       $conf = unserialize($uconf);
+                       foreach($conf as $key => $val) {
+                               $ckey = $key;
+                       }
+                       $ckey++;
+               }
+               
+               $conf[$ckey] = $cs;
+               
+               $nconf = serialize($conf);
+               
+               error_log("add repo as $ckey");
+               $this->config->setConfigVar("repodata", $nconf);
+               $this->config->saveConfig();
+               
+               // now create the base structure in the repo
+               $repostore = $this->config->getConfigVar("storagelocation");
+               
+               
+               // now call update repo
+               if($init) $this->updateRepoYum($ckey);
+       }
+       
+       function updateRepo($repokey)
+       {
+               // we only do yum yet
+               $this->updateRepoYum($repokey);
+       }
+       
+       function updateRepoYum($repokey)
+       {
+               $repostore = $this->config->getConfigVar("storagelocation");
+               
+               $repod = $this->getRepo($repokey);
+               
+               $repourl = $repod["url"];
+               
+               if(!file_exists("$repostore/$repokey")) {
+                       mkdir("$repostore/$repokey");
+               }
+               
+               if(!file_exists("$repostore/$repokey/repodata")) {
+                       mkdir("$repostore/$repokey/repodata");
+               }
+               
+               $actionurl = "$repourl/repodata/repomd.xml";
+               $repomdxml = file_get_contents($actionurl);
+               file_put_contents("$repostore/$repokey/repodata/repomd.xml", $repomdxml);
+               
+               $xml = simplexml_load_file("$repostore/$repokey/repodata/repomd.xml");
+               
+               
+               foreach($xml as $key => $var) {
+                       //echo "for key $key has:\n";
+                       //print_r($var);
+                       if($key == "data") {
+                               $fileloc = $var->location["href"];
+                               if(!file_exists("$repostore/$repokey/$fileloc")) {
+                                       error_log("getting $fileloc for $repokey on $repourl");
+                                       $dlfile = file_get_contents("$repourl/$fileloc");
+                                       file_put_contents("$repostore/$repokey/$fileloc", $dlfile);
+                               } else {
+                                       error_log("Not getting $fileloc because we already have it");
+                               }
+                       }
+               }
+       }
+       
+       function getRepo($id)
+       {
+               $uconf = $this->config->getConfigVar("repodata");
+               if($uconf !== false) {
+                       $lconf = unserialize($uconf);
+                       return $lconf[$id];
+               } else return false;
+               
+       }
+       
+       function getRepos()
+       {
+               $uconf = $this->config->getConfigVar("repodata");
+               if($uconf !== false) {
+                       return unserialize($uconf);
+               } else return false;
+               
+       }
+       
        private $config;
 }