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 3425b4b9d8744d21f2b581a9f09f563cd0c84e01

CSS fixes (more flex); removed 'between' template
Author: Catalin(ux) M. BOIE
Author date (UTC): 2015-12-31 16:07
Committer name: Catalin(ux) M. BOIE
Committer date (UTC): 2016-01-01 09:10
Parent(s): 49acbf556027578733ed631c551b6cb3266d2af6
Signing key:
Tree: c7cdab197226fc342de4ac7dfc84f26e08356503
File Lines added Lines deleted
TODO 7 12
TODO.vm 2 0
inc/rights.inc.php 1 4
inc/util.inc.php 33 11
inc/webhooks.inc.php 23 9
inc/wh/core.inc.php 463 0
inc/wh/http.inc.php 438 0
root/index.php 1 3
root/themes/default/download-vm.html 4 4
root/themes/default/download.html 4 3
root/themes/default/hints/list/between.html 0 1
root/themes/default/hints/list/header.html 1 1
root/themes/default/hints/repo/anon_push.html 1 0
root/themes/default/hints/repo/bug/add.html 2 1
root/themes/default/hints/repo/client_win.html 1 0
root/themes/default/hints/repo/clone_git.html 1 0
root/themes/default/hints/repo/clone_owner.html 1 0
root/themes/default/hints/repo/clone_ssh.html 1 0
root/themes/default/hints/repo/create_repo.html 2 1
root/themes/default/hints/repo/edit_repo_path_rights.html 1 0
root/themes/default/hints/repo/edit_repo_refs_rights.html 1 0
root/themes/default/hints/repo/edit_repo_rights.html 1 0
root/themes/default/hints/repo/edit_rights.html 1 0
root/themes/default/hints/repo/git_setup.html 1 0
root/themes/default/hints/repo/lock_repo.html 1 0
root/themes/default/hints/repo/merge.html 1 0
root/themes/default/hints/ssh/cmds.html 1 0
root/themes/default/hints/ssh/key.html 1 0
root/themes/default/index.html 1 1
root/themes/default/main.css 28 16
root/themes/default/user/hints/totp.html 3 1
root/themes/default/user/settings/totp/hints.html 2 1
root/themes/default/user/settings/totp/sc/hints.html 2 1
root/themes/default/user/settings/wh/add_edit.html 1 1
root/themes/default/user/settings/wh/deny.html 3 0
root/themes/default/user/settings/wh/hints.html 1 0
root/themes/default/user/settings/wh/http/form.html 28 0
root/themes/default/user/settings/wh/http/hints.html 5 0
root/themes/default/user/settings/wh/http/inv_flag.txt 1 0
root/themes/default/user/settings/wh/http/inv_proto.txt 1 0
root/themes/default/user/settings/wh/http/inv_type.txt 1 0
root/themes/default/user/settings/wh/http/show.html 21 0
root/themes/default/user/settings/wh/list/header.html 4 1
root/themes/default/user/settings/wh/list/line.html 5 2
root/themes/default/user/settings/wh/plugins_list/footer.html 2 0
root/themes/default/user/settings/wh/plugins_list/header.html 8 0
root/themes/default/user/settings/wh/plugins_list/line.html 5 0
root/themes/default/user/settings/wh/plugins_list/nodata.html 1 1
scripts/remote.php 2 2
tests/helpers.inc.php 10 2
tests/wh_http.php 375 0
File TODO changed (mode: 100644) (index 8708d3a..a2a5fd7)
1 1 == Where I stopped last time == == Where I stopped last time ==
2 [ ] When we pass the repo_id as parameter, I must validate the user is allowed
3 to do it!!!
2 [ ]
3
4 == BEFORE NEXT RELEASE ==
5 [ ] Somehow, test if we use rg_xss_safe if a 'HTML:' var is set.
6 [ ] ssh: not documented in hints
7 [ ] I do not have rights to del_undel bugs, but I am still getting the
8 token (token_get). Not good.
4 9 [ ] Plan for webhooks: [ ] Plan for webhooks:
5 10 If we do 'include', take care of type to be aonly a-bA-B0-9_! If we do 'include', take care of type to be aonly a-bA-B0-9_!
6 11 [ ] Do not show 'webhooks' menu if the login user has no rights. [ ] Do not show 'webhooks' menu if the login user has no rights.
7 12 This is for when we will allow webhooks per repo. This is for when we will allow webhooks per repo.
8 [ ] rg_wh_http_cosmetic is not used. How should we show custom data?
9 Use a custom function?
10 [ ] Check if we have in database a watch with uid == 0!
11 delete from watch_bug where uid = 0;
12 [ ] bugs in cache are indexed by repo_id! Not good!
13 [ ] I do not have rights to del_undex bugs, but I am still getting the
14 token (token_get). Not good.
15 [ ]
16
17 == BEFORE NEXT RELEASE ==
18 13 [ ] Add labels for users and for repos/comments/etc.? [Also] private ones? [ ] Add labels for users and for repos/comments/etc.? [Also] private ones?
19 14 [ ] I should add "Labels: " in front of labels. [ ] I should add "Labels: " in front of labels.
20 15 [ ] last events: gravatar [ ] last events: gravatar
File TODO.vm changed (mode: 100644) (index 3b7039a..ca2fd2e)
1 [ ] Add an install method to stream the image dirrectly + copy-on-read?
1 2 [ ] Check other filesystems: nils2 etc for virtual machine. [ ] Check other filesystems: nils2 etc for virtual machine.
2 3 [ ] Use guestmount when building VM images? [ ] Use guestmount when building VM images?
3 4 [ ] Add sha1sum of the VM images [ ] Add sha1sum of the VM images
4 5 [ ] Sign vm images. [ ] Sign vm images.
5 6 [ ] Document that is a i386 image to be able to be run on a lot of machines? [ ] Document that is a i386 image to be able to be run on a lot of machines?
7 [ ] Test if we are creating 'repo_history_' tables from 1970!
6 8 [ ] [ ]
File inc/rights.inc.php changed (mode: 100644) (index 463f801..15de716)
... ... function rg_rights_split_ip($ip)
470 470 $ip2 = $ip; $ip2 = $ip;
471 471 } }
472 472
473 // Deal with ::ffff:46.102.28.148
474 if (strncasecmp($ip2, "::ffff:", 7) == 0)
475 $ip2 = substr($ip2, 7);
476
473 $ip2 = rg_ip_fix($ip2);
477 474 if (preg_match('/^[a-fA-F0-9:]*$/D', $ip2) === 1) { /* ipv6 */ if (preg_match('/^[a-fA-F0-9:]*$/D', $ip2) === 1) { /* ipv6 */
478 475 if ($ret['prefix_len'] == -1) { if ($ret['prefix_len'] == -1) {
479 476 $ret['prefix_len'] = 128; $ret['prefix_len'] = 128;
File inc/util.inc.php changed (mode: 100644) (index ed0bcf6..683a12e)
... ... function rg_template_string(&$s, $off, &$data, $xss_protection)
778 778 if (isset($rg_template_functions[$func])) if (isset($rg_template_functions[$func]))
779 779 $value = $rg_template_functions[$func]($param); $value = $rg_template_functions[$func]($param);
780 780 } else { } else {
781 rg_log("DEBUG: VAR [$var] NOT FOUND!");
781 //rg_log("DEBUG: VAR [$var] NOT FOUND!");
782 782 } }
783 783 } }
784 784 //rg_log("DEBUG: value=[$value]"); //rg_log("DEBUG: value=[$value]");
 
... ... function rg_template($file, &$data, $xss_protection)
801 801 global $rg_theme; global $rg_theme;
802 802
803 803 rg_prof_start('template'); rg_prof_start('template');
804 rg_log_enter('template: ' . $file);
804 //rg_log_enter('template: ' . $file);
805 805
806 806 $ret = ''; $ret = '';
807 807 while (1) { while (1) {
 
... ... function rg_template($file, &$data, $xss_protection)
825 825 } }
826 826
827 827 //rg_log("DEBUG: rg_template returns [$ret]"); //rg_log("DEBUG: rg_template returns [$ret]");
828 rg_log_exit();
828 //rg_log_exit();
829 829 rg_prof_end('template'); rg_prof_end('template');
830 830 return $ret; return $ret;
831 831 } }
 
