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