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.
Commit 852d93d3bf7995ca427982f4ec1aa2bd1bf75063

Bulk update.

Author: Catalin(ux) M. BOIE
Author date (UTC): 2011-04-06 15:22
Committer: Catalin(ux) M. BOIE
Commit date (UTC): 2011-04-06 15:22
Tree: 587e6034519bb1d334fcb6196d03d92d142d1760
Parents: aae5180a3eed608170972b9a49bf19be37353141
File Lines added Lines deleted
README 11 1
TODO 11 6
admin/sql.php 11 8
inc/admin/repos/repos.php 1 2
inc/git.inc.php 100 0
inc/keys.inc.php 80 9
inc/keys/add.form.php 3 14
inc/keys/keys.php 50 0
inc/repo.inc.php 437 76
inc/repo/repo.form.php 26 9
inc/repo/repo.php 32 8
inc/repo/repo_page.php 112 0
inc/repo/rights.form.php 7 8
inc/sess.inc.php 8 4
inc/state.inc.php 21 0
inc/user.inc.php 12 4
inc/util.inc.php 29 0
inc/xlog.inc.php 4 1
root/index.php 23 8
root/themes/default/main.css 1 5
samples/config.php 15 2
samples/cron 1 0
samples/gg 1 1
scripts/cron.php 37 18
scripts/q.php 90 0
scripts/ssh.php 3 2
tests/Makefile 1 0
tests/keys.php 2 1
tests/repo.php 77 0

File README changed (mode: 100644) (index 73843b5..29918cb)
... ... client does pull:
2 2 SSH_ORIGINAL_COMMAND=git-upload-pack '/aa/bb/cc/dd.git' SSH_ORIGINAL_COMMAND=git-upload-pack '/aa/bb/cc/dd.git'
3 3
4 4 client does push: client does push:
5 SSH_ORIGINAL_COMMAND=git-receive-pack '/aa/bb/cc/dd.git'
5 SSH_ORIGINAL_COMMAND=git-receive-pack '/aa/bb/cc/dd.git'
6
7 == Rights ==
8 A - Admin - can edit repo info, can add/remove rights for users
9 F - Fetch
10 P - Push
11 D - Delete branch
12 Z - Forced push (history rewriting)
13
14 Notes:
15 - For anonymous access, we store rights directly in repo info row.

File TODO changed (mode: 100644) (index 070b936..a195890)
2 2 [ ] Validate e-mails. [ ] Validate e-mails.
3 3 [ ] Validate repo names. [ ] Validate repo names.
4 4 [ ] Validate user names. [ ] Validate user names.
5 [ ] XSS protection for every cell.
6 [ ] You cannot admin rights of a repository if is not yours.
5 7 [ ] [ ]
6 8
7 9 == Low priority == == Low priority ==
10 [ ] Allow to recover a deleted repository.
11 [ ] Deny access in all functions to deleted repositories.
8 12 [ ] Count the numbers of clones/pushes/pulls. [ ] Count the numbers of clones/pushes/pulls.
9 13 [ ] Add memcache caching for all database lookups. [ ] Add memcache caching for all database lookups.
10 14 [ ] Allow to configure the limit of the patch size to prevent abuses. [ ] Allow to configure the limit of the patch size to prevent abuses.
11 15 [ ] Allow to configure to refuse binary files. [ ] Allow to configure to refuse binary files.
12 [ ] Allow to configure to refuse commits with broken spcaes/tab mixes.
13 [ ] Add a repo_prop_set/get function that will set/get a file in .git folder. THis way we can
16 [ ] Allow to configure to refuse commits with broken spaces/tab mixes.
17 [ ] Add a repo_prop_set/get function that will set/get a file in .git folder. This way we can
14 18 speed up some lookups (no need for database). Hm. speed up some lookups (no need for database). Hm.
15 19 [ ] When we delete an repository, we will do repo_prop_set(repo, disabled) and we will [ ] When we delete an repository, we will do repo_prop_set(repo, disabled) and we will
16 20 return OK, in the background we will do the removing. Do not forget to also remove clones. Hm. return OK, in the background we will do the removing. Do not forget to also remove clones. Hm.
17 [ ] SSH keys section.
18 21 [ ] E-mail aliases section. [ ] E-mail aliases section.
19 22 [ ] User details section (full name, e-mail, blog, avatar, mail notifications). [ ] User details section (full name, e-mail, blog, avatar, mail notifications).
20 23 [ ] Change password section. [ ] Change password section.
 
22 25 [ ] The cron will have to: [ ] The cron will have to:
23 26 [ ] Compute disk usage, ignoring hard links. Hm. Probably we will add [ ] Compute disk usage, ignoring hard links. Hm. Probably we will add
24 27 only the owner, even if the files have multiple links. TBD. only the owner, even if the files have multiple links. TBD.
25 [ ] VACUUM tables.
26 28 [ ] [ ]
27 [ ] UTF-8 checks.
29 [ ] UTF-8 checks of patches.
28 30 [ ] W3C validation on all pages. [ ] W3C validation on all pages.
29 31 [ ] Validate user and repo names. Probably other things. [ ] Validate user and repo names. Probably other things.
30 32 [ ] What happens if a user is suspended? Do we allow forgot pass sending? [ ] What happens if a user is suspended? Do we allow forgot pass sending?
31 33 [ ] Do not allow session updates/any command if user is suspended after his/her login. [ ] Do not allow session updates/any command if user is suspended after his/her login.
32 34 [ ] Timeout for connections (ssh/git-daemon/etc.)! [ ] Timeout for connections (ssh/git-daemon/etc.)!
33 35 [ ] Check if we have to respect 4HEXA also on SSH. I think not. [ ] Check if we have to respect 4HEXA also on SSH. I think not.
34 [ ] Limit number of simultaneously connection per repo and per user. maybe also the time!
36 [ ] Limit number of simultaneously connection per repo and per user. Maybe also the time!
37 [ ] Add /var/run/gg to spec file, to be created at instalation.
38 [ ] We should add a dependency on php-process?
39 [ ] Make everywhere present a "Make a suggestion" area.
35 40 [ ] [ ]

File admin/sql.php changed (mode: 100644) (index 7ff98e8..84971a1)
... ... $db = sql_open($gg_db);
12 12 if ($db === FALSE) if ($db === FALSE)
13 13 fatal("Internal error (db)!"); fatal("Internal error (db)!");
14 14
15 // create repos table
16 $sql = "CREATE TABLE repos (repo_id INTEGER PRIMARY KEY, name TEXT, uid INTEGER"
15 $sql = "CREATE TABLE repos (repo_id INTEGER PRIMARY KEY"
16 . ", name TEXT"
17 . ", uid INTEGER"
17 18 . ", itime INTEGER" . ", itime INTEGER"
18 . ", public INTEGER"
19 19 . ", disk_quota_mb INTEGER" . ", disk_quota_mb INTEGER"
20 20 . ", max_commit_size INTEGER" . ", max_commit_size INTEGER"
21 21 . ", master INTEGER" . ", master INTEGER"
22 . ", desc TEXT"
23 . ", git_dir_done INTEGER"
24 . ", default_rights TEXT"
25 . ", deleted INTEGER"
22 26 . ")"; . ")";
23 27 $res = sql_query($db, $sql); $res = sql_query($db, $sql);
24 28 if ($res === FALSE) if ($res === FALSE)
25 echo "WARN: Cannot create 'repo_access' table!\n";
29 echo "WARN: Cannot create 'repos' table!\n";
26 30
27 // create repo_access table
28 $sql = "CREATE TABLE repo_access (repo_id INTEGER, uid INTEGER, perm CHAR(1)"
31 $sql = "CREATE TABLE repo_rights (repo_id INTEGER, uid INTEGER, rights TEXT"
29 32 . ", itime INTEGER)"; . ", itime INTEGER)";
30 33 $res = sql_query($db, $sql); $res = sql_query($db, $sql);
31 34 if ($res === FALSE) if ($res === FALSE)
32 echo "WARN: Cannot create 'repo_access' table!\n";
35 echo "WARN: Cannot create 'repo_rights' table!\n";
33 36
34 37 $sql = "CREATE TABLE state (var TEXT PRIMARY KEY, value TEXT)"; $sql = "CREATE TABLE state (var TEXT PRIMARY KEY, value TEXT)";
35 38 $res = sql_query($db, $sql); $res = sql_query($db, $sql);
 
... ... $res = sql_query($db, $sql);
61 64 if ($res === FALSE) if ($res === FALSE)
62 65 echo "WARN: Cannot create 'sess' table!\n"; echo "WARN: Cannot create 'sess' table!\n";
63 66
64 $sql = "CREATE TABLE forgot_pass (token TEXT PRIMARY KEY, uid INTEGER, expire INTEGER)"
67 $sql = "CREATE TABLE forgot_pass (token TEXT PRIMARY KEY, uid INTEGER, expire INTEGER)";
65 68 $res = sql_query($db, $sql); $res = sql_query($db, $sql);
66 69 if ($res === FALSE) if ($res === FALSE)
67 70 echo "WARN: Cannot create 'forgot_pass' table!\n"; echo "WARN: Cannot create 'forgot_pass' table!\n";

File inc/admin/repos/repos.php changed (mode: 100644) (index 577cf13..23d21f7)
... ... $_admin_repos_body = "";
15 15
16 16 switch ($subsubop) { switch ($subsubop) {
17 17 case 1: // list case 1: // list
18 $_only_master = 0;
19 18 $_uid = 0; $_uid = 0;
20 $_admin_repos_body .= repo_list($db, $_admin_repos_url . "&subsubop=$subsubop", $_uid, $_only_master);
19 $_admin_repos_body .= repo_list($db, $_admin_repos_url . "&subsubop=$subsubop", $_uid);
21 20 break; break;
22 21 } }
23 22

