r1433 + introduce 2nd optional argument to showError() // calling function name
[racktables] / inc / interface.php
1 <?php
2 /*
3 *
4 * This file contains frontend functions for RackTables.
5 *
6 */
7
8 // Interface function's special.
9 $nextorder['odd'] = 'even';
10 $nextorder['even'] = 'odd';
11
12 // Main menu.
13 function renderIndex ()
14 {
15 global $root;
16 ?>
17 <table border=0 cellpadding=0 cellspacing=0 width='100%'>
18 <tr>
19 <td>
20 <div style='text-align: center; margin: 10px; '>
21 <table width='100%' cellspacing=0 cellpadding=30 class=mainmenu border=0>
22 <tr>
23 <td>
24 <h1><a href='<?php echo $root; ?>?page=rackspace'>Rackspace<br>
25 <?php printImageHREF ('rackspace'); ?></a></h1>
26 </td>
27 <td>
28 <h1><a href='<?php echo $root; ?>?page=objects'>Objects<br>
29 <?php printImageHREF ('objects'); ?></a></h1>
30 </td>
31 <td>
32 <h1><a href='<?php echo $root; ?>?page=ipv4space'>IPv4 space<br>
33 <?php printImageHREF ('ipv4space'); ?></a></h1>
34 </td>
35 </tr>
36 </table>
37 <table width='100%' cellspacing=0 cellpadding=30 class=mainmenu border=0>
38 <tr>
39 <td>
40 <h1><a href='<?php echo $root; ?>?page=config'>Configuration<br>
41 <?php printImageHREF ('config'); ?></a></h1>
42 </td>
43 <td>
44 <h1><a href='<?php echo $root; ?>?page=reports'>Reports<br>
45 <?php printImageHREF ('reports'); ?></a></h1>
46 </td>
47 <td>
48 <h1><a href='<?php echo $root; ?>?page=help'>Help<br>
49 <?php printImageHREF ('help'); ?></a></h1>
50 </td>
51 </tr>
52 </table>
53 </div>
54 </td>
55 </tr>
56 </table>
57 <?php
58 }
59
60 function renderRackspace ()
61 {
62 ?>
63 <table border=0 cellpadding=10 cellpadding=1>
64 <?php
65 // generate thumb gallery
66 $rackrowList = getRackRowInfo();
67 global $root, $nextorder;
68 $rackwidth = getConfigVar ('rtwidth_0') + getConfigVar ('rtwidth_1') + getConfigVar ('rtwidth_2');
69 $order = 'odd';
70 foreach ($rackrowList as $rackrow)
71 {
72 echo "<tr class=row_${order}><th><a href='${root}?page=row&row_id=${rackrow['dict_key']}'>${rackrow['dict_value']}</a></th>";
73 $rackList = getRacksForRow ($rackrow['dict_key']);
74 echo "<td><table border=0 cellspacing=5><tr>";
75 foreach ($rackList as $dummy => $rack)
76 {
77 echo "<td align=center><a href='${root}?page=rack&rack_id=${rack['id']}'>";
78 echo "<img border=0 width=${rackwidth} height=";
79 echo 3 + 3 + $rack['height'] * 2;
80 echo " title='${rack['height']} units'";
81 echo "src='render_rack_thumb.php?rack_id=${rack['id']}'>";
82 echo "<br>${rack['name']}</a></td>";
83 }
84 echo "</tr></table></tr>\n";
85 $order = $nextorder[$order];
86 }
87 echo "</table>\n";
88 }
89
90 function renderRow ($row_id)
91 {
92 if ($row_id == 0)
93 {
94 showError ('Invalid row_id', __FUNCTION__);
95 return;
96 }
97 if (($rowInfo = getRackRowInfo ($row_id)) == NULL)
98 {
99 showError ('getRackRowInfo() failed', __FUNCTION__);
100 return;
101 }
102 // Main layout starts.
103 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
104
105 // Left portlet with row information.
106 echo "<tr><td class=pcleft>";
107 startPortlet ($rowInfo['dict_value']);
108 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
109 echo "<tr><th width='50%' class=tdright>Racks:</th><td class=tdleft>${rowInfo['count']}</td></tr>\n";
110 echo "<tr><th width='50%' class=tdright>Units:</th><td class=tdleft>${rowInfo['sum']}</td></tr>\n";
111 echo "</table><br>\n";
112 finishPortlet();
113
114 echo "</td><td class=pcright>";
115
116 global $root, $nextorder;
117 $rackwidth = getConfigVar ('rtwidth_0') + getConfigVar ('rtwidth_1') + getConfigVar ('rtwidth_2');
118 $rackList = getRacksForRow ($row_id);
119 $order = 'odd';
120 startPortlet ('Racks');
121 echo "<table border=0 cellspacing=5 align='center'><tr>";
122 foreach ($rackList as $dummy => $rack)
123 {
124 echo "<td align=center class=row_${order}><a href='${root}?page=rack&rack_id=${rack['id']}'>";
125 echo "<img border=0 width=" . $rackwidth * getConfigVar ('ROW_SCALE') . " height=";
126 echo (3 + 3 + $rack['height'] * 2) * getConfigVar ('ROW_SCALE');
127 echo " title='${rack['height']} units'";
128 echo "src='render_rack_thumb.php?rack_id=${rack['id']}'>";
129 echo "<br>${rack['name']}</a></td>";
130 $order = $nextorder[$order];
131 }
132 echo "</tr></table>\n";
133 finishPortlet();
134
135 echo "</td></tr></table>";
136 }
137
138 function showError ($info = '', $funcname = 'N/A')
139 {
140 global $root;
141 echo '<div class=msg_error>An error has occured in function [${funcname}]. ';
142 if (empty ($info))
143 echo 'No additional information is available.';
144 else
145 echo "Additional information:<br><p>\n<pre>\n${info}\n</pre></p>";
146 echo "Go back or try starting from <a href='${root}'>index page</a>.<br></div>\n";
147 }
148
149 // This function renders rack as HTML table.
150 function renderRack ($rack_id = 0, $hl_obj_id = 0)
151 {
152 if ($rack_id == 0)
153 {
154 showError ('Invalid rack_id', __FUNCTION__);
155 return;
156 }
157 if (($rackData = getRackData ($rack_id)) == NULL)
158 {
159 showError ('getRackData() failed', __FUNCTION__);
160 return;
161 }
162 global $root, $pageno, $tabno;
163 markAllSpans ($rackData);
164 if ($hl_obj_id > 0)
165 highlightObject ($rackData, $hl_obj_id);
166 markupObjectProblems ($rackData);
167 $prev_id = getPrevIDforRack ($rackData['row_id'], $rack_id);
168 $next_id = getNextIDforRack ($rackData['row_id'], $rack_id);
169 echo "<center>\n<h2><a href='${root}?page=row&row_id=${rackData['row_id']}'>${rackData['row_name']}</a> :";
170 // FIXME: use 'bypass'?
171 if ($prev_id != NULL)
172 echo " <a href='${root}?page=rack&rack_id=${prev_id}'>&lt; &lt; &lt;</a>";
173 echo " <a href='${root}?page=rack&rack_id=${rackData['id']}'>${rackData['name']}</a>";
174 if ($next_id != NULL)
175 echo " <a href='${root}?page=rack&rack_id=${next_id}'>&gt; &gt; &gt;</a>";
176 echo "</h2>\n";
177 if ($rackData['left_is_front'] == 'yes')
178 $markup = array ('left' => 'Front', 'right' => 'Back');
179 else
180 $markup = array ('left' => 'Back', 'right' => 'Front');
181 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
182 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>${markup['left']}</th>";
183 echo "<th width='50%'>Interior</th><th width='20%'>${markup['right']}</th></tr>\n";
184 for ($i = $rackData['height']; $i > 0; $i--)
185 {
186 echo '<tr><th>' . ($rackData['bottom_is_unit1'] == 'yes' ? $i : $rackData['height'] - $i + 1) . '</th>';
187 for ($locidx = 0; $locidx < 3; $locidx++)
188 {
189 if (isset ($rackData[$i][$locidx]['skipped']))
190 continue;
191 $state = $rackData[$i][$locidx]['state'];
192 echo "<td class=state_${state}";
193 if (isset ($rackData[$i][$locidx]['hl']))
194 echo $rackData[$i][$locidx]['hl'];
195 if (isset ($rackData[$i][$locidx]['colspan']))
196 echo ' colspan=' . $rackData[$i][$locidx]['colspan'];
197 if (isset ($rackData[$i][$locidx]['rowspan']))
198 echo ' rowspan=' . $rackData[$i][$locidx]['rowspan'];
199 echo ">";
200 switch ($state)
201 {
202 case 'T':
203 $objectData = getObjectInfo ($rackData[$i][$locidx]['object_id']);
204 if (!empty ($objectData['asset_no']))
205 $prefix = "<div title='${objectData['asset_no']}";
206 else
207 $prefix = "<div title='no asset tag";
208 // Don't tell about label, if it matches common name.
209 if ($objectData['name'] != $objectData['label'] and !empty ($objectData['label']))
210 $suffix = ", visible label is \"${objectData['label']}\"'>";
211 else
212 $suffix = "'>";
213 echo $prefix . $suffix;
214 echo "<a href='${root}?page=object&object_id=${objectData['id']}'>${objectData['dname']}</a></div>";
215 break;
216 case 'A':
217 echo '<div title="This rackspace does not exist">&nbsp;</div>';
218 break;
219 case 'F':
220 echo '<div title="Free rackspace">&nbsp;</div>';
221 break;
222 case 'U':
223 echo '<div title="Problematic rackspace, you CAN\'T mount here">&nbsp;</div>';
224 break;
225 default:
226 echo '<div title="No data">&nbsp;</div>';
227 break;
228 }
229 echo '</td>';
230 }
231 echo "</tr>\n";
232 }
233 echo "</table></center>\n";
234 }
235
236 function renderNewObjectForm ()
237 {
238 global $pageno, $tabno;
239
240 // Look for current submit.
241 if (isset ($_REQUEST['got_data']))
242 {
243 $log = array();
244 assertUIntArg ('object_type_id');
245 assertStringArg ('object_name', TRUE);
246 assertStringArg ('object_label', TRUE);
247 assertStringArg ('object_barcode', TRUE);
248 assertStringArg ('object_asset_no', TRUE);
249 $type_id = $_REQUEST['object_type_id'];
250 $name = $_REQUEST['object_name'];
251 $label = $_REQUEST['object_label'];
252 $asset_no = $_REQUEST['object_asset_no'];
253 $barcode = $_REQUEST['object_barcode'];
254
255 if (commitAddObject ($name, $label, $barcode, $type_id, $asset_no) === TRUE)
256 $log[] = array ('code' => 'success', 'message' => "Added new object '${name}'");
257 else
258 $log[] = array ('code' => 'error', 'message' => 'commitAddObject() failed in renderNewObjectForm()');
259 printLog ($log);
260 }
261
262 // Render a form for the next.
263 startPortlet ('Object attributes');
264 echo '<form>';
265 echo "<input type=hidden name=page value=${pageno}>";
266 echo "<input type=hidden name=tab value=${tabno}>";
267 echo '<table border=0 align=center>';
268 echo "<tr><th class=tdright>Type:</th><td class=tdleft>";
269 printSelect (getObjectTypeList(), 'object_type_id');
270 echo "</td></tr>\n";
271 echo "<tr><th class=tdright>Common name:</th><td class=tdleft><input type=text name=object_name></td></tr>\n";
272 echo "<tr><th class=tdright>Visible label:</th><td class=tdleft><input type=text name=object_label></td></tr>\n";
273 echo "<tr><th class=tdright>Asset tag:</th><td class=tdleft><input type=text name=object_asset_no></td></tr>\n";
274 echo "<tr><th class=tdright>Barcode:</th><td class=tdleft><input type=text name=object_barcode></td></tr>\n";
275 echo "<tr><td class=submit colspan=2><input type=submit name=got_data value='Create'></td></tr>\n";
276 echo '</form></table>';
277 finishPortlet();
278 }
279
280 function renderNewRackForm ($row_id)
281 {
282 global $pageno, $tabno;
283
284 // Look for current submit.
285 if (isset ($_REQUEST['got_data']))
286 {
287 $log = array();
288 assertStringArg ('rack_name');
289 assertUIntArg ('rack_height');
290 assertStringArg ('rack_comment', TRUE);
291 $name = $_REQUEST['rack_name'];
292 $height = $_REQUEST['rack_height'];
293 $comment = $_REQUEST['rack_comment'];
294
295 if (commitAddRack ($name, $height, $row_id, $comment) === TRUE)
296 $log[] = array ('code' => 'success', 'message' => "Added new rack '${name}'");
297 else
298 $log[] = array ('code' => 'error', 'message' => 'commitAddRack() failed in renderNewRackForm()');
299 printLog ($log);
300 }
301
302 // Render a form for the next.
303 startPortlet ('Rack attributes');
304 echo '<form>';
305 echo "<input type=hidden name=page value=${pageno}>";
306 echo "<input type=hidden name=tab value=${tabno}>";
307 echo "<input type=hidden name=row_id value=${row_id}>";
308 echo '<table border=0 align=center>';
309 $defh = getConfigVar ('DEFAULT_RACK_HEIGHT');
310 if ($defh == 0)
311 $defh = '';
312 echo "<tr><th class=tdright>Name (required):</th><td class=tdleft><input type=text name=rack_name tabindex=1></td></tr>\n";
313 echo "<tr><th class=tdright>Height in units (required):</th><td class=tdleft><input type=text name=rack_height tabindex=2 value='${defh}'></td></tr>\n";
314 echo "<tr><th class=tdright>Comment:</th><td class=tdleft><input type=text name=rack_comment tabindex=3></td></tr>\n";
315 echo "<tr><td class=submit colspan=2><input type=submit name=got_data value='Create'></td></tr>\n";
316 echo '</form></table>';
317 finishPortlet();
318 }
319
320 function renderEditObjectForm ($object_id)
321 {
322 showMessageOrError();
323 // Handle submit.
324 if (isset ($_REQUEST['got_data']))
325 {
326 $log = array();
327 // object_id is already verified by page handler
328 assertUIntArg ('object_type_id');
329 assertStringArg ('object_name', TRUE);
330 assertStringArg ('object_label', TRUE);
331 assertStringArg ('object_barcode', TRUE);
332 assertStringArg ('object_asset_no', TRUE);
333 $type_id = $_REQUEST['object_type_id'];
334 if (isset ($_REQUEST['object_has_problems']) and $_REQUEST['object_has_problems'] == 'on')
335 $has_problems = 'yes';
336 else
337 $has_problems = 'no';
338 $name = $_REQUEST['object_name'];
339 $label = $_REQUEST['object_label'];
340 $barcode = $_REQUEST['object_barcode'];
341 $asset_no = $_REQUEST['object_asset_no'];
342 $comment = $_REQUEST['object_comment'];
343
344 if (commitUpdateObject ($object_id, $name, $label, $barcode, $type_id, $has_problems, $asset_no, $comment) === TRUE)
345 $log[] = array ('code' => 'success', 'message' => "Updated object '${name}'");
346 else
347 $log[] = array ('code' => 'error', 'message' => 'commitUpdateObject() failed in renderEditObjectForm()');
348 printLog ($log);
349 }
350
351 global $pageno, $tabno;
352 $object = getObjectInfo ($object_id);
353 if ($object == NULL)
354 {
355 showError ('getObjectInfo() failed', __FUNCTION__);
356 return;
357 }
358
359 // Render a form for the next submit;
360 echo '<table border=0 width=100%><tr>';
361
362 echo '<td class=pcleft>';
363 startPortlet ('Static attributes');
364 echo '<form>';
365 echo "<input type=hidden name=page value=${pageno}>";
366 echo "<input type=hidden name=tab value=${tabno}>";
367 echo "<input type=hidden name=object_id value=${object_id}>";
368 echo '<table border=0 align=center>';
369 echo "<tr><th class=tdright>Type:</th><td class=tdleft>";
370 printSelect (getObjectTypeList(), 'object_type_id', $object['objtype_id']);
371 echo "</td></tr>\n";
372 // Common attributes.
373 echo "<tr><th class=tdright>Common name:</th><td class=tdleft><input type=text name=object_name value='${object['name']}'></td></tr>\n";
374 echo "<tr><th class=tdright>Visible label:</th><td class=tdleft><input type=text name=object_label value='${object['label']}'></td></tr>\n";
375 echo "<tr><th class=tdright>Asset tag:</th><td class=tdleft><input type=text name=object_asset_no value='${object['asset_no']}'></td></tr>\n";
376 echo "<tr><th class=tdright>Barcode:</th><td class=tdleft><input type=text name=object_barcode value='${object['barcode']}'></td></tr>\n";
377 echo "<tr><th class=tdright>Has problems:</th><td class=tdleft><input type=checkbox name=object_has_problems";
378 if ($object['has_problems'] == 'yes')
379 echo ' checked';
380 echo "></td></tr>\n";
381 echo "<tr><td colspan=2><b>Comment:</b><br><textarea name=object_comment rows=10 cols=80>${object['comment']}</textarea></td></tr>";
382 echo "<tr><th class=submit colspan=2><input type=submit name=got_data value='Update'></td></tr>\n";
383 echo '</form></table><br>';
384 finishPortlet();
385 echo '</td>';
386
387 // Optional attributes.
388 echo '<td class=pcright>';
389 startPortlet ('Optional attributes');
390 $values = getAttrValues ($object_id);
391 global $root;
392 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable>\n";
393 echo "<tr><th>&nbsp;</th><th>Attribute</th><th>Value</th><th>&nbsp;</th></tr>\n";
394 echo "<form method=post action='${root}process.php'>\n";
395 echo "<input type=hidden name=page value=${pageno}>\n";
396 echo "<input type=hidden name=tab value=${tabno}>\n";
397 echo "<input type=hidden name=op value=upd>\n";
398 echo "<input type=hidden name=object_id value=${object_id}>\n";
399 echo '<input type=hidden name=num_attrs value=' . count($values) . ">\n";
400
401 $i = 0;
402 foreach ($values as $record)
403 {
404 echo "<input type=hidden name=${i}_attr_id value=${record['id']}>";
405 echo "<tr><td><a href=${root}process.php?page=${pageno}&tab=${tabno}&op=del&object_id=${object_id}&attr_id=${record['id']}>";
406 printImageHREF ('delete', 'Delete value');
407 echo "</a></td>";
408 echo "<td class=tdright>${record['name']}:</td><td class=tdleft>";
409 switch ($record['type'])
410 {
411 case 'uint':
412 case 'float':
413 case 'string':
414 echo "<input type=text name=${i}_value value='${record['value']}'>";
415 break;
416 case 'dict':
417 $chapter = readChapter ($record['chapter_name']);
418 $chapter[0] = '-- NOT SET --';
419 printSelect ($chapter, "${i}_value", $record['key']);
420 break;
421 }
422 echo "</td></tr>\n";
423 $i++;
424 }
425 echo "<tr><td colspan=3><input type=submit value='Update'></td></tr>\n";
426 echo "</form>";
427 echo "</table>\n";
428 finishPortlet();
429 echo '</td>';
430
431 echo '</tr><tr>';
432
433 echo '<td colspan=2>';
434 startPortlet ('history');
435 renderHistory ($pageno, $object_id);
436 finishPortlet();
437 echo '</td>';
438
439 echo '</tr></table>';
440 }
441
442 // This is a clone of renderEditObjectForm().
443 function renderEditRackForm ($rack_id)
444 {
445 // Handle submit.
446 if (isset ($_REQUEST['got_data']))
447 {
448 $log = array();
449 assertUIntArg ('rack_row_id');
450 assertUIntArg ('rack_height');
451 assertStringArg ('rack_name');
452 assertStringArg ('rack_comment', TRUE);
453 $row_id = $_REQUEST['rack_row_id'];
454 $height = $_REQUEST['rack_height'];
455 $name = $_REQUEST['rack_name'];
456 $comment = $_REQUEST['rack_comment'];
457
458 if (commitUpdateRack ($rack_id, $name, $height, $row_id, $comment) === TRUE)
459 $log[] = array ('code' => 'success', 'message' => "Updated rack '${name}'");
460 else
461 $log[] = array ('code' => 'error', 'message' => 'commitUpdateRack() failed in renderEditRackForm()');
462 printLog ($log);
463 }
464
465 global $pageno, $tabno;
466 $rack = getRackData ($rack_id);
467 if ($rack == NULL)
468 {
469 showError ('getRackData() failed', __FUNCTION__);
470 return;
471 }
472
473 // Render a form for the next.
474 startPortlet ('Rack attributes');
475 echo '<form>';
476 echo "<input type=hidden name=page value=${pageno}>";
477 echo "<input type=hidden name=tab value=${tabno}>";
478 echo "<input type=hidden name=rack_id value=${rack_id}>";
479 echo '<table border=0 align=center>';
480 echo "<tr><th class=tdright>Rack row:</th><td class=tdleft>";
481 printSelect (readChapter ('RackRow'), 'rack_row_id', $rack['row_id']);
482 echo "</td></tr>\n";
483 echo "<tr><th class=tdright>Name (required):</th><td class=tdleft><input type=text name=rack_name value='${rack['name']}'></td></tr>\n";
484 echo "<tr><th class=tdright>Height (required):</th><td class=tdleft><input type=text name=rack_height value='${rack['height']}'></td></tr>\n";
485 echo "<tr><th class=tdright>Comment:</th><td class=tdleft><input type=text name=rack_comment value='${rack['comment']}'></td></tr>\n";
486 echo "<tr><td class=submit colspan=2><input type=submit name=got_data value='Update'></td></tr>\n";
487 echo '</form></table><br>';
488 finishPortlet();
489
490 startPortlet ('History');
491 renderHistory ($pageno, $rack_id);
492 finishPortlet();
493 }
494
495 // This is a helper for creators and editors.
496 function printSelect ($rowList, $select_name, $selected_id = 1)
497 {
498 echo "<select name=${select_name}>";
499 foreach ($rowList as $dict_key => $dict_value)
500 {
501 echo "<option value=${dict_key}";
502 if ($dict_key == $selected_id)
503 echo ' selected';
504 echo ">${dict_value}</option>";
505 }
506 echo "</select>";
507 }
508
509 // This is a universal editor of rack design/waste.
510 function renderGridForm ($rack_id = 0, $filter, $header, $submit, $state1, $state2)
511 {
512 if ($rack_id == 0)
513 {
514 showError ('Invalid rack_id in renderGridFrom()');
515 return;
516 }
517 if (($rackData = getRackData ($rack_id)) == NULL)
518 {
519 showError ('getRackData() failed in renderGridFrom()');
520 return;
521 }
522
523 global $root, $pageno, $tabno;
524 $filter($rackData);
525 markupObjectProblems ($rackData);
526
527 // Process form submit.
528 if (isset ($_REQUEST['do_update']))
529 {
530 $log[] = processGridForm ($rackData, $state1, $state2);
531 printLog($log);
532 }
533
534 // Render the result whatever it is.
535 // Main layout.
536 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
537 echo "<tr><td colspan=2 align=center><h1>${rackData['name']}</h1></td></tr>\n";
538
539 // Left column with information portlet.
540 echo "<tr><td class=pcleft height='1%' width='50%'>";
541 startPortlet ('Rack information');
542 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
543 echo "<tr><th width='50%' class=tdright>Rack name:</th><td class=tdleft>${rackData['name']}</td></tr>\n";
544 echo "<tr><th width='50%' class=tdright>Height:</th><td class=tdleft>${rackData['height']}</td></tr>\n";
545 echo "<tr><th width='50%' class=tdright>Rack row:</th><td class=tdleft>${rackData['row_name']}</td></tr>\n";
546 echo "<tr><th width='50%' class=tdright>Comment:</th><td class=tdleft>${rackData['comment']}</td></tr>\n";
547 echo "</table>\n";
548 finishPortlet();
549
550 echo "</td>\n";
551 echo "<td class=pcright>";
552
553 // Grid form.
554 startPortlet ($header);
555 echo "<center>\n";
556 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
557 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>Front</th>";
558 echo "<th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
559 echo "<form action='${root}?'>\n";
560 echo "<input type=hidden name=page value=${pageno}>\n";
561 echo "<input type=hidden name=tab value=${tabno}>\n";
562 echo "<input type=hidden name=rack_id value=${rack_id}>\n";
563 markupAtomGrid ($rackData, $state2);
564 renderAtomGrid ($rackData);
565 echo "</table></center>\n";
566 echo "<br><input type=submit name=do_update value='${submit}'></form><br><br>\n";
567 finishPortlet();
568 echo "</td></tr></table>\n";
569 }
570
571 function renderRackDesign ($rack_id)
572 {
573 renderGridForm ($rack_id, 'applyRackDesignMask', 'Rack design', 'Set rack design', 'A', 'F');
574 }
575
576 function renderRackProblems ($rack_id = 0)
577 {
578 renderGridForm ($rack_id, 'applyRackProblemMask', 'Rack problems', 'Mark unusable atoms', 'F', 'U');
579 }
580
581 function startPortlet ($title = '')
582 {
583 echo "<div class=portlet><h2>${title}</h2>";
584 }
585
586 function finishPortlet ()
587 {
588 echo "</div>\n";
589 }
590
591 function printRefsOfType ($refs, $type, $eq)
592 {
593 global $root;
594 $gotone=0;
595 foreach ($refs as $ref)
596 {
597 if ($eq($ref['type'], $type))
598 {
599 if ($gotone) echo ', ';
600 echo "<a href='${root}?page=object&object_id=${ref['object_id']}'>";
601 if (!empty ($ref['name']))
602 echo $ref['name'] . '@';
603 echo "${ref['object_name']}</a>";
604 $gotone=1;
605 }
606 }
607 }
608
609 function renderRackObject ($object_id = 0)
610 {
611 global $root;
612 if ($object_id <= 0)
613 {
614 showError ('Invalid object_id in renderRackObject()');
615 return;
616 }
617 $info = getObjectInfo ($object_id);
618 if ($info == NULL)
619 {
620 showError ('getObjectInfo() failed in renderRackObject()');
621 return;
622 }
623 // Main layout starts.
624 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
625 echo "<tr><td colspan=2 align=center><h1>${info['dname']}</h1></td></tr>\n";
626 // left column with uknown number of portlets
627 echo "<tr><td class=pcleft>";
628 startPortlet ('Object information');
629 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
630 if (!empty ($info['name']))
631 echo "<tr><th width='50%' class=tdright>Common name:</th><td class=tdleft>${info['name']}</td></tr>\n";
632 elseif (in_array ($info['objtype_id'], explode (',', getConfigVar ('NAMEFUL_OBJTYPES'))))
633 echo "<tr><td colspan=2 class=msg_error>Common name is missing.</td></tr>\n";
634 echo "<tr><th width='50%' class=tdright>Object type:</th><td class=tdleft>${info['objtype_name']}</td></tr>\n";
635 if (!empty ($info['asset_no']))
636 echo "<tr><th width='50%' class=tdright>Asset tag:</th><td class=tdleft>${info['asset_no']}</td></tr>\n";
637 elseif (in_array ($info['objtype_id'], explode (',', getConfigVar ('REQUIRE_ASSET_TAG_FOR'))))
638 echo "<tr><td colspan=2 class=msg_error>Asset tag is missing.</td></tr>\n";
639 if (!empty ($info['label']))
640 echo "<tr><th width='50%' class=tdright>Visible label:</th><td class=tdleft>${info['label']}</td></tr>\n";
641 if (!empty ($info['barcode']))
642 echo "<tr><th width='50%' class=tdright>Barcode:</th><td class=tdleft>${info['barcode']}</td></tr>\n";
643 if ($info['has_problems'] == 'yes')
644 echo "<tr><td colspan=2 class=msg_error>Has problems</td></tr>\n";
645 foreach (getAttrValues ($object_id) as $record)
646 if (!empty ($record['value']))
647 echo "<tr><th width='50%' class=opt_attr_th>${record['name']}:</th><td class=tdleft>${record['a_value']}</td></tr>\n";
648 echo "</table><br>\n";
649 finishPortlet();
650
651 if (!empty ($info['comment']))
652 {
653 startPortlet ('Comment');
654 echo '<div class=commentblock>' . $info['comment'] . '</div>';
655 finishPortlet ();
656 }
657
658 $ports = getObjectPortsAndLinks ($object_id);
659 if (count ($ports))
660 {
661 startPortlet ('Ports and links');
662 usort($ports, 'sortByName');
663 if ($ports)
664 {
665 $hl_port_id = 0;
666 if (isset ($_REQUEST['hl_port_id']))
667 {
668 assertUIntArg ('hl_port_id');
669 $hl_port_id = $_REQUEST['hl_port_id'];
670 }
671 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
672 echo "<tr><th>Local name</th><th>Visible label</th><th>Port type</th><th>L2 address</th>";
673 echo "<th>Rem. Object</th><th>Rem. port</th></tr>\n";
674 foreach ($ports as $port)
675 {
676 echo '<tr';
677 if ($hl_port_id == $port['id'])
678 echo ' class=port_highlight';
679 echo "><td>${port['name']}</td><td>${port['label']}</td><td>${port['type']}</td>";
680 echo "<td>${port['l2address']}</td>";
681 if ($port['remote_object_id'])
682 {
683 echo "<td><a href='${root}?page=object&object_id=${port['remote_object_id']}'>${port['remote_object_name']}</a></td>";
684 echo "<td>${port['remote_name']}</td>";
685 }
686 elseif (!empty ($port['reservation_comment']))
687 {
688 echo "<td><b>Reserved;</b></td>";
689 echo "<td>${port['reservation_comment']}</td>";
690 }
691 else
692 echo '<td>&nbsp;</td><td>&nbsp;</td>';
693 echo "</tr>\n";
694 }
695 echo "</table><br>\n";
696 }
697 finishPortlet();
698 }
699 $addresses = getObjectAddresses ($object_id);
700 usort($addresses, 'sortAddresses');
701 if (count ($addresses))
702 {
703 startPortlet ('IPv4 addresses');
704 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
705 echo "<tr><th>Interface name</th><th>IP Address</th><th>Description</th><th>Misc</th></tr>\n";
706 foreach ($addresses as $addr)
707 {
708 if (strlen($addr['address_name'])>40)
709 $address_name = substr($addr['address_name'],0,38).'...';
710 else
711 $address_name = $addr['address_name'];
712
713 $virtnum = countRefsOfType($addr['references'], 'virtual', 'eq');
714 $sharednum = countRefsOfType($addr['references'], 'shared', 'eq');
715 $regnum = countRefsOfType($addr['references'], 'regular', 'eq');
716 $notvirtnum = countRefsOfType($addr['references'], 'virtual', 'neq');
717
718 if ($addr['address_reserved']=='yes')
719 $class='trwarning';
720 elseif ($addr['type']!='virtual' && $regnum>0)
721 $class='trwarning';
722 elseif ($addr['type']=='regular' && $sharednum>0)
723 $class='trwarning';
724 else
725 $class='';
726
727 echo "<tr class='$class'><td>${addr['name']}</td><td><a href='${root}?page=ipaddress&ip=${addr['ip']}'>${addr['ip']}</a></td><td class='description'>$address_name</td><td>\n";
728
729 if ($addr['address_reserved']=='yes')
730 echo "<b>Reserved;</b> ";
731
732 if ($addr['type'] == 'virtual')
733 {
734 echo "<b>V</b>";
735 if ($notvirtnum > 0)
736 {
737 echo " Owners: ";
738 printRefsOfType($addr['references'], 'virtual', 'neq');
739 }
740 }
741 elseif ($addr['type'] == 'shared')
742 {
743 echo "<b>S</b>";
744 if ($sharednum > 0)
745 {
746 echo " Peers: ";
747 printRefsOfType($addr['references'], 'shared', 'eq');
748 echo ";";
749 }
750 if ($virtnum > 0)
751 {
752 echo " Virtuals: ";
753 printRefsOfType($addr['references'], 'virtual', 'eq');
754 echo ";";
755 }
756 if ($regnum > 0)
757 {
758 echo " Collisions: ";
759 printRefsOfType($addr['references'], 'regular', 'eq');
760 }
761
762 }
763 else
764 {
765 if ($virtnum > 0)
766 {
767 echo " Virtuals: ";
768 printRefsOfType($addr['references'], 'virtual', 'eq');
769 echo ";";
770 }
771 if ($notvirtnum > 0)
772 {
773 echo " Collisions: ";
774 printRefsOfType($addr['references'], 'virtual', 'neq');
775 }
776 }
777
778 echo "</td></tr>\n";
779 }
780 echo "</table><br>\n";
781 finishPortlet();
782 }
783
784 $forwards = getObjectForwards ($object_id);
785 if (count($forwards['in']) or count($forwards['out']))
786 {
787 startPortlet('NATv4');
788
789 if (count($forwards['out']))
790 {
791
792 echo "<h3>locally performed NAT</h3>";
793
794 echo "<table class='widetable' cesspadding=5 cellspacing=0 border=0 align='center'>\n";
795 echo "<tr><th>Proto</th><th>Match endpoint</th><th>Translate to</th><th>Target object</th><th>Rule comment</th></tr>\n";
796
797 foreach ($forwards['out'] as $pf)
798 {
799 $class='trwarning';
800 $name='';
801 foreach ($addresses as $addr)
802 if ($addr['ip'] == $pf['localip'])
803 {
804 $class='';
805 $name=$addr['name'];
806 break;
807 }
808
809 echo "<tr class='$class'>";
810
811 echo "<td>${pf['proto']}</td><td class=tdleft>${name}: <a href='${root}?page=ipaddress&tab=default&ip=${pf['localip']}'>${pf['localip']}</a>:${pf['localport']}</td>";
812
813 echo "<td class=tdleft><a href='${root}?page=ipaddress&tab=default&ip=${pf['remoteip']}'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
814
815 $address=getIPAddress($pf['remoteip']);
816
817 echo "<td class='description'>";
818 if (count ($address['bonds']))
819 foreach($address['bonds'] as $bond)
820 echo "<a href='${root}?page=object&tab=default&object_id=${bond['object_id']}'>${bond['object_name']}(${bond['name']})</a> ";
821 elseif (!empty ($pf['remote_addr_name']))
822 echo '(' . $pf['remote_addr_name'] . ')';
823
824 echo "</td><td class='description'>${pf['description']}</td>";
825
826 echo "</tr>";
827 }
828 echo "</table><br><br>";
829 }
830 if (count($forwards['in']))
831 {
832 echo "<h3>arriving NAT connections</h3>";
833
834 echo "<table class='widetable' cesspadding=5 cellspacing=0 border=0 align='center'>\n";
835 echo "<tr><th>Matched endpoint</th><th>Source object</th><th>Translated to</th><th>Rule comment</th></tr>\n";
836
837 foreach ($forwards['in'] as $pf)
838 {
839 echo "<tr>";
840 echo "<td>${pf['proto']}/<a href='${root}?page=ipaddress&tab=default&ip=${pf['localip']}'>${pf['localip']}</a>:${pf['localport']}</td>";
841
842 echo "<td class='description'><a href='${root}?page=object&tab=default&object_id=${pf['object_id']}'>${pf['object_name']}</a>";
843
844 echo "</td><td><a href='${root}?page=ipaddress&tab=default&ip=${pf['remoteip']}'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
845 echo "<td class='description'>${pf['description']}</td></tr>";
846 }
847
848 echo "</table><br><br>";
849 }
850 finishPortlet();
851 }
852
853 echo "</td>\n";
854
855 // After left column we have (surprise!) right column with rackspace portled only.
856 echo "<td class=pcright>";
857 // rackspace portlet
858 startPortlet ('Rackspace allocation');
859 // FIXME: now we call getRackData() twice
860 $racks = getResidentRacksData ($object_id);
861 foreach ($racks as $rackData)
862 renderRack ($rackData['id'], $object_id);
863 echo '<br>';
864 finishPortlet();
865 echo "</td></tr>";
866 echo "</table>\n";
867 }
868
869 function renderRackMultiSelect ($sname, $racks, $selected)
870 {
871 echo "<select name=${sname} multiple size=" . getConfigVar ('MAXSELSIZE') . " onchange='getElementById(\"racks\").submit()'>\n";
872 foreach ($racks as $rack)
873 {
874 echo "<option value=${rack['id']}";
875 if (!(array_search ($rack['id'], $selected) === FALSE))
876 echo ' selected';
877 echo">${rack['row_name']}: ${rack['name']}</option>\n";
878 }
879 echo "</select>\n";
880 }
881
882 function showMessageOrError ()
883 {
884 if (isset($_REQUEST['message']))
885 echo "<div class=msg_success>${_REQUEST['message']}</div>";
886 if (isset($_REQUEST['error']))
887 echo "<div class=msg_error>${_REQUEST['error']}</div>";
888 }
889
890 // This function renders a form for port edition.
891 function renderPortsForObject ($object_id = 0)
892 {
893 global $root, $pageno, $tabno;
894 if ($object_id <= 0)
895 {
896 showError ('Invalid object_id in renderPortsForObject()');
897 return;
898 }
899 showMessageOrError();
900 startPortlet ('Ports and interfaces');
901 $ports = getObjectPortsAndLinks ($object_id);
902 usort($ports, 'sortByName');
903 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
904 echo "<tr><th>&nbsp;</th><th>Local name</th><th>Visible label</th><th>Port type</th><th>L2 address</th>";
905 echo "<th>Rem. object</th><th>Rem. port</th><th>(Un)link or (un)reserve</th><th>&nbsp;</th></tr>\n";
906 foreach ($ports as $port)
907 {
908 echo "<form action='${root}process.php'>";
909 echo "<input type=hidden name=op value=editPort>";
910 echo "<input type=hidden name=page value='${pageno}'>\n";
911 echo "<input type=hidden name=tab value='${tabno}'>\n";
912 echo "<input type=hidden name=port_id value='${port['id']}'>";
913 echo "<input type=hidden name=object_id value='$object_id'>\n";
914 echo "<tr><td><a href='${root}process.php?op=delPort&page=${pageno}&tab=${tabno}&port_id=${port['id']}&object_id=$object_id&port_name=${port['name']}'>";
915 printImageHREF ('delete', 'Unlink and Delete this port');
916 echo "</a></td>\n";
917 echo "<td><input type=text name=name value='${port['name']}' size=8></td>";
918 echo "<td><input type=text name=label value='${port['label']}' size=24></td>";
919 echo "<td>${port['type']}</td>\n";
920 echo "<td><input type=text name=l2address value='${port['l2address']}'></td>\n";
921 if ($port['remote_object_id'])
922 {
923 echo "<td><a href='${root}?page=object&object_id=${port['remote_object_id']}'>${port['remote_object_name']}</a></td>";
924 echo "<td>${port['remote_name']}</td>";
925 echo "<td><a href='${root}process.php?op=unlinkPort&page=${pageno}&tab=${tabno}&port_id=${port['id']}&object_id=$object_id&port_name=";
926 echo urlencode ($port['name']);
927 echo "&remote_port_name=${port['remote_name']}&remote_object_name=${port['remote_object_name']}'>";
928 printImageHREF ('unlink', 'Unlink this port');
929 echo "</a></td>";
930 }
931 elseif (!empty ($port['reservation_comment']))
932 {
933 echo "<td><b>Reserved;</b></td>";
934 echo "<td><input type=text name=reservation_comment value='${port['reservation_comment']}'></td>";
935 echo "<td><a href='${root}process.php?op=useup&page=${pageno}&tab=${tabno}&port_id=${port['id']}&object_id=${object_id}'>";
936 printImageHREF ('useup', 'Use up this port');
937 echo "</a></td>";
938 }
939 else
940 {
941 echo "<td>&nbsp;</td><td>&nbsp;</td>";
942 echo "<td>";
943 echo "<a href='javascript:;' onclick='window.open(\"${root}link_helper.php?port=${port['id']}&type=${port['type_id']}&object_id=$object_id&port_name=";
944 echo urlencode ($port['name']);
945 echo "\",\"findlink\",\"height=700, width=400, location=no, menubar=no, resizable=yes, scrollbars=no, status=no, titlebar=no, toolbar=no\");'>";
946 printImageHREF ('link', 'Link this port');
947 echo "</a> <input type=text name=reservation_comment>";
948 echo "</td>\n";
949 }
950 echo "<td><input type='submit' value='OK'></td>";
951 echo "</form></tr>\n";
952 }
953 echo "<form action='${root}process.php'><tr>";
954 echo "<td colspan=2><input type=text size=10 name=port_name tabindex=100></td>\n";
955 echo "<td><input type=text size=24 name=port_label tabindex=101></td>";
956 echo "<input type=hidden name=op value=addPort>\n";
957 echo "<input type=hidden name=object_id value='${object_id}'>\n";
958 echo "<input type=hidden name=page value='${pageno}'>\n";
959 echo "<input type=hidden name=tab value='${tabno}'>\n";
960 echo "<td><select name='port_type_id' tabindex=102>\n";
961 $types = getPortTypes();
962 $default_port_type = getConfigVar ('default_port_type');
963 foreach ($types as $typeid => $typename)
964 {
965 echo "<option value='${typeid}'";
966 if ($typeid == $default_port_type)
967 echo " selected";
968 echo ">${typename}</option>\n";
969 }
970 echo "</select></td>";
971 echo "<td><input type=text name=port_l2address tabindex=103></td>\n";
972 echo "<td colspan=4><input type='submit' value='Add a new port' tabindex=104></td></tr></form>";
973 echo "</table><br>\n";
974 finishPortlet();
975
976 startPortlet ('Add/update multiple ports');
977 echo "<form action=${root}process.php method=post>";
978 echo "<input type=hidden name=page value='${pageno}'>\n";
979 echo "<input type=hidden name=tab value='${tabno}'>\n";
980 echo "<input type=hidden name=object_id value='${object_id}'>\n";
981 echo "<input type=hidden name=op value=addMultiPorts>";
982 echo 'Format: <select name=format>';
983 echo '<option value=c2900 disabled>Cisco 2900 series: sh int eth</option>';
984 echo '<option value=c3600eth disabled>Cisco 3600 ethernet: sh arp | inc -</option>';
985 echo '<option value=c3600asy>Cisco 3600 async: sh line | inc TTY</option>';
986 echo '<option value=fiwg selected>Foundry ServerIron/FastIron WorkGroup/Edge: sh int br</option>';
987 echo '<option value=fiedge disabled>Foundry FastIron Edge: sh int br</option>';
988 echo '<option value=fisxii>Foundry FastIron SuperX/II4000: sh int br</option>';
989 echo "</select>";
990 echo 'Default port type: ';
991 echo "<select name=port_type>\n";
992 foreach ($types as $typeid => $typename)
993 {
994 echo "<option value='${typeid}'";
995 if ($typeid == $default_port_type)
996 echo " selected";
997 echo ">${typename}</option>\n";
998 }
999 echo "</select>";
1000 echo "<input type=submit value='Parse output'><br>\n";
1001 echo "<textarea name=input cols=100 rows=50></textarea><br>\n";
1002 echo '</form>';
1003 finishPortlet();
1004 }
1005
1006 function renderNetworkForObject ($object_id=0)
1007 {
1008 global $root, $pageno, $tabno;
1009 if ($object_id <= 0)
1010 {
1011 showError ('Invalid object_id in renderNetworkForObject()');
1012 return;
1013 }
1014 showMessageOrError();
1015 startPortlet ('Network Addresses');
1016 $addresses = getObjectAddresses ($object_id);
1017 usort($addresses, 'sortAddresses');
1018 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
1019 echo "<tr><th>&nbsp;</th><th>Interface name</th><th>IP Address</th><th>Description</th><th>Type</th><th>Misc</th><th>&nbsp</th></tr>\n";
1020 foreach ($addresses as $addr)
1021 {
1022 if (strlen($addr['address_name'])>40)
1023 $address_name = substr($addr['address_name'],0,38).'...';
1024 else
1025 $address_name = $addr['address_name'];
1026
1027 $virtnum = countRefsOfType($addr['references'], 'virtual', 'eq');
1028 $sharednum = countRefsOfType($addr['references'], 'shared', 'eq');
1029 $regnum = countRefsOfType($addr['references'], 'regular', 'eq');
1030 $notvirtnum = countRefsOfType($addr['references'], 'virtual', 'neq');
1031
1032 if ($addr['address_reserved']=='yes')
1033 $class='trwarning';
1034 elseif ($addr['type']!='virtual' && $regnum>0)
1035 $class='trwarning';
1036 elseif ($addr['type']=='regular' && $sharednum>0)
1037 $class='trwarning';
1038 else
1039 $class='';
1040
1041 echo "<form action='process.php'>";
1042 echo "<input type=hidden name=page value='${pageno}'>\n";
1043 echo "<input type=hidden name=tab value='${tabno}'>\n";
1044 echo "<input type=hidden name=op value=editAddressFromObject>";
1045 echo "<input type=hidden name=object_id value='$object_id'>";
1046 echo "<input type=hidden name=ip value='${addr['ip']}'>";
1047 echo "<tr class='$class'><td><a href='process.php?op=delAddrFObj&page=${pageno}&tab=${tabno}&ip=${addr['ip']}&object_id=$object_id'>";
1048 printImageHREF ('delete', 'Delete this IPv4 address');
1049 echo "</a></td>";
1050 echo "<td><input type='text' name='bond_name' value='${addr['name']}' size=10></td>";
1051 echo "<td><a href='${root}?page=ipaddress&ip=${addr['ip']}'>${addr['ip']}</a></td>";
1052 echo "<td class='description'>$address_name</td>\n";
1053 echo "<td><select name='bond_type'>";
1054 foreach (array('regular'=>'Regular', 'virtual'=>'Virtual', 'shared'=>'Shared') as $n => $v)
1055 {
1056 echo "<option value='$n'";
1057 if ($addr['type'] == $n)
1058 echo " selected";
1059 echo ">$v</option>";
1060 }
1061 echo "</td><td>";
1062 if ($addr['address_reserved']=='yes')
1063 echo "<b>Reserved</b>; ";
1064
1065 if ($addr['type'] == 'virtual')
1066 {
1067 if ($notvirtnum > 0)
1068 {
1069 echo " Owners: ";
1070 printRefsOfType($addr['references'], 'virtual', 'neq');
1071 }
1072 }
1073 elseif ($addr['type'] == 'shared')
1074 {
1075 if ($sharednum > 0)
1076 {
1077 echo " Peers: ";
1078 printRefsOfType($addr['references'], 'shared', 'eq');
1079 echo ";";
1080 }
1081 if ($virtnum > 0)
1082 {
1083 echo " Virtuals: ";
1084 printRefsOfType($addr['references'], 'virtual', 'eq');
1085 echo ";";
1086 }
1087 if ($regnum > 0)
1088 {
1089 echo " Collisions: ";
1090 printRefsOfType($addr['references'], 'regular', 'eq');
1091 }
1092
1093 }
1094 else
1095 {
1096 if ($virtnum > 0)
1097 {
1098 echo " Virtuals: ";
1099 printRefsOfType($addr['references'], 'virtual', 'eq');
1100 echo ";";
1101 }
1102 if ($notvirtnum > 0)
1103 {
1104 echo " Collisions: ";
1105 printRefsOfType($addr['references'], 'virtual', 'neq');
1106 }
1107 }
1108
1109 echo "</td><td><input type=submit value='OK'></td></form></tr>\n";
1110 }
1111
1112
1113 echo "<form action='${root}process.php'><tr><td colspan=2><input type='text' size='10' name='name' tabindex=100></td>\n";
1114 echo "<input type=hidden name=page value='${pageno}'>\n";
1115 echo "<input type=hidden name=tab value='${tabno}'>\n";
1116 echo "<input type=hidden name=op value=addAddrFObj>\n";
1117 echo "<input type=hidden name=object_id value='$object_id'>\n";
1118
1119 echo "<td><input type=text name='ip' tabindex=101>\n";
1120 echo "</td><td><select name='type' tabindex=102>";
1121 echo "<option value='regular'>Regular</option>";
1122 echo "<option value='virtual'>Virtual</option>";
1123 echo "<option value='shared'>Shared</option>";
1124 echo "</select>";
1125 echo "</td><td colspan=3><input type='submit' value='Add a new interface' tabindex=103></td></tr></form>";
1126 echo "</table><br>\n";
1127 finishPortlet();
1128
1129 }
1130
1131 function printLog ($log)
1132 {
1133 foreach ($log as $record)
1134 echo "<div class=msg_${record['code']}>${record['message']}</div>";
1135 }
1136
1137 /*
1138 The following conditions must be followed:
1139 1. We can mount onto free atoms only. This means: if any record for an atom
1140 already exists in RackSpace, it can't be used for mounting.
1141 2. We can't unmount from 'W' atoms. Operator should review appropriate comments
1142 and either delete them before unmounting or refuse to unmount the object.
1143 */
1144
1145 // We extensively use $_REQUEST in the function.
1146 function renderRackSpaceForObject ($object_id = 0)
1147 {
1148 if ($object_id <= 0)
1149 {
1150 showError ('Invalid object_id in renderRackSpaceForObject()');
1151 return;
1152 }
1153 $is_submit = isset ($_REQUEST['got_atoms']);
1154 $is_update = isset ($_REQUEST['rackmulti'][0]);
1155 $info = getObjectInfo ($object_id);
1156 if ($info == NULL)
1157 {
1158 showError ('getObjectInfo() failed in renderRackSpaceForObject()');
1159 return;
1160 }
1161 // Always process occupied racks plus racks chosen by user. First get racks with
1162 // already allocated rackspace...
1163 $workingRacksData = getResidentRacksData ($object_id);
1164 if ($workingRacksData === NULL)
1165 {
1166 print_r ($workingRacksData);
1167 showError ('getResidentRacksData() failed in renderRackSpaceForObject()');
1168 return;
1169 }
1170
1171 // ...and then add those chosen by user (if any).
1172 if ($is_update)
1173 foreach ($_REQUEST['rackmulti'] as $cand_id)
1174 {
1175 if (!isset ($workingRacksData[$cand_id]))
1176 {
1177 $rackData = getRackData ($cand_id);
1178 if ($rackData == NULL)
1179 {
1180 showError ('getRackData() failed in renderRackSpaceForObject()');
1181 return NULL;
1182 }
1183 $workingRacksData[$cand_id] = $rackData;
1184 }
1185 }
1186
1187 // Do it only once...
1188 foreach ($workingRacksData as &$rackData)
1189 applyObjectMountMask ($rackData, $object_id);
1190 // Now we workaround an old caveat: http://bugs.php.net/bug.php?id=37410
1191 unset ($rackData);
1192
1193 // Here we process form submit by trying to save all submitted info to database.
1194 if ($is_submit)
1195 {
1196 $oldMolecule = getMoleculeForObject ($object_id);
1197 $worldchanged = FALSE;
1198 $log = array();
1199 foreach ($workingRacksData as $rack_id => $rackData)
1200 {
1201 $logrecord = processGridForm ($rackData, 'F', 'T', $object_id);
1202 $log[] = $logrecord;
1203 if ($logrecord['code'] != 300)
1204 {
1205 $worldchanged = TRUE;
1206 // Reload our working copy after form processing.
1207 $rackData = getRackData ($rack_id);
1208 if ($rackData == NULL)
1209 $log[] = array ('code' => 500, 'message' => 'Working copy update failed in renderRackSpaceForObject()');
1210 applyObjectMountMask ($rackData, $object_id);
1211 $workingRacksData[$rack_id] = $rackData;
1212 }
1213 }
1214 if ($worldchanged)
1215 {
1216 // Log a record.
1217 $newMolecule = getMoleculeForObject ($object_id);
1218 $oc = count ($oldMolecule);
1219 $nc = count ($newMolecule);
1220 $omid = $oc ? createMolecule ($oldMolecule) : 'NULL';
1221 $nmid = $nc ? createMolecule ($newMolecule) : 'NULL';
1222 global $remote_username;
1223 $comment = empty ($_REQUEST['comment']) ? 'NULL' : "'${_REQUEST['comment']}'";
1224 $query =
1225 "insert into MountOperation(object_id, old_molecule_id, new_molecule_id, user_name, comment) " .
1226 "values (${object_id}, ${omid}, ${nmid}, '${remote_username}', ${comment})";
1227 global $dbxlink;
1228 $result = $dbxlink->query ($query);
1229 if ($result == NULL)
1230 $log[] = array ('code' => 'error', 'message' => 'SQL query failed during history logging.');
1231 else
1232 $log[] = array ('code' => 'success', 'message' => 'History logged.');
1233 }
1234 printLog ($log);
1235 }
1236
1237 // This is the time for rendering.
1238 global $root, $pageno, $tabno;
1239 echo "<form id='racks' action='${root}'>";
1240 echo "<input type=hidden name=page value='${pageno}'>\n";
1241 echo "<input type=hidden name=tab value='${tabno}'>\n";
1242 echo "<input type=hidden name=object_id value='${object_id}'>\n";
1243 // Main layout starts.
1244 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0><tr>";
1245
1246 // Left portlet with rack list.
1247 echo "<td class=pcleft height='1%'>";
1248 startPortlet ('Racks');
1249 $allRacksData = getRacksForRow();
1250 renderRackMultiSelect ('rackmulti[]', $allRacksData, array_keys ($workingRacksData));
1251 echo "<br>";
1252 echo "<br>";
1253 finishPortlet();
1254 echo "</td>";
1255
1256 // Middle portlet with comment and submit.
1257 echo "<td class=pcleft>";
1258 startPortlet ('Comment');
1259 echo "<textarea name=comment rows=10 cols=40></textarea><br>\n";
1260 echo "<input type=submit value='Save' name=got_atoms>\n";
1261 echo "<br>";
1262 echo "<br>";
1263 finishPortlet();
1264 echo "</td>";
1265
1266 // Right portlet with rendered racks. If this form submit is not final, we have to
1267 // reflect the former state of the grid in current form.
1268 echo "<td class=pcright rowspan=2 height='1%'>";
1269 startPortlet ('Working copy');
1270 echo '<table border=0 cellspacing=10 align=center><tr>';
1271 foreach ($workingRacksData as $rack_id => $rackData)
1272 {
1273 // Order is important here: only original allocation is highlighted.
1274 highlightObject ($rackData, $object_id);
1275 markupAtomGrid ($rackData, 'T');
1276 // If we have a form processed, discard user input and show new database
1277 // contents.
1278 if (!$is_submit and $is_update)
1279 mergeGridFormToRack ($rackData);
1280 echo "<td valign=top>";
1281 echo "<center>\n<h2>${rackData['name']}</h2>\n";
1282 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
1283 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>Front</th>";
1284 echo "<th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
1285 renderAtomGrid ($rackData);
1286 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>Front</th>";
1287 echo "<th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
1288 echo "</table></center>\n";
1289 echo '</td>';
1290 }
1291 echo "</tr></table>";
1292 finishPortlet();
1293 echo "</td>\n";
1294
1295 echo "</form>\n";
1296 echo "</tr></table>\n";
1297 }
1298
1299 function renderMolecule ($mdata, $object_id)
1300 {
1301 // sort data out
1302 $rackpack = array();
1303 global $loclist;
1304 foreach ($mdata as $dummy => $rua)
1305 {
1306 $rack_id = $rua['rack_id'];
1307 $unit_no = $rua['unit_no'];
1308 $atom = $rua['atom'];
1309 if (!isset ($rackpack[$rack_id]))
1310 {
1311 $rackData = getRackData ($rack_id);
1312 for ($i = $rackData['height']; $i > 0; $i--)
1313 for ($locidx = 0; $locidx < 3; $locidx++)
1314 $rackData[$i][$locidx]['state'] = 'F';
1315 $rackpack[$rack_id] = $rackData;
1316 }
1317 $rackpack[$rack_id][$unit_no][$loclist[$atom]]['state'] = 'T';
1318 $rackpack[$rack_id][$unit_no][$loclist[$atom]]['object_id'] = $object_id;
1319 }
1320 // now we have some racks to render
1321 foreach ($rackpack as $dummy => $rackData)
1322 {
1323 markAllSpans ($rackData);
1324 echo "<table class=molecule cellspacing=0>\n";
1325 echo "<caption>${rackData['name']}</caption>\n";
1326 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>Front</th><th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
1327 for ($i = $rackData['height']; $i > 0; $i--)
1328 {
1329 echo "<tr><th>$i</th>";
1330 for ($locidx = 0; $locidx < 3; $locidx++)
1331 {
1332 $state = $rackData[$i][$locidx]['state'];
1333 echo "<td class=state_${state}>&nbsp;</td>\n";
1334 }
1335 echo "</tr>\n";
1336 }
1337 echo "</table>\n";
1338 }
1339 }
1340
1341 function renderUnmountedObjectsPortlet ()
1342 {
1343 startPortlet ('Unmounted objects');
1344 $objs = getUnmountedObjects();
1345 if ($objs === NULL)
1346 {
1347 showError ('getUnmountedObjects() failed in renderUnmountedObjectsPortlet()');
1348 return;
1349 }
1350 global $root, $nextorder;
1351 $order = 'odd';
1352 echo '<br><br><table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
1353 echo '<tr><th>Common name</th><th>Visible label</th><th>Asset number</th><th>Barcode</th></tr>';
1354 foreach ($objs as $obj)
1355 {
1356 echo "<tr class=row_${order}><td><a href='${root}?page=object&object_id=${obj['id']}'>${obj['dname']}</a></td>";
1357 echo "<td>${obj['label']}</td>";
1358 echo "<td>${obj['asset_no']}</td>";
1359 echo "<td>${obj['barcode']}</td></tr>";
1360 $order = $nextorder[$order];
1361 }
1362 echo "</table><br>\n";
1363 finishPortlet();
1364 }
1365
1366 function renderProblematicObjectsPortlet ()
1367 {
1368 startPortlet ('Problematic objects');
1369 $objs = getProblematicObjects();
1370 if ($objs === NULL)
1371 {
1372 showError ('getProblematicObjects() failed in renderProblematicObjectsPortlet()');
1373 return;
1374 }
1375 global $root, $nextorder;
1376 $order = 'odd';
1377 echo '<br><br><table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
1378 echo '<tr><th>Type</th><th>Common name</th></tr>';
1379 foreach ($objs as $obj)
1380 {
1381 echo "<tr class=row_${order}><td>${obj['objtype_name']}</td>";
1382 echo "<td><a href='${root}?page=object&object_id=${obj['id']}'>${obj['dname']}</a></tr>";
1383 $order = $nextorder[$order];
1384 }
1385 echo "</table><br>\n";
1386 finishPortlet();
1387 }
1388
1389 function renderObjectGroupSummary ()
1390 {
1391 global $root;
1392 $summary = getObjectGroupInfo();
1393 if ($summary === NULL)
1394 {
1395 showError ('getObjectGroupInfo() failed in renderObjectGroupSummary()');
1396 return;
1397 }
1398 echo "<table border=0 class=objectview>\n";
1399 echo "<tr><td class=pcleft width='25%'>";
1400
1401 startPortlet ('Summary');
1402 foreach ($summary as $gi)
1403 {
1404 echo "<a href='${root}?page=objgroup&group_id=${gi['id']}'><b>${gi['name']}</b></a> <i>(${gi['count']})</i><br>";
1405 }
1406 finishPortlet();
1407
1408 echo '</td><td class=pcright>';
1409 renderUnmountedObjectsPortlet();
1410 echo '</td><td class=pcright>';
1411 renderProblematicObjectsPortlet();
1412 echo "</td></tr></table>\n";
1413 }
1414
1415 function renderObjectGroup ($group_id = 0)
1416 {
1417 global $root;
1418 $summary = getObjectGroupInfo();
1419 if ($summary == NULL)
1420 {
1421 showError ('getObjectGroupInfo() failed in renderObjectGroup()');
1422 return;
1423 }
1424 $objects = getObjectList ($group_id);
1425 if ($objects === NULL)
1426 {
1427 showError ('getObjectList() failed in renderObjectGroup()');
1428 return;
1429 }
1430 echo "<table border=0 class=objectview>\n";
1431 echo "<tr><td class=pcleft width='25%'>";
1432
1433 startPortlet ('All objects');
1434 foreach ($summary as $gi)
1435 {
1436 echo "<a href='${root}?page=objgroup&group_id=${gi['id']}'><b>${gi['name']}</b></a> <i>(${gi['count']})</i><br>";
1437 }
1438 finishPortlet();
1439
1440 echo '</td><td class=pcright>';
1441
1442 startPortlet ('Object group');
1443 echo '<br><br><table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
1444 echo '<tr><th>Common name</th><th>Visible label</th><th>Asset tag</th><th>Barcode</th><th>Rack</th></tr>';
1445 $order = 'odd';
1446 global $nextorder;
1447 foreach ($objects as $obj)
1448 {
1449 echo "<tr class=row_${order}><td><a href='${root}?page=object&object_id=${obj['id']}'>${obj['dname']}</a></td>";
1450 echo "<td>${obj['label']}</td>";
1451 echo "<td>${obj['asset_no']}</td>";
1452 echo "<td>${obj['barcode']}</td>";
1453 if ($obj['rack_id'])
1454 echo "<td><a href='${root}?page=rack&rack_id=${obj['rack_id']}'>${obj['Rack_name']}</a></td>";
1455 else
1456 echo '<td>Unmounted</td>';
1457 echo '</tr>';
1458 $order = $nextorder[$order];
1459 }
1460 echo '</table>';
1461 finishPortlet();
1462
1463 echo "</td></tr></table>";
1464 }
1465
1466 function renderEmptyPortsSelect ($port_id, $type_id)
1467 {
1468 $ports = getEmptyPortsOfType($type_id);
1469 usort($ports, 'sortEmptyPorts');
1470 foreach ($ports as $port)
1471 {
1472 if ($port_id == $port['Port_id'])
1473 continue;
1474 echo "<option value='${port['Port_id']}' onclick='getElementById(\"remote_port_name\").value=\"${port['Port_name']}\"; getElementById(\"remote_object_name\").value=\"${port['Object_name']}\";'>${port['Object_name']} ${port['Port_name']}</option>\n";
1475 }
1476 }
1477
1478 function renderObjectAddressesAndNames ()
1479 {
1480 $addresses = getObjectAddressesAndNames();
1481 usort($addresses, 'sortObjectAddressesAndNames');
1482 foreach ($addresses as $address)
1483 {
1484 echo "<option value='${address['ip']}' onclick='getElementById(\"ip\").value=\"${address['ip']}\";'>${address['object_name']} ${address['name']} ${address['ip']}</option>\n";
1485 }
1486 }
1487
1488 // History viewer for history-enabled simple dictionaries.
1489 function renderHistory ($object_type, $object_id)
1490 {
1491 switch ($object_type)
1492 {
1493 case 'row':
1494 $query = "select ctime, user_name, name, deleted, comment from RackRowHistory where id = ${object_id} order by ctime";
1495 $header = '<tr><th>change time</th><th>author</th><th>rack row name</th><th>is deleted?</th><th>rack row comment</th></tr>';
1496 $extra = 4;
1497 break;
1498 case 'rack':
1499 $query =
1500 "select ctime, user_name, rh.name, rh.deleted, d.dict_value as name, rh.height, rh.comment " .
1501 "from RackHistory as rh left join Dictionary as d on rh.row_id = d.dict_key " .
1502 "natural join Chapter " .
1503 "where chapter_name = 'RackRow' and rh.id = ${object_id} order by ctime";
1504 $header = '<tr><th>change time</th><th>author</th><th>rack name</th><th>is deleted?</th><th>rack row name</th><th>rack height</th><th>rack comment</th></tr>';
1505 $extra = 6;
1506 break;
1507 case 'object':
1508 $query =
1509 "select ctime, user_name, name, label, barcode, asset_no, deleted, has_problems, dict_value, comment " .
1510 "from RackObjectHistory inner join Dictionary on objtype_id = dict_key natural join Chapter " .
1511 "where chapter_name = 'RackObjectType' and id=${object_id} order by ctime";
1512 $header = '<tr><th>change time</th><th>author</th><th>common name</th><th>visible label</th><th>barcode</th><th>asset no</th><th>is deleted?</th><th>has problems?</th><th>object type</th><th>comment</th></tr>';
1513 $extra = 9;
1514 break;
1515 default:
1516 showError ("Uknown object type '${object_type}' in renderHistory()");
1517 return;
1518 }
1519 global $dbxlink;
1520 $result = $dbxlink->query ($query);
1521 if ($result == NULL)
1522 {
1523 showError ('SQL query failed in renderHistory()');
1524 return;
1525 }
1526 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
1527 $order = 'odd';
1528 global $nextorder;
1529 echo $header;
1530 while ($row = $result->fetch (PDO::FETCH_NUM))
1531 {
1532 echo "<tr class=row_${order}><td>${row[0]}</td>";
1533 for ($i = 1; $i <= $extra; $i++)
1534 echo "<td>" . $row[$i] . "</td>";
1535 echo "</tr>\n";
1536 $order = $nextorder[$order];
1537 }
1538 echo "</table><br>\n";
1539 }
1540
1541 function renderRackspaceHistory ()
1542 {
1543 global $root, $nextorder, $pageno, $tabno;
1544 $order = 'odd';
1545 $history = getRackspaceHistory();
1546 // Show the last operation by default.
1547 if (isset ($_REQUEST['op_id']))
1548 $op_id = $_REQUEST['op_id'];
1549 elseif (isset ($history[0]['mo_id']))
1550 $op_id = $history[0]['mo_id'];
1551 else $op_id = NULL;
1552
1553 $omid = NULL;
1554 $nmid = NULL;
1555 $object_id = 1;
1556 if ($op_id)
1557 list ($omid, $nmid) = getOperationMolecules ($op_id);
1558
1559 // Main layout starts.
1560 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
1561
1562 // Left top portlet with old allocation.
1563 echo "<tr><td class=pcleft>";
1564 startPortlet ('Old allocation');
1565 if ($omid)
1566 {
1567 $oldMolecule = getMolecule ($omid);
1568 renderMolecule ($oldMolecule, $object_id);
1569 }
1570 else
1571 echo "nothing";
1572 finishPortlet();
1573
1574 echo '</td><td class=pcright>';
1575
1576 // Right top portlet with new allocation
1577 startPortlet ('New allocation');
1578 if ($nmid)
1579 {
1580 $newMolecule = getMolecule ($nmid);
1581 renderMolecule ($newMolecule, $object_id);
1582 }
1583 else
1584 echo "nothing";
1585 finishPortlet();
1586
1587 echo '</td></tr><tr><td colspan=2>';
1588
1589 // Bottom portlet with list
1590
1591 startPortlet ('Rackspace allocation history');
1592 echo "<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>\n";
1593 echo "<tr><th>timestamp</th><th>author</th><th>rack object ID</th><th>rack object type</th><th>rack object name</th><th>comment</th></tr>\n";
1594 foreach ($history as $row)
1595 {
1596 if ($row['mo_id'] == $op_id)
1597 $class = 'hl';
1598 else
1599 $class = "row_${order}";
1600 echo "<tr class=${class}><td><a href='${root}?page=${pageno}&tab=${tabno}&op_id=${row['mo_id']}'>${row['ctime']}</a></td>";
1601 echo "<td>${row['user_name']}</td>";
1602 echo "<td>${row['ro_id']}</td><td>${row['objtype_name']}</td><td>${row['name']}</td><td>${row['comment']}</td>\n";
1603 echo "</tr>\n";
1604 $order = $nextorder[$order];
1605 }
1606 echo "</table>\n";
1607 finishPortlet();
1608
1609 echo '</td></tr></table>';
1610
1611 }
1612
1613 function renderAddressspace ()
1614 {
1615 global $root;
1616 echo '<table border=0 class=objectview cellspacing=0 cellpadding=0><tr><td class=pcleft>';
1617
1618 startPortlet ('Subnets');
1619 echo "<table class='widetable' border=0 cellpadding=10 cellspacing=0 align='center'>\n";
1620 $addrspaceList = getAddressspaceList();
1621 echo "<tr><th>Subnet</th><th>Name</th><th>Total/used addresses</th></tr>";
1622 foreach ($addrspaceList as $iprange)
1623 {
1624 echo "<tr><td><a href='${root}?page=iprange&id=${iprange['id']}'>${iprange['ip']}/${iprange['mask']}</a></td><td>${iprange['name']}</td><td>";
1625 echo ($iprange['ip_bin'] | $iprange['mask_bin_inv']) - ($iprange['ip_bin'] & $iprange['mask_bin'])+1;
1626 $range = getIPRange($iprange['id']);
1627 echo "/";
1628 echo count($range['addrlist']);
1629 echo "</td></tr>";
1630 }
1631 echo "</table>\n";
1632 finishPortlet();
1633
1634 echo "</td>\n<td class=pcright>";
1635
1636 startPortlet ('SLB summary');
1637 finishPortlet ();
1638
1639 echo '</td></tr></table>';
1640 }
1641
1642 function renderAddNewRange ()
1643 {
1644 global $root, $pageno, $tabno;
1645 showMessageOrError();
1646
1647 echo "<center><h2>Add New</h2></center>\n";
1648 echo "<table class='widetable' border=0 cellpadding=10 align='center'>\n";
1649 echo "<tr><th>Address range</th><th>Name</th><th>C&gt;*</th><th>&nbsp;</th></tr>\n";
1650 echo "<form name='add_new_range' action='process.php'>\n";
1651 echo "<input type=hidden name=op value=addRange>\n";
1652 echo "<input type=hidden name=page value='${pageno}'>\n";
1653 echo "<input type=hidden name=tab value='${tabno}'>\n";
1654 echo "<tr><td class='tdcenter'><input type=text name='range' size=18 class='live-validate'></td>\n";
1655 echo "<td class='tdcenter'><input type=text name='name' size='20'></td>\n";
1656 echo "<td class='tdcenter'><input type=checkbox name='is_bcast' checked></td>\n";
1657 echo "<td class='tdcenter'><input type=submit value='Add a new range'></td></tr>\n";
1658 echo "</form></table><br><br>\n";
1659
1660 echo "<center><h2>Manage Existing</h2></center>\n";
1661 echo "<table class='widetable' border=0 cellpadding=10 align='center'>\n";
1662 $addrspaceList = getAddressspaceList();
1663 echo "<tr><th>&nbsp;</th><th>Address range</th><th>Name</th><th>Total/used addresses</th></tr>";
1664 foreach ($addrspaceList as $iprange)
1665 {
1666 $range = getIPRange($iprange['id']);
1667 $usedips = count ($range['addrlist']);
1668 echo "<tr>";
1669 if ($usedips == 0)
1670 {
1671 echo "<td><a href='process.php?op=delRange&page=${pageno}&tab=${tabno}&id=${iprange['id']}'>";
1672 printImageHREF ('delete', 'Delete this IP range');
1673 echo "</a></td>\n";
1674 }
1675 else
1676 echo "<td>&nbsp</td>";
1677 echo "<td><a href='${root}?page=iprange&id=${iprange['id']}'>${iprange['ip']}/${iprange['mask']}</a></td><td>${iprange['name']}</td><td>";
1678 echo ($iprange['ip_bin'] | $iprange['mask_bin_inv']) - ($iprange['ip_bin'] & $iprange['mask_bin'])+1;
1679 echo "/";
1680 echo $usedips;
1681 #echo "</td></tr></table>";
1682 echo "</td></tr>";
1683 }
1684 }
1685
1686 function renderIPRange ()
1687 {
1688 global $root;
1689 $maxperpage = getConfigVar ('IPV4_ADDRS_PER_PAGE');
1690 $id = $_REQUEST['id'];
1691 if (isset($_REQUEST['pg']))
1692 $page = $_REQUEST['pg'];
1693 else
1694 $page=0;
1695
1696 $range = getIPRange($id);
1697 echo "<center><h1>${range['ip']}/${range['mask']}</h1><h2>${range['name']}</h2></center>\n";
1698
1699 $startip = $range['ip_bin'] & $range['mask_bin'];
1700 $endip = $range['ip_bin'] | $range['mask_bin_inv'];
1701 $realstartip = $startip;
1702 $realendip = $endip;
1703 $numpages = 0;
1704 if($endip - $startip > $maxperpage)
1705 {
1706 $numpages = ($endip - $startip)/$maxperpage;
1707 $startip = $startip + $page * $maxperpage;
1708 $endip = $startip + $maxperpage-1;
1709 }
1710 echo "<center>";
1711 if ($numpages)
1712 echo '<h3>' . long2ip ($startip) . ' ~ ' . long2ip ($endip) . '</h3>';
1713 for ($i=0; $i<$numpages; $i++)
1714 {
1715 if ($i == $page)
1716 echo "<b>$i</b> ";
1717 else
1718 echo "<a href='${root}?page=iprange&id=$id&pg=$i'>$i</a> ";
1719 }
1720 echo "</center>";
1721
1722 echo "<table class='widetable' border=0 cellspacing=0 cellpadding=5 align='center'>\n";
1723 echo "<tr><th>Address</th><th>Name</th><th>Allocation</th></tr>\n";
1724
1725
1726 for($ip = $startip; $ip<=$endip; $ip++)
1727 {
1728 if (isset ($range['addrlist'][$ip]))
1729 {
1730 $numshared = countRefsOfType($range['addrlist'][$ip]['references'], 'shared', 'eq');
1731 $numreg = countRefsOfType($range['addrlist'][$ip]['references'], 'regular', 'eq');
1732 $numvirt = countRefsOfType($range['addrlist'][$ip]['references'], 'virtual', 'eq');
1733
1734 $addr = $range['addrlist'][$ip];
1735 if ( ($numshared > 0 && $numreg > 0) || $numreg > 1 )
1736 echo "<tr class='trwarning'>";
1737 elseif ( $addr['reserved'] == 'yes' and $numshared+$numreg+$numvirt > 0)
1738 echo "<tr class='trwarning'>";
1739 elseif ( $addr['reserved'] == 'yes')
1740 echo "<tr class='trbusy'>";
1741 elseif ( $numshared > 0 || $numreg > 0)
1742 echo "<tr class='trbusy'>";
1743 else
1744 echo "<tr>";
1745
1746 echo "<td><a href='${root}?page=ipaddress&ip=${addr['ip']}'>${addr['ip']}</a></td><td>${addr['name']}</td><td>";
1747 if ( $addr['reserved'] == 'yes')
1748 echo "<b>Reserved;</b> ";
1749 foreach ($range['addrlist'][$ip]['references'] as $ref)
1750 {
1751 echo "<a href='${root}?page=object&object_id=${ref['object_id']}'>";
1752 echo $ref['name'] . (empty ($ref['name']) ? '' : '@');
1753 echo "${ref['object_name']}</a>; ";
1754 }
1755 echo "</td></tr>\n";
1756 }
1757 else
1758 {
1759 echo "<tr><td><a href='${root}?page=ipaddress&ip=".long2ip($ip)."'>".long2ip($ip)."</a></td><td>&nbsp;</td><td>&nbsp;</td></tr>\n";
1760 }
1761 }
1762
1763 echo "</table>";
1764
1765 }
1766
1767 function renderIPRangeProperties ()
1768 {
1769 global $pageno, $tabno;
1770 $id = $_REQUEST['id'];
1771 showMessageOrError();
1772 $range = getIPRange($id);
1773 echo "<center><h1>${range['ip']}/${range['mask']}</h1></center>\n";
1774 echo "<table border=0 cellpadding=10 cellpadding=1 align='center'>\n";
1775 echo "<form action='process.php'><input type=hidden name=op value=editRange>";
1776 echo "<input type=hidden name=page value='${pageno}'>\n";
1777 echo "<input type=hidden name=tab value='${tabno}'>\n";
1778 echo "<input type=hidden name=id value='${id}'>";
1779 echo "<tr><td class='tdright'>Name:</td><td class='tdleft'><input type=text name=name size=20 value='${range['name']}'></tr><tr><td colspan=2 class='tdcenter'><input type=submit value='Update range'></td></form></tr>";
1780 echo "</table>\n";
1781
1782 }
1783
1784 function renderIPAddress ()
1785 {
1786 global $root;
1787 $ip = $_REQUEST['ip'];
1788 $address = getIPAddress($ip);
1789 echo "<center><h1>$ip</h1>";
1790 if ($address['exists'] == 1)
1791 echo "<h2>${address['name']}</h2>";
1792 echo "</center>\n";
1793
1794 // echo "<table width='100%' cesspadding=5 cellspacing=0 border=0 align='center'>";
1795 // echo "<tr valign='top'><td>";
1796
1797 startPortlet ('Address assignment');
1798 echo "<table class='widetable' cesspadding=5 cellspacing=0 border=0 align='center'>\n";
1799 echo "<tr><th>Object name</th><th>Interface name</th><th>Interface type</th></tr>\n";
1800
1801 $numshared = countRefsOfType($address['bonds'], 'shared', 'eq');
1802 $numreg = countRefsOfType($address['bonds'], 'regular', 'eq');
1803 $numvirt = countRefsOfType($address['bonds'], 'virtual', 'eq');
1804
1805
1806 if ( ($numshared > 0 && $numreg > 0) || $numreg > 1 )
1807 $class='trwarning';
1808 elseif ( $address['reserved'] == 'yes' and $numshared+$numreg+$numvirt > 0)
1809 $class='trwarning';
1810 else
1811 $class='';
1812
1813
1814
1815 if ($address['reserved'] == 'yes')
1816 echo "<tr class='$class'><td colspan='3'><b>RESERVED</b></td></tr>";
1817 foreach ($address['bonds'] as $bond)
1818 {
1819 echo "<tr class='$class'><td><a href='${root}?page=object&object_id=${bond['object_id']}'>${bond['object_name']}</td><td>${bond['name']}</td><td><b>";
1820 switch ($bond['type'])
1821 {
1822 case 'virtual':
1823 echo "Virtual";
1824 break;
1825 case 'shared':
1826 echo "Shared";
1827 break;
1828 case 'regular':
1829 echo "Regular";
1830 break;
1831 }
1832 echo "</b></td></tr>\n";
1833 }
1834 echo "</table><br><br>";
1835 finishPortlet();
1836
1837 // echo "</td><td>";
1838 // echo "</td></tr></table>";
1839 }
1840
1841 function renderIPAddressProperties ()
1842 {
1843 global $pageno, $tabno;
1844 $ip = $_REQUEST['ip'];
1845 showMessageOrError();
1846 $address = getIPAddress($ip);
1847 echo "<center><h1>$ip</h1></center>\n";
1848 echo "<table border=0 cellpadding=10 cellpadding=1 align='center'>\n";
1849 echo "<form action='process.php'><input type=hidden name=op value=editAddress>";
1850 echo "<input type=hidden name=page value='${pageno}'>\n";
1851 echo "<input type=hidden name=tab value='${tabno}'>\n";
1852 echo "<input type=hidden name=ip value='${ip}'>";
1853 echo "<tr><td class='tdright'>Name:</td><td class='tdleft'><input type=text name=name size=20 value='".($address['exists']==1?$address['name']:'')."'></tr>";
1854 echo "<td class='tdright'>Reserved:</td><td class='tdleft'><input type=checkbox name=reserved size=20 ".($address['exists']==1?(($address['reserved']=='yes')?'checked':''):'')."></tr>";
1855 echo "<tr><td colspan=2 class='tdcenter'><input type=submit value='Update address'></td></form></tr>";
1856 echo "</table>\n";
1857
1858 }
1859
1860 function renderIPAddressAssignment ()
1861 {
1862 global $pageno, $tabno, $root;
1863 $ip = $_REQUEST['ip'];
1864 $address = getIPAddress($ip);
1865
1866 showMessageOrError();
1867 echo "<center><h1>$ip</h1></center>\n";
1868
1869
1870 echo "<table class='widetable' cesspadding=5 cellspacing=0 border=0 align='center'>\n";
1871 echo "<tr><th>&nbsp;</th><th>Object name</th><th>Interface name</th><th>Interface type</th><th>&nbsp;</th></tr>\n";
1872
1873 $numshared = countRefsOfType($address['bonds'], 'shared', 'eq');
1874 $numreg = countRefsOfType($address['bonds'], 'regular', 'eq');
1875 $numvirt = countRefsOfType($address['bonds'], 'virtual', 'eq');
1876
1877
1878 if ( ($numshared > 0 && $numreg > 0) || $numreg > 1 )
1879 $class='trwarning';
1880 elseif ( $address['reserved'] == 'yes' and $numshared+$numreg+$numvirt > 0)
1881 $class='trwarning';
1882 else
1883 $class='';
1884
1885
1886
1887 if ($address['reserved'] == 'yes')
1888 echo "<tr class='$class'><td colspan='5'><b>RESERVED</b></td></tr>";
1889 foreach ($address['bonds'] as $bond)
1890 {
1891 echo "<tr class='$class'><form action='process.php'>";
1892 echo "<input type=hidden name=op value='editBondForAddress'>";
1893 echo "<input type=hidden name=page value='${pageno}'>";
1894 echo "<input type=hidden name=tab value='${tabno}'>";
1895 echo "<input type=hidden name=ip value='$ip'>";
1896 echo "<input type=hidden name=object_id value='${bond['object_id']}'>";
1897 echo "<td><a href='process.php?op=delIpAssignment&page=${pageno}&tab=${tabno}&ip=$ip&object_id=${bond['object_id']}'>";
1898 printImageHREF ('delete', 'Unallocate address');
1899 echo "</a></td>";
1900 echo "<td><a href='${root}?page=object&object_id=${bond['object_id']}'>${bond['object_name']}</td>";
1901 echo "<td><input type='text' name='bond_name' value='${bond['name']}' size=10></td>";
1902 echo "<td><select name='bond_type'>";
1903 switch ($bond['type'])
1904 {
1905 case 'virtual':
1906 echo "<option value='regular'>Regular</option>";
1907 echo "<option value='virtual' selected>Virtual</option>";
1908 echo "<option value='shared'>Shared</option>";
1909 break;
1910 case 'shared':
1911 echo "<option value='regular'>Regular</option>";
1912 echo "<option value='virtual'>Virtual</option>";
1913 echo "<option value='shared' selected>Shared</option>";
1914 break;
1915 case 'regular':
1916 echo "<option value='regular' selected>Regular</option>";
1917 echo "<option value='virtual'>Virtual</option>";
1918 echo "<option value='shared'>Shared</option>";
1919 break;
1920 }
1921 echo "</select></td><td><input type='submit' value='OK'></td></form></tr>\n";
1922 }
1923 echo "<form action='process.php'><input type='hidden' name='op' value='bindObjectToIp'>";
1924 echo "<input type=hidden name=page value='${pageno}'>\n";
1925 echo "<input type=hidden name=tab value='${tabno}'>\n";
1926 echo "<input type='hidden' name='ip' value='$ip'>";
1927 echo "<td colspan=2><select name='object_id'>";
1928
1929 foreach (array(1, 4, 7, 8, 12, 14) as $type)
1930 {
1931 //get all Balck Boxes, Servers, Routers, Switches, UPS, Modems
1932 $objects = getObjectList($type);
1933 foreach ($objects as $object)
1934 echo "<option value='${object['id']}'>${object['dname']}</option>";
1935 }
1936
1937 echo "</select></td><td><input type='text' name='bond_name' value='' size=10></td>";
1938 echo "<td><select name='bond_type'><option value='regular'>Regular</option><option value='virtual'>Virtual</option><option value='shared'>Shared</option></select></td>";
1939 echo "<td><input type='submit' value='Assign address'></td></form></tr>";
1940 echo "</table><br><br>";
1941
1942 }
1943
1944 function renderIPAddressPortForwarding ($object_id=0)
1945 {
1946 global $pageno, $tabno, $root;
1947
1948 $info = getObjectInfo ($object_id);
1949 $forwards = getObjectForwards ($object_id);
1950 $addresses = getObjectAddresses ($object_id);
1951 showMessageOrError();
1952 echo "<center><h2>locally performed NAT</h2></center>";
1953
1954 echo "<table class='widetable' cesspadding=5 cellspacing=0 border=0 align='center'>\n";
1955 echo "<tr><th></th><th>Match endpoint</th><th>Translate to</th><th>Target object</th><th>Comment</th></tr>\n";
1956
1957 foreach ($forwards['out'] as $pf)
1958 {
1959 $class='trwarning';
1960 $name='';
1961 foreach ($addresses as $addr)
1962 if ($addr['ip'] == $pf['localip'])
1963 {
1964 $class='';
1965 $name = $addr['name'];
1966 break;
1967 }
1968
1969 echo "<tr class='$class'>";
1970 echo "<td><a href='process.php?op=delPortForwarding&localip=${pf['localip']}&localport=${pf['localport']}&remoteip=${pf['remoteip']}&remoteport=${pf['remoteport']}&proto=${pf['proto_bin']}&object_id=$object_id&page=${pageno}&tab=${tabno}'><img src='${root}/pix/delete_s.gif' title='Delete port forwarding' border=0 width=16 height=16></a></td>";
1971 echo "<td>${pf['proto']}/${name}: <a href='${root}?page=ipaddress&tab=default&ip=${pf['localip']}'>${pf['localip']}</a>:${pf['localport']}";
1972 if (!empty ($pf['local_addr_name']))
1973 echo ' (' . $pf['local_addr_name'] . ')';
1974 echo "</td>";
1975 echo "<td><a href='${root}?page=ipaddress&tab=default&ip=${pf['remoteip']}'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
1976
1977 $address=getIPAddress($pf['remoteip']);
1978
1979 echo "<td class='description'>";
1980 if (count ($address['bonds']))
1981 foreach($address['bonds'] as $bond)
1982 echo "<a href='${root}?page=object&tab=default&object_id=${bond['object_id']}'>${bond['object_name']}(${bond['name']})</a> ";
1983 elseif (!empty ($pf['remote_addr_name']))
1984 echo '(' . $pf['remote_addr_name'] . ')';
1985 echo "</td><form action='process.php'><input type='hidden' name='op' value='updPortForwarding'><input type=hidden name=page value='${pageno}'><input type=hidden name=tab value='${tabno}'><input type='hidden' name='object_id' value='$object_id'><input type='hidden' name='localip' value='${pf['localip']}'><input type='hidden' name='localport' value='${pf['localport']}'><input type='hidden' name='remoteip' value='${pf['remoteip']}'><input type='hidden' name='remoteport' value='${pf['remoteport']}'><input type='hidden' name='proto' value='${pf['proto_bin']}'><td class='description'><input type='text' name='description' value='${pf['description']}'> <input type='submit' value='OK'></td></form>";
1986 echo "</tr>";
1987 }
1988 echo "<form action='process.php'><input type='hidden' name='op' value='forwardPorts'>";
1989 echo "<input type='hidden' name='object_id' value='$object_id'>";
1990 echo "<input type=hidden name=page value='${pageno}'>\n";
1991 echo "<input type=hidden name=tab value='${tabno}'>\n";
1992 echo "<tr align='center'><td colspan=2>";
1993 printSelect (readChapter ('Protocols'), 'proto');
1994 echo "<select name='localip'>";
1995
1996 foreach ($addresses as $addr)
1997 echo "<option value='${addr['ip']}'>" . (empty ($addr['name']) ? '' : "${addr['name']}: ") .
1998 "${addr['ip']}" . (empty ($addr['address_name']) ? '' : " (${addr['address_name']})") . "</option>";
1999
2000 echo "</select>:<input type='text' name='localport' size='4'></td><td><input type='text' name='remoteip' id='remoteip' size='10'>";
2001 echo "<a href='javascript:;' onclick='window.open(\"${root}/find_object_ip_helper.php\", \"findobjectip\", \"height=700, width=400, location=no, menubar=no, resizable=yes, scrollbars=no, status=no, titlebar=no, toolbar=no\");'><img src='${root}/pix/find.png' title='Find object' border=0 height=16 width=16></a>";
2002 echo ":<input type='text' name='remoteport' size='4'></td><td></td><td colspan=1><input type='text' name='description' size='20'> <input type='submit' value='Create Forwarding'></td></tr>";
2003 echo "</form>";
2004
2005 echo "</table><br><br>";
2006
2007
2008 echo "<center><h2>arriving NAT connections</h2></center>";
2009 echo "<table class='widetable' cesspadding=5 cellspacing=0 border=0 align='center'>\n";
2010 echo "<tr><th></th><th>Source</th><th>Source objects</th><th>Target</th><th>Description</th></tr>\n";
2011
2012 foreach ($forwards['in'] as $pf)
2013 {
2014 echo "<tr>";
2015
2016 echo "<td><a href='process.php?op=delPortForwarding&localip=${pf['localip']}&localport=${pf['localport']}&remoteip=${pf['remoteip']}&remoteport=${pf['remoteport']}&proto=${pf['proto_bin']}&object_id=${pf['object_id']}&page=${pageno}&tab=${tabno}'><img src='${root}/pix/delete_s.gif' title='Delete port forwarding' border=0 width=16 height=16></a></td>";
2017 echo "<td>${pf['proto']}/<a href='${root}?page=ipaddress&tab=default&ip=${pf['localip']}'>${pf['localip']}</a>:${pf['localport']}</td>";
2018 echo "<td class='description'><a href='${root}?page=object&tab=default&object_id=${pf['object_id']}'>${pf['object_name']}</a>";
2019 echo "</td><td><a href='${root}?page=ipaddress&tab=default&ip=${pf['remoteip']}'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
2020 echo "<td class='description'>${pf['description']}</td></tr>";
2021 }
2022
2023 // echo "<form action='process.php'><input type='hidden' name='op' value='forwardPorts'>";
2024 // echo "<input type='hidden' name='object_id' value='$object_id'>";
2025 // echo "<input type=hidden name=page value='${pageno}'>\n";
2026 // echo "<input type=hidden name=tab value='${tabno}'>\n";
2027 // echo "<tr align='center'><td colspan=2><select name='proto'><option value='1'>TCP</option><option value='2'>UDP</option><input type='text' name='localip' size='10'>:<input type='text' name='localport' size='4'></td><td><select name='localip'>";
2028 // foreach ($addresses as $addr)
2029 // echo "<option value='${addr['ip']}'>${addr['ip']}</option>";
2030 //
2031 // echo "</select>:<input type='text' name='remoteport' size='4'></td><td><input type='text' name='description' size='20'></td><td><input type='submit' value='Create Forwarding'></td></tr>";
2032 // echo "</form>";
2033 echo "</table><br><br>";
2034
2035
2036 }
2037
2038
2039 function renderAddMultipleObjectsForm ()
2040 {
2041 global $pageno, $tabno, $nextorder;
2042
2043 $type_id = array();
2044 $global_type_id = 0;
2045 $name = array();
2046 $asset_no = array();
2047 $keepvalues = FALSE;
2048 $log = array();
2049 // Look for current submit.
2050 if (isset ($_REQUEST['got_fast_data']))
2051 {
2052 $keepvalues = TRUE;
2053 $max = getConfigVar ('MASSCOUNT');
2054 for ($i = 0; $i < $max; $i++)
2055 {
2056 if (!isset ($_REQUEST["${i}_object_type_id"]))
2057 {
2058 $log[] = array ('code' => 'error', 'message' => "Submitted form is invalid at line " . $i + 1);
2059 break;
2060 }
2061 assertUIntArg ("${i}_object_type_id", TRUE);
2062 assertStringArg ("${i}_object_name", TRUE);
2063 assertStringArg ("${i}_object_label", TRUE);
2064 assertStringArg ("${i}_object_asset_no", TRUE);
2065 assertStringArg ("${i}_object_barcode", TRUE);
2066 $type_id[$i] = $_REQUEST["${i}_object_type_id"];
2067 // Save user input for possible rendering.
2068 $name[$i] = $_REQUEST["${i}_object_name"];
2069 $label[$i] = $_REQUEST["${i}_object_label"];
2070 $asset_no[$i] = $_REQUEST["${i}_object_asset_no"];
2071 $barcode[$i] = $_REQUEST["${i}_object_barcode"];
2072
2073 // It's better to skip silently than printing a notice.
2074 if ($type_id[$i] == 0)
2075 continue;
2076 if (commitAddObject ($name[$i], $label[$i], $barcode[$i], $type_id[$i], $asset_no[$i]) === TRUE)
2077 $log[] = array ('code' => 'success', 'message' => "Added new object '${name[$i]}'");
2078 else
2079 $log[] = array ('code' => 'error', 'message' => 'commitAddObject() failed in renderAddMultipleObjectsForm()');
2080 }
2081 }
2082 elseif (isset ($_REQUEST['got_very_fast_data']))
2083 {
2084 $keepvalues = TRUE;
2085 assertUIntArg ('global_type_id', TRUE);
2086 assertStringArg ('namelist', TRUE);
2087 $global_type_id = $_REQUEST['global_type_id'];
2088 if ($global_type_id == 0)
2089 {
2090 if (!empty ($_REQUEST['namelist']))
2091 $log[] = array ('code' => 'error', 'message' => 'Object type is not selected, check the form below');
2092 else
2093 $log[] = array ('code' => 'error', 'message' => 'Empty form has been ignored. Cheers.');
2094 }
2095 else
2096 {
2097 // The name extractor below was stolen from ophandlers.php:addMultiPorts()
2098 $names1 = explode ('\n', $_REQUEST['namelist']);
2099 $names2 = array();
2100 foreach ($names1 as $line)
2101 {
2102 $parts = explode ('\r', $line);
2103 reset ($parts);
2104 if (empty ($parts[0]))
2105 continue;
2106 else
2107 $names2[] = rtrim ($parts[0]);
2108 }
2109 foreach ($names2 as $cname)
2110 if (commitAddObject ($cname, '', '', $global_type_id, '') === TRUE)
2111 $log[] = array ('code' => 'success', 'message' => "Added new object '${cname}'");
2112 else
2113 $log[] = array ('code' => 'error', 'message' => "Could not add '${cname}'");
2114 }
2115 }
2116 printLog ($log);
2117
2118 // Render a form for the next.
2119 $typelist = getObjectTypeList();
2120 $typelist[0] = 'select type...';
2121
2122 startPortlet ('Fast way');
2123 echo '<form>';
2124 echo "<input type=hidden name=page value=${pageno}>";
2125 echo "<input type=hidden name=tab value=${tabno}>";
2126 echo '<table border=0 align=center>';
2127 echo "<tr><th>Object type</th><th>Common name</th><th>Visible label</th><th>Asset tag</th><th>Barcode</th></tr>\n";
2128 // If a user forgot to select object type on input, we keep his
2129 // previous input in the form.
2130 $max = getConfigVar ('MASSCOUNT');
2131 for ($i = 0; $i < $max; $i++)
2132 {
2133 echo '<tr><td>';
2134 printSelect ($typelist, "${i}_object_type_id", 0);
2135 echo '</td>';
2136 echo "<td><input type=text size=30 name=${i}_object_name";
2137 if ($keepvalues and $type_id[$i] == 0)
2138 echo " value='${name[$i]}'";
2139 echo "></td>";
2140 echo "<td><input type=text size=30 name=${i}_object_label";
2141 if ($keepvalues and $type_id[$i] == 0)
2142 echo " value='${label[$i]}'";
2143 echo "></td>";
2144 echo "<td><input type=text size=20 name=${i}_object_asset_no";
2145 if ($keepvalues and $type_id[$i] == 0)
2146 echo " value='${asset_no[$i]}'";
2147 echo "></td>";
2148 echo "<td><input type=text size=10 name=${i}_object_barcode";
2149 if ($keepvalues and $type_id[$i] == 0)
2150 echo " value='${barcode[$i]}'";
2151 echo "></td>";
2152 echo "</tr>\n";
2153 }
2154 echo "<tr><td class=submit colspan=5><input type=submit name=got_fast_data value='Create'></td></tr>\n";
2155 echo "</form></table>\n";
2156 finishPortlet();
2157
2158 startPortlet ('Very fast way');
2159 echo '<form>';
2160 echo "<input type=hidden name=page value=${pageno}>";
2161 echo "<input type=hidden name=tab value=${tabno}>";
2162 echo 'For each line shown below create an object of type ';
2163 printSelect ($typelist, "global_type_id", 0);
2164 echo " <input type=submit name=got_very_fast_data value='Go!'><br>\n";
2165 echo "<textarea name=namelist cols=40 rows=25>\n";
2166 if ($keepvalues and $global_type_id == 0)
2167 echo $_REQUEST['namelist'];
2168 echo "</textarea></form>\n";
2169 finishPortlet();
2170 }
2171
2172 function printGreeting ()
2173 {
2174 global $remote_username, $accounts, $root;
2175 $account = $accounts[$remote_username];
2176 echo "Hello, ${account['user_realname']}. This is RackTables " . CODE_VERSION . ". Click <a href='${root}?logout'>here</a> to logout.";
2177 }
2178
2179 function renderSearchResults ()
2180 {
2181 global $remote_username, $root;
2182 $terms = trim ($_REQUEST['q']);
2183 if (empty ($terms))
2184 {
2185 showError ('Search string cannot be empty.');
2186 return;
2187 }
2188 if (!authorized ($remote_username, 'object', 'default'))
2189 {
2190 showError ('You are not authorized for viewing information about objects.');
2191 return;
2192 }
2193 // If we search for L2 address, we can either find one or find none.
2194 if
2195 (
2196 preg_match ('/^[0-9a-f][0-9a-f]?:[0-9a-f][0-9a-f]?:[0-9a-f][0-9a-f]?:[0-9a-f][0-9a-f]?:[0-9a-f][0-9a-f]?:[0-9a-f][0-9a-f]?$/i', $terms) or
2197 preg_match ('/^[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]$/i', $terms) or
2198 preg_match ('/^[0-9a-f][0-9a-f][0-9a-f][0-9a-f].[0-9a-f][0-9a-f][0-9a-f][0-9a-f].[0-9a-f][0-9a-f][0-9a-f][0-9a-f]$/i', $terms)
2199 )
2200 // Search for L2 address.
2201 {
2202 $result = searchByl2address ($terms);
2203 if ($result !== NULL)
2204 {
2205 echo "<script language='Javascript'>document.location='${root}?page=object";
2206 echo "&hl_port_id=${result['port_id']}";
2207 echo "&object_id=${result['object_id']}';//</script>";
2208 }
2209 else
2210 echo "L2 address '${terms}' not found!";
2211 }
2212 elseif (preg_match ('/^[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]$/i', $terms))
2213 // STP bridge ID: bridge priotity + port MAC address. Cut off first 4 chars and look for MAC address.
2214 {
2215 $terms = substr ($terms, 4);
2216 $result = searchByl2address ($terms);
2217 if ($result !== NULL)
2218 {
2219 echo "<script language='Javascript'>document.location='${root}?page=object";
2220 echo "&hl_port_id=${result['port_id']}";
2221 echo "&object_id=${result['object_id']}';//</script>";
2222 }
2223 else
2224 echo "L2 address '${terms}' not found!";
2225 }
2226 elseif (preg_match ('/^[0-9][0-9]?[0-9]?\.[0-9]?[0-9]?[0-9]?\.[0-9][0-9]?[0-9]?\.[0-9]?[0-9]?[0-9]?$/i', $terms))
2227 // Search for IP address.
2228 {
2229 $result = getRangeByIp ($terms);
2230 if ($result !== NULL)
2231 {
2232 echo "<script language='Javascript'>document.location='${root}?page=ipaddress";
2233 echo "&ip=${terms}";
2234 echo "';//</script>";
2235 }
2236 else
2237 echo "IP address '${terms}' not found!";
2238 return;
2239 }
2240 else
2241 // Search for objects.
2242 {
2243 $objects = getSearchResults ($terms);
2244 if (count ($objects) == 1)
2245 {
2246 $obj = current ($objects);
2247 echo "<script language='Javascript'>document.location='${root}?page=object&object_id=${obj['id']}';//</script>";
2248 }
2249 elseif (count ($objects) > 1)
2250 {
2251 echo '<br><br><table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
2252 echo '<tr><th>Common name</th><th>Visible label</th><th>Asset tag</th><th>barcode</th></tr>';
2253 $order = 'odd';
2254 global $nextorder;
2255 foreach ($objects as $obj)
2256 {
2257 echo "<tr class=row_${order}><td><a href=\"${root}?page=object&object_id=${obj['id']}\">${obj['dname']}</a></td>";
2258 echo "<td>${obj['label']}</td>";
2259 echo "<td>${obj['asset_no']}</td>";
2260 echo "<td>${obj['barcode']}</td></tr>";
2261 $order = $nextorder[$order];
2262 }
2263 echo '</table>';
2264 }
2265 else
2266 echo "Object '${terms}' not found!";
2267 }
2268 }
2269
2270 // This function prints a table of checkboxes to aid the user in toggling mount atoms
2271 // from one state to another. The first argument is rack data as
2272 // produced by getRackData(), the second is the value used for the 'unckecked' state
2273 // and the third is the value used for 'checked' state.
2274 // Usage contexts:
2275 // for mounting an object: printAtomGrid ($data, 'F', 'T')
2276 // for changing rack design: printAtomGrid ($data, 'A', 'F')
2277 // for adding rack problem: printAtomGrid ($data, 'F', 'U')
2278 // for adding object problem: printAtomGrid ($data, 'T', 'W')
2279
2280 function renderAtomGrid ($data)
2281 {
2282 $rack_id = $data['id'];
2283 for ($unit_no = $data['height']; $unit_no > 0; $unit_no--)
2284 {
2285 echo "<tr><th>${unit_no}</th>";
2286 for ($locidx = 0; $locidx < 3; $locidx++)
2287 {
2288 $state = $data[$unit_no][$locidx]['state'];
2289 echo "<td class=state_${state}";
2290 if (isset ($data[$unit_no][$locidx]['hl']))
2291 echo $data[$unit_no][$locidx]['hl'];
2292 echo ">";
2293 if (!($data[$unit_no][$locidx]['enabled'] === TRUE))
2294 echo '<input type=checkbox disabled>';
2295 else
2296 echo "<input type=checkbox" . $data[$unit_no][$locidx]['checked'] . " name=atom_${rack_id}_${unit_no}_${locidx}>";
2297 echo '</td>';
2298 }
2299 echo "</tr>\n";
2300 }
2301 }
2302
2303 function renderPermissions ()
2304 {
2305 startPortlet ('User permissions');
2306 echo "<table class=cooltable border=0 cellpadding=5 cellspacing=0 align=center>\n";
2307 echo "<tr><th>Username</th><th>Page</th><th>Tab</th><th>Access</th></tr>";
2308 global $perms, $nextorder;
2309 $order = 'odd';
2310 foreach ($perms as $username => $pages)
2311 foreach ($pages as $page => $tabs)
2312 foreach ($tabs as $tab => $access)
2313 {
2314 echo "<tr class=row_${order}><td class=tdleft>$username</td><td>$page</td><td>$tab</td><td>$access</td></tr>\n";
2315 $order = $nextorder[$order];
2316 }
2317 echo "</table>\n";
2318 finishPortlet();
2319 }
2320
2321 function renderAccounts ()
2322 {
2323 global $nextorder, $accounts;
2324 startPortlet ('User accounts');
2325 echo "<table class=cooltable border=0 cellpadding=5 cellspacing=0 align=center>\n";
2326 echo "<tr><th class=tdleft>Username</th><th class=tdleft>Real name</th></tr>";
2327 $order = 'odd';
2328 foreach ($accounts as $user)
2329 {
2330 echo "<tr class=row_${order}><td class=tdleft>${user['user_name']}</td><td class=tdleft>${user['user_realname']}</td></li>";
2331 $order = $nextorder[$order];
2332 }
2333 echo '</table>';
2334 finishPortlet();
2335 }
2336
2337 function renderAccountsEditForm ()
2338 {
2339 global $root, $pageno, $tabno, $accounts;
2340 startPortlet ('User accounts');
2341 showMessageOrError();
2342 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable>\n";
2343 echo "<tr><th>op</th><th>Username</th><th>Real name</th><th>Password</th><th>&nbsp;</th></tr>\n";
2344 foreach ($accounts as $account)
2345 {
2346 echo "<form action='${root}process.php'>";
2347 echo "<input type=hidden name=op value=updateAccount>";
2348 echo "<input type=hidden name=page value='${pageno}'>\n";
2349 echo "<input type=hidden name=tab value='${tabno}'>\n";
2350 echo "<input type=hidden name=id value='${account['user_id']}'><tr>";
2351 echo "<td>";
2352 if ($account['user_enabled'] == 'yes' && $account['user_id'] != 1)
2353 {
2354 echo "<a href='${root}process.php?op=disableAccount&page=${pageno}&tab=${tabno}&id=${account['user_id']}'>";
2355 printImageHREF ('blockuser', 'disable account');
2356 echo "</a>\n";
2357 }
2358 if ($account['user_enabled'] == 'no' && $account['user_id'] != 1)
2359 {
2360 echo "<a href='${root}process.php?op=enableAccount&page=${pageno}&tab=${tabno}&id=${account['user_id']}'>";
2361 printImageHREF ('unblockuser', 'enable account');
2362 echo "</a>\n";
2363 }
2364 // Otherwise skip icon.
2365 echo "</td>";
2366 echo "<td><input type=text name=username value='${account['user_name']}' size=16></td>";
2367 echo "<td><input type=text name=realname value='${account['user_realname']}' size=24></td>";
2368 echo "<td><input type=password name=password value='${account['user_password_hash']}' size=64></td>";
2369 echo "<td><input type='submit' value='OK'></td>";
2370 echo "</form></tr>\n";
2371 }
2372 echo "<form action='${root}process.php' method=post><tr>";
2373 echo "<input type=hidden name=op value=createAccount>\n";
2374 echo "<input type=hidden name=page value='${pageno}'>\n";
2375 echo "<input type=hidden name=tab value='${tabno}'>\n";
2376 echo "<td colspan=2><input type=text size=16 name=username tabindex=100></td>\n";
2377 echo "<td><input type=text size=24 name=realname tabindex=101></td>";
2378 echo "<td><input type=password size=64 name=password tabindex=102></td>";
2379 echo "<td colspan=4><input type=submit value='Create account' tabindex=103></td></tr></form>";
2380 echo "</table><br>\n";
2381 finishPortlet();
2382 }
2383
2384 function printChildrenAsOptions ($root, $depth = 0)
2385 {
2386 echo "<option value=${root['title']}>";
2387 if ($depth == 0)
2388 echo '* ';
2389 for ($i = 0; $i < $depth; $i++)
2390 echo '-- ';
2391 echo $root['title'];
2392 echo "</option>\n";
2393 foreach ($root['kids'] as $kid)
2394 printChildrenAsOptions ($kid, $depth + 1);
2395 }
2396
2397 // 1. Find all parentless pages.
2398 // 2. For each of them recursively find all children.
2399 // 3. Output the tree with recursion tree display.
2400 function printPagesTree ()
2401 {
2402 global $page;
2403 echo '<pre>';
2404 foreach ($page as $ctitle => $cpage)
2405 if (!isset ($cpage['parent']))
2406 {
2407 $croot['title'] = $ctitle;
2408 $croot['kids'] = getAllChildPages ($ctitle);
2409 printChildrenAsOptions ($croot);
2410 }
2411 echo '</pre>';
2412 }
2413
2414 function renderPermissionsEditForm ()
2415 {
2416 global $root, $pageno, $tabno, $perms, $accounts;
2417 startPortlet ('User permissions');
2418 showMessageOrError();
2419 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
2420 echo "<tr><th>&nbsp;</th><th>Username</th><th>Page</th><th>Tab</th><th>Access</th></tr>\n";
2421 foreach ($perms as $username => $pages)
2422 foreach ($pages as $access_page => $tabs)
2423 foreach ($tabs as $access_tab => $access)
2424 {
2425 echo "<td>";
2426 if ($username != '%')
2427 $userid = $accounts[$username]['user_id'];
2428 else
2429 $userid = 0;
2430 echo "<a href='${root}process.php?op=revoke&page=${pageno}&tab=${tabno}&access_userid=${userid}&access_page=${access_page}&access_tab=${access_tab}'>";
2431 printImageHREF ('revoke', 'Revoke permission');
2432 echo "</a></td>";
2433 echo "<td>${username}</td>";
2434 echo "<td>${access_page}</td>";
2435 echo "<td>${access_tab}</td>";
2436 echo "<td>${access}</td>";
2437 echo "</tr>\n";
2438 }
2439 echo "<form action='${root}process.php' method=post><tr>";
2440 echo "<input type=hidden name=op value=grant>\n";
2441 echo "<input type=hidden name=page value='${pageno}'>\n";
2442 echo "<input type=hidden name=tab value='${tabno}'>\n";
2443 // FIXME: border=0 doesn't work here for unknown reason
2444 echo "<td>";
2445 printImageHREF ('grant', '', TRUE, 103);
2446 echo "</td>";
2447 echo "<td><select name=access_userid>";
2448 echo "<option value=0>ANY</option>";
2449 foreach ($accounts as $account)
2450 echo "<option value=${account['user_id']}>${account['user_name']}</option>";
2451 echo "</select></td>\n";
2452 echo "<td><select name=access_page>";
2453 echo "<option value='%'>ANY</option>";
2454 printPagesTree();
2455 echo "</select></td>";
2456 echo "<td><input type=text size=16 name=access_tab tabindex=102 value=default></td>";
2457 echo "<td><input type=radio name=access_value value=no checked>no <input type=radio name=access_value value=yes>yes</td>";
2458 echo "</tr></form>";
2459 echo "</table><br>\n";
2460 finishPortlet();
2461 }
2462
2463 function renderPortMap ($editable = FALSE)
2464 {
2465 global $nextorder, $root, $pageno, $tabno;
2466 showMessageOrError();
2467 startPortlet ("Port compatibility map");
2468 $ptlist = getPortTypes();
2469 $pclist = getPortCompat();
2470 $pctable = buildPortCompatMatrixFromList ($ptlist, $pclist);
2471 if ($editable)
2472 {
2473 echo "<form method=post action='${root}process.php'>";
2474 echo "<input type=hidden name=page value='${pageno}'>";
2475 echo "<input type=hidden name=tab value='${tabno}'>";
2476 echo "<input type=hidden name=op value=save>";
2477 }
2478 echo "<table class=cooltable border=0 cellpadding=5 cellspacing=0 align=center>\n";
2479 echo "<tr><th class=vert_th>&nbsp;</th>";
2480 foreach ($ptlist as $name2)
2481 echo "<th>to ${name2}</th>";
2482 echo "</tr>";
2483 // Make a copy to have an independent array pointer.
2484 $ptlistY = $ptlist;
2485 $order = 'odd';
2486 foreach ($ptlistY as $type1 => $name1)
2487 {
2488 echo "<tr class=row_${order}><th class=vert_th style='border-bottom: 0px;'>from $name1</th>";
2489 foreach ($ptlist as $type2 => $name2)
2490 {
2491 echo '<td><input type=checkbox' . ($editable ? " name=atom_${type1}_${type2}" : ' disabled');
2492 echo ($pctable[$type1][$type2] ? ' checked' : '') . '></td>';
2493 }
2494 echo "</tr>\n";
2495 $order = $nextorder[$order];
2496 }
2497 echo '</table><br>';
2498 if ($editable)
2499 {
2500 echo "<input type=submit value='Save changes'>";
2501 echo "</form>";
2502 }
2503 finishPortlet();
2504 }
2505
2506 function renderConfigMainpage ()
2507 {
2508 global $pageno, $root;
2509 $children = getDirectChildPages ($pageno);
2510 echo '<ul>';
2511 foreach ($children as $cpageno => $child)
2512 {
2513 $ctitle = $child['title']($cpageno);
2514 echo "<li><a href='${root}?page=${cpageno}'>" . $ctitle['name'] . "</li>\n";
2515 }
2516 echo '';
2517 echo '</ul>';
2518 }
2519
2520 function renderRackPage ($rack_id)
2521 {
2522 if ($rack_id == 0)
2523 {
2524 showError ('Invalid rack_id in renderRackPage()');
2525 return;
2526 }
2527 if (($rackData = getRackData ($rack_id)) == NULL)
2528 {
2529 showError ('getRackData() failed in renderRackPage()');
2530 return;
2531 }
2532 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0><tr>";
2533
2534 // Left column with information.
2535 echo "<td class=pcleft>";
2536 startPortlet ('Rack information');
2537 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
2538 echo "<tr><th width='50%' class=tdright>Rack row:</th><td class=tdleft>${rackData['row_name']}</td></tr>\n";
2539 echo "<tr><th width='50%' class=tdright>Name:</th><td class=tdleft>${rackData['name']}</td></tr>\n";
2540 echo "<tr><th width='50%' class=tdright>Height:</th><td class=tdleft>${rackData['height']}</td></tr>\n";
2541 if (!empty ($rackData['comment']))
2542 echo "<tr><th width='50%' class=tdright>Comment:</th><td class=tdleft>${rackData['comment']}</td></tr>\n";
2543 echo '</table>';
2544 finishPortlet();
2545 echo '</td>';
2546
2547 // Right column with rendered rack.
2548 echo '<td>';
2549 startPortlet ('Rack diagram');
2550 renderRack ($rack_id);
2551 finishPortlet();
2552 echo '</td>';
2553
2554 echo '</tr></table>';
2555 }
2556
2557 function renderDictionary ()
2558 {
2559 global $nextorder;
2560 $dict = getDict();
2561 echo "<table border=0><tr>";
2562 foreach ($dict as $chapter)
2563 {
2564 echo "<td class=pcleft>";
2565 startPortlet ($chapter['name'] . ' (' . count ($chapter['word']) . ')');
2566 echo "<table class=cooltable border=0 cellpadding=5 cellspacing=0 align=center>\n";
2567 $order = 'odd';
2568 foreach ($chapter['word'] as $key => $value)
2569 {
2570 echo "<tr class=row_${order}><td class=tdleft><div title='key=${key}'>${value}</div></td></tr>";
2571 $order = $nextorder[$order];
2572 }
2573 echo "</table>";
2574 finishPortlet();
2575 echo "</td>";
2576 }
2577 echo "</tr></table>";
2578 }
2579
2580 function renderDictionaryEditor ()
2581 {
2582 global $root, $pageno, $tabno;
2583 showMessageOrError();
2584 $dict = getDict();
2585 echo "<table border=0><tr>";
2586 foreach ($dict as $chapter)
2587 {
2588 echo "<td class=pcleft>";
2589 startPortlet ($chapter['name'] . ' (' . count ($chapter['word']) . ')');
2590 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable>\n";
2591 foreach ($chapter['word'] as $key => $value)
2592 {
2593 echo "<form action='${root}process.php' method=post>";
2594 echo "<input type=hidden name=page value='${pageno}'>";
2595 echo "<input type=hidden name=tab value='${tabno}'>";
2596 echo "<input type=hidden name=op value='upd'>";
2597 echo "<input type=hidden name=chapter_no value='${chapter['no']}'>";
2598 echo "<input type=hidden name=dict_key value='${key}'>";
2599 echo '<tr>';
2600 echo "<td><a href='${root}process.php?page=${pageno}&tab=${tabno}&op=del&chapter_no=${chapter['no']}&dict_key=${key}'>";
2601 printImageHREF ('delete', 'Delete word');
2602 echo "</a></td>";
2603 echo "<td class=tdright><input type=text name=dict_value size=32 value='${value}'></td>";
2604 echo "<td><input type=submit value=OK></td>";
2605 echo '</tr></form>';
2606 }
2607 echo "<form action='${root}process.php' method=post>";
2608 echo "<input type=hidden name=page value='${pageno}'>";
2609 echo "<input type=hidden name=tab value='${tabno}'>";
2610 echo "<input type=hidden name=op value=add>";
2611 echo "<input type=hidden name=chapter_no value='${chapter['no']}'>";
2612 echo '<tr>';
2613 echo "<td>&nbsp;</td>";
2614 echo "<td class=tdright><input type=text name=dict_value size=32></td>";
2615 echo "<td><input type=submit value=OK></td>";
2616 echo '</tr></form>';
2617 echo "</table>";
2618 finishPortlet();
2619 echo "</td>";
2620 }
2621 echo "</tr></table>";
2622 }
2623
2624 // We don't allow to rename/delete a sticky chapter and we don't allow
2625 // to delete a non-empty chapter.
2626 function renderChaptersEditor ()
2627 {
2628 global $root, $pageno, $tabno;
2629 showMessageOrError();
2630 $dict = getDict();
2631 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable>\n";
2632 echo '<tr><th>&nbsp;</th><th>Chapter name</th><th>Words</th><th>&nbsp;</th></tr>';
2633 foreach ($dict as $chapter)
2634 {
2635 $wordcount = count ($chapter['word']);
2636 $sticky = $chapter['sticky'];
2637 echo "<form action='${root}process.php' method=post>";
2638 echo "<input type=hidden name=page value='${pageno}'>";
2639 echo "<input type=hidden name=tab value='${tabno}'>";
2640 echo "<input type=hidden name=op value=upd>";
2641 echo "<input type=hidden name=chapter_no value='${chapter['no']}'>";
2642 echo '<tr>';
2643 echo '<td>';
2644 if ($sticky or $wordcount > 0)
2645 echo '&nbsp;';
2646 else
2647 {
2648 echo "<a href='${root}process.php?page=${pageno}&tab=${tabno}&op=del&chapter_no=${chapter['no']}'>";
2649 printImageHREF ('delete', 'Remove chapter');
2650 echo "</a>";
2651 }
2652 echo '</td>';
2653 echo "<td><input type=text name=chapter_name value='${chapter['name']}'" . ($sticky ? ' disabled' : '') . "></td>";
2654 echo "<td class=tdleft>${wordcount}</td><td>";
2655 if ($sticky)
2656 echo '&nbsp;';
2657 else
2658 echo "<input type=submit value='OK'>";
2659 echo '</td></tr>';
2660 echo '</form>';
2661 }
2662 echo "<form action='${root}process.php' method=post>";
2663 echo "<input type=hidden name=page value='${pageno}'>";
2664 echo "<input type=hidden name=tab value='${tabno}'>";
2665 echo "<input type=hidden name=op value=add>";
2666 echo '<tr><td>';
2667 printImageHREF ('add', '', TRUE);
2668 echo "</td><td colspan=3><input type=text name=chapter_name></td>";
2669 echo '</tr>';
2670 echo '</form>';
2671 echo "</table>\n";
2672 }
2673
2674 function renderAttributes ()
2675 {
2676 global $nextorder;
2677 $attrMap = getAttrMap();
2678 startPortlet ('Optional attributes');
2679 echo "<table class=cooltable border=0 cellpadding=5 cellspacing=0 align=center>\n";
2680 echo "<tr><th class=tdleft>Attribute name</th><th class=tdleft>Attribute type</th><th class=tdleft>Applies to</th></tr>";
2681 $order = 'odd';
2682 foreach ($attrMap as $attr)
2683 {
2684 echo "<tr class=row_${order}>";
2685 echo "<td class=tdleft>${attr['name']}</td>";
2686 echo "<td class=tdleft>${attr['type']}</td>";
2687 echo '<td class=tdleft>';
2688 if (count ($attr['application']) == 0)
2689 echo '&nbsp;';
2690 else
2691 foreach ($attr['application'] as $app)
2692 if ($attr['type'] == 'dict')
2693 echo "${app['objtype_name']} (values from '${app['chapter_name']}')<br>";
2694 else
2695 echo "${app['objtype_name']}<br>";
2696 echo '</td>';
2697 echo "</tr>\n";
2698 $order = $nextorder[$order];
2699 }
2700 echo "</table><br>\n";
2701 finishPortlet();
2702 }
2703
2704 function renderEditAttributesForm ()
2705 {
2706 global $root, $pageno, $tabno;
2707 $attrMap = getAttrMap();
2708 showMessageOrError();
2709 startPortlet ('Optional attributes');
2710 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable>\n";
2711 echo '<tr><th>&nbsp;</th><th>Name</th><th>Type</th><th>&nbsp;</th></tr>';
2712 foreach ($attrMap as $attr)
2713 {
2714 echo "<form action='${root}process.php' method=post>";
2715 echo "<input type=hidden name=page value='${pageno}'>";
2716 echo "<input type=hidden name=tab value='${tabno}'>";
2717 echo "<input type=hidden name=op value=upd>";
2718 echo "<input type=hidden name=attr_id value='${attr['id']}'>";
2719 echo '<tr>';
2720 echo "<td><a href='${root}process.php?page=${pageno}&tab=${tabno}&op=del&attr_id=${attr['id']}'>";
2721 printImageHREF ('delete', 'Remove attribute');
2722 echo '</a></td>';
2723 echo "<td><input type=text name=attr_name value='${attr['name']}'></td>";
2724 echo "<td>${attr['type']}</td>";
2725 echo "<td><input type=submit value='OK'></td>";
2726 echo '</tr>';
2727 echo '</form>';
2728 }
2729 echo "<form action='${root}process.php' method=post>";
2730 echo "<input type=hidden name=page value='${pageno}'>";
2731 echo "<input type=hidden name=tab value='${tabno}'>";
2732 echo "<input type=hidden name=op value=add>";
2733 echo '<tr><td>';
2734 printImageHREF ('add', '', TRUE);
2735 echo "</td><td><input type=text name=attr_name></td>";
2736 echo '<td><select name=attr_type>';
2737 echo '<option value=uint>uint</option>';
2738 echo '<option value=float>float</option>';
2739 echo '<option value=string>string</option>';
2740 echo '<option value=dict>dict</option>';
2741 echo '</select></td>';
2742 echo '</tr>';
2743 echo '</form>';
2744 echo "</table>\n";
2745 finishPortlet();
2746 }
2747
2748 function renderEditAttrMapForm ()
2749 {
2750 global $root, $pageno, $tabno;
2751 $attrMap = getAttrMap();
2752 showMessageOrError();
2753 startPortlet ('Attribute map');
2754 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable>\n";
2755 echo '<tr><th>&nbsp;</th><th>Attribute name</th><th>Object type</th><th>Dictionary chapter</th></tr>';
2756 foreach ($attrMap as $attr)
2757 {
2758 if (count ($attr['application']) == 0)
2759 continue;
2760 foreach ($attr['application'] as $app)
2761 {
2762 echo '<tr>';
2763 echo '<td>';
2764 echo "<a href='${root}process.php?page=${pageno}&tab=${tabno}&op=del&";
2765 echo "attr_id=${attr['id']}&objtype_id=${app['objtype_id']}'>";
2766 printImageHREF ('delete', 'Remove mapping');
2767 echo "</a>";
2768 echo '</td>';
2769 echo "<td>${attr['name']}</td>";
2770 echo "<td>${app['objtype_name']}</td>";
2771 echo "<td>";
2772 if ($attr['type'] == 'dict')
2773 echo "${app['chapter_name']}";
2774 else
2775 echo '&nbsp;';
2776 echo "</td></tr>\n";
2777 }
2778 }
2779 echo "<form action='${root}process.php' method=post>";
2780 echo "<input type=hidden name=page value='${pageno}'>";
2781 echo "<input type=hidden name=tab value='${tabno}'>";
2782 echo "<input type=hidden name=op value=add>";
2783 echo '<tr><td>';
2784 printImageHREF ('add', '', TRUE);
2785 echo "</td><td><select name=attr_id>";
2786 $shortType['uint'] = 'U';
2787 $shortType['float'] = 'F';
2788 $shortType['string'] = 'S';
2789 $shortType['dict'] = 'D';
2790 foreach ($attrMap as $attr)
2791 echo "<option value=${attr['id']}>[" . $shortType[$attr['type']] . "] ${attr['name']}</option>";
2792 echo "</select></td>";
2793 echo '<td>';
2794 printSelect (getObjectTypeList(), 'objtype_id');
2795 echo '</td>';
2796 $dict = getDict();
2797 echo '<td><select name=chapter_no>';
2798 foreach ($dict as $chapter)
2799 if (!$chapter['sticky'])
2800 echo "<option value='${chapter['no']}'>${chapter['name']}</option>";
2801 echo '</select></td>';
2802 echo '</tr>';
2803 echo '</form>';
2804 echo "</table>\n";
2805 finishPortlet();
2806 }
2807
2808 function printImageHREF ($tag, $title = '', $do_input = FALSE, $tabindex = 0)
2809 {
2810 global $root;
2811 $image['error']['path'] = 'pix/error.png';
2812 $image['error']['width'] = 76;
2813 $image['error']['height'] = 17;
2814 $image['logo']['path'] = 'pix/defaultlogo.png';
2815 $image['logo']['width'] = 210;
2816 $image['logo']['height'] = 40;
2817 $image['rackspace']['path'] = 'pix/racks.png';
2818 $image['rackspace']['width'] = 218;
2819 $image['rackspace']['height'] = 200;
2820 $image['objects']['path'] = 'pix/server.png';
2821 $image['objects']['width'] = 218;
2822 $image['objects']['height'] = 200;
2823 $image['ipv4space']['path'] = 'pix/addressspace.png';
2824 $image['ipv4space']['width'] = 218;
2825 $image['ipv4space']['height'] = 200;
2826 $image['config']['path'] = 'pix/configuration.png';
2827 $image['config']['width'] = 218;
2828 $image['config']['height'] = 200;
2829 $image['reports']['path'] = 'pix/report.png';
2830 $image['reports']['width'] = 218;
2831 $image['reports']['height'] = 200;
2832 $image['help']['path'] = 'pix/help.png';
2833 $image['help']['width'] = 218;
2834 $image['help']['height'] = 200;
2835 $image['reserve']['path'] = 'pix/stop.png';
2836 $image['reserve']['width'] = 16;
2837 $image['reserve']['height'] = 16;
2838 $image['useup']['path'] = 'pix/go.png';
2839 $image['useup']['width'] = 16;
2840 $image['useup']['height'] = 16;
2841 $image['blockuser'] = $image['reserve'];
2842 $image['unblockuser'] = $image['useup'];
2843 $image['link']['path'] = 'pix/link.png';
2844 $image['link']['width'] = 24;
2845 $image['link']['height'] = 24;
2846 $image['unlink']['path'] = 'pix/unlink.png';
2847 $image['unlink']['width'] = 24;
2848 $image['unlink']['height'] = 24;
2849 $image['add']['path'] = 'pix/greenplus.png';
2850 $image['add']['width'] = 16;
2851 $image['add']['height'] = 16;
2852 $image['delete']['path'] = 'pix/delete_s.gif';
2853 $image['delete']['width'] = 16;
2854 $image['delete']['height'] = 16;
2855 $image['grant'] = $image['add'];
2856 $image['revoke'] = $image['delete'];
2857 $image['helphint']['path'] = 'pix/helphint.png';
2858 $image['helphint']['width'] = 24;
2859 $image['helphint']['height'] = 24;
2860 if (!isset ($image[$tag]))
2861 $tag = 'error';
2862 $img = $image[$tag];
2863 if ($do_input == TRUE)
2864 echo
2865 "<input type=image name=submit " .
2866 "src='${root}${img['path']}' " .
2867 "border=0 " .
2868 ($tabindex ? '' : "tabindex=${tabindex}") .
2869 ">";
2870 else
2871 echo
2872 "<img " .
2873 "src='${root}${img['path']}' " .
2874 "width=${img['width']} " .
2875 "height=${img['height']} " .
2876 "border=0 " .
2877 (empty ($title) ? '' : "title='${title}'") .
2878 ">";
2879 }
2880
2881 // This function returns URL for favourite icon.
2882 function getFaviconURL ()
2883 {
2884 global $root;
2885 return $root . 'pix/racktables.ico';
2886 }
2887
2888 function renderReportSummary ()
2889 {
2890 echo "<table width='100%'>\n";
2891 echo "<tr><td class=pcleft>\n";
2892 startPortlet ("Dictionary/objects stats");
2893 echo "<table>\n";
2894 foreach (getDictStats() as $header => $data)
2895 {
2896 echo "<tr><th>${header}:</th><td>${data}</td></tr>\n";
2897 }
2898 echo "</table>\n";
2899 finishPortlet();
2900
2901 echo "</td><td class=pcright>\n";
2902
2903 startPortlet ("Here be dragons");
2904 dragon();
2905 dragon();
2906 dragon();
2907 echo 'ASCII art &copy; Daniel C. Au';
2908 finishPortlet();
2909 echo "</td></tr>\n";
2910 echo "</table>\n";
2911 }
2912
2913 function dragon ()
2914 {
2915 ?>
2916 <div class=dragon><pre><font color="#00ff33">
2917 \||/
2918 | <font color="#ff0000">@</font>___oo
2919 /\ /\ / (__<font color=yellow>,,,,</font>|
2920 ) /^\) ^\/ _)
2921 ) /^\/ _)
2922 ) _ / / _)
2923 /\ )/\/ || | )_)
2924 &lt; &gt; |(<font color=white>,,</font>) )__)
2925 || / \)___)\
2926 | \____( )___) )___
2927 \______(_______<font color=white>;;;</font> __<font color=white>;;;</font>
2928
2929 </font></pre></div>
2930 <?php
2931 }
2932
2933 function renderUIConfig ()
2934 {
2935 global $configCache, $nextorder;
2936 showMessageOrError();
2937 startPortlet ('Current configuration');
2938 echo '<table class=cooltable border=0 cellpadding=5 cellspacing=0 align=center width="50%">';
2939 echo '<tr><th class=tdleft>Option</th><th class=tdleft>Value</th></tr>';
2940 $order = 'odd';
2941 foreach ($configCache as $v)
2942 {
2943 if ($v['is_hidden'] != 'no')
2944 continue;
2945 echo "<tr class=row_${order}>";
2946 echo "<td class=tdright>${v['description']}</td>\n";
2947 echo "<td class=tdleft>${v['varvalue']}</td></tr>";
2948 $order = $nextorder[$order];
2949 }
2950 echo "</table>\n";
2951 finishPortlet();
2952 }
2953
2954 function renderUIConfigEditForm ()
2955 {
2956 global $root, $pageno, $tabno, $configCache;
2957 showMessageOrError();
2958 startPortlet ('Current configuration');
2959 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable width='50%'>\n";
2960 echo "<tr><th class=tdleft>Option</th>";
2961 echo "<th class=tdleft>Value</th></tr>";
2962 echo "<form action='${root}process.php'>";
2963 echo "<input type=hidden name=op value='upd'>";
2964 echo "<input type=hidden name=page value='${pageno}'>\n";
2965 echo "<input type=hidden name=tab value='${tabno}'>\n";
2966
2967 $i = 0;
2968 foreach ($configCache as $v)
2969 {
2970 if ($v['is_hidden'] != 'no')
2971 continue;
2972 echo "<input type=hidden name=${i}_varname value='${v['varname']}'>";
2973 echo "<tr><td class=tdright>${v['description']}</td>";
2974 echo "<td class=tdleft><input type=text name=${i}_varvalue value='${v['varvalue']}' size=24></td>";
2975 echo "</tr>\n";
2976 $i++;
2977 }
2978 echo "<input type=hidden name=num_vars value=${i}>\n";
2979 echo "<tr><td colspan=2><input type=submit value='Save changes'></td></tr>";
2980 echo "</form>";
2981 finishPortlet();
2982 }
2983
2984 // This function queries the gateway about current VLAN configuration and
2985 // renders a form suitable for submit. Ah, and it does submit processing as well.
2986 function renderVLANMembership ($object_id = 0)
2987 {
2988 global $root, $pageno, $tabno, $remote_username;
2989 if ($object_id <= 0)
2990 {
2991 showError ('Invalid object_id in renderVLANMembership()');
2992 return;
2993 }
2994
2995 // Handle probable pending submit.
2996 if (isset ($_REQUEST['portcount']))
2997 {
2998 $data = getSwitchVLANs ($object_id);
2999 if ($data === NULL)
3000 {
3001 showError ('getSwitchVLANs() failed in renderVLANMembership() during submit processing');
3002 return;
3003 }
3004 list ($vlanlist, $portlist) = $data;
3005 // Here we just build up 1 set command for the gateway with all of the ports
3006 // included. The gateway is expected to filter unnecessary changes silently
3007 // and to provide a list of responses with either error or success message
3008 // for each of the rest.
3009 assertUIntArg ('portcount');
3010 $nports = $_REQUEST['portcount'];
3011 $prefix = 'set ';
3012 $log = array();
3013 $setcmd = '';
3014 for ($i = 0; $i < $nports; $i++)
3015 if
3016 (
3017 !isset ($_REQUEST['portname_' . $i]) ||
3018 !isset ($_REQUEST['vlanid_' . $i]) ||
3019 $_REQUEST['portname_' . $i] != $portlist[$i]['portname']
3020 )
3021 $log[] = array ('code' => 'error', 'message' => "Ignoring mailformed record #${i} in form submit");
3022 elseif
3023 (
3024 $_REQUEST['vlanid_' . $i] == $portlist[$i]['vlanid'] ||
3025 $portlist[$i]['vlaind'] == 'TRUNK'
3026 )
3027 continue;
3028 else
3029 {
3030 $setcmd .= $prefix . $_REQUEST['portname_' . $i] . '=' . $_REQUEST['vlanid_' . $i];
3031 $prefix = ';';
3032 }
3033 printLog ($log);
3034 // Feed the gateway and interpret its (non)response.
3035 if ($setcmd != '')
3036 printLog (setSwitchVLANs ($object_id, $setcmd));
3037 }
3038
3039 // Reload and render.
3040 $data = getSwitchVLANs ($object_id);
3041 if ($data === NULL)
3042 return;
3043 list ($vlanlist, $portlist, $maclist) = $data;
3044
3045 echo '<table border=0 width="100%"><tr><td colspan=3>';
3046
3047 startPortlet ('Current status');
3048 echo "<table class=widetable cellspacing=3 cellpadding=5 align=center width='100%'><tr>";
3049 echo "<form method=post>";
3050 echo "<input type=hidden name=page value='${pageno}'>";
3051 echo "<input type=hidden name=tab value='${tabno}'>";
3052 echo "<input type=hidden name=object_id value=${object_id}>";
3053 $portcount = count ($portlist);
3054 echo "<input type=hidden name=portcount value=" . $portcount . ">\n";
3055 $portno = 0;
3056 $ports_per_row = getConfigVar ('PORTS_PER_ROW');
3057 foreach ($portlist as $port)
3058 {
3059 // Don't let wide forms break our fancy pages.
3060 if ($portno % $ports_per_row == 0)
3061 {
3062 if ($portno > 0)
3063 echo "</tr>\n";
3064 echo "<tr><th>" . ($portno + 1) . "-" . ($portno + $ports_per_row > $portcount ? $portcount : $portno + $ports_per_row) . "</th>";
3065 }
3066 echo '<td class=port_';
3067 if ($port['status'] == 'notconnect')
3068 echo 'notconnect';
3069 elseif ($port['status'] == 'disabled')
3070 echo 'disabled';
3071 elseif ($port['status'] != 'connected')
3072 echo 'unknown';
3073 elseif (!isset ($maclist[$port['portname']]))
3074 echo 'connected_none';
3075 else
3076 {
3077 $maccount = 0;
3078 foreach ($maclist[$port['portname']] as $vlanid => $addrs)
3079 $maccount += count ($addrs);
3080 if ($maccount == 1)
3081 echo 'connected_single';
3082 else
3083 echo 'connected_multi';
3084 }
3085 echo '>' . $port['portname'] . '<br>';
3086 echo "<input type=hidden name=portname_${portno} value=" . $port['portname'] . '>';
3087 if ($port['vlanid'] == 'trunk')
3088 {
3089 echo "<input type=hidden name=vlanid_${portno} value='trunk'>";
3090 echo "<select disabled multiple='multiple' size=1><option>TRUNK</option></select>";
3091 }
3092 else
3093 {
3094 echo "<select name=vlanid_${portno}>";
3095 // A port may belong to a VLAN, which is absent from the VLAN table, this is normal.
3096 // We must be able to render its SELECT properly at least.
3097 $in_table = FALSE;
3098 foreach ($vlanlist as $v => $d)
3099 {
3100 echo "<option value=${v}";
3101 if ($v == $port['vlanid'])
3102 {
3103 echo ' selected';
3104 $in_table = TRUE;
3105 }
3106 echo ">${v}</option>\n";
3107 }
3108 if (!$in_table)
3109 echo "<option value=${port['vlanid']} selected>${port['vlanid']}</option>\n";
3110 echo "</select>";
3111 }
3112 $portno++;
3113 echo "</td>";
3114 }
3115 echo "</tr><tr><td colspan=" . ($ports_per_row + 1) . "><input type=submit value='Save changes'></form></td></tr></table>";
3116 finishPortlet();
3117
3118 echo '</td></tr><tr><td class=pcleft>';
3119 startPortlet ('VLAN table');
3120 echo '<table class=cooltable cellspacing=0 cellpadding=5 align=center width="100%">';
3121 echo "<tr><th>ID</th><th>Description</th></tr>";
3122 $order = 'even';
3123 global $nextorder;
3124 foreach ($vlanlist as $id => $descr)
3125 {
3126 echo "<tr class=row_${order}><td class=tdright>${id}</td><td class=tdleft>${descr}</td></tr>";
3127 $order = $nextorder[$order];
3128 }
3129 echo '</table>';
3130 finishPortlet();
3131
3132 echo '</td><td class=pcright>';
3133
3134 startPortlet ('Color legend');
3135 echo '<table>';
3136 echo "<tr><th>port state</th><th>color code</th></tr>";
3137 echo "<tr><td>not connected</td><td class=port_notconnect>SAMPLE</td></tr>";
3138 echo "<tr><td>disabled</td><td class=port_disabled>SAMPLE</td></tr>";
3139 echo "<tr><td>unknown</td><td class=port_unknown>SAMPLE</td></tr>";
3140 echo "<tr><td>connected with none MAC addresses active</td><td class=port_connected_none>SAMPLE</td></tr>";
3141 echo "<tr><td>connected with 1 MAC addresses active</td><td class=port_connected_single>SAMPLE</td></tr>";
3142 echo "<tr><td>connected with 1+ MAC addresses active</td><td class=port_connected_multi>SAMPLE</td></tr>";
3143 echo '</table>';
3144 finishPortlet();
3145
3146 echo '</td><td class=pcright>';
3147
3148 if (count ($maclist))
3149 {
3150 startPortlet ('MAC address table');
3151 echo '<table border=0 class=cooltable align=center cellspacing=0 cellpadding=5>';
3152 echo "<tr><th>Port</th><th>VLAN ID</th><th>MAC address</th></tr>\n";
3153 $order = 'even';
3154 foreach ($maclist as $portname => $portdata)
3155 foreach ($portdata as $vlanid => $addrgroup)
3156 foreach ($addrgroup as $addr)
3157 {
3158 echo "<tr class=row_${order}><td>$portname</td><td>$vlanid</td><td>$addr</td></tr>\n";
3159 $order = $nextorder[$order];
3160 }
3161 echo '</table>';
3162 finishPortlet();
3163 }
3164
3165 // End of main table.
3166 echo '</td></tr></table>';
3167 }
3168
3169 // This snippet either renders a form inviting the user to start SNMP query
3170 // on the current device or displays the result of the scan.
3171 function renderSNMPPortFinder ($object_id = 0)
3172 {
3173 global $root, $pageno, $tabno, $remote_username;
3174 if ($object_id <= 0)
3175 {
3176 showError ('Invalid object_id in renderSNMPPortFinder()');
3177 return;
3178 }
3179 // FIXME: check if SNMP PHP extension is available!
3180 if (isset ($_REQUEST['do_scan']))
3181 {
3182 $log = array();
3183 // IDs: http://cisco.com/en/US/products/sw/cscowork/ps2064/products_device_support_table09186a0080803bb4.html
3184 // 2960: http://www.cisco.com/en/US/products/ps6406/prod_models_comparison.html
3185 // 2970: http://cisco.com/en/US/products/hw/switches/ps5206/products_qanda_item09186a00801b1750.shtml
3186 // 3500XL: http://cisco.com/en/US/products/hw/switches/ps637/products_eol_models.html
3187 // 3560: http://cisco.com/en/US/products/hw/switches/ps5528/products_data_sheet09186a00801f3d7f.html
3188 // 3750: http://cisco.com/en/US/products/hw/switches/ps5023/products_data_sheet09186a008016136f.html
3189 $ciscomodel[283] = 'WS-C6509-E (9-slot system)';
3190 // FIXME: hwtype hardcoded value will become invalid after the Dictionary table transformation
3191 // in 0.14.7 version. Either the values will have to be adjusted as well or we have to switch
3192 // to value lookup (not reliable).
3193 $hwtype[283] = 148;
3194 # $ciscomodel[694] = 'WS-C2960-24TC-L (24 Ethernet 10/100 ports and 2 dual-purpose uplinks)';
3195 # $ciscomodel[695] = 'WS-C2960-48TC-L (48 Ethernet 10/100 ports and 2 dual-purpose uplinks)';
3196 $ciscomodel[696] = 'WS-C2960G-24TC-L (20 Ethernet 10/100/1000 ports and 4 dual-purpose uplinks)';
3197 $hwtype[696] = 167;
3198 $ciscomodel[697] = 'WS-C2960G-48TC-L (44 Ethernet 10/100/1000 ports and 4 dual-purpose uplinks)';
3199 $hwtype[697] = 166;
3200 # $ciscomodel[716] = 'WS-C2960-24TT-L (24 Ethernet 10/100 ports and 2 10/100/1000 uplinks)';
3201 # $ciscomodel[717] = 'WS-C2960-48TT-L (48 Ethernet 10/100 ports and 2 10/100/1000 uplinks)';
3202 $ciscomodel[527] = 'WS-C2970G-24T (24 Ethernet 10/100/1000 ports)';
3203 $hwtype[527] = 210;
3204 $ciscomodel[561] = 'WS-C2970G-24TS (24 Ethernet 10/100/1000 ports and 4 10/100/1000 SFP uplinks)';
3205 $hwtype[561] = 115;
3206 # $ciscomodel[633] = 'WS-C3560-24TS (24 Ethernet 10/100 ports and 2 10/100/1000 SFP uplinks)';
3207 # $hwtype[633] = 169;
3208 $ciscomodel[634] = 'WS-C3560-48TS (48 Ethernet 10/100 ports and 4 10/100/1000 SFP uplinks)';
3209 $hwtype[634] = 170;
3210 # $ciscomodel[563] = 'WS-C3560-24PS (24 Ethernet 10/100 POE ports and 2 10/100/1000 SFP uplinks)';
3211 # $hwtype[563] = 171;
3212 $ciscomodel[564] = 'WS-C3560-48PS (48 Ethernet 10/100 POE ports and 4 10/100/1000 SFP uplinks)';
3213 $hwtype[564] = 172;
3214 $ciscomodel[614] = 'WS-C3560G-24PS (24 Ethernet 10/100/1000 POE ports and 4 10/100/1000 SFP uplinks)';
3215 $hwtype[614] = 175;
3216 $ciscomodel[615] = 'WS-C3560G-24TS (24 Ethernet 10/100/1000 ports and 4 10/100/1000 SFP uplinks)';
3217 $hwtype[615] = 173;
3218 $ciscomodel[616] = 'WS-C3560G-48PS (48 Ethernet 10/100/1000 POE ports and 4 10/100/1000 SFP uplinks)';
3219 $hwtype[616] = 176;
3220 $ciscomodel[617] = 'WS-C3560G-48TS (48 Ethernet 10/100/1000 ports and 4 10/100/1000 SFP uplinks)';
3221 $hwtype[617] = 174;
3222 $ciscomodel[58] = 'WS-C4503 (3-slot system)';
3223 $hwtype[58] = 145;
3224 $ciscomodel[503] = '4503 (3-slot system)';
3225 $hwtype[503] = 145;
3226 $ciscomodel[59] = 'WS-C4506 (6-slot system)';
3227 $hwtype[59] = 156;
3228 $ciscomodel[502] = '4506 (6-slot system)';
3229 $hwtype[502] = 156;
3230 $ciscomodel[626] = 'WS-C4948 (48 Ethernet 10/100/1000 ports and 4 10/100/1000 SFP uplinks)';
3231 $hwtype[626] = 147;
3232 $ciscomodel[659] = 'WS-C4948-10GE (48 Ethernet 10/100/1000 ports and 2 10Gb X2 uplinks)';
3233 $hwtype[659] = 377;
3234 assertStringArg ('community');
3235 $community = $_REQUEST['community'];
3236 $objectInfo = getObjectInfo ($object_id);
3237 $endpoints = findAllEndpoints ($object_id, $objectInfo['name']);
3238 $sysDescr = snmpget ($endpoints[0], $community, 'sysDescr.0');
3239 // Strip the object type, it's always string here.
3240 $sysDescr = substr ($sysDescr, strlen ('STRING: '));
3241 if (strpos ($sysDescr, 'Cisco IOS Software') === 0 or strpos ($sysDescr, 'Cisco Internetwork Operating System Software') === 0)
3242 $log[] = array ('code' => 'success', 'message' => 'Seems to be a Cisco box');
3243 else
3244 {
3245 $log[] = array ('code' => 'error', 'message' => 'No idea how to handle ' . $sysDescr);
3246 printLog ($log);
3247 return;
3248 }
3249
3250 // It's a Cisco. Go on.
3251 $attrs = getAttrValues ($object_id);
3252 // Only fill in attribute values, if they are not set.
3253 // FIXME: this is hardcoded
3254
3255 if (empty ($attrs[5]['value'])) // SW version
3256 {
3257 $IOSversion = ereg_replace ('^.*, Version ([^ ]+), .*$', '\\1', $sysDescr);
3258 $error = commitUpdateAttrValue ($object_id, 5, $IOSversion);
3259 if ($error == TRUE)
3260 $log[] = array ('code' => 'success', 'message' => 'SW version set to ' . $IOSversion);
3261 else
3262 $log[] = array ('code' => 'error', 'message' => 'Failed settig SW version: ' . $error);
3263 }
3264
<