| 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 | ?> | ||