File inc/git.inc.php added (mode: 100644) (index 0000000..71b60d9)
1 <?php
2 require_once($INC . "/util.inc.php");
3 require_once($INC . "/xlog.inc.php");
4
5 function gg_git_set_error($str)
6 {
7 global $_gg_git_error;
8
9 xlog("\tError: $str");
10 $_gg_git_error = $str;
11 }
12
13 function gg_git_error()
14 {
15 global $_gg_git_error;
16 return $_gg_git_error;
17 }
18
19 function git_install_hooks($dst)
20 {
21 xlog("git_install_hooks: dst=$dst...");
22
23 xlog("\tNot yet implemented!");
24 return TRUE;
25 }
26
27 function gg_git_init($dst)
28 {
29 xlog("git_init: dst=$dst...");
30
31 $dir = dirname($dst);
32 if (!file_exists($dir)) {
33 $r = @mkdir($dir, 0755, TRUE);
34 if ($r === FALSE) {
35 xlog("\tCannot create dir [$dir] ($php_errormsg)!");
36 return FALSE;
37 }
38 }
39
40 if (file_exists($dst . "/gg")) {
41 xlog("\tGit repo was created OK. Skip cloning.");
42 } else {
43 $cmd = "git init --bare '" . escapeshellcmd($dst) . "'";
44 xlog("\texec $cmd...");
45 $a = exec($cmd, $output, $err);
46 if ($err != 0) {
47 xlog("\tError $err (" . implode("|", $output) . " ($a)!");
48 return FALSE;
49 }
50
51 if (!@mkdir($dst . "/gg")) {
52 xlog("\tCannot create gg dir ($php_errormsg)!");
53 return FALSE;
54 }
55 }
56
57 if (git_install_hooks($dst) === FALSE)
58 return FALSE;
59
60 return TRUE;
61 }
62
63 function gg_git_clone($src, $dst)
64 {
65 xlog("git_clone: src=$src, dst=$dst...");
66
67 $dir = dirname($dst);
68 if (!file_exists($dir)) {
69 $r = @mkdir($dir, 0755, TRUE);
70 if ($r === FALSE) {
71 xlog("\tCannot create dir [$dir] ($php_errormsg)!");
72 return FALSE;
73 }
74 }
75
76 if (file_exists($dst . "/gg")) {
77 xlog("\tGit repo was created OK. Skip cloning.");
78 } else {
79 $cmd = "git clone --bare '" . escapeshellcmd($src) . "'"
80 . " '" . escapeshellcmd($dst) . "'";
81 xlog("\texec $cmd...");
82 $a = exec($cmd);
83 if ($err != 0) {
84 xlog("\tError $err (" . implode("|", $output) . " ($a)!");
85 return FALSE;
86 }
87
88 if (!@mkdir($dst . "/gg")) {
89 xlog("\tCannot create gg dir ($php_errormsg)!");
90 return FALSE;
91 }
92 }
93
94 if (git_install_hooks($dst) === FALSE)
95 return FALSE;
96
97 return TRUE;
98 }
99
100 ?>

File inc/keys.inc.php changed (mode: 100644) (index 507b9c7..92fd4d2)
... ... function keys_error()
19 19 } }
20 20
21 21 /* /*
22 * Generates the fingerprint of a key
23 */
24 function keys_fingerprint($key)
25 {
26 $v = explode(" ", $key);
27
28 $decoded = base64_decode(trim($v[1]));
29 $digest = md5($decoded);
30
31 $a = array();
32 for ($i = 0; $i < 16; $i++)
33 $a[] = substr($digest, $i * 2, 2);
34
35 return implode(":", $a);
36 }
37
38 /*
22 39 * Remove a key from database * Remove a key from database
23 40 */ */
24 41 function keys_remove($db, $uid, $key_id) function keys_remove($db, $uid, $key_id)
 
