xaizek / rocketgit (License: AGPLv3+) (since 2018-12-09)
Light and fast Git hosting solution suitable to serve both as a hub or as a personal code storage with its tickets, pull requests, API and much more.
Commit 422d74f1cd4133e73ceb3edbb7a7da6d48c102f2

webhooks fixes
Author: Catalin(ux) M. BOIE
Author date (UTC): 2015-11-17 15:53
Committer name: Catalin(ux) M. BOIE
Committer date (UTC): 2015-11-17 15:53
Parent(s): c8ac332f2ffda6149048dd17eaef8ff2f2920650
Signing key:
Tree: 5acd5bace26bdda4a62ab164f4255649af4b3212
File Lines added Lines deleted
Compare.txt 24 21
README 1 0
TODO 33 0
TODO.perf 5 0
TODO.vm 2 1
inc/bug.inc.php 8 6
inc/cache.inc.php 50 7
inc/events.inc.php 11 32
inc/git.inc.php 15 9
inc/mr.inc.php 26 43
inc/sql.inc.php 4 5
inc/struct.inc.php 8 2
inc/user.inc.php 3 3
inc/user/repo-page.php 10 10
inc/util.inc.php 6 0
inc/webhooks.inc.php 49 21
root/themes/default/mail/user/key/del.body.txt 1 1
root/themes/default/mail/user/key/new.body.txt 1 1
root/themes/default/mail/user/repo/del.body.txt 1 1
root/themes/default/mail/user/repo/new.body.txt 1 1
root/themes/default/mail/user/repo/update.body.txt 1 1
root/themes/default/repo/mr/list/header.html 2 0
root/themes/default/repo/mr/list/line.html 2 0
root/themes/default/user/home.html 1 1
root/themes/default/user/settings/wh/add_edit.html 10 0
root/themes/default/user/settings/wh/hints.html 10 1
samples/config.php 1 1
scripts/events.php 107 41
scripts/remote.php 8 7
selinux/rocketgit.te 7 3
tests/.gitignore 1 0
tests/Makefile 2 1
tests/ca.sh 4 2
tests/cache.php 12 2
tests/helpers.inc.php 35 7
tests/http.inc.php 23 2
tests/pr_anon.php 71 2
tests/repo.php 1 0
tests/ssh.php 1 0
tests/wh-stunnel.conf 3 3
tests/wh.php 76 35
File Compare.txt changed (mode: 100644) (index f73470f..22ffae5)
1 RocketGit Gitlab GitHub Gitorious unfuddle.com gitolite
1 RocketGit Gitlab GitHub Gitorious unfuddle.com gitolite
2 2
3 License Affero GPLv3 OpenCore? Proprietary ?open ? ?
3 License Affero GPLv3 OpenCore? Proprietary ?open ? ?
4 4
5 5 [Features] [Features]
6 Easy installation Yes No Yes? No! ? Yes
7 SELinux friendly Yes ? ? ? ? ?
8 Distro friendly Yes No No No ? Yes
9 Bug tracker Yes Yes Yes No ? No
10 CLI commands (SSH) Yes ? ? ? ? ?
11 API HTTP(S) ? Yes ? ? ?
12 Anonymous push Yes ? No ? ? ?
13 Languages 1 ? ? ? ? ?
14 IPv6 Yes ? ? ? ? ?
15 Submodules ? ? ? ? ? ?
16 Usable with lynx ? ? ? ? ? ?
17 2fa Yes ? yes 1) ? ? ?
18
6 Easy installation Yes No Yes? No! ? Yes
7 SELinux friendly Yes ? ? ? ? ?
8 Distro friendly Yes No (see 2) No (see 2) No ? Yes
9 Bug tracker Yes Yes Yes No ? No
10 CLI commands (SSH) Yes ? ? ? ? ?
11 API HTTP(S) ? Yes ? ? ?
12 Anonymous push Yes ? No ? ? ?
13 Languages 1 ? ? ? ? ?
14 IPv6 Yes ? ? ? ? ?
15 Submodules ? ? ? ? ? ?
16 Usable with lynx ? ? ? ? ? ?
17 2fa Yes ? Yes (see 1) ? ? ?
18 Web Hooks Yes Yes Yes ? ? No
19 Web Hooks - client certs Yes No No ? ? n/a
20 Web Hooks - auth server (CA cert) Yes No No ? ? n/a
19 21
20 22 [Rights] [Rights]
21 Path control Yes ? ? ? ? ?
22 Refs control Yes ? ? ? ? ?
23 IP control Yes ? ? ? ? ?
23 Path control Yes ? ? ? ? ?
24 Refs control Yes ? ? ? ? ?
25 IP control Yes ? ? ? ? ?
24 26
25 27
26 28 [Details] [Details]
27 Language PHP Ruby+Perl Ruby Ruby ? Perl
28 Cache custom Redis ? ? ? No
29 Language PHP Ruby+Perl Ruby Ruby ? Perl
30 Cache Custom Redis ? ? ? No
29 31
30 32
31 1) Seems is not really secure.
33 1) Seems is not really secure: if key is leaking, the attacker can push.
34 2) They have a distro inside a distro; so, upgrading distro does not update the software.
File README changed (mode: 100644) (index 4fe4e0b..6236b45)
28 28 . Prepare SELinux . Prepare SELinux
29 29 # setsebool -P \ # setsebool -P \
30 30 httpd_can_network_connect_db=on \ httpd_can_network_connect_db=on \
31 httpd_can_network_connect=on \
31 32 httpd_can_sendmail=on httpd_can_sendmail=on
32 33
33 34 . Edit /etc/rocketgit/config.php . Edit /etc/rocketgit/config.php
File TODO changed (mode: 100644) (index d80e02a..573f6ff)
2 2 [ ] [ ]
3 3
4 4 == BEFORE NEXT RELEASE == == BEFORE NEXT RELEASE ==
5 [ ] wh: operation ('event') is not present in the post request!
6 [ ] Alert admin on any problems (for example if authorized_keys is not
7 updated)?
8 [ ] An attacker can use a webhook (same url) and same repo name
9 and, because of ssl caching, will be able to post the notification
10 to the victim's server. In C I will be able to use
11 CURLOPT_SSL_SESSIONID_CACHE = 0.
12 [ ] Add a signing key for webhooks to compute a HMAC.
13 [ ] events: add more "threads", so one webhook (for example)
14 will not block all request. Use a pool with a configurable
15 number of workers.
16 [ ] tests: if rg_debug == 1 and a test fails, do not retry it!
17 Maybe also delete it from 'events' table?
18 [ ] pr: Allow to add a pr even if the repo is not hosted on rocketgit.
19 For example, somebody can create a pull request specifying
20 an external url and src/dst branch!
21 [ ] pr: if a ref is a tag/branch, show them nice.
22 [ ] hint: add a custom hint whenone pull request is loaded.
23 Custom = exactly the instructions to pull that request.
24 [ ] unit test: check if the log is correctly generated after a push.
25 I suspect some rights problems.
26 [ ] pr: I should add also the user who made the pull request
27 or anonymous. Also, IP must be shown also to the owner.
28 [ ] After some releases, remove any trace of q_merge_requests!
29 [ ] pr: seems now I go through /var/lib/rocketgit/q_merge_requests
30 We should use events! And then get rid of this dir.
31 What happends now?
32 Seems I need to replace rg_mr_queue_add with rg_mr_create.
33 Cron loads merge requests from files and calls mr_queue_add.
34 [ ] Add avatars for notes and bugs.
35 [ ] Allow an admin to run extra hooks by adding them info
36 /var/lib/rocketgit/extra_hooks/{update,post-receive,...}/
5 37 [ ] check 'man git-receive-pack' for gpg (about signed pushes). [ ] check 'man git-receive-pack' for gpg (about signed pushes).
6 38 [ ] I still have to investigate if I can send git messages. [ ] I still have to investigate if I can send git messages.
39 Not in hooks, but at start. I want to send the welcome message.
7 40 [ ] After pushing using anon-push feature, give to the user a link to be able [ ] After pushing using anon-push feature, give to the user a link to be able
8 41 to add a proper subject/body. Else, use the first commit for this. to add a proper subject/body. Else, use the first commit for this.
9 42 Or, join all commits messages. I think is better. Or, join all commits messages. I think is better.
File TODO.perf added (mode: 100644) (index 0000000..a2863c6)
1 == This is the TODO for performance stuff ==
2 [ ] Replace 'git cat-file' with open/read/close.
3 [ ] Instead of executing a script (hooks for example), just connect
4 to a port and spit the needed info.
5 [ ]
File TODO.vm changed (mode: 100644) (index 873fa3e..3b7039a)
1 1 [ ] Check other filesystems: nils2 etc for virtual machine. [ ] Check other filesystems: nils2 etc for virtual machine.
2 [ ] VM: Test if IPv4/IPv6 address is shown at login time.
3 2 [ ] Use guestmount when building VM images? [ ] Use guestmount when building VM images?
4 3 [ ] Add sha1sum of the VM images [ ] Add sha1sum of the VM images
5 4 [ ] Sign vm images. [ ] Sign vm images.
5 [ ] Document that is a i386 image to be able to be run on a lot of machines?
6 [ ]
File inc/bug.inc.php changed (mode: 100644) (index 057fc14..5451e46)
... ... function rg_bug_next_id($db, $repo_id)
254 254 } }
255 255
256 256 $row = rg_sql_fetch_array($res); $row = rg_sql_fetch_array($res);
257 $next_bug_id = $row['next_bug_id'];
258 257 rg_sql_free_result($res); rg_sql_free_result($res);
258 $next_bug_id = $row['next_bug_id'];
259 259
260 $key = 'repo_by_id' . '::' . $repo_id . '::' . 'last_bug_id';
261 rg_cache_set($key, $next_bug_id, RG_SOCKET_NO_WAIT);
260 // We must not do this. Else, repo_info will find the empty
261 // repo info!
262 //$key = 'repo_by_id' . '::' . $repo_id . '::' . 'last_bug_id';
263 //rg_cache_set($key, $next_bug_id, RG_SOCKET_NO_WAIT);
262 264 break; break;
263 265 } }
264 266
 
... ... function rg_bug_note_add($db, $repo_id, $bug_id, $login_uid, $data)
1014 1016 . ", @@ip@@, @@note@@)"; . ", @@ip@@, @@note@@)";
1015 1017 $res = rg_sql_query_params($db, $sql, $params); $res = rg_sql_query_params($db, $sql, $params);
1016 1018 if ($res === FALSE) { if ($res === FALSE) {
1017 rg_bug_set_error("Cannot insert bug note (" . rg_sql_error() . ")");
1019 rg_bug_set_error('cannot insert bug note');
1018 1020 break; break;
1019 1021 } }
1020 1022 rg_sql_free_result($res); rg_sql_free_result($res);
1021 1023
1022 1024 $_ri = rg_repo_info($db, $repo_id, 0, ""); $_ri = rg_repo_info($db, $repo_id, 0, "");
1025 rg_log_ml("DEBUG: _ri: " . print_r($_ri, TRUE));
1023 1026 if ($_ri['exists'] != 1) { if ($_ri['exists'] != 1) {
1024 1027 rg_bug_set_error("cannot lookup repo" rg_bug_set_error("cannot lookup repo"
1025 1028 . " (" . rg_repo_error() . ")"); . " (" . rg_repo_error() . ")");
1026 1029 break; break;
1027 1030 } }
1028 rg_log_ml("_ri: " . print_r($_ri, TRUE));
1029 1031
1030 1032 $_bi = rg_bug_info($db, $repo_id, $bug_id); $_bi = rg_bug_info($db, $repo_id, $bug_id);
1031 1033 if ($_bi['exists'] != 1) { if ($_bi['exists'] != 1) {
 
... ... function rg_bug_note_add($db, $repo_id, $bug_id, $login_uid, $data)
1058 1060 . " ( . rg_event_error() . )"); . " ( . rg_event_error() . )");
1059 1061 break; break;
1060 1062 } }
1061 rg_event_signal_daemon("", 0);
1063 rg_event_signal_daemon('', 0);
1062 1064
1063 1065 $ret = TRUE; $ret = TRUE;
1064 1066 break; break;
File inc/cache.inc.php changed (mode: 100644) (index bab3b1c..4fa2f04)
... ... require_once($INC . "/prof.inc.php");
9 9 // Client side can disable the cache for various reasons (unit testing etc.) // Client side can disable the cache for various reasons (unit testing etc.)
10 10 if (!isset($rg_cache_enable)) if (!isset($rg_cache_enable))
11 11 $rg_cache_enable = TRUE; $rg_cache_enable = TRUE;
12 if (!isset($rg_cache_core_enable))
13 $rg_cache_core_enable = TRUE;
12 14
13 15 // timeout in miliseconds // timeout in miliseconds
14 16 $rg_cache_timeout = 500; $rg_cache_timeout = 500;
 
