X-Git-Url: http://git.pjr.cc/?a=blobdiff_plain;f=gwvpmini%2Fgwvpmini_gitbackend.php;h=f55038cfebb081a7da4db6a766bb8de2090bc2df;hb=746924e785c55b28d1d7a36d3f3dfab79559bc7e;hp=69c828fb77128ddd327e6eb2db335c4b3d6e5f69;hpb=56521de0c066787c601f6859c35a49fcee62a282;p=gwvp-mini.git diff --git a/gwvpmini/gwvpmini_gitbackend.php b/gwvpmini/gwvpmini_gitbackend.php index 69c828f..f55038c 100644 --- a/gwvpmini/gwvpmini_gitbackend.php +++ b/gwvpmini/gwvpmini_gitbackend.php @@ -26,10 +26,48 @@ function gwvpmini_gitControlCallMe() } +function gwvpmini_CreateRepoHooks($repopath, $cmdpath, $reponame) +{ + $fp = fopen("$repopath/hooks/pre-receive", "w"); + + if(!$fp) error_log("could not create pre-receive hook"); + + // TODO: think about this one + //$script = '#!/bin/bash'."\n\n".'DCOMMIT=`cat`'."\n".'START=`echo $DCOMMIT|cut -d " " -f 1`'."\n".'END=`echo $DCOMMIT|cut -d " " -f 2`'."\n".'REF=`echo $DCOMMIT|cut -d " " -f 3`'."\n\n"; + $script = "#!/bin/bash\n\nDCOMMIT=".'`cat`'."\n\nphp $cmdpath $reponame \$REMOTE_USER pre-receive \$DCOMMIT\n\n"; + fwrite($fp, $script); + + fclose($fp); + + chmod("$repopath/hooks/pre-receive", 0755); + + + $fp = fopen("$repopath/hooks/update", "w"); + + if(!$fp) error_log("could not create update hook"); + + // TODO: think about this one + unset($script); + $script = "#!/bin/bash\n\nphp $cmdpath $reponame \$REMOTE_USER update \$1 \$2 \$3\n\n"; + fwrite($fp, $script); + + fclose($fp); + + chmod("$repopath/hooks/update", 0755); +} + function gwvpmini_gitBackendInterface() { // and this is where i re-code the git backend interface from scratch - global $BASE_URL; + global $BASE_URL, $cmd_line_tool; + + header_remove("Pragma"); + header_remove("Cache-Control"); + header_remove("Set-Cookie"); + header_remove("Expires"); + header_remove("X-Powered-By"); + header_remove("Vary"); + $repo_base = gwvpmini_getConfigVal("repodir"); @@ -37,16 +75,16 @@ function gwvpmini_gitBackendInterface() /* bizare git problem that ignores 403's or continues on with a push despite them - error_log("FLAP for ".$_SERVER["REQUEST_URI"]); + // error_log("FLAP for ".$_SERVER["REQUEST_URI"]); if(isset($_REQUEST)) { $dump = print_r($_REQUEST, true); - error_log("FLAP, $dump"); + // error_log("FLAP, $dump"); } if(isset($_SERVER["PHP_AUTH_USER"])) { - error_log("FLAP: donut hole"); + // error_log("FLAP: donut hole"); }*/ - + error_log("REQUESTINBACKEND: ".print_r($_REQUEST, true)); $repo = ""; $repoid = false; @@ -71,20 +109,24 @@ function gwvpmini_gitBackendInterface() chdir("$repo_base/$repo.git"); exec("/usr/bin/git update-server-info"); + if(!file_exists("$repo_base/$repo.git/hooks/pre-receive") || !file_exists("$repo_base/$repo.git/hooks/update")) { + // error_log("WRITING HOOKS"); + gwvpmini_CreateRepoHooks("$repo_base/$repo.git", $cmd_line_tool, $repo); + } + // so now we have the repo // next we determine if this is a read or a write + + // TODO: WE NEED TO FIX THIS, IT DOESNT ALWAYS DETECT a "WRITE" $write = false; if(isset($_REQUEST["service"])) { if($_REQUEST["service"] == "git-receive-pack") { - error_log("got write as receivepack in post"); + // error_log("got write as receivepack in post"); $write = true; } } - if($_SERVER["REQUEST_METHOD"] == "POST") { - $write = true; - } - + if(preg_match("/.*git-receive-pack$/", $_REQUEST["q"])) $write = true; //$write = true; // THIS MAY CAUSE ISSUES LATER ON but we do it cause the git client ignores our 403 when it uses git-receive-pack after an auth // no, this isnt a solution cause auth'd read attempts will come up as writes... @@ -92,61 +134,86 @@ function gwvpmini_gitBackendInterface() //$write = true; //} - $perms = 5; + $person = gwvpmini_checkBasicAuthLogin(); //$write = true; + // next, figure out permissions for repo + $rid = gwvpmini_GetRepoId($repo); + $uid = -1; + // error_log("AT THIS POINT WE HAVE $uid, $rid, $repo $person"); - // if its a write, we push for authentication - if($write) { - error_log("is write attempt, ask for login"); - $person = gwvpmini_checkBasicAuthLogin(); - if($person == false) { - error_log("person is false, push auth"); + if(!$person) { + if($write) { + // error_log("ASK FOR BASIC AUTH"); gwvpmini_AskForBasicAuth(); - echo "Login"; return; } else { - error_log("checking perms for $person against $repoid for repo $repo"); - // here we pass to the git backend - error_log("perms are $perms and im allowed"); - gwvpmini_callGitBackend($person["username"], $repo); + $perm = gwvpmini_GetRepoPerm($rid, "a"); + if($perm < 1) { + // error_log("ASK FOR BASIC AUTH 2"); + gwvpmini_AskForBasicAuth(); + return; + } + } + } else { + $uid = gwvpmini_GetUserId($person); + $perm = gwvpmini_GetRepoPerm($rid, $uid); + if($write) { + if($perm < 2) { + // error_log("SEND FOFF"); + gwvpmini_fourZeroThree(); + return; + } + } else { + if($perm < 1) { + gwvpmini_fourZeroThree(); + return; + } } - return; } + // if its a write, we push for authentication - // if they're less then read, we need to then check the user auth permissions - if($perms < 2) { - // we ask for auth - $person = gwvpmini_checkBasicAuthLogin(); - if($person == false) { - gwvpmini_AskForBasicAuth(); - return; - } else { - } + //if($write) { + if(!$person) { + $person = "anonymous"; + } + + // if its a write, we check (before and after) the branch/tag info to see if they were updated + if($write) { + error_log("REQUESTINBACKEND: processed as write"); + } else { + error_log("REQUESTINBACKEND: processed as read"); } + gwvpmini_callGitBackend($person, $repo); + + //if($write) { + //} + return; + //} + // if we made it this far, we a read and we have permissions to do so, just search the file from the repo - if(file_exists("$repo_base/$repo.git/$newloc")) { - error_log("would ask $repo for $repo.git/$newloc from $repo_base/$repo.git/$newloc"); + /*if(file_exists("$repo_base/$repo.git/$newloc")) { + // error_log("would ask $repo for $repo.git/$newloc from $repo_base/$repo.git/$newloc"); $fh = fopen("$repo_base/$repo.git/$newloc", "rb"); - error_log("pushing file"); + // error_log("pushing file"); while(!feof($fh)) { echo fread($fh, 8192); } } else { - //echo "would ask $repo,$actual_repo_name for $repo/$newloc from $repo_base/$repo/$newloc, NE"; + // error_log("would ask $repo for $repo/$newloc from $repo_base/$repo/$newloc, NE"); gwvpmini_fourZeroFour(); return; - } + }*/ } function gwvpmini_canManageRepo($userid, $repoid) { // only the owner or an admin can do these tasks - error_log("Checking repoid, $repoid against userid $userid"); + // error_log("Checking repoid, $repoid against userid $userid"); if(gwvpmini_IsUserAdmin(null, null, $userid)) return true; if(gwvpmini_IsRepoOwner($userid, $repoid)) return true; @@ -173,7 +240,7 @@ function gwvpmini_callGitBackend($username, $repo) $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"; } @@ -181,7 +248,7 @@ function gwvpmini_callGitBackend($username, $repo) //sleep(2); - + $userdets = gwvpmini_getUser($username); // this is where the fun, it ends. $myoutput = ""; @@ -194,6 +261,8 @@ function gwvpmini_callGitBackend($username, $repo) $procenv["GATEWAY_INTERFACE"] = "CGI/1.1"; $procenv["PATH_TRANSLATED"] = "/$repo_base/$repo.git/$euri"; $procenv["REQUEST_METHOD"] = "$rmeth"; + $procenv["GIT_COMMITTER_NAME"] = $userdets["fullname"]; + $procenv["GIT_COMMITTER_EMAIL"] = $userdets["email"]; $procenv["GIT_HTTP_EXPORT_ALL"] = "1"; $procenv["QUERY_STRING"] = "$qs"; $procenv["HTTP_USER_AGENT"] = "git/1.7.1"; @@ -201,6 +270,8 @@ function gwvpmini_callGitBackend($username, $repo) $procenv["REMOTE_ADDR"] = $_SERVER["REMOTE_ADDR"]; $procenv["AUTH_TYPE"] = "Basic"; + //// error_log("PROCENV: ".print_r($procenv,true)); + if(isset($_SERVER["CONTENT_TYPE"])) { $procenv["CONTENT_TYPE"] = $_SERVER["CONTENT_TYPE"]; } else { @@ -210,7 +281,7 @@ function gwvpmini_callGitBackend($username, $repo) $procenv["CONTENT_LENGTH"] = $_SERVER["CONTENT_LENGTH"]; } - error_log("path trans'd is /$repo_base/$repo.git/$euri from $ruri with ".$_REQUEST["q"]." $strrem"); + // error_log("path trans'd is /$repo_base/$repo.git/$euri from $ruri with ".$_REQUEST["q"]." $strrem"); @@ -223,13 +294,13 @@ function gwvpmini_callGitBackend($username, $repo) while(!$untilblank&&!feof($pipes[1])) { $lines_t = fgets($pipes[1]); $lines = trim($lines_t); - error_log("got line: $lines"); + // error_log("got line: $lines"); if($lines_t == "\r\n") { $untilblank = true; - error_log("now blank"); + // error_log("now blank"); } else header($lines); if($lines === false) { - error_log("got an unexpexted exit..."); + // error_log("got an unexpexted exit..."); exit(0); } @@ -240,25 +311,32 @@ function gwvpmini_callGitBackend($username, $repo) $continue = true; if(!stream_set_blocking($fh,0)) { - error_log("cant set input non-blocking"); + // error_log("cant set input non-blocking"); } if(!stream_set_blocking($pipes[1],0)) { - error_log("cant set pipe1 non-blocking"); + // error_log("cant set pipe1 non-blocking"); } + + $stlimit = 0; + $fp = fopen("/tmp/gitup.".rand(0,4000000), "w"); // 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); + if($from_client_data !== false) { + fwrite($pipes[0], $from_client_data); + fwrite($fp, $from_client_data); + } fflush($pipes[0]); //fwrite($fl, $from_client_data); $client_len = strlen($from_client_data); } else { - error_log("client end"); + // error_log("client end"); $client_len = 0; + //$continue = false; } // do cgi @@ -278,9 +356,9 @@ function gwvpmini_callGitBackend($username, $repo) // TODO: find out why this happens $from_cgi_data = preg_replace("/^\r\n/", "", $from_cgi_data_t); if(strlen($from_cgi_data)!=strlen($from_cgi_data_t)) { - error_log("MOOOKS - we did trunc"); + // error_log("MOOOKS - we did trunc"); } else { - error_log("MOOOKS - we did not trunc"); + // error_log("MOOOKS - we did not trunc"); } $firstline = false; } @@ -292,7 +370,7 @@ function gwvpmini_callGitBackend($username, $repo) } $cgi_len = strlen($from_cgi_data); } else { - error_log("cgi end"); + // error_log("cgi end"); $cgi_len = 0; } @@ -300,11 +378,14 @@ function gwvpmini_callGitBackend($username, $repo) else { if($client_len == 0 && $cgi_len == 0) { usleep(200000); - error_log("sleep tick"); + // error_log("sleep tick"); + $stlimit++; + if($stlimit > 2) $continue = false; } else { - error_log("sizes: $client_len, $cgi_len"); + $stlimit = 0; + // error_log("sizes: $client_len, $cgi_len"); if($cgi_len > 0) { - error_log("from cgi: \"$from_cgi_data\""); + // error_log("from cgi: \"$from_cgi_data\""); } } } @@ -332,18 +413,18 @@ function gwvpmini_repoExists($name) // 0 - anyone can clone/read, only owner can write // 1 - noone can clone/read, repo is visible (i.e. name), only owner can read/write repo // 2 - only owner can see anything -function gwvpmini_createGitRepo($name, $ownerid, $desc) +function gwvpmini_createGitRepo($name, $ownerid, $desc, $clonefrom) { $repo_base = gwvpmini_getConfigVal("repodir"); // phew, this works, but i tell you this - bundles arent quite as nice as they should be - error_log("would create $repo_base/$name.git"); + // error_log("would create $repo_base/$name.git"); exec("/usr/bin/git init $repo_base/$name.git --bare > /tmp/gitlog 2>&1"); chdir("$repo_base/$name.git"); exec("/usr/bin/git update-server-info"); // gwvpmini_AddRepo($reponame, $repodesc, $repoowner, $defaultperms = 0) - gwvpmini_AddRepo($name, $desc, $ownerid); + gwvpmini_AddRepo($name, $desc, $ownerid, $clonefrom); return true; }