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