... ... function rg_cache_error()
45 47 function rg_cache_core_dump() function rg_cache_core_dump()
46 48 { {
47 49 global $rg_cache; global $rg_cache;
50 global $rg_cache_core_enable;
51
52 if (!$rg_cache_core_enable)
53 return '';
48 54
49 55 return "rg_cache:\n" . print_r($rg_cache, TRUE); return "rg_cache:\n" . print_r($rg_cache, TRUE);
50 56 } }
 
... ... function rg_cache_core_dump()
56 62 function rg_cache_core_set($ns_var, $value) function rg_cache_core_set($ns_var, $value)
57 63 { {
58 64 global $rg_cache; global $rg_cache;
65 global $rg_cache_core_enable;
66
67 if (!$rg_cache_core_enable)
68 return;
59 69
60 70 //rg_log_ml("cache_core_set: $ns_var = " . print_r($value, TRUE)); //rg_log_ml("cache_core_set: $ns_var = " . print_r($value, TRUE));
61 71
 
... ... function rg_cache_core_set($ns_var, $value)
78 88 function rg_cache_core_merge($ns_var, $list) function rg_cache_core_merge($ns_var, $list)
79 89 { {
80 90 global $rg_cache; global $rg_cache;
91 global $rg_cache_core_enable;
92
93 if (!$rg_cache_core_enable)
94 return;
81 95
82 96 //rg_log_ml("cache_core_merge: $ns_var = " . print_r($list, TRUE)); //rg_log_ml("cache_core_merge: $ns_var = " . print_r($list, TRUE));
83 97
 
... ... function rg_cache_core_merge($ns_var, $list)
102 116 function rg_cache_core_inc($ns_var) function rg_cache_core_inc($ns_var)
103 117 { {
104 118 global $rg_cache; global $rg_cache;
119 global $rg_cache_core_enable;
120
121 if (!$rg_cache_core_enable)
122 return;
105 123
106 124 $tree = &$rg_cache; $tree = &$rg_cache;
107 125 $t = explode("::", $ns_var); $t = explode("::", $ns_var);
 
... ... function rg_cache_core_inc($ns_var)
129 147 function rg_cache_core_get($ns_var) function rg_cache_core_get($ns_var)
130 148 { {
131 149 global $rg_cache; global $rg_cache;
150 global $rg_cache_core_enable;
151
152 if (!$rg_cache_core_enable)
153 return FALSE;
132 154
133 155 //rg_log("cache_core_get: $ns_var"); //rg_log("cache_core_get: $ns_var");
134 156
 
... ... function rg_cache_core_get($ns_var)
160 182 function rg_cache_core_unset($ns_var) function rg_cache_core_unset($ns_var)
161 183 { {
162 184 global $rg_cache; global $rg_cache;
185 global $rg_cache_core_enable;
186
187 if (!$rg_cache_core_enable)
188 return;
163 189
164 190 $tree = &$rg_cache; $tree = &$rg_cache;
165 191 $t = explode("::", $ns_var); $t = explode("::", $ns_var);
 
... ... function rg_cache_core_unset($ns_var)
188 214 function rg_cache_core_apush($ns_var, $value) function rg_cache_core_apush($ns_var, $value)
189 215 { {
190 216 global $rg_cache; global $rg_cache;
217 global $rg_cache_core_enable;
218
219 if (!$rg_cache_core_enable)
220 return;
191 221
192 222 $tree = &$rg_cache; $tree = &$rg_cache;
193 223 $t = explode("::", $ns_var); $t = explode("::", $ns_var);
 
... ... function rg_cache_core_apush($ns_var, $value)
211 241 function rg_cache_core_apop($ns_var) function rg_cache_core_apop($ns_var)
212 242 { {
213 243 global $rg_cache; global $rg_cache;
244 global $rg_cache_core_enable;
245
246 if (!$rg_cache_core_enable)
247 return FALSE;
214 248
215 249 $tree = &$rg_cache; $tree = &$rg_cache;
216 250 $t = explode("::", $ns_var); $t = explode("::", $ns_var);
 
... ... function rg_cache_core_apop($ns_var)
232 266 } }
233 267
234 268 /* /*
235 * Pop a variable from the begining of a queue
269 * Pops and returns a variable from the begining of a queue
236 270 */ */
237 271 function rg_cache_core_ashift($ns_var) function rg_cache_core_ashift($ns_var)
238 272 { {
239 273 global $rg_cache; global $rg_cache;
274 global $rg_cache_core_enable;
275
276 if (!$rg_cache_core_enable)
277 return FALSE;
240 278
241 279 $tree = &$rg_cache; $tree = &$rg_cache;
242 280 $t = explode("::", $ns_var); $t = explode("::", $ns_var);
 
... ... function rg_cache_core_ashift($ns_var)
263 301 function rg_cache_core_adump($ns_var) function rg_cache_core_adump($ns_var)
264 302 { {
265 303 global $rg_cache; global $rg_cache;
304 global $rg_cache_core_enable;
305
306 if (!$rg_cache_core_enable)
307 return FALSE;
266 308
267 309 $tree = &$rg_cache; $tree = &$rg_cache;
268 310 $t = explode("::", $ns_var); $t = explode("::", $ns_var);
 
... ... function rg_cache_send($cmd, $para, $flags)
328 370
329 371 $a = explode("\n", $ret); $a = explode("\n", $ret);
330 372 foreach ($a as $line) { foreach ($a as $line) {
331 if ($rg_cache_debug)
332 rg_log('Parsing line [' . $line . ']');
373 //if ($rg_cache_debug)
374 // rg_log('Parsing line [' . $line . ']');
333 375
334 376 $t = explode(' ', $line, 3); $t = explode(' ', $line, 3);
335 377 if (!isset($t[1])) if (!isset($t[1]))
336 378 return FALSE; return FALSE;
337 379
380 $status = $t[0];
338 381 $id = intval($t[1]); $id = intval($t[1]);
339 382 if ($id < $rg_cache_count) { if ($id < $rg_cache_count) {
340 383 if ($rg_cache_debug) if ($rg_cache_debug)
341 384 rg_log('DEBUG: id: ' . $id . ' < ' . $rg_cache_count); rg_log('DEBUG: id: ' . $id . ' < ' . $rg_cache_count);
342 385 continue; continue;
343 386 } }
344 if ($rg_cache_debug)
345 rg_log('DEBUG: id: ' . $id . ' == ' . $rg_cache_count);
387 //if ($rg_cache_debug)
388 // rg_log('DEBUG: id: ' . $id . ' == ' . $rg_cache_count);
346 389
347 if (strcmp($t[0], 'OK') != 0) {
348 //rg_log('DEBUG: not an OK answer: ' . $t[0]);
390 if (strcmp($status, 'OK') != 0) {
391 //rg_log('DEBUG: not an OK answer: ' . $status);
349 392 return FALSE; return FALSE;
350 393 } }
351 394
File inc/events.inc.php changed (mode: 100644) (index bb4b73f..ef94bf5)
... ... function rg_event_signal_daemon($ev_id, $timeout)
68 68 rg_log_enter("event_signal_daemon: event_id=[$ev_id] timeout=$s_timeout"); rg_log_enter("event_signal_daemon: event_id=[$ev_id] timeout=$s_timeout");
69 69
70 70 if (empty($ev_id)) if (empty($ev_id))
71 $buf = "W";
71 $buf = "W\n";
72 72 else else
73 $buf = "NOTIFY " . $ev_id;
73 $buf = "NOTIFY " . $ev_id . "\n";
74 74
75 75 $flags = 0; $flags = 0;
76 76 if ($timeout === 0) if ($timeout === 0)
 
... ... function rg_event_add($db, $event)
93 93 rg_prof_start("event_add"); rg_prof_start("event_add");
94 94 rg_log_enter("event_add: event=" . rg_array2string($event)); rg_log_enter("event_add: event=" . rg_array2string($event));
95 95
96 if (!isset($event['IP']))
97 $event['IP'] = rg_var_str('REMOTE_ADDR');
96 if (!isset($event['ip']))
97 $event['ip'] = rg_var_str('REMOTE_ADDR');
98 98
99 99 if (!isset($event['debug'])) if (!isset($event['debug']))
100 100 $event['debug'] = 0; $event['debug'] = 0;
 
... ... function rg_event_process($db, $event)
186 186 } }
187 187
188 188 /* /*
189 * Cleans the notification list
190 */
191 function rg_event_notify_clean(&$notify_list)
192 {
193 if (empty($notify_list))
194 return;
195
196 $limit = time() - 5 * 60;
197
198 foreach ($notify_list as $ev_id => $ei) {
199 if (empty($ei)) {
200 unset($notify_list[$ev_id]);
201 continue;
202 }
203
204 foreach ($ei as $index => $info) {
205 if ($info['itime'] < $limit) {
206 unset($notify_list[$ev_id][$index]);
207 socket_close($info['fd']);
208 }
209 }
210 }
211 }
212
213 /*
214 * Tries to notify a client if requested
189 * Notifies all listeners when @ev_id is happening.
215 190 */ */
216 191 function rg_event_notify(&$notify_list, $ev_id, $misc) function rg_event_notify(&$notify_list, $ev_id, $misc)
217 192 { {
218 193 if (!isset($notify_list[$ev_id])) if (!isset($notify_list[$ev_id]))
219 194 return; return;
220 195
221 $buf = "DONE $ev_id\n" . $misc;
196 $buf = "DONE $ev_id $misc\n";
222 197 $buf_len = strlen($buf); $buf_len = strlen($buf);
223 198 foreach ($notify_list[$ev_id] as $index => $info) { foreach ($notify_list[$ev_id] as $index => $info) {
199 if (isset($info['func'])) {
200 $info['func']($info['priv'], $buf);
201 continue;
202 }
203
224 204 $fd = $info['fd']; $fd = $info['fd'];
225 205 rg_log("Notify [$ev_id] [fd=$fd]..."); rg_log("Notify [$ev_id] [fd=$fd]...");
226 206 $r = @socket_send($fd, $buf, $buf_len, 0); $r = @socket_send($fd, $buf, $buf_len, 0);
227 207 if ($r === FALSE) if ($r === FALSE)
228 208 rg_log("Error in sending."); rg_log("Error in sending.");
229 socket_shutdown($fd, 1);
230 209 } }
231 210
232 211 return; return;
File inc/git.inc.php changed (mode: 100644) (index 7746371..64c2717)
2 2 require_once($INC . "/util.inc.php"); require_once($INC . "/util.inc.php");
3 3 require_once($INC . "/log.inc.php"); require_once($INC . "/log.inc.php");
4 4 require_once($INC . "/prof.inc.php"); require_once($INC . "/prof.inc.php");
5 require_once($INC . "/events.inc.php");
5 6
6 7 $rg_git_zero = "0000000000000000000000000000000000000000"; $rg_git_zero = "0000000000000000000000000000000000000000";
7 8 $rg_git_empty = "4b825dc642cb6eb9a060e54bf8d69288fbee4904"; $rg_git_empty = "4b825dc642cb6eb9a060e54bf8d69288fbee4904";
 
... ... function rg_git_diff2array($diff, &$extra)
682 683 */ */
683 684 function rg_git_log($path, $max, $from, $to, $also_patch) function rg_git_log($path, $max, $from, $to, $also_patch)
684 685 { {
686 global $rg_git_empty, $rg_git_zero;
687
685 688 rg_prof_start("git_log"); rg_prof_start("git_log");
686 689 rg_log_enter("git_log: path=$path from=$from to=$to max=$max"); rg_log_enter("git_log: path=$path from=$from to=$to max=$max");
687 690
 
... ... function rg_git_log($path, $max, $from, $to, $also_patch)
699 702 $patches = $also_patch ? " --patch" : " --shortstat"; $patches = $also_patch ? " --patch" : " --shortstat";
700 703
701 704 if (empty($from) && empty($to)) { if (empty($from) && empty($to)) {
702 $from_to = "";
705 $from_to = '';
703 706 } else { } else {
704 707 if (empty($from)) if (empty($from))
705 $from_to = " " . $to;
708 $from_to = ' ' . $to;
709 else if (strcmp($from, $rg_git_zero) == 0)
710 $from_to = ' ' . $rg_git_empty . '..' . $to;
706 711 else else
707 $from_to = " " . $from . ".." . $to;
712 $from_to = ' ' . $from . '..' . $to;
708 713 } }
709 714
710 715 $cmd = "git --no-pager" $cmd = "git --no-pager"
 
... ... function rg_git_update_branch($db, $a)
1325 1330 rg_git_fatal($a['refname'] . ": Cannot set refs/mr/." rg_git_fatal($a['refname'] . ": Cannot set refs/mr/."
1326 1331 . " Try again later."); . " Try again later.");
1327 1332 } }
1328 $r = rg_mr_queue_add($a['repo_id'], $a['namespace'],
1329 $a['old_rev'], $a['new_rev'], $a['refname'], $a['ip']);
1333 $ev = $a;
1334 $ev['category'] = 7000;
1335 $ev['prio'] = 100;
1336 $r = rg_event_add($db, $ev);
1330 1337 if ($r !== TRUE) if ($r !== TRUE)
1331 rg_git_fatal($a['refname'] . ": " . rg_mr_error());
1338 rg_git_fatal($a['refname'] . ": " . rg_event_error());
1339 rg_event_signal_daemon('', 0);
1340
1332 1341 $_x = array(); $_x = array();
1333 1342 $msg = rg_template("msg/push_merge_request.txt", $_x, FALSE /*xss*/); $msg = rg_template("msg/push_merge_request.txt", $_x, FALSE /*xss*/);
1334 1343 rg_git_info($a['refname'] . ':' . "\n" . $msg); rg_git_info($a['refname'] . ':' . "\n" . $msg);
 
... ... function rg_git_update_branch($db, $a)
1336 1345 $history['history_category'] = REPO_CAT_GIT_BRANCH_ANON_PUSH; $history['history_category'] = REPO_CAT_GIT_BRANCH_ANON_PUSH;
1337 1346 $history['history_message'] = 'Anonymous push to ref ' $history['history_message'] = 'Anonymous push to ref '
1338 1347 . $a['refname'] . ' into namespace ' . $mr; . $a['refname'] . ' into namespace ' . $mr;
1339
1340 // TODO: we should notify by e-mail that a merge request is
1341 // waiting.
1342 1348 } else { } else {
1343 1349 rg_log("DEBUG: We are allowed to push."); rg_log("DEBUG: We are allowed to push.");
1344 1350
File inc/mr.inc.php changed (mode: 100644) (index 85d0fe0..d4c3748)
3 3
4 4 require_once($INC . "/util.inc.php"); require_once($INC . "/util.inc.php");
5 5 require_once($INC . "/sql.inc.php"); require_once($INC . "/sql.inc.php");
6 require_once($INC . "/events.inc.php");
6 7
7 8 $rg_mr_env_q = getenv("ROCKETGIT_MR_QUEUE"); $rg_mr_env_q = getenv("ROCKETGIT_MR_QUEUE");
8 9 if (empty($rg_mr_env_q)) if (empty($rg_mr_env_q))
 
... ... function rg_mr_error()
26 27 } }
27 28
28 29 /* /*
29 * Add a merge request to the queue
30 * We should put it in a queue, with fsync; also, in cron, we must process it
30 * Events functions
31 31 */ */
32 function rg_mr_queue_add($repo_id, $namespace, $old_rev, $new_rev, $refname, $ip)
33 {
34 global $php_errormsg;
35 global $rg_mr_queue;
36
37 rg_log("rg_mr_create: repo_id=$repo_id namespace=$namespace"
38 . " old_rev=$old_rev new_rev=$new_rev, refname=$refname"
39 . " ip=$ip rg_mr_queue=$rg_mr_queue");
32 $rg_mr_functions = array(
33 7000 => 'rg_mr_event_new',
34 7001 => 'rg_mr_event_add_to_db'
35 );
36 rg_event_register_functions($rg_mr_functions);
40 37
41 $c = "repo_id=$repo_id namespace=$namespace old_rev=$old_rev"
42 . " new_rev=$new_rev refname=$refname ip=$ip";
43
44 $f = "mr-" . $repo_id . "-" . time() . "-" . rg_id(6);
38 /*
39 * This is called when a new pull request is done
40 */
41 function rg_mr_event_new($db, $ev)
42 {
43 $ret = array();
45 44
46 if (!file_exists($rg_mr_queue)) {
47 if (@mkdir($rg_mr_queue, 0700) === FALSE) {
48 rg_mr_set_error("cannot create merge requests queue ($php_errormsg)");
49 return FALSE;
50 }
51 }
45 // Insert it into database
46 $ret[] = array_merge($ev,
47 array('category' => 7001, 'prio' => 100));
52 48
53 if (@file_put_contents($rg_mr_queue . "/" . $f, $c) === FALSE) {
54 rg_mr_set_error("cannot store merge request ($php_errormsg)");
55 return FALSE;
56 }
49 // TODO: Notify admins of the repo
57 50
58 // TODO: fsync
51 // TODO: Call a webhook
59 52
60 return TRUE;
53 return $ret;
61 54 } }
62 55
63 56 /* /*
64 57 * Add a merge request file to database * Add a merge request file to database
65 58 */ */
66 function rg_mr_create($db, $repo_id, $namespace, $old_rev, $new_rev, $refname,
67 $ip)
59 function rg_mr_event_add_to_db($db, $a)
68 60 { {
69 rg_log("rg_mr_create: repo_id=$repo_id namespace=$namespace"
70 . " old_rev=$old_rev new_rev=$new_rev, refname=$refname"
71 . " ip=$ip");
61 rg_log_ml('mr_add_to_db: a: ' . print_r($a, TRUE));
72 62
73 63 $now = time(); $now = time();
74 $params = array("repo_id" => $repo_id,
75 "now" => $now,
76 "namespace" => $namespace,
77 "refname" => $refname,
78 "old_rev" => $old_rev,
79 "new_rev" => $new_rev,
80 "ip" => $ip);
81 64 $sql = "INSERT INTO merge_requests (repo_id, itime, namespace" $sql = "INSERT INTO merge_requests (repo_id, itime, namespace"
82 65 . ", refname, old_rev, new_rev, done, ip)" . ", refname, old_rev, new_rev, done, ip)"
83 . " VALUES (@@repo_id@@, @@now@@, @@namespace@@, @@refname@@"
66 . " VALUES (@@repo_id@@, @@itime@@, @@namespace@@, @@refname@@"
84 67 . ", @@old_rev@@, @@new_rev@@, 0, @@ip@@)"; . ", @@old_rev@@, @@new_rev@@, 0, @@ip@@)";
85 $res = rg_sql_query_params($db, $sql, $params);
68 $res = rg_sql_query_params($db, $sql, $a);
86 69 if ($res === FALSE) { if ($res === FALSE) {
87 70 rg_mr_set_error("cannot insert merge request" rg_mr_set_error("cannot insert merge request"
88 71 . " (" . rg_sql_error() . ")"); . " (" . rg_sql_error() . ")");
 
... ... function rg_mr_create($db, $repo_id, $namespace, $old_rev, $new_rev, $refname,
91 74
92 75 rg_sql_free_result($res); rg_sql_free_result($res);
93 76
94 return TRUE;
77 return array();
95 78 } }
96 79
97 80 /* /*
 
... ... function rg_mr_condiment(&$row)
181 164 */ */
182 165 function rg_mr_load($db, $repo_id, $limit) function rg_mr_load($db, $repo_id, $limit)
183 166 { {
184 rg_log("rg_mr_load: repo_id=$repo_id limit=$limit");
167 rg_log("mr_load: repo_id=$repo_id limit=$limit");
185 168
186 169 $params = array("repo_id" => $repo_id); $params = array("repo_id" => $repo_id);
187 170 $sql = "SELECT * FROM merge_requests" $sql = "SELECT * FROM merge_requests"
 
... ... function rg_mr_load($db, $repo_id, $limit)
211 194 */ */
212 195 function rg_mr_load_one($db, $repo_id, $namespace) function rg_mr_load_one($db, $repo_id, $namespace)
213 196 { {
214 rg_log("rg_mr_load_one: repo_id=$repo_id namespace=$namespace");
197 rg_log("mr_load_one: repo_id=$repo_id namespace=$namespace");
215 198
216 199 $params = array("repo_id" => $repo_id, "namespace" => $namespace); $params = array("repo_id" => $repo_id, "namespace" => $namespace);
217 200 $sql = "SELECT * FROM merge_requests" $sql = "SELECT * FROM merge_requests"
File inc/sql.inc.php changed (mode: 100644) (index a66f437..8854a3d)
... ... function rg_sql_open_nodelay($h)
68 68
69 69 $_s = microtime(TRUE); $_s = microtime(TRUE);
70 70
71 $tries = 5;
71 $tries = 30;
72 72 while ($tries > 0) { while ($tries > 0) {
73 $db = @pg_pconnect($str);
73 $db = pg_pconnect($str);
74 74 if ($db === FALSE) { if ($db === FALSE) {
75 75 rg_log("Cannot connect to db. Sleep 1 second and try again."); rg_log("Cannot connect to db. Sleep 1 second and try again.");
76 76 sleep(1); sleep(1);
 
... ... function rg_sql_open_nodelay($h)
82 82 $diff = sprintf("%u", (microtime(TRUE) - $_s) * 1000); $diff = sprintf("%u", (microtime(TRUE) - $_s) * 1000);
83 83 rg_prof_set(array("db_c_ms" => $diff)); rg_prof_set(array("db_c_ms" => $diff));
84 84 if ($db === FALSE) { if ($db === FALSE) {
85 rg_log("Cannot connect to database (" . $php_errormsg . ").");
86 rg_sql_set_error("cannot connect to database (" . $php_errormsg . ")");
87 rg_prof_set(array("db_conn_errors" => 1));
85 rg_sql_set_error('cannot connect to database');
86 rg_prof_set(array('db_conn_errors' => 1));
88 87 break; break;
89 88 } }
90 89
File inc/struct.inc.php changed (mode: 100644) (index decbaae..6b201cd)
... ... $rg_sql_struct[35]['tables'] = array(
473 473 ); );
474 474 $rg_sql_struct[35]['other'] = array( $rg_sql_struct[35]['other'] = array(
475 475 "webhooks_i_uid" => "webhooks_i_uid" =>
476 "CREATE INDEX webhooks_i_uid ON webhooks(uid)"
476 "CREATE INDEX webhooks_i_uid ON webhooks(uid)",
477 'history_push not needed' =>
478 'DROP TABLE history_push',
479 'add_key_for_webhooks' =>
480 "ALTER TABLE webhooks ADD key TEXT NOT NULL DEFAULT ''",
481 'add_opaque_for_webhooks' =>
482 "ALTER TABLE webhooks ADD opaque TEXT NOT NULL DEFAULT ''"
477 483 ); );
478 484
479 485 // This must be the last line // This must be the last line
 
... ... function rg_sql_struct_update_needed($db)
582 588
583 589 $old = rg_sql_struct_get_current_ver($db); $old = rg_sql_struct_get_current_ver($db);
584 590 if ($old === FALSE) if ($old === FALSE)
585 return FALSE;
591 return 1;
586 592
587 593 if ($rg_sql_schema_ver == $old) if ($rg_sql_schema_ver == $old)
588 594 return 0; return 0;
File inc/user.inc.php changed (mode: 100644) (index e927c4c..bcc3b10)
... ... function rg_user_event_login($db, $event)
73 73 { {
74 74 $ret = FALSE; $ret = FALSE;
75 75 while (1) { while (1) {
76 $r = rg_user_set_last_seen($db, $event['uid'], $event['ts'],
77 $event['IP']);
76 $r = rg_user_set_last_seen($db, $event['uid'], $event['itime'],
77 $event['ip']);
78 78 if ($r !== TRUE) if ($r !== TRUE)
79 79 break; break;
80 80
 
... ... function rg_user_login_by_user_pass($db, $user, $pass, $login_token, $lock_ip,
932 932 'category' => 2001, 'category' => 2001,
933 933 'prio' => 100, 'prio' => 100,
934 934 'uid' => $ui0['uid'], 'uid' => $ui0['uid'],
935 'ts' => time());
935 'itime' => time());
936 936 $r = rg_event_add($db, $event); $r = rg_event_add($db, $event);
937 937 if ($r !== TRUE) { if ($r !== TRUE) {
938 938 rg_user_set_error('internal error; try again later'); rg_user_set_error('internal error; try again later');
File inc/user/repo-page.php changed (mode: 100644) (index f983453..23b8358)
... ... if (strcmp($_subop, "history") == 0) {
245 245 } else { } else {
246 246 $_repo_body .= rg_template("repo/mrs.html", $rg, TRUE /*xss*/); $_repo_body .= rg_template("repo/mrs.html", $rg, TRUE /*xss*/);
247 247
248 $r = rg_mr_load($db, $rg['ri']['repo_id'], 0 /*no limit*/);
249 if ($r === FALSE) {
250 $_repo_body .= "Error getting merge request list ("
251 . rg_mr_error() . ").";
252 } else {
253 $_repo_body .= rg_template_table("repo/mr/list",
254 $r, $rg);
255 }
256
257 248 while (1) { while (1) {
258 if (empty($paras))
249 if (empty($paras)) {
250 $r = rg_mr_load($db, $rg['ri']['repo_id'], 0 /*no limit*/);
251 if ($r === FALSE) {
252 $_repo_body .= "Error getting merge request list ("
253 . rg_mr_error() . ").";
254 } else {
255 $_repo_body .= rg_template_table("repo/mr/list",
256 $r, $rg);
257 }
259 258 break; break;
259 }
260 260
261 261 $mr = preg_replace('/[^0-9a-zA-Z_]/', '', $mr = preg_replace('/[^0-9a-zA-Z_]/', '',
262 262 array_shift($paras)); array_shift($paras));
File inc/util.inc.php changed (mode: 100644) (index 6313a70..9f4ebdf)
... ... function rg_copy_tree($src, $dst, $mask)
1178 1178 } }
1179 1179
1180 1180 $d = rg_dir_load($src); $d = rg_dir_load($src);
1181 if ($d === FALSE)
1182 break;
1183
1181 1184 $err = FALSE; $err = FALSE;
1182 1185 foreach ($d as $obj) { foreach ($d as $obj) {
1183 1186 if (is_dir($src . "/" . $obj)) { if (is_dir($src . "/" . $obj)) {
 
... ... function rg_del_tree($dst)
1232 1235 break; break;
1233 1236
1234 1237 $d = rg_dir_load($dst); $d = rg_dir_load($dst);
1238 if ($d === FALSE)
1239 break;
1240
1235 1241 $err = FALSE; $err = FALSE;
1236 1242 foreach ($d as $obj) { foreach ($d as $obj) {
1237 1243 if (is_dir($dst . '/' . $obj)) { if (is_dir($dst . '/' . $obj)) {
File inc/webhooks.inc.php changed (mode: 100644) (index 5da2344..16d1ff3)
... ... function rg_wh_error()
21 21 } }
22 22
23 23 $rg_wh_functions = array( $rg_wh_functions = array(
24 10000 => 'rg_wh_send',
25 10001 => 'rg_wh_send_one'
24 10000 => 'rg_wh_send',
25 10001 => 'rg_wh_send_one'
26 26 ); );
27 27 rg_event_register_functions($rg_wh_functions); rg_event_register_functions($rg_wh_functions);
28 28
 
... ... function rg_wh_send_one($db, $event)
36 36 $wh = &$event['wh']; $wh = &$event['wh'];
37 37 $info = &$wh['info']; $info = &$wh['info'];
38 38
39 rg_log('flags=' . $info['flags']);
39 rg_log_ml('wh_send_one: event: ' . print_r($event, TRUE));
40 if ($event['debug'] == 1)
41 rg_log_ml('XXX DEBUG: wh[data]=' . print_r($wh['data'], TRUE));
40 42
41 43 $headers = array(); $headers = array();
42 44
45 while (!empty($info['key'])) {
46 if ($info['type'] == 0)
47 break;
48
49 $headers[] = 'X-RocketGit-Signature: '
50 . hash_hmac('sha512', $wh['data'], $info['key']);
51 break;
52 }
53
43 54 $c = curl_init($info['url']); $c = curl_init($info['url']);
44 55 curl_setopt($c, CURLOPT_POST, 1); curl_setopt($c, CURLOPT_POST, 1);
45 56 curl_setopt($c, CURLOPT_POSTFIELDS, $wh['data']); curl_setopt($c, CURLOPT_POSTFIELDS, $wh['data']);
46 57 curl_setopt($c, CURLOPT_RETURNTRANSFER, TRUE); curl_setopt($c, CURLOPT_RETURNTRANSFER, TRUE);
47 curl_setopt($c, CURLOPT_FOLLOWLOCATION, 0);
58 curl_setopt($c, CURLOPT_FOLLOWLOCATION, 0); // TODO: really?
48 59 curl_setopt($c, CURLOPT_HEADER, 1); curl_setopt($c, CURLOPT_HEADER, 1);
49 60 curl_setopt($c, CURLOPT_HTTPHEADER, $headers); curl_setopt($c, CURLOPT_HTTPHEADER, $headers);
50 61 curl_setopt($c, CURLOPT_USERAGENT, 'RocketGit WebHook'); curl_setopt($c, CURLOPT_USERAGENT, 'RocketGit WebHook');
 
... ... function rg_wh_send_one($db, $event)
52 63 curl_setopt($c, CURLOPT_ENCODING, ''); // => use all methods curl_setopt($c, CURLOPT_ENCODING, ''); // => use all methods
53 64 curl_setopt($c, CURLOPT_VERBOSE, TRUE); curl_setopt($c, CURLOPT_VERBOSE, TRUE);
54 65 curl_setopt($c, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS); curl_setopt($c, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
66 curl_setopt($c, CURLOPT_CERTINFO, TRUE);
67 // Else, a second wh, without client cert can use the connection:
68 curl_setopt($c, CURLOPT_FORBID_REUSE, TRUE);
69
55 70 $err = @fopen('php://temp', 'w'); $err = @fopen('php://temp', 'w');
56 71 if ($err !== FALSE) if ($err !== FALSE)
57 72 curl_setopt($c, CURLOPT_STDERR, $err); curl_setopt($c, CURLOPT_STDERR, $err);
 
... ... function rg_wh_send_one($db, $event)
60 75 curl_setopt($c, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($c, CURLOPT_SSL_VERIFYPEER, FALSE);
61 76
62 77 if (strchr($info['flags'], 'H')) if (strchr($info['flags'], 'H'))
63 curl_setopt($c, CURLOPT_SSL_VERIFYHOST, FALSE);
78 curl_setopt($c, CURLOPT_SSL_VERIFYHOST, 0); // TODO verify 0 is a good value (default 2)
64 79
65 80 $ret = FALSE; $ret = FALSE;
66 81 $cert_file = FALSE; $cert_file = FALSE;
67 82 $ca_file = FALSE; $ca_file = FALSE;
68 83 while (1) { while (1) {
84 $xid = rg_id(8);
85
69 86 if (!empty($info['client_cert'])) { if (!empty($info['client_cert'])) {
70 $f = 'wh-' . $event['ui']['uid'] . '-' . $wh['id'] . '-client';
87 rg_log('DEBUG: will provide client cert...');
88 $f = 'wh-' . $event['ui']['uid'] . '-' . $wh['id'] . '-client-' . $xid;
71 89 $cert_file = rg_tmp_file($f, $info['client_cert']); $cert_file = rg_tmp_file($f, $info['client_cert']);
72 90 if ($cert_file === FALSE) if ($cert_file === FALSE)
73 91 break; break;
74 92
75 93 curl_setopt($c, CURLOPT_SSLCERT, $cert_file); curl_setopt($c, CURLOPT_SSLCERT, $cert_file);
94 } else {
95 rg_log('DEBUG: will NOT provide client cert...');
76 96 } }
77 97
78 98 if (!empty($info['client_ca_cert'])) { if (!empty($info['client_ca_cert'])) {
79 $f = 'wh-' . $event['ui']['uid'] . '-' . $wh['id'] . '-ca';
99 $f = 'wh-' . $event['ui']['uid'] . '-' . $wh['id'] . '-ca-' . $xid;
80 100 $ca_file = rg_tmp_file($f, $info['client_ca_cert']); $ca_file = rg_tmp_file($f, $info['client_ca_cert']);
81 101 if ($ca_file === FALSE) if ($ca_file === FALSE)
82 102 break; break;
 
... ... function rg_wh_send_one($db, $event)
85 105 } }
86 106
87 107 $r = curl_exec($c); $r = curl_exec($c);
108
109 if ($err !== FALSE) {
110 rewind($err);
111 $xerr = @fread($err, 16 * 4096);
112 fclose($err);
113 rg_log_ml($xerr);
114 }
115
88 116 if ($r === FALSE) { if ($r === FALSE) {
89 117 rg_log('Cannot execute curl: ' . curl_error($c)); rg_log('Cannot execute curl: ' . curl_error($c));
90 $info = curl_getinfo($c);
91 rg_log_ml('Debug: ' . print_r($info, TRUE));
118 $_info = curl_getinfo($c);
119 rg_log_ml('Debug: ' . print_r($_info, TRUE));
92 120
93 121 if ($event['debug'] == 1) if ($event['debug'] == 1)
94 122 rg_cache_set('DEBUG::webhooks::' . $event['ui']['uid'] rg_cache_set('DEBUG::webhooks::' . $event['ui']['uid']
123 . '::' . $info['opaque']
95 124 . '::' . $wh['id'], . '::' . $wh['id'],
96 125 'BAD', RG_SOCKET_NO_WAIT); 'BAD', RG_SOCKET_NO_WAIT);
97 126 break; break;
 
... ... function rg_wh_send_one($db, $event)
99 128
100 129 rg_log_ml('Answer: ' . print_r($r, TRUE)); rg_log_ml('Answer: ' . print_r($r, TRUE));
101 130
102 if ($err !== FALSE) {
103 rewind($err);
104 $xerr = @fread($err, 4 * 4096);
105 fclose($err);
106 rg_log_ml('xerr = ' . $xerr);
107 }
108
109 131 if ($event['debug'] == 1) if ($event['debug'] == 1)
110 132 rg_cache_set('DEBUG::webhooks::' . $event['ui']['uid'] rg_cache_set('DEBUG::webhooks::' . $event['ui']['uid']
133 . '::' . $info['opaque']
111 134 . '::' . $wh['id'], . '::' . $wh['id'],
112 135 'OK', RG_SOCKET_NO_WAIT); 'OK', RG_SOCKET_NO_WAIT);
113 136
 
... ... function rg_wh_send($db, $event)
133 156 { {
134 157 rg_prof_start('wh_send'); rg_prof_start('wh_send');
135 158
136 rg_log_ml('event: ' . print_r($event, TRUE));
159 rg_log_ml('wh_send: event: ' . print_r($event, TRUE));
137 160
138 161 // First, get the list of hooks // First, get the list of hooks
139 162 $r = rg_wh_list($db, $event['ui']['uid']); $r = rg_wh_list($db, $event['ui']['uid']);
 
... ... function rg_wh_send($db, $event)
177 200 break; break;
178 201
179 202 case 1: // php serialize case 1: // php serialize
180 $cache[$type] = array(
181 'data' => serialize($event['wh_data']));
203 $cache[$type] = serialize($event['wh_data']);
182 204 break; break;
183 205
184 206 default: default:
 
... ... function rg_wh_add($db, $uid, $data)
430 452 if ($data['id'] == 0) if ($data['id'] == 0)
431 453 $sql = 'INSERT INTO webhooks (uid, repo_id, itime, events' $sql = 'INSERT INTO webhooks (uid, repo_id, itime, events'
432 454 . ', url, client_cert, client_ca_cert, flags' . ', url, client_cert, client_ca_cert, flags'
433 . ', add_ip, description)'
455 . ', add_ip, description, key, opaque)'
434 456 . ' VALUES (@@uid@@, @@repo_id@@, @@itime@@' . ' VALUES (@@uid@@, @@repo_id@@, @@itime@@'
435 457 . ', @@events@@, @@url@@, @@client_cert@@' . ', @@events@@, @@url@@, @@client_cert@@'
436 458 . ', @@client_ca_cert@@, @@flags@@, @@add_ip@@' . ', @@client_ca_cert@@, @@flags@@, @@add_ip@@'
437 . ', @@description@@)'
459 . ', @@description@@, @@key@@, @@opaque@@)'
438 460 . ' RETURNING id'; . ' RETURNING id';
439 461 else else
440 462 $sql = 'UPDATE webhooks' $sql = 'UPDATE webhooks'
 
... ... function rg_wh_add($db, $uid, $data)
445 467 . ', flags = @@flags@@' . ', flags = @@flags@@'
446 468 . ', type = @@type@@' . ', type = @@type@@'
447 469 . ', description = @@description@@' . ', description = @@description@@'
470 . ', key = @@key@@'
471 . ', opaque = @@opaque@@'
448 472 . ' WHERE uid = @@uid@@' . ' WHERE uid = @@uid@@'
449 473 . ' AND id = @@id@@'; . ' AND id = @@id@@';
450 474
 
... ... function rg_wh_add_high_level($db, $rg, $paras)
601 625 $rg['wh']['flags'] = rg_var_a2s('wh::flags'); $rg['wh']['flags'] = rg_var_a2s('wh::flags');
602 626 $rg['wh']['add_ip'] = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : ''; $rg['wh']['add_ip'] = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '';
603 627 $rg['wh']['description'] = rg_var_str('wh::description'); $rg['wh']['description'] = rg_var_str('wh::description');
628 $rg['wh']['opaque'] = rg_var_str('wh::opaque');
629 $rg['wh']['key'] = rg_var_str('wh::key');
604 630
605 631 // TODO: validate here the paras // TODO: validate here the paras
606 632 if ((strncasecmp($rg['wh']['url'], "http", 4) != 0) if ((strncasecmp($rg['wh']['url'], "http", 4) != 0)
 
... ... function rg_wh_add_high_level($db, $rg, $paras)
648 674 $rg['wh']['client_ca_cert'] = ''; $rg['wh']['client_ca_cert'] = '';
649 675 $rg['wh']['flags'] = ''; $rg['wh']['flags'] = '';
650 676 $rg['wh']['description'] = ''; $rg['wh']['description'] = '';
677 $rg['wh']['opaque'] = '';
678 $rg['wh']['key'] = '';
651 679 } }
652 680 } }
653 681
File root/themes/default/mail/user/key/del.body.txt changed (mode: 100644) (index e58d6c3..90be092)
... ... Hello!
2 2
3 3 Some SSH keys were removed from your account. Some SSH keys were removed from your account.
4 4
5 IP: @@IP@@
5 IP: @@ip@@
6 6
7 7 -- --
8 8 RocketGit Team RocketGit Team
File root/themes/default/mail/user/key/new.body.txt changed (mode: 100644) (index 44ba5f6..18f6a8c)
... ... Type: @@ki::type@@
5 5 Comment: @@ki::comment@@ Comment: @@ki::comment@@
6 6 Fingerprint(md5): @@ki::fingerprint_md5@@ Fingerprint(md5): @@ki::fingerprint_md5@@
7 7 Fingerprint(sha256): @@ki::fingerprint_sha256@@ Fingerprint(sha256): @@ki::fingerprint_sha256@@
8 IP: @@IP@@
8 IP: @@ip@@
9 9 Key: Key:
10 10 @@ki::key@@ @@ki::key@@
11 11
File root/themes/default/mail/user/repo/del.body.txt changed (mode: 100644) (index b81b6bc..c991698)
... ... Hello!
2 2
3 3 Repository '@@ri::name@@' was deleted. Repository '@@ri::name@@' was deleted.
4 4
5 IP: @@IP@@
5 IP: @@ip@@
6 6
7 7 -- --
8 8 RocketGit Team RocketGit Team
File root/themes/default/mail/user/repo/new.body.txt changed (mode: 100644) (index 06ec600..3ab3601)
... ... Description:
6 6 @@ri::description@@ @@ri::description@@
7 7
8 8 Link to repository: @@ri::url@@. Link to repository: @@ri::url@@.
9 IP: @@IP@@
9 IP: @@ip@@
10 10
11 11 -- --
12 12 RocketGit Team RocketGit Team
File root/themes/default/mail/user/repo/update.body.txt changed (mode: 100644) (index f2d5c18..ef18b73)
... ... Description changed to:
8 8 Repository is @@if(@@ri::public@@ == 1){{public}}{{private}}. Repository is @@if(@@ri::public@@ == 1){{public}}{{private}}.
9 9 Link to repository: @@ri::url@@ Link to repository: @@ri::url@@
10 10
11 IP: @@IP@@
11 IP: @@ip@@
12 12
13 13 -- --
14 14 RocketGit Team RocketGit Team
File root/themes/default/repo/mr/list/header.html changed (mode: 100644) (index 13ad6b1..2212c42)
3 3 <th>ID</th> <th>ID</th>
4 4 <th>Date / time</th> <th>Date / time</th>
5 5 <th>Ref</th> <th>Ref</th>
6 <th>From</th>
7 <th>To</th>
6 8 @@if(@@can_admin@@ == 1){{<th>IP</th>}}{{}} @@if(@@can_admin@@ == 1){{<th>IP</th>}}{{}}
7 9 </tr> </tr>
8 10
File root/themes/default/repo/mr/list/line.html changed (mode: 100644) (index b649404..b93f30a)
2 2 <td><a href="@@url_repo@@/mr/@@namespace@@">@@namespace@@</a></td> <td><a href="@@url_repo@@/mr/@@namespace@@">@@namespace@@</a></td>
3 3 <td>@@date_utc@@</td> <td>@@date_utc@@</td>
4 4 <td>@@refname@@</td> <td>@@refname@@</td>
5 <td>@@old_rev_short@@</td>
6 <td>@@new_rev_short@@</td>
5 7 @@if(@@can_admin@@ == 1){{<td>@@ip@@</td>}}{{}} @@if(@@can_admin@@ == 1){{<td>@@ip@@</td>}}{{}}
6 8 </tr> </tr>
File root/themes/default/user/home.html changed (mode: 100644) (index 084d7c5..1fa1929)
1 1 <div class="main_title"> <div class="main_title">
2 <img src="https://www.gravatar.com/avatar/@@page_ui::email_md5@@?s=64&r=g" width="64" height="64" />
2 <img src="https://www.gravatar.com/avatar/@@page_ui::email_md5@@?s=64&amp;r=g" alt="avatar" width="64" height="64" />
3 3 Home page of user @@page_ui::username@@ (#@@page_ui::uid@@) Home page of user @@page_ui::username@@ (#@@page_ui::uid@@)
4 4 </div> </div>
File root/themes/default/user/settings/wh/add_edit.html changed (mode: 100644) (index 14233f0..b3ba0ad)
29 29 </textarea> </textarea>
30 30 </p> </p>
31 31
32 <p>
33 <label for="key">HMAC SHA512 key (optional, see hints)</label><br />
34 <input type="text" name="wh::key" id="key" value="@@wh::key@@" />
35 </p>
36
37 <p>
38 <label for="opaque">Opaque string (optional, will be sent in the request)</label><br />
39 <input type="text" name="wh::opaque" id="opaque" value="@@wh::opaque@@" />
40 </p>
41
32 42 <p> <p>
33 43 <label for="client_cert">Optional concatenated certificate and key used to <label for="client_cert">Optional concatenated certificate and key used to
34 44 authenticate us to the server (PEM format, no password)</label><br /> authenticate us to the server (PEM format, no password)</label><br />
File root/themes/default/user/settings/wh/hints.html changed (mode: 100644) (index 22bb562..602ac04)
1 1 Webhooks helps you to trigger some actions on your server when an event Webhooks helps you to trigger some actions on your server when an event
2 happens with you repositories.
2 happens with you repositories.<br />
3 <br />
4
5 Key: a string used to "sign" the requests to your server. You can create it
6 using any character you want: letters, digits and any symbol.<br />
7 The server will create a HMAC over the payload using SHA512 and will add
8 HTTP header <i>X-RocketGit-Signature: &lt;signature&gt;</i>. It is
9 recommended to verify it before parsing the body, for security reasons.
10 It is not generated for <i>application/x-www-form-urlencoded</i> type.<br />
11 <br />
File samples/config.php changed (mode: 100644) (index 1067e69..6dae9c2)
... ... $rg_admin_email = "op@rocketgit.com";
44 44 $rg_account_allow_creation = 1; $rg_account_allow_creation = 1;
45 45
46 46 // Set to 0 if you do not want mandatory e-mail confirmation before usage. // Set to 0 if you do not want mandatory e-mail confirmation before usage.
47 $rg_account_email_confirm = 0;
47 $rg_account_email_confirm = 1;
48 48
49 49 // Maximum number of keys per user // Maximum number of keys per user
50 50 $rg_max_ssh_keys = 10; $rg_max_ssh_keys = 10;
File scripts/events.php changed (mode: 100644) (index 7d7671e..30ba1f0)
... ... require_once($INC . "/plan.inc.php");
29 29 require_once($INC . "/admin.inc.php"); require_once($INC . "/admin.inc.php");
30 30 require_once($INC . "/ver.php"); require_once($INC . "/ver.php");
31 31
32 function rg_destroy($key)
33 {
34 global $conn_table;
35
36 if (isset($conn_table['r'][$key]))
37 unset($conn_table['r'][$key]);
38 if (isset($conn_table['w'][$key]))
39 unset($conn_table['w'][$key]);
40 if (isset($conn_table['conns'][$key]['socket']))
41 if (is_resource($conn_table['conns'][$key]['socket']))
42 socket_close($conn_table['conns'][$key]['socket']);
43 unset($conn_table['conns'][$key]);
44 }
45
46 function rg_event_send($key, $buf)
47 {
48 global $conn_table;
49
50 $s = &$conn_table['conns'][$key];
51 $s['send'] .= $buf;
52 $conn_table['w'][$key] = $s['socket'];
53 }
54
32 55 rg_prof_start("MAIN"); rg_prof_start("MAIN");
33 56
34 57 rg_log_set_file($rg_log_dir . "/events.log"); rg_log_set_file($rg_log_dir . "/events.log");
35 58 rg_log_set_sid("000000"); // to spread the logs rg_log_set_sid("000000"); // to spread the logs
59 // We msut disable cache, else, we will not receive the updates because
60 // of the core cache. Do not forget that we are a long live process.
61 $rg_cache_core_enable = FALSE;
36 62
37 63 rg_log("Start (ver=$rocketgit_version)..."); rg_log("Start (ver=$rocketgit_version)...");
38 64
 
... ... if (file_exists($rg_event_socket))
54 80 unlink($rg_event_socket); unlink($rg_event_socket);
55 81
56 82 // Prepare socket for signaling // Prepare socket for signaling
57 $socket = socket_create(AF_UNIX, SOCK_STREAM, 0);
83 $socket = @socket_create(AF_UNIX, SOCK_STREAM, 0);
58 84 if ($socket === FALSE) { if ($socket === FALSE) {
59 85 rg_internal_error("Cannot create events socket!"); rg_internal_error("Cannot create events socket!");
60 86 exit(1); exit(1);
61 87 } }
62 88
63 $r = socket_bind($socket, $rg_event_socket);
89 $r = @socket_bind($socket, $rg_event_socket);
64 90 if ($r === FALSE) { if ($r === FALSE) {
65 91 rg_internal_error("Cannot bind socket!"); rg_internal_error("Cannot bind socket!");
66 92 exit(1); exit(1);
67 93 } }
68 94
69 $r = socket_listen($socket, 128);
95 $r = @socket_listen($socket, 128);
70 96 if ($r === FALSE) { if ($r === FALSE) {
71 97 rg_internal_error("Cannot set queue length on socket!"); rg_internal_error("Cannot set queue length on socket!");
72 98 exit(1); exit(1);
73 99 } }
74 100
101 socket_set_nonblock($socket);
102
75 103 // Allow apache to connect to socket // Allow apache to connect to socket
76 104 $r = chmod($rg_event_socket, 0666); $r = chmod($rg_event_socket, 0666);
77 105 if ($r === FALSE) { if ($r === FALSE) {
 
... ... if ($r === FALSE) {
79 107 exit(1); exit(1);
80 108 } }
81 109
82 /* This will force accept "accept" to return too early
83 $r = socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array("sec" => 5, "usec" => 0));
84 if ($r === FALSE) {
85 rg_internal_error("Cannot set SO_RCVTIMEO!");
86 exit(1);
87 }
88 */
110 $conn_table = array('r' => array(), 'w' => array(), 'conns' => array());
111 $conn_table['r']['master'] = $socket;
89 112
90 113 $original_mtime = @filemtime(__FILE__); $original_mtime = @filemtime(__FILE__);
91 114 $notify_list = array(); $notify_list = array();
92 115 do { do {
116 rg_log_buffer_clear();
117
93 118 // Check our mtime so we can upgrade the software and this script // Check our mtime so we can upgrade the software and this script
94 119 // will restart. // will restart.
95 120 clearstatcache(); clearstatcache();
 
... ... do {
100 125 break; break;
101 126 } }
102 127
103 rg_log_buffer_clear();
104
128 $r = 0;
105 129 do { do {
106 130 // check machine load - if too big we will delay // check machine load - if too big we will delay
107 131 $load = rg_load(); $load = rg_load();
 
... ... do {
119 143
120 144 // Wait for signal // Wait for signal
121 145 rg_log("Waiting for signal..."); rg_log("Waiting for signal...");
122 // TODO: use socket_select because, else, we are blocking!
123 $client = socket_accept($socket);
124 if ($client === FALSE) {
125 rg_log("Connection seems broken!");
146 $r2 = $conn_table['r'];
147 $w2 = $conn_table['w'];
148 $e2 = array();
149 $r = @socket_select($r2, $w2, $e2, 60);
150 if ($r === FALSE)
151 rg_fatal('Cannot select: '
152 . socket_strerror(socket_last_error()));
153 if ($r == 0)
126 154 continue; continue;
127 }
128 155
129 // TODO: this will be used with select
130 //socket_set_nonblock($client);
131
132 $close = 1;
133 $r = socket_recv($client, $buf, 1024, 0);
134 if ($r === 0) { // remote close the connection
135 rg_log("Remote closed the connection.");
136 } else if ($r === FALSE) {
137 $errno = socket_last_error($client);
138 rg_log("Error in receive (" . socket_strerror($errno) . ").");
139 } else {
140 rg_log("Received $r byte(s): [$buf].");
141 if (strncmp($buf, "NOTIFY ", 7) == 0) {
142 $ev_id = trim(substr($buf, 7));
143 $notify_list[$ev_id][] = array("fd" => $client, "itime" => time());
144 $close = 0;
145
146 // It is possible that we already executed the task
147 rg_event_notify($notify_list, $ev_id, "");
156 //rg_log_ml('conn_table: ' . print_r($conn_table, TRUE));
157 foreach ($r2 as $key => $sock) {
158 if (strcmp($key, "master") == 0) {
159 $client = @socket_accept($sock);
160 if ($client === FALSE) {
161 rg_log("Connection seems broken!");
162 continue;
163 }
164
165 socket_set_nonblock($client);
166 $key = intval($client);
167 $conn_table['conns'][$key] = array(
168 'socket' => $client,
169 'send' => '',
170 'recv' => '');
171 $conn_table['r'][$key] = $client;
172 continue;
173 }
174
175 $r = @socket_recv($client, $buf, 1024, 0);
176 if ($r === FALSE) {
177 rg_log('Error in recv: '
178 . socket_strerror(socket_last_error()));
179 rg_destroy($key);
180 continue;
181 }
182 if ($r === 0) { // remote close the connection
183 rg_log("Remote closed the connection (received 0).");
184 rg_destroy($key);
185 continue;
186 }
187
188 $s = &$conn_table['conns'][$key];
189 $s['recv'] .= $buf;
190 if (!strstr($buf, "\n"))
191 continue;
192 rg_log('RECEIVED: ' . $s['recv']);
193 if (strncmp($s['recv'], 'NOTIFY ', 7) == 0) {
194 $ev_id = trim(substr($s['recv'], 7));
195 $notify_list[$ev_id][] = array(
196 'priv' => $key,
197 'func' => 'rg_event_send');
148 198 } }
199 $s['recv'] = '';
149 200 } }
150 201
151 if ($close == 1)
152 socket_close($client);
202 foreach ($w2 as $key => $sock) {
203 if (!isset($conn_table['conns'][$key]))
204 continue;
205
206 $s = &$conn_table['conns'][$key];
207 $ret = @socket_send($s['socket'], $s['send'], strlen($s['send']), 0);
208 if ($ret === FALSE) {
209 rg_log("Cannot send: " . socket_strerror(socket_last_error()));
210 rg_destroy($key);
211 continue;
212 }
213
214 $s['send'] = substr($s['send'], $ret);
215 if (empty($s['send']))
216 unset($conn_table['w'][$key]);
217 }
153 218
154 // clean up notify_list
155 rg_event_notify_clean($notify_list);
219 //rg_log_ml("e2: " . print_r($e2, TRUE));
220 foreach ($e2 as $key => $sock)
221 rg_destroy($key);
156 222 } while (1); } while (1);
157 223
158 socket_close($socket);
224 @socket_close($socket);
159 225
160 226 rg_log("Exiting..."); rg_log("Exiting...");
161 227
File scripts/remote.php changed (mode: 100644) (index bb6bf26..bc9fae5)
... ... if (isset($_SERVER['SSH_CONNECTION'])) {
125 125 // we have no client info // we have no client info
126 126 $login_uid = 0; $login_uid = 0;
127 127 $key_id = 0; $key_id = 0;
128 $conn_ui = array('uid' => 0, 'username' => '');
128 $conn_ui = array('uid' => 0, 'username' => 'anonymous user');
129 129
130 130 $line = @fread(STDIN, 8000); $line = @fread(STDIN, 8000);
131 131 $line_len = strlen($line); $line_len = strlen($line);
 
... ... if (isset($_SERVER['SSH_CONNECTION'])) {
136 136 if ($line_len < $len) if ($line_len < $len)
137 137 fatal("Too less data ($line_len/$len) received!"); fatal("Too less data ($line_len/$len) received!");
138 138
139 // parse something like: 002bgit-upload-pack /aa.git[0x00]host=localhost
139 // parse something like: 002bgit-upload-pack /aa.git[0x00]host=localhost:9418[0x00]
140 140 $line = substr($line, 4); $line = substr($line, 4);
141 141 $v = explode("\0", $line); $v = explode("\0", $line);
142 142 $cmd_repo = trim($v[0]); $cmd_repo = trim($v[0]);
143 $host = isset($v[1]) ? trim(substr($v[1], 5)) : "";
143 $host_port = isset($v[1]) ? trim(substr($v[1], 5)) : '';
144 $v = explode(':', $host_port);
145 $host = $v[0];
144 146
145 147 $ip = getenv("REMOTE_HOST"); $ip = getenv("REMOTE_HOST");
146
147 info('you are connecting as anonymous.');
148 148 } }
149 149
150 150 // Extracts command and computes permissions // Extracts command and computes permissions
 
... ... if ($push == 1) {
267 267 } }
268 268
269 269 $run = "git-shell -c \"" . $cmd . " " . escapeshellarg($repo_path) . "\""; $run = "git-shell -c \"" . $cmd . " " . escapeshellarg($repo_path) . "\"";
270 $run = $cmd . ' ' . escapeshellarg($repo_path);
270 271 rg_log("Running [$run]..."); rg_log("Running [$run]...");
271 rg_prof_start("git-shell");
272 rg_prof_start($cmd);
272 273 passthru($run, $ret); passthru($run, $ret);
273 rg_prof_end("git-shell");
274 rg_prof_end($cmd);
274 275 rg_log("[$run] returned $ret."); rg_log("[$run] returned $ret.");
275 276
276 277 rg_prof_end("remote.php"); rg_prof_end("remote.php");
File selinux/rocketgit.te changed (mode: 100644) (index de5a2c8..3beff1d)
1 policy_module(rocketgit,1.0.79)
1 policy_module(rocketgit,1.0.81)
2 2
3 3 ######################################## ########################################
4 4 # #
 
... ... gen_require(`
11 11 type httpd_log_t; type httpd_log_t;
12 12 type system_mail_t; type system_mail_t;
13 13 type unconfined_t; type unconfined_t;
14 type unreserved_port_t;
14 15 role unconfined_r; role unconfined_r;
15 16 ') ')
16 17
 
... ... domain_entry_file(rocketgit_t, rocketgit_exec_t)
37 38 # When cron executes rocketgit_exec_t, we transition to rocketgit_t # When cron executes rocketgit_exec_t, we transition to rocketgit_t
38 39 cron_system_entry(rocketgit_t, rocketgit_exec_t) cron_system_entry(rocketgit_t, rocketgit_exec_t)
39 40
40 # When running from inetd, transit to rocketgit_t. Seems that rocketgit_exec_t is
41 # not enough. Why?!
41 # When running from inetd, transit to rocketgit_t. Seems that rocketgit_exec_t
42 # is not enough. Why?!
42 43 optional_policy(` optional_policy(`
43 44 inetd_tcp_service_domain(rocketgit_t, rocketgit_exec_t) inetd_tcp_service_domain(rocketgit_t, rocketgit_exec_t)
44 45 ') ')
 
... ... allow rocketgit_t self:tcp_socket { connect getopt getattr create setopt };
66 67 sysnet_read_config(rocketgit_t) sysnet_read_config(rocketgit_t)
67 68 sysnet_dns_name_resolve(rocketgit_t) sysnet_dns_name_resolve(rocketgit_t)
68 69
70 # Allow it to connect to any port - think about webhooks
71 allow rocketgit_t unreserved_port_t:tcp_socket name_connect;
72
69 73 # Probably to list owner of files # Probably to list owner of files
70 74 auth_read_passwd(rocketgit_t) auth_read_passwd(rocketgit_t)
71 75
File tests/.gitignore changed (mode: 100644) (index e0e46ea..1e238b1)
... ... keys/*
20 20 *.pid *.pid
21 21 ca ca
22 22 pr_anon.git pr_anon.git
23 *.tmp
File tests/Makefile changed (mode: 100644) (index 1154e0a..4a322a8)
... ... git2:
101 101 clean: clean:
102 102 @rm -rf git_log1 *.log *.strace *.strace.* *.out *.lock err-* *.diff \ @rm -rf git_log1 *.log *.strace *.strace.* *.out *.lock err-* *.diff \
103 103 http.arond *.pub git2key git2 *.in q_merge_requests/mr-* \ http.arond *.pub git2key git2 *.in q_merge_requests/mr-* \
104 qstats/* repos/* helper helper.pub keys/* ca *.pid pr_anon.git
104 qstats/* repos/* helper helper.pub keys/* ca *.pid pr_anon.git \
105 *.tmp
File tests/ca.sh changed (mode: 100755) (index 64ccaed..3a8ff3c)
1 1 #!/bin/bash #!/bin/bash
2 2
3 ID=`date +%s`
4
3 5 set -e set -e
4 6
5 7 # Generates a CA # Generates a CA
 
... ... if [ ! -r certs/cacert.pem ]; then
28 30 -extensions v3_ca \ -extensions v3_ca \
29 31 -key private/cakey.pem \ -key private/cakey.pem \
30 32 -out certs/cacert.pem \ -out certs/cacert.pem \
31 -subj "/C=XX/ST=XXX/L=XXX/O=XXX/CN=ca.example.com"
33 -subj "/C=XX/ST=XXX/L=XXX/O=XXX-${ID}/CN=ca.example.com"
32 34 fi fi
33 35
34 36 for i in localhost client; do for i in localhost client; do
 
... ... for i in localhost client; do
40 42 if [ ! -r csr/${i}.csr ]; then if [ ! -r csr/${i}.csr ]; then
41 43 echo "Generating ${i} csr..." echo "Generating ${i} csr..."
42 44 openssl req -new -key private/${i}.key -out csr/${i}.csr \ openssl req -new -key private/${i}.key -out csr/${i}.csr \
43 -subj "/C=XX/ST=XXX/L=XXX/O=XXX/CN=${i}"
45 -subj "/C=XX/ST=XXX/L=XXX/O=XXX-${ID}/CN=${i}"
44 46 fi fi
45 47
46 48 if [ ! -r certs/${i}.pem ]; then if [ ! -r certs/${i}.pem ]; then
File tests/cache.php changed (mode: 100644) (index 6eea041..137abe8)
... ... require_once("common.php");
17 17 $rg_cache_enable = TRUE; $rg_cache_enable = TRUE;
18 18 $rg_cache_debug = TRUE; $rg_cache_debug = TRUE;
19 19
20
21 rg_log('');
22 rg_log('Seting a var in core...');
20 23 rg_cache_core_set("a::b::c", "1"); rg_cache_core_set("a::b::c", "1");
21 24
25
26 rg_log('');
27 rg_log('Testing core_get...');
22 28 $e = "1"; $e = "1";
23 29 $r = rg_cache_core_get("a::b::c"); $r = rg_cache_core_get("a::b::c");
24 30 if ($r !== $e) { if ($r !== $e) {
25 print_r($rg_cache);
31 rg_log_ml('rg_cache: ' . print_r($rg_cache, TRUE));
26 32 rg_log("[$r] != [$e]!"); rg_log("[$r] != [$e]!");
27 33 exit(1); exit(1);
28 34 } }
29 35
36 rg_log('');
37 rg_log('Getting an invalid var...');
30 38 $e = FALSE; $e = FALSE;
31 39 $r = rg_cache_core_get("x::y::z"); $r = rg_cache_core_get("x::y::z");
32 40 if ($r !== $e) { if ($r !== $e) {
33 print_r($rg_cache);
41 rg_log_ml('rg_cache: ' . print_r($rg_cache, TRUE));
34 42 rg_log("r must be FALSE!"); rg_log("r must be FALSE!");
35 43 exit(1); exit(1);
36 44 } }
37 45
46 rg_log('');
47 rg_log('Testing unsetting...');
38 48 rg_cache_core_unset("x::y::z"); rg_cache_core_unset("x::y::z");
39 49 $e = FALSE; $e = FALSE;
40 50 $r = rg_cache_core_get("x::y::z"); $r = rg_cache_core_get("x::y::z");
File tests/helpers.inc.php changed (mode: 100644) (index 6b03636..9c94f42)
... ... function rg_test_create_repo($db, $rg_ui, &$extra)
152 152 RG_SOCKET_NO_WAIT); RG_SOCKET_NO_WAIT);
153 153 } }
154 154
155 rg_log('Waiting for the repo git dir to be created...');
156 $key = 'repo_by_id' . '::' . $extra['repo_id'];
157 $tries = 10;
158 while ($tries-- > 0) {
159 rg_cache_core_unset($key);
160
161 $r = rg_cache_get($key);
162 if ($r === FALSE) {
163 rg_log('r is FALSE');
164 sleep(1);
165 continue;
166 }
167
168 //rg_log_ml('DEBUG: r: ' . print_r($r, TRUE));
169
170 if ($r['git_dir_done'] == 1)
171 break;
172
173 sleep(1);
174 }
175
155 176 return TRUE; return TRUE;
156 177 } }
157 178
 
... ... function rg_test_upload_ssh_key($db, $rg_ui, $key_name, $good_sid)
183 204 exit(1); exit(1);
184 205 } }
185 206 if (empty($r['tokens']['keys'])) { if (empty($r['tokens']['keys'])) {
186 rg_log_ml("token not found! r:" . print_r($r, TRUE));
207 rg_log_ml('r: ' . print_r($r, TRUE));
208 rg_log('token not found!');
187 209 exit(1); exit(1);
188 210 } }
189 211
 
... ... function rg_test_upload_ssh_key($db, $rg_ui, $key_name, $good_sid)
192 214 $headers = array('Cookie: sid=' . $good_sid); $headers = array('Cookie: sid=' . $good_sid);
193 215 $r = do_req($test_url . '/op/settings/keys?t=upload_ssh_key', $data, $headers); $r = do_req($test_url . '/op/settings/keys?t=upload_ssh_key', $data, $headers);
194 216 if ($r === FALSE) { if ($r === FALSE) {
195 rg_log_ml("Cannot upload key: " . print_r($r, TRUE));
217 rg_log_ml('r: ' . print_r($r, TRUE));
218 rg_log_ml("Cannot upload key!");
196 219 exit(1); exit(1);
197 220 } }
198 221
 
... ... function rg_test_sc_generate($db, $rg_ui, $good_sid)
227 250 exit(1); exit(1);
228 251 } }
229 252 if (empty($r['tokens']['sc'])) { if (empty($r['tokens']['sc'])) {
230 rg_log_ml("token not found! r:" . print_r($r, TRUE));
253 rg_log_ml('r: ' . print_r($r, TRUE));
254 rg_log('token not found!');
231 255 exit(1); exit(1);
232 256 } }
233 257
 
... ... function rg_test_sc_generate($db, $rg_ui, $good_sid)
236 260 $headers = array('Cookie: sid=' . $good_sid); $headers = array('Cookie: sid=' . $good_sid);
237 261 $r = do_req($test_url . '/op/settings/totp/sc', $data, $headers); $r = do_req($test_url . '/op/settings/totp/sc', $data, $headers);
238 262 if ($r === FALSE) { if ($r === FALSE) {
239 rg_log_ml("Cannot generate scratch codes: " . print_r($r, TRUE));
263 rg_log_ml('r: ' . print_r($r, TRUE));
264 rg_log_ml('Cannot generate scratch codes!');
240 265 exit(1); exit(1);
241 266 } }
242 267
 
... ... function rg_test_wh_add_edit($db, $rg_ui, $good_sid, $extra)
268 293 exit(1); exit(1);
269 294 } }
270 295 if (empty($r['tokens']['wh_add'])) { if (empty($r['tokens']['wh_add'])) {
271 rg_log_ml("token not found! r:" . print_r($r, TRUE));
296 rg_log_ml('r: ' . print_r($r, TRUE));
297 rg_log_ml('Token not found!');
272 298 exit(1); exit(1);
273 299 } }
274 300
 
... ... function rg_test_wh_add_edit($db, $rg_ui, $good_sid, $extra)
278 304 $headers = array('Cookie: sid=' . $good_sid); $headers = array('Cookie: sid=' . $good_sid);
279 305 $r = do_req($test_url . '/op/settings/wh/add', $data, $headers); $r = do_req($test_url . '/op/settings/wh/add', $data, $headers);
280 306 if ($r === FALSE) { if ($r === FALSE) {
281 rg_log_ml("Cannot add webhook: " . print_r($r, TRUE));
307 rg_log_ml('r: ' . print_r($r, TRUE));
308 rg_log_ml('Cannot add webhook!');
282 309 exit(1); exit(1);
283 310 } }
284 311
285 312 if (!strstr($r['body'], 'with success')) { if (!strstr($r['body'], 'with success')) {
286 rg_log_ml("Cannot add webhook (no success message): " . print_r($r, TRUE));
313 rg_log_ml('r[body]: ' . print_r($r['body']));
314 rg_log('Cannot add webhook (no \'with success\' message)!');
287 315 exit(1); exit(1);
288 316 } }
289 317 } }
File tests/http.inc.php changed (mode: 100644) (index 8454742..a23e94a)
... ... function do_req($url, &$data, &$headers)
13 13 if (!is_array($data)) if (!is_array($data))
14 14 $data = array(); $data = array();
15 15
16 $data['rg_rebug'] = 1;
16 $data['rg_debug'] = 1;
17 17
18 18 if (!is_array($headers)) { if (!is_array($headers)) {
19 19 rg_log("Headers is not an array, reset it."); rg_log("Headers is not an array, reset it.");
 
... ... function do_req($url, &$data, &$headers)
41 41 curl_setopt($c, CURLOPT_HTTPHEADER, $headers); curl_setopt($c, CURLOPT_HTTPHEADER, $headers);
42 42 curl_setopt($c, CURLOPT_USERAGENT, $test_ua); curl_setopt($c, CURLOPT_USERAGENT, $test_ua);
43 43 curl_setopt($c, CURLOPT_REFERER, $test_referer); curl_setopt($c, CURLOPT_REFERER, $test_referer);
44 curl_setopt($c, CURLOPT_CERTINFO, TRUE);
45 curl_setopt($c, CURLOPT_VERBOSE, TRUE);
46
47 $err = @fopen('php://temp', 'w');
48 if ($err !== FALSE) {
49 curl_setopt($c, CURLOPT_STDERR, $err);
50 } else {
51 rg_log('Cannot open stderr redirection!');
52 }
53
44 54 $r = curl_exec($c); $r = curl_exec($c);
55
56 if ($err !== FALSE) {
57 rewind($err);
58 $xerr = @fread($err, 16 * 4096);
59 fclose($err);
60 rg_log_ml($xerr);
61 }
62
45 63 if ($r === FALSE) { if ($r === FALSE) {
46 64 rg_log_ml("Cannot load (url=$url), data: " rg_log_ml("Cannot load (url=$url), data: "
47 65 . print_r($data, TRUE)); . print_r($data, TRUE));
 
... ... function do_req($url, &$data, &$headers)
93 111 } }
94 112
95 113 $ret['tokens'] = array(); $ret['tokens'] = array();
96 $x = preg_match_all('/ name="token" value="([a-zA-Z0-9_:]*)"/', $ret['body'], $matches);
114 $x = preg_match_all('/ name="token" value="([a-zA-Z0-9_:]*)"/',
115 $ret['body'], $matches);
97 116 //rg_log_ml('DEBUG: matches: ' . print_r($matches, TRUE)); //rg_log_ml('DEBUG: matches: ' . print_r($matches, TRUE));
98 117 if (($x === FALSE) || (!isset($matches[1]))) { if (($x === FALSE) || (!isset($matches[1]))) {
99 118 //rg_log("CHECK: no token found"); //rg_log("CHECK: no token found");
 
... ... function do_req($url, &$data, &$headers)
101 120 foreach ($matches[1] as $m) { foreach ($matches[1] as $m) {
102 121 $t = explode(':', $m); $t = explode(':', $m);
103 122 if (!isset($t[1])) { if (!isset($t[1])) {
123 rg_log_ml('body: ' . print_r($ret['body'], TRUE));
124 rg_log_ml('matches: ' . print_r($matches[1], TRUE));
104 125 rg_log('Invalid debug token: ' . $m); rg_log('Invalid debug token: ' . $m);
105 126 exit(1); exit(1);
106 127 } }
File tests/pr_anon.php changed (mode: 100644) (index bc96e3c..84a7586)
... ... $repo = array('repo_id' => 0, 'public' => 1);
35 35 rg_test_create_repo($db, $rg_ui, $repo); rg_test_create_repo($db, $rg_ui, $repo);
36 36
37 37
38 rg_log('');
39 rg_log("Giving anon push rights to any user");
40 $x = array();
41 $x['right_id'] = 0;
42 $x['who'] = $rg_ui['uid'];
43 $x['obj_id'] = $repo['repo_id'];
44 $x['uid'] = 0; // any user
45 $x['rights'] = 'FH'; // fetch and anon push
46 $x['misc'] = ''; // all refs
47 $x['ip'] = ''; // any IP
48 $x['prio'] = 100;
49 $x['description'] = 'bla bla bla';
50 $r = rg_rights_set($db, 'repo_refs', $x);
51 if ($r !== TRUE) {
52 rg_log("We cannot give rights to the user");
53 exit(1);
54 }
55
56
38 57 rg_log(''); rg_log('');
39 58 rg_log('Do an anonymous push...'); rg_log('Do an anonymous push...');
59 system('rm -rf pr_anon.git');
40 60 system('git init pr_anon.git'); system('git init pr_anon.git');
41 61 system('cd pr_anon.git; echo "change1" > a'); system('cd pr_anon.git; echo "change1" > a');
42 62 system('cd pr_anon.git; git add a; git commit -m "change1 desc"'); system('cd pr_anon.git; git add a; git commit -m "change1 desc"');
 
... ... system('cd pr_anon.git; git remote add origin '
50 70 . '/user/' . escapeshellarg($rg_ui['username']) . '/' . '/user/' . escapeshellarg($rg_ui['username']) . '/'
51 71 . escapeshellarg($repo['name'])); . escapeshellarg($repo['name']));
52 72 system('cd pr_anon.git; git push origin master'); system('cd pr_anon.git; git push origin master');
53 exit(1);
54 73
55 74
56 75 rg_log(''); rg_log('');
57 rg_log('Login...');
76 rg_log('Check if the pull request was done...');
77 $tries = 10;
78 while ($tries > 0) {
79 $sql = 'SELECT * FROM merge_requests WHERE repo_id = ' . $repo['repo_id'];
80 $res = rg_sql_query($db, $sql);
81 $rows = rg_sql_num_rows($res);
82 if ($rows > 0)
83 $row = rg_sql_fetch_array($res);
84 rg_sql_free_result($res);
85 if ($rows > 0)
86 break;
87
88 sleep(1);
89 $tries--;
90 }
91 if ($rows == 0) {
92 rg_log('Seems the pull request did not hit the database!');
93 exit(1);
94 }
95 $ns = $row['namespace'];
96 $ref = $row['refname'];
97 if (strcmp($ref, 'refs/heads/master') != 0) {
98 rg_log('Seems the ref is not master: ' . $ref . '!');
99 exit(1);
100 }
101
102
103 rg_log('');
104 rg_log('Login, so we can load the merge request...');
58 105 $r = test_login($test_url, $rg_ui, $good_sid); $r = test_login($test_url, $rg_ui, $good_sid);
59 106 if ($r === FALSE) { if ($r === FALSE) {
60 107 rg_log("Cannot login!"); rg_log("Cannot login!");
 
... ... if ($r === FALSE) {
62 109 } }
63 110
64 111
112 rg_log('');
113 rg_log('Loading the merge requests page - just to see it appears there');
114 $data = array();
115 $headers = array("Cookie: sid=" . $good_sid);
116 $r = do_req($test_url . '/user/' . $rg_ui['username']
117 . '/' . $repo['name'] . '/mr?t=pr_anon', $data, $headers);
118 if (!strstr($r['body'], '>' . $ns . '<')) {
119 rg_log_ml('r: ' . print_r($r, TRUE));
120 rg_log('namespace link not found!');
121 exit(1);
122 }
123
124
125 rg_log('');
126 rg_log('Loading the merge request specific page');
127 $data = array();
128 $headers = array("Cookie: sid=" . $good_sid);
129 $r = do_req($test_url . '/user/' . $rg_ui['username']
130 . '/' . $repo['name'] . '/mr/' . $ns . '?t=pr_anon', $data, $headers);
131 rg_log_ml('r: ' . print_r($r, TRUE));
132
133
65 134 rg_log("OK!"); rg_log("OK!");
66 135 ?> ?>
File tests/repo.php changed (mode: 100644) (index 61a3a18..0ad7c28)
... ... rg_log("Starting");
22 22 require_once("common.php"); require_once("common.php");
23 23
24 24 $rg_sql_debug = 1; $rg_sql_debug = 1;
25 $rg_event_socket = "/var/lib/rocketgit/sockets/event.sock";
25 26
26 27 $sql = "DELETE FROM repos"; $sql = "DELETE FROM repos";
27 28 $res = rg_sql_query($db, $sql); $res = rg_sql_query($db, $sql);
File tests/ssh.php changed (mode: 100644) (index c3fe87e..20cf572)
... ... require_once("common.php");
18 18 $_testns = 'ssh'; $_testns = 'ssh';
19 19 $rg_cache_enable = TRUE; $rg_cache_enable = TRUE;
20 20 $rg_cache_debug = TRUE; $rg_cache_debug = TRUE;
21 $rg_event_socket = "/var/lib/rocketgit/sockets/event.sock";
21 22
22 23 // This test makes sense only on my devel machine // This test makes sense only on my devel machine
23 24 if (php_uname("n") != "r1.embedromix.ro") { if (php_uname("n") != "r1.embedromix.ro") {
File tests/wh-stunnel.conf changed (mode: 100644) (index 5555be0..15a129b)
1 debug = 5
1 debug = 7
2 2 log = overwrite log = overwrite
3 3 CAfile = ca/wh/certs/cacert.pem CAfile = ca/wh/certs/cacert.pem
4 4 cert = ca/wh/certs/localhost.pem cert = ca/wh/certs/localhost.pem
5 5 key = ca/wh/private/localhost.key key = ca/wh/private/localhost.key
6 output = wh-stunnel.log
6 output = wh-stunnel-@@port@@.log
7 7 foreground = yes foreground = yes
8 8 exec = ./wh-helper.sh exec = ./wh-helper.sh
9 9 syslog = no syslog = no
10 10 socket = a:SO_REUSEADDR=yes socket = a:SO_REUSEADDR=yes
11 11
12 12 [me] [me]
13 accept = 127.0.0.1:64000
13 accept = 127.0.0.1:@@port@@
14 14 verify = 2 verify = 2
File tests/wh.php changed (mode: 100644) (index d704d94..64ffa4c)
... ... $_testns = 'wh';
19 19 $rg_cache_enable = TRUE; $rg_cache_enable = TRUE;
20 20 $rg_cache_debug = TRUE; $rg_cache_debug = TRUE;
21 21 $rg_event_socket = "/var/lib/rocketgit/sockets/event.sock"; $rg_event_socket = "/var/lib/rocketgit/sockets/event.sock";
22 $port = 64000;
23 22
23 $port1 = 64000 + (rand(0, 100000) + time()) % 1000;
24 $port2 = $port1 + 1;
25 rg_log('port1=' . $port1 . ' port2=' . $port2);
24 26
25 function clean($pid)
27 function clean()
26 28 { {
27 rg_log("Killing pid $pid...");
28 $r = posix_kill($pid, SIGQUIT);
29 if ($r === FALSE)
30 rg_log('Fail to kill!');
29 system('fuser -k wh-stunnel-1.log 1>/dev/null 2>&1');
30 system('fuser -k wh-stunnel-2.log 1>/dev/null 2>&1');
31 31
32 system('fuser -k wh-stunnel.log');
32 @unlink('wh-stunnel.conf-1.tmp');
33 @unlink('wh-stunnel.conf-2.tmp');
33 34 } }
35 register_shutdown_function('clean');
34 36
35 37
36 38 rg_log(''); rg_log('');
 
... ... if (!strstr($r, 'CA_SH_OK')) {
43 45 } }
44 46
45 47
48 rg_log('');
49 rg_log('Preparing stunnel conf file...');
50 $x = file_get_contents('wh-stunnel.conf');
51 if ($x === FALSE) {
52 rg_log('Cannot load conf file');
53 exit(1);
54 }
55 $y = str_replace('@@port@@', $port1, $x);
56 file_put_contents('wh-stunnel.conf-1.tmp', $y);
57 $y = str_replace('@@port@@', $port2, $x);
58 file_put_contents('wh-stunnel.conf-2.tmp', $y);
59
60
46 61 rg_log(''); rg_log('');
47 62 rg_log('Starting stunnel1...'); rg_log('Starting stunnel1...');
48 63 $pid = pcntl_fork(); $pid = pcntl_fork();
49 64 if ($pid == -1) { if ($pid == -1) {
50 rg_log('Cannot fork1');
65 rg_log('Cannot fork');
51 66 exit(1); exit(1);
52 67 } }
53 68 if ($pid == 0) { //child if ($pid == 0) { //child
54 $r = exec('stunnel wh-stunnel.conf 2>/dev/null');
69 $r = exec('stunnel wh-stunnel.conf-1.tmp 2>/dev/null');
55 70 exit(0); exit(0);
56 71 } }
57 register_shutdown_function('clean', $pid);
72 rg_log('Started stunnel with pid ' . $pid);
73
74
75 rg_log('');
76 rg_log('Starting stunnel2...');
77 $pid = pcntl_fork();
78 if ($pid == -1) {
79 rg_log('Cannot fork');
80 exit(1);
81 }
82 if ($pid == 0) { //child
83 $r = exec('stunnel wh-stunnel.conf-2.tmp 2>/dev/null');
84 exit(0);
85 }
86 rg_log('Started stunnel with pid ' . $pid);
58 87
59 88
60 89 rg_log(''); rg_log('');
61 90 rg_log("Creating a user..."); rg_log("Creating a user...");
62 91 rg_test_create_user($db, $rg_ui); rg_test_create_user($db, $rg_ui);
63 $key = 'DEBUG::webhooks::' . $rg_ui['uid'];
92 $key1 = 'DEBUG::webhooks::' . $rg_ui['uid'] . '::' . $port1;
93 $key2 = 'DEBUG::webhooks::' . $rg_ui['uid'] . '::' . $port2;
64 94
65 95
66 96 rg_log(''); rg_log('');
 
... ... if ($r === FALSE) {
74 104
75 105 rg_log(''); rg_log('');
76 106 rg_log('Registering webhook1...'); rg_log('Registering webhook1...');
77 $extra = array('wh::url' => 'https://localhost:' . $port . '/wh.html',
107 $extra = array(
108 'wh::url' => 'https://localhost:' . $port1 . '/wh.html',
78 109 'wh::type' => 0, 'wh::type' => 0,
79 110 'wh::events[C]' => 'on', 'wh::events[C]' => 'on',
80 111 'wh::events[P]' => 'on', 'wh::events[P]' => 'on',
81 112 'wh::events[B]' => 'on', 'wh::events[B]' => 'on',
82 113 'wh::description' => 'description1 <xss>', 'wh::description' => 'description1 <xss>',
114 'wh::key' => 'key1 <xss>',
115 'wh::opaque' => $port1,
83 116 'wh::client_cert' => '', 'wh::client_cert' => '',
84 117 'wh::client_ca_cert' => file_get_contents('ca/wh/certs/cacert.pem') 'wh::client_ca_cert' => file_get_contents('ca/wh/certs/cacert.pem')
85 118 ); );
 
... ... rg_test_wh_add_edit($db, $rg_ui, $good_sid, $extra);
88 121
89 122 rg_log(''); rg_log('');
90 123 rg_log('Registering webhook2...'); rg_log('Registering webhook2...');
91 $extra = array('wh::url' => 'https://localhost:' . $port . '/wh.html',
92 'wh::type' => 0,
124 $extra = array(
125 'wh::url' => 'https://localhost:' . $port2 . '/wh.html',
126 'wh::type' => 1,
93 127 'wh::events[C]' => 'on', 'wh::events[C]' => 'on',
94 128 'wh::events[P]' => 'on', 'wh::events[P]' => 'on',
95 129 'wh::events[B]' => 'on', 'wh::events[B]' => 'on',
96 'wh::description' => 'description <xss>',
130 'wh::description' => 'description1 <xss>',
131 'wh::key' => 'key2 <xss>',
132 'wh::opaque' => $port2,
97 133 'wh::client_cert' => file_get_contents('ca/wh/certs/client.pem') 'wh::client_cert' => file_get_contents('ca/wh/certs/client.pem')
98 134 . file_get_contents('ca/wh/private/client.key'), . file_get_contents('ca/wh/private/client.key'),
99 135 'wh::client_ca_cert' => file_get_contents('ca/wh/certs/cacert.pem') 'wh::client_ca_cert' => file_get_contents('ca/wh/certs/cacert.pem')
 
... ... rg_log('wh_id2=' . $wh_id2);
122 158
123 159 rg_log(''); rg_log('');
124 160 rg_log('Creating a repo and waiting for trigger'); rg_log('Creating a repo and waiting for trigger');
125 rg_log("rg_debug=$rg_debug.");
126 161 $repo = array(); $repo = array();
127 162 rg_test_create_repo($db, $rg_ui, $repo); rg_test_create_repo($db, $rg_ui, $repo);
128 163
129 164
130 165 rg_log(''); rg_log('');
131 rg_log('Testing if the curl posted with success');
166 rg_log('Testing if the curl posted with success (wh1)');
132 167 for ($i = 0; $i < 10; $i++) { for ($i = 0; $i < 10; $i++) {
133 $r = rg_cache_get($key. '::' . $wh_id1);
168 $r = rg_cache_get($key1 . '::' . $wh_id1);
134 169 rg_log_ml('cache: ' . $r); rg_log_ml('cache: ' . $r);
135 170 if ($r !== FALSE) if ($r !== FALSE)
136 171 break; break;
 
... ... if ($r === FALSE) {
141 176 exit(1); exit(1);
142 177 } }
143 178 if (strcmp($r, "BAD") != 0) { if (strcmp($r, "BAD") != 0) {
144 rg_log('Seems the webhook executed correctly without client cert!');
179 rg_log('Seems wh1 executed correctly without client'
180 . ' cert (r=' . $r . ')!');
145 181 exit(1); exit(1);
146 182 } }
147 183
148 184
149 185 rg_log(''); rg_log('');
150 rg_log('Testing if the curl posted with success');
186 rg_log('Testing if the curl posted with success (wh2)');
151 187 for ($i = 0; $i < 10; $i++) { for ($i = 0; $i < 10; $i++) {
152 $r = rg_cache_get($key. '::' . $wh_id2);
188 $r = rg_cache_get($key2 . '::' . $wh_id2);
189 rg_log_ml('cache: ' . print_r($r, TRUE));
153 190 if ($r !== FALSE) if ($r !== FALSE)
154 191 break; break;
155 rg_log_ml('cache: ' . print_r($r, TRUE));
156 192 sleep(1); sleep(1);
157 193 } }
158 194 if (strcmp($r, "OK") != 0) { if (strcmp($r, "OK") != 0) {
159 rg_log('Seems the webhook did not returned success!');
195 rg_log('Seems wh2 did not returned success'
196 . ' (r=' . $r . ')!');
160 197 exit(1); exit(1);
161 198 } }
162 199
163 200
164 201 rg_log(''); rg_log('');
165 202 rg_log('Testing the edit of webhook1...'); rg_log('Testing the edit of webhook1...');
166 $extra = array('wh::url' => 'https://localhost:' . $port . '/wh.html',
203 $extra = array(
204 'wh::url' => 'https://localhost:' . $port1 . '/wh.html',
167 205 'wh::id' => $wh_id1, 'wh::id' => $wh_id1,
168 206 'wh::type' => 1, 'wh::type' => 1,
169 207 'wh::flags[I]' => 'on', 'wh::flags[I]' => 'on',
170 208 'wh::events[C]' => 'on', 'wh::events[C]' => 'on',
171 209 'wh::events[B]' => 'on', 'wh::events[B]' => 'on',
172 'wh::description' => 'desc2',
173 'wh::client_cert' => 'abc',
174 'wh::client_ca_cert' => 'zzz'
210 'wh::description' => 'desc2 <xss>',
211 'wh::key' => 'another key <xss>',
212 'wh::opaque' => 'xxx',
213 'wh::client_cert' => 'abc <xss>',
214 'wh::client_ca_cert' => 'zzz <xss>'
175 215 ); );
176 216 rg_test_wh_add_edit($db, $rg_ui, $good_sid, $extra); rg_test_wh_add_edit($db, $rg_ui, $good_sid, $extra);
177 217 $sql = "SELECT * FROM webhooks WHERE uid = " . $rg_ui['uid'] $sql = "SELECT * FROM webhooks WHERE uid = " . $rg_ui['uid']
 
... ... $sql = "SELECT * FROM webhooks WHERE uid = " . $rg_ui['uid']
179 219 $res = rg_sql_query($db, $sql); $res = rg_sql_query($db, $sql);
180 220 $row = rg_sql_fetch_array($res); $row = rg_sql_fetch_array($res);
181 221 rg_sql_free_result($res); rg_sql_free_result($res);
182 $key1 = 'user' . '::' . $rg_ui['uid'] . '::' . 'wh' . '::' . $wh_id1;
183 rg_cache_core_unset($key1); // else we will get previous copy!
184 $c = rg_cache_get($key1);
222 $key = 'user' . '::' . $rg_ui['uid'] . '::' . 'wh' . '::' . $wh_id1;
223 rg_cache_core_unset($key); // else we will get previous copy!
224 $c = rg_cache_get($key);
185 225 $list = array('flags' => 'I', 'events' => 'CB', 'type' => '1', $list = array('flags' => 'I', 'events' => 'CB', 'type' => '1',
186 'description' => 'desc2', 'client_cert' => 'abc',
187 'client_ca_cert' => 'zzz');
226 'description' => 'desc2 <xss>', 'key' => 'another key <xss>',
227 'opaque' => 'xxx', 'client_cert' => 'abc <xss>',
228 'client_ca_cert' => 'zzz <xss>');
188 229 foreach ($list as $k => $v) { foreach ($list as $k => $v) {
189 230 if (strcmp($row[$k], $v) != 0) { if (strcmp($row[$k], $v) != 0) {
190 231 rg_log_ml('row: ' . print_r($row, TRUE)); rg_log_ml('row: ' . print_r($row, TRUE));
191 rg_log("db: Seems that $k was not updated [" . $row[$k] . "] != " . $v);
232 rg_log("db: Seems that [$k] was not updated [" . $row[$k] . "] != " . $v);
192 233 exit(1); exit(1);
193 234 } }
194 235
195 236 if (strcmp($c[$k], $v) != 0) { if (strcmp($c[$k], $v) != 0) {
196 237 rg_log_ml('c: ' . print_r($c, TRUE)); rg_log_ml('c: ' . print_r($c, TRUE));
197 rg_log("cache: Seems that $k was not updated [" . $c[$k] . "] != " . $v);
238 rg_log("cache: Seems that [$k] was not updated [" . $c[$k] . "] != " . $v);
198 239 exit(1); exit(1);
199 240 } }
200 241 } }
 
... ... $data = array( 'delete' => 1,
220 261 'delete_list[' . $wh_id1 . ']' => 'on'); 'delete_list[' . $wh_id1 . ']' => 'on');
221 262 $r = do_req($test_url . "/op/settings/wh/list", $data, $headers); $r = do_req($test_url . "/op/settings/wh/list", $data, $headers);
222 263 if (!strstr($r['body'], 'deleted with success')) { if (!strstr($r['body'], 'deleted with success')) {
223 rg_log_ml('r: ' . print_r($r, TRUE));
264 rg_log_ml('r[body]: ' . print_r($r['body'], TRUE));
224 265 rg_log("Cannot delete webhook!"); rg_log("Cannot delete webhook!");
225 266 exit(1); exit(1);
226 267 } }
Hints

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

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

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

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