xaizek / rocketgit (License: AGPLv3+) (since 2018-12-09)
Light and fast Git hosting solution suitable to serve both as a hub or as a personal code storage with its tickets, pull requests, API and much more.
<root> / root / index.php (83f8d97a064fdce28ff5f3c8bffcf4dc0be523c8) (6,828B) (mode 100644) [raw]
<?php
error_reporting(E_ALL);
ini_set("track_errors", "On");
set_time_limit(30);

$peak0 = memory_get_peak_usage();

$rg = array();

require_once("/etc/rocketgit/config.php");
$INC = dirname(__FILE__) . "/../inc";
require_once($INC . "/init.inc.php");
require_once($INC . "/log.inc.php");
include_once($INC . "/sql.inc.php");
include_once($INC . "/struct.inc.php");
include_once($INC . "/user.inc.php");
include_once($INC . "/repo.inc.php");
include_once($INC . "/keys.inc.php");
include_once($INC . "/token.inc.php");
include_once($INC . "/prof.inc.php");
include_once($INC . "/mr.inc.php");
include_once($INC . "/bug.inc.php");
include_once($INC . "/fixes.inc.php");
include_once($INC . "/plan.inc.php");
include_once($INC . "/admin.inc.php");
include_once($INC . "/api.inc.php");
include_once($INC . "/apikeys.inc.php");
include_once($INC . "/demo.inc.php");
include_once($INC . "/ver.php");

rg_prof_start("MAIN");

rg_log_set_file($rg_log_dir . "/web.log");

// database connection
rg_sql_app("rg-web");
$db = rg_sql_open($rg_sql);

// Store configuration into 'rg'
if (!isset($rg_account_email_confirm))
	$rg_account_email_confirm = 1;
if (rg_var_uint('force_confirm') == 1)
	$rg_account_email_confirm = 1;
$rg['rg_account_email_confirm'] = $rg_account_email_confirm;
if (!isset($rg_account_allow_creation))
	$rg_account_allow_creation = 0;
$rg['rg_account_allow_creation'] = $rg_account_allow_creation;

// Init variables
$THEME_URL = "/themes/" . $rg_theme;
$rg['rg_redirect_html'] = 0;
$rg['rg_theme_url'] = $THEME_URL;
$rg['login_ui'] = rg_user_empty();
$rg['target_ui'] = array("ok" => 1, "exists" => 0, "uid" => 0);
$rg['ri'] = array("repo_id" => 0, "uid" => 0);
$rg['bug'] = array("bug_id" => 0);
$rg['debug'] = rg_var_uint('rg_debug');
$rg['base_url'] = rg_base_url();

// We have variable 'vv' passed from webserver - build 'op' and rest of paras
$sparas = rg_var_str("vv");
rg_log("DEBUG: sparas=$sparas");
$rg['current_url'] = rawurlencode($sparas);
$rg['url'] = '/op';
$paras = explode("/", trim($sparas, "/"));
$_t = empty($paras) ? "" : $paras[0];
if (strcmp($_t, "op") == 0) {
	array_shift($paras);
	$_op = empty($paras) ? '' : array_shift($paras);
} else {
	$_op = '';
}

$rg['doit'] = rg_var_uint("doit");
$rg['sid'] = rg_var_cookie_re("sid", "/[^A-Za-z0-9]/");
$rg['token'] = rg_var_re("token", "A-Za-z0-9");
$user = ""; $repo = ""; $organization = 0; // TODO: those are really used?

//rg_log_ml("rg: " . print_r($rg, TRUE));

$rg['ua'] = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : "";
$rg['ip'] = isset($_SERVER['REMOTE_ADDR']) ? rg_fix_ip($_SERVER['REMOTE_ADDR']) : '';
$req = $_REQUEST;
if (isset($req['pass']))
	$req['pass'] = '*****';
if (isset($req['old_pass']))
	$req['old_pass'] = '*****';
if (isset($req['pass1']))
	$req['pass1'] = '*****';
if (isset($req['pass2']))
	$req['pass2'] = '*****';
rg_log("DEBUG: _REQUEST: " . rg_array2string($req));
rg_log("DEBUG: _COOKIE: " . rg_array2string($_COOKIE));
rg_log($rg['ip'] . " ver=$rocketgit_version");

// Try to detect if we cloning by http(s)
rg_log_ml('_SERVER: ' . print_r($_SERVER, TRUE));
$rg['ct'] = isset($_SERVER['CONTENT_TYPE']) ? $_SERVER['CONTENT_TYPE'] : '';


$r = rg_struct_ok($db);
if ($r === FALSE) {
	echo "Internal error; please try again later.";
	exit(0);
}

// Is it a http push/fetch?
$r = rg_user_http_git($db, $rg, $paras);
if ($r === TRUE) {
	rg_prof_end("MAIN");
	rg_prof_log();
	exit(0);
}

