r4452 Make VLAN switch templates one of "generic" realms:
[racktables] / wwwroot / inc / ophandlers.php
1 <?php
2 /*
3
4 "Ophandler" in RackTables stands for "operation handler", or a function,
5 which handles execution of "operation" (in the meaning explained in
6 navigation.php). Most of the ophandlers are meant to perform one specific
7 action, for example, to set a name of an object. Each such action often
8 requires a set of parameters (e. g. ID of the object and the new name),
9 and it is responsibility of each ophandler function to verify, that all
10 necessary parameters are provided by the user and have proper values. There
11 is a number of helper functions to make such verification simple.
12
13 Errors occuring in ophandlers are typically indicated with exceptions of
14 assorted classes. Namely, an "InvalidRequestArgException" class means, that
15 at least one of the parameters provided by the user is not acceptable. This
16 is a "soft" error, which gets displayed in the standard message area of
17 otherwise usual interface. A different case is "InvalidArgException", which
18 means, that one of the internal functions detected its argument(s) invalid
19 or currupted, and that argument(s) did not come from user's input (and thus
20 cannot be fixed without fixing a bug in the code). Such "hard" errors don't
21 get special early handling and end up in the default catching block. The
22 latter may print a detailed stack trace instead of the interface HTML to
23 help a developer debug the issue.
24
25 As long as an ophandler makes through its request (extracting arguments,
26 performing validation and actually updating records in the database), it
27 may queue up messages (often referred to as "green" and "red" bars) by
28 means of showError() and showSuccess() function. The messages are not
29 displayed immediately, because successfull ophandlers are expected to
30 return only the new URL, where the user will be immediately redirected to
31 (it is also possible to return an empty string to mean, that the current
32 logical location remains the same). The page at the "next" location is
33 supposed to translate message buffer into the standard message area.
34
35 A very special case of an ophandler is tableHandler(). This generic
36 function handles the most trivial actions, which map to a single INSERT,
37 UPDATE or DELETE SQL statement with a fixed number of arguments. The rules
38 of argument validation and mapping are listed in $opspec_list (operation
39 specifications list) array.
40
41 */
42
43 // This array is deprecated. Please do not add new message constants to it.
44 // use the new showError, showWarning, showSuccess functions instead
45 global $msgcode;
46 $msgcode = array();
47
48 global $opspec_list;
49 $opspec_list = array();
50
51 $opspec_list['rackspace-edit-addRow'] = array
52 (
53 'table' => 'RackRow',
54 'action' => 'INSERT',
55 'arglist' => array
56 (
57 array ('url_argname' => 'name', 'assertion' => 'string')
58 ),
59 );
60 $opspec_list['rackspace-edit-delete'] = array
61 (
62 'table' => 'RackRow',
63 'action' => 'DELETE',
64 'arglist' => array
65 (
66 array ('url_argname' => 'row_id', 'table_colname' => 'id', 'assertion' => 'uint')
67 ),
68 );
69 $opspec_list['rackspace-edit-updateRow'] = array
70 (
71 'table' => 'RackRow',
72 'action' => 'UPDATE',
73 'set_arglist' => array
74 (
75 array ('url_argname' => 'name', 'assertion' => 'string')
76 ),
77 'where_arglist' => array
78 (
79 array ('url_argname' => 'row_id', 'table_colname' => 'id', 'assertion' => 'uint')
80 ),
81 );
82 $opspec_list['object-ports-delPort'] = array
83 (
84 'table' => 'Port',
85 'action' => 'DELETE',
86 'arglist' => array
87 (
88 array ('url_argname' => 'port_id', 'table_colname' => 'id', 'assertion' => 'uint'),
89 array ('url_argname' => 'object_id', 'assertion' => 'uint'),
90 ),
91 );
92 $opspec_list['object-ports-deleteAll'] = array
93 (
94 'table' => 'Port',
95 'action' => 'DELETE',
96 'arglist' => array
97 (
98 array ('url_argname' => 'object_id', 'assertion' => 'uint'),
99 ),
100 );
101 $opspec_list['object-log-del'] = array
102 (
103 'table' => 'ObjectLog',
104 'action' => 'DELETE',
105 'arglist' => array
106 (
107 array ('url_argname' => 'logid', 'table_colname' => 'id', 'assertion' => 'uint'),
108 array ('url_argname' => 'object_id', 'assertion' => 'uint'),
109 ),
110 );
111 $opspec_list['ipv4vs-editlblist-delLB'] =
112 $opspec_list['ipv4rspool-editlblist-delLB'] =
113 $opspec_list['object-editrspvs-delLB'] = array
114 (
115 'table' => 'IPv4LB',
116 'action' => 'DELETE',
117 'arglist' => array
118 (
119 array ('url_argname' => 'object_id', 'assertion' => 'uint'),
120 array ('url_argname' => 'pool_id', 'table_colname' => 'rspool_id', 'assertion' => 'uint'),
121 array ('url_argname' => 'vs_id', 'assertion' => 'uint'),
122 ),
123 );
124 $opspec_list['ipv4vs-editlblist-updLB'] =
125 $opspec_list['ipv4rspool-editlblist-updLB'] =
126 $opspec_list['object-editrspvs-updLB'] = array
127 (
128 'table' => 'IPv4LB',
129 'action' => 'UPDATE',
130 'set_arglist' => array
131 (
132 array ('url_argname' => 'vsconfig', 'assertion' => 'string0', 'if_empty' => 'NULL'),
133 array ('url_argname' => 'rsconfig', 'assertion' => 'string0', 'if_empty' => 'NULL'),
134 array ('url_argname' => 'prio', 'assertion' => 'uint0', 'if_empty' => 'NULL'),
135 ),
136 'where_arglist' => array
137 (
138 array ('url_argname' => 'object_id', 'assertion' => 'uint'),
139 array ('url_argname' => 'pool_id', 'table_colname' => 'rspool_id', 'assertion' => 'uint'),
140 array ('url_argname' => 'vs_id', 'assertion' => 'uint'),
141 ),
142 );
143 $opspec_list['ipv4net-properties-editRange'] = array
144 (
145 'table' => 'IPv4Network',
146 'action' => 'UPDATE',
147 'set_arglist' => array
148 (
149 array ('url_argname' => 'name', 'assertion' => 'string0'),
150 array ('url_argname' => 'comment', 'assertion' => 'string0'),
151 ),
152 'where_arglist' => array
153 (
154 array ('url_argname' => 'id', 'assertion' => 'uint')
155 ),
156 );
157 $opspec_list['ipv6net-properties-editRange'] = array
158 (
159 'table' => 'IPv6Network',
160 'action' => 'UPDATE',
161 'set_arglist' => array
162 (
163 array ('url_argname' => 'name', 'assertion' => 'string0'),
164 array ('url_argname' => 'comment', 'assertion' => 'string0'),
165 ),
166 'where_arglist' => array
167 (
168 array ('url_argname' => 'id', 'assertion' => 'uint')
169 ),
170 );
171 $opspec_list['ipv4rspool-editrslist-delRS'] = array
172 (
173 'table' => 'IPv4RS',
174 'action' => 'DELETE',
175 'arglist' => array
176 (
177 array ('url_argname' => 'id', 'assertion' => 'uint'),
178 ),
179 );
180 $opspec_list['ipv4rspool-edit-updIPv4RSP'] = array
181 (
182 'table' => 'IPv4RSPool',
183 'action' => 'UPDATE',
184 'set_arglist' => array
185 (
186 array ('url_argname' => 'name', 'assertion' => 'string0', 'if_empty' => 'NULL'),
187 array ('url_argname' => 'vsconfig', 'assertion' => 'string0', 'if_empty' => 'NULL'),
188 array ('url_argname' => 'rsconfig', 'assertion' => 'string0', 'if_empty' => 'NULL'),
189 ),
190 'where_arglist' => array
191 (
192 array ('url_argname' => 'pool_id', 'table_colname' => 'id', 'assertion' => 'uint')
193 ),
194 );
195 $opspec_list['file-edit-updateFile'] = array
196 (
197 'table' => 'File',
198 'action' => 'UPDATE',
199 'set_arglist' => array
200 (
201 array ('url_argname' => 'file_name', 'table_colname' => 'name', 'assertion' => 'string'),
202 array ('url_argname' => 'file_type', 'table_colname' => 'type', 'assertion' => 'string'),
203 array ('url_argname' => 'file_comment', 'table_colname' => 'comment', 'assertion' => 'string0', 'if_empty' => 'NULL'),
204 ),
205 'where_arglist' => array
206 (
207 array ('url_argname' => 'file_id', 'table_colname' => 'id', 'assertion' => 'uint')
208 ),
209 );
210 $opspec_list['parentmap-edit-add'] = array
211 (
212 'table' => 'ObjectParentCompat',
213 'action' => 'INSERT',
214 'arglist' => array
215 (
216 array ('url_argname' => 'parent_objtype_id', 'assertion' => 'uint'),
217 array ('url_argname' => 'child_objtype_id', 'assertion' => 'uint'),
218 ),
219 );
220 $opspec_list['parentmap-edit-del'] = array
221 (
222 'table' => 'ObjectParentCompat',
223 'action' => 'DELETE',
224 'arglist' => array
225 (
226 array ('url_argname' => 'parent_objtype_id', 'assertion' => 'uint'),
227 array ('url_argname' => 'child_objtype_id', 'assertion' => 'uint'),
228 ),
229 );
230 $opspec_list['portmap-edit-add'] = array
231 (
232 'table' => 'PortCompat',
233 'action' => 'INSERT',
234 'arglist' => array
235 (
236 array ('url_argname' => 'type1', 'assertion' => 'uint'),
237 array ('url_argname' => 'type2', 'assertion' => 'uint'),
238 ),
239 );
240 $opspec_list['portmap-edit-del'] = array
241 (
242 'table' => 'PortCompat',
243 'action' => 'DELETE',
244 'arglist' => array
245 (
246 array ('url_argname' => 'type1', 'assertion' => 'uint'),
247 array ('url_argname' => 'type2', 'assertion' => 'uint'),
248 ),
249 );
250 $opspec_list['portifcompat-edit-del'] = array
251 (
252 'table' => 'PortInterfaceCompat',
253 'action' => 'DELETE',
254 'arglist' => array
255 (
256 array ('url_argname' => 'iif_id', 'assertion' => 'uint'),
257 array ('url_argname' => 'oif_id', 'assertion' => 'uint'),
258 ),
259 );
260 $opspec_list['attrs-editmap-del'] = array
261 (
262 'table' => 'AttributeMap',
263 'action' => 'DELETE',
264 'arglist' => array
265 (
266 array ('url_argname' => 'attr_id', 'assertion' => 'uint'),
267 array ('url_argname' => 'objtype_id', 'assertion' => 'uint'),
268 ),
269 );
270 $opspec_list['attrs-editattrs-add'] = array
271 (
272 'table' => 'Attribute',
273 'action' => 'INSERT',
274 'arglist' => array
275 (
276 array ('url_argname' => 'attr_type', 'table_colname' => 'type', 'assertion' => 'enum/attr_type'),
277 array ('url_argname' => 'attr_name', 'table_colname' => 'name', 'assertion' => 'string'),
278 ),
279 );
280 $opspec_list['attrs-editattrs-del'] = array
281 (
282 'table' => 'Attribute',
283 'action' => 'DELETE',
284 'arglist' => array
285 (
286 array ('url_argname' => 'attr_id', 'table_colname' => 'id', 'assertion' => 'uint'),
287 ),
288 );
289 $opspec_list['attrs-editattrs-upd'] = array
290 (
291 'table' => 'Attribute',
292 'action' => 'UPDATE',
293 'set_arglist' => array
294 (
295 array ('url_argname' => 'attr_name', 'table_colname' => 'name', 'assertion' => 'string'),
296 ),
297 'where_arglist' => array
298 (
299 array ('url_argname' => 'attr_id', 'table_colname' => 'id', 'assertion' => 'uint'),
300 ),
301 );
302 $opspec_list['dict-chapters-add'] = array
303 (
304 'table' => 'Chapter',
305 'action' => 'INSERT',
306 'arglist' => array
307 (
308 array ('url_argname' => 'chapter_name', 'table_colname' => 'name', 'assertion' => 'string')
309 ),
310 );
311 $opspec_list['chapter-edit-add'] = array
312 (
313 'table' => 'Dictionary',
314 'action' => 'INSERT',
315 'arglist' => array
316 (
317 array ('url_argname' => 'chapter_no', 'table_colname' => 'chapter_id', 'assertion' => 'uint'),
318 array ('url_argname' => 'dict_value', 'assertion' => 'string'),
319 ),
320 );
321 $opspec_list['chapter-edit-del'] = array
322 (
323 'table' => 'Dictionary',
324 'action' => 'DELETE',
325 'arglist' => array
326 (
327 // Technically dict_key is enough to delete, but including chapter_id into
328 // WHERE clause makes sure, that the action actually happends for the same
329 // chapter, which authorization was granted for.
330 array ('url_argname' => 'chapter_no', 'table_colname' => 'chapter_id', 'assertion' => 'uint'),
331 array ('url_argname' => 'dict_key', 'assertion' => 'uint'),
332 ),
333 );
334 $opspec_list['tagtree-edit-createTag'] = array
335 (
336 'table' => 'TagTree',
337 'action' => 'INSERT',
338 'arglist' => array
339 (
340 array ('url_argname' => 'tag_name', 'table_colname' => 'tag', 'assertion' => 'tag'),
341 array ('url_argname' => 'parent_id', 'assertion' => 'uint0', 'if_empty' => 'NULL'),
342 ),
343 );
344 $opspec_list['tagtree-edit-destroyTag'] = array
345 (
346 'table' => 'TagTree',
347 'action' => 'DELETE',
348 'arglist' => array
349 (
350 array ('url_argname' => 'tag_id', 'table_colname' => 'id', 'assertion' => 'uint'),
351 ),
352 );
353 $opspec_list['tagtree-edit-updateTag'] = array
354 (
355 'table' => 'TagTree',
356 'action' => 'UPDATE',
357 'set_arglist' => array
358 (
359 array ('url_argname' => 'tag_name', 'table_colname' => 'tag', 'assertion' => 'tag'),
360 array ('url_argname' => 'parent_id', 'assertion' => 'uint0', 'if_empty' => 'NULL'),
361 ),
362 'where_arglist' => array
363 (
364 array ('url_argname' => 'tag_id', 'table_colname' => 'id', 'assertion' => 'uint'),
365 ),
366 );
367 $opspec_list['8021q-vstlist-upd'] = array
368 (
369 'table' => 'VLANSwitchTemplate',
370 'action' => 'UPDATE',
371 'set_arglist' => array
372 (
373 array ('url_argname' => 'vst_descr', 'table_colname' => 'description', 'assertion' => 'string'),
374 ),
375 'where_arglist' => array
376 (
377 array ('url_argname' => 'vst_id', 'table_colname' => 'id', 'assertion' => 'uint'),
378 ),
379 );
380 $opspec_list['8021q-vdlist-upd'] = array
381 (
382 'table' => 'VLANDomain',
383 'action' => 'UPDATE',
384 'set_arglist' => array
385 (
386 array ('url_argname' => 'vdom_descr', 'table_colname' => 'description', 'assertion' => 'string'),
387 ),
388 'where_arglist' => array
389 (
390 array ('url_argname' => 'vdom_id', 'table_colname' => 'id', 'assertion' => 'uint'),
391 ),
392 );
393 $opspec_list['vlandomain-vlanlist-add'] = array
394 (
395 'table' => 'VLANDescription',
396 'action' => 'INSERT',
397 'arglist' => array
398 (
399 array ('url_argname' => 'vdom_id', 'table_colname' => 'domain_id', 'assertion' => 'uint'),
400 array ('url_argname' => 'vlan_id', 'assertion' => 'vlan'),
401 array ('url_argname' => 'vlan_type', 'assertion' => 'enum/vlan_type'),
402 array ('url_argname' => 'vlan_descr', 'assertion' => 'string0', 'if_empty' => 'NULL'),
403 ),
404 );
405 $opspec_list['vlandomain-vlanlist-del'] = array
406 (
407 'table' => 'VLANDescription',
408 'action' => 'DELETE',
409 'arglist' => array
410 (
411 array ('url_argname' => 'vdom_id', 'table_colname' => 'domain_id', 'assertion' => 'uint'),
412 array ('url_argname' => 'vlan_id', 'assertion' => 'vlan'),
413 ),
414 );
415 $opspec_list['vlandomain-vlanlist-upd'] = array
416 (
417 'table' => 'VLANDescription',
418 'action' => 'UPDATE',
419 'set_arglist' => array
420 (
421 array ('url_argname' => 'vlan_type', 'assertion' => 'enum/vlan_type'),
422 array ('url_argname' => 'vlan_descr', 'assertion' => 'string0', 'if_empty' => 'NULL'),
423 ),
424 'where_arglist' => array
425 (
426 array ('url_argname' => 'vdom_id', 'table_colname' => 'domain_id', 'assertion' => 'uint'),
427 array ('url_argname' => 'vlan_id', 'assertion' => 'vlan'),
428 ),
429 );
430
431 // This function is DEPRECATED. Show messages through showError and showSuccess,
432 // you dont need to return anything from an ophandler to redirect user back to the page containing submit form
433 function buildWideRedirectURL ($log = NULL, $nextpage = NULL, $nexttab = NULL, $moreArgs = array())
434 {
435 global $page, $pageno, $tabno;
436 if ($nextpage === NULL)
437 $nextpage = $pageno;
438 if ($nexttab === NULL)
439 $nexttab = $tabno;
440 $url = "index.php?page=${nextpage}&tab=${nexttab}";
441 if (isset ($page[$nextpage]['bypass']))
442 $url .= '&' . $page[$nextpage]['bypass'] . '=' . $_REQUEST[$page[$nextpage]['bypass']];
443
444 if (count ($moreArgs) > 0)
445 foreach ($moreArgs as $arg => $value)
446 if (is_array ($value))
447 foreach ($value as $v)
448 $url .= '&' . urlencode ($arg . '[]') . '=' . urlencode ($v);
449 elseif ($arg != 'module')
450 $url .= '&' . urlencode ($arg) . '=' . urlencode ($value);
451
452 if (! empty ($log))
453 {
454 if (empty ($_SESSION['log']))
455 $_SESSION['log'] = $log;
456 elseif ($_SESSION['log']['v'] == $log['v'])
457 $_SESSION['log'] = array_merge_recursive($log, $_SESSION['log']);
458 elseif ($log['v'] == 1 and $_SESSION['log']['v'] == 2)
459 foreach ($log['m'] as $msg)
460 setMessage ($msg['code'], $msg['message'], FALSE);
461 elseif ($log['v'] == 2 and $_SESSION['log']['v'] == 1)
462 {
463 foreach ($_SESSION['log'] as $msg)
464 {
465 if (! is_array ($msg))
466 continue;
467 $new_v2_item = array('c' => '', 'a' => array());
468 switch ($msg['code'])
469 {
470 case 'error':
471 $new_v2_item['c'] = 100;
472 break;
473 case 'success':
474 $new_v2_item['c'] = 0;
475 break;
476 case 'warning':
477 $new_v2_item['c'] = 200;
478 break;
479 default:
480 $new_v2_item['c'] = 300;
481 }
482 $new_v2_item['a'][] = $msg['message'];
483 $log['m'][] = $new_v2_item;
484 }
485 $_SESSION['log'] = $log; // substitute v1 log structure with merged v2
486 }
487 }
488 return $url;
489 }
490
491 // This function is DEPRECATED. Show messages through showError and showSuccess,
492 // you dont need to return anything from an ophandler to redirect user back to the page containing submit form
493 function buildRedirectURL ($callfunc, $status, $log_args = array(), $nextpage = NULL, $nexttab = NULL, $url_args = array())
494 {
495 global $pageno, $tabno, $msgcode;
496 if ($nextpage === NULL)
497 $nextpage = $pageno;
498 if ($nexttab === NULL)
499 $nexttab = $tabno;
500 return buildWideRedirectURL (oneLiner ($msgcode[$callfunc][$status], $log_args), $nextpage, $nexttab, $url_args);
501 }
502
503 $msgcode['addPortForwarding']['OK'] = 48;
504 $msgcode['addPortForwarding']['ERR'] = 100;
505 function addPortForwarding ()
506 {
507 assertUIntArg ('object_id');
508 assertIPv4Arg ('localip');
509 assertIPv4Arg ('remoteip');
510 assertUIntArg ('localport');
511 assertStringArg ('proto');
512 assertStringArg ('description', TRUE);
513 $remoteport = isset ($_REQUEST['remoteport']) ? $_REQUEST['remoteport'] : '';
514 if (!strlen ($remoteport))
515 $remoteport = $_REQUEST['localport'];
516
517 $error = newPortForwarding
518 (
519 $_REQUEST['object_id'],
520 $_REQUEST['localip'],
521 $_REQUEST['localport'],
522 $_REQUEST['remoteip'],
523 $remoteport,
524 $_REQUEST['proto'],
525 $_REQUEST['description']
526 );
527
528 if ($error == '')
529 return buildRedirectURL (__FUNCTION__, 'OK');
530 else
531 return buildRedirectURL (__FUNCTION__, 'ERR', array ($error));
532 }
533
534 $msgcode['delPortForwarding']['OK'] = 49;
535 $msgcode['delPortForwarding']['ERR'] = 111;
536 function delPortForwarding ()
537 {
538 assertUIntArg ('object_id');
539 assertIPv4Arg ('localip');
540 assertIPv4Arg ('remoteip');
541 assertUIntArg ('localport');
542 assertUIntArg ('remoteport');
543 assertStringArg ('proto');
544
545 $result = deletePortForwarding
546 (
547 $_REQUEST['object_id'],
548 $_REQUEST['localip'],
549 $_REQUEST['localport'],
550 $_REQUEST['remoteip'],
551 $_REQUEST['remoteport'],
552 $_REQUEST['proto']
553 );
554 buildRedirectURL (__FUNCTION__, $result !== FALSE ? 'OK' : 'ERR');
555 }
556
557 $msgcode['updPortForwarding']['OK'] = 51;
558 $msgcode['updPortForwarding']['ERR'] = 109;
559 function updPortForwarding ()
560 {
561 assertUIntArg ('object_id');
562 assertIPv4Arg ('localip');
563 assertIPv4Arg ('remoteip');
564 assertUIntArg ('localport');
565 assertUIntArg ('remoteport');
566 assertStringArg ('proto');
567 assertStringArg ('description');
568
569 $result = updatePortForwarding
570 (
571 $_REQUEST['object_id'],
572 $_REQUEST['localip'],
573 $_REQUEST['localport'],
574 $_REQUEST['remoteip'],
575 $_REQUEST['remoteport'],
576 $_REQUEST['proto'],
577 $_REQUEST['description']
578 );
579 buildRedirectURL (__FUNCTION__, $result !== FALSE ? 'OK' : 'ERR');
580 }
581
582 $msgcode['addPortForObject']['OK'] = 48;
583 function addPortForObject ()
584 {
585 assertStringArg ('port_name', TRUE);
586 genericAssertion ('port_l2address', 'l2address0');
587 genericAssertion ('port_name', 'string');
588 commitAddPort
589 (
590 $_REQUEST['object_id'],
591 trim ($_REQUEST['port_name']),
592 $_REQUEST['port_type_id'],
593 trim ($_REQUEST['port_label']),
594 trim ($_REQUEST['port_l2address'])
595 );
596 return buildRedirectURL (__FUNCTION__, 'OK', array ($_REQUEST['port_name']));
597 }
598
599 $msgcode['editPortForObject']['OK'] = 6;
600 function editPortForObject ()
601 {
602 global $sic;
603 assertUIntArg ('port_id');
604 assertUIntArg ('port_type_id');
605 assertStringArg ('reservation_comment', TRUE);
606 genericAssertion ('l2address', 'l2address0');
607 genericAssertion ('name', 'string');
608 commitUpdatePort ($sic['object_id'], $sic['port_id'], $sic['name'], $sic['port_type_id'], $sic['label'], $sic['l2address'], $sic['reservation_comment']);
609 return buildRedirectURL (__FUNCTION__, 'OK', array ($_REQUEST['name']));
610 }
611
612 $msgcode['linkPortForObject']['OK'] = 8;
613 $msgcode['linkPortForObject']['ERR'] = 100;
614 function linkPortForObject ()
615 {
616 assertUIntArg ('port_id');
617 assertUIntArg ('remote_port_id');
618 assertStringArg ('cable', TRUE);
619
620 // FIXME: ensure, that at least one of these ports belongs to the current object
621 $error = linkPorts ($_REQUEST['port_id'], $_REQUEST['remote_port_id'], $_REQUEST['cable']);
622 if ($error != '')
623 return buildRedirectURL (__FUNCTION__, 'ERR', array ($error));
624 global $sic;
625 $port_info = getPortInfo ($sic['port_id']);
626 return buildRedirectURL
627 (
628 __FUNCTION__,
629 'OK',
630 array
631 (
632 formatPortLink ($port_info['id'], $port_info['name'], NULL, NULL),
633 formatLinkedPort ($port_info),
634 )
635 );
636 }
637
638 $msgcode['addMultiPorts']['OK'] = 10;
639 $msgcode['addMultiPorts']['ERR'] = 123;
640 function addMultiPorts ()
641 {
642 assertStringArg ('format');
643 assertStringArg ('input');
644 assertStringArg ('port_type');
645 $format = $_REQUEST['format'];
646 $port_type = $_REQUEST['port_type'];
647 $object_id = $_REQUEST['object_id'];
648 // Input lines are escaped, so we have to explode and to chop by 2-char
649 // \n and \r respectively.
650 $lines1 = explode ("\n", $_REQUEST['input']);
651 foreach ($lines1 as $line)
652 {
653 $parts = explode ('\r', $line);
654 reset ($parts);
655 if (!strlen ($parts[0]))
656 continue;
657 else
658 $lines2[] = rtrim ($parts[0]);
659 }
660 $ports = array();
661 foreach ($lines2 as $line)
662 {
663 switch ($format)
664 {
665 case 'fisxii':
666 $words = explode (' ', preg_replace ('/[[:space:]]+/', ' ', $line));
667 list ($slot, $port) = explode ('/', $words[0]);
668 $ports[] = array
669 (
670 'name' => "e ${slot}/${port}",
671 'l2address' => $words[8],
672 'label' => "slot ${slot} port ${port}"
673 );
674 break;
675 case 'c3600asy':
676 $words = explode (' ', preg_replace ('/[[:space:]]+/', ' ', trim (substr ($line, 3))));
677 /*
678 How Async Lines are Numbered in Cisco 3600 Series Routers
679 http://www.cisco.com/en/US/products/hw/routers/ps274/products_tech_note09186a00801ca70b.shtml
680
681 Understanding 16- and 32-Port Async Network Modules
682 http://www.cisco.com/en/US/products/hw/routers/ps274/products_tech_note09186a00800a93f0.shtml
683 */
684 $async = $words[0];
685 $slot = floor (($async - 1) / 32);
686 $octalgroup = floor (($async - 1 - $slot * 32) / 8);
687 $cable = $async - $slot * 32 - $octalgroup * 8;
688 $og_label[0] = 'async 0-7';
689 $og_label[1] = 'async 8-15';
690 $og_label[2] = 'async 16-23';
691 $og_label[3] = 'async 24-31';
692 $ports[] = array
693 (
694 'name' => "async ${async}",
695 'l2address' => '',
696 'label' => "slot ${slot} " . $og_label[$octalgroup] . " cable ${cable}"
697 );
698 break;
699 case 'fiwg':
700 $words = explode (' ', preg_replace ('/[[:space:]]+/', ' ', $line));
701 $ifnumber = $words[0] * 1;
702 $ports[] = array
703 (
704 'name' => "e ${ifnumber}",
705 'l2address' => "${words[8]}",
706 'label' => "${ifnumber}"
707 );
708 break;
709 case 'ssv1':
710 $words = explode (' ', $line);
711 if (!strlen ($words[0]) or !strlen ($words[1]))
712 continue;
713 $ports[] = array
714 (
715 'name' => $words[0],
716 'l2address' => $words[1],
717 'label' => ''
718 );
719 break;
720 default:
721 return buildRedirectURL (__FUNCTION__, 'ERR');
722 break;
723 }
724 }
725 // Create ports, if they don't exist.
726 $added_count = $updated_count = $error_count = 0;
727 foreach ($ports as $port)
728 {
729 $port_ids = getPortIDs ($object_id, $port['name']);
730 if (!count ($port_ids))
731 {
732 commitAddPort ($object_id, $port['name'], $port_type, $port['label'], $port['l2address']);
733 $added_count++;
734 }
735 elseif (count ($port_ids) == 1) // update only single-socket ports
736 {
737 commitUpdatePort ($object_id, $port_ids[0], $port['name'], $port_type, $port['label'], $port['l2address']);
738 $updated_count++;
739 }
740 }
741 return buildRedirectURL (__FUNCTION__, 'OK', array ($added_count, $updated_count, $error_count));
742 }
743
744 $msgcode['addBulkPorts']['OK'] = 82;
745 function addBulkPorts ()
746 {
747 assertStringArg ('port_type_id');
748 assertStringArg ('port_name');
749 assertStringArg ('port_label', TRUE);
750 assertUIntArg ('port_numbering_start', TRUE);
751 assertUIntArg ('port_numbering_count');
752
753 $object_id = $_REQUEST['object_id'];
754 $port_name = $_REQUEST['port_name'];
755 $port_type_id = $_REQUEST['port_type_id'];
756 $port_label = $_REQUEST['port_label'];
757 $port_numbering_start = $_REQUEST['port_numbering_start'];
758 $port_numbering_count = $_REQUEST['port_numbering_count'];
759
760 $added_count = $error_count = 0;
761 if(strrpos($port_name, "%u") === false )
762 $port_name .= '%u';
763 for ($i=0,$c=$port_numbering_start; $i<$port_numbering_count; $i++,$c++)
764 {
765 commitAddPort ($object_id, @sprintf($port_name,$c), $port_type_id, @sprintf($port_label,$c), '');
766 $added_count++;
767 }
768 return buildRedirectURL (__FUNCTION__, 'OK', array ($added_count, $error_count));
769 }
770
771 $msgcode['updIPv4Allocation']['OK'] = 51;
772 $msgcode['updIPv4Allocation']['ERR'] = 109;
773 function updIPv4Allocation ()
774 {
775 assertIPv4Arg ('ip');
776 assertUIntArg ('object_id');
777 assertStringArg ('bond_name', TRUE);
778 genericAssertion ('bond_type', 'enum/inet4alloc');
779
780 $result = updateBond ($_REQUEST['ip'], $_REQUEST['object_id'], $_REQUEST['bond_name'], $_REQUEST['bond_type']);
781 return buildRedirectURL (__FUNCTION__, $result === FALSE ? 'ERR' : 'OK');
782 }
783
784 $msgcode['updIPv6Allocation']['OK'] = 51;
785 $msgcode['updIv6PAllocation']['ERR'] = 109;
786 function updIPv6Allocation ()
787 {
788 $ipv6 = assertIPv6Arg ('ip');
789 assertUIntArg ('object_id');
790 assertStringArg ('bond_name', TRUE);
791 genericAssertion ('bond_type', 'enum/inet6alloc');
792
793 $result = updateIPv6Bond ($ipv6, $_REQUEST['object_id'], $_REQUEST['bond_name'], $_REQUEST['bond_type']);
794 return buildRedirectURL (__FUNCTION__, $result === FALSE ? 'ERR' : 'OK');
795 }
796
797 $msgcode['delIPv4Allocation']['OK'] = 49;
798 $msgcode['delIPv4Allocation']['ERR'] = 111;
799 function delIPv4Allocation ()
800 {
801 assertIPv4Arg ('ip');
802 assertUIntArg ('object_id');
803
804 $result = unbindIpFromObject ($_REQUEST['ip'], $_REQUEST['object_id']);
805 return buildRedirectURL (__FUNCTION__, $result === FALSE ? 'ERR' : 'OK');
806 }
807
808 $msgcode['delIPv6Allocation']['OK'] = 49;
809 $msgcode['delIPv6Allocation']['ERR'] = 111;
810 function delIPv6Allocation ()
811 {
812 assertUIntArg ('object_id');
813 $ipv6 = assertIPv6Arg ('ip');
814 $result = unbindIPv6FromObject ($ipv6, $_REQUEST['object_id']);
815 return buildRedirectURL (__FUNCTION__, $result === FALSE ? 'ERR' : 'OK');
816 }
817
818 $msgcode['addIPv4Allocation']['OK'] = 48;
819 $msgcode['addIPv4Allocation']['ERR1'] = 170;
820 $msgcode['addIPv4Allocation']['ERR2'] = 100;
821 function addIPv4Allocation ()
822 {
823 assertIPv4Arg ('ip');
824 assertUIntArg ('object_id');
825 assertStringArg ('bond_name', TRUE);
826 genericAssertion ('bond_type', 'enum/inet4alloc');
827
828 // Strip masklen.
829 $ip = preg_replace ('@/[[:digit:]]+$@', '', $_REQUEST['ip']);
830 if (getConfigVar ('IPV4_JAYWALK') != 'yes' and NULL === getIPv4AddressNetworkId ($ip))
831 return buildRedirectURL (__FUNCTION__, 'ERR1', array ($ip));
832
833 if (FALSE === bindIpToObject ($ip, $_REQUEST['object_id'], $_REQUEST['bond_name'], $_REQUEST['bond_type']))
834 return buildRedirectURL (__FUNCTION__, 'ERR2', array ($error));
835 $address = getIPv4Address ($ip);
836 if ($address['reserved'] == 'yes' or strlen ($address['name']))
837 {
838 $release = getConfigVar ('IPV4_AUTO_RELEASE');
839 if ($release >= 1)
840 $address['reserved'] = 'no';
841 if ($release >= 2)
842 $address['name'] = '';
843 updateAddress ($ip, $address['name'], $address['reserved']);
844 }
845 return buildRedirectURL (__FUNCTION__, 'OK');
846 }
847
848 $msgcode['addIPv6Allocation']['OK'] = 48;
849 $msgcode['addIPv6Allocation']['ERR1'] = 170;
850 $msgcode['addIPv6Allocation']['ERR2'] = 100;
851 function addIPv6Allocation ()
852 {
853 assertUIntArg ('object_id');
854 assertStringArg ('bond_name', TRUE);
855 genericAssertion ('bond_type', 'enum/inet6alloc');
856
857 // Strip masklen.
858 $ipv6 = new IPv6Address;
859 if (! $ipv6->parse (preg_replace ('@/\d+$@', '', $_REQUEST['ip'])))
860 throw new InvalidRequestArgException('ip', $_REQUEST['ip'], 'parameter is not a valid ipv6 address');
861
862 if (getConfigVar ('IPV4_JAYWALK') != 'yes' and NULL === getIPv6AddressNetworkId ($ipv6))
863 return buildRedirectURL (__FUNCTION__, 'ERR1', array ($ip));
864
865 if (FALSE === bindIPv6ToObject ($ipv6, $_REQUEST['object_id'], $_REQUEST['bond_name'], $_REQUEST['bond_type']))
866 return buildRedirectURL (__FUNCTION__, 'ERR2', array ($error));
867 $address = getIPv6Address ($ipv6);
868 if ($address['reserved'] == 'yes' or strlen ($address['name']))
869 {
870 $release = getConfigVar ('IPV4_AUTO_RELEASE');
871 if ($release >= 1)
872 $address['reserved'] = 'no';
873 if ($release >= 2)
874 $address['name'] = '';
875 updateAddress ($ipv6, $address['name'], $address['reserved']);
876 }
877 return buildRedirectURL (__FUNCTION__, 'OK');
878 }
879
880 $msgcode['addIPv4Prefix']['OK'] = 48;
881 function addIPv4Prefix ()
882 {
883 assertStringArg ('range');
884 assertStringArg ('name', TRUE);
885
886 $is_bcast = isset ($_REQUEST['is_bcast']) ? $_REQUEST['is_bcast'] : 'off';
887 $taglist = isset ($_REQUEST['taglist']) ? $_REQUEST['taglist'] : array();
888 global $sic;
889 createIPv4Prefix ($_REQUEST['range'], $sic['name'], $is_bcast == 'on', $taglist);
890 return buildRedirectURL (__FUNCTION__, 'OK');
891 }
892
893 $msgcode['addIPv6Prefix']['OK'] = 48;
894 function addIPv6Prefix ()
895 {
896 assertStringArg ('range');
897 assertStringArg ('name', TRUE);
898
899 $taglist = isset ($_REQUEST['taglist']) ? $_REQUEST['taglist'] : array();
900 global $sic;
901 createIPv6Prefix ($_REQUEST['range'], $sic['name'], $taglist);
902 return buildRedirectURL (__FUNCTION__, 'OK');
903 }
904
905 $msgcode['delIPv4Prefix']['OK'] = 49;
906 function delIPv4Prefix ()
907 {
908 assertUIntArg ('id');
909 destroyIPv4Prefix ($_REQUEST['id']);
910 return buildRedirectURL (__FUNCTION__, 'OK');
911 }
912
913 $msgcode['delIPv6Prefix']['OK'] = 49;
914 function delIPv6Prefix ()
915 {
916 assertUIntArg ('id');
917 destroyIPv6Prefix ($_REQUEST['id']);
918 return buildRedirectURL (__FUNCTION__, 'OK');
919 }
920
921 $msgcode['editAddress']['OK'] = 51;
922 $msgcode['editAddress']['ERR'] = 100;
923 function editAddress ()
924 {
925 assertStringArg ('name', TRUE);
926
927 if (isset ($_REQUEST['reserved']))
928 $reserved = $_REQUEST['reserved'];
929 else
930 $reserved = 'off';
931 $error = updateAddress ($_REQUEST['ip'], $_REQUEST['name'], $reserved == 'on' ? 'yes' : 'no');
932 if ($error != '')
933 return buildRedirectURL (__FUNCTION__, 'ERR', array ($error));
934 else
935 return buildRedirectURL (__FUNCTION__, 'OK');
936 }
937
938 $msgcode['editv6Address']['OK'] = 51;
939 $msgcode['editv6Address']['ERR'] = 100;
940 function editv6Address ()
941 {
942 $ipv6 = assertIPArg ('ip');
943 assertStringArg ('name', TRUE);
944
945 if (isset ($_REQUEST['reserved']))
946 $reserved = $_REQUEST['reserved'];
947 else
948 $reserved = 'off';
949 $error = updateAddress ($ipv6, $_REQUEST['name'], $reserved == 'on' ? 'yes' : 'no');
950 if ($error != '')
951 return buildRedirectURL (__FUNCTION__, 'ERR', array ($error));
952 else
953 return buildRedirectURL (__FUNCTION__, 'OK');
954 }
955
956 $msgcode['createUser']['OK'] = 5;
957 $msgcode['createUser']['ERR'] = 102;
958 function createUser ()
959 {
960 assertStringArg ('username');
961 assertStringArg ('realname', TRUE);
962 assertStringArg ('password');
963 $username = $_REQUEST['username'];
964 $password = sha1 ($_REQUEST['password']);
965 $result = commitCreateUserAccount ($username, $_REQUEST['realname'], $password);
966 if ($result != TRUE)
967 return buildRedirectURL (__FUNCTION__, 'ERR', array ($username));
968 if (isset ($_REQUEST['taglist']))
969 produceTagsForLastRecord ('user', $_REQUEST['taglist']);
970 return buildRedirectURL (__FUNCTION__, 'OK', array ($username));
971 }
972
973 $msgcode['updateUser']['OK'] = 6;
974 $msgcode['updateUser']['ERR2'] = 104;
975 function updateUser ()
976 {
977 genericAssertion ('user_id', 'uint');
978 assertStringArg ('username');
979 assertStringArg ('realname', TRUE);
980 assertStringArg ('password');
981 $username = $_REQUEST['username'];
982 $new_password = $_REQUEST['password'];
983 $userinfo = spotEntity ('user', $_REQUEST['user_id']);
984 // Update user password only if provided password is not the same as current password hash.
985 if ($new_password != $userinfo['user_password_hash'])
986 $new_password = sha1 ($new_password);
987 $result = commitUpdateUserAccount ($_REQUEST['user_id'], $username, $_REQUEST['realname'], $new_password);
988 if ($result !== FALSE)
989 return buildRedirectURL (__FUNCTION__, 'OK', array ($username));
990 else
991 return buildRedirectURL (__FUNCTION__, 'ERR2', array ($username));
992 }
993
994 $msgcode['updateDictionary']['OK'] = 51;
995 function updateDictionary ()
996 {
997 assertUIntArg ('dict_key');
998 assertStringArg ('dict_value');
999 // this request must be built with chapter_no
1000 usePreparedUpdateBlade
1001 (
1002 'Dictionary',
1003 array ('dict_value' => $sic['dict_value']),
1004 array
1005 (
1006 'chapter_id' => $sic['chapter_no'],
1007 'dict_key' => $sic['dict_key'],
1008 )
1009 );
1010 return buildRedirectURL (__FUNCTION__, 'OK');
1011 }
1012
1013 $msgcode['updateChapter']['OK'] = 51;
1014 function updateChapter ()
1015 {
1016 assertUIntArg ('chapter_no');
1017 assertStringArg ('chapter_name');
1018 usePreparedUpdateBlade
1019 (
1020 'Chapter',
1021 array
1022 (
1023 'name' => $chapter_name,
1024 ),
1025 array
1026 (
1027 'id' => $chapter_no,
1028 'sticky' => 'no', // note this constant, it protects system chapters
1029 )
1030 );
1031 return buildRedirectURL (__FUNCTION__, 'OK');
1032 }
1033
1034 $msgcode['delChapter']['OK'] = 49;
1035 $msgcode['delChapter']['ERR'] = 111;
1036 function delChapter ()
1037 {
1038 assertUIntArg ('chapter_no');
1039 if (commitDeleteChapter ($_REQUEST['chapter_no']))
1040 return buildRedirectURL (__FUNCTION__, 'OK');
1041 else
1042 return buildRedirectURL (__FUNCTION__, 'ERR');
1043 }
1044
1045 $msgcode['supplementAttrMap']['OK'] = 48;
1046 $msgcode['supplementAttrMap']['ERR1'] = 154;
1047 $msgcode['supplementAttrMap']['ERR2'] = 110;
1048 function supplementAttrMap ()
1049 {
1050 assertUIntArg ('attr_id');
1051 assertUIntArg ('objtype_id');
1052 $attrMap = getAttrMap();
1053 if ($attrMap[$_REQUEST['attr_id']]['type'] != 'dict')
1054 $chapter_id = NULL;
1055 else
1056 {
1057 try
1058 {
1059 assertUIntArg ('chapter_no');
1060 }
1061 catch (InvalidRequestArgException $e)
1062 {
1063 return buildRedirectURL (__FUNCTION__, 'ERR1', array ('chapter not selected'));
1064 }
1065 $chapter_id = $_REQUEST['chapter_no'];
1066 }
1067 if (commitSupplementAttrMap ($_REQUEST['attr_id'], $_REQUEST['objtype_id'], $chapter_id) !== FALSE)
1068 return buildRedirectURL (__FUNCTION__, 'OK');
1069 else
1070 return buildRedirectURL (__FUNCTION__, 'ERR2');
1071 }
1072
1073 $msgcode['clearSticker']['OK'] = 49;
1074 function clearSticker ()
1075 {
1076 global $sic;
1077 assertUIntArg ('attr_id');
1078 commitUpdateAttrValue (getBypassValue(), $sic['attr_id']);
1079 }
1080
1081 $msgcode['updateObjectAllocation']['OK'] = 63;
1082 function updateObjectAllocation ()
1083 {
1084 global $remote_username, $sic;
1085 if (!isset ($_REQUEST['got_atoms']))
1086 {
1087 unset($_GET['page']);
1088 unset($_GET['tab']);
1089 unset($_GET['op']);
1090 unset($_POST['page']);
1091 unset($_POST['tab']);
1092 unset($_POST['op']);
1093 return buildWideRedirectURL (array(), NULL, NULL, array_merge ($_GET, $_POST));
1094 }
1095 $object_id = getBypassValue();
1096 $workingRacksData = array();
1097 foreach ($_REQUEST['rackmulti'] as $cand_id)
1098 {
1099 if (!isset ($workingRacksData[$cand_id]))
1100 {
1101 $rackData = spotEntity ('rack', $cand_id);
1102 amplifyCell ($rackData);
1103 $workingRacksData[$cand_id] = $rackData;
1104 }
1105 }
1106
1107 foreach ($workingRacksData as &$rd)
1108 applyObjectMountMask ($rd, $object_id);
1109
1110 $oldMolecule = getMoleculeForObject ($object_id);
1111 $changecnt = 0;
1112 $log = array();
1113 foreach ($workingRacksData as $rack_id => $rackData)
1114 {
1115 $logrecord = processGridForm ($rackData, 'F', 'T', $object_id);
1116 $log[] = $logrecord;
1117 if ($logrecord['code'] == 300)
1118 continue;
1119 $changecnt++;
1120 // Reload our working copy after form processing.
1121 $rackData = spotEntity ('rack', $cand_id);
1122 amplifyCell ($rackData);
1123 applyObjectMountMask ($rackData, $object_id);
1124 $workingRacksData[$rack_id] = $rackData;
1125 }
1126 if (!$changecnt)
1127 return buildRedirectURL (__FUNCTION__, 'OK', $changecnt);
1128 // Log a record.
1129 $newMolecule = getMoleculeForObject ($object_id);
1130 usePreparedInsertBlade
1131 (
1132 'MountOperation',
1133 array
1134 (
1135 'object_id' => $object_id,
1136 'old_molecule_id' => count ($oldMolecule) ? createMolecule ($oldMolecule) : NULL,
1137 'new_molecule_id' => count ($newMolecule) ? createMolecule ($newMolecule) : NULL,
1138 'user_name' => $remote_username,
1139 'comment' => empty ($sic['comment']) ? NULL : $sic['comment'],
1140 )
1141 );
1142 $log[] = array ('code' => 200, 'message' => 'history logged');
1143 return buildWideRedirectURL ($log);
1144 }
1145
1146 $msgcode['updateObject']['OK'] = 51;
1147 function updateObject ()
1148 {
1149 genericAssertion ('num_attrs', 'uint0');
1150 genericAssertion ('object_name', 'string0');
1151 genericAssertion ('object_label', 'string0');
1152 genericAssertion ('object_asset_no', 'string0');
1153 genericAssertion ('object_comment', 'string0');
1154 genericAssertion ('object_type_id', 'uint');
1155 if (array_key_exists ('object_has_problems', $_REQUEST) and $_REQUEST['object_has_problems'] == 'on')
1156 $has_problems = 'yes';
1157 else
1158 $has_problems = 'no';
1159 $object_id = getBypassValue();
1160
1161 global $dbxlink, $sic;
1162 $dbxlink->beginTransaction();
1163 commitUpdateObject
1164 (
1165 $object_id,
1166 $_REQUEST['object_name'],
1167 $_REQUEST['object_label'],
1168 $has_problems,
1169 $_REQUEST['object_asset_no'],
1170 $_REQUEST['object_comment']
1171 );
1172 // Update optional attributes
1173 $oldvalues = getAttrValues ($object_id);
1174 for ($i = 0; $i < $_REQUEST['num_attrs']; $i++)
1175 {
1176 genericAssertion ("${i}_attr_id", 'uint');
1177 $attr_id = $_REQUEST["${i}_attr_id"];
1178 if (! array_key_exists ($attr_id, $oldvalues))
1179 throw new InvalidRequestArgException ('attr_id', $attr_id, 'malformed request');
1180 $value = $_REQUEST["${i}_value"];
1181
1182 # Delete attribute and move on, when the field is empty or if the field
1183 # type is a dictionary and it is the "--NOT SET--" value of 0.
1184 if ($value == '' || ($oldvalues[$attr_id]['type'] == 'dict' && $value == 0))
1185 {
1186 commitUpdateAttrValue ($object_id, $attr_id);
1187 continue;
1188 }
1189
1190 // The value could be uint/float, but we don't know ATM. Let SQL
1191 // server check this and complain.
1192 assertStringArg ("${i}_value");
1193 switch ($oldvalues[$attr_id]['type'])
1194 {
1195 case 'uint':
1196 case 'float':
1197 case 'string':
1198 $oldvalue = $oldvalues[$attr_id]['value'];
1199 break;
1200 case 'dict':
1201 $oldvalue = $oldvalues[$attr_id]['key'];
1202 break;
1203 default:
1204 }
1205 if ($value === $oldvalue) // ('' == 0), but ('' !== 0)
1206 continue;
1207 commitUpdateAttrValue ($object_id, $attr_id, $value);
1208 }
1209 $object = spotEntity ('object', $object_id);
1210 if ($sic['object_type_id'] != $object['objtype_id'])
1211 {
1212 if (! array_key_exists ($sic['object_type_id'], getObjectTypeChangeOptions ($object_id)))
1213 throw new InvalidRequestArgException ('new type_id', $sic['object_type_id'], 'incompatible with requested attribute values');
1214 usePreparedUpdateBlade ('RackObject', array ('objtype_id' => $sic['object_type_id']), array ('id' => $object_id));
1215 }
1216 // Invalidate thumb cache of all racks objects could occupy.
1217 foreach (getResidentRacksData ($object_id, FALSE) as $rack_id)
1218 usePreparedUpdateBlade ('Rack', array ('thumb_data' => NULL), array ('id' => $rack_id));
1219 $dbxlink->commit();
1220 return buildRedirectURL (__FUNCTION__, 'OK');
1221 }
1222
1223 function addMultipleObjects()
1224 {
1225 $log = emptyLog();
1226 $taglist = isset ($_REQUEST['taglist']) ? $_REQUEST['taglist'] : array();
1227 $max = getConfigVar ('MASSCOUNT');
1228 for ($i = 0; $i < $max; $i++)
1229 {
1230 if (!isset ($_REQUEST["${i}_object_type_id"]))
1231 {
1232 $log = mergeLogs ($log, oneLiner (184, array ($i + 1)));
1233 break;
1234 }
1235
1236 // set to empty values for virtual objects
1237 if (isset ($_REQUEST['virtual_objects']))
1238 {
1239 $_REQUEST["${i}_object_label"] = '';
1240 $_REQUEST["${i}_object_asset_no"] = '';
1241 }
1242
1243 assertUIntArg ("${i}_object_type_id", TRUE);
1244 assertStringArg ("${i}_object_name", TRUE);
1245 assertStringArg ("${i}_object_label", TRUE);
1246 assertStringArg ("${i}_object_asset_no", TRUE);
1247 $name = $_REQUEST["${i}_object_name"];
1248
1249 // It's better to skip silently, than to print a notice.
1250 if ($_REQUEST["${i}_object_type_id"] == 0)
1251 continue;
1252 if (($object_id = commitAddObject
1253 (
1254 $name,
1255 $_REQUEST["${i}_object_label"],
1256 $_REQUEST["${i}_object_type_id"],
1257 $_REQUEST["${i}_object_asset_no"],
1258 $taglist
1259 )) !== FALSE){
1260 $info = spotEntity ('object', $object_id);
1261 // FIXME: employ amplifyCell() instead of calling loader functions directly
1262 amplifyCell ($info);
1263 $log = mergeLogs ($log, oneLiner (5, array ('<a href="' . makeHref (array ('page' => 'object', 'tab' => 'default', 'object_id' => $object_id)) . '">' . $info['dname'] . '</a>')));
1264 }else{
1265 $log = mergeLogs ($log, oneLiner (147, array ($name)));
1266 }
1267 }
1268 return buildWideRedirectURL ($log);
1269 }
1270
1271 function addLotOfObjects()
1272 {
1273 $log = emptyLog();
1274 $taglist = isset ($_REQUEST['taglist']) ? $_REQUEST['taglist'] : array();
1275 assertUIntArg ('global_type_id', TRUE);
1276 assertStringArg ('namelist', TRUE);
1277 $global_type_id = $_REQUEST['global_type_id'];
1278 if ($global_type_id == 0 or !strlen ($_REQUEST['namelist']))
1279 $log = mergeLogs ($log, oneLiner (186));
1280 else
1281 {
1282 // The name extractor below was stolen from ophandlers.php:addMultiPorts()
1283 $names1 = explode ("\n", $_REQUEST['namelist']);
1284 $names2 = array();
1285 foreach ($names1 as $line)
1286 {
1287 $parts = explode ('\r', $line);
1288 reset ($parts);
1289 if (!strlen ($parts[0]))
1290 continue;
1291 else
1292 $names2[] = rtrim ($parts[0]);
1293 }
1294 foreach ($names2 as $name)
1295 if (($object_id = commitAddObject ($name, '', $global_type_id, '', $taglist)) !== FALSE)
1296 {
1297 $info = spotEntity ('object', $object_id);
1298 amplifyCell ($info);
1299 $log = mergeLogs ($log, oneLiner (5, array ('<a href="' . makeHref (array ('page' => 'object', 'tab' => 'default', 'object_id' => $object_id)) . '">' . $info['dname'] . '</a>')));
1300 }
1301 else
1302 $log = mergeLogs ($log, oneLiner (147, array ($name)));
1303 }
1304 return buildWideRedirectURL ($log);
1305 }
1306
1307 $msgcode['deleteObject']['OK'] = 6;
1308 function deleteObject ()
1309 {
1310 assertUIntArg ('object_id');
1311 $oinfo = spotEntity ('object', $_REQUEST['object_id']);
1312
1313 $racklist = getResidentRacksData ($_REQUEST['object_id'], FALSE);
1314 commitDeleteObject ($_REQUEST['object_id']);
1315 foreach ($racklist as $rack_id)
1316 usePreparedUpdateBlade ('Rack', array ('thumb_data' => NULL), array ('id' => $rack_id));
1317 return buildRedirectURL (__FUNCTION__, 'OK', array ($oinfo['dname']));
1318 }
1319
1320 $msgcode['resetObject']['OK'] = 57;
1321 function resetObject ()
1322 {
1323 $racklist = getResidentRacksData (getBypassValue(), FALSE);
1324 commitResetObject (getBypassValue());
1325 foreach ($racklist as $rack_id)
1326 usePreparedUpdateBlade ('Rack', array ('thumb_data' => NULL), array ('id' => $rack_id));
1327 return buildRedirectURL (__FUNCTION__, 'OK');
1328 }
1329
1330 $msgcode['useupPort']['OK'] = 49;
1331 function useupPort ()
1332 {
1333 assertUIntArg ('port_id');
1334 commitUpdatePortComment ($_REQUEST['port_id'], '');
1335 return buildRedirectURL (__FUNCTION__, 'OK');
1336 }
1337
1338 $msgcode['updateUI']['OK'] = 51;
1339 function updateUI ()
1340 {
1341 assertUIntArg ('num_vars');
1342
1343 for ($i = 0; $i < $_REQUEST['num_vars']; $i++)
1344 {
1345 assertStringArg ("${i}_varname");
1346 assertStringArg ("${i}_varvalue", TRUE);
1347 $varname = $_REQUEST["${i}_varname"];
1348 $varvalue = $_REQUEST["${i}_varvalue"];
1349
1350 // If form value = value in DB, don't bother updating DB
1351 if (!isConfigVarChanged($varname, $varvalue))
1352 continue;
1353 // any exceptions will be handled by process.php
1354 setConfigVar ($varname, $varvalue, TRUE);
1355 }
1356 return buildRedirectURL (__FUNCTION__, 'OK');
1357 }
1358
1359 $msgcode['saveMyPreferences']['OK'] = 51;
1360 function saveMyPreferences ()
1361 {
1362 assertUIntArg ('num_vars');
1363
1364 for ($i = 0; $i < $_REQUEST['num_vars']; $i++)
1365 {
1366 assertStringArg ("${i}_varname");
1367 assertStringArg ("${i}_varvalue", TRUE);
1368 $varname = $_REQUEST["${i}_varname"];
1369 $varvalue = $_REQUEST["${i}_varvalue"];
1370
1371 // If form value = value in DB, don't bother updating DB
1372 if (!isConfigVarChanged($varname, $varvalue))
1373 continue;
1374 setUserConfigVar ($varname, $varvalue);
1375 }
1376 return buildRedirectURL (__FUNCTION__, 'OK');
1377 }
1378
1379 $msgcode['resetMyPreference']['OK'] = 51;
1380 function resetMyPreference ()
1381 {
1382 assertStringArg ("varname");
1383 resetUserConfigVar ($_REQUEST["varname"]);
1384 return buildRedirectURL (__FUNCTION__, 'OK');
1385 }
1386
1387 $msgcode['resetUIConfig']['OK'] = 57;
1388 function resetUIConfig()
1389 {
1390 setConfigVar ('MASSCOUNT','8');
1391 setConfigVar ('MAXSELSIZE','30');
1392 setConfigVar ('ROW_SCALE','2');
1393 setConfigVar ('PORTS_PER_ROW','12');
1394 setConfigVar ('IPV4_ADDRS_PER_PAGE','256');
1395 setConfigVar ('DEFAULT_RACK_HEIGHT','42');
1396 setConfigVar ('DEFAULT_SLB_VS_PORT','');
1397 setConfigVar ('DEFAULT_SLB_RS_PORT','');
1398 setConfigVar ('DETECT_URLS','no');
1399 setConfigVar ('RACK_PRESELECT_THRESHOLD','1');
1400 setConfigVar ('DEFAULT_IPV4_RS_INSERVICE','no');
1401 setConfigVar ('AUTOPORTS_CONFIG','4 = 1*33*kvm + 2*24*eth%u;15 = 1*446*kvm');
1402 setConfigVar ('SHOW_EXPLICIT_TAGS','yes');
1403 setConfigVar ('SHOW_IMPLICIT_TAGS','yes');
1404 setConfigVar ('SHOW_AUTOMATIC_TAGS','no');
1405 setConfigVar ('DEFAULT_OBJECT_TYPE','4');
1406 setConfigVar ('IPV4_AUTO_RELEASE','1');
1407 setConfigVar ('SHOW_LAST_TAB', 'no');
1408 setConfigVar ('EXT_IPV4_VIEW', 'yes');
1409 setConfigVar ('TREE_THRESHOLD', '25');
1410 setConfigVar ('IPV4_JAYWALK', 'no');
1411 setConfigVar ('ADDNEW_AT_TOP', 'yes');
1412 setConfigVar ('IPV4_TREE_SHOW_USAGE', 'yes');
1413 setConfigVar ('PREVIEW_TEXT_MAXCHARS', '10240');
1414 setConfigVar ('PREVIEW_TEXT_ROWS', '25');
1415 setConfigVar ('PREVIEW_TEXT_COLS', '80');
1416 setConfigVar ('PREVIEW_IMAGE_MAXPXS', '320');
1417 setConfigVar ('VENDOR_SIEVE', '');
1418 setConfigVar ('IPV4LB_LISTSRC', '{$typeid_4}');
1419 setConfigVar ('IPV4OBJ_LISTSRC','{$typeid_4} or {$typeid_7} or {$typeid_8} or {$typeid_12} or {$typeid_445} or {$typeid_447} or {$typeid_798} or {$typeid_1504}');
1420 setConfigVar ('IPV4NAT_LISTSRC','{$typeid_4} or {$typeid_7} or {$typeid_8} or {$typeid_798}');
1421 setConfigVar ('ASSETWARN_LISTSRC','{$typeid_4} or {$typeid_7} or {$typeid_8}');
1422 setConfigVar ('NAMEWARN_LISTSRC','{$typeid_4} or {$typeid_7} or {$typeid_8}');
1423 setConfigVar ('RACKS_PER_ROW','12');
1424 setConfigVar ('FILTER_PREDICATE_SIEVE','');
1425 setConfigVar ('FILTER_DEFAULT_ANDOR','or');
1426 setConfigVar ('FILTER_SUGGEST_ANDOR','yes');
1427 setConfigVar ('FILTER_SUGGEST_TAGS','yes');
1428 setConfigVar ('FILTER_SUGGEST_PREDICATES','yes');
1429 setConfigVar ('FILTER_SUGGEST_EXTRA','no');
1430 setConfigVar ('DEFAULT_SNMP_COMMUNITY','public');
1431 setConfigVar ('IPV4_ENABLE_KNIGHT','yes');
1432 setConfigVar ('TAGS_TOPLIST_SIZE','50');
1433 setConfigVar ('TAGS_QUICKLIST_SIZE','20');
1434 setConfigVar ('TAGS_QUICKLIST_THRESHOLD','50');
1435 setConfigVar ('ENABLE_MULTIPORT_FORM', 'no');
1436 setConfigVar ('DEFAULT_PORT_IIF_ID', '1');
1437 setConfigVar ('DEFAULT_PORT_OIF_IDS', '1=24; 3=1078; 4=1077; 5=1079; 6=1080; 8=1082; 9=1084');
1438 setConfigVar ('IPV4_TREE_RTR_AS_CELL', 'yes');
1439 setConfigVar ('PROXIMITY_RANGE', 0);
1440 setConfigVar ('IPV4_TREE_SHOW_VLAN', 'yes');
1441 setConfigVar ('VLANSWITCH_LISTSRC', '');
1442 setConfigVar ('VLANIPV4NET_LISTSRC', '');
1443 setConfigVar ('DEFAULT_VDOM_ID', '');
1444 setConfigVar ('DEFAULT_VST_ID', '');
1445 setConfigVar ('STATIC_FILTER', 'yes');
1446 setConfigVar ('8021Q_DEPLOY_MINAGE', '300');
1447 setConfigVar ('8021Q_DEPLOY_MAXAGE', '3600');
1448 setConfigVar ('8021Q_DEPLOY_RETRY', '10800');
1449 setConfigVar ('8021Q_WRI_AFTER_CONFT_LISTSRC', 'false');
1450 setConfigVar ('8021Q_INSTANT_DEPLOY', 'no');
1451 setConfigVar ('CDP_RUNNERS_LISTSRC', '');
1452 setConfigVar ('LLDP_RUNNERS_LISTSRC', '');
1453 setConfigVar ('HNDP_RUNNERS_LISTSRC', '');
1454 setConfigVar ('SHRINK_TAG_TREE_ON_CLICK', 'yes');
1455 setConfigVar ('MAX_UNFILTERED_ENTITIES', '0');
1456 setConfigVar ('SYNCDOMAIN_MAX_PROCESSES', '0');
1457 setConfigVar ('PORT_EXCLUSION_LISTSRC', '{$typeid_3} or {$typeid_10} or {$typeid_11} or {$typeid_1505} or {$typeid_1506}');
1458 setConfigVar ('FILTER_RACKLIST_BY_TAGS', 'yes');
1459 setConfigVar ('SSH_OBJS_LISTSRC', 'none');
1460 setConfigVar ('TELNET_OBJS_LISTSRC', 'none');
1461 return buildRedirectURL (__FUNCTION__, 'OK');
1462 }
1463
1464 $msgcode['addRealServer']['OK'] = 48;
1465 $msgcode['addRealServer']['ERR'] = 110;
1466 // Add single record.
1467 function addRealServer ()
1468 {
1469 assertIPv4Arg ('remoteip');
1470 assertStringArg ('rsport', TRUE);
1471 assertStringArg ('rsconfig', TRUE);
1472 if (!addRStoRSPool (
1473 getBypassValue(),
1474 $_REQUEST['remoteip'],
1475 $_REQUEST['rsport'],
1476 getConfigVar ('DEFAULT_IPV4_RS_INSERVICE'),
1477 $_REQUEST['rsconfig']
1478 ))
1479 return buildRedirectURL (__FUNCTION__, 'ERR');
1480 else
1481 return buildRedirectURL (__FUNCTION__, 'OK');
1482 }
1483
1484 $msgcode['addRealServers']['OK'] = 37;
1485 $msgcode['addRealServers']['ERR1'] = 131;
1486 $msgcode['addRealServers']['ERR2'] = 127;
1487 // Parse textarea submitted and try adding a real server for each line.
1488 function addRealServers ()
1489 {
1490 assertStringArg ('format');
1491 assertStringArg ('rawtext');
1492 $ngood = $nbad = 0;
1493 $rsconfig = '';
1494 // Keep in mind, that the text will have HTML entities (namely '>') escaped.
1495 foreach (explode ("\n", dos2unix ($_REQUEST['rawtext'])) as $line)
1496 {
1497 if (!strlen ($line))
1498 continue;
1499 $match = array ();
1500 switch ($_REQUEST['format'])
1501 {
1502 case 'ipvs_2': // address and port only
1503 if (!preg_match ('/^ -&gt; ([0-9\.]+):([0-9]+) /', $line, $match))
1504 continue;
1505 if (addRStoRSPool (getBypassValue(), $match[1], $match[2], getConfigVar ('DEFAULT_IPV4_RS_INSERVICE'), ''))
1506 $ngood++;
1507 else
1508 $nbad++;
1509 break;
1510 case 'ipvs_3': // address, port and weight
1511 if (!preg_match ('/^ -&gt; ([0-9\.]+):([0-9]+) +[a-zA-Z]+ +([0-9]+) /', $line, $match))
1512 continue;
1513 if (addRStoRSPool (getBypassValue(), $match[1], $match[2], getConfigVar ('DEFAULT_IPV4_RS_INSERVICE'), 'weight ' . $match[3]))
1514 $ngood++;
1515 else
1516 $nbad++;
1517 break;
1518 case 'ssv_2': // IP address and port
1519 if (!preg_match ('/^([0-9\.]+) ([0-9]+)$/', $line, $match))
1520 continue;
1521 if (addRStoRSPool (getBypassValue(), $match[1], $match[2], getConfigVar ('DEFAULT_IPV4_RS_INSERVICE'), ''))
1522 $ngood++;
1523 else
1524 $nbad++;
1525 break;
1526 case 'ssv_1': // IP address
1527 if (!preg_match ('/^([0-9\.]+)$/', $line, $match))
1528 continue;
1529 if (addRStoRSPool (getBypassValue(), $match[1], 0, getConfigVar ('DEFAULT_IPV4_RS_INSERVICE'), ''))
1530 $ngood++;
1531 else
1532 $nbad++;
1533 break;
1534 default:
1535 return buildRedirectURL (__FUNCTION__, 'ERR1');
1536 break;
1537 }
1538 }
1539 if ($nbad == 0 and $ngood > 0)
1540 return buildRedirectURL (__FUNCTION__, 'OK', array ($ngood));
1541 else
1542 return buildRedirectURL (__FUNCTION__, 'ERR2', array ($ngood, $nbad));
1543 }
1544
1545 $msgcode['addVService']['OK'] = 48;
1546 function addVService ()
1547 {
1548 assertIPv4Arg ('vip');
1549 assertUIntArg ('vport');
1550 genericAssertion ('proto', 'enum/ipproto');
1551 assertStringArg ('name', TRUE);
1552 assertStringArg ('vsconfig', TRUE);
1553 assertStringArg ('rsconfig', TRUE);
1554 usePreparedExecuteBlade
1555 (
1556 'INSERT INTO IPv4VS (vip, vport, proto, name, vsconfig, rsconfig) VALUES (INET_ATON(?), ?, ?, ?, ?, ?)',
1557 array
1558 (
1559 $_REQUEST['vip'],
1560 $_REQUEST['vport'],
1561 $_REQUEST['proto'],
1562 !mb_strlen ($_REQUEST['name']) ? NULL : $_REQUEST['name'],
1563 !strlen ($_REQUEST['vsconfig']) ? NULL : $_REQUEST['vsconfig'],
1564 !strlen ($_REQUEST['rsconfig']) ? NULL : $_REQUEST['rsconfig'],
1565 )
1566 );
1567 produceTagsForLastRecord ('ipv4vs', isset ($_REQUEST['taglist']) ? $_REQUEST['taglist'] : array());
1568 return buildRedirectURL (__FUNCTION__, 'OK');
1569 }
1570
1571 $msgcode['deleteVService']['OK'] = 49;
1572 $msgcode['deleteVService']['ERR'] = 111;
1573 function deleteVService ()
1574 {
1575 assertUIntArg ('vs_id');
1576 if (!commitDeleteVS ($_REQUEST['vs_id']))
1577 return buildRedirectURL (__FUNCTION__, 'ERR');
1578 else
1579 return buildRedirectURL (__FUNCTION__, 'OK');
1580 }
1581
1582 $msgcode['updateSLBDefConfig']['OK'] = 43;
1583 $msgcode['updateSLBDefConfig']['ERR'] = 109;
1584 function updateSLBDefConfig ()
1585 {
1586 $data = array(
1587 'vs' => $_REQUEST['vsconfig'],
1588 'rs' => $_REQUEST['rsconfig']
1589 );
1590 if (!commitUpdateSLBDefConf ($data))
1591 return buildRedirectURL (__FUNCTION__, 'ERR');
1592 else
1593 return buildRedirectURL (__FUNCTION__, 'OK');
1594 }
1595
1596 $msgcode['updateRealServer']['OK'] = 51;
1597 $msgcode['updateRealServer']['ERR'] = 109;
1598 function updateRealServer ()
1599 {
1600 assertUIntArg ('rs_id');
1601 assertIPv4Arg ('rsip');
1602 assertStringArg ('rsport', TRUE);
1603 assertStringArg ('rsconfig', TRUE);
1604 if (FALSE === commitUpdateRS (
1605 $_REQUEST['rs_id'],
1606 $_REQUEST['rsip'],
1607 $_REQUEST['rsport'],
1608 $_REQUEST['rsconfig']
1609 ))
1610 return buildRedirectURL (__FUNCTION__, 'ERR');
1611 else
1612 return buildRedirectURL (__FUNCTION__, 'OK');
1613 }
1614
1615 $msgcode['updateVService']['OK'] = 51;
1616 $msgcode['updateVService']['ERR'] = 109;
1617 function updateVService ()
1618 {
1619 assertUIntArg ('vs_id');
1620 assertIPv4Arg ('vip');
1621 assertUIntArg ('vport');
1622 genericAssertion ('proto', 'enum/ipproto');
1623 assertStringArg ('name', TRUE);
1624 assertStringArg ('vsconfig', TRUE);
1625 assertStringArg ('rsconfig', TRUE);
1626 if (FALSE === commitUpdateVS (
1627 $_REQUEST['vs_id'],
1628 $_REQUEST['vip'],
1629 $_REQUEST['vport'],
1630 $_REQUEST['proto'],
1631 $_REQUEST['name'],
1632 $_REQUEST['vsconfig'],
1633 $_REQUEST['rsconfig']
1634 ))
1635 return buildRedirectURL (__FUNCTION__, 'ERR');
1636 else
1637 return buildRedirectURL (__FUNCTION__, 'OK');
1638 }
1639
1640 $msgcode['addLoadBalancer']['OK'] = 48;
1641 $msgcode['addLoadBalancer']['ERR'] = 110;
1642 function addLoadBalancer ()
1643 {
1644 assertUIntArg ('pool_id');
1645 assertUIntArg ('object_id');
1646 assertUIntArg ('vs_id');
1647 assertStringArg ('vsconfig', TRUE);
1648 assertStringArg ('rsconfig', TRUE);
1649 if (! empty($_REQUEST['prio']))
1650 assertUIntArg('prio', TRUE);
1651
1652 if (!addLBtoRSPool (
1653 $_REQUEST['pool_id'],
1654 $_REQUEST['object_id'],
1655 $_REQUEST['vs_id'],
1656 $_REQUEST['vsconfig'],
1657 $_REQUEST['rsconfig'],
1658 $_REQUEST['prio']
1659 ))
1660 return buildRedirectURL (__FUNCTION__, 'ERR');
1661 else
1662 return buildRedirectURL (__FUNCTION__, 'OK');
1663 }
1664
1665 $msgcode['addRSPool']['OK'] = 48;
1666 function addRSPool ()
1667 {
1668 assertStringArg ('name');
1669 assertStringArg ('vsconfig', TRUE);
1670 assertStringArg ('rsconfig', TRUE);
1671 commitCreateRSPool
1672 (
1673 $_REQUEST['name'],
1674 $_REQUEST['vsconfig'],
1675 $_REQUEST['rsconfig'],
1676 isset ($_REQUEST['taglist']) ? $_REQUEST['taglist'] : array()
1677 );
1678 return buildRedirectURL (__FUNCTION__, 'OK');
1679 }
1680
1681 $msgcode['deleteRSPool']['OK'] = 49;
1682 $msgcode['deleteRSPool']['ERR'] = 111;
1683 function deleteRSPool ()
1684 {
1685 assertUIntArg ('pool_id');
1686 if (commitDeleteRSPool ($_REQUEST['pool_id']) === FALSE)
1687 return buildRedirectURL (__FUNCTION__, 'ERR');
1688 else
1689 return buildRedirectURL (__FUNCTION__, 'OK');
1690 }
1691
1692 $msgcode['updateRSInService']['OK'] = 26;
1693 $msgcode['updateRSInService']['ERR'] = 141;
1694 function updateRSInService ()
1695 {
1696 assertUIntArg ('rscount');
1697 $orig = spotEntity ('ipv4rspool', getBypassValue());
1698 amplifyCell ($orig);
1699 $nbad = $ngood = 0;
1700 for ($i = 1; $i <= $_REQUEST['rscount']; $i++)
1701 {
1702 $rs_id = $_REQUEST["rsid_${i}"];
1703 if (isset ($_REQUEST["inservice_${i}"]) and $_REQUEST["inservice_${i}"] == 'on')
1704 $newval = 'yes';
1705 else
1706 $newval = 'no';
1707 if ($newval != $orig['rslist'][$rs_id]['inservice'])
1708 {
1709 if (FALSE !== commitSetInService ($rs_id, $newval))
1710 $ngood++;
1711 else
1712 $nbad++;
1713 }
1714 }
1715 if (!$nbad)
1716 return buildRedirectURL (__FUNCTION__, 'OK', array ($ngood));
1717 else
1718 return buildRedirectURL (__FUNCTION__, 'ERR', array ($nbad, $ngood));
1719 }
1720
1721 $msgcode['importPTRData']['OK'] = 26;
1722 $msgcode['importPTRData']['ERR'] = 141;
1723 // FIXME: check, that each submitted address belongs to the prefix we
1724 // are operating on.
1725 function importPTRData ()
1726 {
1727 assertUIntArg ('addrcount');
1728 $nbad = $ngood = 0;
1729 for ($i = 0; $i < $_REQUEST['addrcount']; $i++)
1730 {
1731 $inputname = "import_${i}";
1732 if (!isset ($_REQUEST[$inputname]) or $_REQUEST[$inputname] != 'on')
1733 continue;
1734 assertIPv4Arg ("addr_${i}");
1735 assertStringArg ("descr_${i}", TRUE);
1736 assertStringArg ("rsvd_${i}");
1737 // Non-existent addresses will not have this argument set in request.
1738 $rsvd = 'no';
1739 if ($_REQUEST["rsvd_${i}"] == 'yes')
1740 $rsvd = 'yes';
1741 if (updateAddress ($_REQUEST["addr_${i}"], $_REQUEST["descr_${i}"], $rsvd) == '')
1742 $ngood++;
1743 else
1744 $nbad++;
1745 }
1746 if (!$nbad)
1747 return buildRedirectURL (__FUNCTION__, 'OK', array ($ngood));
1748 else
1749 return buildRedirectURL (__FUNCTION__, 'ERR', array ($nbad, $ngood));
1750 }
1751
1752 $msgcode['generateAutoPorts']['OK'] = 21;
1753 function generateAutoPorts ()
1754 {
1755 $object = spotEntity ('object', getBypassValue());
1756 executeAutoPorts ($object['id'], $object['objtype_id']);
1757 return buildRedirectURL (__FUNCTION__, 'OK', array(), NULL, 'ports');
1758 }
1759
1760 $msgcode['saveEntityTags']['OK'] = 26;
1761 $msgcode['saveEntityTags']['ERR1'] = 143;
1762 // Filter out implicit tags before storing the new tag set.
1763 function saveEntityTags ()
1764 {
1765 global $pageno, $etype_by_pageno;
1766 if (!isset ($etype_by_pageno[$pageno]))
1767 throw new RackTablesError ('key not found in etype_by_pageno', RackTablesError::INTERNAL);
1768 $realm = $etype_by_pageno[$pageno];
1769 $entity_id = getBypassValue();
1770 $taglist = isset ($_REQUEST['taglist']) ? $_REQUEST['taglist'] : array();
1771 // Build a chain from the submitted data, minimize it,
1772 // then wipe existing records and store the new set instead.
1773 destroyTagsForEntity ($realm, $entity_id);
1774 // TODO: these actions are very close to what rebuildTagChainForEntity() does,
1775 // so why not use it?
1776 $newchain = getExplicitTagsOnly (buildTagChainFromIds ($taglist));
1777 $n_succeeds = $n_errors = 0;
1778 foreach ($newchain as $taginfo)
1779 if (addTagForEntity ($realm, $entity_id, $taginfo['id']))
1780 $n_succeeds++;
1781 else
1782 $n_errors++;
1783 if ($n_errors)
1784 return buildRedirectURL (__FUNCTION__, 'ERR1', array ($n_succeeds, $n_errors));
1785 else
1786 return buildRedirectURL (__FUNCTION__, 'OK', array ($n_succeeds));
1787 }
1788
1789 $msgcode['rollTags']['OK'] = 67;
1790 $msgcode['rollTags']['ERR'] = 149;
1791 function rollTags ()
1792 {
1793 assertStringArg ('sum', TRUE);
1794 assertUIntArg ('realsum');
1795 if ($_REQUEST['sum'] != $_REQUEST['realsum'])
1796 return buildRedirectURL (__FUNCTION__, 'ERR');
1797 // Even if the user requested an empty tag list, don't bail out, but process existing
1798 // tag chains with "zero" extra. This will make sure, that the stuff processed will
1799 // have its chains refined to "normal" form.
1800 $extratags = isset ($_REQUEST['taglist']) ? $_REQUEST['taglist'] : array();
1801 $n_ok = 0;
1802 // Minimizing the extra chain early, so that tag rebuilder doesn't have to
1803 // filter out the same tag again and again. It will have own noise to cancel.
1804 $extrachain = getExplicitTagsOnly (buildTagChainFromIds ($extratags));
1805 foreach (listCells ('rack', getBypassValue()) as $rack)
1806 {
1807 if (rebuildTagChainForEntity ('rack', $rack['id'], $extrachain))
1808 $n_ok++;
1809 amplifyCell ($rack);
1810 foreach ($rack['mountedObjects'] as $object_id)
1811 if (rebuildTagChainForEntity ('object', $object_id, $extrachain))
1812 $n_ok++;
1813 }
1814 return buildRedirectURL (__FUNCTION__, 'OK', array ($n_ok));
1815 }
1816
1817 $msgcode['changeMyPassword']['OK'] = 51;
1818 $msgcode['changeMyPassword']['ERR1'] = 150;
1819 $msgcode['changeMyPassword']['ERR2'] = 151;
1820 $msgcode['changeMyPassword']['ERR3'] = 152;
1821 $msgcode['changeMyPassword']['ERR4'] = 153;
1822 function changeMyPassword ()
1823 {
1824 global $remote_username, $user_auth_src;
1825 if ($user_auth_src != 'database')
1826 return buildRedirectURL (__FUNCTION__, 'ERR1');
1827 assertStringArg ('oldpassword');
1828 assertStringArg ('newpassword1');
1829 assertStringArg ('newpassword2');
1830 $remote_userid = getUserIDByUsername ($remote_username);
1831 $userinfo = spotEntity ('user', $remote_userid);
1832 if ($userinfo['user_password_hash'] != sha1 ($_REQUEST['oldpassword']))
1833 return buildRedirectURL (__FUNCTION__, 'ERR2');
1834 if ($_REQUEST['newpassword1'] != $_REQUEST['newpassword2'])
1835 return buildRedirectURL (__FUNCTION__, 'ERR3');
1836 if (FALSE !== commitUpdateUserAccount ($remote_userid, $userinfo['user_name'], $userinfo['user_realname'], sha1 ($_REQUEST['newpassword1'])))
1837 return buildRedirectURL (__FUNCTION__, 'OK');
1838 else
1839 return buildRedirectURL (__FUNCTION__, 'ERR4');
1840 }
1841
1842 $msgcode['saveRackCode']['OK'] = 43;
1843 $msgcode['saveRackCode']['ERR1'] = 154;
1844 $msgcode['saveRackCode']['ERR2'] = 155;
1845 function saveRackCode ()
1846 {
1847 assertStringArg ('rackcode');
1848 // For the test to succeed, unescape LFs, strip CRs.
1849 $newcode = dos2unix ($_REQUEST['rackcode']);
1850 $parseTree = getRackCode ($newcode);
1851 if ($parseTree['result'] != 'ACK')
1852 return buildRedirectURL (__FUNCTION__, 'ERR1', array ($parseTree['load']));
1853 if (FALSE !== saveScript ('RackCode', $newcode))
1854 {
1855 saveScript ('RackCodeCache', base64_encode (serialize ($parseTree)));
1856 return buildRedirectURL (__FUNCTION__, 'OK');
1857 }
1858 return buildRedirectURL (__FUNCTION__, 'ERR2');
1859 }
1860
1861 $msgcode['setPortVLAN']['ERR'] = 164;
1862 // This handler's context is pre-built, but not authorized. It is assumed, that the
1863 // handler will take existing context and before each commit check authorization
1864 // on the base chain plus necessary context added.
1865 function setPortVLAN ()
1866 {
1867 assertUIntArg ('portcount');
1868 try
1869 {
1870 $data = getSwitchVLANs ($_REQUEST['object_id']);
1871 }
1872 catch (RTGatewayError $re)
1873 {
1874 return buildRedirectURL (__FUNCTION__, 'ERR', array ($re->getMessage()));
1875 }
1876 list ($vlanlist, $portlist) = $data;
1877 // Here we just build up 1 set command for the gateway with all of the ports
1878 // included. The gateway is expected to filter unnecessary changes silently
1879 // and to provide a list of responses with either error or success message
1880 // for each of the rest.
1881 $nports = $_REQUEST['portcount'];
1882 $prefix = 'set ';
1883 $log = emptyLog();
1884 $setcmd = '';
1885 for ($i = 0; $i < $nports; $i++)
1886 {
1887 genericAssertion ('portname_' . $i, 'string');
1888 genericAssertion ('vlanid_' . $i, 'string');
1889 if ($_REQUEST['portname_' . $i] != $portlist[$i]['portname'])
1890 throw new InvalidRequestArgException ('portname_' . $i, $_REQUEST['portname_' . $i], 'expected to be ' . $portlist[$i]['portname']);
1891 if
1892 (
1893 $_REQUEST['vlanid_' . $i] == $portlist[$i]['vlanid'] ||
1894 $portlist[$i]['vlanid'] == 'TRUNK'
1895 )
1896 continue;
1897 $portname = $_REQUEST['portname_' . $i];
1898 $oldvlanid = $portlist[$i]['vlanid'];
1899 $newvlanid = $_REQUEST['vlanid_' . $i];
1900 if
1901 (
1902 !permitted (NULL, NULL, NULL, array (array ('tag' => '$fromvlan_' . $oldvlanid), array ('tag' => '$vlan_' . $oldvlanid))) or
1903 !permitted (NULL, NULL, NULL, array (array ('tag' => '$tovlan_' . $newvlanid), array ('tag' => '$vlan_' . $newvlanid)))
1904 )
1905 {
1906 $log = mergeLogs ($log, oneLiner (159, array ($portname, $oldvlanid, $newvlanid)));
1907 continue;
1908 }
1909 $setcmd .= $prefix . $portname . '=' . $newvlanid;
1910 $prefix = ';';
1911 }
1912 // Feed the gateway and interpret its (non)response.
1913 if ($setcmd == '')
1914 $log = mergeLogs ($log, oneLiner (201));
1915 else
1916 {
1917 try
1918 {
1919 $log = mergeLogs ($log, setSwitchVLANs ($_REQUEST['object_id'], $setcmd));
1920 }
1921 catch (RTGatewayError $e)
1922 {
1923 $log = mergeLogs ($log, oneLiner (164, $e->getMessage()));
1924 }
1925 }
1926 return buildWideRedirectURL ($log);
1927 }
1928
1929 $msgcode['submitSLBConfig']['OK'] = 66;
1930 $msgcode['submitSLBConfig']['ERR'] = 164;
1931 function submitSLBConfig ()
1932 {
1933 $newconfig = buildLVSConfig (getBypassValue());
1934 try
1935 {
1936 gwSendFileToObject (getBypassValue(), 'slbconfig', html_entity_decode ($newconfig, ENT_QUOTES, 'UTF-8'));
1937 }
1938 catch (RTGatewayError $e)
1939 {
1940 return buildRedirectURL (__FUNCTION__, 'ERR', array ($e->getMessage()));
1941 }
1942 return buildRedirectURL (__FUNCTION__, 'OK', array ('slbconfig'));
1943 }
1944
1945 $msgcode['addRack']['OK'] = 48;
1946 $msgcode['addRack']['ERR2'] = 172;
1947 function addRack ()
1948 {
1949 $taglist = isset ($_REQUEST['taglist']) ? $_REQUEST['taglist'] : array();
1950 if (isset ($_REQUEST['got_data']))
1951 {
1952 assertStringArg ('rack_name');
1953 assertUIntArg ('rack_height1');
1954 assertStringArg ('rack_comment', TRUE);
1955 commitAddRack ($_REQUEST['rack_name'], $_REQUEST['rack_height1'], $_REQUEST['row_id'], $_REQUEST['rack_comment'], $taglist);
1956 return buildRedirectURL (__FUNCTION__, 'OK', array ($_REQUEST['rack_name']));
1957 }
1958 elseif (isset ($_REQUEST['got_mdata']))
1959 {
1960 assertUIntArg ('rack_height2');
1961 assertStringArg ('rack_names', TRUE);
1962 $log = emptyLog();
1963 // copy-and-paste from renderAddMultipleObjectsForm()
1964 $names1 = explode ("\n", $_REQUEST['rack_names']);
1965 $names2 = array();
1966 foreach ($names1 as $line)
1967 {
1968 $parts = explode ('\r', $line);
1969 reset ($parts);
1970 if (!strlen ($parts[0]))
1971 continue;
1972 else
1973 $names2[] = rtrim ($parts[0]);
1974 }
1975 global $msgcode;
1976 foreach ($names2 as $cname)
1977 {
1978 commitAddRack ($cname, $_REQUEST['rack_height2'], $_REQUEST['row_id'], '', $taglist);
1979 $log['m'][] = array ('c' => $msgcode[__FUNCTION__]['OK'], 'a' => array ($cname));
1980 }
1981 return buildWideRedirectURL ($log);
1982 }
1983 else
1984 return buildRedirectURL (__FUNCTION__, 'ERR2');
1985 }
1986
1987 $msgcode['deleteRack']['OK'] = 6;
1988 $msgcode['deleteRack']['ERR'] = 100;
1989 $msgcode['deleteRack']['ERR1'] = 206;
1990 function deleteRack ()
1991 {
1992 assertUIntArg ('rack_id');
1993 $rackData = spotEntity ('rack', $_REQUEST['rack_id']);
1994 amplifyCell ($rackData);
1995 if (count ($rackData['mountedObjects']))
1996 return buildRedirectURL (__FUNCTION__, 'ERR1');
1997 if (TRUE !== commitDeleteRack ($_REQUEST['rack_id']))
1998 return buildRedirectURL (__FUNCTION__, 'ERR', array(), 'rackspace', 'default');
1999 return buildRedirectURL (__FUNCTION__, 'OK', array ($rackData['name']), 'rackspace', 'default');
2000 }
2001
2002 $msgcode['updateRack']['OK'] = 6;
2003 $msgcode['updateRack']['ERR'] = 109;
2004 function updateRack ()
2005 {
2006 assertUIntArg ('rack_row_id');
2007 assertUIntArg ('rack_height');
2008 assertStringArg ('rack_name');
2009 assertStringArg ('rack_comment', TRUE);
2010
2011 $rack_id = getBypassValue();
2012 usePreparedUpdateBlade ('Rack', array ('thumb_data' => NULL), array ('id' => $rack_id));
2013 if (TRUE === commitUpdateRack ($rack_id, $_REQUEST['rack_name'], $_REQUEST['rack_height'], $_REQUEST['rack_row_id'], $_REQUEST['rack_comment']))
2014 return buildRedirectURL (__FUNCTION__, 'OK', array ($_REQUEST['rack_name']));
2015 else
2016 return buildRedirectURL (__FUNCTION__, 'ERR');
2017 }
2018
2019 function updateRackDesign ()
2020 {
2021 $rackData = spotEntity ('rack', getBypassValue());
2022 amplifyCell ($rackData);
2023 applyRackDesignMask($rackData);
2024 markupObjectProblems ($rackData);
2025 $response = processGridForm ($rackData, 'A', 'F');
2026 return buildWideRedirectURL (array($response));
2027 }
2028
2029 function updateRackProblems ()
2030 {
2031 $rackData = spotEntity ('rack', getBypassValue());
2032 amplifyCell ($rackData);
2033 applyRackProblemMask($rackData);
2034 markupObjectProblems ($rackData);
2035 $response = processGridForm ($rackData, 'F', 'U');
2036 return buildWideRedirectURL (array($response));
2037 }
2038
2039 function querySNMPData ()
2040 {
2041 assertStringArg ('community', TRUE);
2042
2043 $snmpsetup = array ();
2044 if ($_REQUEST['community'] != '')
2045 $snmpsetup['community'] = $_REQUEST['community'];
2046 else
2047 {
2048 assertStringArg ('sec_name');
2049 assertStringArg ('sec_level');
2050 assertStringArg ('auth_protocol');
2051 assertStringArg ('auth_passphrase', TRUE);
2052 assertStringArg ('priv_protocol');
2053 assertStringArg ('priv_passphrase', TRUE);
2054
2055 $snmpsetup['sec_name'] = $_REQUEST['sec_name'];
2056 $snmpsetup['sec_level'] = $_REQUEST['sec_level'];
2057 $snmpsetup['auth_protocol'] = $_REQUEST['auth_protocol'];
2058 $snmpsetup['auth_passphrase'] = $_REQUEST['auth_passphrase'];
2059 $snmpsetup['priv_protocol'] = $_REQUEST['priv_protocol'];
2060 $snmpsetup['priv_passphrase'] = $_REQUEST['priv_passphrase'];
2061 }
2062 return doSNMPmining (getBypassValue(), $snmpsetup);
2063 }
2064
2065 $msgcode['linkEntities']['OK'] = 51;
2066 $msgcode['linkEntities']['ERR2'] = 109;
2067 function linkEntities ()
2068 {
2069 assertStringArg ('parent_entity_type');
2070 assertUIntArg ('parent_entity_id');
2071 assertStringArg ('child_entity_type');
2072 assertUIntArg ('child_entity_id');
2073 $result = usePreparedInsertBlade
2074 (
2075 'EntityLink',
2076 array
2077 (
2078 'parent_entity_type' => $_REQUEST['parent_entity_type'],
2079 'parent_entity_id' => $_REQUEST['parent_entity_id'],
2080 'child_entity_type' => $_REQUEST['child_entity_type'],
2081 'child_entity_id' => $_REQUEST['child_entity_id'],
2082 )
2083 );
2084 if ($result === FALSE)
2085 return buildRedirectURL (__FUNCTION__, 'ERR2');
2086 return buildRedirectURL (__FUNCTION__, 'OK');
2087 }
2088
2089 $msgcode['unlinkEntities']['OK'] = 49;
2090 $msgcode['unlinkEntities']['ERR'] = 111;
2091 function unlinkEntities ()
2092 {
2093 assertUIntArg ('link_id');
2094 return buildRedirectURL (__FUNCTION__, commitUnlinkEntities ($_REQUEST['link_id']) === FALSE ? 'ERR' : 'OK');
2095 }
2096
2097 $msgcode['addFileWithoutLink']['OK'] = 5;
2098 // File-related functions
2099 function addFileWithoutLink ()
2100 {
2101 assertStringArg ('comment', TRUE);
2102
2103 // Make sure the file can be uploaded
2104 if (get_cfg_var('file_uploads') != 1)
2105 throw new RackTablesError ('file uploads not allowed, change "file_uploads" parameter in php.ini', RackTablesError::MISCONFIGURED);
2106
2107 $fp = fopen($_FILES['file']['tmp_name'], 'rb');
2108 global $sic;
2109 commitAddFile ($_FILES['file']['name'], $_FILES['file']['type'], $fp, $sic['comment']);
2110 if (isset ($_REQUEST['taglist']))
2111 produceTagsForLastRecord ('file', $_REQUEST['taglist']);
2112 return buildRedirectURL (__FUNCTION__, 'OK', array (htmlspecialchars ($_FILES['file']['name'])));
2113 }
2114
2115 $msgcode['addFileToEntity']['OK'] = 5;
2116 function addFileToEntity ()
2117 {
2118 global $pageno, $etype_by_pageno;
2119 if (!isset ($etype_by_pageno[$pageno]))
2120 throw new RackTablesError ('key not found in etype_by_pageno', RackTablesError::INTERNAL);
2121 $realm = $etype_by_pageno[$pageno];
2122 assertStringArg ('comment', TRUE);
2123
2124 // Make sure the file can be uploaded
2125 if (get_cfg_var('file_uploads') != 1)
2126 throw new RackTablesError ('file uploads not allowed, change "file_uploads" parameter in php.ini', RackTablesError::MISCONFIGURED);
2127
2128 $fp = fopen($_FILES['file']['tmp_name'], 'rb');
2129 global $sic;
2130 commitAddFile ($_FILES['file']['name'], $_FILES['file']['type'], $fp, $sic['comment']);
2131 usePreparedInsertBlade
2132 (
2133 'FileLink',
2134 array
2135 (
2136 'file_id' => lastInsertID(),
2137 'entity_type' => $realm,
2138 'entity_id' => getBypassValue(),
2139 )
2140 );
2141 return buildRedirectURL (__FUNCTION__, 'OK', array (htmlspecialchars ($_FILES['file']['name'])));
2142 }
2143
2144 $msgcode['linkFileToEntity']['OK'] = 71;
2145 function linkFileToEntity ()
2146 {
2147 assertUIntArg ('file_id');
2148 global $pageno, $etype_by_pageno, $sic;
2149 if (!isset ($etype_by_pageno[$pageno]))
2150 throw new RackTablesError ('key not found in etype_by_pageno', RackTablesError::INTERNAL);
2151
2152 $fi = spotEntity ('file', $sic['file_id']);
2153 usePreparedInsertBlade
2154 (
2155 'FileLink',
2156 array
2157 (
2158 'file_id' => $sic['file_id'],
2159 'entity_type' => $etype_by_pageno[$pageno],
2160 'entity_id' => getBypassValue(),
2161 )
2162 );
2163 return buildRedirectURL (__FUNCTION__, 'OK', array (htmlspecialchars ($fi['name'])));
2164 }
2165
2166 $msgcode['replaceFile']['OK'] = 7;
2167 $msgcode['replaceFile']['ERR2'] = 201;
2168 function replaceFile ()
2169 {
2170 // Make sure the file can be uploaded
2171 if (get_cfg_var('file_uploads') != 1)
2172 throw new RackTablesError ('file uploads not allowed, change "file_uploads" parameter in php.ini', RackTablesError::MISCONFIGURED);
2173 $shortInfo = spotEntity ('file', getBypassValue());
2174
2175 if (FALSE === $fp = fopen ($_FILES['file']['tmp_name'], 'rb'))
2176 return buildRedirectURL (__FUNCTION__, 'ERR2');
2177 commitReplaceFile ($shortInfo['id'], $fp);
2178
2179 return buildRedirectURL (__FUNCTION__, 'OK', array (htmlspecialchars ($shortInfo['name'])));
2180 }
2181
2182 $msgcode['unlinkFile']['OK'] = 72;
2183 $msgcode['unlinkFile']['ERR'] = 111;
2184 function unlinkFile ()
2185 {
2186 assertUIntArg ('link_id');
2187 return buildRedirectURL (__FUNCTION__, commitUnlinkFile ($_REQUEST['link_id']) === FALSE ? 'ERR' : 'OK');
2188 }
2189
2190 $msgcode['deleteFile']['OK'] = 7;
2191 function deleteFile ()
2192 {
2193 assertUIntArg ('file_id');
2194 $shortInfo = spotEntity ('file', $_REQUEST['file_id']);
2195 commitDeleteFile ($_REQUEST['file_id']);
2196 return buildRedirectURL (__FUNCTION__, 'OK', array (htmlspecialchars ($shortInfo['name'])));
2197 }
2198
2199 $msgcode['updateFileText']['OK'] = 7;
2200 $msgcode['updateFileText']['ERR1'] = 179;
2201 $msgcode['updateFileText']['ERR2'] = 155;
2202 function updateFileText ()
2203 {
2204 assertStringArg ('mtime_copy');
2205 assertStringArg ('file_text', TRUE); // it's Ok to save empty
2206 $shortInfo = spotEntity ('file', getBypassValue());
2207 if ($shortInfo['mtime'] != $_REQUEST['mtime_copy'])
2208 return buildRedirectURL (__FUNCTION__, 'ERR1');
2209 global $sic;
2210 commitReplaceFile ($shortInfo['id'], $sic['file_text']);
2211 return buildRedirectURL (__FUNCTION__, 'OK', array (htmlspecialchars ($shortInfo['name'])));
2212 }
2213
2214 $msgcode['addIIFOIFCompat']['OK'] = 48;
2215 $msgcode['addIIFOIFCompat']['ERR'] = 110;
2216 function addIIFOIFCompat ()
2217 {
2218 assertUIntArg ('iif_id');
2219 assertUIntArg ('oif_id');
2220 if (commitSupplementPIC ($_REQUEST['iif_id'], $_REQUEST['oif_id']))
2221 return buildRedirectURL (__FUNCTION__, 'OK');
2222 return buildRedirectURL (__FUNCTION__, 'ERR');
2223 }
2224
2225 $msgcode['addIIFOIFCompatPack']['OK'] = 44;
2226 function addIIFOIFCompatPack ()
2227 {
2228 genericAssertion ('standard', 'enum/wdmstd');
2229 genericAssertion ('iif_id', 'iif');
2230 global $wdm_packs, $sic;
2231 $ngood = $nbad = 0;
2232 foreach ($wdm_packs[$sic['standard']]['oif_ids'] as $oif_id)
2233 if (commitSupplementPIC ($sic['iif_id'], $oif_id))
2234 $ngood++;
2235 else
2236 $nbad++;
2237 return buildRedirectURL (__FUNCTION__, 'OK', array ($nbad, $ngood));
2238 }
2239
2240 $msgcode['delIIFOIFCompatPack']['OK'] = 44;
2241 function delIIFOIFCompatPack ()
2242 {
2243 genericAssertion ('standard', 'enum/wdmstd');
2244 genericAssertion ('iif_id', 'iif');
2245 global $wdm_packs, $sic;
2246 $ngood = $nbad = 0;
2247 foreach ($wdm_packs[$sic['standard']]['oif_ids'] as $oif_id)
2248 if (usePreparedDeleteBlade ('PortInterfaceCompat', array ('iif_id' => $sic['iif_id'], 'oif_id' => $oif_id)))
2249 $ngood++;
2250 else
2251 $nbad++;
2252 return buildRedirectURL (__FUNCTION__, 'OK', array ($nbad, $ngood));
2253 }
2254
2255 $msgcode['addOIFCompatPack']['OK'] = 21;
2256 function addOIFCompatPack ()
2257 {
2258 genericAssertion ('standard', 'enum/wdmstd');
2259 global $wdm_packs;
2260 $oifs = $wdm_packs[$_REQUEST['standard']]['oif_ids'];
2261 foreach ($oifs as $oif_id_1)
2262 {
2263 $args = $qmarks = array();
2264 $query = 'REPLACE INTO PortCompat (type1, type2) VALUES ';
2265 foreach ($oifs as $oif_id_2)
2266 {
2267 $qmarks[] = '(?, ?)';
2268 $args[] = $oif_id_1;
2269 $args[] = $oif_id_2;
2270 }
2271 $query .= implode (', ', $qmarks);
2272 usePreparedExecuteBlade ($query, $args);
2273 }
2274 return buildRedirectURL (__FUNCTION__, 'OK');
2275 }
2276
2277 $msgcode['delOIFCompatPack']['OK'] = 21;
2278 function delOIFCompatPack ()
2279 {
2280 genericAssertion ('standard', 'enum/wdmstd');
2281 global $wdm_packs;
2282 $oifs = $wdm_packs[$_REQUEST['standard']]['oif_ids'];
2283 foreach ($oifs as $oif_id_1)
2284 foreach ($oifs as $oif_id_2)
2285 if ($oif_id_1 != $oif_id_2) # leave narrow-band mapping intact
2286 usePreparedDeleteBlade ('PortCompat', array ('type1' => $oif_id_1, 'type2' => $oif_id_2));
2287 return buildRedirectURL (__FUNCTION__, 'OK');
2288 }
2289
2290 $msgcode['add8021QOrder']['OK'] = 48;
2291 $msgcode['add8021QOrder']['ERR'] = 110;
2292 function add8021QOrder ()
2293 {
2294 assertUIntArg ('vdom_id');
2295 assertUIntArg ('object_id');
2296 assertUIntArg ('vst_id');
2297 global $sic;
2298 $result = usePreparedExecuteBlade
2299 (
2300 'INSERT INTO VLANSwitch (domain_id, object_id, template_id, last_change, out_of_sync) ' .
2301 'VALUES (?, ?, ?, NOW(), "yes")',
2302 array ($sic['vdom_id'], $sic['object_id'], $sic['vst_id'])
2303 );
2304 return buildRedirectURL (__FUNCTION__, $result !== FALSE ? 'OK' : 'ERR');
2305 }
2306
2307 $msgcode['del8021QOrder']['OK'] = 49;
2308 $msgcode['del8021QOrder']['ERR'] = 111;
2309 function del8021QOrder ()
2310 {
2311 assertUIntArg ('object_id');
2312 assertUIntArg ('vdom_id');
2313 assertUIntArg ('vst_id');
2314 global $sic;
2315 $result = usePreparedDeleteBlade ('VLANSwitch', array ('object_id' => $sic['object_id']));
2316 $focus_hints = array
2317 (
2318 'prev_objid' => $_REQUEST['object_id'],
2319 'prev_vstid' => $_REQUEST['vst_id'],
2320 'prev_vdid' => $_REQUEST['vdom_id'],
2321 );
2322 return buildRedirectURL (__FUNCTION__, $result ? 'OK' : 'ERR', array(), NULL, NULL, $focus_hints);
2323 }
2324
2325 $msgcode['createVLANDomain']['OK'] = 48;
2326 $msgcode['createVLANDomain']['ERR'] = 110;
2327 function createVLANDomain ()
2328 {
2329 assertStringArg ('vdom_descr');
2330 global $sic;
2331 $result = usePreparedInsertBlade
2332 (
2333 'VLANDomain',
2334 array
2335 (
2336 'description' => $sic['vdom_descr'],
2337 )
2338 );
2339 $result = $result and usePreparedInsertBlade
2340 (
2341 'VLANDescription',
2342 array
2343 (
2344 'domain_id' => lastInsertID(),
2345 'vlan_id' => VLAN_DFL_ID,
2346 'vlan_type' => 'compulsory',
2347 'vlan_descr' => 'default',
2348 )
2349 );
2350 return buildRedirectURL (__FUNCTION__, $result ? 'OK' : 'ERR');
2351 }
2352
2353 $msgcode['destroyVLANDomain']['OK'] = 49;
2354 $msgcode['destroyVLANDomain']['ERR'] = 111;
2355 function destroyVLANDomain ()
2356 {
2357 assertUIntArg ('vdom_id');
2358 global $sic;
2359 $result = FALSE !== usePreparedDeleteBlade ('VLANDomain', array ('id' => $sic['vdom_id']));
2360 return buildRedirectURL (__FUNCTION__, $result ? 'OK' : 'ERR');
2361 }
2362
2363 $msgcode['save8021QPorts']['OK1'] = 63;
2364 $msgcode['save8021QPorts']['OK2'] = 41;
2365 $msgcode['save8021QPorts']['ERR2'] = 109;
2366 function save8021QPorts ()
2367 {
2368 global $sic, $dbxlink;
2369 assertUIntArg ('mutex_rev', TRUE); // counts from 0
2370 assertStringArg ('form_mode');
2371 if ($sic['form_mode'] != 'save' and $sic['form_mode'] != 'duplicate')
2372 throw new InvalidRequestArgException ('form_mode', $sic['form_mode']);
2373 $extra = array();
2374 $dbxlink->beginTransaction();
2375 try
2376 {
2377 if (NULL === $vswitch = getVLANSwitchInfo ($sic['object_id'], 'FOR UPDATE'))
2378 throw new InvalidArgException ('object_id', $object_id, 'VLAN domain is not set for this object');
2379 if ($vswitch['mutex_rev'] != $sic['mutex_rev'])
2380 throw new InvalidRequestArgException ('mutex_rev', $sic['mutex_rev'], 'expired form data');
2381 $after = $before = apply8021QOrder ($vswitch['template_id'], getStored8021QConfig ($sic['object_id'], 'desired'));
2382 $changes = array();
2383 switch ($sic['form_mode'])
2384 {
2385 case 'save':
2386 assertUIntArg ('nports');
2387 if ($sic['nports'] == 1)
2388 {
2389 assertStringArg ('pn_0');
2390 $extra = array ('port_name' => $sic['pn_0']);
2391 }
2392 for ($i = 0; $i < $sic['nports']; $i++)
2393 {
2394 assertStringArg ('pn_' . $i);
2395 assertStringArg ('pm_' . $i);
2396 // An access port only generates form input for its native VLAN,
2397 // which we derive allowed VLAN list from.
2398 $native = isset ($sic['pnv_' . $i]) ? $sic['pnv_' . $i] : 0;
2399 switch ($sic["pm_${i}"])
2400 {
2401 case 'trunk':
2402 # assertArrayArg ('pav_' . $i);
2403 $allowed = isset ($sic['pav_' . $i]) ? $sic['pav_' . $i] : array();
2404 break;
2405 case 'access':
2406 if ($native == 'same')
2407 continue 2;
2408 assertUIntArg ('pnv_' . $i);
2409 $allowed = array ($native);
2410 break;
2411 default:
2412 throw new InvalidRequestArgException ("pm_${i}", $_REQUEST["pm_${i}"], 'unknown port mode');
2413 }
2414 $changes[$sic['pn_' . $i]] = array
2415 (
2416 'mode' => $sic['pm_' . $i],
2417 'allowed' => $allowed,
2418 'native' => $native,
2419 );
2420 }
2421 break;
2422 case 'duplicate':
2423 assertStringArg ('from_port');
2424 # assertArrayArg ('to_ports');
2425 if (!array_key_exists ($sic['from_port'], $before))
2426 throw new InvalidArgException ('from_port', $sic['from_port'], 'this port does not exist');
2427 foreach ($sic['to_ports'] as $tpn)
2428 if (!array_key_exists ($tpn, $before))
2429 throw new InvalidArgException ('to_ports[]', $tpn, 'this port does not exist');
2430 elseif ($tpn != $sic['from_port'])
2431 $changes[$tpn] = $before[$sic['from_port']];
2432 break;
2433 }
2434 $domain_vlanlist = getDomainVLANs ($vswitch['domain_id']);
2435 $changes = filter8021QChangeRequests
2436 (
2437 $domain_vlanlist,
2438 $before,
2439 apply8021QOrder ($vswitch['template_id'], $changes)
2440 );
2441 $changes = authorize8021QChangeRequests ($before, $changes);
2442 foreach ($changes as $port_name => $port)
2443 $after[$port_name] = $port;
2444 $new_uplinks = filter8021QChangeRequests ($domain_vlanlist, $after, produceUplinkPorts ($domain_vlanlist, $after, $vswitch['object_id']));
2445 $npulled = replace8021QPorts ('desired', $vswitch['object_id'], $before, $changes);
2446 $nsaved_uplinks = replace8021QPorts ('desired', $vswitch['object_id'], $before, $new_uplinks);
2447 }
2448 catch (Exception $e)
2449 {
2450 $dbxlink->rollBack();
2451 return buildRedirectURL (__FUNCTION__, 'ERR2', array(), NULL, NULL, $extra);
2452 }
2453 if ($npulled + $nsaved_uplinks)
2454 usePreparedExecuteBlade
2455 (
2456 'UPDATE VLANSwitch SET mutex_rev=mutex_rev+1, last_change=NOW(), out_of_sync="yes" WHERE object_id=?',
2457 array ($sic['object_id'])
2458 );
2459 $dbxlink->commit();
2460 $log = oneLiner (63, array ($npulled + $nsaved_uplinks));
2461 if ($nsaved_uplinks)
2462 {
2463 initiateUplinksReverb ($vswitch['object_id'], $new_uplinks);
2464 $log = mergeLogs ($log, oneLiner (41));
2465 }
2466 if ($npulled + $nsaved_uplinks > 0 and getConfigVar ('8021Q_INSTANT_DEPLOY') == 'yes')
2467 {
2468 try
2469 {
2470 if (FALSE === $done = exec8021QDeploy ($sic['object_id'], TRUE))
2471 $log = mergeLogs ($log, oneLiner (191));
2472 else
2473 $log = mergeLogs ($log, oneLiner (63, array ($done)));
2474 }
2475 catch (Exception $e)
2476 {
2477 $log = mergeLogs ($log, oneLiner (109));
2478 }
2479 }
2480 return buildWideRedirectURL ($log, NULL, NULL, $extra);
2481 }
2482
2483 $msgcode['bindVLANtoIPv4']['OK'] = 48;
2484 $msgcode['bindVLANtoIPv4']['ERR'] = 110;
2485 function bindVLANtoIPv4 ()
2486 {
2487 assertUIntArg ('id'); // network id
2488 global $sic;
2489 $result = commitSupplementVLANIPv4 ($sic['vlan_ck'], $sic['id']);
2490 return buildRedirectURL (__FUNCTION__, $result ? 'OK' : 'ERR');
2491 }
2492
2493 $msgcode['bindVLANtoIPv6']['OK'] = 48;
2494 $msgcode['bindVLANtoIPv6']['ERR'] = 110;
2495 function bindVLANtoIPv6 ()
2496 {
2497 assertUIntArg ('id'); // network id
2498 global $sic;
2499 $result = commitSupplementVLANIPv6 ($sic['vlan_ck'], $_REQUEST['id']);
2500 return buildRedirectURL (__FUNCTION__, $result ? 'OK' : 'ERR');
2501 }
2502
2503 $msgcode['unbindVLANfromIPv4']['OK'] = 49;
2504 $msgcode['unbindVLANfromIPv4']['ERR'] = 111;
2505 function unbindVLANfromIPv4 ()
2506 {
2507 assertUIntArg ('id'); // network id
2508 global $sic;
2509 $result = commitReduceVLANIPv4 ($sic['vlan_ck'], $sic['id']);
2510 return buildRedirectURL (__FUNCTION__, $result ? 'OK' : 'ERR');
2511 }
2512
2513 $msgcode['unbindVLANfromIPv6']['OK'] = 49;
2514 $msgcode['unbindVLANfromIPv6']['ERR'] = 111;
2515 function unbindVLANfromIPv6 ()
2516 {
2517 assertUIntArg ('id'); // network id
2518 global $sic;
2519 $result = commitReduceVLANIPv6 ($sic['vlan_ck'], $sic['id']);
2520 return buildRedirectURL (__FUNCTION__, $result ? 'OK' : 'ERR');
2521 }
2522
2523 $msgcode['process8021QSyncRequest']['OK'] = 63;
2524 $msgcode['process8021QSyncRequest']['ERR'] = 191;
2525 function process8021QSyncRequest ()
2526 {
2527 // behave depending on current operation: exec8021QPull or exec8021QPush
2528 global $sic, $op;
2529 if (FALSE === $done = exec8021QDeploy ($sic['object_id'], $op == 'exec8021QPush'))
2530 return buildRedirectURL (__FUNCTION__, 'ERR');
2531 return buildRedirectURL (__FUNCTION__, 'OK', array ($done));
2532 }
2533
2534 $msgcode['process8021QRecalcRequest']['CHANGED'] = 87;
2535 $msgcode['process8021QRecalcRequest']['NO_CHANGES'] = 300;
2536 function process8021QRecalcRequest ()
2537 {
2538 assertPermission (NULL, NULL, NULL, array (array ('tag' => '$op_recalc8021Q')));
2539 $counters = recalc8021QPorts (getBypassValue());
2540 if ($counters['ports'])
2541 return buildRedirectURL (__FUNCTION__, 'CHANGED', array ($counters['ports'], $counters['switches']));
2542 else
2543 return buildRedirectURL (__FUNCTION__, 'NO_CHANGES', array ('No changes were made'));
2544 }
2545
2546 $msgcode['resolve8021QConflicts']['OK'] = 63;
2547 $msgcode['resolve8021QConflicts']['ERR1'] = 179;
2548 $msgcode['resolve8021QConflicts']['ERR2'] = 109;
2549 function resolve8021QConflicts ()
2550 {
2551 global $sic, $dbxlink;
2552 assertUIntArg ('mutex_rev', TRUE); // counts from 0
2553 assertUIntArg ('nrows');
2554 // Divide submitted radio buttons into 3 groups:
2555 // left (saved version wins)
2556 // asis (ignore)
2557 // right (running version wins)
2558 $F = array();
2559 for ($i = 0; $i < $sic['nrows']; $i++)
2560 {
2561 if (!array_key_exists ("i_${i}", $sic))
2562 continue;
2563 // let's hope other inputs are in place
2564 switch ($sic["i_${i}"])
2565 {
2566 case 'left':
2567 case 'right':
2568 $F[$sic["pn_${i}"]] = array
2569 (
2570 'mode' => $sic["rm_${i}"],
2571 'allowed' => $sic["ra_${i}"],
2572 'native' => $sic["rn_${i}"],
2573 'decision' => $sic["i_${i}"],
2574 );
2575 break;
2576 default:
2577 // don't care
2578 }
2579 }
2580 $dbxlink->beginTransaction();
2581 try
2582 {
2583 if (NULL === $vswitch = getVLANSwitchInfo ($sic['object_id'], 'FOR UPDATE'))
2584 throw new InvalidArgException ('object_id', $sic['object_id'], 'VLAN domain is not set for this object');
2585 if ($vswitch['mutex_rev'] != $sic['mutex_rev'])
2586 throw new InvalidRequestArgException ('mutex_rev', $sic['mutex_rev'], 'expired form (table data has changed)');
2587 $D = getStored8021QConfig ($vswitch['object_id'], 'desired');
2588 $C = getStored8021QConfig ($vswitch['object_id'], 'cached');
2589 $R = getRunning8021QConfig ($vswitch['object_id']);
2590 $plan = get8021QSyncOptions ($vswitch, $D, $C, $R['portdata']);
2591 $ndone = 0;
2592 foreach ($F as $port_name => $port)
2593 {
2594 if (!array_key_exists ($port_name, $plan))
2595 continue;
2596 elseif ($plan[$port_name]['status'] == 'merge_conflict')
2597 {
2598 // for R neither mutex nor revisions can be emulated, but revision change can be
2599 if (!same8021QConfigs ($port, $R['portdata'][$port_name]))
2600 throw new InvalidRequestArgException ("port ${port_name}", '(hidden)', 'expired form (switch data has changed)');
2601 if ($port['decision'] == 'right') // D wins, frame R by writing value of R to C
2602 $ndone += upd8021QPort ('cached', $vswitch['object_id'], $port_name, $port);
2603 elseif ($port['decision'] == 'left') // R wins, cross D up
2604 $ndone += upd8021QPort ('cached', $vswitch['object_id'], $port_name, $D[$port_name]);
2605 // otherwise there was no decision made
2606 }
2607 elseif
2608 (
2609 $plan[$port_name]['status'] == 'delete_conflict' or
2610 $plan[$port_name]['status'] == 'martian_conflict'
2611 )
2612 {
2613 if ($port['decision'] == 'left') // confirm deletion of local copy
2614 $ndone += del8021QPort ($vswitch['object_id'], $port_name);
2615 }
2616 // otherwise ignore a decision, which doesn't address a conflict
2617 }
2618 }
2619 catch (InvalidRequestArgException $e)
2620 {
2621 $dbxlink->rollBack();
2622 return buildRedirectURL (__FUNCTION__, 'ERR1');
2623 }
2624 catch (Exception $e)
2625 {
2626 $dbxlink->rollBack();
2627 return buildRedirectURL (__FUNCTION__, 'ERR2');
2628 }
2629 $dbxlink->commit();
2630 return buildRedirectURL (__FUNCTION__, 'OK', array ($ndone));
2631 }
2632
2633 $msgcode['addVLANSwitchTemplate']['OK'] = 48;
2634 $msgcode['addVLANSwitchTemplate']['ERR'] = 110;
2635 function addVLANSwitchTemplate()
2636 {
2637 assertStringArg ('vst_descr');
2638 global $sic;
2639 $result = usePreparedInsertBlade
2640 (
2641 'VLANSwitchTemplate',
2642 array
2643 (
2644 'description' => $sic['vst_descr'],
2645 )
2646 );
2647 return buildRedirectURL (__FUNCTION__, $result ? 'OK' : 'ERR');
2648 }
2649
2650 $msgcode['delVLANSwitchTemplate']['OK'] = 49;
2651 $msgcode['delVLANSwitchTemplate']['ERR'] = 111;
2652 function delVLANSwitchTemplate()
2653 {
2654 assertUIntArg ('vst_id');
2655 global $sic;
2656 $result = FALSE !== usePreparedDeleteBlade ('VLANSwitchTemplate', array ('id' => $sic['vst_id']));
2657 return buildRedirectURL (__FUNCTION__, $result ? 'OK' : 'ERR');
2658 }
2659
2660 $msgcode['cloneVST']['OK'] = 48;
2661 function cloneVST()
2662 {
2663 assertUIntArg ('mutex_rev', TRUE);
2664 assertUIntArg ('from_id');
2665 $src_vst = spotEntity ('vst', $_REQUEST['from_id']);
2666 amplifyCell ($src_vst);
2667 commitUpdateVSTRules (getBypassValue(), $_REQUEST['mutex_rev'], $src_vst['rules']);
2668 return buildRedirectURL (__FUNCTION__, 'OK');
2669 }
2670
2671 $msgcode['updVSTRule']['OK'] = 43;
2672 function updVSTRule()
2673 {
2674 // this is used for making throwing an invalid argument exception easier.
2675 function updVSTRule_get_named_param ($name, $haystack, &$last_used_name)
2676 {
2677 $last_used_name = $name;
2678 return isset ($haystack[$name]) ? $haystack[$name] : NULL;
2679 }
2680
2681 global $port_role_options, $sic;
2682 assertUIntArg ('mutex_rev', TRUE);
2683 genericAssertion ('template_json', 'json');
2684 $data = json_decode ($sic['template_json'], TRUE);
2685 $rule_no = 0;
2686 try
2687 {
2688 $last_field = '';
2689 foreach ($data as $rule)
2690 {
2691 $rule_no++;
2692 if
2693 (
2694 ! isInteger (updVSTRule_get_named_param ('rule_no', $rule, $last_field))
2695 or ! isPCRE (updVSTRule_get_named_param ('port_pcre', $rule, $last_field))
2696 or NULL === updVSTRule_get_named_param ('port_role', $rule, $last_field)
2697 or ! array_key_exists (updVSTRule_get_named_param ('port_role', $rule, $last_field), $port_role_options)
2698 or NULL === updVSTRule_get_named_param ('wrt_vlans', $rule, $last_field)
2699 or ! preg_match ('/^[ 0-9\-,]*$/', updVSTRule_get_named_param ('wrt_vlans', $rule, $last_field))
2700 or NULL === updVSTRule_get_named_param ('description', $rule, $last_field)
2701 )
2702 throw new InvalidRequestArgException ($last_field, $rule[$last_field], "rule #$rule_no");
2703 }
2704 commitUpdateVSTRules ($_REQUEST['vst_id'], $_REQUEST['mutex_rev'], $data);
2705 }
2706 catch (Exception $e)
2707 {
2708 // Every case, which is soft-processed in process.php, will have the working copy available for a retry.
2709 if ($e instanceof InvalidRequestArgException or $e instanceof RTDatabaseError)
2710 $_SESSION['vst_edited'] = $data;
2711 throw $e;
2712 }
2713 return buildRedirectURL (__FUNCTION__, 'OK');
2714 }
2715
2716 $msgcode['importDPData']['OK'] = 44;
2717 function importDPData()
2718 {
2719 global $sic, $dbxlink;
2720 assertUIntArg ('nports');
2721 $nignored = $ndone = 0;
2722 $POIFC = getPortOIFCompat();
2723 for ($i = 0; $i < $sic['nports']; $i++)
2724 if (array_key_exists ("do_${i}", $sic))
2725 {
2726 $params = array();
2727 assertStringArg ("ports_${i}");
2728 foreach (explode (',', $_REQUEST["ports_${i}"]) as $item)
2729 {
2730 $pair = explode (':', $item);
2731 if (count ($pair) != 2)
2732 continue;
2733 $params[$pair[0]] = $pair[1];
2734 }
2735 if (! isset ($params['a_id']) || ! isset ($params['b_id']) ||
2736 ! intval ($params['a_id']) || ! intval ($params['b_id']))
2737 throw new InvalidArgException ("ports_${i}", $_REQUEST["ports_${i}"], "can not unpack port ids");
2738
2739 $porta = getPortInfo ($params['a_id']);
2740 $portb = getPortInfo ($params['b_id']);
2741 if
2742 (
2743 $porta['linked'] or
2744 $portb['linked'] or
2745 ($porta['object_id'] != $sic['object_id'] and $portb['object_id'] != $sic['object_id'])
2746 )
2747 {
2748 $nignored++;
2749 continue;
2750 }
2751 $oif_a = intval (@$params['a_oif']); // these parameters are optional
2752 $oif_b = intval (@$params['b_oif']);
2753
2754 $dbxlink->beginTransaction();
2755 if ($oif_a || $oif_b)
2756 try
2757 {
2758 if ($oif_a)
2759 if (commitUpdatePortOIF ($params['a_id'], $oif_a))
2760 $porta['oif_id'] = $oif_a;
2761 if ($oif_b)
2762 if (commitUpdatePortOIF ($params['b_id'], $oif_b))
2763 $portb['oif_id'] = $oif_b;
2764 }
2765 catch (RTDatabaseError $e)
2766 {
2767 $dbxlink->rollBack();
2768 $nignored++;
2769 continue;
2770 }
2771
2772 foreach ($POIFC as $item)
2773 if ($item['type1'] == $porta['oif_id'] and $item['type2'] == $portb['oif_id'])
2774 {
2775 $ret = linkPorts ($params['a_id'], $params['b_id']);
2776 if (empty ($ret))
2777 {
2778 $ndone++;
2779 $dbxlink->commit();
2780 continue 2; //next port
2781 }
2782 else
2783 $nignored++;
2784 break;
2785 }
2786 $dbxlink->rollback();
2787 }
2788 return buildRedirectURL (__FUNCTION__, 'OK', array ($nignored, $ndone));
2789 }
2790
2791 $msgcode['addObjectlog']['OK'] = 0;
2792 function addObjectlog ()
2793 {
2794 assertStringArg ('logentry');
2795 global $remote_username, $sic;
2796 $oi = spotEntity ('object', $sic['object_id']);
2797 usePreparedExecuteBlade ('INSERT INTO ObjectLog SET object_id=?, user=?, date=NOW(), content=?', array ($sic['object_id'], $remote_username, $sic['logentry']));
2798 return buildRedirectURL (__FUNCTION__, 'OK', array ('Log entry for ' . mkA ($oi['dname'], 'object', $sic['object_id'], 'log') . " added by ${remote_username}"));
2799 }
2800
2801 function getOpspec()
2802 {
2803 global $pageno, $tabno, $op, $opspec_list;
2804 if (!array_key_exists ($pageno . '-' . $tabno . '-' . $op, $opspec_list))
2805 throw new RackTablesError ('key not found in opspec_list', RackTablesError::INTERNAL);
2806 $ret = $opspec_list[$pageno . '-' . $tabno . '-' . $op];
2807 if
2808 (
2809 !array_key_exists ('table', $ret)
2810 or !array_key_exists ('action', $ret)
2811 // add further checks here
2812 )
2813 throw new RackTablesError ('malformed array structure in opspec_list', RackTablesError::INTERNAL);
2814 return $ret;
2815 }
2816
2817 function unlinkPort ()
2818 {
2819 assertUIntArg ('port_id');
2820 if (commitUnlinkPort ($_REQUEST['port_id']))
2821 showSuccess ("Port unlinked successfully");
2822 else
2823 showError ("Error unlinking port");
2824 }
2825
2826 function tableHandler()
2827 {
2828 $opspec = getOpspec();
2829 global $sic;
2830 $columns = array();
2831 foreach (array ('arglist', 'set_arglist', 'where_arglist') as $listname)
2832 {
2833 if (! array_key_exists ($listname, $opspec))
2834 continue;
2835 foreach ($opspec[$listname] as $argspec)
2836 {
2837 genericAssertion ($argspec['url_argname'], $argspec['assertion']);
2838 // "table_colname" is normally used for an override, if it is not
2839 // set, use the URL argument name
2840 $table_colname = array_key_exists ('table_colname', $argspec) ?
2841 $argspec['table_colname'] :
2842 $argspec['url_argname'];
2843 $arg_value = $sic[$argspec['url_argname']];
2844 if
2845 (
2846 ($argspec['assertion'] == 'uint0' and $arg_value == 0)
2847 or ($argspec['assertion'] == 'string0' and $arg_value == '')
2848 )
2849 switch (TRUE)
2850 {
2851 case !array_key_exists ('if_empty', $argspec): // no action requested
2852 break;
2853 case $argspec['if_empty'] == 'NULL':
2854 $arg_value = NULL;
2855 break;
2856 default:
2857 throw new InvalidArgException ('opspec', '(malformed array structure)', '"if_empty" not recognized');
2858 }
2859 $columns[$listname][$table_colname] = $arg_value;
2860 }
2861 }
2862 switch ($opspec['action'])
2863 {
2864 case 'INSERT':
2865 $retcode = TRUE === usePreparedInsertBlade ($opspec['table'], $columns['arglist']) ? 48 : 110;
2866 break;
2867 case 'DELETE':
2868 $conjunction = array_key_exists ('conjunction', $opspec) ? $opspec['conjunction'] : 'AND';
2869 $retcode = FALSE !== usePreparedDeleteBlade ($opspec['table'], $columns['arglist'], $conjunction) ? 49 : 111;
2870 break;
2871 case 'UPDATE':
2872 usePreparedUpdateBlade
2873 (
2874 $opspec['table'],
2875 $columns['set_arglist'],
2876 $columns['where_arglist'],
2877 array_key_exists ('conjunction', $opspec) ? $opspec['conjunction'] : 'AND'
2878 );
2879 $retcode = 51;
2880 break;
2881 default:
2882 throw new InvalidArgException ('opspec/action', $opspec['action']);
2883 }
2884 return buildWideRedirectURL (oneLiner ($retcode));
2885 }
2886
2887 ?>