Array ('pass' => 'a94a8fe5ccb19ba61c4c0873d391e987982fbbd3', 'name' => 'Test User', 'email' => 'test@somewhere')
);
// passwords are sha1 hashes, uncomment next line to create the password hash:
// exit (sha1 ('my pass'));
// author for when you don't use authentication
$author = $auth ['testuser2']['name'] . '<' . $auth ['testuser2']['email'] . '>'; // 'firstname lastname ERROR: '.$str . "
\n";
return false;
}
function debug ($input = '', $force = false) {
global $debug;
if ($force === false && $debug === false)
return true;
if (is_string ($input))
echo "$input
";
elseif (is_array ($input)) {
echo "";
print_r ($input);
echo "
";
} else {
echo "";
var_dump ($input);
echo "
";
}
}
///////////////////////////////
function make_one_hash (&$rs) {
$str = '';
if (isset ($rs ['lines']) && is_array ($rs ['lines']))
foreach ($rs ['lines'] as $v)
$str .= $v ['hash'];
$str .= $rs ['outputhash'];
$rs ['hash'] = sha1 ($str);
}
function get_status ($disabled = false, $makediff = true, $stats = false) {
global $somethingstaged, $gitpath;
static $firstrun;
if (!isset ($firstrun))
$firstrun = true;
else
$firstrun = false;
if (!$firstrun)
echo close_and_add_filelist_parent ();
$result = Array ('lines' => Array ());
$somethingstaged = false;
clearstatcache ();
$h = start_command ($gitpath, Array ('status', '--porcelain'), false);
if ($h === false)
return error ('command failed to start');
else {
close_stdin ($h);
$err = '';
$out = '';
while (!is_done ($h)) {
$line = get_stdout_line ($h);
if ($line != '') {
debug ($line);
$parsed = parse_line ($line);
$int = interpret ($parsed, $disabled, $makediff, $stats);
if ($int !== false) {
if (isset ($int ['dir'])) {
$list = Array ();
$list = add_directory_listing ($parsed ['dir'], $disabled, $makediff, $stats, $list);
$result ['lines'] = array_merge ($result ['lines'], $list);
} else
$result ['lines'][] = $int;
}
flush ();
}
}
$exit = get_exit_code ($h);
if ($exit !== 0) {
$errors = get_all_data ($h, Array ('stdout', 'stderr'));
if (!is_array ($errors))
$errors = Array ();
return error ("command failed with exitcode ".$exit.":\n".implode (' ', $errors));
}
$result ['output'] = get_all_data ($h);
$result ['outputhash'] = sha1 ($result['output']);
$result ['disable_commit'] = false;
make_one_hash ($result);
}
clean_up ($h);
return $result;
}
function get_file_hash ($file) {
if (file_exists ($file))
return sha1 ($file . sha1_file ($file));
return false;
}
function parse_line ($str) {
global $sha1_empty_string;
$str = rtrim ($str);
$file = substr ($str, 3);
if (file_exists ($file) ) {
$res = Array ('strstaged' => $str [0], 'strmodified' => $str [1], 'str' => $str);
$type = filetype ($file);
if ($type === 'file') {
$res ['hash'] = get_file_hash ($file);
$res ['file'] = $file;
} elseif ($type == 'dir') {
$res ['dir'] = $file;
} else
$res = Array ('str' => $str);
return $res;
} elseif ($str [0] == ' ' && $str [1] == 'D') {
$res = Array ('strstaged' => ' ', 'strmodified' => 'D', 'str' => $str, 'file' => $file, 'hash' => sha1 ($file . $sha1_empty_string));
} elseif ($str [0] == 'D' && $str [1] == ' ') {
$res = Array ('strstaged' => 'D', 'strmodified' => ' ', 'str' => $str, 'file' => $file, 'hash' => sha1 ($file . $sha1_empty_string));
} elseif ($str [0] == 'R') {
$sub = substr ($str, 4);
$arr = explode (' -> ', $sub);
$res = Array ('strstaged' => 'R', 'strmodified' => ' ', 'str' => $str, 'oldfile' => $arr [0], 'newfile' => $arr [1], 'hash' => get_file_hash ($arr[1]), 'file' => $arr[1]);
} elseif ($str [0] == 'C') {
preg_match ('/(.*) -> (.*)/', $file, $filenames);
$res = Array ('strstaged' => $str [0], 'strmodified' => ' ', 'oldfile' => $filenames [1], 'newfile' => $filenames [2], 'str' => $str, 'hash' => get_file_hash ($filenames [2]), 'file' => $filenames [2]);
} else
$res = Array ('str' => $str);
return $res;
}
function interpret ($parsed, $disabled = false, $makediff = true, $stats = false) {
global $gitpath;
if (isset ($parsed ['file'])) {
if ($parsed ['strstaged'] == '?' || $parsed ['strstaged'] == 'A') {
if ($makediff) {
$command = 'diff';
$args = Array ('-u', '/dev/null', $parsed ['file']);
if (isset ($parsed ['staged']) && $parsed ['staged'] == 'A') {
$args = Array ('diff', '--cached', $parsed ['file']);
$command = $gitpath;
}
$h = start_command ($command, $args);
close_stdin ($h);
$diff = htmlentities (get_all_data ($h));
clean_up ($h);
} else
$diff = false;
$parsed ['state'] = set_state ($parsed ['strmodified'], $parsed ['strstaged']);
$parsed ['staged'] = set_staged ($parsed ['strmodified'], $parsed ['strstaged']);
list ($str, $prefix) = html_file ($parsed ['file'], $parsed ['state'], $parsed ['staged'], $parsed ['hash'], $diff, $disabled);
echo $str;
$parsed ['prefix'] = $prefix;
} elseif (( $parsed ['strmodified'] == 'M') || ($parsed ['strstaged'] == 'M' && $parsed ['strmodified'] == ' ')) {
if ($makediff) {
$args = Array ('diff', $parsed ['file']);
if ($parsed ['strstaged'] == 'M' && $parsed ['strmodified'] == ' ')
$args = Array ('diff', '--cached', $parsed ['file']);
$h = start_command ($gitpath, $args);
close_stdin ($h);
$str = get_all_data ($h);
$diff = htmlentities ($str);
$exit = get_exit_code ($h);
clean_up ($h);
} else
$diff = false;
$parsed ['state'] = set_state ($parsed ['strmodified'], $parsed ['strstaged']);
$parsed ['staged'] = set_staged ($parsed ['strmodified'], $parsed ['strstaged']);
list ($str, $prefix) = html_file ($parsed ['file'], $parsed ['state'], $parsed ['staged'], $parsed ['hash'], $diff, $disabled);
echo $str;
$parsed ['prefix'] = $prefix;
} elseif ($parsed ['strmodified'] == 'D') {
if ($makediff) {
$args = Array ('diff', '--', $parsed ['file']);
$h = start_command ($gitpath, $args);
close_stdin ($h);
$str = get_all_data ($h);
$diff = htmlentities ($str);
$exit = get_exit_code ($h);
clean_up ($h);
} else
$diff = false;
$parsed ['state'] = set_state ($parsed ['strmodified'], $parsed ['strstaged']);
$parsed ['staged'] = set_staged ($parsed ['strmodified'], $parsed ['strstaged']);
list ($str, $prefix) = html_file ($parsed ['file'], $parsed ['state'], $parsed ['staged'], $parsed ['hash'], $diff, $disabled);
echo $str;
$parsed ['prefix'] = $prefix;
} elseif ($parsed ['strstaged'] == 'D') {
if ($makediff) {
$args = Array ('diff', '--cached', '--', $parsed ['file']);
$h = start_command ($gitpath, $args);
close_stdin ($h);
$str = get_all_data ($h);
$diff = htmlentities ($str);
$exit = get_exit_code ($h);
clean_up ($h);
} else
$diff = false;
$parsed ['state'] = set_state ($parsed ['strmodified'], $parsed ['strstaged']);
$parsed ['staged'] = set_staged ($parsed ['strmodified'], $parsed ['strstaged']);
list ($str, $prefix) = html_file ($parsed ['file'], $parsed ['state'], $parsed ['staged'], $parsed ['hash'], $diff, $disabled);
echo $str;
$parsed ['prefix'] = $prefix;
} elseif ($parsed ['strstaged'] == 'R') {
if ($makediff) {
$args = Array ('diff', '--cached', '--', $parsed ['file']);
$h = start_command ($gitpath, $args);
close_stdin ($h);
$str = get_all_data ($h);
$diff = htmlentities ($str);
$exit = get_exit_code ($h);
clean_up ($h);
} else
$diff = false;
$parsed ['state'] = set_state ($parsed ['strmodified'], $parsed ['strstaged']);
$parsed ['staged'] = set_staged ($parsed ['strmodified'], $parsed ['strstaged']);
list ($str, $prefix) = html_file ($parsed ['file'], $parsed ['state'], $parsed ['staged'], $parsed ['hash'], $diff, $disabled);
echo $str;
$parsed ['prefix'] = $prefix;
} elseif ($parsed ['strstaged'] == 'C') {
$info = htmlentities ('file ' . $parsed ['newfile'] . ' is a copy of ' . $parsed ['oldfile']);
$parsed ['state'] = set_state ($parsed ['strmodified'], $parsed ['strstaged']);
$parsed ['staged'] = set_staged ($parsed ['strmodified'], $parsed ['strstaged']);
list ($str, $prefix) = html_file ($parsed ['file'], $parsed ['state'], $parsed ['staged'], $parsed ['hash'], $info, $disabled);
echo $str;
$parsed ['prefix'] = $prefix;
} else
interpret_not_supported ($parsed, __FILE__, __LINE__);
} else {
if (isset ($parsed ['dir']) && $parsed ['strmodified'] == '?' && $parsed ['strstaged'] == '?') {
// is a dir, handled outside this function
} else {
// if type == 'link' -> readlink ( see Github issue #3 )
interpret_not_supported ($parsed, __FILE__, __LINE__);
}
}
return $parsed;
}
function add_directory_listing ($dir, $disabled, $makediff, $stats, &$list) {
global $diffpath;
$handle = opendir ($dir);
while (($entry = readdir ($handle)) !== false)
if ($entry != '.' && $entry != '..') {
$type = filetype ($dir . $entry);
if ($type == 'file') {
$file = $dir . $entry;
$hash = get_file_hash ($file);
$parsed = Array ('file' => $file, 'hash' => $hash);
$parsed ['state'] = 'New';
$parsed ['staged'] = 'N';
if ($makediff) {
$command = $diffpath;
$args = Array ('-u', '/dev/null', $parsed ['file']);
$h = start_command ($command, $args);
close_stdin ($h);
$diff = htmlentities (get_all_data ($h));
clean_up ($h);
} else
$diff = false;
list ($str, $prefix) = html_file ($file, $parsed ['state'], $parsed ['staged'], $parsed ['hash'], $diff, $disabled);
echo $str;
$parsed ['prefix'] = $prefix;
$list [] = $parsed;
} elseif ($type == 'dir') {
add_directory_listing ($dir . $entry . '/', $disabled, $makediff, $stats, $list);
} else
interpret_not_supported ($dir . $entry, __FILE__, __LINE__);
}
return $list;
}
function interpret_not_supported ($debug, $file = false, $line = false) {
if ($file === false)
$file = '';
else
$file = $file . ': ';
if ($line === false)
$line = '';
else
$line = $line . ': ';
error ($file.$line.'Not implemented: Only changed, added, deleted files is supported right now. Found something else in the output of git status, debug output is below. Sorry.');
debug ($debug, true);
exit ();
}
function set_state ($modified, $staged) {
$rv = $modified; // last resort ?
if ($modified == '?' || $staged == 'A')
$rv = 'New';
if ($modified == 'D' || $staged == 'D')
$rv = 'Deleted';
if ($modified == 'M' || $staged == 'M')
$rv = 'Modified';
if ($staged == 'R')
$rv = 'Renamed';
if ($staged == 'C')
$rv = 'Copied';
return $rv;
}
function set_staged ($modified, $staged) {
$rv = $staged; // last resort ?
if ($staged == ' ' || $staged == '?')
$rv = 'N';
if ($staged == 'Y' || $staged == 'M' || $staged == 'A' || $staged == 'D' || $staged == 'R' || $staged == 'C')
$rv = 'Y';
return $rv;
}
///////////////////////////////
function start_command ($command, $argarr, $blocking = true) {
$descriptorspec = array(
0 => Array ('pipe', 'r'), // stdin
1 => Array ('pipe', 'w'), // stdout
2 => Array ('pipe', 'w'), // stderr
);
$pipes = Array ();
$args = '';
foreach ($argarr as $v)
$args .= ' '. escapeshellarg ($v);
$command = escapeshellcmd ($command);
$proc = proc_open($command . ' ' . $args, $descriptorspec, $pipes);
if (is_resource($proc)) {
if ($blocking === false) {
stream_set_blocking ($pipes [0], 0);
stream_set_blocking ($pipes [1], 0);
stream_set_blocking ($pipes [2], 0);
} else {
// should already be the default
stream_set_blocking ($pipes [0], 1);
stream_set_blocking ($pipes [1], 1);
stream_set_blocking ($pipes [2], 1);
}
global $_handles, $_handlecount;
$h = ++$_handlecount;
$_handles [$h] = Array ('proc' => $proc, 0 => $pipes [0], 1 => $pipes [1], 2 => $pipes [2]);
return $h;
} else
return false;
}
function end_command ($h) {
global $_handles;
if (!isset ($_handles [$h]))
return false;
// It is important that you close any pipes before calling
// proc_close in order to avoid a deadlock
@fclose ($_handles [$h][0]);
@fclose ($_handles [$h][1]);
@fclose ($_handles [$h][2]);
if ((!isset ($_handles [$h]['running'])) || ($_handles [$h]['running'] !== false))
$rv = proc_close ($_handles [$h] ['proc']);
else
$rv = $_handles [$h]['rv'];
$_handles [$h]['running'] = false;
return $rv;
}
function is_done ($h) {
global $_handles;
if (!isset ($_handles [$h]))
return true; // closest thing to an error
if (isset ($_handles [$h]['done']) && $_handles [$h]['done'] === true)
return true;
return false;
}
function put_in_stdin ($h, $str) {
global $_handles;
if (!isset ($_handles [$h]))
return false;
return fwrite ($_handles [$h][0]);
}
function close_stdin ($h) {
global $_handles;
if (!isset ($_handles [$h]))
return false;
return @fclose ($_handles [$h][0]);
}
function get_stdout_line ($h) {
return _get_line ($h, 0);
}
function get_stderr_line ($h) {
return _get_line ($h, 1);
}
function _get_line ($h, $num) {
global $_handles;
if (!isset ($_handles [$h]))
return ""; // closest thing to an error
$rv = _get_data ($h);
if ($rv === false)
return ""; // closest thing to an error
return $rv [$num];
}
function _get_data ($h) {
global $_handles;
if (!isset ($_handles [$h]))
return false;
$read = array($_handles[$h][1], $_handles[$h][2]);
$write = NULL;
$except = NULL;
$wait = 120;
$rv = Array ('', '');
if (false === ($num_changed_streams = stream_select($read, $write, $except, $wait))) {
/* Error handling */
$_handles [$h]['done'] = true; // ?
return error ("error occured");
} elseif ($num_changed_streams > 0) {
/* At least on one of the streams something interesting happened */
$alleof = true;
$newout = fgets ($_handles[$h][1], 8192);
$newerr = fgets ($_handles[$h][2], 8192);
if (!isset ($_handles[$h]['stdout']))
$_handles[$h]['stdout'] = '';
if (!isset ($_handles[$h]['stderr']))
$_handles[$h]['stderr'] = '';
if ($newout !== false)
$_handles[$h]['stdout'] .= $newout;
if ($newerr !== false)
$_handles[$h]['stderr'] .= $newerr;
if (!feof ($_handles[$h][1]) && $newout != '')
$alleof = false;
if (!feof ($_handles[$h][2]) && $newerr != '')
$alleof = false;
if ($newout != '')
$rv [0] = $newout;
if ($newerr != '')
$rv [1] = $newerr;
if ($alleof) {
$_handles [$h]['done'] = true;
$status = proc_get_status ($_handles[$h] ['proc']);
if ($status ['running'] === false)
$return_value = $status ['exitcode'];
else
$return_value = end_command ($h);
$_handles [$h]['rv'] = $return_value;
$_handles [$h]['running'] = false;
}
} else
debug ( "hier" );
return $rv;
}
function get_all_data ($h, $intype = 'stdout') {
global $_handles;
if (!isset ($_handles [$h]))
return false;
if (!is_array ($intype))
$types = Array ($intype);
else
$types = $intype;
$rv = Array ();
if (isset ($_handles [$h]['done']) && $_handles [$h]['done']) {
foreach ($types as $k => $type)
$rv [$k] = $_handles [$h][$type];
if (!is_array ($intype))
return $rv [0];
return $rv;
}
// XXX BUG: possibly a second call to function will fail, if done was false the first time and done = true second time.
foreach ($types as $k => $type) {
// if $rv == false we return false at the end
if ($type == 'stdout')
$rv [$k] = stream_get_contents ($_handles[$h][1]);
elseif ($type == 'stderr')
$rv [$k] = stream_get_contents ($_handles[$h][2]);
}
$status = proc_get_status ($_handles[$h]['proc']);
if ($status ['running'] === false)
$return_value = $status ['exitcode'];
else
$return_value = end_command ($h);
$_handles [$h]['rv'] = $return_value;
$_handles [$h]['running'] = false;
if (!is_array ($intype))
return $rv [0];
return $rv;
}
function get_exit_code ($h) {
global $_handles;
if (!isset ($_handles [$h]))
return false;
if (!isset ($_handles [$h]['rv']))
return false;
return $_handles [$h]['rv'];
}
function clean_up ($h) {
global $_handles;
if (!isset ($_handles [$h]))
return false;
if (isset ($_handles [$h]['done']) && $_handles [$h]['done'] !== true)
end_command ($h);
unset ($_handles [$h]);
}
///////////////////////////////
function handle_basic_auth ($realm = 'private area') {
global $auth;
if (isset ($_SERVER['PHP_AUTH_USER'])
&& isset ($_SERVER['PHP_AUTH_PW'])
&& isset ($auth [$_SERVER['PHP_AUTH_USER']])
&& $auth [$_SERVER['PHP_AUTH_USER']]['pass'] === sha1 ($_SERVER['PHP_AUTH_PW'])
) {
return $auth [$_SERVER['PHP_AUTH_USER']]['name'] . ' <'.$auth [$_SERVER['PHP_AUTH_USER']]['email'].'>';
}
header('WWW-Authenticate: Basic realm="'.$realm.'"');
header('HTTP/1.0 401 Unauthorized');
exit ('You did not supply any or the wrong username/password combination');
}
function handle_htpasswd_auth () {
global $auth;
if (!isset ($_SERVER['REMOTE_USER']))
exit ('htpasswd not setup correctly');
if (isset ($_SERVER['REMOTE_USER']) && isset ($auth [$_SERVER ['REMOTE_USER']]))
return $auth [$_SERVER ['REMOTE_USER']]['name'] . ' <'.$auth [$_SERVER ['REMOTE_USER']]['email'].'>';
exit ('htpasswd user unknown to git-webcommit');
}
///////////////////////////////
function html_js_remove_container ($prefix) {
return <<