From b43f610c8d1458e4778e0a0a719367c478dacbb0 Mon Sep 17 00:00:00 2001 From: paulr Date: Tue, 1 Nov 2011 02:14:20 +1100 Subject: [PATCH] working git-http-backend proxy poc code --- gwvplib/gwvpweb.php | 159 +++++++++++++++++++++++++++++++++++++++++++-------- 1 files changed, 134 insertions(+), 25 deletions(-) diff --git a/gwvplib/gwvpweb.php b/gwvplib/gwvpweb.php index 03daa77..9ad85ae 100644 --- a/gwvplib/gwvpweb.php +++ b/gwvplib/gwvpweb.php @@ -11,13 +11,18 @@ function goWebGitBackEnd() // well, i cant believe it, but this actually freaking works... for pulls/clones anyways... commits are not working... // but wow thats better then what i had hoped for + // first thing to do + $fh = fopen('php://input', "r"); $k1 = print_r($_REQUEST, true); $k2 = print_r($_SERVER, true); $k3 = print_r($_POST, true); + $k4 = print_r($_GET, true); error_log("k1: $k1"); error_log("k2: $k2"); error_log("k3: $k3"); + error_log("k4: $k4"); + error_log($_SERVER["REQUEST_URI"]); $ruri = $_SERVER["REQUEST_URI"]; $euri = str_replace("test.git", "", $_REQUEST["q"]); @@ -27,7 +32,7 @@ function goWebGitBackEnd() $qs = ""; foreach($_REQUEST as $key => $var) { if($key != "q") { - error_log("adding, $var from $key"); + //error_log("adding, $var from $key"); if($qs == "") $qs.="$key=$var"; else $qs.="&$key=$var"; } @@ -35,10 +40,6 @@ function goWebGitBackEnd() //sleep(2); - $body = ''; - if($rmeth == "POST") { - $body = file_get_contents("php://input"); - } // this is where the fun, it ends. @@ -55,52 +56,160 @@ function goWebGitBackEnd() $procenv["GIT_HTTP_EXPORT_ALL"] = "1"; $procenv["QUERY_STRING"] = "$qs"; $procenv["HTTP_USER_AGENT"] = "git/1.7.1"; - $procenv["REMOTE_USER"] = "paulr"; + $procenv["REMOTE_USER"] = "user"; $procenv["REMOTE_ADDR"] = "1.2.3.4"; - $procenv["CONTENT_TYPE"] = "application/x-git-upload-pack-request"; + $procenv["AUTH_TYPE"] = "Basic"; + + if(isset($_SERVER["CONTENT_TYPE"])) { + $procenv["CONTENT_TYPE"] = $_SERVER["CONTENT_TYPE"]; + } else { + //$procenv["CONTENT_TYPE"] = ""; + } + if(isset($_SERVER["CONTENT_LENGTH"])) { + $procenv["CONTENT_LENGTH"] = $_SERVER["CONTENT_LENGTH"]; + } + + $pwd = "/var/cache/git"; - error_log("openproc"); - $proc = proc_open("/usr/lib/git-core/git-http-backend", array(array("pipe","r"),array("pipe","w"),array("file","/dev/null", "w")), $pipes, $pwd, $procenv); - error_log("openproc2, $proc"); + //error_log("openproc"); + $proc = proc_open("/usr/lib/git-core/git-http-backend", array(array("pipe","rb"),array("pipe","wb"),array("file","/tmp/err", "a")), $pipes, $pwd, $procenv); + //$proc = proc_open("/home/paulr/src/eclipse-workspace/gwvp/datacatch/../datacatcher.sh", array(array("pipe","r"),array("pipe","w"),array("file","/tmp/err", "a")), $pipes, $pwd, $procenv); + //error_log("openproc2, $proc"); - $stdin = $pipes[0]; - $stdout = $pipes[1]; + //error_log("openproc3"); - error_log("openproc3"); + //if($rmeth == "POST") { + //} - if($body != "") { - fwrite($pipes[0], $body); - } - error_log("openproc4"); + //error_log("openproc4"); $untilblank = false; while(!$untilblank&&!feof($pipes[1])) { - $lines = rtrim(fgets($pipes[1])); + $lines_t = fgets($pipes[1]); + $lines = trim($lines_t); error_log("got line: $lines"); - if($lines == "") { + if($lines_t == "\r\n") { $untilblank = true; error_log("now blank"); } else header($lines); - if($lines === false) exit(0); + if($lines === false) { + error_log("got an unexpexted exit..."); + exit(0); + } } - error_log("openproc5"); + //error_log("openproc5"); + // if would seam that post and output must be synchronised together somehow... i think + /* + $fh = fopen('php://input', 'rb'); + if ($fh) { + while (!feof($fh)) { + $s = fread($fh, 1024); + if($s === false) { + error_log("unexpected eror on input read"); + } + fwrite($pipes[0], $s); + } + fclose($fh); + } // now the body + $fl = fopen("/tmp/pushpipe", "ab"); while(!feof($pipes[1])) { - echo fread($pipes[1], 1024); + $d = fread($pipes[1], 1024); + error_log("got read, $d"); + if($d === false) { + errog_log("got unexpected false on reads"); + } else { + echo $d; + fwrite($fl, $d); + } + }*/ + + // oh god, something goes wrong with all this data and i dont know what it is + // but i think its cause proc_open doesnt deal with binary data properly + $firstline = true; + $continue = true; + //$fl = fopen("/tmp/pushpipe", "w"); + + if(!stream_set_blocking($fh,0)) { + error_log("cant set input non-blocking"); + } + // problem no 1 - dont do this + //if(!stream_set_blocking($pipes[0],0)) { + //error_log("cant set pipe 0 non-blocking"); + //} + if(!stream_set_blocking($pipes[1],0)) { + error_log("cant set pipe1 non-blocking"); } - error_log("openproc6"); + // i was going to use stream_select, but i feel this works better like this + while($continue) { + // do client + if(!feof($fh)) { + $from_client_data = fread($fh,8192); + if($from_client_data !== false) fwrite($pipes[0], $from_client_data); + fflush($pipes[0]); + //fwrite($fl, $from_client_data); + $client_len = strlen($from_client_data); + } else { + error_log("client end"); + $client_len = 0; + } + + // do cgi + // sometimes, we get a \r\n from the cgi, i do not know why she swallowed the fly, + // but i do know that the fgets for the headers above should have comsued that + if(!feof($pipes[1])) { + $from_cgi_data_t = fread($pipes[1],8192); + $from_cgi_data = $from_cgi_data_t; + + // i dont know if this will solve it... it coudl cause some serious issues elsewhere + // TODO: this is a hack, i need to know why the fgets above doesn consume the \r\n even tho it reads it + // i.e. why the pointer doesnt increment over it, cause the freads above then get them again. + if($firstline) { + if(strlen($from_cgi_data_t)>0) { + $from_cgi_data = preg_replace("/^\r\n/", "", $from_cgi_data_t); + $firstline = false; + } + } + + if($from_cgi_data !== false) { + echo $from_cgi_data; + flush(); + } + $cgi_len = strlen($from_cgi_data); + } else { + error_log("cgi end"); + $cgi_len = 0; + } + + if(feof($pipes[1])) $continue = false; + else { + if($client_len == 0 && $cgi_len == 0) { + usleep(200000); + error_log("sleep tick"); + } else { + error_log("sizes: $client_len, $cgi_len"); + if($cgi_len > 0) { + error_log("from cgi: \"$from_cgi_data\""); + } + } + } + + } - fclose($stdout); - fclose($stdin); + //fclose($fl); + fclose($fh); + fclose($pipes[1]); + fclose($pipes[0]); + //error_log("openproc6"); } } -- 1.7.0.4