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