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