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() | |
18 | 18 | return $keys_error; | return $keys_error; |
19 | 19 | } | } |
20 | 20 | ||
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 | |||
21 | 38 | /* | /* |
22 | 39 | * Remove a key from database | * Remove a key from database |
23 | 40 | */ | */ |
... | ... | 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&key_id=" . $row['key_id'] | ||
173 | . "&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&subop=1\">Add</a>]"; | ||
18 | $_menu .= " [<a href=\"$_url&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 . "&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&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) | |
218 | 295 | return $ret; | return $ret; |
219 | 296 | } | } |
220 | 297 | ||
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 | |||
221 | 340 | /* | /* |
222 | 341 | * Computes the size of a repository | * Computes the size of a repository |
223 | 342 | */ | */ |
... | ... | 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 . "&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&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&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&subop=1\">Create</a>]"; | $_menu .= "[<a href=\"$_url&subop=1\">Create</a>]"; |
13 | 25 | $_menu .= " [<a href=\"$_url&subop=2\">List</a>]"; | $_menu .= " [<a href=\"$_url&subop=2\">List</a>]"; |
26 | $_menu .= " [<a href=\"$_url&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&repo_id=$repo_id"; | ||
17 | $_menu = ""; | ||
18 | $_menu .= "[<a href=\"$_url&subop=1\">Edit</a>]"; | ||
19 | $_menu .= " [<a href=\"$_url&subop=2\">Rights</a>]"; | ||
20 | $_menu .= " [<a href=\"$_url&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&op=1\">Login</a>]"; | $menu .= "[<a href=\"$url&op=1\">Login</a>]"; |
73 | 75 | if (isset($gg_ui['user'])) { | if (isset($gg_ui['user'])) { |
74 | $menu .= " [<a href=\"$url&op=2\">Repositories</a>]"; | ||
76 | $menu .= " [<a href=\"$url&op=4\">Keys</a>]\n"; | ||
77 | $menu .= " [<a href=\"$url&op=2\">My repositories</a>]\n"; | ||
75 | 78 | if ($gg_ui['is_admin'] == 1) | if ($gg_ui['is_admin'] == 1) |
76 | $menu .= " [<a href=\"$url&op=3\">Admin</a>]"; | ||
77 | $menu .= " [<a href=\"$url&op=9\">Logout</a>]"; | ||
78 | $menu .= " [" . $gg_ui['user'] . "]"; | ||
79 | $menu .= " [<a href=\"$url&op=3\">Admin</a>]\n"; | ||
80 | |||
81 | $menu .= " [<a href=\"$url&op=9\">Logout</a>]\n"; | ||
82 | |||
83 | $menu .= " [" . $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 | ?> |