From: paulr Date: Mon, 31 Oct 2011 16:40:39 +0000 (+1100) Subject: some framework stuff X-Git-Url: http://git.pjr.cc/?p=gwvp.git;a=commitdiff_plain;h=4c20cd2f33699e549a06995d9c5ab1374cceeaee some framework stuff --- diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..dd4c311 --- /dev/null +++ b/INSTALL @@ -0,0 +1 @@ +Yeah, like theres f*** all to install right now? \ No newline at end of file diff --git a/README b/README index ddc2292..7448964 100644 --- a/README +++ b/README @@ -1,23 +1,26 @@ GWVP ==== +Note - this is barely (currently) proof-of-concept code and simply does a thru-php proxy of git-http-backend +it is not in the least bit useful for anything, yet. + Git over Web Via PHP is a project to do something i've wanted to have a long time - a web based git remote with administration and all git related activities happening over http/https. Git has this now, its called git-http-backend and its quite broken. If you read its man page it'll tell you this: - To enable anonymous read access but authenticated write access, - require authorization with a LocationMatch directive: - - - AuthType Basic - AuthName "Git Access" - Require group committers - ... - + To enable anonymous read access but authenticated write access, + require authorization with a LocationMatch directive: + + + AuthType Basic + AuthName "Git Access" + Require group committers + ... + -This will never work in a month of sundays, but yet its been in the man page and been un-fixed now for a year -and besides that i've decided i want a web based one. Im sick of git over ssh with ssh keys, its annoying -when it can be done with user/password auth over https. +This will never work in a month of sundays, but yet its been in the man page and been un-fixed now for a year. +Aside from that though, i wanted an application capable of handling my repo's without having to deal with the +ssh fluff i tend to deal with its annoying when it can be done with user/password auth over https. Thats what the project is designed to do - give people the ability to administrate a set of a git repo's via a web interface and have the same web interface for pull and push. @@ -30,11 +33,22 @@ What you will ultimately be able to do is: but most importantly: git add remote origin https://username@server/git/myrepo.git -git push +git push origin master + +Ultimately I want people to be able to install this app, create a directory where it can save its files (db), +create another directory for storing git repos then allow people to login to the web interface and control +everything, for example: +1) create a user and control what they can see +2) allow users to control who can push to their repos +3) control how many repo's a user can create +4) import code into a repo (via git bundle for eg) +5) setup a group heirachy +I think that describes the places i'd like this app to go How it Works ============ Initially this thing will have a fairly boring interface for creating/contorlling users and repos while also pushing directly back to git-http-backend AND providing the authentication interface IT needs to function -Gitweb.cgi may also be incorporated as the git view tool - but thats less important at this point \ No newline at end of file +Gitweb.cgi may also be incorporated as the git view tool - but thats less important at this point and will +probably be just a portion of the php code designed to show something similar to gitweb.cgi with more control \ No newline at end of file diff --git a/gwvplib/gwvpdatabase.php b/gwvplib/gwvpdatabase.php new file mode 100644 index 0000000..d53373e --- /dev/null +++ b/gwvplib/gwvpdatabase.php @@ -0,0 +1,48 @@ + \ No newline at end of file diff --git a/gwvplib/gwvpgitbackend.php b/gwvplib/gwvpgitbackend.php new file mode 100644 index 0000000..9ad85ae --- /dev/null +++ b/gwvplib/gwvpgitbackend.php @@ -0,0 +1,217 @@ + $var) { + if($key != "q") { + //error_log("adding, $var from $key"); + if($qs == "") $qs.="$key=$var"; + else $qs.="&$key=$var"; + } + } + + //sleep(2); + + + + // this is where the fun, it ends. + $myoutput = ""; + unset($myoutput); + + // this be nasty! + + // setup env + if(isset($procenv)) unset($procenv); + $procenv["GATEWAY_INTERFACE"] = "CGI/1.1"; + $procenv["PATH_TRANSLATED"] = "/var/cache/git/test.git$euri"; + $procenv["REQUEST_METHOD"] = "$rmeth"; + $procenv["GIT_HTTP_EXPORT_ALL"] = "1"; + $procenv["QUERY_STRING"] = "$qs"; + $procenv["HTTP_USER_AGENT"] = "git/1.7.1"; + $procenv["REMOTE_USER"] = "user"; + $procenv["REMOTE_ADDR"] = "1.2.3.4"; + $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","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"); + + //error_log("openproc3"); + + //if($rmeth == "POST") { + //} + + + //error_log("openproc4"); + + $untilblank = false; + while(!$untilblank&&!feof($pipes[1])) { + $lines_t = fgets($pipes[1]); + $lines = trim($lines_t); + error_log("got line: $lines"); + if($lines_t == "\r\n") { + $untilblank = true; + error_log("now blank"); + } else header($lines); + if($lines === false) { + error_log("got an unexpexted exit..."); + exit(0); + } + + } + + //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])) { + $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"); + } + + // 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($fl); + fclose($fh); + fclose($pipes[1]); + fclose($pipes[0]); + + //error_log("openproc6"); + + } +} + +?> \ No newline at end of file diff --git a/gwvplib/gwvplib.php b/gwvplib/gwvplib.php index 7e671e0..2a70f0c 100644 --- a/gwvplib/gwvplib.php +++ b/gwvplib/gwvplib.php @@ -1,5 +1,14 @@ \ No newline at end of file diff --git a/gwvplib/gwvprepoadmin.php b/gwvplib/gwvprepoadmin.php new file mode 100644 index 0000000..49073c0 --- /dev/null +++ b/gwvplib/gwvprepoadmin.php @@ -0,0 +1,29 @@ + \ No newline at end of file diff --git a/gwvplib/gwvpuseradmin.php b/gwvplib/gwvpuseradmin.php new file mode 100644 index 0000000..af44eb6 --- /dev/null +++ b/gwvplib/gwvpuseradmin.php @@ -0,0 +1,33 @@ + \ No newline at end of file diff --git a/gwvplib/gwvpweb.php b/gwvplib/gwvpweb.php index 9ad85ae..f476161 100644 --- a/gwvplib/gwvpweb.php +++ b/gwvplib/gwvpweb.php @@ -1,217 +1,134 @@ $var) { - if($key != "q") { - //error_log("adding, $var from $key"); - if($qs == "") $qs.="$key=$var"; - else $qs.="&$key=$var"; - } - } - - //sleep(2); - - - - // this is where the fun, it ends. - $myoutput = ""; - unset($myoutput); - - // this be nasty! - - // setup env - if(isset($procenv)) unset($procenv); - $procenv["GATEWAY_INTERFACE"] = "CGI/1.1"; - $procenv["PATH_TRANSLATED"] = "/var/cache/git/test.git$euri"; - $procenv["REQUEST_METHOD"] = "$rmeth"; - $procenv["GIT_HTTP_EXPORT_ALL"] = "1"; - $procenv["QUERY_STRING"] = "$qs"; - $procenv["HTTP_USER_AGENT"] = "git/1.7.1"; - $procenv["REMOTE_USER"] = "user"; - $procenv["REMOTE_ADDR"] = "1.2.3.4"; - $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"]; + global $CALL_ME_FUNCTIONS; + + // first we determine if we have a valid setup and run the installer if not + if(!gwvp_issetup()) { + gwvp_goSetup(); + return; + } + + // next, we go thru the CALL_ME_FUNCTIONS - the purpose of call_me_functions is to determine if a function should be called based on + // the functions return (i.e. if function returns false, its not it, otherwise it returns a function name we have to call) + // this is important for our plugin structure later on + foreach($CALL_ME_FUNCTIONS as $key => $val) { + error_log("checking callmefunction $key as $val"); + $callme = $val(); + if($callme !== false) { + $callme(); + return; } - - + } + + // we fell-thru to the main web page builder + gwvp_goMainPage(); +} - $pwd = "/var/cache/git"; - - //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"); - - //error_log("openproc3"); - - //if($rmeth == "POST") { - //} - - - //error_log("openproc4"); - - $untilblank = false; - while(!$untilblank&&!feof($pipes[1])) { - $lines_t = fgets($pipes[1]); - $lines = trim($lines_t); - error_log("got line: $lines"); - if($lines_t == "\r\n") { - $untilblank = true; - error_log("now blank"); - } else header($lines); - if($lines === false) { - error_log("got an unexpexted exit..."); - exit(0); - } - - } - - //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])) { - $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"); - } - - // 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(); +function gwvp_goMainPage($bodyFunction = null) +{ + // the main page will look pretty simple, a title, a menu then a body + global $WEB_ROOT_FS, $BASE_URL; + + // a simple web page layout that loads any css and js files that exist in the css and js directories + echo "GWVP"; + + // load css + if(file_exists("$WEB_ROOT_FS/css")) { + $dh = opendir("$WEB_ROOT_FS/css"); + if($dh) { + while(($file = readdir($dh))!==false) { + $mt = preg_match("/.*.css$/", $file); + if($mt > 0) { + error_log("loading css $file"); + echo ""; + //echo "required $basedir/$file\n"; } - $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\""); - } + } + } + + // load js + if(file_exists("$WEB_ROOT_FS/js")) { + $dh = opendir("$WEB_ROOT_FS/js"); + if($dh) { + while(($file = readdir($dh))!==false) { + $mt = preg_match("/.*.js$/", $file); + if($mt > 0) { + error_log("loading js $file"); + echo ""; + //echo "required $basedir/$file\n"; } } - + } + } + + + // start body + echo ""; + + echo "