... ... function keys_add($db, $uid, $key)
71 88 /* /*
72 89 * Regenerates authorized_keys files * Regenerates authorized_keys files
73 90 */ */
74 function keys_regen($db, $file)
91 function keys_regen($db)
75 92 { {
76 $tmp = $file . ".tmp";
77 $f = @fopen($tmp, "w+");
78 if (!$f)
93 global $gg_keys_file;
94 global $gg_scripts;
95
96 $dirty = state_get($db, "authorized_keys");
97 if ($dirty == 0)
98 return TRUE;
99
100 $tmp = $gg_keys_file . ".tmp";
101 $f = @fopen($tmp, "w");
102 if ($f === FALSE) {
103 keys_set_error("Cannot open file $tmp ($php_errormsg)!");
104 return FALSE;
105 }
106
107 if (chmod($tmp, 0600) === FALSE) {
108 keys_set_error("Cannot chmod tmp file ($php_errmsg)!");
79 109 return FALSE; return FALSE;
110 }
80 111
81 112 $sql = "SELECT uid, key FROM keys"; $sql = "SELECT uid, key FROM keys";
82 113 $res = sql_query($db, $sql); $res = sql_query($db, $sql);
114 if ($res === FALSE) {
115 keys_set_error("Cannot query (" . sql_error() . ")");
116 return FALSE;
117 }
83 118 while (($row = sql_fetch_array($res))) { while (($row = sql_fetch_array($res))) {
84 $buf = "command=\"/usr/bin/xxx " . $row['uid'] . "\""
119 $buf = "command=\"/usr/bin/php " . $gg_scripts . "/ssh.php " . $row['uid'] . "\""
85 120 . ",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty" . ",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty"
86 121 . " " . $row['key'] . "\n"; . " " . $row['key'] . "\n";
87 if (fwrite($f, $buf) === FALSE) {
88 keys_set_error("Cannot write. Disk space problems?");
122 if (@fwrite($f, $buf) === FALSE) {
123 keys_set_error("Cannot write. Disk space problems? ($php_errormsg)");
89 124 fclose($f); fclose($f);
90 125 unlink($tmp); unlink($tmp);
91 126 sql_free_result($res); sql_free_result($res);
 
... ... function keys_regen($db, $file)
96 131
97 132 fclose($f); fclose($f);
98 133
99 if (rename($tmp, $file) === FALSE) {
100 keys_set_error("Cannot rename $tmp to $file!");
134 if (@rename($tmp, $gg_keys_file) === FALSE) {
135 keys_set_error("Cannot rename $tmp to $gg_keys_file ($php_errormsg)!");
101 136 unlink($tmp); unlink($tmp);
102 137 return FALSE; return FALSE;
103 138 } }
 
... ... function keys_regen($db, $file)
108 143 return TRUE; return TRUE;
109 144 } }
110 145
146 /*
147 * List keys
148 */
149 function keys_list($db, $uid, $url)
150 {
151 xlog("keys_list: uid=$uid, url=$url...");
152
153 $sql = "SELECT * FROM keys WHERE uid = $uid";
154 $res = sql_query($db, $sql);
155 if ($res === FALSE) {
156 keys_set_error("Cannot query (" . sql_error() . ")");
157 return FALSE;
158 }
159
160 $ret = "<table>\n";
161 $ret .= "<tr>\n";
162 $ret .= " <th>Date (UTC)</th>\n";
163 $ret .= " <th>Fingerprint</th>\n";
164 $ret .= " <th>Operations</th>\n";
165 $ret .= "</tr>\n";
166 while (($row = sql_fetch_array($res))) {
167 $ret .= "<tr>\n";
168 $ret .= " <td>" . gmdate("Y-m-d H:i:s", $row['itime']) . "</td>\n";
169 $ret .= " <td>" . keys_fingerprint($row['key']) . "</td>\n";
170
171 $oper = "";
172 $oper = "[<a href=\"$url&amp;key_id=" . $row['key_id']
173 . "&amp;delete=1\">Delete!</a>]";
174 $ret .= " <td>" . $oper . "</td>\n";
175 $ret .= "</tr>\n";
176 }
177 $ret .= "</table>\n";
178 sql_free_result($res);
179
180 return $ret;
181 }
111 182 ?> ?>

File inc/keys/add.form.php copied from file inc/repo/search.form.php (similarity 51%) (mode: 100644) (index 2491cea..f1896b0)
... ... $_form = '
7 7 <input type="hidden" name="doit" value="1"> <input type="hidden" name="doit" value="1">
8 8
9 9 <table> <table>
10 <tr>
11 <td>Name:</td>
12 <td>
13 <input type="text" name="q" value=""><br />
14 </td>
15 </tr>
16
17 <tr>
18 <td>Only masters?</td>
10 <td>Key (starts with ssh-...):</td>
19 11 <td> <td>
20 <select name="masters">
21 <option value="1">Yes</option>
22 <option value="0">No</option>
23 </select>
12 <textarea name="key" value="' . $key . '" rows="4" cols="30"></textarea><br />
24 13 </td> </td>
25 14 </tr> </tr>
26 15
27 16 <tr> <tr>
28 <td colspan="2"><input type="submit" value="Search!"></td>
17 <td colspan="2"><input type="submit" value="Add!"></td>
29 18 </tr> </tr>
30 19
31 20 </table> </table>

File inc/keys/keys.php added (mode: 100644) (index 0000000..ee46f0a)
1 <?php
2 xlog("/inc/keys/keys.php");
3
4 if ($gg_uid == 0) {
5 $_body = "You do not have access here!";
6 return;
7 }
8
9 $subop = @intval($_REQUEST['subop']);
10 $key = @$_REQUEST['key'];
11 $key = preg_replace("|[^/A-Za-z0-9 @/+_\.\=,-]|", "", $key);
12 $key_id = @intval($_REQUEST['key_id']);
13
14 // menu
15 $_url = $_SERVER['PHP_SELF'] . "?op=$op";
16 $_menu = "";
17 $_menu .= "[<a href=\"$_url&amp;subop=1\">Add</a>]";
18 $_menu .= "&nbsp;[<a href=\"$_url&amp;subop=2\">List</a>]";
19 $_menu .= "<br />\n";
20 $_menu .= "<br />\n";
21
22 $_body = "";
23
24 switch ($subop) {
25 case 1: // add
26 if ($doit == 1) {
27 $_r = keys_add($db, $gg_uid, $key);
28 if ($_r === FALSE)
29 $_body .= keys_error();
30 else
31 $_body = "OK!";
32 } else {
33 include($INC . "/keys/add.form.php");
34 $_body .= $_form;
35 }
36 break;
37
38 case 2: // list
39 if (@$_REQUEST['delete'] == 1) {
40 if (keys_remove($db, $gg_uid, $key_id) === FALSE)
41 $_body .= "Bad: " . keys_error() . "!<br />\n";
42 }
43
44 $_body .= keys_list($db, $gg_uid, $_url . "&amp;subop=2");
45 break;
46
47 }
48
49 $_keys = $_menu . $_body;
50 ?>

File inc/repo.inc.php changed (mode: 100644) (index 69506c4..12ee83d)
... ... require_once($INC . "/util.inc.php");
3 3 require_once($INC . "/xlog.inc.php"); require_once($INC . "/xlog.inc.php");
4 4 require_once($INC . "/db.inc.php"); require_once($INC . "/db.inc.php");
5 5 require_once($INC . "/user.inc.php"); require_once($INC . "/user.inc.php");
6 require_once($INC . "/git.inc.php");
6 7
7 $repo_error = "";
8 $gg_repo_error = "";
8 9
9 function repo_set_error($str)
10 $gg_repo_rights = array("A" => "Admin",
11 "F" => "Fetch",
12 "P" => "Push",
13 "D" => "Delete branch");
14
15 function gg_repo_set_error($str)
10 16 { {
11 global $repo_error;
17 global $gg_repo_error;
12 18
13 19 xlog("\tError: $str"); xlog("\tError: $str");
14 $repo_error = $str;
20 $gg_repo_error = $str;
15 21 } }
16 22
17 function repo_error()
23 function gg_repo_error()
18 24 { {
19 global $repo_error;
20 return $repo_error;
25 global $gg_repo_error;
26 return $gg_repo_error;
21 27 } }
22 28
23 29 /* /*
 
... ... function repo_id2base($repo_id)
27 33 { {
28 34 global $gg_base_repo; global $gg_base_repo;
29 35
30 $r3 = sprintf("%03u", $repo_id / 1000);
36 $r3 = sprintf("%03u", $repo_id % 1000);
31 37
32 38 return $gg_base_repo . "/" return $gg_base_repo . "/"
33 . $r3[0] . "/" . $r3[1] . "/" . $r3[2];
39 . $r3[0] . "/" . $r3[1] . "/" . $r3[2] . "/";
34 40 } }
35 41
36 42 /* /*
 
... ... function repo_id2base($repo_id)
38 44 */ */
39 45 function repo_info($db, $repo_id, $repo) function repo_info($db, $repo_id, $repo)
40 46 { {
41 xlog("repo_info: $repo_id, repo=$repo...");
47 xlog("repo_info: repo_id=$repo_id, repo=$repo...");
42 48
43 49 $ret['ok'] = 0; $ret['ok'] = 0;
50 $ret['exists'] = 0;
44 51
45 52 $repo_id = sprintf("%u", $repo_id); $repo_id = sprintf("%u", $repo_id);
46 53 if ($repo_id > 0) { if ($repo_id > 0) {
 
... ... function repo_info($db, $repo_id, $repo)
61 68 return $ret; return $ret;
62 69 } }
63 70 $ret['ok'] = 1; $ret['ok'] = 1;
64 $ret['exists'] = 0;
65 71 $row = sql_fetch_array($res); $row = sql_fetch_array($res);
66 72 sql_free_result($res); sql_free_result($res);
67 73 if (!isset($row['repo_id'])) { if (!isset($row['repo_id'])) {
 
... ... function repo_info($db, $repo_id, $repo)
77 83 /* /*
78 84 * Check if a uid has access to repository * Check if a uid has access to repository
79 85 */ */
80 function repo_allow($db, $ri, $uid, $perms)
86 function repo_allow($db, $ri, $uid, $needed_rights)
81 87 { {
82 xlog("repo_allow: uid=$uid, perms=$perms...");
88 xlog("repo_allow: uid=$uid, needed_rights=$needed_rights...");
83 89
84 90 $e_uid = sprintf("%u", $uid); $e_uid = sprintf("%u", $uid);
85 91 $e_perms = preg_replace("/[^A-Z]/", "", $perms); $e_perms = preg_replace("/[^A-Z]/", "", $perms);
86 92
93 if (($ri['deleted'] == 1) && ($ri['uid'] != $uid)) {
94 xlog("\tRepo is deleted!");
95 return FALSE;
96 }
97
87 98 if (empty($e_perms)) { if (empty($e_perms)) {
88 99 xlog("\tNo perms passed!"); xlog("\tNo perms passed!");
89 100 return FALSE; return FALSE;
90 101 } }
91 102
92 // anonymouse access?
93 if ($uid == 0) {
94 if ($ri['ok'] == 0)
95 return FALSE;
96 if ($ri['exists'] != 1)
97 return FALSE;
98 if ($ri['public'] == 0) {
99 xlog("\tRepo is not public!");
100 return FALSE;
101 }
102 if (($ri['public'] == 1) && (strcmp($perms, "W") == 0)) {
103 xlog("\tRepo is public, but no write allowed!");
103 $rr = gg_repo_rights_get($db, $ri['repo_id'], $uid);
104 if ($rr['exists'] != 1) {
105 gg_repo_set_error("No access!");
106 return FALSE;
107 }
108 xlog("\tdb rights: " . $rr['rights']);
109
110 $len = strlen($needed_rights);
111 for ($i = 0; $i < $len; $i++) {
112 if (!strstr($rr['rights'], $needed_rights[$i])) {
113 gg_repo_set_error("No rights (" . $needed_rights[$i] . ")");
104 114 return FALSE; return FALSE;
105 115 } }
116 }
106 117
107 return TRUE;
118 xlog("\tAllow access!");
119
120 return TRUE;
121 }
122
123 /*
124 * Add a repository
125 * @master - makes sense only for clones - who is the master.
126 */
127 function repo_create($db, $master, $gg_uid, $name, $max_commit_size, $desc,
128 $rights)
129 {
130 // TODO: reorder parameters - are not logical
131 xlog("repo_create: gg_uid=$gg_uid, name=[$name], master=$master"
132 . ", max_commit_size=$max_commit_size, desc=[$desc]"
133 . ", rights=$rights...");
134
135 // First, test if it already exists
136 $ri = repo_info($db, 0, $name);
137 if ($ri['ok'] != 1)
138 return FALSE;
139 if ($ri['exists'] == 1) {
140 gg_repo_set_error("Repository already exists.");
141 return FALSE;
108 142 } }
109 143
110 if (strcmp($perms, "R") == 0)
111 $perms_add = " AND (perm = 'R' OR perm = 'W')";
112 else
113 $perms_add = " AND perm = 'W'";
144 // XSS protection
145 $name = gg_xss($name);
146 $desc = gg_xss($desc);
114 147
115 $sql = "SELECT 1 AS junk FROM repo_access"
116 . " WHERE repo_id = " . $ri['repo_id']
117 . " AND uid = $e_uid"
118 . $perms_add;
148 $e_name = sql_escape($db, $name);
149 $e_desc = sql_escape($db, $desc);
150
151 $itime = time();
152
153 $sql = "INSERT INTO repos (uid, master, name, itime"
154 . ", max_commit_size, desc, git_dir_done, default_rights)"
155 . " VALUES ($gg_uid, $master, '$e_name', $itime"
156 . ", $max_commit_size, '$e_desc', 0, '$rights')";
119 157 $res = sql_query($db, $sql); $res = sql_query($db, $sql);
120 if ($res === FALSE)
158 if ($res === FALSE) {
159 gg_repo_set_error("Cannot insert (" . sql_error() . ")");
121 160 return FALSE; return FALSE;
122 $row = sql_fetch_array($res);
161 }
123 162 sql_free_result($res); sql_free_result($res);
124 163
125 if (!isset($row['junk'])) {
126 xlog("\tDo not allow access!");
164 // git repo creation will be delayed for serialization reasons
165 // and for permission reasons (we are apache here)
166
167 return TRUE;
168 }
169
170 /*
171 * Delete a repo
172 */
173 function gg_repo_delete($db, $repo_id, $gg_uid)
174 {
175 xlog("repo_delete: gg_uid=$gg_uid, repo_id=$repo_id");
176
177 // TODO: Check rights
178
179 // Only mark it as such, deletion will happen in background
180 $sql = "UPDATE repos SET deleted = 1 WHERE repo_id = $repo_id";
181 $res = sql_query($db, $sql);
182 if ($res === FALSE) {
183 gg_repo_set_error("Cannot delete (" . sql_error() . ")");
127 184 return FALSE; return FALSE;
128 185 } }
129
130 xlog("\tAllow access!");
186 sql_free_result($res);
131 187
132 188 return TRUE; return TRUE;
133 189 } }
134 190
135 191 /* /*
136 * Add a repository
137 * @master - makes sense only for clones - who is the master.
192 * Update a repository
193 * TODO: check rights - also for create?
138 194 */ */
139 function repo_create($db, $master, $uid, $name, $public, $max_commit_size)
195 function gg_repo_update($db, $repo_id, $gg_uid, $name, $max_commit_size, $desc,
196 $rights)
140 197 { {
141 xlog("repo_create: name=[$name], master=$master, public=$public"
142 . ", max_commit_size=$max_commit_size"
143 . "...");
198 xlog("repo_update: repo_id=$repo_id, gg_uid=$gg_uid, name=[$name]"
199 . ", max_commit_size=$max_commit_size, desc=[$desc]"
200 . ", rights=$rights...");
144 201
145 $name = htmlspecialchars($name);
146 $e_name = sql_escape($db, $name);
202 // First, test if it already exists
203 $ri = repo_info($db, 0, $name);
204 if ($ri['ok'] != 1)
205 return FALSE;
206 if (($ri['exists'] == 1) && ($ri['repo_id'] != $repo_id)) {
207 gg_repo_set_error("Name already taken.");
208 return FALSE;
209 }
147 210
148 $itime = time();
211 // Second, test if we repo_id is valid
212 $ri = repo_info($db, $repo_id, "");
213 if ($ri['ok'] != 1)
214 return FALSE;
215 if ($ri['exists'] == 0) {
216 gg_repo_set_error("Repo $repo_id does not eists.");
217 return FALSE;
218 }
219
220 // XSS protection
221 $name = gg_xss($name);
222 $desc = gg_xss($desc);
149 223
150 $sql = "INSERT INTO repos (uid, master, name, itime, public"
151 . ", max_commit_size)"
152 . " VALUES ($uid, $master, '$e_name', $itime, $public"
153 . ", $max_commit_size)";
224 $e_name = sql_escape($db, $name);
225 $e_desc = sql_escape($db, $desc);
226
227 $sql = "UPDATE repos SET name = '$e_name'"
228 . ", max_commit_size = $max_commit_size"
229 . ", desc = '$e_desc'"
230 . ", default_rights = '$rights'"
231 . " WHERE repo_id = $repo_id";
154 232 $res = sql_query($db, $sql); $res = sql_query($db, $sql);
155 233 if ($res === FALSE) { if ($res === FALSE) {
156 repo_set_error("Cannot insert (" . sql_error() . ")");
234 gg_repo_set_error("Cannot update (" . sql_error() . ")");
157 235 return FALSE; return FALSE;
158 236 } }
159 237 sql_free_result($res); sql_free_result($res);
238
239 return TRUE;
160 240 } }
161 241
162 242 /* /*
163 243 * List repositories * List repositories
164 244 */ */
165 function repo_list($db, $url, $uid, $only_master)
245 function repo_list_query($db, $url, $sql)
166 246 { {
167 xlog("repo_list: url=$url, uid=$uid, only_master=$only_master...");
168
169 $add = "";
170 if ($uid > 0)
171 $add = " AND uid = $uid";
172
173 if ($only_master == 1)
174 $add .= " AND master = 0";
247 xlog("repo_list_query: url=$url, sql=$sql...");
175 248
176 $sql = "SELECT * FROM repos WHERE 1 = 1"
177 . $add
178 . " ORDER BY name";
179 249 $res = sql_query($db, $sql); $res = sql_query($db, $sql);
180 250 if ($res === FALSE) if ($res === FALSE)
181 251 return FALSE; return FALSE;
 
... ... function repo_list($db, $url, $uid, $only_master)
183 253 $ret = "<table>\n"; $ret = "<table>\n";
184 254 $ret .= "<tr>\n"; $ret .= "<tr>\n";
185 255 $ret .= " <th>Name</th>\n"; $ret .= " <th>Name</th>\n";
186 if ($only_master == 0)
187 $ret .= " <th>Master?</th>\n";
256 $ret .= " <th>Description</th>\n";
257 $ret .= " <th>Clone of</th>\n";
188 258 $ret .= " <th>Creation date (UTC)</th>\n"; $ret .= " <th>Creation date (UTC)</th>\n";
189 $ret .= " <th>Public</th>\n";
259 $ret .= " <th>Default rights</th>\n";
190 260 $ret .= " <th>Disk current/max</th>\n"; $ret .= " <th>Disk current/max</th>\n";
191 261 $ret .= " <th>Max commit size</th>\n"; $ret .= " <th>Max commit size</th>\n";
192 $ret .= " <th>Operations</th>\n";
193 262 $ret .= "</tr>\n"; $ret .= "</tr>\n";
194 263 while (($row = sql_fetch_array($res))) { while (($row = sql_fetch_array($res))) {
195 264 $ret .= "<tr>\n"; $ret .= "<tr>\n";
196 $ret .= " <td>" . $row['name'] . "</td>\n";
197 if ($only_master == 0)
198 $ret .= " <td>" . ($row['master'] == 0 ? "Yes" : "No") . "</td>\n";
199 $ret .= " <td>" . date("Y-m-d H:i:s", $row['itime']) . "</td>\n";
200 $ret .= " <td>" . ($row['public'] == 1 ? "Yes" : "No") . "</td>\n";
265 $ret .= " <td><a href=\"" . $_SERVER['PHP_SELF'] . "?op=10&amp;repo_id=" . $row['repo_id'] . "\">" . $row['name'] . "</a></td>\n";
266 $ret .= " <td><small>" . nl2br($row['desc']) . "</small></td>\n";
267 if ($row['master'] > 0) {
268 $master_repo = "?";
269 $_mi = repo_info($db, $row['master'], "");
270 if ($_mi['exists'] = 1)
271 $master_repo = $_mi['name'];
272 }
273 $ret .= " <td>" . ($row['master'] == 0 ? "-" : $master_repo) . "</td>\n";
274 $ret .= " <td>" . gmdate("Y-m-d H:i:s", $row['itime']) . "</td>\n";
275
276 // rights
277 $_r = implode(", ", gg_repo_rights_text($row['default_rights']));
278 $ret .= " <td>" . $_r . "</td>\n";
201 279
202 280 $_max = "ulimited"; $_max = "ulimited";
203 281 if ($row['disk_quota_mb'] > 0) if ($row['disk_quota_mb'] > 0)
 
... ... function repo_list($db, $url, $uid, $only_master)
209 287 $_v = gg_1024($row['max_commit_size']); $_v = gg_1024($row['max_commit_size']);
210 288 $ret .= " <td>" . $_v . "</td>\n"; $ret .= " <td>" . $_v . "</td>\n";
211 289
212 $ret .= " <td>-</td>\n";
213 290 $ret .= "</tr>\n"; $ret .= "</tr>\n";
214 291 } }
215 292 $ret .= "</table>\n"; $ret .= "</table>\n";
 
... ... function repo_list($db, $url, $uid, $only_master)
219 296 } }
220 297
221 298 /* /*
299 *
300 */
301 function repo_list($db, $url, $uid)
302 {
303 xlog("repo_list: url=$url, uid=$uid...");
304
305 $add = "";
306 if ($uid > 0)
307 $add = " AND uid = $uid";
308
309 $sql = "SELECT * FROM repos"
310 . " WHERE deleted = 0"
311 . $add
312 . " ORDER BY name";
313
314 return repo_list_query($db, $url, $sql);
315 }
316
317 /*
318 *
319 */
320 function repo_search($db, $q, $masters)
321 {
322 xlog("repo_search: q=$q, masters=$masters...");
323
324 $add = "";
325 if ($masters == 1)
326 $add = " AND master = 0";
327
328 $e_q = sql_escape($db, $q);
329
330 $sql = "SELECT * FROM repos"
331 . " WHERE deleted = 0"
332 . " AND name LIKE '%$e_q%'"
333 . $add
334 . " ORDER BY name"
335 . " LIMIT 10";
336
337 return repo_list_query($db, "", $sql);
338 }
339
340 /*
222 341 * Computes the size of a repository * Computes the size of a repository
223 342 */ */
224 343 function repo_disk_mb($path) function repo_disk_mb($path)
225 344 { {
226 345 xlog("repo_disk_mb: path=$path..."); xlog("repo_disk_mb: path=$path...");
227 346
347 // TODO
348
228 349 return 10; return 10;
229 350 } }
230 351
352 /*
353 * Mark a git repo as done
354 */
355 function repo_git_done($db, $repo_id)
356 {
357 xlog("repo_git_done: repo_id=$repo_id...");
358
359 $sql = "UPDATE repos SET git_dir_done = 1"
360 . " WHERE repo_id = $repo_id";
361 $res = sql_query($db, $sql);
362 if ($res === FALSE) {
363 gg_repo_set_error("Cannot query (" . sql_error() . ")");
364 return FALSE;
365 }
366 sql_free_result($res);
367
368 return TRUE;
369 }
370
371
372 // Functions for repo rights management
373
374 /*
375 * Get rights for a user
376 */
377 function gg_repo_rights_get($db, $repo_id, $uid)
378 {
379 xlog("gg_repo_rights_get: repo_id=$repo_id, uid=$uid...");
380
381 $ret = array();
382 $ret['ok'] = 0;
383 $ret['exists'] = 0;
384
385 $sql = "SELECT * FROM repo_rights"
386 . " WHERE repo_id = $repo_id"
387 . " AND uid = $uid"
388 . " LIMIT 1";
389 $res = sql_query($db, $sql);
390 if ($res === FALSE) {
391 gg_repo_set_error("Cannot get info (" . sql_error() . ")!");
392 return $ret;
393 }
394
395 $ret['ok'] = 1;
396 $row = sql_fetch_array($res);
397 sql_free_result($res);
398 if (!isset($row['uid'])) {
399 gg_repo_set_error("User not found!");
400 return $ret;
401 }
402
403 $row['ok'] = 1;
404 $row['exists'] = 1;
405 return $row;
406 }
407
408 /*
409 * Add rights for a repo
410 */
411 function gg_repo_rights_set($db, $repo_id, $gg_uid, $uid, $rights)
412 {
413 xlog("gg_repo_rights_add: repo_id=$repo_id, gg_uid=$gg_uid"
414 . ", uid=$uid, rights=$rights...");
415
416 // check if repo owner is gg_uid, or has admin rights
417 $ri = repo_info($db, $repo_id, "");
418 if ($ri['exists'] != 1) {
419 gg_repo_set_error("Repo does not exists");
420 return FALSE;
421 }
422
423 // check default rights first
424 if (!strstr($ri['default_rights'], "A")) {
425 if ($ri['uid'] != $gg_uid) {
426 // this means that web user is not the owner, search rights
427 $rr = gg_repo_rights_get($db, $repo_id, $gg_uid);
428 if ($rr['exists'] != 1) {
429 gg_repo_set_error("You are not allowed (no rights)!");
430 return FALSE;
431 }
432
433 if (!strstr($rr['rights'], "A")) {
434 gg_repo_set_error("You are not allowed (no admin rights)!");
435 return FALSE;
436 }
437 }
438 }
439
440 if (empty($rights)) {
441 $sql = "DELETE FROM repo_rights"
442 . " WHERE repo_id = $repo_id"
443 . " AND uid = $uid";
444 } else {
445 $r = gg_repo_rights_get($db, $repo_id, $uid);
446 if ($r['ok'] != 1)
447 return $r;
448
449 $e_rights = sql_escape($db, $rights);
450
451 if ($r['exists'] == 1) {
452 $sql = "UPDATE repo_rights"
453 . " SET rights = '$e_rights'"
454 . " WHERE repo_id = $repo_id"
455 . " AND uid = $uid";
456 } else {
457 $itime = time();
458
459 $sql = "INSERT INTO repo_rights (repo_id, uid, rights"
460 . ", itime)"
461 . " VALUES ($repo_id, $uid, '$e_rights'"
462 . ", $itime)";
463 }
464 }
465
466 $res = sql_query($db, $sql);
467 if ($res === FALSE) {
468 gg_repo_set_error("Cannot alter rights (" . sql_error() . ")!");
469 return FALSE;
470 }
471 sql_free_result($res);
472
473 return TRUE;
474 }
475
476 /*
477 * List rights for a repo
478 */
479 function gg_repo_rights_list($db, $repo_id)
480 {
481 xlog("gg_repo_rights: repo_id=$repo_id");
482
483 $ret = "";
484
485 $sql = "SELECT * FROM repo_rights WHERE repo_id = $repo_id";
486 $res = sql_query($db, $sql);
487 if ($res === FALSE) {
488 gg_repo_set_error("Cannot get info (" . sql_error() . ")!");
489 return FALSE;
490 }
491
492 $ret .= "<table>\n";
493 $ret .= "<tr>\n";
494 $ret .= " <th>User</th>\n";
495 $ret .= " <th>Rights</th>\n";
496 $ret .= " <th>Operations</th>\n";
497 $ret .= "</tr>\n";
498 while (($row = sql_fetch_array($res))) {
499 $ret .= "<tr>\n";
500
501 $_u = $row['uid'];
502 $_ui = user_info($db, $row['uid'], "", "");
503 if ($_ui['exists'] == 1)
504 $_u = $_ui['user'];
505
506 $ret .= " <td>" . $_u . "</td>\n";
507
508 $_r = gg_repo_rights_text($row['rights']);
509 $_r = implode("<br />\n", $_r);
510 $ret .= " <td>" . $_r . "</td>\n";
511
512 // operations
513 // suspend
514 $ret .= " <td>";
515 /*TODO
516 $_url = $url . "&amp;xuid=" . $row['uid'];
517 $v = 1; $t = "Suspend";
518 if ($row['suspended'] > 0) {
519 $t = "Unsuspend";
520 $v = 0;
521 }
522 $ret .= "[<a href=\"$_url&amp;suspend=$v\">$t</a>]";
523 // admin
524 $v = 1; $t = "Admin";
525 if ($row['is_admin'] == 1) {
526 $t = "Remove admin";
527 $v = 0;
528 }
529 $ret .= "[<a href=\"$_url&amp;admin=$v\">$t</a>]";
530 */
531 $ret .= " </td>";
532 $ret .= "</tr>\n";
533 }
534 $ret .= "</table>\n";
535 sql_free_result($res);
536
537 return $ret;
538 }
539
540 /*
541 * Rights -> form
542 */
543 function gg_repo_rights_checkboxes($def_rights)
544 {
545 global $gg_repo_rights;
546
547 $ret = "";
548 foreach ($gg_repo_rights as $right => $info) {
549 $add = "";
550 if (strstr($def_rights, $right))
551 $add = " checked";
552 $ret .= "<input type=\"checkbox\" name=\"rights[$right]\""
553 . $add . " />$info<br />\n";
554 }
555
556 return $ret;
557 }
558
559 /*
560 * List rights as text
561 */
562 function gg_repo_rights_text($rights)
563 {
564 global $gg_repo_rights;
565
566 $ret = array();
567
568 $len = strlen($rights);
569 for ($i = 0; $i < $len; $i++) {
570 if (isset($gg_repo_rights[$rights[$i]]))
571 $ret[] = $gg_repo_rights[$rights[$i]];
572 else
573 $ret[] = "?" . $rights[$i] . "?";
574 }
575
576 return $ret;
577 }
578
579 /*
580 * Transforms rights array into a string
581 */
582 function gg_repo_rights_a2s($a)
583 {
584 $rights = "";
585
586 if (is_array($a))
587 foreach ($a as $right => $junk)
588 $rights .= $right;
589
590 return preg_replace("/[^A-Za-z0-9]/", "", $rights);
591 }
231 592 ?> ?>

File inc/repo/repo.form.php changed (mode: 100644) (index 4fede90..7c8e9ff)
... ... $_form = '
4 4 <form type="post" action="' . $_SERVER['PHP_SELF'] . '"> <form type="post" action="' . $_SERVER['PHP_SELF'] . '">
5 5 <input type="hidden" name="op" value="' . $op . '"> <input type="hidden" name="op" value="' . $op . '">
6 6 <input type="hidden" name="subop" value="' . $subop . '"> <input type="hidden" name="subop" value="' . $subop . '">
7 <input type="hidden" name="repo_id" value="' . $repo_id . '">
8 <input type="hidden" name="master_repo_id" value="' . $master_repo_id . '">
7 9 <input type="hidden" name="doit" value="1"> <input type="hidden" name="doit" value="1">
8 10
9 11 <table> <table>
12 ';
13
14 if ($master_repo_id > 0) {
15 $master_name = $master_repo_id;
16 $_mi = repo_info($db, $master_repo_id, "");
17 if ($_mi['exists'] == 1)
18 $master_name = $_mi['name'];
19 $_form .= '<tr><td>Master repo:</td><td>' . $master_name . '</td></tr>';
20 }
21
22 $_form .= '
10 23 <tr> <tr>
11 24 <td>Name:</td> <td>Name:</td>
12 25 <td> <td>
13 <input type="text" name="name" value="' . $name . '"><br />
26 <input type="text" name="name" value="' . $name . '" /><br />
14 27 </td> </td>
15 28 </tr> </tr>
16 29
17 30 <tr> <tr>
18 <td>Public?</td>
31 <td>Max commit size (bytes):</td>
19 32 <td> <td>
20 <select name="public">
21 <option value="1">Yes</option>
22 <option value="0">No</option>
23 </select>
33 <input type="text" name="max_commit_size" value="' . $max_commit_size . '" /><br />
24 34 </td> </td>
25 35 </tr> </tr>
26 36
27 37 <tr> <tr>
28 <td>Max commit size (bytes):</td>
38 <td>Description:</td>
39 <td>
40 <textarea name="desc" value="' . $desc . '" rows="4" cols="30">' . $desc . '</textarea><br />
41 </td>
42 </tr>
43
44 <tr>
45 <td>Default rights:</td>
29 46 <td> <td>
30 <input type="text" name="max_commit_size" value="' . $max_commit_size . '"><br />
47 ' . gg_repo_rights_checkboxes($rights) . '
31 48 </td> </td>
32 49 </tr> </tr>
33 50
34 51 <tr> <tr>
35 <td colspan="2"><input type="submit" value="Go!"></td>
52 <td colspan="2"><input type="submit" value="' . $_action . '" /></td>
36 53 </tr> </tr>
37 54
38 55 </table> </table>

File inc/repo/repo.php changed (mode: 100644) (index 194bbaa..61e3d2d)
1 1 <?php <?php
2 2 xlog("/inc/repo/repo.php"); xlog("/inc/repo/repo.php");
3 3
4 if ($gg_uid == 0) {
5 $_body = "You do not have access here!";
6 return;
7 }
8
4 9 $subop = @intval($_REQUEST['subop']); $subop = @intval($_REQUEST['subop']);
5 $public = @intval($_REQUEST['public']);
6 10 $name = @$_REQUEST['name']; $name = @$_REQUEST['name'];
7 11 $max_commit_size = @intval($_REQUEST['max_commit_size']); $max_commit_size = @intval($_REQUEST['max_commit_size']);
12 $desc = @$_REQUEST['desc'];
13 $master_repo_id = sprintf("%u", @$_REQUEST['master_repo_id']);
14 $rights = @$_REQUEST['rights'];
15 $rights = gg_repo_rights_a2s($rights);
16 $repo_id = @intval($_REQUEST['repo_id']);
17 $q = @$_REQUEST['q'];
18 $masters = @intval($_REQUEST['masters']);
19
8 20
9 21 // menu // menu
10 22 $_url = $_SERVER['PHP_SELF'] . "?op=$op"; $_url = $_SERVER['PHP_SELF'] . "?op=$op";
11 23 $_menu = ""; $_menu = "";
12 24 $_menu .= "[<a href=\"$_url&amp;subop=1\">Create</a>]"; $_menu .= "[<a href=\"$_url&amp;subop=1\">Create</a>]";
13 25 $_menu .= "&nbsp;[<a href=\"$_url&amp;subop=2\">List</a>]"; $_menu .= "&nbsp;[<a href=\"$_url&amp;subop=2\">List</a>]";
26 $_menu .= "&nbsp;[<a href=\"$_url&amp;subop=3\">Search</a>]";
14 27 $_menu .= "<br />\n"; $_menu .= "<br />\n";
15 28 $_menu .= "<br />\n"; $_menu .= "<br />\n";
16 29
 
... ... $_body = "";
19 32 switch ($subop) { switch ($subop) {
20 33 case 1: // create case 1: // create
21 34 if ($doit == 1) { if ($doit == 1) {
22 $master = 1;
23 $_r = repo_create($db, $master, $uid, $name, $public,
24 $max_commit_size);
25 $_body = "bau!";
35 $_r = repo_create($db, $master_repo_id, $gg_uid, $name,
36 $max_commit_size, $desc, $rights);
37 if ($_r === FALSE)
38 $_body .= gg_repo_error();
39 else
40 $_body .= "OK!";
26 41 } else { } else {
42 $_action = "Create";
27 43 include($INC . "/repo/repo.form.php"); include($INC . "/repo/repo.form.php");
28 44 $_body .= $_form; $_body .= $_form;
29 45 } }
30 46 break; break;
31 47
32 case 2: //list
33 $only_masters = 1;
34 $_body .= repo_list($db, "", $uid, $only_masters);
48 case 2: // list
49 $_body .= repo_list($db, "", $gg_uid);
50 break;
51
52 case 3: // search
53 if ($doit == 1) {
54 $_body .= repo_search($db, $q, $masters);
55 } else {
56 include($INC . "/repo/search.form.php");
57 $_body .= $_form;
58 }
35 59 break; break;
36 60 } }
37 61

File inc/repo/repo_page.php added (mode: 100644) (index 0000000..e067b97)
1 <?php
2 xlog("/inc/repo/repo_page.php");
3
4 $repo_id = @intval($_REQUEST['repo_id']);
5
6 $subop = @intval($_REQUEST['subop']);
7 $name = @$_REQUEST['name'];
8 $max_commit_size = @intval($_REQUEST['max_commit_size']);
9 $desc = @$_REQUEST['desc'];
10 $rights = @$_REQUEST['rights'];
11 $rights = gg_repo_rights_a2s($rights);
12 $user = @gg_user_fix($_REQUEST['user']);
13 $master_repo_id = 0;
14
15 // menu
16 $_url = $_SERVER['PHP_SELF'] . "?op=$op&amp;repo_id=$repo_id";
17 $_menu = "";
18 $_menu .= "[<a href=\"$_url&amp;subop=1\">Edit</a>]";
19 $_menu .= "&nbsp;[<a href=\"$_url&amp;subop=2\">Rights</a>]";
20 $_menu .= "&nbsp;[<a href=\"$_url&amp;subop=3\">Delete</a>]";
21 $_menu .= "<br />\n";
22 $_menu .= "<br />\n";
23
24 $_body = "";
25
26 switch ($subop) {
27 case 1: // edit
28 if ($doit == 1) {
29 $_r = gg_repo_update($db, $repo_id, $gg_uid, $name,
30 $max_commit_size, $desc, $rights);
31 if ($_r === FALSE)
32 $_body .= gg_repo_error();
33 else
34 $_body .= "OK!";
35 } else {
36 $_ri = repo_info($db, $repo_id, "");
37 if ($_ri['ok'] != 1) {
38 $_body .= "Invalid repository!";
39 } else {
40 // load variables
41 $name = $_ri['name'];
42 $rights = $_ri['default_rights'];
43 $max_commit_size = $_ri['max_commit_size'];
44 $desc = $_ri['desc'];
45
46 $_action = "Update";
47 include($INC . "/repo/repo.form.php");
48 $_body .= $_form;
49 }
50 }
51 break;
52
53 case 2: // rights
54 $errmsg = "";
55
56 if ($doit == 1) {
57 $_errors = 0;
58
59 while (1) {
60 // lookup user
61 $_ui = user_info($db, 0, $user, "");
62 if ($_ui['exists'] != 1) {
63 $errmsg .= "User does not exists!";
64 $_errors++;
65 break;
66 }
67
68 // TODO: Check if user is allowed to give rights
69
70 $e = gg_repo_rights_set($db, $repo_id, $gg_uid,
71 $_ui['uid'], $rights);
72 if ($e === FALSE) {
73 $errmsg .= gg_repo_error();
74 $_errors++;
75 break;
76 }
77
78 break;
79 }
80 }
81
82 $_ri = repo_info($db, $repo_id, "");
83 if ($_ri['ok'] != 1) {
84 $_body .= "Invalid repository!";
85 } else {
86 // list rights
87 $_body .= "<b>Repository " . $_ri['name'] . "</b><br />\n";
88 $_body .= gg_repo_rights_list($db, $repo_id);
89
90 // give rights form
91 $_body .= "<br />\n";
92
93 $checkboxes = gg_repo_rights_checkboxes($rights);
94
95 include($INC . "/repo/rights.form.php");
96 $_body .= $_form;
97 }
98 break;
99
100 case 3: //delete
101 $r = gg_repo_delete($db, $repo_id, $gg_uid);
102 if ($r === FALSE) {
103 $_body .= "Error: " . gg_repo_error();
104 } else {
105 $_body .= "OK!";
106 }
107
108 break;
109 }
110
111 $_repo = $_menu . $_body;
112 ?>

File inc/repo/rights.form.php copied from file inc/repo/search.form.php (similarity 53%) (mode: 100644) (index 2491cea..a189e57)
1 1 <?php <?php
2 2
3 3 $_form = ' $_form = '
4 <font color="red">' . $errmsg . '</font><br />
4 5 <form type="post" action="' . $_SERVER['PHP_SELF'] . '"> <form type="post" action="' . $_SERVER['PHP_SELF'] . '">
5 6 <input type="hidden" name="op" value="' . $op . '"> <input type="hidden" name="op" value="' . $op . '">
6 7 <input type="hidden" name="subop" value="' . $subop . '"> <input type="hidden" name="subop" value="' . $subop . '">
8 <input type="hidden" name="repo_id" value="' . $repo_id . '">
7 9 <input type="hidden" name="doit" value="1"> <input type="hidden" name="doit" value="1">
8 10
9 11 <table> <table>
10 12 <tr> <tr>
11 <td>Name:</td>
13 <td>User:</td>
12 14 <td> <td>
13 <input type="text" name="q" value=""><br />
15 <input type="text" name="user" value="' . $user . '" />
14 16 </td> </td>
15 17 </tr> </tr>
16 18
17 19 <tr> <tr>
18 <td>Only masters?</td>
20 <td>Rights:</td>
19 21 <td> <td>
20 <select name="masters">
21 <option value="1">Yes</option>
22 <option value="0">No</option>
23 </select>
22 ' . $checkboxes . '
24 23 </td> </td>
25 24 </tr> </tr>
26 25
27 26 <tr> <tr>
28 <td colspan="2"><input type="submit" value="Search!"></td>
27 <td colspan="2"><input type="submit" value="Add!"></td>
29 28 </tr> </tr>
30 29
31 30 </table> </table>

File inc/sess.inc.php changed (mode: 100644) (index c22be6b..ef6bff1)
... ... function sess_add($db, $uid, $sid, $session_time)
21 21 return FALSE; return FALSE;
22 22 } }
23 23 sql_free_result($res); sql_free_result($res);
24
25 return TRUE;
24 26 } }
25 27
26 28 /* /*
 
... ... function sess_valid($db, $sid)
47 49 $row = sql_fetch_array($res); $row = sql_fetch_array($res);
48 50 sql_free_result($res); sql_free_result($res);
49 51 if (isset($row['uid'])) { if (isset($row['uid'])) {
50 if ($row['expire'] >= $now)
52 if ($row['expire'] >= $now) {
51 53 $uid = $row['uid']; $uid = $row['uid'];
52 else
54 xlog("\tSession valid, uid=$uid, expire=+" . ($row['expire'] - $now));
55 } else {
53 56 xlog("\tSession too old (" . ($now - $row['expire']) . "s)"); xlog("\tSession too old (" . ($now - $row['expire']) . "s)");
57 }
58 } else {
59 xlog("\tSession not found!");
54 60 } }
55 61
56 xlog("\tuid=$uid.");
57
58 62 return $uid; return $uid;
59 63 } }
60 64

File inc/state.inc.php changed (mode: 100644) (index 3731470..66b2342)
... ... function state_set($db, $var, $value)
19 19 return TRUE; return TRUE;
20 20 } }
21 21
22 /*
23 * Get state
24 */
25 function state_get($db, $var)
26 {
27 $e_var = sql_escape($db, $var);
28
29 $sql = "SELECT value FROM state WHERE var = '$e_var'";
30 $res = sql_query($db, $sql);
31 if ($res === FALSE)
32 return FALSE;
33
34 $row = sql_fetch_array($res);
35 if (!isset($row['value']))
36 return FALSE;
37
38 sql_free_result($res);
39
40 return $row['value'];
41 }
42
22 43 ?> ?>

File inc/user.inc.php changed (mode: 100644) (index dffe347..4fd43cb)
... ... function user_list($db, $url)
234 234 $ret .= " <th>Name</th>\n"; $ret .= " <th>Name</th>\n";
235 235 $ret .= " <th>E-mail</th>\n"; $ret .= " <th>E-mail</th>\n";
236 236 $ret .= " <th>Admin?</th>\n"; $ret .= " <th>Admin?</th>\n";
237 $ret .= " <th>Creation date</th>\n";
237 $ret .= " <th>Creation date (UTC)</th>\n";
238 238 $ret .= " <th>Quota</th>\n"; $ret .= " <th>Quota</th>\n";
239 239 $ret .= " <th>Suspended?</th>\n"; $ret .= " <th>Suspended?</th>\n";
240 240 $ret .= " <th>Session time</th>\n"; $ret .= " <th>Session time</th>\n";
241 $ret .= " <th>Last seen</th>\n";
241 $ret .= " <th>Last seen (UTC)</th>\n";
242 242 $ret .= " <th>Operations</th>\n"; $ret .= " <th>Operations</th>\n";
243 243 $ret .= "</tr>\n"; $ret .= "</tr>\n";
244 244 while (($row = sql_fetch_array($res))) { while (($row = sql_fetch_array($res))) {
 
... ... function user_list($db, $url)
246 246 $ret .= " <td>" . $row['user'] . "</td>\n"; $ret .= " <td>" . $row['user'] . "</td>\n";
247 247 $ret .= " <td>" . $row['email'] . "</td>\n"; $ret .= " <td>" . $row['email'] . "</td>\n";
248 248 $ret .= " <td>" . ($row['is_admin'] == 1 ? "Yes" : "No") . "</td>\n"; $ret .= " <td>" . ($row['is_admin'] == 1 ? "Yes" : "No") . "</td>\n";
249 $ret .= " <td>" . date("Y-m-d H:i:s", $row['itime']) . "</td>\n";
249 $ret .= " <td>" . gmdate("Y-m-d H:i:s", $row['itime']) . "</td>\n";
250 250 $_v = "unlimited"; $_v = "unlimited";
251 251 if ($row['disk_quota_mb'] > 0) if ($row['disk_quota_mb'] > 0)
252 252 $_v = gg_1024($row['disk_quota_mb']); $_v = gg_1024($row['disk_quota_mb']);
253 253 $ret .= " <td>" . $_v . "</td>\n"; $ret .= " <td>" . $_v . "</td>\n";
254 254 $ret .= " <td>" . ($row['suspended'] == 0 ? "No" : "Yes") . "</th>\n"; $ret .= " <td>" . ($row['suspended'] == 0 ? "No" : "Yes") . "</th>\n";
255 255 $ret .= " <td>" . $row['session_time'] . "s</td>\n"; $ret .= " <td>" . $row['session_time'] . "s</td>\n";
256 $ret .= " <td>" . date("Y-m-d H:i:s", $row['last_seen']) . "</td>\n";
256 $ret .= " <td>" . gmdate("Y-m-d", $row['last_seen']) . "</td>\n";
257 257 // operations // operations
258 258 // suspend // suspend
259 259 $ret .= " <td>"; $ret .= " <td>";
 
... ... function user_set_pass($db, $uid, $pass)
390 390 return TRUE; return TRUE;
391 391 } }
392 392
393 /*
394 * Remove forbidden chars
395 */
396 function gg_user_fix($user)
397 {
398 return preg_replace("/[^A-Za-z0-9_.-]/", "", $user);
399 }
400
393 401 ?> ?>

File inc/util.inc.php changed (mode: 100644) (index 7f8245c..b2b6d1f)
... ... function gg_xss($v)
49 49 { {
50 50 return htmlspecialchars($v, ENT_QUOTES); return htmlspecialchars($v, ENT_QUOTES);
51 51 } }
52
53 $_lock = FALSE;
54 function gg_lock_or_exit($file)
55 {
56 global $_lock;
57
58 if ($_lock !== FALSE) {
59 xlog("\tYou already have a lock on $file! Bad!");
60 exit(1);
61 }
62
63 $_lock = @fopen($file, "w");
64 if ($_lock === FALSE) {
65 xlog("\tCannot open $file!");
66 exit(1);
67 }
68
69 if (!flock($_lock, LOCK_EX | LOCK_NB)) {
70 fclose($_lock);
71 exit(0);
72 }
73
74 fwrite($_lock, getmypid() . "\n");
75 }
76
77 function gg_load()
78 {
79 return intval(file_get_contents("/proc/loadavg"));
80 }
52 81 ?> ?>

File inc/xlog.inc.php changed (mode: 100644) (index 4473d19..b2cd414)
... ... function xlog($str)
22 22 $_xlog_fd = @fopen($_xlog_file, "a+"); $_xlog_fd = @fopen($_xlog_file, "a+");
23 23 if ($_xlog_fd === FALSE) if ($_xlog_fd === FALSE)
24 24 return; return;
25 // write an empty line
26 fwrite($_xlog_fd, "\n");
25 27 } }
26 28
27 $buf = date("Y-m-d H:i:s");
29 $t = gettimeofday();
30 $buf = gmdate("Y-m-d H:i:s", $t['sec']) . "." . sprintf("%06d", $t['usec']);
28 31 $buf .= " " . $_xlog_sid . " " . $str . "\n"; $buf .= " " . $_xlog_sid . " " . $str . "\n";
29 32
30 33 fwrite($_xlog_fd, $buf); fwrite($_xlog_fd, $buf);

File root/index.php changed (mode: 100644) (index c7d2be5..4c64719)
... ... require_once($INC . "/xlog.inc.php");
13 13 include_once($INC . "/db.inc.php"); include_once($INC . "/db.inc.php");
14 14 include_once($INC . "/user.inc.php"); include_once($INC . "/user.inc.php");
15 15 include_once($INC . "/repo.inc.php"); include_once($INC . "/repo.inc.php");
16 include_once($INC . "/keys.inc.php");
16 17
17 18 xlog_set_file("/tmp/gg_web.log"); xlog_set_file("/tmp/gg_web.log");
18 19
 
... ... $sid = @$_COOKIE['sid'];
26 27 if (empty($sid)) if (empty($sid))
27 28 $sid = @$_REQUEST['sid']; $sid = @$_REQUEST['sid'];
28 29
30 xlog("IP: " . @$_SERVER['REMOTE_ADDR']);
29 31 xlog("_REQUEST: " . print_r($_REQUEST, TRUE)); xlog("_REQUEST: " . print_r($_REQUEST, TRUE));
30 32 xlog("_COOKIE: " . print_r($_COOKIE, TRUE)); xlog("_COOKIE: " . print_r($_COOKIE, TRUE));
31 33 xlog("Start! op=$op, doit=$doit, sid=$sid..."); xlog("Start! op=$op, doit=$doit, sid=$sid...");
 
... ... if ($db === FALSE)
50 52 die("Cannot open database!"); die("Cannot open database!");
51 53
52 54 // deal with login // deal with login
53 $uid = user_login($db, $sid, $gg_ui);
54 if (($op == 1) && ($doit == 1) && ($uid > 0))
55 $gg_uid = user_login($db, $sid, $gg_ui);
56 if (($op == 1) && ($doit == 1) && ($gg_uid > 0))
55 57 $op = 0; $op = 0;
56 58
57 59 // deal with logout // deal with logout
58 60 if ($op == 9) { if ($op == 9) {
59 61 sess_destroy($db, $sid); sess_destroy($db, $sid);
60 $uid = 0;
62 $gg_uid = 0;
61 63 $gg_ui = FALSE; $gg_ui = FALSE;
62 64 } }
63 65
 
... ... $url = $_SERVER['PHP_SELF'] . "?a=1";
71 73 $menu = ""; $menu = "";
72 74 $menu .= "[<a href=\"$url&amp;op=1\">Login</a>]"; $menu .= "[<a href=\"$url&amp;op=1\">Login</a>]";
73 75 if (isset($gg_ui['user'])) { if (isset($gg_ui['user'])) {
74 $menu .= "&nbsp;[<a href=\"$url&amp;op=2\">Repositories</a>]";
76 $menu .= "&nbsp;[<a href=\"$url&amp;op=4\">Keys</a>]\n";
77 $menu .= "&nbsp;[<a href=\"$url&amp;op=2\">My repositories</a>]\n";
75 78 if ($gg_ui['is_admin'] == 1) if ($gg_ui['is_admin'] == 1)
76 $menu .= "&nbsp;[<a href=\"$url&amp;op=3\">Admin</a>]";
77 $menu .= "&nbsp;[<a href=\"$url&amp;op=9\">Logout</a>]";
78 $menu .= "&nbsp;&nbsp;&nbsp;[" . $gg_ui['user'] . "]";
79 $menu .= "&nbsp;[<a href=\"$url&amp;op=3\">Admin</a>]\n";
80
81 $menu .= "&nbsp;[<a href=\"$url&amp;op=9\">Logout</a>]\n";
82
83 $menu .= "&nbsp;&nbsp;&nbsp;[" . $gg_ui['user'] . "]\n";
79 84 } }
80 85 $menu .= "<br />\n"; $menu .= "<br />\n";
81 86
 
... ... case 3:
97 102 $body .= $_admin; $body .= $_admin;
98 103 break; break;
99 104
105 case 4: // keys
106 include($INC . "/keys/keys.php");
107 $body .= $_keys;
108 break;
109
100 110 case 6: // forgot pass link case 6: // forgot pass link
101 111 include($INC . "/user/forgot.php"); include($INC . "/user/forgot.php");
102 112 $body .= $_forgot; $body .= $_forgot;
 
... ... case 7: // forgot pass - send mail
106 116 include($INC . "/user/forgot_mail.php"); include($INC . "/user/forgot_mail.php");
107 117 $body .= $_forgot; $body .= $_forgot;
108 118 break; break;
119
120 case 10: // repo page
121 include($INC . "/repo/repo_page.php");
122 $body .= $_repo;
123 break;
109 124 } }
110 125
111 $body .= "</body>";
126 $body .= "</body>\n";
112 127 $body .= "</html>\n"; $body .= "</html>\n";
113 128
114 129 echo $head . $menu . $body; echo $head . $menu . $body;

