File | Lines added | Lines deleted |
---|---|---|
TODO | 27 | 1 |
admin/sql.php | 15 | 3 |
inc/admin/admin.php | 1 | 1 |
inc/admin/repos/repos.php | 3 | 1 |
inc/admin/users/add.php | 1 | 2 |
inc/admin/users/users.php | 1 | 1 |
inc/keys.inc.php | 2 | 0 |
inc/login/login.form.php | 17 | 3 |
inc/login/login.php | 7 | 4 |
inc/repo.inc.php | 124 | 12 |
inc/repo/repo.form.php | 8 | 1 |
inc/repo/repo.php | 8 | 2 |
inc/user.inc.php | 133 | 11 |
inc/user/forgot.form.php | 37 | 0 |
inc/user/forgot.php | 39 | 0 |
inc/user/forgot_mail.php | 16 | 0 |
inc/xlog.inc.php | 4 | 1 |
root/index.php | 29 | 11 |
samples/cron | 1 | 0 |
samples/gg | 15 | 0 |
scripts/cron.php | 77 | 0 |
scripts/ssh.php | 101 | 37 |
tests/Makefile | 1 | 0 |
tests/user.php | 34 | 0 |
tests/util.php | 10 | 0 |
File TODO changed (mode: 100644) (index 27052f2..070b936) | |||
1 | == BEFORE FIRST RELEASE! == | ||
2 | [ ] Validate e-mails. | ||
3 | [ ] Validate repo names. | ||
4 | [ ] Validate user names. | ||
5 | [ ] | ||
6 | |||
7 | == Low priority == | ||
1 | 8 | [ ] Count the numbers of clones/pushes/pulls. | [ ] Count the numbers of clones/pushes/pulls. |
2 | 9 | [ ] Add memcache caching for all database lookups. | [ ] Add memcache caching for all database lookups. |
3 | 10 | [ ] Allow to configure the limit of the patch size to prevent abuses. | [ ] Allow to configure the limit of the patch size to prevent abuses. |
6 | 13 | [ ] Add a repo_prop_set/get function that will set/get a file in .git folder. THis way we can | [ ] Add a repo_prop_set/get function that will set/get a file in .git folder. THis way we can |
7 | 14 | speed up some lookups (no need for database). Hm. | speed up some lookups (no need for database). Hm. |
8 | 15 | [ ] 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 |
9 | return OK, in the background we will do the removing. Do not forget to also remove clones. Hm. | ||
16 | return OK, in the background we will do the removing. Do not forget to also remove clones. Hm. | ||
17 | [ ] SSH keys section. | ||
18 | [ ] E-mail aliases section. | ||
19 | [ ] User details section (full name, e-mail, blog, avatar, mail notifications). | ||
20 | [ ] Change password section. | ||
21 | [ ] Check if user is over-quota on push. | ||
22 | [ ] The cron will have to: | ||
23 | [ ] Compute disk usage, ignoring hard links. Hm. Probably we will add | ||
24 | only the owner, even if the files have multiple links. TBD. | ||
25 | [ ] VACUUM tables. | ||
26 | [ ] | ||
27 | [ ] UTF-8 checks. | ||
28 | [ ] W3C validation on all pages. | ||
29 | [ ] Validate user and repo names. Probably other things. | ||
30 | [ ] What happens if a user is suspended? Do we allow forgot pass sending? | ||
31 | [ ] Do not allow session updates/any command if user is suspended after his/her login. | ||
32 | [ ] Timeout for connections (ssh/git-daemon/etc.)! | ||
33 | [ ] 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! | ||
35 | [ ] |
File admin/sql.php changed (mode: 100644) (index afdd9d0..7ff98e8) | |||
... | ... | if ($db === FALSE) | |
15 | 15 | // create repos table | // create repos table |
16 | 16 | $sql = "CREATE TABLE repos (repo_id INTEGER PRIMARY KEY, name TEXT, uid INTEGER" | $sql = "CREATE TABLE repos (repo_id INTEGER PRIMARY KEY, name TEXT, uid INTEGER" |
17 | 17 | . ", itime INTEGER" | . ", itime INTEGER" |
18 | . ", public INTEGER)"; | ||
18 | . ", public INTEGER" | ||
19 | . ", disk_quota_mb INTEGER" | ||
20 | . ", max_commit_size INTEGER" | ||
21 | . ", master INTEGER" | ||
22 | . ")"; | ||
19 | 23 | $res = sql_query($db, $sql); | $res = sql_query($db, $sql); |
20 | 24 | if ($res === FALSE) | if ($res === FALSE) |
21 | 25 | echo "WARN: Cannot create 'repo_access' table!\n"; | echo "WARN: Cannot create 'repo_access' table!\n"; |
... | ... | if ($res === FALSE) | |
41 | 45 | $sql = "CREATE TABLE users (uid INTEGER PRIMARY KEY, user TEXT, salt TEXT" | $sql = "CREATE TABLE users (uid INTEGER PRIMARY KEY, user TEXT, salt TEXT" |
42 | 46 | . ", pass TEXT, email TEXT, itime INTEGER" | . ", pass TEXT, email TEXT, itime INTEGER" |
43 | 47 | . ", suspended INTEGER" | . ", suspended INTEGER" |
44 | . ", session_time INTEGER" | ||
48 | . ", session_time INTEGER DEFAULT 3600" | ||
45 | 49 | . ", last_seen INTEGER" | . ", last_seen INTEGER" |
46 | . ", is_admin INTEGER)"; | ||
50 | . ", is_admin INTEGER" | ||
51 | . ", disk_quota_mb INTEGER" | ||
52 | . ", disk_mb INTEGER" | ||
53 | . ")"; | ||
47 | 54 | $res = sql_query($db, $sql); | $res = sql_query($db, $sql); |
48 | 55 | if ($res === FALSE) | if ($res === FALSE) |
49 | 56 | echo "WARN: Cannot create 'users' table!\n"; | echo "WARN: Cannot create 'users' table!\n"; |
... | ... | $res = sql_query($db, $sql); | |
54 | 61 | if ($res === FALSE) | if ($res === FALSE) |
55 | 62 | echo "WARN: Cannot create 'sess' table!\n"; | echo "WARN: Cannot create 'sess' table!\n"; |
56 | 63 | ||
64 | $sql = "CREATE TABLE forgot_pass (token TEXT PRIMARY KEY, uid INTEGER, expire INTEGER)" | ||
65 | $res = sql_query($db, $sql); | ||
66 | if ($res === FALSE) | ||
67 | echo "WARN: Cannot create 'forgot_pass' table!\n"; | ||
68 | |||
57 | 69 | echo "Done!\n"; | echo "Done!\n"; |
58 | 70 | ?> | ?> |
File inc/admin/admin.php changed (mode: 100644) (index e206e85..9e60be1) | |||
1 | 1 | <?php | <?php |
2 | xlog("/admin"); | ||
2 | xlog("/inc/admin"); | ||
3 | 3 | ||
4 | 4 | if ($gg_ui['is_admin'] != 1) { | if ($gg_ui['is_admin'] != 1) { |
5 | 5 | $_admin = "You do not have access here!"; | $_admin = "You do not have access here!"; |
File inc/admin/repos/repos.php changed (mode: 100644) (index 4a0e298..577cf13) | |||
... | ... | $_admin_repos_body = ""; | |
15 | 15 | ||
16 | 16 | switch ($subsubop) { | switch ($subsubop) { |
17 | 17 | case 1: // list | case 1: // list |
18 | $_admin_repos_body .= repo_list($db, $_admin_repos_url . "&subsubop=$subsubop", 0); | ||
18 | $_only_master = 0; | ||
19 | $_uid = 0; | ||
20 | $_admin_repos_body .= repo_list($db, $_admin_repos_url . "&subsubop=$subsubop", $_uid, $_only_master); | ||
19 | 21 | break; | break; |
20 | 22 | } | } |
21 | 23 |
File inc/admin/users/add.php changed (mode: 100644) (index bd02e82..38d55a2) | |||
... | ... | if ($doit == 1) { | |
7 | 7 | $xuser = @$_REQUEST['xuser']; | $xuser = @$_REQUEST['xuser']; |
8 | 8 | $email = @$_REQUEST['email']; | $email = @$_REQUEST['email']; |
9 | 9 | $xpass = @$_REQUEST['xpass']; | $xpass = @$_REQUEST['xpass']; |
10 | xlog("xxx: " . print_r($_REQUEST, TRUE)); | ||
11 | 10 | $is_admin = @intval($_REQUEST['is_admin']); | $is_admin = @intval($_REQUEST['is_admin']); |
12 | 11 | ||
13 | $_ui = user_info($db, 0, $xuser); | ||
12 | $_ui = user_info($db, 0, $xuser, ""); | ||
14 | 13 | if ($_ui['ok'] == 0) { | if ($_ui['ok'] == 0) { |
15 | 14 | $_user_add .= "Error: Internal error!"; | $_user_add .= "Error: Internal error!"; |
16 | 15 | } else if ($_ui['exists'] == 0) { | } else if ($_ui['exists'] == 0) { |
File inc/admin/users/users.php changed (mode: 100644) (index ef85c8a..c45c3ba) | |||
1 | 1 | <?php | <?php |
2 | xlog("/admin/users"); | ||
2 | xlog("/inc/admin/users"); | ||
3 | 3 | ||
4 | 4 | $subsubop = @intval($_REQUEST['subsubop']); | $subsubop = @intval($_REQUEST['subsubop']); |
5 | 5 |
File inc/keys.inc.php changed (mode: 100644) (index f813cdd..507b9c7) | |||
... | ... | $keys_error = ""; | |
7 | 7 | function keys_set_error($str) | function keys_set_error($str) |
8 | 8 | { | { |
9 | 9 | global $keys_error; | global $keys_error; |
10 | |||
11 | xlog("\tError: $str"); | ||
10 | 12 | $keys_error = $str; | $keys_error = $str; |
11 | 13 | } | } |
12 | 14 |
File inc/login/login.form.php changed (mode: 100644) (index 182216f..26ea6eb) | |||
1 | 1 | <?php | <?php |
2 | $_form = ''; | ||
2 | 3 | ||
3 | $_form = ' | ||
4 | <form type="post" action="' . $_SERVER['PHP_SELF'] . '"> | ||
4 | if (!empty($error)) | ||
5 | $_form .= "<font color=red>$error</font>\n"; | ||
6 | |||
7 | $_form .= ' | ||
8 | <form method="post" action="' . $_SERVER['PHP_SELF'] . '"> | ||
5 | 9 | <input type="hidden" name="op" value="' . $op . '"> | <input type="hidden" name="op" value="' . $op . '"> |
6 | 10 | <input type="hidden" name="doit" value="1"> | <input type="hidden" name="doit" value="1"> |
7 | 11 | ||
8 | 12 | User: <input type="text" name="user" value="' . $user . '"><br /> | User: <input type="text" name="user" value="' . $user . '"><br /> |
9 | 13 | Password: <input type="password" name="pass" value="' . $pass . '"><br /> | Password: <input type="password" name="pass" value="' . $pass . '"><br /> |
10 | <input type="submit" value="Go!"> | ||
14 | <input type="submit" value="Login"> | ||
15 | </form> | ||
16 | <br /> | ||
17 | |||
18 | Forgot your password?<br /> | ||
19 | <form method="post" action="' . $_SERVER['PHP_SELF'] . '"> | ||
20 | <input type="hidden" name="op" value="7"> | ||
21 | <input type="hidden" name="doit" value="1"> | ||
22 | |||
23 | E-mail: <input type="text" name="email" value=""><br /> | ||
24 | <input type="submit" value="Recover password"> | ||
11 | 25 | </form> | </form> |
12 | 26 | '; | '; |
13 | 27 |
File inc/login/login.php changed (mode: 100644) (index 267d01d..d677c0c) | |||
1 | 1 | <?php | <?php |
2 | xlog("/inc/login/login.php"); | ||
2 | 3 | ||
3 | 4 | $doit = @intval($_REQUEST['doit']); | $doit = @intval($_REQUEST['doit']); |
4 | 5 | $user = @$_COOKIE['user']; | $user = @$_COOKIE['user']; |
... | ... | $pass = ""; | |
6 | 7 | ||
7 | 8 | $_login = "<br />\n"; | $_login = "<br />\n"; |
8 | 9 | ||
9 | if ($doit == 0) { | ||
10 | include($INC . "/login/login.form.php"); | ||
11 | $_login .= $_form; | ||
12 | } | ||
10 | $error = ""; | ||
11 | if ($doit == 1) | ||
12 | $error = "Invalid user and/or pass."; | ||
13 | |||
14 | include($INC . "/login/login.form.php"); | ||
15 | $_login .= $_form; | ||
13 | 16 | ||
14 | 17 | ?> | ?> |
File inc/repo.inc.php changed (mode: 100644) (index 9463070..69506c4) | |||
1 | 1 | <?php | <?php |
2 | require_once($INC . "/util.inc.php"); | ||
2 | 3 | require_once($INC . "/xlog.inc.php"); | require_once($INC . "/xlog.inc.php"); |
3 | 4 | require_once($INC . "/db.inc.php"); | require_once($INC . "/db.inc.php"); |
4 | 5 | require_once($INC . "/user.inc.php"); | require_once($INC . "/user.inc.php"); |
... | ... | function repo_error() | |
19 | 20 | return $repo_error; | return $repo_error; |
20 | 21 | } | } |
21 | 22 | ||
23 | /* | ||
24 | * Returns the path to a repository based on repo_id | ||
25 | */ | ||
26 | function repo_id2base($repo_id) | ||
27 | { | ||
28 | global $gg_base_repo; | ||
29 | |||
30 | $r3 = sprintf("%03u", $repo_id / 1000); | ||
31 | |||
32 | return $gg_base_repo . "/" | ||
33 | . $r3[0] . "/" . $r3[1] . "/" . $r3[2]; | ||
34 | } | ||
35 | |||
36 | /* | ||
37 | * Return info about a repo | ||
38 | */ | ||
39 | function repo_info($db, $repo_id, $repo) | ||
40 | { | ||
41 | xlog("repo_info: $repo_id, repo=$repo..."); | ||
42 | |||
43 | $ret['ok'] = 0; | ||
44 | |||
45 | $repo_id = sprintf("%u", $repo_id); | ||
46 | if ($repo_id > 0) { | ||
47 | $add = " AND repo_id = $repo_id"; | ||
48 | } else if (!empty($repo)) { | ||
49 | $e_repo = sql_escape($db, $repo); | ||
50 | $add = " AND name = '$e_repo'"; | ||
51 | } else { | ||
52 | $ret['errmsg'] = "No repo_id or name specified!"; | ||
53 | return $ret; | ||
54 | } | ||
55 | |||
56 | $sql = "SELECT * FROM repos WHERE 1 = 1" . $add; | ||
57 | $res = sql_query($db, $sql); | ||
58 | if ($res === FALSE) { | ||
59 | $ret['errmsg'] = "Cannot query (" . sql_error() . ")"; | ||
60 | xlog("\t" . $ret['errmsg']); | ||
61 | return $ret; | ||
62 | } | ||
63 | $ret['ok'] = 1; | ||
64 | $ret['exists'] = 0; | ||
65 | $row = sql_fetch_array($res); | ||
66 | sql_free_result($res); | ||
67 | if (!isset($row['repo_id'])) { | ||
68 | xlog("\tRepo not found!"); | ||
69 | return $ret; | ||
70 | } | ||
71 | |||
72 | $row['exists'] = 1; | ||
73 | $row['ok'] = 1; | ||
74 | return $row; | ||
75 | } | ||
76 | |||
22 | 77 | /* | /* |
23 | 78 | * Check if a uid has access to repository | * Check if a uid has access to repository |
24 | 79 | */ | */ |
25 | function repo_allow($db, $repo_id, $uid, $perms) | ||
80 | function repo_allow($db, $ri, $uid, $perms) | ||
26 | 81 | { | { |
27 | xlog("repo_allow: repo_id=$repo_id, uid=$uid, perms=$perms..."); | ||
82 | xlog("repo_allow: uid=$uid, perms=$perms..."); | ||
28 | 83 | ||
29 | $e_repo_id = sprintf("%u", $repo_id); | ||
30 | 84 | $e_uid = sprintf("%u", $uid); | $e_uid = sprintf("%u", $uid); |
31 | 85 | $e_perms = preg_replace("/[^A-Z]/", "", $perms); | $e_perms = preg_replace("/[^A-Z]/", "", $perms); |
32 | 86 | ||
33 | if (empty($e_perms)) | ||
87 | if (empty($e_perms)) { | ||
88 | xlog("\tNo perms passed!"); | ||
34 | 89 | return FALSE; | return FALSE; |
90 | } | ||
91 | |||
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!"); | ||
104 | return FALSE; | ||
105 | } | ||
106 | |||
107 | return TRUE; | ||
108 | } | ||
35 | 109 | ||
36 | 110 | if (strcmp($perms, "R") == 0) | if (strcmp($perms, "R") == 0) |
37 | 111 | $perms_add = " AND (perm = 'R' OR perm = 'W')"; | $perms_add = " AND (perm = 'R' OR perm = 'W')"; |
... | ... | function repo_allow($db, $repo_id, $uid, $perms) | |
39 | 113 | $perms_add = " AND perm = 'W'"; | $perms_add = " AND perm = 'W'"; |
40 | 114 | ||
41 | 115 | $sql = "SELECT 1 AS junk FROM repo_access" | $sql = "SELECT 1 AS junk FROM repo_access" |
42 | . " WHERE repo_id = $e_repo_id" | ||
116 | . " WHERE repo_id = " . $ri['repo_id'] | ||
43 | 117 | . " AND uid = $e_uid" | . " AND uid = $e_uid" |
44 | 118 | . $perms_add; | . $perms_add; |
45 | 119 | $res = sql_query($db, $sql); | $res = sql_query($db, $sql); |
... | ... | function repo_allow($db, $repo_id, $uid, $perms) | |
60 | 134 | ||
61 | 135 | /* | /* |
62 | 136 | * Add a repository | * Add a repository |
137 | * @master - makes sense only for clones - who is the master. | ||
63 | 138 | */ | */ |
64 | function repo_create($db, $uid, $name, $public) | ||
139 | function repo_create($db, $master, $uid, $name, $public, $max_commit_size) | ||
65 | 140 | { | { |
66 | xlog("repo_create: name=[$name], public=$public..."); | ||
141 | xlog("repo_create: name=[$name], master=$master, public=$public" | ||
142 | . ", max_commit_size=$max_commit_size" | ||
143 | . "..."); | ||
67 | 144 | ||
68 | 145 | $name = htmlspecialchars($name); | $name = htmlspecialchars($name); |
69 | 146 | $e_name = sql_escape($db, $name); | $e_name = sql_escape($db, $name); |
70 | 147 | ||
71 | 148 | $itime = time(); | $itime = time(); |
72 | 149 | ||
73 | $sql = "INSERT INTO repos (uid, name, itime, public)" | ||
74 | . " VALUES ($uid, '$e_name', $itime, $public)"; | ||
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)"; | ||
75 | 154 | $res = sql_query($db, $sql); | $res = sql_query($db, $sql); |
76 | 155 | if ($res === FALSE) { | if ($res === FALSE) { |
77 | 156 | repo_set_error("Cannot insert (" . sql_error() . ")"); | repo_set_error("Cannot insert (" . sql_error() . ")"); |
... | ... | function repo_create($db, $uid, $name, $public) | |
83 | 162 | /* | /* |
84 | 163 | * List repositories | * List repositories |
85 | 164 | */ | */ |
86 | function repo_list($db, $url, $uid) | ||
165 | function repo_list($db, $url, $uid, $only_master) | ||
87 | 166 | { | { |
88 | xlog("repo_list: url=$url, uid=$uid..."); | ||
167 | xlog("repo_list: url=$url, uid=$uid, only_master=$only_master..."); | ||
89 | 168 | ||
90 | 169 | $add = ""; | $add = ""; |
91 | 170 | if ($uid > 0) | if ($uid > 0) |
92 | 171 | $add = " AND uid = $uid"; | $add = " AND uid = $uid"; |
93 | 172 | ||
94 | $sql = "SELECT * FROM repos WHERE 1 = 1" . $add; | ||
173 | if ($only_master == 1) | ||
174 | $add .= " AND master = 0"; | ||
175 | |||
176 | $sql = "SELECT * FROM repos WHERE 1 = 1" | ||
177 | . $add | ||
178 | . " ORDER BY name"; | ||
95 | 179 | $res = sql_query($db, $sql); | $res = sql_query($db, $sql); |
96 | 180 | if ($res === FALSE) | if ($res === FALSE) |
97 | 181 | return FALSE; | return FALSE; |
... | ... | function repo_list($db, $url, $uid) | |
99 | 183 | $ret = "<table>\n"; | $ret = "<table>\n"; |
100 | 184 | $ret .= "<tr>\n"; | $ret .= "<tr>\n"; |
101 | 185 | $ret .= " <th>Name</th>\n"; | $ret .= " <th>Name</th>\n"; |
186 | if ($only_master == 0) | ||
187 | $ret .= " <th>Master?</th>\n"; | ||
102 | 188 | $ret .= " <th>Creation date (UTC)</th>\n"; | $ret .= " <th>Creation date (UTC)</th>\n"; |
103 | 189 | $ret .= " <th>Public</th>\n"; | $ret .= " <th>Public</th>\n"; |
190 | $ret .= " <th>Disk current/max</th>\n"; | ||
191 | $ret .= " <th>Max commit size</th>\n"; | ||
104 | 192 | $ret .= " <th>Operations</th>\n"; | $ret .= " <th>Operations</th>\n"; |
105 | 193 | $ret .= "</tr>\n"; | $ret .= "</tr>\n"; |
106 | 194 | while (($row = sql_fetch_array($res))) { | while (($row = sql_fetch_array($res))) { |
107 | 195 | $ret .= "<tr>\n"; | $ret .= "<tr>\n"; |
108 | 196 | $ret .= " <td>" . $row['name'] . "</td>\n"; | $ret .= " <td>" . $row['name'] . "</td>\n"; |
197 | if ($only_master == 0) | ||
198 | $ret .= " <td>" . ($row['master'] == 0 ? "Yes" : "No") . "</td>\n"; | ||
109 | 199 | $ret .= " <td>" . date("Y-m-d H:i:s", $row['itime']) . "</td>\n"; | $ret .= " <td>" . date("Y-m-d H:i:s", $row['itime']) . "</td>\n"; |
110 | 200 | $ret .= " <td>" . ($row['public'] == 1 ? "Yes" : "No") . "</td>\n"; | $ret .= " <td>" . ($row['public'] == 1 ? "Yes" : "No") . "</td>\n"; |
201 | |||
202 | $_max = "ulimited"; | ||
203 | if ($row['disk_quota_mb'] > 0) | ||
204 | $_max = gg_1024($row['disk_quota_mb']); | ||
205 | $ret .= " <td>" . $row['disk_mb'] . "/" . $_max . "</td>\n"; | ||
206 | |||
207 | $_v = "ulimited"; | ||
208 | if ($row['max_commit_size'] > 0) | ||
209 | $_v = gg_1024($row['max_commit_size']); | ||
210 | $ret .= " <td>" . $_v . "</td>\n"; | ||
211 | |||
111 | 212 | $ret .= " <td>-</td>\n"; | $ret .= " <td>-</td>\n"; |
112 | 213 | $ret .= "</tr>\n"; | $ret .= "</tr>\n"; |
113 | 214 | } | } |
... | ... | function repo_list($db, $url, $uid) | |
116 | 217 | ||
117 | 218 | return $ret; | return $ret; |
118 | 219 | } | } |
220 | |||
221 | /* | ||
222 | * Computes the size of a repository | ||
223 | */ | ||
224 | function repo_disk_mb($path) | ||
225 | { | ||
226 | xlog("repo_disk_mb: path=$path..."); | ||
227 | |||
228 | return 10; | ||
229 | } | ||
230 | |||
119 | 231 | ?> | ?> |
File inc/repo/repo.form.php changed (mode: 100644) (index ab8add9..4fede90) | |||
... | ... | $_form = ' | |
24 | 24 | </td> | </td> |
25 | 25 | </tr> | </tr> |
26 | 26 | ||
27 | <tr> | ||
28 | <td>Max commit size (bytes):</td> | ||
29 | <td> | ||
30 | <input type="text" name="max_commit_size" value="' . $max_commit_size . '"><br /> | ||
31 | </td> | ||
32 | </tr> | ||
33 | |||
27 | 34 | <tr> | <tr> |
28 | 35 | <td colspan="2"><input type="submit" value="Go!"></td> | <td colspan="2"><input type="submit" value="Go!"></td> |
29 | 36 | </tr> | </tr> |
... | ... | $_form = ' | |
33 | 40 | '; | '; |
34 | 41 | ||
35 | 42 | ||
36 | ?> | ||
43 | ?> |
File inc/repo/repo.php changed (mode: 100644) (index 3d10172..194bbaa) | |||
1 | 1 | <?php | <?php |
2 | xlog("/inc/repo/repo.php"); | ||
3 | |||
2 | 4 | $subop = @intval($_REQUEST['subop']); | $subop = @intval($_REQUEST['subop']); |
3 | 5 | $public = @intval($_REQUEST['public']); | $public = @intval($_REQUEST['public']); |
4 | 6 | $name = @$_REQUEST['name']; | $name = @$_REQUEST['name']; |
7 | $max_commit_size = @intval($_REQUEST['max_commit_size']); | ||
5 | 8 | ||
6 | 9 | // menu | // menu |
7 | 10 | $_url = $_SERVER['PHP_SELF'] . "?op=$op"; | $_url = $_SERVER['PHP_SELF'] . "?op=$op"; |
... | ... | $_body = ""; | |
16 | 19 | switch ($subop) { | switch ($subop) { |
17 | 20 | case 1: // create | case 1: // create |
18 | 21 | if ($doit == 1) { | if ($doit == 1) { |
19 | $_r = repo_create($db, $uid, $name, $public); | ||
22 | $master = 1; | ||
23 | $_r = repo_create($db, $master, $uid, $name, $public, | ||
24 | $max_commit_size); | ||
20 | 25 | $_body = "bau!"; | $_body = "bau!"; |
21 | 26 | } else { | } else { |
22 | 27 | include($INC . "/repo/repo.form.php"); | include($INC . "/repo/repo.form.php"); |
... | ... | case 1: // create | |
25 | 30 | break; | break; |
26 | 31 | ||
27 | 32 | case 2: //list | case 2: //list |
28 | $_body .= repo_list($db, "", $uid); | ||
33 | $only_masters = 1; | ||
34 | $_body .= repo_list($db, "", $uid, $only_masters); | ||
29 | 35 | break; | break; |
30 | 36 | } | } |
31 | 37 |
File inc/user.inc.php changed (mode: 100644) (index ead7291..dffe347) | |||
1 | 1 | <?php | <?php |
2 | require_once($INC . "/util.inc.php"); | ||
2 | 3 | require_once($INC . "/xlog.inc.php"); | require_once($INC . "/xlog.inc.php"); |
3 | 4 | require_once($INC . "/db.inc.php"); | require_once($INC . "/db.inc.php"); |
4 | 5 | require_once($INC . "/sess.inc.php"); | require_once($INC . "/sess.inc.php"); |
... | ... | function gg_user_error() | |
22 | 23 | */ | */ |
23 | 24 | function user_add($db, $user, $pass, $email, $is_admin) | function user_add($db, $user, $pass, $email, $is_admin) |
24 | 25 | { | { |
26 | global $gg_session_time; | ||
27 | |||
25 | 28 | xlog("user_add: user=$user, pass=$pass, email=$email, is_admin=$is_admin..."); | xlog("user_add: user=$user, pass=$pass, email=$email, is_admin=$is_admin..."); |
26 | 29 | ||
27 | 30 | $itime = time(); | $itime = time(); |
28 | $e_salt = sha1(mt_rand() . microtime(TRUE)); | ||
31 | $e_salt = gg_id(40); | ||
29 | 32 | $e_sha1pass = sha1($e_salt . "===" . $pass); | $e_sha1pass = sha1($e_salt . "===" . $pass); |
33 | $session_time = $gg_session_time; | ||
30 | 34 | ||
31 | 35 | $e_user = sql_escape($db, $user); | $e_user = sql_escape($db, $user); |
32 | 36 | $e_email = sql_escape($db, $email); | $e_email = sql_escape($db, $email); |
33 | 37 | ||
34 | $sql = "INSERT INTO users (user, salt, pass, email, itime, is_admin)" | ||
38 | $sql = "INSERT INTO users (user, salt, pass, email, itime, is_admin, session_time)" | ||
35 | 39 | . " VALUES ('$e_user', '$e_salt', '$e_sha1pass', '$e_email'" | . " VALUES ('$e_user', '$e_salt', '$e_sha1pass', '$e_email'" |
36 | . ", $itime, $is_admin)"; | ||
40 | . ", $itime, $is_admin, $session_time)"; | ||
37 | 41 | $res = sql_query($db, $sql); | $res = sql_query($db, $sql); |
38 | 42 | if ($res === FALSE) { | if ($res === FALSE) { |
39 | 43 | gg_user_set_error("Cannot insert user (" . sql_error() . ")!"); | gg_user_set_error("Cannot insert user (" . sql_error() . ")!"); |
... | ... | function user_remove($db, $uid) | |
65 | 69 | /* | /* |
66 | 70 | * Returns info about a user (by uid or user fields) | * Returns info about a user (by uid or user fields) |
67 | 71 | */ | */ |
68 | function user_info($db, $uid, $user) | ||
72 | function user_info($db, $uid, $user, $email) | ||
69 | 73 | { | { |
70 | xlog("user_info: uid=[$uid], user=[$user]..."); | ||
74 | xlog("user_info: uid=[$uid], user=[$user], email=[$email]..."); | ||
71 | 75 | ||
72 | 76 | $ret = array(); | $ret = array(); |
73 | 77 | $ret['ok'] = 0; | $ret['ok'] = 0; |
... | ... | function user_info($db, $uid, $user) | |
75 | 79 | ||
76 | 80 | if ($uid > 0) { | if ($uid > 0) { |
77 | 81 | $add = " AND uid = " . sprintf("%u", $uid); | $add = " AND uid = " . sprintf("%u", $uid); |
78 | } else { | ||
82 | } else if (!empty($user)) { | ||
79 | 83 | $e_user = sql_escape($db, $user); | $e_user = sql_escape($db, $user); |
80 | 84 | $add = " AND user = '$e_user'"; | $add = " AND user = '$e_user'"; |
85 | } else if (!empty($email)) { | ||
86 | $e_email = sql_escape($db, $email); | ||
87 | $add = " AND email = '$e_email'"; | ||
88 | } else { | ||
89 | return FALSE; | ||
81 | 90 | } | } |
82 | 91 | ||
83 | 92 | $sql = "SELECT * FROM users WHERE 1 = 1" . $add; | $sql = "SELECT * FROM users WHERE 1 = 1" . $add; |
... | ... | function user_login($db, $sid, &$ui) | |
108 | 117 | xlog("user_login: sid=$sid..."); | xlog("user_login: sid=$sid..."); |
109 | 118 | ||
110 | 119 | if (($uid = sess_valid($db, $sid))) { | if (($uid = sess_valid($db, $sid))) { |
111 | $ui = user_info($db, $uid, ""); | ||
120 | $ui = user_info($db, $uid, "", ""); | ||
112 | 121 | sess_update($db, $sid); | sess_update($db, $sid); |
113 | 122 | return $uid; | return $uid; |
114 | 123 | } | } |
... | ... | function user_login($db, $sid, &$ui) | |
119 | 128 | if (empty($user) || empty($pass)) | if (empty($user) || empty($pass)) |
120 | 129 | return FALSE; | return FALSE; |
121 | 130 | ||
122 | $ui = user_info($db, 0, $user); | ||
131 | $ui = user_info($db, 0, $user, ""); | ||
123 | 132 | if ($ui['ok'] == 0) { | if ($ui['ok'] == 0) { |
124 | 133 | gg_user_set_error("Internal error"); | gg_user_set_error("Internal error"); |
125 | 134 | return FALSE; | return FALSE; |
... | ... | function user_login($db, $sid, &$ui) | |
137 | 146 | return FALSE; | return FALSE; |
138 | 147 | } | } |
139 | 148 | ||
140 | $sid = sha1(mt_rand() . microtime(TRUE)); | ||
149 | $sid = gg_id(40); | ||
141 | 150 | sess_add($db, $ui['uid'], $sid, $ui['session_time']); | sess_add($db, $ui['uid'], $sid, $ui['session_time']); |
142 | 151 | setcookie("sid", $sid, 0); | setcookie("sid", $sid, 0); |
143 | 152 | ||
... | ... | function user_list($db, $url) | |
224 | 233 | $ret .= "<tr>\n"; | $ret .= "<tr>\n"; |
225 | 234 | $ret .= " <th>Name</th>\n"; | $ret .= " <th>Name</th>\n"; |
226 | 235 | $ret .= " <th>E-mail</th>\n"; | $ret .= " <th>E-mail</th>\n"; |
227 | $ret .= " <th>Admin</th>\n"; | ||
236 | $ret .= " <th>Admin?</th>\n"; | ||
228 | 237 | $ret .= " <th>Creation date</th>\n"; | $ret .= " <th>Creation date</th>\n"; |
238 | $ret .= " <th>Quota</th>\n"; | ||
229 | 239 | $ret .= " <th>Suspended?</th>\n"; | $ret .= " <th>Suspended?</th>\n"; |
230 | 240 | $ret .= " <th>Session time</th>\n"; | $ret .= " <th>Session time</th>\n"; |
231 | 241 | $ret .= " <th>Last seen</th>\n"; | $ret .= " <th>Last seen</th>\n"; |
... | ... | function user_list($db, $url) | |
237 | 247 | $ret .= " <td>" . $row['email'] . "</td>\n"; | $ret .= " <td>" . $row['email'] . "</td>\n"; |
238 | 248 | $ret .= " <td>" . ($row['is_admin'] == 1 ? "Yes" : "No") . "</td>\n"; | $ret .= " <td>" . ($row['is_admin'] == 1 ? "Yes" : "No") . "</td>\n"; |
239 | 249 | $ret .= " <td>" . date("Y-m-d H:i:s", $row['itime']) . "</td>\n"; | $ret .= " <td>" . date("Y-m-d H:i:s", $row['itime']) . "</td>\n"; |
250 | $_v = "unlimited"; | ||
251 | if ($row['disk_quota_mb'] > 0) | ||
252 | $_v = gg_1024($row['disk_quota_mb']); | ||
253 | $ret .= " <td>" . $_v . "</td>\n"; | ||
240 | 254 | $ret .= " <td>" . ($row['suspended'] == 0 ? "No" : "Yes") . "</th>\n"; | $ret .= " <td>" . ($row['suspended'] == 0 ? "No" : "Yes") . "</th>\n"; |
241 | 255 | $ret .= " <td>" . $row['session_time'] . "s</td>\n"; | $ret .= " <td>" . $row['session_time'] . "s</td>\n"; |
242 | 256 | $ret .= " <td>" . date("Y-m-d H:i:s", $row['last_seen']) . "</td>\n"; | $ret .= " <td>" . date("Y-m-d H:i:s", $row['last_seen']) . "</td>\n"; |
... | ... | function user_list($db, $url) | |
251 | 265 | } | } |
252 | 266 | $ret .= "[<a href=\"$_url&suspend=$v\">$t</a>]"; | $ret .= "[<a href=\"$_url&suspend=$v\">$t</a>]"; |
253 | 267 | // admin | // admin |
254 | $v = 1; $t = "Make admin"; | ||
268 | $v = 1; $t = "Admin"; | ||
255 | 269 | if ($row['is_admin'] == 1) { | if ($row['is_admin'] == 1) { |
256 | 270 | $t = "Remove admin"; | $t = "Remove admin"; |
257 | 271 | $v = 0; | $v = 0; |
... | ... | function user_list($db, $url) | |
268 | 282 | ||
269 | 283 | return $ret; | return $ret; |
270 | 284 | } | } |
285 | |||
286 | /* | ||
287 | * Returns uid by token, if not expired | ||
288 | */ | ||
289 | function user_forgot_pass_uid($db, $token) | ||
290 | { | ||
291 | $ret = array(); | ||
292 | $ret['ok'] = 0; | ||
293 | $ret['uid'] = 0; | ||
294 | |||
295 | xlog("user_forgot_pass_uid: token=$token"); | ||
296 | |||
297 | $now = time(); | ||
298 | $e_token = sql_escape($db, $token); | ||
299 | |||
300 | $sql = "SELECT uid FROM forgot_pass" | ||
301 | . " WHERE token = '$e_token'" | ||
302 | . " AND expire > $now"; | ||
303 | $res = sql_query($db, $sql); | ||
304 | if ($res === FALSE) | ||
305 | return $ret; | ||
306 | |||
307 | $ret['ok'] = 1; | ||
308 | |||
309 | $row = sql_fetch_array($res); | ||
310 | sql_free_result($res); | ||
311 | if (!isset($row['uid'])) | ||
312 | return $ret; | ||
313 | |||
314 | $ret['uid'] = $row['uid']; | ||
315 | |||
316 | return $ret; | ||
317 | } | ||
318 | |||
319 | /* | ||
320 | * Reset password function (send mail) | ||
321 | */ | ||
322 | function user_forgot_pass_mail($db, $email) | ||
323 | { | ||
324 | xlog("user_forgot_pass_mail: email=$email"); | ||
325 | |||
326 | $expire = time() + 24 * 3600; | ||
327 | $token = gg_id(40); | ||
328 | |||
329 | $r = user_info($db, 0, "", $email); | ||
330 | if ($r['ok'] == 0) | ||
331 | return FALSE; | ||
332 | if ($r['exists'] == 0) | ||
333 | return FALSE; | ||
334 | $uid = $r['uid']; | ||
335 | |||
336 | // store token in database | ||
337 | $sql = "INSERT INTO forgot_pass (token, uid, expire)" | ||
338 | . " VALUES ('$token', $uid, $expire)"; | ||
339 | $res = sql_query($db, $sql); | ||
340 | if ($res === FALSE) { | ||
341 | gg_user_set_error("Cannot query!"); | ||
342 | return FALSE; | ||
343 | } | ||
344 | sql_free_result($res); | ||
345 | |||
346 | if (!mail($email, "Forgot password", | ||
347 | "Hello!\nIf you want to reset the password, follow:\n" | ||
348 | . "http://" . $_SERVER['SERVER_NAME'] . "/" . $_SERVER['PHP_SELF'] . "?op=6&token=$token")) { | ||
349 | gg_user_set_error("Cannot send mail!"); | ||
350 | return FALSE; | ||
351 | } | ||
352 | |||
353 | return TRUE; | ||
354 | } | ||
355 | |||
356 | /* | ||
357 | * After reseting the pass, we have to destroy all 'reset pass' requests | ||
358 | */ | ||
359 | function user_forgot_pass_destroy($db, $uid) | ||
360 | { | ||
361 | xlog("user_forgot_pass_destroy: token=$token"); | ||
362 | |||
363 | $sql = "DELETE FROM forgot_pass WHERE uid = $uid"; | ||
364 | $res = sql_query($db, $sql); | ||
365 | if ($res === FALSE) { | ||
366 | gg_user_set_error("Cannot query!"); | ||
367 | return FALSE; | ||
368 | } | ||
369 | sql_free_result($res); | ||
370 | |||
371 | return TRUE; | ||
372 | } | ||
373 | |||
374 | function user_set_pass($db, $uid, $pass) | ||
375 | { | ||
376 | xlog("user_set_pass..."); | ||
377 | |||
378 | $e_salt = gg_id(40); | ||
379 | $e_sha1pass = sha1($e_salt . "===" . $pass); | ||
380 | |||
381 | $sql = "UPDATE users SET" | ||
382 | ." salt = '$e_salt'" | ||
383 | . ", pass = '$e_sha1pass'" | ||
384 | . " WHERE uid = " . $uid; | ||
385 | $res = sql_query($db, $sql); | ||
386 | if ($res === FALSE) | ||
387 | return FALSE; | ||
388 | sql_free_result($res); | ||
389 | |||
390 | return TRUE; | ||
391 | } | ||
392 | |||
271 | 393 | ?> | ?> |
File inc/user/forgot.form.php added (mode: 100644) (index 0000000..c4b1021) | |||
1 | <?php | ||
2 | |||
3 | $_forgot_form = ""; | ||
4 | |||
5 | if (!empty($error)) | ||
6 | $_forgot_form .= "<font color=red>$error</font><br />\n"; | ||
7 | |||
8 | $_forgot_form .= ' | ||
9 | <form type="post" action="' . $_SERVER['PHP_SELF'] . '"> | ||
10 | <input type="hidden" name="op" value="' . $op . '"> | ||
11 | <input type="hidden" name="token" value="' . $_REQUEST['token'] . '"> | ||
12 | <input type="hidden" name="doit" value="1"> | ||
13 | |||
14 | <table> | ||
15 | <tr> | ||
16 | <td>New password:</td> | ||
17 | <td> | ||
18 | <input type="password" name="pass1" value=""><br /> | ||
19 | </td> | ||
20 | </tr> | ||
21 | |||
22 | <tr> | ||
23 | <td>New password (retype):</td> | ||
24 | <td> | ||
25 | <input type="password" name="pass2" value=""><br /> | ||
26 | </td> | ||
27 | </tr> | ||
28 | |||
29 | <tr> | ||
30 | <td colspan="2"><input type="submit" value="Change password"></td> | ||
31 | </tr> | ||
32 | |||
33 | </table> | ||
34 | </form> | ||
35 | '; | ||
36 | |||
37 | ?> |
File inc/user/forgot.php added (mode: 100644) (index 0000000..7138b70) | |||
1 | <?php | ||
2 | xlog("/inc/user/forgot.php"); | ||
3 | |||
4 | $token = @$_REQUEST['token']; | ||
5 | $pass1 = @$_REQUEST['pass1']; | ||
6 | $pass2 = @$_REQUEST['pass2']; | ||
7 | |||
8 | $_forgot = "<br />\n"; | ||
9 | |||
10 | $_hide_form = 0; | ||
11 | |||
12 | if ($doit == 1) { | ||
13 | $error = ""; | ||
14 | if (strcmp($pass1, $pass2) != 0) { | ||
15 | $error .= "Passwords mismatch."; | ||
16 | } else { | ||
17 | $r = user_forgot_pass_uid($db, $token); | ||
18 | if ($r['ok'] != 1) { | ||
19 | $error .= "Internal error, try again later."; | ||
20 | } else if ($r['uid'] == 0) { | ||
21 | $error .= "Invalid (or expired) reset pass URL!"; | ||
22 | } else { | ||
23 | if (user_set_pass($db, $r['uid'], $pass1)) { | ||
24 | user_forgot_pass_destroy($db, $r['uid']); | ||
25 | $_forgot .= "OK!"; | ||
26 | $_hide_form = 1; | ||
27 | } else { | ||
28 | $error .= "Internal error - try later!"; | ||
29 | } | ||
30 | } | ||
31 | } | ||
32 | } | ||
33 | |||
34 | if ($_hide_form == 0) { | ||
35 | include($INC . "/user/forgot.form.php"); | ||
36 | $_forgot .= $_forgot_form; | ||
37 | } | ||
38 | |||
39 | ?> |
File inc/user/forgot_mail.php added (mode: 100644) (index 0000000..597f7f1) | |||
1 | <?php | ||
2 | xlog("/inc/user/forgot_mail.php"); | ||
3 | |||
4 | $email = @$_REQUEST['email']; | ||
5 | |||
6 | $_forgot = "<br />\n"; | ||
7 | |||
8 | if ($doit == 1) { | ||
9 | $r = user_forgot_pass_mail($db, $email); | ||
10 | if ($r === FALSE) | ||
11 | $_forgot .= "Cannot send mail!"; | ||
12 | else | ||
13 | $_forgot .= "E-mail was sent!"; | ||
14 | } | ||
15 | |||
16 | ?> |
File inc/xlog.inc.php changed (mode: 100644) (index b073370..c7b2caa) | |||
1 | 1 | <?php | <?php |
2 | require_once($INC . "/util.inc.php"); | ||
2 | 3 | ||
3 | 4 | $_xlog_file = "/tmp/gg.log"; | $_xlog_file = "/tmp/gg.log"; |
4 | 5 | $_xlog_fd = FALSE; | $_xlog_fd = FALSE; |
6 | $_xlog_sid = gg_id(6); | ||
5 | 7 | ||
6 | 8 | function xlog_set_file($file) | function xlog_set_file($file) |
7 | 9 | { | { |
... | ... | function xlog($str) | |
14 | 16 | { | { |
15 | 17 | global $_xlog_file; | global $_xlog_file; |
16 | 18 | global $_xlog_fd; | global $_xlog_fd; |
19 | global $_xlog_sid; | ||
17 | 20 | ||
18 | 21 | if ($_xlog_fd === FALSE) { | if ($_xlog_fd === FALSE) { |
19 | 22 | $_xlog_fd = @fopen($_xlog_file, "a+"); | $_xlog_fd = @fopen($_xlog_file, "a+"); |
... | ... | function xlog($str) | |
24 | 27 | $buf = date("Y-m-d H:i:s"); | $buf = date("Y-m-d H:i:s"); |
25 | 28 | if (!empty($_SERVER['REMOTE_ADDR'])) | if (!empty($_SERVER['REMOTE_ADDR'])) |
26 | 29 | $buf .= " " . $_SERVER['REMOTE_ADDR']; | $buf .= " " . $_SERVER['REMOTE_ADDR']; |
27 | $buf .= " " . $str . "\n"; | ||
30 | $buf .= " " . $_xlog_sid . " " . $str . "\n"; | ||
28 | 31 | ||
29 | 32 | fwrite($_xlog_fd, $buf); | fwrite($_xlog_fd, $buf); |
30 | 33 | } | } |
File root/index.php changed (mode: 100644) (index 0398183..c7d2be5) | |||
1 | 1 | <?php | <?php |
2 | 2 | error_reporting(E_ALL); | error_reporting(E_ALL); |
3 | 3 | ||
4 | $_s = microtime(TRUE); | ||
5 | |||
4 | 6 | $INC = dirname(__FILE__) . "/../inc"; | $INC = dirname(__FILE__) . "/../inc"; |
5 | 7 | $ROOT = dirname(__FILE__); | $ROOT = dirname(__FILE__); |
6 | 8 | ||
... | ... | if ($db === FALSE) | |
49 | 51 | ||
50 | 52 | // deal with login | // deal with login |
51 | 53 | $uid = user_login($db, $sid, $gg_ui); | $uid = user_login($db, $sid, $gg_ui); |
52 | if (($op == 1) && ($doit == 1) && ($uid == 0)) | ||
54 | if (($op == 1) && ($doit == 1) && ($uid > 0)) | ||
53 | 55 | $op = 0; | $op = 0; |
54 | 56 | ||
55 | 57 | // deal with logout | // deal with logout |
... | ... | if ($op == 9) { | |
59 | 61 | $gg_ui = FALSE; | $gg_ui = FALSE; |
60 | 62 | } | } |
61 | 63 | ||
64 | // auto-login user by forgot-pass token | ||
65 | if ($op == 6) { | ||
66 | // TODO | ||
67 | } | ||
68 | |||
62 | 69 | // menu | // menu |
63 | 70 | $url = $_SERVER['PHP_SELF'] . "?a=1"; | $url = $_SERVER['PHP_SELF'] . "?a=1"; |
64 | 71 | $menu = ""; | $menu = ""; |
65 | $u = "Not logged in"; | ||
66 | if (isset($gg_ui['user'])) | ||
67 | $u = $gg_ui['user']; | ||
68 | $menu .= "[$u]<br />\n"; | ||
69 | 72 | $menu .= "[<a href=\"$url&op=1\">Login</a>]"; | $menu .= "[<a href=\"$url&op=1\">Login</a>]"; |
70 | $menu .= " [<a href=\"$url&op=2\">Repositories</a>]"; | ||
71 | if ($gg_ui['is_admin'] == 1) | ||
72 | $menu .= " [<a href=\"$url&op=3\">Admin</a>]"; | ||
73 | $menu .= " [<a href=\"$url&op=9\">Logout</a>]"; | ||
73 | if (isset($gg_ui['user'])) { | ||
74 | $menu .= " [<a href=\"$url&op=2\">Repositories</a>]"; | ||
75 | 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 | } | ||
80 | $menu .= "<br />\n"; | ||
74 | 81 | ||
75 | 82 | ||
76 | 83 | $body = ""; | $body = ""; |
... | ... | case 3: | |
89 | 96 | include($INC . "/admin/admin.php"); | include($INC . "/admin/admin.php"); |
90 | 97 | $body .= $_admin; | $body .= $_admin; |
91 | 98 | break; | break; |
99 | |||
100 | case 6: // forgot pass link | ||
101 | include($INC . "/user/forgot.php"); | ||
102 | $body .= $_forgot; | ||
103 | break; | ||
104 | |||
105 | case 7: // forgot pass - send mail | ||
106 | include($INC . "/user/forgot_mail.php"); | ||
107 | $body .= $_forgot; | ||
108 | break; | ||
92 | 109 | } | } |
93 | 110 | ||
94 | 111 | $body .= "</body>"; | $body .= "</body>"; |
95 | 112 | $body .= "</html>\n"; | $body .= "</html>\n"; |
96 | 113 | ||
97 | echo $head . $menu . "<br />\n" . $body; | ||
114 | echo $head . $menu . $body; | ||
98 | 115 | ||
99 | xlog("Done!"); | ||
116 | $_diff = sprintf("%u", (microtime(TRUE) - $_s) * 1000); | ||
117 | xlog("Done in $_diff ms."); | ||
100 | 118 | ?> | ?> |
File samples/cron added (mode: 100644) (index 0000000..028fe23) | |||
1 | * * * * * gg php /BIG1T/sync1/Dev/gg/scripts/cron.php |
File samples/gg added (mode: 100644) (index 0000000..fc7d98b) | |||
1 | # default: off | ||
2 | # description: The git dæmon allows git repositories to be exported using \ | ||
3 | # the git:// protocol. | ||
4 | |||
5 | service git | ||
6 | { | ||
7 | flags = IPv6 | ||
8 | disable = no | ||
9 | socket_type = stream | ||
10 | wait = no | ||
11 | user = nobody | ||
12 | server = /usr/bin/php | ||
13 | server_args = /BIG1T/sync1/Dev/gg/scripts/ssh.php | ||
14 | log_on_failure += USERID | ||
15 | } |
File scripts/cron.php added (mode: 100644) (index 0000000..1422a27) | |||
1 | <?php | ||
2 | // This is called by cron | ||
3 | error_reporting(E_ALL); | ||
4 | |||
5 | $now = time(); | ||
6 | |||
7 | require_once("/etc/gg/config.php"); | ||
8 | |||
9 | $INC = dirname(__FILE__) . "/../inc"; | ||
10 | require_once($INC . "/xlog.inc.php"); | ||
11 | require_once($INC . "/db.inc.php"); | ||
12 | require_once($INC . "/repo.inc.php"); | ||
13 | |||
14 | xlog_set_file("/tmp/gg_cron.log"); | ||
15 | |||
16 | $sql_debug = $gg_db_debug; | ||
17 | |||
18 | $db = sql_open($gg_db); | ||
19 | if ($db === FALSE) { | ||
20 | xlog("Cannot connect to database!"); | ||
21 | // TODO: inform admin - already by e-mail? | ||
22 | exit(1); | ||
23 | } | ||
24 | |||
25 | if (date("H") == 0) { | ||
26 | xlog("Compute repository sizes if dirty..."); | ||
27 | // delete 'dirty' files | ||
28 | $sql = "SELECT * FROM repos"; | ||
29 | $res = sql_query($db, $sql); | ||
30 | if ($res === FALSE) { | ||
31 | 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); | ||
46 | } | ||
47 | } | ||
48 | sql_free_result($res); | ||
49 | } | ||
50 | |||
51 | xlog("Update user quota..."); | ||
52 | |||
53 | // Send notifications | ||
54 | |||
55 | // Clean old forgot_pass entries | ||
56 | if (date("H") == 0) { | ||
57 | xlog("Clean old forget_pass entries..."); | ||
58 | $sql = "DELETE FROM forgot_pass WHERE expire < $now"; | ||
59 | $res = sql_query($db, $sql); | ||
60 | sql_free_result($res); | ||
61 | } | ||
62 | |||
63 | // this has to be the last thing that touches the database | ||
64 | if (date("H") == 0) { | ||
65 | xlog("Run VACUUM on database..."); | ||
66 | $sql = "VACUUM"; | ||
67 | $res = sql_query($db, $sql); | ||
68 | sql_free_result($res); | ||
69 | |||
70 | xlog("Run ANALYZE on database..."); | ||
71 | $sql = "ANALYZE"; | ||
72 | $res = sql_query($db, $sql); | ||
73 | sql_free_result($res); | ||
74 | } | ||
75 | |||
76 | xlog("Done!"); | ||
77 | ?> |
File scripts/ssh.php changed (mode: 100644) (index 757a20a..bb3009e) | |||
1 | 1 | <?php | <?php |
2 | // This is called by a remote client that does push or fetch | ||
2 | 3 | error_reporting(E_ALL); | error_reporting(E_ALL); |
3 | 4 | ||
4 | 5 | $_start = microtime(TRUE); | $_start = microtime(TRUE); |
... | ... | $_start = microtime(TRUE); | |
6 | 7 | require_once("/etc/gg/config.php"); | require_once("/etc/gg/config.php"); |
7 | 8 | ||
8 | 9 | $INC = dirname(__FILE__) . "/../inc"; | $INC = dirname(__FILE__) . "/../inc"; |
10 | require_once($INC . "/util.inc.php"); | ||
9 | 11 | require_once($INC . "/xlog.inc.php"); | require_once($INC . "/xlog.inc.php"); |
10 | 12 | require_once($INC . "/db.inc.php"); | require_once($INC . "/db.inc.php"); |
11 | 13 | require_once($INC . "/repo.inc.php"); | require_once($INC . "/repo.inc.php"); |
... | ... | $sql_debug = $gg_db_debug; | |
14 | 16 | ||
15 | 17 | function fatal($str) | function fatal($str) |
16 | 18 | { | { |
17 | xlog($str); | ||
18 | fwrite(STDERR, "FATAL ERROR: " . $str . "\n"); | ||
19 | global $access_type; | ||
20 | |||
21 | xlog("Sending error: " . $str); | ||
22 | $str2 = "FATAL ERROR: " . $str . "\n"; | ||
23 | if ($access_type == 2) { //git | ||
24 | $str3 = "\n" . $str2; | ||
25 | $len = strlen($str3) + 4; | ||
26 | $str4 = sprintf("%04x", $len) . $str3; | ||
27 | fwrite(STDERR, $str4); | ||
28 | } else { // ssh | ||
29 | fwrite(STDERR, $str2); | ||
30 | } | ||
19 | 31 | exit(1); | exit(1); |
20 | 32 | } | } |
21 | 33 | ||
22 | 34 | xlog("Start..."); | xlog("Start..."); |
35 | //xlog("_SERVER: " . print_r($_SERVER, TRUE)); | ||
23 | 36 | ||
24 | 37 | umask(0022); | umask(0022); |
25 | 38 | ||
26 | $ssh_conn = @$_SERVER['SSH_CONNECTION']; | ||
27 | xlog("SSH_CONNECTION: $ssh_conn."); | ||
39 | if (isset($_SERVER['SSH_CONNECTION'])) { | ||
40 | xlog("SSH connection: " . @$_SERVER['SSH_CONNECTION']); | ||
41 | $access_type = 1; | ||
28 | 42 | ||
29 | // first parameter must be uid of the user | ||
30 | $uid = @$_SERVER['argv'][1]; | ||
31 | if (empty($uid)) | ||
32 | fatal("uid not provided!"); | ||
33 | xlog("uid is $uid."); | ||
43 | // we do not have host info | ||
44 | $host = ""; | ||
34 | 45 | ||
35 | $cmd = trim(@$_SERVER['SSH_ORIGINAL_COMMAND']); | ||
36 | if (empty($cmd)) | ||
37 | fatal("No SSH_ORIGINAL_COMMAND provided!"); | ||
38 | xlog("SSH_ORIGINAL_COMMAND is [$cmd]."); | ||
46 | // first parameter must be uid of the user | ||
47 | $uid = @$_SERVER['argv'][1]; | ||
48 | if (empty($uid)) | ||
49 | fatal("uid not provided!"); | ||
50 | xlog("\tuid is $uid."); | ||
39 | 51 | ||
40 | // extract command | ||
41 | if (strncmp($cmd, "git-upload-pack", 15) == 0) { | ||
42 | $op = "git-upload-pack"; | ||
52 | $cmd_repo = trim(@$_SERVER['SSH_ORIGINAL_COMMAND']); | ||
53 | if (empty($cmd_repo)) | ||
54 | fatal("No SSH_ORIGINAL_COMMAND provided!"); | ||
55 | } else { | ||
56 | xlog("git-daemon connection..."); | ||
57 | $access_type = 2; | ||
58 | |||
59 | // we have no client info | ||
60 | $uid = 0; | ||
61 | |||
62 | $f = @fopen("php://stdin", "r"); | ||
63 | if ($f === FALSE) | ||
64 | fatal("\tCannot open stdin!"); | ||
65 | $line = @fread($f, 8000); | ||
66 | if ($line === FALSE) | ||
67 | fatal("\tCannot read!"); | ||
68 | fclose($f); | ||
69 | $line_len = strlen($line); | ||
70 | |||
71 | if ($line_len < 4) | ||
72 | fatal("\tLine is too short!"); | ||
73 | $len = @hexdec(substr($line, 0, 4)); | ||
74 | if ($line_len < $len) | ||
75 | fatal("Too less data ($line_len/$len) received!"); | ||
76 | |||
77 | // parse something like: 002bgit-upload-pack /aa.git.host=localhost | ||
78 | $line = substr($line, 4); | ||
79 | $v = explode("\0", $line); | ||
80 | $cmd_repo = trim($v[0]); | ||
81 | $host = trim(substr($v[1], 5)); | ||
82 | } | ||
83 | |||
84 | // extract command and compute permissions | ||
85 | if (strncmp($cmd_repo, "git-upload-pack", 15) == 0) { | ||
86 | $cmd = "git-upload-pack"; | ||
43 | 87 | $perms = "R"; | $perms = "R"; |
44 | } else if (strncmp($cmd, "git-receive-pack", 16) == 0) { | ||
45 | $op = "git-receive-pack"; | ||
88 | } else if (strncmp($cmd_repo, "git-receive-pack", 16) == 0) { | ||
89 | $cmd = "git-receive-pack"; | ||
46 | 90 | $perms = "W"; | $perms = "W"; |
47 | 91 | } else { | } else { |
48 | 92 | fatal("Unknown command!"); | fatal("Unknown command!"); |
49 | 93 | } | } |
50 | xlog("real operation is $op, perms is [$perms]."); | ||
51 | 94 | ||
52 | 95 | // extract repository name | // extract repository name |
53 | $repo = substr($cmd, strlen($op)); | ||
96 | $repo = substr($cmd_repo, strlen($cmd)); | ||
54 | 97 | $repo = trim($repo, "' "); | $repo = trim($repo, "' "); |
98 | $repo = ltrim($repo, "/"); | ||
99 | $repo = preg_replace('/\.git$/' , '', $repo); | ||
100 | |||
101 | xlog("host=[$host] cmd=[$cmd] repo=[$repo] perms=[$perms]."); | ||
102 | |||
103 | // validity/security checks | ||
55 | 104 | if (empty($repo)) | if (empty($repo)) |
56 | 105 | fatal("Repo is invalid!"); | fatal("Repo is invalid!"); |
57 | // security checks | ||
58 | 106 | if (preg_match('/\.\./', $repo)) | if (preg_match('/\.\./', $repo)) |
59 | 107 | fatal("Repo must not contain [..]!"); | fatal("Repo must not contain [..]!"); |
60 | xlog("repo is [$repo]."); | ||
61 | |||
62 | // Check if repository exists | ||
63 | $path = $gg_base_repo . "/" . $repo; | ||
64 | if (!file_exists($path)) | ||
65 | fatal("Cannot find repo $path!"); | ||
66 | xlog("path is [$path]."); | ||
67 | |||
68 | // check access - uid is allowed to access this repo? | ||
69 | $repo_id = sprintf("%u", @file_get_contents($path . "/gg/repo_id")); | ||
70 | if ($repo_id == 0) | ||
71 | fatal("Invalid repo!"); | ||
72 | xlog("repo_id is [$repo_id]"); | ||
108 | if (preg_match('/\//', $repo)) | ||
109 | fatal("Repo must not contain [/]!"); | ||
73 | 110 | ||
74 | 111 | $db = sql_open($gg_db); | $db = sql_open($gg_db); |
75 | 112 | if ($db === FALSE) | if ($db === FALSE) |
76 | 113 | fatal("Internal error (db)!"); | fatal("Internal error (db)!"); |
77 | 114 | ||
78 | if (!repo_allow($db, $repo_id, $uid, $perms)) | ||
79 | fatal("You do not have access to this repository!"); | ||
115 | // load info about the repository | ||
116 | $ri = repo_info($db, 0, $repo); | ||
117 | if ($ri['ok'] != 1) | ||
118 | fatal("Temporary error!"); | ||
119 | if ($ri['exists'] != 1) | ||
120 | fatal("Repo does not exists!"); | ||
121 | |||
122 | if (!repo_allow($db, $ri, $uid, $perms)) | ||
123 | fatal("You do not have this type of access to this repository!"); | ||
124 | |||
125 | // TODO: limit per connection | ||
80 | 126 | ||
81 | $run = "git-shell -c \"" . $op . " '" . escapeshellcmd($path) . "'\""; | ||
127 | // TODO: limit time and/or cpu | ||
128 | |||
129 | $repo_base = repo_id2base($ri['repo_id']); | ||
130 | $repo_path = $repo_base . "/" . $repo . ".git"; | ||
131 | xlog("repo_path=$repo_path."); | ||
132 | |||
133 | $run = "git-shell -c \"" . $cmd . " '" . escapeshellcmd($repo_path) . "'\""; | ||
82 | 134 | xlog("Running [$run]..."); | xlog("Running [$run]..."); |
83 | 135 | passthru($run, $ret); | passthru($run, $ret); |
84 | 136 | xlog("[$run] returned $ret."); | xlog("[$run] returned $ret."); |
85 | 137 | ||
86 | 138 | $diff = sprintf("%u", (microtime(TRUE) - $_start) * 1000); | $diff = sprintf("%u", (microtime(TRUE) - $_start) * 1000); |
87 | 139 | xlog("Took " . $diff . "ms."); | xlog("Took " . $diff . "ms."); |
140 | |||
141 | @file_put_contents($repo_path . "/gg/last_access", | ||
142 | "repo: " . $repo . " ($repo_path)" | ||
143 | . "\nat: " . sprintf("%u", $_start) | ||
144 | . "\nuid: " . $uid | ||
145 | . "\ncmd: $cmd" | ||
146 | . "\nperms: $perms" | ||
147 | . "\nTook: " . $diff . "ms"); | ||
148 | |||
149 | // Mark repository dirty for disk statistics and other stuff | ||
150 | if (strcmp($cmd, "git-receive-pack") == 0) | ||
151 | @file_put_contents($gg_path . "/dirty", ""); | ||
88 | 152 | ?> | ?> |
File tests/Makefile changed (mode: 100644) (index 196fb8f..7771f05) | |||
1 | 1 | .PHONY: test | .PHONY: test |
2 | 2 | test: | test: |
3 | php util.php | ||
3 | 4 | php db.php | php db.php |
4 | 5 | php keys.php | php keys.php |
File tests/user.php added (mode: 100644) (index 0000000..7e5f149) | |||
1 | <?php | ||
2 | $INC = "../inc"; | ||
3 | require_once($INC . "/user.inc.php"); | ||
4 | |||
5 | @unlink("user.sqlite"); | ||
6 | |||
7 | $db = sql_open("sqlite:user.sqlite"); | ||
8 | if ($db === FALSE) { | ||
9 | echo "Cannot create a database (" . sql_error() . ")!"; | ||
10 | exit(1); | ||
11 | } | ||
12 | |||
13 | $sql = "CREATE TABLE users (email TEXT PRIMARY KEY, forgot_pass_token TEXT, forgot_pass_expire INTEGER)"; | ||
14 | $res = sql_query($db, $sql); | ||
15 | if ($res === FALSE) { | ||
16 | echo "Cannot create users table!"; | ||
17 | exit(1); | ||
18 | } | ||
19 | |||
20 | $sql = "INSERT INTO users VALUES ('gg@localhost', '', 0)"; | ||
21 | $res = sql_query($db, $sql); | ||
22 | if ($res === FALSE) { | ||
23 | echo "Cannot insert a user!"; | ||
24 | exit(1); | ||
25 | } | ||
26 | |||
27 | $v = user_forgot_pass($db, "gg@localhost"); | ||
28 | if ($v === FALSE) { | ||
29 | echo "Error: " . user_error() . "!\n"; | ||
30 | exit(1); | ||
31 | } | ||
32 | |||
33 | @unlink("user.sqlite"); | ||
34 | ?> |
File tests/util.php added (mode: 100644) (index 0000000..5b96512) | |||
1 | <?php | ||
2 | $INC = "../inc"; | ||
3 | require_once($INC . "/util.inc.php"); | ||
4 | |||
5 | $id = gg_id(16); | ||
6 | if (strlen($id) != 16) { | ||
7 | echo "Cannot generate an id!\n"; | ||
8 | exit(1); | ||
9 | } | ||
10 | ?> |