Git over Web Via PHP

"; + + + echo ""; + + echo ""; + + echo "
"; + gwvp_MenuBuilder(); + echo "
"; + if($bodyFunction == null) { + gwvp_BodyBuilder(); + } else { + if(function_exists($bodyFunction)) { + $bodyFunction(); + } else { + error_log("Got called with non-existant body function"); + gwvp_BodyBuilder(); } - - - //fclose($fl); - fclose($fh); - fclose($pipes[1]); - fclose($pipes[0]); - - //error_log("openproc6"); - } + echo "
"; + gwvp_TailBuilder(); + echo "
"; + +} + +// builds the menu structure +function gwvp_MenuBuilder() +{ + global $MENU_ITEMS; + + ksort($MENU_ITEMS); + + echo ""; + foreach($MENU_ITEMS as $key => $val) { + $link = $val["link"]; + $text = $val["text"]; + echo ""; + } + echo "
Menu$text
"; + +} + +// builds the body structure +function gwvp_BodyBuilder() +{ + echo "I AM THE MAIN BODY, FEAR ME!!!!"; +} + +// builds the tail structure +function gwvp_TailBuilder() +{ + echo "Copyright 2011, PJR - licensed under GPL"; } ?> \ No newline at end of file diff --git a/www/config.php b/www/config.php index aa70504..51b9ddc 100644 --- a/www/config.php +++ b/www/config.php @@ -4,21 +4,9 @@ $repo_base = "/tmp/gwvp-repos/"; $lib_base = "../gwvplib/"; $data_directory = "../data"; - - - -// nothing to configure from here -$WEB_ROOT_FS = realpath(dirname(__FILE__)); -$BASE_URL = dirname($_SERVER["PHP_SELF"]); - -global $WEB_ROOT_FS, $BASE_URL; - -// add libglcas as if it were a path in ../libglcas -if(file_exists($lib_base)) { - $path = realpath($lib_base); - set_include_path(get_include_path().PATH_SEPARATOR.$path); -} - -require_once("gwvplib.php"); +$db_type = "sqlite"; // could be mysql or pgsql - but not yet +$db_name = "$data_directory/gwvp.db"; // just a file for sqlite, for anything else is a pdo url without driver, i.e. host=localhost;dbname=whatever;user=asdf;password=asdf +$db_username = ""; +$db_password = ""; ?> \ No newline at end of file diff --git a/www/index.php b/www/index.php index cfe2386..aef8e3d 100644 --- a/www/index.php +++ b/www/index.php @@ -1,8 +1,22 @@ "; echo "BASEURL: $BASE_URL\n"; echo "CUSTOM\n"; @@ -24,6 +39,6 @@ print_r($_REQUEST); echo ""; -*/ + ?>