File root/themes/default/main.css changed (mode: 100644) (index bd25083..d25b7ad)
1 1 body { body {
2 2 margin: 5px; margin: 5px;
3 3 font-family: Verdana, arial, helvetica, sans-serif; font-family: Verdana, arial, helvetica, sans-serif;
4 }
5
6 body, td, a, p, .h {
7 margin-bottom: 20px;
4 font-size: 14px;
8 5 } }
9 6
10 7 table { table {
 
... ... table {
12 9 border: 1px solid #000; border: 1px solid #000;
13 10 background: #fff; background: #fff;
14 11 color: #000; color: #000;
15 font-size: 14px;
16 12 border-spacing: 1px; border-spacing: 1px;
17 13 padding: 1px; padding: 1px;
18 14 } }

File samples/config.php changed (mode: 100644) (index 6e9675b..de5fe71)
1 1 <?php <?php
2 // Base
3 $gg_base = "/home/gg";
4
2 5 // Base for repositories // Base for repositories
3 $gg_base_repo = "/home/gg/repositories";
6 $gg_base_repo = $gg_base . "/repositories";
4 7
5 8 // Database // Database
6 9 $gg_db = "sqlite:/tmp/gg.sqlite"; $gg_db = "sqlite:/tmp/gg.sqlite";
10 $gg_db_debug = 1;
11
12 // Session
13 $gg_session_time = 3600;
14
15 // Keys
16 $gg_keys_file = $gg_base . "/.ssh/authorized_keys";
17
18 // Scripts
19 $gg_scripts = "/BIG1T/sync1/Dev/gg/scripts";
7 20
8 ?>
21 ?>

File samples/cron changed (mode: 100644) (index 028fe23..f8ea8c6)
1 1 * * * * * gg php /BIG1T/sync1/Dev/gg/scripts/cron.php * * * * * gg php /BIG1T/sync1/Dev/gg/scripts/cron.php
2 * * * * * gg php /BIG1T/sync1/Dev/gg/scripts/q.php

File samples/gg changed (mode: 100644) (index fc7d98b..d8f2712)
... ... service git
8 8 disable = no disable = no
9 9 socket_type = stream socket_type = stream
10 10 wait = no wait = no
11 user = nobody
11 user = gg
12 12 server = /usr/bin/php server = /usr/bin/php
13 13 server_args = /BIG1T/sync1/Dev/gg/scripts/ssh.php server_args = /BIG1T/sync1/Dev/gg/scripts/ssh.php
14 14 log_on_failure += USERID log_on_failure += USERID

File scripts/cron.php changed (mode: 100644) (index 1422a27..f1575f7)
1 1 <?php <?php
2 2 // This is called by cron // This is called by cron
3 3 error_reporting(E_ALL); error_reporting(E_ALL);
4 ini_set("track_errors", "On");
4 5
5 6 $now = time(); $now = time();
6 7
 
... ... $INC = dirname(__FILE__) . "/../inc";
10 11 require_once($INC . "/xlog.inc.php"); require_once($INC . "/xlog.inc.php");
11 12 require_once($INC . "/db.inc.php"); require_once($INC . "/db.inc.php");
12 13 require_once($INC . "/repo.inc.php"); require_once($INC . "/repo.inc.php");
14 require_once($INC . "/keys.inc.php");
13 15
14 16 xlog_set_file("/tmp/gg_cron.log"); xlog_set_file("/tmp/gg_cron.log");
15 17
18 // locking
19 $lock = "/var/run/gg/cron.lock";
20 gg_lock_or_exit($lock);
21
16 22 $sql_debug = $gg_db_debug; $sql_debug = $gg_db_debug;
17 23
24 xlog("Start: euid=" . posix_geteuid() . "...");
25
18 26 $db = sql_open($gg_db); $db = sql_open($gg_db);
19 27 if ($db === FALSE) { if ($db === FALSE) {
20 28 xlog("Cannot connect to database!"); xlog("Cannot connect to database!");
 
... ... if (date("H") == 0) {
29 37 $res = sql_query($db, $sql); $res = sql_query($db, $sql);
30 38 if ($res === FALSE) { if ($res === FALSE) {
31 39 xlog("Cannot run query (" . sql_error() . ")!"); xlog("Cannot run query (" . sql_error() . ")!");
32 exit(1); // TODO: we should only skip this part not all scripts
33 }
34 while (($row = sql_fetch_array($res))) {
35 xlog("Processing repository [" . $row['name'] . "]...");
36 $repo_path = repo_id2base($row['repo_id']) . "/" . $row['name'] . ".git";
37 $disk_mb = repo_disk_mb($repo_path);
38 $sql = "UPDATE repos SET disk_mb = $disk_mb"
39 . " WHERE repo_id = " . $row['repo_id'];
40 $res2 = sql_query($db, $sql);
41 if ($res2 === FALSE) {
42 xlog("Cannot run query!");
43 } else {
44 @unlink($repo_path . "/gg/dirty");
45 sql_free_result($res2);
40 } else {
41 while (($row = sql_fetch_array($res))) {
42 xlog("Processing repository [" . $row['name'] . "]...");
43 $repo_path = repo_id2base($row['repo_id']) . $row['name'] . ".git";
44 $disk_mb = repo_disk_mb($repo_path);
45 $sql = "UPDATE repos SET disk_mb = $disk_mb"
46 . " WHERE repo_id = " . $row['repo_id'];
47 $res2 = sql_query($db, $sql);
48 if ($res2 === FALSE) {
49 xlog("Cannot run query!");
50 } else {
51 @unlink($repo_path . "/gg/dirty");
52 sql_free_result($res2);
53 }
46 54 } }
55 sql_free_result($res);
47 56 } }
48 sql_free_result($res);
49 57 } }
50 58
51 xlog("Update user quota...");
59 // TODO
60 //xlog("Update user quota...");
52 61
53 // Send notifications
62 // TODO
63 //xlog("Sending notifications...");
54 64
55 // Clean old forgot_pass entries
56 65 if (date("H") == 0) { if (date("H") == 0) {
57 66 xlog("Clean old forget_pass entries..."); xlog("Clean old forget_pass entries...");
58 67 $sql = "DELETE FROM forgot_pass WHERE expire < $now"; $sql = "DELETE FROM forgot_pass WHERE expire < $now";
 
... ... if (date("H") == 0) {
60 69 sql_free_result($res); sql_free_result($res);
61 70 } }
62 71
72 if (date("H") == 1) {
73 xlog("Clean old sess entries...");
74 $sql = "DELETE FROM sess WHERE expire < $now";
75 $res = sql_query($db, $sql);
76 sql_free_result($res);
77 }
78
79 xlog("Regenerate keys...");
80 keys_regen($db);
81
63 82 // this has to be the last thing that touches the database // this has to be the last thing that touches the database
64 83 if (date("H") == 0) { if (date("H") == 0) {
65 84 xlog("Run VACUUM on database..."); xlog("Run VACUUM on database...");

File scripts/q.php added (mode: 100644) (index 0000000..c2911ce)
1 <?php
2 // This is called by cron, and is persistent.
3 // It takes care of repository init/clone
4 error_reporting(E_ALL);
5 ini_set("track_errors", "On");
6
7 $now = time();
8 $_s = microtime(TRUE);
9
10 require_once("/etc/gg/config.php");
11
12 $INC = dirname(__FILE__) . "/../inc";
13 require_once($INC . "/xlog.inc.php");
14 require_once($INC . "/db.inc.php");
15 require_once($INC . "/repo.inc.php");
16
17 xlog_set_file("/tmp/gg_q.log");
18
19 // locking
20 $lock = "/var/run/gg/q.lock";
21 gg_lock_or_exit($lock);
22
23 $sql_debug = $gg_db_debug;
24
25 xlog("Start: euid=" . posix_geteuid() . "...");
26
27 $db = sql_open($gg_db);
28 if ($db === FALSE) {
29 xlog("Cannot connect to database!");
30 // TODO: inform admin - already by e-mail?
31 exit(1);
32 }
33
34 // limit the number of runs, so we can upgrade the software and this script will
35 // restart.
36 $runs = 1;
37 while ($runs-- > 0) {
38 // check machine load - if too big we will delay
39 while (1) {
40 $load = gg_load();
41 if ($load < 10)
42 break;
43
44 xlog("\tLoad too big!");
45 sleep(10);
46 }
47
48 xlog("Check to create not-yet-created repos...");
49 $sql = "SELECT repo_id, master, name FROM repos"
50 . " WHERE git_dir_done = 0"
51 . " ORDER BY master";
52 $res = sql_query($db, $sql);
53 if ($res === FALSE) {
54 xlog("\tCannot query!");
55 exit(1);
56 }
57 while (($row = sql_fetch_array($res))) {
58 xlog("\tProcess repo " . $row['name'] . "...");
59
60 $dst = repo_id2base($row['repo_id']) . $row['name'] . ".git";
61 if ($row['master'] == 0) {
62 $r = gg_git_init($dst);
63 if ($r === FALSE) {
64 xlog("\tCannot init master!");
65 } else {
66 repo_git_done($db, $row['repo_id']);
67 }
68 } else {
69 $mi = repo_info($db, $row['master'], "");
70 if ($mi['exists'] != 1) {
71 xlog("\tCannot find master!");
72 } else {
73 $src = repo_id2base($mi['repo_id']) . $mi['name'] . ".git";
74 $r = gg_git_clone($src, $dst);
75 if ($r === FALSE) {
76 xlog("\tCould not create repo!");
77 } else {
78 repo_git_done($db, $row['repo_id']);
79 }
80 }
81 }
82 }
83 sql_free_result($res);
84
85 sleep(10);
86 }
87
88 $_diff = sprintf("%u", microtime(TRUE) - $_s);
89 xlog("Done in " . $_diff . "s!");
90 ?>

File scripts/ssh.php changed (mode: 100644) (index bb3009e..7c4b308)
1 1 <?php <?php
2 2 // This is called by a remote client that does push or fetch // This is called by a remote client that does push or fetch
3 3 error_reporting(E_ALL); error_reporting(E_ALL);
4 ini_set("track_errors", "On");
4 5
5 6 $_start = microtime(TRUE); $_start = microtime(TRUE);
6 7
 
... ... function fatal($str)
31 32 exit(1); exit(1);
32 33 } }
33 34
34 xlog("Start...");
35 xlog("Start: euid=" . posix_geteuid() . "...");
35 36 //xlog("_SERVER: " . print_r($_SERVER, TRUE)); //xlog("_SERVER: " . print_r($_SERVER, TRUE));
36 37
37 38 umask(0022); umask(0022);
 
... ... if (!repo_allow($db, $ri, $uid, $perms))
127 128 // TODO: limit time and/or cpu // TODO: limit time and/or cpu
128 129
129 130 $repo_base = repo_id2base($ri['repo_id']); $repo_base = repo_id2base($ri['repo_id']);
130 $repo_path = $repo_base . "/" . $repo . ".git";
131 $repo_path = $repo_base . $repo . ".git";
131 132 xlog("repo_path=$repo_path."); xlog("repo_path=$repo_path.");
132 133
133 134 $run = "git-shell -c \"" . $cmd . " '" . escapeshellcmd($repo_path) . "'\""; $run = "git-shell -c \"" . $cmd . " '" . escapeshellcmd($repo_path) . "'\"";

File tests/Makefile changed (mode: 100644) (index 7771f05..7b3aaa8)
... ... test:
3 3 php util.php php util.php
4 4 php db.php php db.php
5 5 php keys.php php keys.php
6 php repo.php

File tests/keys.php changed (mode: 100644) (index a243c79..ce69fa4)
... ... if ($r === FALSE) {
45 45 } }
46 46
47 47 // test key file generation // test key file generation
48 $r = keys_regen($db, "afile.txt");
48 $gg_keys_file = "afile.txt";
49 $r = keys_regen($db);
49 50 if ($r === FALSE) { if ($r === FALSE) {
50 51 echo "Cannot regenerate keys (" . keys_error() . ")!"; echo "Cannot regenerate keys (" . keys_error() . ")!";
51 52 exit(1); exit(1);

File tests/repo.php added (mode: 100644) (index 0000000..e912ddc)
1 <?php
2 $INC = "../inc";
3 require_once($INC . "/repo.inc.php");
4
5 @unlink("repo.sqlite");
6
7 $db = sql_open("sqlite:repo.sqlite");
8 if ($db === FALSE) {
9 echo "Cannot create a database (" . sql_error() . ")!\n";
10 exit(1);
11 }
12
13 $sql = "CREATE TABLE repos (repo_id INTEGER PRIMARY KEY, name TEXT, uid INTEGER"
14 . ", itime INTEGER"
15 . ", public INTEGER"
16 . ", disk_quota_mb INTEGER"
17 . ", max_commit_size INTEGER"
18 . ", master INTEGER"
19 . ", desc TEXT"
20 . ", git_dir_done INTEGER"
21 . ")";
22 $res = sql_query($db, $sql);
23 if ($res === FALSE) {
24 echo "WARN: Cannot create 'repos' table!\n";
25 exit(1);
26 }
27
28 $sql = "CREATE TABLE repo_rights (repo_id INTEGER, uid INTEGER, rights TEXT"
29 . ", itime INTEGER)";
30 $res = sql_query($db, $sql);
31 if ($res === FALSE) {
32 echo "WARN: Cannot create 'repo_rights' table!\n";
33 exit(1);
34 }
35
36 $sql = "CREATE TABLE users (uid INTEGER PRIMARY KEY, user TEXT, salt TEXT"
37 . ", pass TEXT, email TEXT, itime INTEGER"
38 . ", suspended INTEGER"
39 . ", session_time INTEGER DEFAULT 3600"
40 . ", last_seen INTEGER"
41 . ", is_admin INTEGER"
42 . ", disk_quota_mb INTEGER"
43 . ", disk_mb INTEGER"
44 . ")";
45 $res = sql_query($db, $sql);
46 if ($res === FALSE) {
47 echo "WARN: Cannot create 'users' table!\n";
48 exit(1);
49 }
50
51 $sql = "INSERT INTO repos (repo_id, name, uid, itime"
52 . ", disk_quota_mb, max_commit_size"
53 . ", master, desc, git_dir_done)"
54 . " VALUES (1, 'repo1', 1, 0, 0, 0, 0, 'bla bla desc', 1)";
55 $res = sql_query($db, $sql);
56 if ($res === FALSE) {
57 echo "Cannot insert a user!\n";
58 exit(1);
59 }
60
61 $v = gg_repo_rights_set($db, 1, 1, "F");
62 if ($v === FALSE) {
63 echo "Cannot give rights (1)!\n";
64 exit(1);
65 }
66
67 // check if we try to give rights for a not owned repo
68 $gg_uid = 2;
69 $uid = 1;
70 $v = gg_repo_rights_get($db, $repo_id, $gg_uid, $uid, "A");
71 if ($v === TRUE) {
72 echo "Error: " . gg_repo_error() . "!\n";
73 exit(1);
74 }
75
76 @unlink("repo.sqlite");
77 ?>
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