// API dispatch
if (strcmp($_op, 'api') == 0) {
	// https://en.wikipedia.org/wiki/Cross-origin_resource_sharing
	header('Access-Control-Allow-Origin: *');
	header('Access-Control-Allow-Headers: Authorization');
	header('Content-Type: application/json;charset=UTF-8');

	$_auth = isset($_SERVER['HTTP_AUTHORIZATION']) ? $_SERVER['HTTP_AUTHORIZATION'] : '';
	$_t = explode(' ', $_auth, 2);
	$_user = trim($_t[0]);
	if (isset($_t[1]))
		$_key = trim($_t[1]);
	else
		$_key = '';
	rg_log('api user=[' . $_user . '] key=[' . $_key . ']!');
	$body = '';
	while (1) {
		$ui = rg_user_info($db, 0, $_user, '');
		if ($ui['ok'] != 1) {
			$body = array('error' => rg_user_error());
			echo json_encode($body, JSON_PRETTY_PRINT) . "\n";
			break;
		}
		if ($ui['exists'] != 1) {
			$body = array('error' => 'invalid user or apikey');
			echo json_encode($body, JSON_PRETTY_PRINT) . "\n";
			break;
		}

		$key_id = rg_ak_valid($db, $ui['uid'], $_key);
		if ($key_id === FALSE) {
			$body = array('error' => 'invalid user or apikey');
			echo json_encode($body, JSON_PRETTY_PRINT) . "\n";
			break;
		}

		$post = @file_get_contents("php://input");
		rg_log('post=' . $post);

		$d = @json_decode($post);
		if ($d === NULL) {
			rg_log('error parsing!');
			$body = array('error' => json_last_error_msg());
			echo json_encode($body, JSON_PRETTY_PRINT) . "\n";
			break;
		}

		rg_ak_update_use($db, $ui['uid'], $key_id, $rg['ip'], $post);

		// we need to transform the object 'd' into an array
		$d2 = array();
		foreach ($d as $k => $v)
			$d2[$k] = $v;
		$d2['connect_uid'] = $ui['uid'];
		$d2['ip'] = $rg['ip'];
		echo rg_api($db, $d2);
		break;
	}

	rg_prof_end("MAIN");
	rg_prof_log();
	exit(0);
}

rg_user_login_by_sid($db, $rg);
rg_log("After login_by_sid, login_ui=" . rg_array2string($rg['login_ui']));
// If user provided an old/expired sid, we generate a new one, pre-login
if (($rg['login_ui']['uid'] == 0) && (strncmp($rg['sid'], "X", 1) != 0))
	$rg['sid'] = "";
if (empty($rg['sid'])) {
	$rg['sid'] = rg_user_set_session_cookie($db, 0 /*uid*/, 600, FALSE);
	rg_log("User has no sid, generate one [" . $rg['sid'] . "]");
}

$body = "";

// Some variables from the database
$rg['first_install_text'] = "?";

$r = rg_state_get($db, "first_install");
if ($r === FALSE) {
	// Probably we cannot connect to database/cache
	$body .= rg_template('admin/db_error.html', TRUE /*xss*/);
} else if ($r === '') {
	$body .= rg_init($db, $rg);
} else {
	$rg['first_install_text'] = gmdate("Y-m-d", $r);

	rg_log("Dispatching to [$_op]");
	include($INC . "/dispatch/dispatch.php");
}

if ($rg['login_ui']['uid'] > 0) {
	$rg['logout_token'] = rg_token_get($db, $rg, 'logout');
} else {
	$rg['logout_token'] = '';
}


$rg['HTML:rg_body'] = $body;
$_c = rg_template("index.html", $rg, TRUE /* xss */);

// TODO: really?!
header('Cache-Control: private, no-cache');

// Caching
$proto = rg_var_str('SERVER_PROTOCOL');
if (strcmp($proto, 'HTTP/1.1') == 0) {
	$we_have = sha1($_c);
	if (isset($_SERVER['HTTP_IF_NONE_MATCH']))
		$client_have = $_SERVER['HTTP_IF_NONE_MATCH'];
	else
		$client_have = '';

	if (strcmp($client_have, $we_have) == 0) {
		rg_log('CACHE: Client has the latest version; no need to resend');
		header('HTTP/1.1 304 Not modified');
	} else {
		header('ETag: ' . $we_have);
		echo $_c;
	}
} else {
	rg_log('WARN: Un-handled protocol ' . $proto);
	echo $_c;
}

rg_prof_end("MAIN");
rg_prof_log();
?>
Hints

Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://code.reversed.top/user/xaizek/rocketgit

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@code.reversed.top/user/xaizek/rocketgit

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a pull request:
... clone the repository ...
... make some changes and some commits ...
git push origin master