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