... ... function rg_template_table($dir, &$data, $more)
840 840 global $rg_theme; global $rg_theme;
841 841
842 842 rg_prof_start('template_table'); rg_prof_start('template_table');
843 rg_log('template_table: ' . $dir);
843 //rg_log('template_table: ' . $dir);
844 844
845 845 $xdir = $rg_theme_dir . "/" . $rg_theme . "/" . $dir; $xdir = $rg_theme_dir . "/" . $rg_theme . "/" . $dir;
846 846 if (!is_dir($xdir)) { if (!is_dir($xdir)) {
 
... ... function rg_template_table($dir, &$data, $more)
857 857
858 858 $head = rg_template($xdir . "/header.html", $more, TRUE /* xss */); $head = rg_template($xdir . "/header.html", $more, TRUE /* xss */);
859 859 $foot = rg_template($xdir . "/footer.html", $more, TRUE /* xss */); $foot = rg_template($xdir . "/footer.html", $more, TRUE /* xss */);
860 $between = rg_template($xdir . "/between.html", $more, TRUE /* xss */);
861 860
862 861 $line = rg_file_get_contents($xdir . "/line.html"); $line = rg_file_get_contents($xdir . "/line.html");
863 862
864 863 $body = ''; $body = '';
865 $first = 1;
866 864 foreach ($data as $index => $info) { foreach ($data as $index => $info) {
867 if ($first == 1)
868 $first = 0;
869 else
870 $body .= $between;
871
872 865 $more2 = array_merge($more, $info); $more2 = array_merge($more, $info);
873 866 $body .= rg_template_string($line, 0, $more2, TRUE /* xss */); $body .= rg_template_string($line, 0, $more2, TRUE /* xss */);
874 867 } }
 
... ... function rg_tmp_file($file, $content)
1591 1584 return $final_name; return $final_name;
1592 1585 } }
1593 1586
1587 /*
1588 * Function to short the certificates
1589 */
1590 function rg_cert_short($s)
1591 {
1592 if (empty($s))
1593 return 'n/a';
1594
1595 if (strlen($s) < 12)
1596 return $s;
1597
1598 $s = str_replace('-----BEGIN CERTIFICATE-----', '', $s);
1599 $s = str_replace('-----END CERTIFICATE-----', '', $s);
1600 $s = trim($s);
1601
1602 return substr($s, 0, 4) . '...' . substr($s, -4, 4);
1603 }
1604
1605 /*
1606 * Remove ::ffff: prefix
1607 */
1608 function rg_fix_ip($ip)
1609 {
1610 if (strncasecmp($ip, "::ffff:", 7) == 0)
1611 $ip = substr($ip, 7);
1612
1613 return $ip;
1614 }
1615
1594 1616 ?> ?>
File inc/webhooks.inc.php changed (mode: 100644) (index 1878445..cdd66a3)
... ... function rg_wh_list_high_level($db, $rg, $paras)
48 48 $rg, TRUE /*xss*/); $rg, TRUE /*xss*/);
49 49 } else { } else {
50 50 rg_wh_cosmetic($r['list']); rg_wh_cosmetic($r['list']);
51 //rg_log_ml("DEBUG: r[list]: " . print_r($r['list'], TRUE));
51 //rg_log_ml('DEBUG: wh_list_high_level: r[list]: '
52 // . print_r($r['list'], TRUE));
52 53 $rg['rg_form_token'] = rg_token_get($db, $rg, 'wh_list'); $rg['rg_form_token'] = rg_token_get($db, $rg, 'wh_list');
53 54 $rg['HTML:errmsg'] = rg_template_errmsg($errmsg); $rg['HTML:errmsg'] = rg_template_errmsg($errmsg);
54 55 $ret .= rg_template_table('user/settings/wh/list', $ret .= rg_template_table('user/settings/wh/list',
 
... ... function rg_wh_add_high_level($db, $rg, $paras)
68 69 rg_prof_start('wh_add_high_level'); rg_prof_start('wh_add_high_level');
69 70 rg_log_enter('wh_add_high_level'); rg_log_enter('wh_add_high_level');
70 71
72 rg_log('DEBUG: paras:' . rg_array2string($paras));
73
71 74 $ret = ''; $ret = '';
72 75 $errmsg = array(); $errmsg = array();
73 76 $show_form = TRUE; $show_form = TRUE;
74 77
75 78 $rg['wh'] = array(); $rg['wh'] = array();
79 $rg['wh']['htype'] = rg_var_str('wh::htype');
76 80 // We need the id in any case // We need the id in any case
77 $rg['wh']['id'] = rg_var_str('wh::id');
81 if (isset($paras[0])) {
82 $rg['wh']['id'] = intval($paras[0]);
83 } else {
84 $rg['wh']['id'] = rg_var_str('wh::id');
85
86 if (empty($rg['wh']['htype'])) {
87 $ret .= rg_wh_htypes($rg);
88 $show_form = FALSE;
89 }
78 90
79 $rg['wh']['htype'] = rg_var_str('wh::htype');
80 if (empty($rg['wh']['htype'])) {
81 $ret .= rg_wh_htypes($rg);
82 $show_form = FALSE;
83 91 } }
84 92
85 93 $add = rg_var_uint('add'); $add = rg_var_uint('add');
 
... ... function rg_wh_add_high_level($db, $rg, $paras)
94 102 $rg['wh']['key'] = rg_var_str('wh::key'); $rg['wh']['key'] = rg_var_str('wh::key');
95 103 rg_wh_fill_vars($rg); rg_wh_fill_vars($rg);
96 104
97 rg_log('DEBUG: before validate_vars');
98 105 $r = rg_wh_validate_vars($rg, $errmsg); $r = rg_wh_validate_vars($rg, $errmsg);
99 106 if ($r !== TRUE) if ($r !== TRUE)
100 107 break; break;
101 108
102 rg_log('DEBUG: before valid_referer');
103 109 if (!rg_valid_referer()) { if (!rg_valid_referer()) {
104 110 $errmsg[] = 'invalid referer; try again'; $errmsg[] = 'invalid referer; try again';
105 111 break; break;
 
... ... function rg_wh_add_high_level($db, $rg, $paras)
128 134 if ($add == 0) { if ($add == 0) {
129 135 // TODO: if edit, load data based on id // TODO: if edit, load data based on id
130 136 if ($rg['wh']['id'] > 0) { if ($rg['wh']['id'] > 0) {
131 rg_log('TODO: edit is not yet implemented');
137 $r = rg_wh_list($db, $rg['login_ui']['uid']);
138 if ($r['ok'] != 1) {
139 $errmsg[] = 'cannot load webhook info; try again later';
140 } else if (!isset($r['list'][$rg['wh']['id']])) {
141 $errmsg[] = 'invalid webhook id';
142 } else {
143 $rg['wh'] = $r['list'][$rg['wh']['id']];
144 }
132 145 } else { } else {
133 146 // here is clear an add // here is clear an add
134 147 $rg['wh']['id'] = 0; $rg['wh']['id'] = 0;
 
... ... function rg_wh_high_level($db, $rg, $paras)
180 193
181 194 switch ($op) { switch ($op) {
182 195 case 'add': case 'add':
196 case 'edit':
183 197 $ret .= rg_wh_add_high_level($db, $rg, $paras); $ret .= rg_wh_add_high_level($db, $rg, $paras);
184 198 break; break;
185 199
File inc/wh/core.inc.php added (mode: 100644) (index 0000000..3597cae)
1 <?php
2 require_once($INC . "/util.inc.php");
3 require_once($INC . "/log.inc.php");
4 require_once($INC . "/sql.inc.php");
5 require_once($INC . "/prof.inc.php");
6
7 $rg_wh_error = "";
8
9 function rg_wh_set_error($str)
10 {
11 global $rg_wh_error;
12
13 $rg_wh_error = $str;
14 rg_log($str);
15 }
16
17 function rg_wh_error()
18 {
19 global $rg_wh_error;
20 return $rg_wh_error;
21 }
22
23 // Here plugins will store the functions
24 $rg_wh_plugins = array();
25
26 $rg_wh_events = array(
27 'C' => 'Create repository',
28 'P' => 'Push',
29 'B' => 'Create branch'
30 );
31 /*
32 * Generates event list as html
33 */
34 function rg_wh_check_events($events)
35 {
36 global $rg_wh_events;
37
38 $ret = '<fieldset>';
39 $ret .= '<legend>Select trigger events</legend>';
40 $br = '';
41 foreach ($rg_wh_events as $id => $name) {
42 $add = '';
43 if (strchr($events, $id))
44 $add = ' checked="checked"';
45
46 $ret .= $br
47 . '<input type="checkbox" name="wh::events[' . $id . ']"'
48 . ' id="events-' . $id . '"'
49 . $add . ' />'
50 . "\n"
51 . '<label for="events-' . $id . '">' . $name . '</label>';
52 $br = '<br />' . "\n";
53 }
54 $ret .= '</fieldset>' . "\n";
55
56 return $ret;
57 }
58
59 /*
60 * Generates an events list as text
61 */
62 function rg_wh_events($events)
63 {
64 global $rg_wh_events;
65
66 $a = array();
67 foreach ($rg_wh_events as $id => $name) {
68 if (strchr($events, $id))
69 $a[] = $name;
70 }
71
72 return implode(', ', $a);
73 }
74
75 /*
76 * Some cosmetics applied to a webhook
77 */
78 function rg_wh_cosmetic(&$list)
79 {
80 global $rg_wh_plugins;
81
82 foreach ($list as $id => &$row) {
83 if (isset($row['itime']))
84 $row['itime_nice'] = gmdate('Y-m-d H:i', $row['itime']);
85
86 if (isset($row['description'])) {
87 if (empty($row['description']))
88 $row['HTML:description_nice'] = 'n/a';
89 else
90 $row['HTML:description_nice'] =
91 nl2br(rg_xss_safe($row['description']));
92 }
93
94 if (isset($row['events']))
95 $row['events_text'] = rg_wh_events($row['events']);
96
97 if (isset($row['last_output'])) {
98 if (empty($row['last_output']))
99 $row['HTML:last_output_nice'] = 'n/a';
100 else
101 $row['HTML:last_output_nice'] =
102 nl2br(rg_xss_safe($row['last_output']));
103 }
104
105 $t = $row['htype'];
106 if (isset($rg_wh_plugins[$t]['cosmetic']))
107 $rg_wh_plugins[$t]['cosmetic']($row);
108 }
109 }
110
111 /*
112 * Set last_output field of a webhook
113 */
114 function rg_wh_set_last_output($db, $uid, $id, $output)
115 {
116 rg_prof_start('wh_set_last_output');
117 rg_log_enter('wh_set_last_output id=$id');
118
119 $ret = FALSE;
120 while (1) {
121 $params = array('id' => $id, 'last_output' => $output);
122 $sql = 'UPDATE webhooks'
123 . ' SET last_output = @@last_output@@'
124 . ' WHERE id = @@id@@';
125 $res = rg_sql_query_params($db, $sql, $params);
126 if ($res === FALSE) {
127 rg_wh_set_error('cannot insert/update data');
128 break;
129 }
130 rg_sql_free_result($res);
131
132 $key = 'wh' . '::' . $uid . '::' . 'list'
133 . '::' . $id . '::' . 'last_output';
134 rg_cache_set($key, $output, RG_SOCKET_NO_WAIT);
135
136 $ret = TRUE;
137 break;
138 }
139
140 rg_log_exit();
141 rg_prof_end('wh_set_last_output');
142 return $ret;
143 }
144
145 /*
146 * Sorting the webhooks list by itime DESC
147 */
148 function rg_wh_sort_helper($a, $b)
149 {
150 if ($a['itime'] > $b['itime'])
151 return -1;
152
153 if ($a['itime'] == $b['itime'])
154 return 0;
155
156 return 1;
157 }
158
159 /*
160 * Returns a list of webhooks associated with a user
161 * @repo_id may be 0 => hooks installed on user account
162 */
163 function rg_wh_list($db, $uid)
164 {
165 rg_prof_start('wh_list');
166 rg_log_enter('wh_list');
167
168 $ret = array('ok' => 0, 'list' => array());
169 while (1) {
170 $key = 'wh' . '::' . $uid;
171 $r = rg_cache_get($key);
172 if (($r !== FALSE) && isset($r['LIST_LOADED'])) {
173 $ret['list'] = $r['list'];
174 $ret['ok'] = 1;
175 break;
176 }
177
178 $params = array('uid' => $uid);
179 $sql = 'SELECT * FROM webhooks'
180 . ' WHERE uid = @@uid@@'
181 . ' ORDER BY itime DESC';
182 $res = rg_sql_query_params($db, $sql, $params);
183 if ($res === FALSE) {
184 rg_wh_set_error('cannot load data');
185 break;
186 }
187
188 while (($row = rg_sql_fetch_array($res))) {
189 //rg_log_ml('DEBUG: wh_list: row: ' . print_r($row, TRUE));
190 $id = $row['id'];
191 if (strcmp($row['idata'], "") != 0) {
192 $row['idata'] = unserialize($row['idata']);
193 if ($row['idata'] === FALSE) {
194 rg_internal_error('cannot unserialize data');
195 // we try to continue
196 $row['idata'] = array();
197 }
198 } else {
199 $row['idata'] = array();
200 }
201
202 $ret['list'][$id] = $row;
203 }
204 rg_sql_free_result($res);
205
206 $a = array('LIST_LOADED' => 1, 'list' => $ret['list']);
207 rg_cache_merge($key, $a, RG_SOCKET_NO_WAIT);
208 $ret['ok'] = 1;
209 break;
210 }
211 uasort($ret['list'], 'rg_wh_sort_helper');
212
213 rg_log_exit();
214 rg_prof_end('wh_list');
215 return $ret;
216 }
217
218 /*
219 * Adds/edits a webhook
220 */
221 function rg_wh_add($db, $uid, $data)
222 {
223 rg_prof_start('wh_add');
224 rg_log_enter('wh_add');
225
226 $ret = array('ok' => 0);
227 while (1) {
228 $data['uid'] = $uid;
229 $data['itime'] = time();
230 $params = $data;
231 $params['idata'] = serialize($params['idata']);
232
233 if ($data['id'] == 0) {
234 $data['last_output'] = '';
235 $sql = 'INSERT INTO webhooks (uid, repo_id, itime'
236 . ', htype, events, url'
237 . ', add_ip, description, key, opaque, idata)'
238 . ' VALUES (@@uid@@, @@repo_id@@, @@itime@@'
239 . ', @@htype@@, @@events@@, @@url@@'
240 . ', @@add_ip@@'
241 . ', @@description@@, @@key@@, @@opaque@@'
242 . ', @@idata@@)'
243 . ' RETURNING id';
244 } else {
245 $sql = 'UPDATE webhooks'
246 . ' SET events = @@events@@'
247 . ', url = @@url@@'
248 . ', description = @@description@@'
249 . ', key = @@key@@'
250 . ', opaque = @@opaque@@'
251 . ', idata = @@idata@@'
252 . ' WHERE uid = @@uid@@'
253 . ' AND id = @@id@@';
254 }
255
256 $res = rg_sql_query_params($db, $sql, $params);
257 if ($res === FALSE) {
258 rg_wh_set_error('cannot insert/update data');
259 break;
260 }
261 if ($data['id'] == 0)
262 $row = rg_sql_fetch_array($res);
263 rg_sql_free_result($res);
264
265 if ($data['id'] == 0)
266 $data['id'] = $row['id'];
267 $key = 'wh' . '::' . $uid . '::' . 'list'
268 . '::' . $data['id'];
269 rg_cache_merge($key, $data, RG_SOCKET_NO_WAIT);
270
271 $ret['ok'] = 1;
272 break;
273 }
274
275 rg_log_exit();
276 rg_prof_end('wh_add');
277 return $ret;
278 }
279
280 /*
281 * Removes a list of webhooks
282 */
283 function rg_wh_remove($db, $uid, $list)
284 {
285 rg_prof_start('wh_remove');
286 rg_log_enter('wh_remove');
287
288 $ret = array('ok' => 0);
289 while (1) {
290 if (empty($list)) {
291 rg_wh_set_error('you did not select anything');
292 break;
293 }
294
295 $my_list = array();
296 foreach ($list as $id => $junk)
297 $my_list[] = sprintf("%u", $id);
298
299 $params = array('uid' => $uid);
300 $sql_list = implode(', ', $my_list);
301
302 $sql = 'DELETE FROM webhooks'
303 . ' WHERE uid = @@uid@@'
304 . ' AND id IN (' . $sql_list . ')';
305 $res = rg_sql_query_params($db, $sql, $params);
306 if ($res === FALSE) {
307 rg_wh_set_error('cannot remove webhooks');
308 break;
309 }
310 rg_sql_free_result($res);
311
312 foreach ($my_list as $junk => $id) {
313 $key = 'wh' . '::' . $uid
314 . '::' . 'list' . '::' . $id;
315 rg_cache_unset($key, RG_SOCKET_NO_WAIT);
316 }
317
318 $ret['ok'] = 1;
319 break;
320 }
321
322 rg_log_exit();
323 rg_prof_end('wh_remove');
324 return $ret;
325 }
326
327 /*
328 * Extract vars from request
329 */
330 function rg_wh_fill_vars(&$rg)
331 {
332 global $rg_wh_plugins;
333
334 $ret = FALSE;
335 while (1) {
336 $t = $rg['wh']['htype'];
337
338 if (!isset($rg_wh_plugins[$t])) {
339 $errmsg[] = rg_template('user/settings/wh/invalid_htype',
340 $rg, TRUE /*xss*/);
341 break;
342 }
343
344 if (isset($rg_wh_plugins[$t]['fill_vars'])) {
345 $rg_wh_plugins[$t]['fill_vars']($rg);
346 break;
347 }
348
349 $ret = TRUE;
350 break;
351 }
352
353 return $ret;
354 }
355
356 /*
357 * Validate parameters
358 */
359 function rg_wh_validate_vars($rg, &$errmsg)
360 {
361 global $rg_wh_plugins;
362
363 $ret = FALSE;
364 while (1) {
365 $t = $rg['wh']['htype'];
366
367 if (!isset($rg_wh_plugins[$t])) {
368 $errmsg[] = rg_template('user/settings/wh/invalid_htype',
369 $rg, TRUE /*xss*/);
370 break;
371 }
372
373 if (isset($rg_wh_plugins[$t]['validate_vars'])) {
374 $r = $rg_wh_plugins[$t]['validate_vars']($rg, $errmsg);
375 if ($r !== TRUE)
376 break;
377 }
378
379 $ret = TRUE;
380 break;
381 }
382
383 return $ret;
384 }
385
386 /*
387 * Generic add_form function
388 */
389 function rg_wh_add_form(&$rg)
390 {
391 global $rg_wh_plugins;
392
393 while (1) {
394 $t = $rg['wh']['htype'];
395
396 if (!isset($rg_wh_plugins[$t]))
397 break;
398
399 if (isset($rg_wh_plugins[$t]['add_form'])) {
400 $rg_wh_plugins[$t]['add_form']($rg);
401 break;
402 }
403
404 break;
405 }
406 }
407
408 /*
409 * Generic default_paras function
410 */
411 function rg_wh_default_paras(&$rg)
412 {
413 global $rg_wh_plugins;
414
415 while (1) {
416 $t = $rg['wh']['htype'];
417
418 if (!isset($rg_wh_plugins[$t]))
419 break;
420
421 if (isset($rg_wh_plugins[$t]['default_paras'])) {
422 $rg_wh_plugins[$t]['default_paras']($rg);
423 break;
424 }
425
426 break;
427 }
428 }
429
430 /*
431 * Generic hints add function
432 */
433 function rg_wh_fill_hints(&$rg, &$hints)
434 {
435 global $rg_wh_plugins;
436
437 while (1) {
438 $t = $rg['wh']['htype'];
439
440 if (!isset($rg_wh_plugins[$t]))
441 break;
442
443 if (isset($rg_wh_plugins[$t]['fill_hints'])) {
444 $rg_wh_plugins[$t]['fill_hints']($rg, $hints);
445 break;
446 }
447
448 break;
449 }
450 }
451
452 /*
453 * Returns a HTML list with possible htypes
454 */
455 function rg_wh_htypes($rg)
456 {
457 global $rg_wh_plugins;
458
459 return rg_template_table('user/settings/wh/plugins_list',
460 $rg_wh_plugins, $rg);
461 }
462
463 ?>
File inc/wh/http.inc.php added (mode: 100644) (index 0000000..c142d9c)
1 <?php
2 require_once($INC . "/util.inc.php");
3 require_once($INC . "/log.inc.php");
4 require_once($INC . "/sql.inc.php");
5 require_once($INC . "/prof.inc.php");
6 require_once($INC . "/wh/core.inc.php");
7
8 $rg_wh_http_functions = array(
9 10000 => 'rg_wh_http_send',
10 10001 => 'rg_wh_http_send_one'
11 );
12 rg_event_register_functions($rg_wh_http_functions);
13
14 /*
15 * Helper for rg_wh_send
16 */
17 function rg_wh_http_send_one($db, $event)
18 {
19 rg_prof_start('wh_http_send_helper');
20
21 $wh = &$event['wh'];
22 $info = &$wh['info'];
23
24 rg_log_ml('wh_send_one: event: ' . print_r($event, TRUE));
25 if ($event['debug'] == 1)
26 rg_log_ml('XXX DEBUG: wh[data]=' . print_r($wh['data'], TRUE));
27
28 $headers = array();
29
30 while (!empty($info['key'])) {
31 if ($info['idata']['itype'] == 0)
32 break;
33
34 $headers[] = 'X-RocketGit-Signature: '
35 . hash_hmac('sha512', $wh['data'], $info['key']);
36 break;
37 }
38
39 $c = curl_init($info['url']);
40 curl_setopt($c, CURLOPT_POST, 1);
41 curl_setopt($c, CURLOPT_POSTFIELDS, $wh['data']);
42 curl_setopt($c, CURLOPT_RETURNTRANSFER, TRUE);
43 curl_setopt($c, CURLOPT_FOLLOWLOCATION, 1);
44 curl_setopt($c, CURLOPT_HEADER, 1);
45 curl_setopt($c, CURLOPT_HTTPHEADER, $headers);
46 curl_setopt($c, CURLOPT_USERAGENT, 'RocketGit WebHook');
47 curl_setopt($c, CURLOPT_CONNECTTIMEOUT, 30);
48 curl_setopt($c, CURLOPT_ENCODING, ''); // => use all methods
49 curl_setopt($c, CURLOPT_VERBOSE, TRUE);
50 curl_setopt($c, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
51 curl_setopt($c, CURLOPT_CERTINFO, TRUE);
52 // Else, a second wh, without client cert can use the connection:
53 curl_setopt($c, CURLOPT_FORBID_REUSE, TRUE);
54
55 $err = @fopen('php://temp', 'w');
56 if ($err !== FALSE)
57 curl_setopt($c, CURLOPT_STDERR, $err);
58
59 if (strchr($info['idata']['flags'], 'I'))
60 curl_setopt($c, CURLOPT_SSL_VERIFYPEER, FALSE);
61
62 if (strchr($info['idata']['flags'], 'H'))
63 curl_setopt($c, CURLOPT_SSL_VERIFYHOST, 0); // TODO verify 0 is a good value (default 2)
64
65 $ret = FALSE;
66 $cert_file = FALSE;
67 $ca_file = FALSE;
68 while (1) {
69 $xid = rg_id(8);
70
71 if (!empty($info['idata']['client_cert'])) {
72 rg_log('DEBUG: will provide client cert...');
73 $f = 'wh-' . $event['ui']['uid'] . '-' . $wh['id'] . '-client-' . $xid;
74 $cert_file = rg_tmp_file($f, $info['idata']['client_cert']);
75 if ($cert_file === FALSE)
76 break;
77
78 curl_setopt($c, CURLOPT_SSLCERT, $cert_file);
79 } else {
80 rg_log('DEBUG: will NOT provide client cert...');
81 // TODO: Somehow, without next line, the cert is still sent!
82 curl_setopt($c, CURLOPT_SSLCERT, FALSE);
83 }
84
85 if (!empty($info['idata']['client_ca_cert'])) {
86 $f = 'wh-' . $event['ui']['uid'] . '-' . $wh['id'] . '-ca-' . $xid;
87 $ca_file = rg_tmp_file($f, $info['idata']['client_ca_cert']);
88 if ($ca_file === FALSE)
89 break;
90
91 curl_setopt($c, CURLOPT_CAINFO, $ca_file);
92 } else {
93 curl_setopt($c, CURLOPT_CAINFO, FALSE);
94 }
95
96 $r = curl_exec($c);
97
98 if ($err !== FALSE) {
99 rewind($err);
100 $xerr = @fread($err, 16 * 4096);
101 fclose($err);
102 rg_log_ml($xerr);
103 }
104
105 if ($r === FALSE) {
106 rg_log('Cannot execute curl: ' . curl_error($c));
107 $_info = curl_getinfo($c);
108 rg_log_ml('Debug: ' . print_r($_info, TRUE));
109
110 if ($event['debug'] == 1)
111 rg_cache_set('DEBUG::' . $event['ui']['uid']
112 . '::webhooks::' . $info['opaque']
113 . '::' . $wh['id'],
114 'BAD', RG_SOCKET_NO_WAIT);
115 break;
116 }
117
118 $xerr = &$r;
119 rg_log_ml('Answer: ' . print_r($r, TRUE));
120
121 if ($event['debug'] == 1)
122 rg_cache_set('DEBUG::' . $event['ui']['uid']
123 . '::webhooks::' . $info['opaque']
124 . '::' . $wh['id'],
125 'OK', RG_SOCKET_NO_WAIT);
126
127 $ret = array();
128 break;
129 }
130 curl_close($c);
131
132 if ($cert_file !== FALSE)
133 @unlink($cert_file);
134
135 if ($ca_file !== FALSE)
136 @unlink($ca_file);
137
138 rg_wh_set_last_output($db, $event['ui']['uid'], $wh['id'],
139 substr($xerr, 0, 4096));
140
141 rg_prof_end('wh_http_send_helper');
142 return $ret;
143 }
144
145 /*
146 * Generic function which will be called when a webhook must be posted
147 */
148 function rg_wh_http_send($db, $event)
149 {
150 rg_prof_start('wh_http_send');
151
152 rg_log_ml('wh_http_send: event: ' . print_r($event, TRUE));
153
154 // First, get the list of hooks
155 $r = rg_wh_list($db, $event['ui']['uid']);
156 if ($r['ok'] != 1)
157 return FALSE;
158
159 // Filter them by repo_id
160 $real_list = array();
161 foreach ($r['list'] as $id => $info) {
162 if (($info['repo_id'] > 0)
163 && ($event['ri']['repo_id'] != $info['repo_id'])) {
164 rg_log('hook is not for this repo');
165 continue;
166 }
167
168 // If the web hook does not contain our type, skip it
169 if (!strchr($info['events'], $event['wh_event'])) {
170 rg_log($event['wh_event'] . ' is not present in ' . $info['events']);
171 continue;
172 }
173
174 $real_list[] = $id;
175 }
176
177 // Something to do?
178 if (empty($real_list))
179 return array();
180
181 $cache = array();
182 $wh = array();
183 $ret = array();
184 foreach ($real_list as $id) {
185 $wh['info'] = $r['list'][$id];
186 $wh['id'] = $id;
187
188 if (!isset($wh['info']['idata']['itype'])) {
189 rg_log_ml('wh[info]: ' . print_r($wh['info'], TRUE));
190 rg_internal_error('DEBUG: itype is not present');
191 }
192 $type = $wh['info']['idata']['itype'];
193 if (!isset($cache[$type])) {
194 switch ($type) {
195 case 0: // http post
196 $cache[$type] = &$event['wh_data'];
197 break;
198
199 case 1: // php serialize
200 $cache[$type] = serialize($event['wh_data']);
201 break;
202
203 default:
204 rg_log('Unknown type ' . $type . '!');
205 $cache[$type] = '';
206 break;
207 }
208 }
209 $wh['data'] = $cache[$type];
210
211 $x = $event;
212 $x['category'] = 10001;
213 $x['wh'] = $wh;
214 $ret[] = $x;
215 }
216
217 rg_prof_end('wh_http_send');
218 return $ret;
219 }
220
221 $rg_wh_http_itypes = array(
222 0 => 'HTTP (application/x-www-form-urlencoded)',
223 1 => 'PHP serialize'
224 );
225 /*
226 * Transforms a type into HTML select
227 */
228 function rg_wh_http_select_itype($itype)
229 {
230 global $rg_wh_http_itypes;
231
232 $ret = '<select name="wh::idata::itype" id="itype">';
233 foreach ($rg_wh_http_itypes as $_itype => $name) {
234 $add = '';
235 if ($_itype == $itype)
236 $add = ' selected';
237
238 $ret .= '<option value="' . $_itype . '"' . $add . '>'
239 . $name
240 . '</option>' . "\n";
241 }
242 $ret .= '</select>' . "\n";
243
244 return $ret;
245 }
246
247 /*
248 * Returns type text based on id
249 */
250 function rg_wh_http_itype($itype)
251 {
252 global $rg_wh_http_itypes;
253
254 foreach ($rg_wh_http_itypes as $_itype => $name)
255 if ($_itype == $itype)
256 return $name;
257 }
258
259 $rg_wh_http_flags = array(
260 'I' => 'Do not verify the server certificate',
261 'H' => 'Do not verify the server hostname'
262 );
263 /*
264 * Generates flags list
265 */
266 function rg_wh_http_check_flags($flags)
267 {
268 global $rg_wh_http_flags;
269
270 $ret = '';
271 $br = '';
272 foreach ($rg_wh_http_flags as $id => $name) {
273 $add = '';
274 if (strchr($flags, $id))
275 $add = ' checked="checked"';
276
277 $ret .= $br
278 . '<input type="checkbox" name="wh::idata::flags[' . $id . ']"'
279 . ' id="flags-' . $id . '"'
280 . $add . ' />'
281 . "\n"
282 . '<label for="flags-' . $id . '">' . $name . '</label>';
283 $br = '<br />' . "\n";
284 }
285
286 return $ret;
287 }
288
289 /*
290 * Generates a flags list as text
291 */
292 function rg_wh_http_flags($flags)
293 {
294 global $rg_wh_http_flags;
295
296 $a = array();
297 foreach ($rg_wh_http_flags as $id => $name) {
298 if (strchr($flags, $id))
299 $a[] = $name;
300 }
301
302 return implode(', ', $a);
303 }
304
305 /*
306 * Some cosmetics applied to a webhook
307 */
308 function rg_wh_http_cosmetic(&$row)
309 {
310 // TODO DEBUG remove the following 2 lines
311 if (!isset($row['idata']['itype']))
312 $row['idata']['itype'] = 0;
313
314 $row['idata']['itype_text'] = rg_wh_http_itype($row['idata']['itype']);
315
316 $row['idata']['flags_text'] = rg_wh_http_flags($row['idata']['flags']);
317
318 $row['idata']['HTML:client_cert_short'] =
319 rg_xss_safe(rg_cert_short($row['idata']['client_cert']));
320
321 $row['idata']['HTML:client_ca_cert_short'] =
322 rg_xss_safe(rg_cert_short($row['idata']['client_ca_cert']));
323
324 $row['idata']['HTML:private'] = rg_template(
325 'user/settings/wh/http/show.html', $row['idata'], TRUE /*xss*/);
326 }
327
328 /*
329 * Fill private data based on parameters passed
330 */
331 function rg_wh_http_fill_vars(&$rg)
332 {
333 $a = array();
334 $a['itype'] = rg_var_uint('wh::idata::itype');
335 $a['client_cert'] = trim(rg_var_str('wh::idata::client_cert'));
336 $a['client_ca_cert'] = trim(rg_var_str('wh::idata::client_ca_cert'));
337 $a['flags'] = rg_var_a2s('wh::idata::flags');
338 $rg['wh']['idata'] = $a;
339 }
340
341 /*
342 * Validate parameters passed
343 */
344 function rg_wh_http_validate_vars($rg, &$errmsg)
345 {
346 global $rg_wh_http_itypes;
347 global $rg_wh_http_flags;
348
349 $a = $rg['wh'];
350
351 $ret = FALSE;
352 while (1) {
353 if ((strncasecmp($a['url'], 'http', 4) != 0)
354 && (strncasecmp($a['url'], 'https', 5) != 0)) {
355 $errmsg[] = rg_template('user/settings/wh/http/inv_proto.txt',
356 $rg, TRUE /*xss*/);
357 break;
358 }
359
360 if (!isset($rg_wh_http_itypes[$a['idata']['itype']])) {
361 $errmsg[] = rg_template('user/settings/wh/http/inv_type.txt',
362 $rg, TRUE /*xss*/);
363 break;
364 }
365
366 $all_ok = TRUE;
367 $len = strlen($a['idata']['flags']);
368 for ($i = 0; $i < $len; $i++) {
369 $f = $a['idata']['flags'][$i];
370 if (!isset($rg_wh_http_flags[$f])) {
371 $all_ok = FALSE;
372 $errmsg[] = rg_template('user/settings/wh/http/inv_flag.txt',
373 $rg, TRUE /*xss*/);
374 break;
375 }
376 }
377 if (!$all_ok)
378 break;
379
380 $ret = TRUE;
381 break;
382 }
383
384 return $ret;
385 }
386
387 /*
388 * Transfers to $rg the custom parameters - used when showing the form
389 */
390 function rg_wh_http_add_form(&$rg)
391 {
392 // TODO DEBUG remove this
393 if (!isset($rg['wh']['idata']['itype']))
394 $rg['wh']['idata']['itype'] = 0;
395 $rg['HTML:select_itype'] = rg_wh_http_select_itype($rg['wh']['idata']['itype']);
396 $rg['HTML:check_flags'] = rg_wh_http_check_flags($rg['wh']['idata']['flags']);
397
398 $rg['HTML:custom_form'] = rg_template('user/settings/wh/http/form.html',
399 $rg, TRUE /*xss*/);
400 }
401
402 /*
403 * Add custom hints
404 */
405 function rg_wh_http_fill_hints($rg, &$hints)
406 {
407 $hints[]['HTML:hint'] = rg_template('user/settings/wh/http/hints.html',
408 $rg, TRUE /*xss*/);
409 }
410
411 /*
412 * Loads default paras for a form
413 */
414 function rg_wh_http_default_paras(&$rg)
415 {
416 $a = array();
417 $a['itype'] = 0;
418 $a['flags'] = '';
419 $a['client_cert'] = '';
420 $a['client_ca_cert'] = '';
421 $rg['wh']['idata'] = $a;
422 }
423
424
425
426 $rg_wh_plugins['http'] = array(
427 'htype' => 'http',
428 'description' => 'HTTP[S]',
429 'cosmetic' => 'rg_wh_http_cosmetic',
430 'html_form' => 'rg_wh_http_form',
431 'fill_vars' => 'rg_wh_http_fill_vars',
432 'validate_vars' => 'rg_wh_http_validate_vars',
433 'add_form' => 'rg_wh_http_add_form',
434 'default_paras' => 'rg_wh_http_default_paras',
435 'fill_hints' => 'rg_wh_http_fill_hints'
436 );
437
438 ?>
File root/index.php changed (mode: 100644) (index 5c96d93..1ce867d)
... ... $user = ""; $repo = ""; $organization = 0; // TODO: those are really used?
73 73 //rg_log_ml("rg: " . print_r($rg, TRUE)); //rg_log_ml("rg: " . print_r($rg, TRUE));
74 74
75 75 $rg['ua'] = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : ""; $rg['ua'] = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : "";
76 $rg['ip'] = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : "";
77 if (strncasecmp($rg['ip'], "::ffff:", 7) == 0)
78 $rg['ip'] = substr($rg['ip'], 7);
76 $rg['ip'] = isset($_SERVER['REMOTE_ADDR']) ? rg_fix_ip($_SERVER['REMOTE_ADDR']) : '';
79 77 rg_log("DEBUG: _REQUEST: " . rg_array2string($_REQUEST)); rg_log("DEBUG: _REQUEST: " . rg_array2string($_REQUEST));
80 78 rg_log("DEBUG: _COOKIE: " . rg_array2string($_COOKIE)); rg_log("DEBUG: _COOKIE: " . rg_array2string($_COOKIE));
81 79 rg_log($rg['ip'] . " ver=$rocketgit_version"); rg_log($rg['ip'] . " ver=$rocketgit_version");
File root/themes/default/download-vm.html changed (mode: 100644) (index 9187043..50bd81d)
31 31 </div> </div>
32 32 <br /> <br />
33 33
34 * download qemu image (109 MiB):<br />
34 * download qemu image (~130 MiB):<br />
35 35 <div class="xcode"> <div class="xcode">
36 36 wget -c -O /var/lib/libvirt/images/rocketgit1-master.qcow2.xz wget -c -O /var/lib/libvirt/images/rocketgit1-master.qcow2.xz
37 37 http://downloads.rocketgit.com/vm/last/rocketgit1.qcow2.xz http://downloads.rocketgit.com/vm/last/rocketgit1.qcow2.xz
 
129 129 * download VMX config file (2 KiB) from * download VMX config file (2 KiB) from
130 130 <a href="http://downloads.rocketgit.com/vm/rocketgit1-i386.vmx">http://downloads.rocketgit.com/vm/rocketgit1-i386-esx.vmx</a><br /> <a href="http://downloads.rocketgit.com/vm/rocketgit1-i386.vmx">http://downloads.rocketgit.com/vm/rocketgit1-i386-esx.vmx</a><br />
131 131
132 * download VMDK image (164 MiB) from
132 * download VMDK image (~200 MiB) from
133 133 <a href="http://downloads.rocketgit.com/vm/last/rocketgit1-i386.vmdk.zip">http://downloads.rocketgit.com/vm/last/rocketgit1-i386.vmdk.zip</a> <a href="http://downloads.rocketgit.com/vm/last/rocketgit1-i386.vmdk.zip">http://downloads.rocketgit.com/vm/last/rocketgit1-i386.vmdk.zip</a>
134 134 in the same folder as the previous file<br /> in the same folder as the previous file<br />
135 135
 
170 170 * download VMX config file (2 KiB) from * download VMX config file (2 KiB) from
171 171 <a href="http://downloads.rocketgit.com/vm/rocketgit1-i386.vmx">http://downloads.rocketgit.com/vm/rocketgit1-i386.vmx</a><br /> <a href="http://downloads.rocketgit.com/vm/rocketgit1-i386.vmx">http://downloads.rocketgit.com/vm/rocketgit1-i386.vmx</a><br />
172 172
173 * download VMDK image (164 MiB) from
173 * download VMDK image (~200 MiB) from
174 174 <a href="http://downloads.rocketgit.com/vm/rocketgit1-i386.vmdk.zip">http://downloads.rocketgit.com/vm/last/rocketgit1-i386.vmdk.zip</a><br /> <a href="http://downloads.rocketgit.com/vm/rocketgit1-i386.vmdk.zip">http://downloads.rocketgit.com/vm/last/rocketgit1-i386.vmdk.zip</a><br />
175 175
176 176 * decompress the image<br /> * decompress the image<br />
 
212 212 * download the OVF file (12 KiB) from * download the OVF file (12 KiB) from
213 213 <a href="http://downloads.rocketgit.com/vm/rocketgit1-i386.ovf">http://downloads.rocketgit.com/vm/rocketgit1-i386.ovf</a><br /> <a href="http://downloads.rocketgit.com/vm/rocketgit1-i386.ovf">http://downloads.rocketgit.com/vm/rocketgit1-i386.ovf</a><br />
214 214
215 * download the compressed VMDK image (164 MiB) from
215 * download the compressed VMDK image (~200 MiB) from
216 216 <a href="http://downloads.rocketgit.com/vm/rocketgit1-i386.vmdk.zip">http://downloads.rocketgit.com/vm/last/rocketgit1-i386.vmdk.zip</a><br /> <a href="http://downloads.rocketgit.com/vm/rocketgit1-i386.vmdk.zip">http://downloads.rocketgit.com/vm/last/rocketgit1-i386.vmdk.zip</a><br />
217 217
218 218 * decompress the image<br /> * decompress the image<br />
File root/themes/default/download.html changed (mode: 100644) (index d790ab3..e0a1dfe)
14 14 <div class="island_cell"> <div class="island_cell">
15 15 <div class="island"> <div class="island">
16 16 <div class="island_title">Fedora</div> <div class="island_title">Fedora</div>
17 If you are running a Fedora server, just add DinoRepo to your system
17 If you are running a Fedora distribution,
18 just add DinoRepo to your system
18 19 and install the rocketgit package:<br /> and install the rocketgit package:<br />
19 20 <div class="xcode"> <div class="xcode">
20 21 yum install http://kernel.embedromix.ro/dinorepo-0.0.10-1.noarch.rpm<br /> yum install http://kernel.embedromix.ro/dinorepo-0.0.10-1.noarch.rpm<br />
 
40 41 <div class="island_cell"> <div class="island_cell">
41 42 <div class="island"> <div class="island">
42 43 <div class="island_title">Virtual machines images</div> <div class="island_title">Virtual machines images</div>
43 If you want to test RocketGit in a virtual environment,
44 If you want to run RocketGit in a virtual environment,
44 45 follow this <a href="/op/download/vm">link</a>. follow this <a href="/op/download/vm">link</a>.
45 46 We provide qemu/KVM, VMware and VirtualBox images, the size We provide qemu/KVM, VMware and VirtualBox images, the size
46 being under 180MiB.
47 being under 200MiB.
47 48 </div> </div>
48 49 </div> </div>
49 50 </div> </div>
File root/themes/default/hints/list/between.html deleted (index 3fc714a..0000000)
1 <br />
File root/themes/default/hints/list/header.html changed (mode: 100644) (index 7f3462e..72d650a)
1 1 <div class="hints"> <div class="hints">
2 <b>Hints:</b><br />
2 <b>Hints:</b>
File root/themes/default/hints/repo/anon_push.html changed (mode: 100644) (index ea83b2c..524a1d9)
1 <br />
1 2 You are allowed to anonymously push to this repository.<br /> You are allowed to anonymously push to this repository.<br />
2 3 This means that your pushed commits will automatically be transformed into a This means that your pushed commits will automatically be transformed into a
3 4 pull request:<br /> pull request:<br />
File root/themes/default/hints/repo/bug/add.html changed (mode: 100644) (index a986adb..ad29742)
1 <br />
1 2 Labels are a powerful way to assign some properties to a bug.<br /> Labels are a powerful way to assign some properties to a bug.<br />
2 When you search for a bug, you can filter also by labels.
3 When you search for a bug, you can filter also by labels.<br />
File root/themes/default/hints/repo/client_win.html changed (mode: 100644) (index 5c7b9d3..dd7d81f)
1 <br />
1 2 Recommended client software:<br /> Recommended client software:<br />
2 3 <ul> <ul>
3 4 <li><a href="http://msysgit.github.com/">msysgit</a></li> <li><a href="http://msysgit.github.com/">msysgit</a></li>
File root/themes/default/hints/repo/clone_git.html changed (mode: 100644) (index fa41883..5acd961)
1 <br />
1 2 Clone this repository using git:<br /> Clone this repository using git:<br />
2 3 <div class="xcode"> <div class="xcode">
3 4 git clone @@git@@ local_dir<br /> git clone @@git@@ local_dir<br />
File root/themes/default/hints/repo/clone_owner.html changed (mode: 100644) (index 1f91434..8ba93af)
1 <br />
1 2 If you have the project locally, but not versioned with Git:<br /> If you have the project locally, but not versioned with Git:<br />
2 3 <div class="xcode"> <div class="xcode">
3 4 cd local_project_dir<br /> cd local_project_dir<br />
File root/themes/default/hints/repo/clone_ssh.html changed (mode: 100644) (index 424f43d..a6b4ab2)
1 <br />
1 2 Clone this repository using ssh (do not forget to upload a key first):<br /> Clone this repository using ssh (do not forget to upload a key first):<br />
2 3 <div class="xcode"> <div class="xcode">
3 4 git clone @@ssh@@ local_dir<br /> git clone @@ssh@@ local_dir<br />
File root/themes/default/hints/repo/create_repo.html changed (mode: 100644) (index d500d47..8594d6d)
1 <br />
1 2 "Max commit size" is an optional protection against committing unwanted types "Max commit size" is an optional protection against committing unwanted types
2 of files (binaries, images etc.).
3 of files (binaries, images etc.).<br />
File root/themes/default/hints/repo/edit_repo_path_rights.html changed (mode: 100644) (index 5601fdb..a01b3a5)
1 <br />
1 2 Examples: Examples:
2 3 <table summary="examples"> <table summary="examples">
3 4 <tr> <tr>
File root/themes/default/hints/repo/edit_repo_refs_rights.html changed (mode: 100644) (index b0123fd..298759a)
1 <br />
1 2 Bad whitespace: if checked, commits with mixed tabs and spaces, trailing Bad whitespace: if checked, commits with mixed tabs and spaces, trailing
2 3 spaces/tabs etc. will be allowed.<br /> spaces/tabs etc. will be allowed.<br />
3 4 <br /> <br />
File root/themes/default/hints/repo/edit_repo_rights.html changed (mode: 100644) (index b22a9ef..a254abe)
1 <br />
1 2 Here you can add generic rights for your co-workers / friends.<br /> Here you can add generic rights for your co-workers / friends.<br />
File root/themes/default/hints/repo/edit_rights.html changed (mode: 100644) (index 94734fe..f710ae3)
1 <br />
1 2 You do not have to grant yourself rights. You do not have to grant yourself rights.
2 3 You can observe the autogenerated rule that grants you maximum rights.<br /> You can observe the autogenerated rule that grants you maximum rights.<br />
3 4 <br /> <br />
File root/themes/default/hints/repo/git_setup.html changed (mode: 100644) (index 5d6e8cf..4124678)
1 <br />
1 2 Before first commit, do not forget to setup your git environment:<br /> Before first commit, do not forget to setup your git environment:<br />
2 3 <div class="xcode"> <div class="xcode">
3 4 git config --global user.name "your name here"<br /> git config --global user.name "your name here"<br />
File root/themes/default/hints/repo/lock_repo.html changed (mode: 100644) (index 9872dc2..2172fa5)
1 <br />
1 2 When a repository is locked, only the users that have "Lock" rights will be When a repository is locked, only the users that have "Lock" rights will be
2 3 able to push into it.<br /> able to push into it.<br />
3 4 You may want to lock a repo to repair bad pushes.<br /> You may want to lock a repo to repair bad pushes.<br />
File root/themes/default/hints/repo/merge.html changed (mode: 100644) (index 131d1fb..e580a80)
1 <br />
1 2 How to merge on your machine?<br /> How to merge on your machine?<br />
2 3
3 4 <div class="xcode"> <div class="xcode">
File root/themes/default/hints/ssh/cmds.html changed (mode: 100644) (index 866c5a9..667e755)
1 <br />
1 2 You can use ssh to quickly find information about your RocketGit account.<br /> You can use ssh to quickly find information about your RocketGit account.<br />
2 3 Commands:<br /> Commands:<br />
3 4 <ul> <ul>
File root/themes/default/hints/ssh/key.html changed (mode: 100644) (index fb1a7dc..145cef9)
1 <br />
1 2 How to create a SSH key for RocketGit:<br /> How to create a SSH key for RocketGit:<br />
2 3 <div class="xcode"> <div class="xcode">
3 4 ssh-keygen -t rsa -b 4096 -o -C "Key for RocketGit" -f ~/.ssh/rocketgit1<br /> ssh-keygen -t rsa -b 4096 -o -C "Key for RocketGit" -f ~/.ssh/rocketgit1<br />
File root/themes/default/index.html changed (mode: 100644) (index 963cc24..1210df9)
63 63 <i>Git was created by Linus Torvalds.</i><br /> <i>Git was created by Linus Torvalds.</i><br />
64 64 rocketgit.com site is operated by Embedromix SRL,<br /> rocketgit.com site is operated by Embedromix SRL,<br />
65 65 RO13505234, J08/979/2000, Brasov, Romania.<br /> RO13505234, J08/979/2000, Brasov, Romania.<br />
66 All data is stored in Germany.
66 All data is stored in Germany only.
67 67 </div> </div>
68 68 </div> <!-- footer --> </div> <!-- footer -->
69 69
File root/themes/default/main.css changed (mode: 100644) (index af15e47..35b01c4)
... ... table {
21 21 background-color: #eeeeee; background-color: #eeeeee;
22 22 color: #000000; color: #000000;
23 23 padding: 1px; padding: 1px;
24 margin-top: 5px;
25 margin-left: auto;
26 margin-right: auto;
24 xxx-margin-left: auto;
25 xxx-margin-right: auto;
26 width: 100%;
27 27 } }
28 28
29 29 th, td { th, td {
 
... ... legend { padding: 0px 2pt; }
120 120
121 121 .menus { .menus {
122 122 display: flex; display: flex;
123 flex-flow: column nowrap;
124 align-items: stretch;
123 125 } }
124 126
125 127 .menu { .menu {
126 128 background-color: #999; background-color: #999;
127 129 display: flex; display: flex;
128 130 flex-flow: row nowrap; flex-flow: row nowrap;
129 flex-grow: 0;
130 131 } }
131 .menu ul { list-style-type: none; display: flex; }
132 .menu ul {
133 list-style-type: none;
134 display: flex;
135 }
132 136 .menu ul li { .menu ul li {
133 137 display: flex; display: flex;
134 138 padding: 2px 0px; padding: 2px 0px;
 
... ... legend { padding: 0px 2pt; }
171 175
172 176
173 177 #container { #container {
174 width: 100%;
178 xxx-width: 100%;
175 179 height: 100%; height: 100%;
176 180 display: flex; display: flex;
177 181 flex-flow: column nowrap; flex-flow: column nowrap;
178 justify-content: space-between;
179 xxx-align-content: center;
180 182 align-items: stretch; align-items: stretch;
181 183 } }
182 184
 
... ... legend { padding: 0px 2pt; }
184 186 width: 80%; width: 80%;
185 187 margin-top: 12pt; margin-top: 12pt;
186 188 margin-bottom: 12pt; margin-bottom: 12pt;
187 margin-left: auto;
188 margin-right: auto;
189 189 line-height: 120%; line-height: 120%;
190 text-align: center;
191 190 display: flex; display: flex;
192 191 flex-flow: column nowrap; flex-flow: column nowrap;
193 192 flex-grow: 1; flex-grow: 1;
193 align-self: center;
194 align-items: stretch;
194 195 } }
195 196
196 197 #header { #header {
 
... ... legend { padding: 0px 2pt; }
253 254 border: 1px solid #999998; border: 1px solid #999998;
254 255 padding: 5pt; padding: 5pt;
255 256 border-radius: 4px 4px 4px 4px; border-radius: 4px 4px 4px 4px;
256 display: inline-block;
257 display: flex;
258 flex-flow: column nowrap;
259 align-self: center;
257 260 } }
258 261
259 262 .formarea_title { .formarea_title {
 
... ... legend { padding: 0px 2pt; }
273 276 margin-top: 20px; margin-top: 20px;
274 277 } }
275 278
276 .rg_wh_list {}
279 .wh_list {}
280
281 .wh_plugins_list {}
277 282
278 283 .blob_title { .blob_title {
279 284 font-size: 11pt; font-size: 11pt;
 
... ... legend { padding: 0px 2pt; }
447 452 margin-top: 5px; margin-top: 5px;
448 453 padding: 5px; padding: 5px;
449 454 box-shadow: 0px 2px 3px #666666; box-shadow: 0px 2px 3px #666666;
455 display: flex;
456 flex-flow: row nowrap;
457 flex-grow: 0;
450 458 } }
451 459
452 460 .error { .error {
 
... ... legend { padding: 0px 2pt; }
476 484 .islands { .islands {
477 485 text-align: left; text-align: left;
478 486 font-size: 13pt; font-size: 13pt;
479 xxx-width: 70%;
480 margin-left: auto;
481 margin-right: auto;
482 487 } }
483 488
484 489 .island_row { .island_row {
 
... ... legend { padding: 0px 2pt; }
529 534 .gravatar { .gravatar {
530 535 display: inline; display: inline;
531 536 } }
537
538 .small {
539 margin: 0;
540 font-size: 7pt;
541 line-height: 8pt;
542 }
543
File root/themes/default/user/hints/totp.html changed (mode: 100644) (index 576e573..186f1fb)
1 <br />
1 2 You are <b>not</b> enrolled in You are <b>not</b> enrolled in
2 3 <a href="https://en.wikipedia.org/wiki/Time-based_One-time_Password_Algorithm" target="_blank"> <a href="https://en.wikipedia.org/wiki/Time-based_One-time_Password_Algorithm" target="_blank">
3 4 two-factor authentication two-factor authentication
4 5 </a> </a>
5 6 for extra security. for extra security.
6 Go to <a href="/op/settings/totp/info">Settings / Login tokens</a> to activate it.
7 Go to <a href="/op/settings/totp/info">Settings / Login tokens</a> to
8 activate it.<br />
File root/themes/default/user/settings/totp/hints.html changed (mode: 100644) (index 7b5182e..4bdc419)
1 <br />
1 2 Login token feature implements two-factor authentication (2FA) using Login token feature implements two-factor authentication (2FA) using
2 3 <a href="https://en.wikipedia.org/wiki/Time-based_One-time_Password_Algorithm" target="_blank"> <a href="https://en.wikipedia.org/wiki/Time-based_One-time_Password_Algorithm" target="_blank">
3 4 TOTP (Time-based One-time Password Algorithm) TOTP (Time-based One-time Password Algorithm)
 
... ... You may enroll multiple devices if needed. Use the 'name' field to distinguish
43 44 between them.<br /> between them.<br />
44 45 <br /> <br />
45 46 If you loose your device, login with a scratch code and delete all enrollments If you loose your device, login with a scratch code and delete all enrollments
46 done with the lost device.
47 done with the lost device.<br />
File root/themes/default/user/settings/totp/sc/hints.html changed (mode: 100644) (index 7b3b10b..70f953d)
1 <br />
1 2 You can print the list of generated scratch codes and keep the paper into your You can print the list of generated scratch codes and keep the paper into your
2 wallet or save them in a password manager on your phone/tablet/PC.
3 wallet or save them in a password manager on your phone/tablet/PC.<br />
File root/themes/default/user/settings/wh/add_edit.html changed (mode: 100644) (index c216628..da7c0c4)
4 4
5 5 @@errmsg@@ @@errmsg@@
6 6
7 <form method="post" action="/op/settings/wh/add">
7 <form method="post" action="/op/settings/wh/@@if(@@wh::id@@ == 0){{add}}{{edit/@@wh::id@@}}">
8 8 <input type="hidden" name="add" value="1" /> <input type="hidden" name="add" value="1" />
9 9 <input type="hidden" name="wh::htype" value="@@wh::htype@@" /> <input type="hidden" name="wh::htype" value="@@wh::htype@@" />
10 10 <input type="hidden" name="token" value="@@rg_form_token@@" /> <input type="hidden" name="token" value="@@rg_form_token@@" />
File root/themes/default/user/settings/wh/deny.html added (mode: 100644) (index 0000000..4d120fe)
1 <div class="mess error">
2 You are not allowed to manage webhooks.
3 </div>
File root/themes/default/user/settings/wh/hints.html changed (mode: 100644) (index 92baad0..d1ff372)
1 <br />
1 2 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 3 happens with you repositories.<br /> happens with you repositories.<br />
3 4 <br /> <br />
File root/themes/default/user/settings/wh/http/form.html added (mode: 100644) (index 0000000..8020fb4)
1 <p>
2 <label for="itype">Data encoding</label><br />
3 @@select_itype@@
4 </p>
5
6 <fieldset>
7 <legend>Flags</legend>
8 @@check_flags@@
9 </fieldset>
10
11 <p>
12 <label for="client_cert">Optional concatenated certificate and key used to
13 authenticate us to the server (PEM format, no password)</label><br />
14 <textarea name="wh::idata::client_cert" id="client_cert" rows="3" cols="80">
15 @@wh::idata::client_cert@@
16 </textarea>
17 </p>
18
19 <p>
20 <label for="client_ca_cert">
21 Optional CA certificate(s) used to authenticate your server
22 (PEM format)
23 </label><br />
24 <textarea name="wh::idata::client_ca_cert" id="client_ca_cert" rows="3" cols="80">
25 @@wh::idata::client_ca_cert@@
26 </textarea>
27 </p>
28
File root/themes/default/user/settings/wh/http/hints.html added (mode: 100644) (index 0000000..acd67c8)
1 <br />
2 Optional CA certificates(s): if you have a self-signed CA, you may want to
3 add the CA certificate here, to be able to verify that the server we are
4 connecting to is the real one. If you add it and a man-in-the-middle attack
5 takes place, the link will not be made.<br />
File root/themes/default/user/settings/wh/http/inv_flag.txt added (mode: 100644) (index 0000000..2898621)
1 invalid flag
File root/themes/default/user/settings/wh/http/inv_proto.txt added (mode: 100644) (index 0000000..53dd1bb)
1 invalid protocol; only http and https are suported
File root/themes/default/user/settings/wh/http/inv_type.txt added (mode: 100644) (index 0000000..e4946e3)
1 invalid type
File root/themes/default/user/settings/wh/http/show.html added (mode: 100644) (index 0000000..4a8e317)
1 <table summary="plugin internal info">
2 <tr>
3 <td>Data encoding</td>
4 <td>@@itype_text@@</td>
5 </tr>
6
7 <tr>
8 <td>Flags</td>
9 <td>@@flags_text@@</td>
10 </tr>
11
12 <tr>
13 <td>Client cert</td>
14 <td>@@client_cert_short@@</td>
15 </tr>
16
17 <tr>
18 <td>Client CA cert</td>
19 <td>@@client_ca_cert_short@@</td>
20 </tr>
21 </table>
File root/themes/default/user/settings/wh/list/header.html changed (mode: 100644) (index 218df89..083e55b)
1 <div class="rg_wh_list">
1 <div class="wh_list">
2 2
3 3 @@errmsg@@ @@errmsg@@
4 4
 
8 8
9 9 <table summary="webhooks"> <table summary="webhooks">
10 10 <tr> <tr>
11 <th>ID</th>
11 12 <th>Select</th> <th>Select</th>
13 <th>Edit</th>
12 14 <th>Date (UTC)</th> <th>Date (UTC)</th>
13 15 <th>Events</th> <th>Events</th>
14 16 <th>URL</th> <th>URL</th>
15 17 <th>Description</th> <th>Description</th>
16 18 <th>Add IP</th> <th>Add IP</th>
19 <th>Private info</th>
17 20 <th>Last output</th> <th>Last output</th>
18 21 </tr> </tr>
File root/themes/default/user/settings/wh/list/line.html changed (mode: 100644) (index 8333bc0..5fb4284)
1 1 <tr> <tr>
2 <td>@@id@@</td>
2 3 <td><input type="checkbox" name="delete_list[@@id@@]" /></td> <td><input type="checkbox" name="delete_list[@@id@@]" /></td>
4 <td><a href="/op/settings/wh/edit/@@id@@">Edit</a></td>
3 5 <td>@@itime_nice@@</td> <td>@@itime_nice@@</td>
4 6 <td>@@events_text@@</td> <td>@@events_text@@</td>
5 7 <td>@@url@@</td> <td>@@url@@</td>
6 <td>@@description@@</td>
8 <td class="small">@@description_nice@@</td>
7 9 <td>@@add_ip@@</td> <td>@@add_ip@@</td>
8 <td><small>@@last_output_nice@@</small></td>
10 <td>@@idata::private@@</td>
11 <td class="small">@@last_output_nice@@</td>
9 12 </tr> </tr>
File root/themes/default/user/settings/wh/plugins_list/footer.html copied from file root/themes/default/repo/fstat/footer.html (similarity 52%) (mode: 100644) (index 000ca4b..27bf87e)
1 1 </table> </table>
2
3 </div>
File root/themes/default/user/settings/wh/plugins_list/header.html added (mode: 100644) (index 0000000..32e34eb)
1 <div class="wh_plugins_list">
2
3 <table summary="webhooks types">
4 <tr>
5 <th>Name</th>
6 <th>Description</th>
7 <th>Add</th>
8 </tr>
File root/themes/default/user/settings/wh/plugins_list/line.html added (mode: 100644) (index 0000000..ff6ebda)
1 <tr>
2 <td>@@htype@@</td>
3 <td>@@description@@</td>
4 <td><a href="/op/settings/wh/add?wh::htype=@@htype@@">Add</a></td>
5 </tr>
File root/themes/default/user/settings/wh/plugins_list/nodata.html copied from file root/themes/default/repo/bug/list/nodata.html (similarity 50%) (mode: 100644) (index 5a9a182..949c8df)
1 1 <div class="mess ok"> <div class="mess ok">
2 No bugs found.
2 No webhooks plugins present.
3 3 </div> </div>
File scripts/remote.php changed (mode: 100644) (index d2d7a93..6003ee9)
... ... if (isset($_SERVER['SSH_CONNECTION'])) {
93 93
94 94 $ssh_client = getenv("SSH_CLIENT"); $ssh_client = getenv("SSH_CLIENT");
95 95 $_t = explode(" ", $ssh_client); $_t = explode(" ", $ssh_client);
96 $ip = $_t[0];
96 $ip = rg_fix_ip($_t[0]);
97 97
98 98 info('== Welcome to RocketGit! =='); info('== Welcome to RocketGit! ==');
99 99 info('you are connecting from IP ' . $ip . '.'); info('you are connecting from IP ' . $ip . '.');
 
... ... if (isset($_SERVER['SSH_CONNECTION'])) {
144 144 $v = explode(':', $host_port); $v = explode(':', $host_port);
145 145 $host = $v[0]; $host = $v[0];
146 146
147 $ip = getenv("REMOTE_HOST");
147 $ip = rg_fix_ip(getenv("REMOTE_HOST"));
148 148 } }
149 149
150 150 // Extracts command and computes permissions // Extracts command and computes permissions
File tests/helpers.inc.php changed (mode: 100644) (index fd6e29d..d57e7d5)
... ... function rg_test_wh_add_edit($db, $rg_ui, $good_sid, $htype, $extra)
287 287 rg_log("Loading webhook add form..."); rg_log("Loading webhook add form...");
288 288 $data = array('wh::htype' => $htype); $data = array('wh::htype' => $htype);
289 289 $headers = array("Cookie: sid=" . $good_sid); $headers = array("Cookie: sid=" . $good_sid);
290 $r = do_req($test_url . "/op/settings/wh/add", $data, $headers);
290
291 if (!isset($extra['wh::id']))
292 $extra['wh::id'] = 0;
293
294 if ($extra['wh::id'] == 0)
295 $url = 'add';
296 else
297 $url = 'edit/' . $extra['wh::id'];
298 $r = do_req($test_url . "/op/settings/wh/" . $url, $data, $headers);
291 299 if ($r === FALSE) { if ($r === FALSE) {
292 300 rg_log("Cannot load form!"); rg_log("Cannot load form!");
293 301 exit(1); exit(1);
 
... ... function rg_test_wh_add_edit($db, $rg_ui, $good_sid, $htype, $extra)
302 310 $data = array('add' => 1, 'token' => $r['tokens']['wh_add']); $data = array('add' => 1, 'token' => $r['tokens']['wh_add']);
303 311 $data = array_merge($data, $extra); $data = array_merge($data, $extra);
304 312 $headers = array('Cookie: sid=' . $good_sid); $headers = array('Cookie: sid=' . $good_sid);
305 $r = do_req($test_url . '/op/settings/wh/add', $data, $headers);
313 $r = do_req($test_url . '/op/settings/wh/' . $url, $data, $headers);
306 314 if ($r === FALSE) { if ($r === FALSE) {
307 315 rg_log_ml('r: ' . print_r($r, TRUE)); rg_log_ml('r: ' . print_r($r, TRUE));
308 316 rg_log_ml('Cannot add webhook!'); rg_log_ml('Cannot add webhook!');
File tests/wh_http.php added (mode: 100644) (index 0000000..76214d5)
1 <?php
2 error_reporting(E_ALL | E_STRICT);
3 ini_set("track_errors", "On");
4
5 $INC = dirname(__FILE__) . "/../inc";
6 require_once(dirname(__FILE__) . "/config.php");
7 require_once($INC . "/init.inc.php");
8 require_once($INC . "/user.inc.php");
9 require_once("helpers.inc.php");
10 require_once("http.inc.php");
11
12 rg_log_set_file("wh_http.log");
13
14 $rg_sql = "host=localhost user=rocketgit dbname=rocketgit connect_timeout=10";
15 $rg_no_db = TRUE;
16 require_once("common.php");
17
18 $_testns = 'wh_http';
19 $rg_cache_enable = TRUE;
20 $rg_cache_debug = TRUE;
21 $rg_event_socket = "/var/lib/rocketgit/sockets/event.sock";
22
23 $port1 = 64000 + (rand(0, 100000) + time()) % 1000;
24 $port2 = $port1 + 1;
25 $port3 = $port2 + 1;
26 rg_log('port1=' . $port1 . ' port2=' . $port2 . ' port3=' . $port3);
27
28 function clean()
29 {
30 system('fuser -k -9 wh-stunnel-1.log 1>/dev/null 2>&1');
31 system('fuser -k -9 wh-stunnel-2.log 1>/dev/null 2>&1');
32 system('fuser -k -9 wh-stunnel-3.log 1>/dev/null 2>&1');
33
34 @unlink('wh-stunnel.conf-1.tmp');
35 @unlink('wh-stunnel.conf-2.tmp');
36 @unlink('wh-stunnel.conf-3.tmp');
37 }
38 register_shutdown_function('clean');
39
40
41 rg_log('');
42 rg_log('Generating certificates...');
43 $r = shell_exec('./ca.sh wh');
44 if (!strstr($r, 'CA_SH_OK')) {
45 rg_log_ml('r: ' . print_r($r, TRUE));
46 rg_log('Cannot generate certificates!');
47 exit(1);
48 }
49
50
51 rg_log('');
52 rg_log('Preparing stunnel conf file...');
53 $x = file_get_contents('wh-stunnel.conf');
54 if ($x === FALSE) {
55 rg_log('Cannot load conf file');
56 exit(1);
57 }
58
59 $y = str_replace('@@port@@', $port1, $x);
60 $y = str_replace('@@verify@@', '2', $y);
61 $y = str_replace('@@id@@', '1', $y);
62 file_put_contents('wh-stunnel.conf-1.tmp', $y);
63
64 $y = str_replace('@@port@@', $port2, $x);
65 $y = str_replace('@@verify@@', '2', $y);
66 $y = str_replace('@@id@@', '2', $y);
67 file_put_contents('wh-stunnel.conf-2.tmp', $y);
68
69 $y = str_replace('@@port@@', $port3, $x);
70 $y = str_replace('@@verify@@', '0', $y);
71 $y = str_replace('@@id@@', '3', $y);
72 file_put_contents('wh-stunnel.conf-3.tmp', $y);
73
74
75 rg_log('');
76 rg_log('Starting stunnel1...');
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-1.tmp 2>/dev/null');
84 exit(0);
85 }
86 rg_log('Started stunnel with pid ' . $pid);
87
88
89 rg_log('');
90 rg_log('Starting stunnel2...');
91 $pid = pcntl_fork();
92 if ($pid == -1) {
93 rg_log('Cannot fork');
94 exit(1);
95 }
96 if ($pid == 0) { //child
97 $r = exec('stunnel wh-stunnel.conf-2.tmp 2>/dev/null');
98 exit(0);
99 }
100 rg_log('Started stunnel with pid ' . $pid);
101
102
103 rg_log('');
104 rg_log('Starting stunnel3...');
105 $pid = pcntl_fork();
106 if ($pid == -1) {
107 rg_log('Cannot fork');
108 exit(1);
109 }
110 if ($pid == 0) { //child
111 $r = exec('stunnel wh-stunnel.conf-3.tmp 2>/dev/null');
112 exit(0);
113 }
114 rg_log('Started stunnel with pid ' . $pid);
115
116
117 rg_log('');
118 rg_log("Creating a user...");
119 rg_test_create_user($db, $rg_ui);
120 $key1 = 'DEBUG::' . $rg_ui['uid'] . '::webhooks::' . $port1;
121 $key2 = 'DEBUG::' . $rg_ui['uid'] . '::webhooks::' . $port2;
122 $key3 = 'DEBUG::' . $rg_ui['uid'] . '::webhooks::' . $port3;
123
124
125 rg_log('');
126 rg_log('Login...');
127 $r = test_login($test_url, $rg_ui, $good_sid);
128 if ($r === FALSE) {
129 rg_log("Cannot login!");
130 exit(1);
131 }
132
133
134 rg_log('');
135 rg_log('Registering webhook1...');
136 $extra = array(
137 'wh::htype' => 'http',
138 'wh::url' => 'https://localhost:' . $port1 . '/wh.html',
139 'wh::events[C]' => 'on',
140 'wh::events[P]' => 'on',
141 'wh::events[B]' => 'on',
142 'wh::description' => 'description1 <xss>',
143 'wh::key' => 'key1 <xss>',
144 'wh::opaque' => $port1,
145 'wh::client_cert' => '',
146 'wh::idata::itype' => 0,
147 'wh::idata::client_ca_cert' => file_get_contents('ca/wh/certs/cacert.pem')
148 );
149 rg_test_wh_add_edit($db, $rg_ui, $good_sid, 'http', $extra);
150
151
152 rg_log('');
153 rg_log('Registering webhook2...');
154 $extra = array(
155 'wh::htype' => 'http',
156 'wh::url' => 'https://localhost:' . $port2 . '/wh.html',
157 'wh::events[C]' => 'on',
158 'wh::events[P]' => 'on',
159 'wh::events[B]' => 'on',
160 'wh::description' => 'description1 <xss>',
161 'wh::key' => 'key2 <xss>',
162 'wh::opaque' => $port2,
163 'wh::idata::itype' => 1,
164 'wh::idata::client_cert' => file_get_contents('ca/wh/certs/client.pem')
165 . file_get_contents('ca/wh/private/client.key'),
166 'wh::idata::client_ca_cert' => file_get_contents('ca/wh/certs/cacert.pem')
167 );
168 rg_test_wh_add_edit($db, $rg_ui, $good_sid, 'http', $extra);
169
170
171 rg_log('');
172 rg_log('Registering webhook3...');
173 $extra = array(
174 'wh::htype' => 'http',
175 'wh::url' => 'https://localhost:' . $port3 . '/wh.html',
176 'wh::events[C]' => 'on',
177 'wh::events[P]' => 'on',
178 'wh::events[B]' => 'on',
179 'wh::description' => 'description1 <xss>',
180 'wh::key' => 'key2 <xss>',
181 'wh::opaque' => $port3,
182 'wh::idata::itype' => 1,
183 'wh::idata::client_cert' => '',
184 'wh::idata::client_ca_cert' => file_get_contents('ca/wh/certs/cacert.pem')
185 );
186 rg_test_wh_add_edit($db, $rg_ui, $good_sid, 'http', $extra);
187
188
189 rg_log('Finding out the ids...');
190 for ($i = 0; $i < 10; $i++) {
191 $r = rg_cache_get('wh' . '::' . $rg_ui['uid']);
192 if ($r !== FALSE)
193 break;
194 sleep(1);
195 }
196 if ($r === FALSE) {
197 rg_log('Cannot get id from cache');
198 exit(1);
199 }
200 rg_log_ml('r=' . print_r($r, TRUE));
201 $t = array_keys($r['list']);
202 if (count($t) != 3) {
203 rg_log('We do not have 3 ids!');
204 exit(1);
205 }
206 $wh_id1 = $t[0];
207 $wh_id2 = $t[1];
208 $wh_id3 = $t[2];
209 rg_log('wh_id1=' . $wh_id1);
210 rg_log('wh_id2=' . $wh_id2);
211 rg_log('wh_id3=' . $wh_id3);
212
213
214 rg_log('');
215 rg_log('Creating a repo and waiting for trigger');
216 $repo = array();
217 rg_test_create_repo($db, $rg_ui, $repo);
218
219
220 rg_log('');
221 rg_log('Testing if the curl posted with success (wh1)');
222 for ($i = 0; $i < 10; $i++) {
223 $r = rg_cache_get($key1 . '::' . $wh_id1);
224 rg_log_ml('cache: ' . $r);
225 if ($r !== FALSE)
226 break;
227 sleep(1);
228 }
229 if ($r === FALSE) {
230 rg_log('Seems the event does not set the cache!');
231 exit(1);
232 }
233 if (strcmp($r, "BAD") != 0) {
234 rg_log('Seems wh1 executed correctly without client'
235 . ' cert (r=' . $r . ')!');
236 exit(1);
237 }
238
239
240 rg_log('');
241 rg_log('Testing if the curl posted with success (wh2)');
242 for ($i = 0; $i < 10; $i++) {
243 $r = rg_cache_get($key2 . '::' . $wh_id2);
244 rg_log_ml('cache: ' . print_r($r, TRUE));
245 if ($r !== FALSE)
246 break;
247 sleep(1);
248 }
249 if (strcmp($r, "OK") != 0) {
250 rg_log('Seems wh2 did not returned success'
251 . ' (r=' . $r . ')!');
252 exit(1);
253 }
254
255
256 rg_log('');
257 rg_log('Testing if the curl posted with success (wh3)');
258 for ($i = 0; $i < 10; $i++) {
259 $r = rg_cache_get($key3 . '::' . $wh_id3);
260 rg_log_ml('cache: ' . print_r($r, TRUE));
261 if ($r !== FALSE)
262 break;
263 sleep(1);
264 }
265 if (strcmp($r, "OK") != 0) {
266 rg_log('Seems wh3 did not returned success'
267 . ' (r=' . $r . ')!');
268 exit(1);
269 }
270
271
272 rg_log('');
273 rg_log('Testing the edit of webhook1...');
274 $extra = array(
275 'wh::htype' => 'http',
276 'wh::url' => 'https://localhost:' . $port1 . '/wh.html',
277 'wh::id' => $wh_id1,
278 'wh::events[C]' => 'on',
279 'wh::events[B]' => 'on',
280 'wh::description' => 'desc2 <xss>',
281 'wh::key' => 'another key <xss>',
282 'wh::opaque' => 'xxx',
283 'wh::idata::itype' => 1,
284 'wh::idata::flags[I]' => 'on',
285 'wh::idata::client_cert' => 'abc <xss>',
286 'wh::idata::client_ca_cert' => 'zzz <xss>'
287 );
288 rg_test_wh_add_edit($db, $rg_ui, $good_sid, 'http', $extra);
289 $sql = "SELECT * FROM webhooks WHERE uid = " . $rg_ui['uid']
290 . " AND id = " . $wh_id1;
291 $res = rg_sql_query($db, $sql);
292 $row = rg_sql_fetch_array($res);
293 rg_sql_free_result($res);
294 $row['idata'] = unserialize($row['idata']);
295 $key = 'wh' . '::' . $rg_ui['uid'] . '::' . 'list' . '::' . $wh_id1;
296 rg_cache_core_unset($key); // else we will get previous copy!
297 $c = rg_cache_get($key);
298 $list = array('htype' => 'http', 'events' => 'CB',
299 'description' => 'desc2 <xss>', 'key' => 'another key <xss>',
300 'opaque' => 'xxx', 'itype' => '1', 'flags' => 'I',
301 'client_cert' => 'abc <xss>', 'client_ca_cert' => 'zzz <xss>');
302 foreach ($list as $k => $v) {
303 if (isset($row[$k]))
304 $a = $row[$k];
305 else if (isset($row['idata'][$k]))
306 $a = $row['idata'][$k];
307 else {
308 rg_log('Key [' . $k . '] not found! Bad!');
309 exit(1);
310 }
311 if (strcmp($a, $v) != 0) {
312 rg_log_ml('row: ' . print_r($row, TRUE));
313 rg_log("db: Seems that [$k] has not been updated"
314 . " [" . $a . "] != " . $v);
315 exit(1);
316 }
317
318 if (isset($c[$k]))
319 $a = $c[$k];
320 else
321 $a = $c['idata'][$k];
322 if (strcmp($a, $v) != 0) {
323 rg_log_ml('c: ' . print_r($c, TRUE));
324 rg_log("cache: Seems that [$k] has not been updated"
325 . " [" . $a . "] != " . $v);
326 exit(1);
327 }
328 }
329
330
331 rg_log('');
332 rg_log_enter('Testing the delete - loading form...');
333 $data = array();
334 $headers = array("Cookie: sid=" . $good_sid);
335 $r = do_req($test_url . "/op/settings/wh/list", $data, $headers);
336 if ($r === FALSE) {
337 rg_log("Cannot load list form.");
338 exit(1);
339 }
340 if (!isset($r['tokens']['wh_list'])) {
341 rg_log_ml('tokens: ' . print_r($r['tokens'], TRUE));
342 rg_log('Cannot find wh_list token!');
343 exit(1);
344 }
345 $good_token = $r['tokens']['wh_list'];
346 $data = array( 'delete' => 1,
347 'token' => $good_token,
348 'delete_list[' . $wh_id1 . ']' => 'on');
349 $r = do_req($test_url . "/op/settings/wh/list", $data, $headers);
350 if (!strstr($r['body'], 'deleted with success')) {
351 rg_log_ml('r[body]: ' . print_r($r['body'], TRUE));
352 rg_log("Cannot delete webhook!");
353 exit(1);
354 }
355 $sql = "SELECT id FROM webhooks WHERE id = " . $wh_id1;
356 $res = rg_sql_query($db, $sql);
357 $rows = rg_sql_num_rows($res);
358 rg_sql_free_result($res);
359 if ($rows != 0) {
360 rg_log("Cannot delete webhook - sql still returns data!");
361 exit(1);
362 }
363 $key = 'user::' . $rg_ui['uid'] . '::wh::' . $wh_id1;
364 rg_cache_core_unset($key); // else we will get data from local mem!
365 $r = rg_cache_get($key);
366 if (strcmp($r, '') != 0) {
367 rg_log_ml($key . ': ' . print_r($r, TRUE));
368 rg_log('Deleted webhooks are still in cache!');
369 exit(1);
370 }
371 rg_log_exit();
372
373
374 rg_log("OK!");
375 ?>
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