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