r5083 commitUpdateVS: vport argument is not mandatory if proto is 'MARK'
[racktables] / wwwroot / inc / interface.php
CommitLineData
b325120a 1<?php
cddbb9fd
DO
2
3# This file is a part of RackTables, a datacenter and server room management
4# framework. See accompanying file "COPYING" for the full copyright and
5# licensing information.
6
e673ee24
DO
7/*
8*
9* This file contains frontend functions for RackTables.
10*
11*/
12
e82deb48 13require_once 'ajax-interface.php';
defd92d8 14require_once 'slb-interface.php';
65e557dd 15
9c0b0016
DO
16// Interface function's special.
17$nextorder['odd'] = 'even';
18$nextorder['even'] = 'odd';
19
52c836b1
DO
20// address allocation type
21$aat = array
22(
23 'regular' => 'Connected',
24 'virtual' => 'Loopback',
25 'shared' => 'Shared',
26 'router' => 'Router',
27);
beb9e88a 28// address allocation code, IPv4 addresses and objects view
52c836b1
DO
29$aac = array
30(
31 'regular' => '',
4318ced5
AA
32 'virtual' => '<span class="aac">L</span>',
33 'shared' => '<span class="aac">S</span>',
34 'router' => '<span class="aac">R</span>',
52c836b1 35);
beb9e88a
DO
36// address allocation code, IPv4 networks view
37$aac2 = array
38(
39 'regular' => '',
40 'virtual' => '<strong>L:</strong>',
29025f8e 41 'shared' => '<strong>S:</strong>',
beb9e88a
DO
42 'router' => '<strong>R:</strong>',
43);
52c836b1 44
0dabdc53
DO
45$vtdecoder = array
46(
47 'ondemand' => '',
54b7ced3
DO
48 'compulsory' => 'P',
49# 'alien' => 'NT',
0dabdc53
DO
50);
51
52$vtoptions = array
53(
54b7ced3
DO
54 'ondemand' => 'auto',
55 'compulsory' => 'permanent',
56# 'alien' => 'never touch',
0dabdc53
DO
57);
58
e5c4506d
DO
59// This may be populated later onsite, report rendering function will use it.
60// See the $systemreport for structure.
61$localreports = array();
d6adad3e 62
9db67d95
DO
63$CodePressMap = array
64(
65 'sql' => 'sql',
66 'php' => 'php',
67 'html' => 'html',
68 'css' => 'css',
69 'js' => 'javascript',
70);
e5c4506d 71
8d4f7d18
DO
72$attrtypes = array
73(
74 'uint' => '[U] unsigned integer',
75 'float' => '[F] floating point',
76 'string' => '[S] string',
86ff26ae
DO
77 'dict' => '[D] dictionary record',
78 'date' => '[T] date'
8d4f7d18
DO
79);
80
a1d72d2e
AA
81$quick_links = NULL; // you can override this in your local.php, but first initialize it with getConfiguredQuickLinks()
82
83function renderQuickLinks()
84{
85 global $quick_links;
86 if (! isset ($quick_links))
87 $quick_links = getConfiguredQuickLinks();
88 echo '<ul class="qlinks">';
89 foreach ($quick_links as $link)
90 echo '<li><a href="' . $link['href'] . '">' . str_replace (' ', '&nbsp;', $link['title']) . '</a></li>';
91 echo '</ul>';
92}
93
f97df464
DO
94function renderInterfaceHTML ($pageno, $tabno, $payload)
95{
96?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
97<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
98<head><title><?php echo getTitle ($pageno); ?></title>
99<?php printPageHeaders(); ?>
100</head>
101<body>
102<table border=0 cellpadding=0 cellspacing=0 width="100%" height="100%" class="maintable">
103 <tr class="mainheader"><td>
a1d72d2e
AA
104 <?php echo getConfigVar ('enterprise') ?> RackTables <a href="http://racktables.org" title="Visit RackTables site"><?php echo CODE_VERSION ?></a><?php renderQuickLinks() ?>
105 <div style="float: right" class=greeting><a href='index.php?page=myaccount&tab=default'><?php global $remote_displayname; echo $remote_displayname ?></a> [ <a href='?logout'>logout</a> ]</div>
f97df464
DO
106 </td></tr>
107 <tr><td class="menubar">
108 <table border="0" width="100%" cellpadding="3" cellspacing="0">
109 <tr><?php showPathAndSearch ($pageno); ?></tr>
110 </table>
111 </td></tr>
112 <tr><td><?php showTabs ($pageno, $tabno); ?></td></tr>
113 <tr><td><?php showMessageOrError(); ?></td></tr>
114 <tr><td><?php echo $payload; ?></td></tr>
115</table>
116</body>
117</html>
118<?php
119}
120
e673ee24 121// Main menu.
4b680876
DO
122function renderIndexItem ($ypageno) {
123 global $page;
124 if (permitted($ypageno)) {
a1d72d2e
AA
125 $title = getPageName ($ypageno);
126 print " <td>\n";
21ee3351 127 print " <h1><a href='".makeHref(array('page'=>$ypageno))."'>".$title."<br>\n";
4b680876
DO
128 printImageHREF ($ypageno);
129 print "</a></h1>\n";
130 print " </td>\n";
131 } else {
132 print " <td>&nbsp;</td>\n";
133 }
134}
135
e673ee24
DO
136function renderIndex ()
137{
67c5c049 138 global $indexlayout;
e673ee24
DO
139?>
140<table border=0 cellpadding=0 cellspacing=0 width='100%'>
141 <tr>
142 <td>
143 <div style='text-align: center; margin: 10px; '>
a544d2c4 144 <table width='100%' cellspacing=0 cellpadding=20 class=mainmenu border=0>
4b680876 145<?php
67c5c049
DO
146foreach ($indexlayout as $row)
147{
148 echo '<tr>';
149 foreach ($row as $column)
150 if ($column === NULL)
151 echo '<td>&nbsp;</td>';
152 else
153 renderIndexItem ($column);
154 echo '</tr>';
155}
156?>
e673ee24
DO
157 </table>
158 </div>
159 </td>
160 </tr>
161</table>
b325120a 162<?php
e673ee24
DO
163}
164
f3505b35
AA
165function getRenderedAlloc ($object_id, $alloc)
166{
167 $ret = array
168 (
169 'tr_class' => '',
40c9fc94 170 'td_name_suffix' => '',
f3505b35
AA
171 'td_ip' => '',
172 'td_network' => '',
173 'td_routed_by' => '',
174 'td_peers' => '',
175 );
176 $dottedquad = $alloc['addrinfo']['ip'];
4318ced5 177 $ip_bin = $alloc['addrinfo']['ip_bin'];
f3505b35 178
4318ced5
AA
179 $hl_ip_bin = NULL;
180 if (isset ($_REQUEST['hl_ip']))
f3505b35 181 {
4318ced5
AA
182 $hl_ip_bin = ip_parse ($_REQUEST['hl_ip']);
183 addAutoScrollScript ("ip-" . $_REQUEST['hl_ip']);
f3505b35
AA
184 }
185
186 $ret['tr_class'] = $alloc['addrinfo']['class'];
4318ced5
AA
187 if ($hl_ip_bin === $ip_bin)
188 $ret['tr_class'] .= ' port_highlight';
f3505b35 189
68c91b9c
AA
190 // render IP change history
191 $ip_title = '';
192 $ip_class = '';
193 if (isset ($alloc['addrinfo']['last_log']))
194 {
195 $log = $alloc['addrinfo']['last_log'];
196 $ip_title = "title='" .
197 htmlspecialchars
198 (
199 $log['user'] . ', ' . formatAge ($log['time']),
200 ENT_QUOTES
201 ) . "'";
202 $ip_class = 'hover-history underline';
203 }
204
f3505b35
AA
205 // render IP address td
206 global $aac;
4318ced5
AA
207 $netinfo = spotNetworkByIP ($ip_bin);
208 $ret['td_ip'] = "<td class='tdleft'>";
209 if (isset ($netinfo))
210 {
211 $title = $dottedquad;
212 if (getConfigVar ('EXT_IPV4_VIEW') != 'yes')
213 $title .= '/' . $netinfo['mask'];
68c91b9c 214 $ret['td_ip'] .= "<a name='ip-$dottedquad' class='$ip_class' $ip_title href='" .
f3505b35
AA
215 makeHref (
216 array
217 (
4318ced5 218 'page' => 'ipaddress',
f3505b35
AA
219 'hl_object_id' => $object_id,
220 'ip' => $dottedquad,
221 )
4318ced5
AA
222 ) . "'>$title</a>";
223 }
f3505b35 224 else
68c91b9c 225 $ret['td_ip'] .= "<span class='$ip_class' $ip_title>$dottedquad</span>";
4318ced5 226 $ret['td_ip'] .= $aac[$alloc['type']];
f3505b35
AA
227 if (strlen ($alloc['addrinfo']['name']))
228 $ret['td_ip'] .= ' (' . niftyString ($alloc['addrinfo']['name']) . ')';
229 $ret['td_ip'] .= '</td>';
230
231 // render network and routed_by tds
4318ced5
AA
232 $td_class = 'tdleft';
233 if (! isset ($netinfo))
f3505b35
AA
234 {
235 $ret['td_network'] = "<td class='$td_class sparenetwork'>N/A</td>";
236 $ret['td_routed_by'] = $ret['td_network'];
237 }
238 else
239 {
240 $ret['td_network'] = "<td class='$td_class'>" .
241 getOutputOf ('renderCell', $netinfo) . '</td>';
242
243 // filter out self-allocation
4318ced5 244 loadIPAddrList ($netinfo);
f3505b35 245 $other_routers = array();
4318ced5 246 foreach (findRouters ($netinfo['own_addrlist']) as $router)
f3505b35
AA
247 if ($router['id'] != $object_id)
248 $other_routers[] = $router;
249 if (count ($other_routers))
f59e175c 250 $ret['td_routed_by'] = getOutputOf ('printRoutersTD', $other_routers, getConfigVar ('IPV4_TREE_RTR_AS_CELL'));
f3505b35
AA
251 else
252 $ret['td_routed_by'] = "<td class='$td_class'>&nbsp;</td>";
253 }
254
255 // render peers td
256 $ret['td_peers'] = "<td class='$td_class'>";
257 $prefix = '';
258 if ($alloc['addrinfo']['reserved'] == 'yes')
259 {
260 $ret['td_peers'] .= $prefix . '<strong>RESERVED</strong>';
261 $prefix = '; ';
262 }
263 foreach ($alloc['addrinfo']['allocs'] as $allocpeer)
264 {
265 if ($allocpeer['object_id'] == $object_id)
266 continue;
267 $ret['td_peers'] .= $prefix . "<a href='" . makeHref (array ('page' => 'object', 'object_id' => $allocpeer['object_id'])) . "'>";
268 if (isset ($allocpeer['osif']) and strlen ($allocpeer['osif']))
269 $ret['td_peers'] .= $allocpeer['osif'] . '@';
270 $ret['td_peers'] .= $allocpeer['object_name'] . '</a>';
271 $prefix = '; ';
272 }
273 $ret['td_peers'] .= '</td>';
274
275 return $ret;
276}
277
e673ee24
DO
278function renderRackspace ()
279{
95857b5c
DO
280 $found_racks = array();
281 $rows = array();
a8efc03e 282 $cellfilter = getCellFilter();
1ebbf889 283 $rackCount = 0;
9b8174d7 284 foreach (getRows() as $row_id => $row_name) {
95857b5c
DO
285 $rackList = filterCellList (listCells ('rack', $row_id), $cellfilter['expression']);
286 $found_racks = array_merge($found_racks, $rackList);
287 $rows[] = array(
288 'row_id' => $row_id,
289 'row_name' => $row_name,
290 'racks' => $rackList
291 );
1ebbf889 292 $rackCount += count($rackList);
95857b5c 293 }
1ebbf889 294
95857b5c 295 echo "<table class=objview border=0 width='100%'><tr><td class=pcleft>";
1ebbf889
AA
296
297 if (! renderEmptyResults($cellfilter, 'racks', $rackCount))
e673ee24 298 {
1ebbf889
AA
299 echo '<table border=0 cellpadding=10 cellpadding=1>';
300 // generate thumb gallery
301 global $nextorder;
302 $rackwidth = getRackImageWidth();
303 // Zero value effectively disables the limit.
304 $maxPerRow = getConfigVar ('RACKS_PER_ROW');
305 $order = 'odd';
306 foreach ($rows as $row)
307 {
308 $row_id = $row['row_id'];
309 $row_name = $row['row_name'];
310 $rackList = $row['racks'];
311
312 if (!count ($rackList) and count ($cellfilter['expression']))
313 continue;
314 $rackListIdx = 0;
315 echo "<tr class=row_${order}><th class=tdleft>";
316 echo "<a href='".makeHref(array('page'=>'row', 'row_id'=>$row_id))."${cellfilter['urlextra']}'>";
317 echo "${row_name}</a></th><td><table border=0 cellspacing=5><tr>";
318 if (!count ($rackList))
319 echo "<td>(empty row)</td>";
320 else
321 foreach ($rackList as $rack)
48325652 322 {
1ebbf889
AA
323 if ($rackListIdx > 0 and $maxPerRow > 0 and $rackListIdx % $maxPerRow == 0)
324 {
325 echo '</tr></table></tr>';
326 echo "<tr class=row_${order}><th class=tdleft>${row_name} (continued)";
327 echo "</th><td><table border=0 cellspacing=5><tr>";
328 }
a3021995 329 echo "<td align=center valign=bottom><a href='".makeHref(array('page'=>'rack', 'rack_id'=>$rack['id']))."'>";
1ebbf889
AA
330 echo "<img border=0 width=${rackwidth} height=";
331 echo getRackImageHeight ($rack['height']);
332 echo " title='${rack['height']} units'";
4afb4c10 333 echo "src='?module=image&img=minirack&rack_id=${rack['id']}'>";
1ebbf889
AA
334 echo "<br>${rack['name']}</a></td>";
335 $rackListIdx++;
48325652 336 }
1ebbf889
AA
337 $order = $nextorder[$order];
338 echo "</tr></table></tr>\n";
339 }
340 echo "</table>\n";
e673ee24 341 }
14ad4f4a
DO
342 echo '</td><td class=pcright width="25%">';
343 renderCellFilterPortlet ($cellfilter, 'rack', $found_racks);
489a7502 344 echo "</td></tr></table>\n";
e673ee24
DO
345}
346
345fd640
AD
347function renderRackspaceRowEditor ()
348{
349 function printNewItemTR ()
350 {
351 printOpFormIntro ('addRow');
1f02e311 352 echo "<input type=hidden name=objtype_id value=1561>\n";
7be51fea
DO
353 echo "<tr><td>";
354 printImageHREF ('create', 'Add new row', TRUE);
355 echo "</td><td><input type=text name=name tabindex=100></td><td>";
345fd640 356 printImageHREF ('create', 'Add new row', TRUE, 101);
7be51fea 357 echo "</td></tr></form>";
345fd640 358 }
d732e47e 359 startPortlet ('Rows');
345fd640 360 echo "<table border=0 cellspacing=0 cellpadding=5 align=center class=widetable>\n";
7be51fea 361 echo "<tr><th>&nbsp;</th><th>Name</th><th>&nbsp;</th></tr>\n";
345fd640
AD
362 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
363 printNewItemTR();
9b8174d7 364 foreach (getRows() as $row_id => $row_name)
345fd640 365 {
7be51fea 366 echo "<tr><td>";
a8efc03e 367 if ($rc = count (listCells ('rack', $row_id)))
6c18dd08 368 printImageHREF ('nodestroy', "${rc} rack(s) here");
7be51fea 369 else
5af82683 370 {
1f02e311 371 echo "<a href=\"".makeHrefProcess(array('op'=>'deleteRow', 'row_id'=>$row_id))."\">";
7be51fea 372 printImageHREF ('destroy', 'Delete row');
5af82683
DY
373 echo "</a>";
374 }
c40666f5
DO
375 printOpFormIntro ('updateRow', array ('row_id' => $row_id));
376 echo "</td><td><input type=text name=name value='${row_name}'></td><td>";
7be51fea
DO
377 printImageHREF ('save', 'Save changes', TRUE);
378 echo "</form></td></tr>\n";
345fd640
AD
379 }
380 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
381 printNewItemTR();
382 echo "</table><br>\n";
383 finishPortlet();
384}
385
7e1db771 386function renderRow ($row_id)
e673ee24 387{
9b8174d7 388 $rowInfo = getRowInfo ($row_id);
a8efc03e
DO
389 $cellfilter = getCellFilter();
390 $rackList = filterCellList (listCells ('rack', $row_id), $cellfilter['expression']);
e673ee24
DO
391 // Main layout starts.
392 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
393
394 // Left portlet with row information.
395 echo "<tr><td class=pcleft>";
a8ce7234 396 startPortlet ($rowInfo['name']);
e673ee24 397 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
5af82683
DY
398 echo "<tr><th width='50%' class=tdright>Racks:</th><td class=tdleft>${rowInfo['count']}</td></tr>\n";
399 echo "<tr><th width='50%' class=tdright>Units:</th><td class=tdleft>${rowInfo['sum']}</td></tr>\n";
9b8174d7
AD
400 echo "<tr><th width='50%' class=tdright>% used:</th><td class=tdleft>";
401 renderProgressBar (getRSUforRow ($rackList));
114e50af 402 echo "</td></tr>\n";
e673ee24
DO
403 echo "</table><br>\n";
404 finishPortlet();
95857b5c 405 renderCellFilterPortlet ($cellfilter, 'rack', $rackList, 'row_id', $row_id);
e673ee24 406
48325652 407 echo "</td><td class=pcright>";
e673ee24 408
4fbb5a00 409 global $nextorder;
d5157018 410 $rackwidth = getRackImageWidth() * getConfigVar ('ROW_SCALE');
f5883ec1
DO
411 // Maximum number of racks per row is proportionally less, but at least 1.
412 $maxPerRow = max (floor (getConfigVar ('RACKS_PER_ROW') / getConfigVar ('ROW_SCALE')), 1);
413 $rackListIdx = 0;
e673ee24
DO
414 $order = 'odd';
415 startPortlet ('Racks');
416 echo "<table border=0 cellspacing=5 align='center'><tr>";
64b95774 417 foreach ($rackList as $rack)
e673ee24 418 {
f5883ec1
DO
419 if ($rackListIdx % $maxPerRow == 0)
420 {
421 if ($rackListIdx > 0)
422 echo '</tr>';
423 echo '<tr>';
424 }
9b8174d7 425 $class = ($rack['has_problems'] == 'yes') ? 'error' : $order;
d69e5d6f 426 echo "<td align=center valign=bottom class=row_${class}><a href='".makeHref(array('page'=>'rack', 'rack_id'=>$rack['id']))."'>";
d5157018 427 echo "<img border=0 width=${rackwidth} height=" . (getRackImageHeight ($rack['height']) * getConfigVar ('ROW_SCALE'));
e673ee24 428 echo " title='${rack['height']} units'";
4afb4c10 429 echo "src='?module=image&img=minirack&rack_id=${rack['id']}'>";
e673ee24
DO
430 echo "<br>${rack['name']}</a></td>";
431 $order = $nextorder[$order];
f5883ec1 432 $rackListIdx++;
e673ee24
DO
433 }
434 echo "</tr></table>\n";
435 finishPortlet();
e673ee24
DO
436 echo "</td></tr></table>";
437}
438
0a7feebb
AD
439// Used by renderRack()
440function printObjectDetailsForRenderRack ($object_id)
441{
442 $objectData = spotEntity ('object', $object_id);
443 if (strlen ($objectData['asset_no']))
444 $prefix = "<div title='${objectData['asset_no']}";
445 else
446 $prefix = "<div title='no asset tag";
447 // Don't tell about label, if it matches common name.
448 $body = '';
449 if ($objectData['name'] != $objectData['label'] and strlen ($objectData['label']))
450 $body = ", visible label is \"${objectData['label']}\"";
451 // Display list of child objects, if any
452 $objectChildren = getEntityRelatives ('children', 'object', $objectData['id']);
453 if (count($objectChildren) > 0)
454 {
455 foreach ($objectChildren as $child)
456 $childNames[] = $child['name'];
457 natsort($childNames);
458 $suffix = sprintf(", contains %s'>", implode(', ', $childNames));
459 }
460 else
461 $suffix = "'>";
462 echo $prefix . $body . $suffix;
463 echo "<a href='".makeHref(array('page'=>'object', 'object_id'=>$objectData['id']))."'>${objectData['dname']}</a></div>";
464}
465
e673ee24 466// This function renders rack as HTML table.
7e1db771 467function renderRack ($rack_id, $hl_obj_id = 0)
e673ee24 468{
61a1d996
DO
469 $rackData = spotEntity ('rack', $rack_id);
470 amplifyCell ($rackData);
e673ee24
DO
471 markAllSpans ($rackData);
472 if ($hl_obj_id > 0)
473 highlightObject ($rackData, $hl_obj_id);
474 markupObjectProblems ($rackData);
475 $prev_id = getPrevIDforRack ($rackData['row_id'], $rack_id);
476 $next_id = getNextIDforRack ($rackData['row_id'], $rack_id);
d48d8820 477 echo "<center><table border=0><tr valign=middle>";
4fbb5a00 478 echo "<td><h2><a href='".makeHref(array('page'=>'row', 'row_id'=>$rackData['row_id']))."'>${rackData['row_name']}</a> :</h2></td>";
e673ee24
DO
479 // FIXME: use 'bypass'?
480 if ($prev_id != NULL)
9803c56c 481 {
4fbb5a00 482 echo "<td><a href='".makeHref(array('page'=>'rack', 'rack_id'=>$prev_id))."'>";
9803c56c 483 printImageHREF ('prev', 'previous rack');
d48d8820 484 echo "</a></td>";
9803c56c 485 }
4fbb5a00 486 echo "<td><h2><a href='".makeHref(array('page'=>'rack', 'rack_id'=>$rackData['id']))."'>${rackData['name']}</a></h2></td>";
e673ee24 487 if ($next_id != NULL)
9803c56c 488 {
4fbb5a00 489 echo "<td><a href='".makeHref(array('page'=>'rack', 'rack_id'=>$next_id))."'>";
f444c095 490 printImageHREF ('next', 'next rack');
d48d8820 491 echo "</a></td>";
9803c56c 492 }
d48d8820 493 echo "</h2></td></tr></table>\n";
e673ee24 494 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
d08147d6
DO
495 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>Front</th>";
496 echo "<th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
e673ee24
DO
497 for ($i = $rackData['height']; $i > 0; $i--)
498 {
d08147d6 499 echo "<tr><th>${i}</th>";
e673ee24
DO
500 for ($locidx = 0; $locidx < 3; $locidx++)
501 {
502 if (isset ($rackData[$i][$locidx]['skipped']))
503 continue;
504 $state = $rackData[$i][$locidx]['state'];
65e557dd 505 echo "<td class='atom state_${state}";
e673ee24
DO
506 if (isset ($rackData[$i][$locidx]['hl']))
507 echo $rackData[$i][$locidx]['hl'];
65e557dd 508 echo "'";
e673ee24
DO
509 if (isset ($rackData[$i][$locidx]['colspan']))
510 echo ' colspan=' . $rackData[$i][$locidx]['colspan'];
511 if (isset ($rackData[$i][$locidx]['rowspan']))
512 echo ' rowspan=' . $rackData[$i][$locidx]['rowspan'];
513 echo ">";
514 switch ($state)
515 {
516 case 'T':
0a7feebb 517 printObjectDetailsForRenderRack($rackData[$i][$locidx]['object_id']);
e673ee24
DO
518 break;
519 case 'A':
520 echo '<div title="This rackspace does not exist">&nbsp;</div>';
521 break;
522 case 'F':
523 echo '<div title="Free rackspace">&nbsp;</div>';
524 break;
525 case 'U':
526 echo '<div title="Problematic rackspace, you CAN\'T mount here">&nbsp;</div>';
527 break;
528 default:
529 echo '<div title="No data">&nbsp;</div>';
530 break;
531 }
532 echo '</td>';
533 }
534 echo "</tr>\n";
535 }
0a7feebb
AD
536 echo "</table>\n";
537 // Get a list of all of objects Zero-U mounted to this rack
538 $zeroUObjects = getEntityRelatives('children', 'rack', $rack_id);
539 if (count($zeroUObjects) > 0) {
540 echo "<br><table width='75%' class=rack border=0 cellspacing=0 cellpadding=1>\n";
541 echo "<tr><th>Zero-U:</th></tr>\n";
542 foreach ($zeroUObjects as $zeroUObject)
543 {
544 $state = ($zeroUObject['entity_id'] == $hl_obj_id) ? 'Th' : 'T';
545 echo "<tr><td class='atom state_${state}'>";
546 printObjectDetailsForRenderRack($zeroUObject['entity_id']);
547 echo "</td></tr>\n";
548 }
549 echo "</table>\n";
550 }
551 echo "</center>\n";
e673ee24
DO
552}
553
e673ee24
DO
554function renderNewRackForm ($row_id)
555{
9b8174d7
AD
556 $default_height = getConfigVar ('DEFAULT_RACK_HEIGHT');
557 if ($default_height == 0)
558 $default_height = '';
50b4ba85 559 startPortlet ('Add one');
f19c75d6 560 printOpFormIntro ('addRack', array ('got_data' => 'TRUE'));
e673ee24 561 echo '<table border=0 align=center>';
9b8174d7 562 echo "<tr><th class=tdright>Name (required):</th><td class=tdleft><input type=text name=name tabindex=1></td>";
72d52730 563 echo "<td rowspan=4>Assign tags:<br>";
a26a6ccc 564 renderNewEntityTags ('rack');
72d52730 565 echo "</td></tr>\n";
9b8174d7 566 echo "<tr><th class=tdright>Height in units (required):</th><td class=tdleft><input type=text name=height1 tabindex=2 value='${default_height}'></td></tr>\n";
9b8174d7 567 echo "<tr><th class=tdright>Asset tag:</th><td class=tdleft><input type=text name=asset_no tabindex=4></td></tr>\n";
f19c75d6
DO
568 echo "<tr><td class=submit colspan=2>";
569 printImageHREF ('CREATE', 'Add', TRUE);
570 echo "</td></tr></table></form>";
406b54bd 571 finishPortlet();
406b54bd 572
50b4ba85 573 startPortlet ('Add many');
f19c75d6 574 printOpFormIntro ('addRack', array ('got_mdata' => 'TRUE'));
50b4ba85 575 echo '<table border=0 align=center>';
9b8174d7 576 echo "<tr><th class=tdright>Height in units (*):</th><td class=tdleft><input type=text name=height2 value='${default_height}'></td>";
72d52730 577 echo "<td rowspan=3 valign=top>Assign tags:<br>";
a26a6ccc 578 renderNewEntityTags ('rack');
72d52730 579 echo "</td></tr>\n";
9b8174d7 580 echo "<tr><th class=tdright>Rack names (required):</th><td class=tdleft><textarea name=names cols=40 rows=25></textarea></td></tr>\n";
f19c75d6
DO
581 echo "<tr><td class=submit colspan=2>";
582 printImageHREF ('CREATE', 'Add', TRUE);
e673ee24
DO
583 echo '</form></table>';
584 finishPortlet();
585}
586
3825c4db 587function renderEditObjectForm()
e673ee24 588{
8dc2a6c8 589 global $pageno, $virtual_obj_types;
3825c4db 590 $object_id = getBypassValue();
fb6e2f57 591 $object = spotEntity ('object', $object_id);
cdd3efe9 592 startPortlet ();
43fb6eaf 593 printOpFormIntro ('update');
cdd3efe9
AD
594
595 // static attributes
e10f583a
DO
596 echo '<table border=0 cellspacing=0 cellpadding=3 align=center>';
597 echo "<tr><td>&nbsp;</td><th colspan=2><h2>Attributes</h2></th></tr>";
3825c4db
DO
598 echo '<tr><td>&nbsp;</td><th class=tdright>Type:</th><td class=tdleft>';
599 printSelect (getObjectTypeChangeOptions ($object['id']), array ('name' => 'object_type_id'), $object['objtype_id']);
600 echo '</td></tr>';
22bb04da 601 // baseline info
e10f583a 602 echo "<tr><td>&nbsp;</td><th class=tdright>Common name:</th><td class=tdleft><input type=text name=object_name value='${object['name']}'></td></tr>\n";
8dc2a6c8 603 if (in_array($object['objtype_id'], $virtual_obj_types))
0682218d
AD
604 {
605 echo "<input type=hidden name=object_label value=''>\n";
606 echo "<input type=hidden name=object_asset_no value=''>\n";
0682218d
AD
607 }
608 else
609 {
610 echo "<tr><td>&nbsp;</td><th class=tdright>Visible label:</th><td class=tdleft><input type=text name=object_label value='${object['label']}'></td></tr>\n";
611 echo "<tr><td>&nbsp;</td><th class=tdright>Asset tag:</th><td class=tdleft><input type=text name=object_asset_no value='${object['asset_no']}'></td></tr>\n";
0682218d
AD
612 }
613 // parent selection
9b8174d7 614 if (objectTypeMayHaveParent ($object['objtype_id']))
0682218d
AD
615 {
616 $parents = getEntityRelatives ('parents', 'object', $object_id);
617 foreach ($parents as $link_id => $parent_details)
618 {
619 if (!isset($label))
620 $label = count($parents) > 1 ? 'Containers:' : 'Container:';
621 echo "<tr><td>&nbsp;</td>";
622 echo "<th class=tdright>${label}</th><td class=tdleft>";
623 echo "<a href='".makeHref(array('page'=>'object', 'object_id'=>$parent_details['entity_id']))."'>${parent_details['name']}</a>";
624 echo "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
625 echo "<a href='".
626 makeHrefProcess(array(
627 'op'=>'unlinkEntities',
628 'link_id'=>$link_id,
629 'object_id'=>$object_id,
630 'page='=>'object',
631 'tab'=>'edit')).
632 "'>";
633 printImageHREF ('cut', 'Unlink container');
634 echo "</a>";
635 echo "</td></tr>\n";
636 $label = '&nbsp;';
637 }
638 echo "<tr><td>&nbsp;</td>";
639 echo "<th class=tdright>Select container:</th><td class=tdleft>";
640 echo "<span";
641 $helper_args = array ('object_id' => $object_id);
642 $popup_args = 'height=700, width=400, location=no, menubar=no, '.
643 'resizable=yes, scrollbars=yes, status=no, titlebar=no, toolbar=no';
644 echo " onclick='window.open(\"" . makeHrefForHelper ('objlist', $helper_args);
645 echo "\",\"findlink\",\"${popup_args}\");'>";
646 printImageHREF ('attach', 'Select a container');
647 echo "</span></td></tr>\n";
648 }
cdd3efe9 649 // optional attributes
e673ee24 650 $values = getAttrValues ($object_id);
0f63538a 651 echo '<input type=hidden name=num_attrs value=' . count($values) . ">\n";
2b98d5a2 652 if (count($values) > 0)
e673ee24 653 {
2b98d5a2
AD
654 $i = 0;
655 foreach ($values as $record)
e673ee24 656 {
2b98d5a2
AD
657 echo "<input type=hidden name=${i}_attr_id value=${record['id']}>";
658 echo '<tr><td>';
59a83bd8 659 if (strlen ($record['value']))
2b98d5a2 660 {
4fbb5a00 661 echo "<a href='".makeHrefProcess(array('op'=>'clearSticker', 'object_id'=>$object_id, 'attr_id'=>$record['id']))."'>";
2b98d5a2
AD
662 printImageHREF ('clear', 'Clear value');
663 echo '</a>';
664 }
665 else
666 echo '&nbsp;';
667 echo '</td>';
e10f583a 668 echo "<th class=sticker>${record['name']}:</th><td class=tdleft>";
2b98d5a2
AD
669 switch ($record['type'])
670 {
671 case 'uint':
672 case 'float':
673 case 'string':
674 echo "<input type=text name=${i}_value value='${record['value']}'>";
675 break;
676 case 'dict':
7fa7047a 677 $chapter = readChapter ($record['chapter_id'], 'o');
2b98d5a2 678 $chapter[0] = '-- NOT SET --';
f3d274bf 679 $chapter = cookOptgroups ($chapter, $object['objtype_id'], $record['key']);
cd3775e9 680 printNiftySelect ($chapter, array ('name' => "${i}_value"), $record['key']);
2b98d5a2 681 break;
86ff26ae
DO
682 case 'date':
683 $date_value = $record['value'] ? date(getConfigVar('DATETIME_FORMAT'), $record['value']) : '';
684 echo "<input type=text name=${i}_value value='${date_value}'>";
685 break;
2b98d5a2
AD
686 }
687 echo "</td></tr>\n";
688 $i++;
e673ee24 689 }
e673ee24 690 }
e10f583a
DO
691 echo "<tr><td>&nbsp;</td><th class=tdright>Has problems:</th><td class=tdleft><input type=checkbox name=object_has_problems";
692 if ($object['has_problems'] == 'yes')
693 echo ' checked';
694 echo "></td></tr>\n";
abd1e9ac
DO
695 echo "<tr><td>&nbsp;</td><th class=tdright>Actions:</th><td class=tdleft>";
696 echo "<a href='".
3067f362 697 makeHrefProcess(array('op'=>'deleteObject', 'page'=>'depot', 'tab'=>'addmore', 'object_id'=>$object_id)).
abd1e9ac
DO
698 "' onclick=\"javascript:return confirm('Are you sure you want to delete the object?')\">" . getImageHREF ('destroy', 'Delete object') . "</a>";
699 echo "&nbsp;";
700 echo "<a href='".
701 makeHrefProcess(array ('op'=>'resetObject', 'page' => 'object', 'tab' => 'edit', 'object_id' => $object_id)).
702 "' onclick=\"javascript:return confirm('Are you sure you want to reset most of object properties?')\">" . getImageHREF ('clear', 'Reset (cleanup) object') . "</a>";
703 echo "</td></tr>\n";
e10f583a 704 echo "<tr><td colspan=3><b>Comment:</b><br><textarea name=object_comment rows=10 cols=80>${object['comment']}</textarea></td></tr>";
cdd3efe9 705
e10f583a 706 echo "<tr><th class=submit colspan=3>";
5bbbeaa2 707 printImageHREF ('SAVE', 'Save changes', TRUE);
cdd3efe9 708 echo "</form></th></tr></table>\n";
e673ee24 709 finishPortlet();
e673ee24 710
cdd3efe9 711 echo '<table border=0 width=100%><tr><td>';
e673ee24 712 startPortlet ('history');
9b8174d7 713 renderObjectHistory ($object_id);
e673ee24 714 finishPortlet();
cdd3efe9 715 echo '</td></tr></table>';
e673ee24
DO
716}
717
718// This is a clone of renderEditObjectForm().
719function renderEditRackForm ($rack_id)
720{
0c2b7c4a 721 global $pageno;
61a1d996
DO
722 $rack = spotEntity ('rack', $rack_id);
723 amplifyCell ($rack);
e673ee24 724
9b8174d7 725 startPortlet ('Attributes');
7056988c 726 printOpFormIntro ('updateRack');
e673ee24 727 echo '<table border=0 align=center>';
9b8174d7
AD
728 echo "<tr><td>&nbsp;</td><th class=tdright>Rack row:</th><td class=tdleft>";
729 printSelect (getRows(), array ('name' => 'row_id'), $rack['row_id']);
e673ee24 730 echo "</td></tr>\n";
9b8174d7
AD
731 echo "<tr><td>&nbsp;</td><th class=tdright>Name (required):</th><td class=tdleft><input type=text name=name value='${rack['name']}'></td></tr>\n";
732 echo "<tr><td>&nbsp;</td><th class=tdright>Height (required):</th><td class=tdleft><input type=text name=height value='${rack['height']}'></td></tr>\n";
9b8174d7
AD
733 echo "<tr><td>&nbsp;</td><th class=tdright>Asset tag:</th><td class=tdleft><input type=text name=asset_no value='${rack['asset_no']}'></td></tr>\n";
734 // optional attributes
735 $values = getAttrValues ($rack_id);
736 $num_attrs = count($values);
737 $num_attrs = $num_attrs-1; // subtract for the 'height' attribute
738 echo "<input type=hidden name=num_attrs value=${num_attrs}>\n";
739 $i = 0;
740 foreach ($values as $record)
741 {
742 // Skip the 'height' attribute as it's already displayed as a required field
743 if ($record['id'] == 27)
744 continue;
745 echo "<input type=hidden name=${i}_attr_id value=${record['id']}>";
746 echo '<tr><td>';
747 if (strlen ($record['value']))
748 {
749 echo "<a href='".makeHrefProcess(array('op'=>'clearSticker', 'rack_id'=>$rack_id, 'attr_id'=>$record['id']))."'>";
750 printImageHREF ('clear', 'Clear value');
751 echo '</a>';
752 }
753 else
754 echo '&nbsp;';
755 echo '</td>';
756 echo "<th class=sticker>${record['name']}:</th><td class=tdleft>";
757 switch ($record['type'])
758 {
759 case 'uint':
760 case 'float':
761 case 'string':
762 echo "<input type=text name=${i}_value value='${record['value']}'>";
763 break;
764 case 'dict':
765 $chapter = readChapter ($record['chapter_id'], 'o');
766 $chapter[0] = '-- NOT SET --';
767 $chapter = cookOptgroups ($chapter, 1560, $record['key']);
768 printNiftySelect ($chapter, array ('name' => "${i}_value"), $record['key']);
769 break;
770 }
771 echo "</td></tr>\n";
772 $i++;
773 }
774 echo "<tr><td>&nbsp;</td><th class=tdright>Has problems:</th><td class=tdleft><input type=checkbox name=has_problems";
775 if ($rack['has_problems'] == 'yes')
776 echo ' checked';
777 echo "></td></tr>\n";
c8187437
DY
778 if (count ($rack['mountedObjects']) == 0)
779 {
9b8174d7
AD
780 echo "<tr><td>&nbsp;</td><th class=tdright>Actions:</th><td class=tdleft>";
781 echo "<a href='".
782 makeHrefProcess(array('op'=>'deleteRack', 'rack_id'=>$rack_id)).
783 "' onclick=\"javascript:return confirm('Are you sure you want to delete the rack?')\">" . getImageHREF ('destroy', 'Delete rack') . "</a>";
784 echo "&nbsp;</td></tr>\n";
c8187437 785 }
9b8174d7
AD
786 echo "<tr><td colspan=3><b>Comment:</b><br><textarea name=comment rows=10 cols=80>${rack['comment']}</textarea></td></tr>";
787 echo "<tr><td class=submit colspan=3>";
7056988c
DO
788 printImageHREF ('SAVE', 'Save changes', TRUE);
789 echo "</td></tr>\n";
e673ee24
DO
790 echo '</form></table><br>';
791 finishPortlet();
792
793 startPortlet ('History');
9b8174d7 794 renderObjectHistory ($rack_id);
e673ee24
DO
795 finishPortlet();
796}
797
254673dd
DO
798// used by renderGridForm() and renderRackPage()
799function renderRackInfoPortlet ($rackData)
800{
646272be
AA
801 $summary = array();
802 $summary['Rack row'] = $rackData['row_name'];
803 $summary['Name'] = $rackData['name'];
804 $summary['Height'] = $rackData['height'];
9b8174d7 805 if (strlen ($rackData['asset_no']))
646272be 806 $summary['Asset tag'] = $rackData['asset_no'];
9b8174d7 807 if ($rackData['has_problems'] == 'yes')
646272be 808 $summary[] = array ('<tr><td colspan=2 class=msg_error>Has problems</td></tr>');
9b8174d7
AD
809 // Display populated attributes, but skip Height since it's already displayed above
810 foreach (getAttrValues ($rackData['id']) as $record)
811 if ($record['id'] != 27 && strlen ($record['value']))
646272be
AA
812 $summary['{sticker}' . $record['name']] = formatAttributeValue ($record);
813 $summary['% used'] = getProgressBar (getRSUforRack ($rackData));
814 $summary['Objects'] = count ($rackData['mountedObjects']);
815 $summary['tags'] = '';
59a83bd8 816 if (strlen ($rackData['comment']))
646272be
AA
817 $summary['Comment'] = $rackData['comment'];
818 renderEntitySummary ($rackData, 'summary', $summary);
254673dd
DO
819}
820
e673ee24 821// This is a universal editor of rack design/waste.
7056988c 822// FIXME: switch to using printOpFormIntro()
7e1db771 823function renderGridForm ($rack_id, $filter, $header, $submit, $state1, $state2)
e673ee24 824{
61a1d996
DO
825 $rackData = spotEntity ('rack', $rack_id);
826 amplifyCell ($rackData);
254673dd 827 $filter ($rackData);
e673ee24
DO
828 markupObjectProblems ($rackData);
829
e673ee24
DO
830 // Render the result whatever it is.
831 // Main layout.
832 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
833 echo "<tr><td colspan=2 align=center><h1>${rackData['name']}</h1></td></tr>\n";
834
835 // Left column with information portlet.
836 echo "<tr><td class=pcleft height='1%' width='50%'>";
254673dd 837 renderRackInfoPortlet ($rackData);
e673ee24 838 echo "</td>\n";
bb09cca0 839 echo "<td class=pcright>";
e673ee24
DO
840
841 // Grid form.
842 startPortlet ($header);
65e557dd 843 addJS ('js/racktables.js');
e673ee24
DO
844 echo "<center>\n";
845 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
57c69e9c 846 echo "<tr><th width='10%'>&nbsp;</th>";
bd0bfb76
AD
847 echo "<th width='20%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '0', ${rackData['height']})\">Front</a></th>";
848 echo "<th width='50%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '1', ${rackData['height']})\">Interior</a></th>";
849 echo "<th width='20%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '2', ${rackData['height']})\">Back</a></th></tr>\n";
4fbb5a00 850 printOpFormIntro ('updateRack');
e673ee24
DO
851 markupAtomGrid ($rackData, $state2);
852 renderAtomGrid ($rackData);
853 echo "</table></center>\n";
854 echo "<br><input type=submit name=do_update value='${submit}'></form><br><br>\n";
855 finishPortlet();
bb09cca0 856 echo "</td></tr></table>\n";
e673ee24
DO
857}
858
859function renderRackDesign ($rack_id)
860{
bb09cca0 861 renderGridForm ($rack_id, 'applyRackDesignMask', 'Rack design', 'Set rack design', 'A', 'F');
e673ee24
DO
862}
863
7e1db771 864function renderRackProblems ($rack_id)
e673ee24 865{
bb09cca0 866 renderGridForm ($rack_id, 'applyRackProblemMask', 'Rack problems', 'Mark unusable atoms', 'F', 'U');
e673ee24
DO
867}
868
40c9fc94
AA
869function renderObjectPortRow ($port, $is_highlighted)
870{
871 echo '<tr';
872 if ($is_highlighted)
873 echo ' class=port_highlight';
874 $a_class = isEthernetPort ($port) ? 'port-menu' : '';
875 echo "><td class='tdleft' NOWRAP><a name='port-${port['id']}' class='ancor interactive-portname nolink $a_class'>${port['name']}</a></td>";
876 echo "<td class=tdleft>${port['label']}</td>";
877 echo "<td class=tdleft>" . formatPortIIFOIF ($port) . "</td><td class=tdleft><tt>${port['l2address']}</tt></td>";
878 if ($port['remote_object_id'])
879 {
880 echo "<td class=tdleft>" .
881 formatPortLink ($port['remote_object_id'], $port['remote_object_name'], $port['remote_id'], NULL) .
882 "</td>";
883 echo "<td class=tdleft>" . formatLoggedSpan ($port['last_log'], $port['remote_name'], 'underline') . "</td>";
0b8d8309
AA
884 $editable = permitted ('object', 'ports', 'editPort')
885 ? 'editable'
886 : '';
887 echo "<td class=tdleft><span class='rsvtext $editable id-${port['id']} op-upd-reservation-cable'>${port['cableid']}</span></td>";
40c9fc94
AA
888 }
889 else
890 echo implode ('', formatPortReservation ($port)) . '<td></td>';
891 echo "</tr>";
892}
893
9b8174d7 894function renderObject ($object_id)
e673ee24 895{
8dc2a6c8 896 global $nextorder, $virtual_obj_types;
fb6e2f57 897 $info = spotEntity ('object', $object_id);
94fe6370 898 amplifyCell ($info);
e673ee24
DO
899 // Main layout starts.
900 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
901 echo "<tr><td colspan=2 align=center><h1>${info['dname']}</h1></td></tr>\n";
902 // left column with uknown number of portlets
903 echo "<tr><td class=pcleft>";
646272be
AA
904
905 // display summary portlet
906 $summary = array();
59a83bd8 907 if (strlen ($info['name']))
646272be 908 $summary['Common name'] = $info['name'];
94fe6370 909 elseif (considerConfiguredConstraint ($info, 'NAMEWARN_LISTSRC'))
646272be
AA
910 $summary[] = array ('<tr><td colspan=2 class=msg_error>Common name is missing.</td></tr>');
911 $summary['Object type'] = '<a href="' . makeHref (array (
341fd895
DO
912 'page' => 'depot',
913 'tab' => 'default',
914 'cfe' => '{$typeid_' . $info['objtype_id'] . '}'
646272be 915 )) . '">' . decodeObjectType ($info['objtype_id'], 'o') . '</a>';
9b8174d7 916 if (strlen ($info['label']))
646272be 917 $summary['Visible label'] = $info['label'];
59a83bd8 918 if (strlen ($info['asset_no']))
646272be 919 $summary['Asset tag'] = $info['asset_no'];
d4e8ddeb 920 elseif (considerConfiguredConstraint ($info, 'ASSETWARN_LISTSRC'))
646272be
AA
921 $summary[] = array ('<tr><td colspan=2 class=msg_error>Asset tag is missing.</td></tr>');
922 $parents = getEntityRelatives ('parents', 'object', $object_id);
923 if (count ($parents))
0682218d 924 {
646272be 925 $fmt_parents = array();
0682218d 926 foreach ($parents as $parent)
8023ee39
AA
927 $fmt_parents[] = "<a href='".makeHref(array('page'=>$parent['page'], $parent['id_name'] => $parent['entity_id']))."'>${parent['name']}</a>";
928 $summary[count($parents) > 1 ? 'Containers' : 'Container'] = implode ('<br>', $fmt_parents);
0682218d 929 }
646272be
AA
930 $children = getEntityRelatives ('children', 'object', $object_id);
931 if (count ($children))
0682218d 932 {
646272be 933 $fmt_children = array();
0682218d 934 foreach ($children as $child)
8023ee39 935 $fmt_children[] = "<a href='".makeHref(array('page'=>$child['page'], $child['id_name']=>$child['entity_id']))."'>${child['name']}</a>";
dcde9835 936 $summary['Contains'] = implode ('<br>', $fmt_children);
0682218d 937 }
e673ee24 938 if ($info['has_problems'] == 'yes')
646272be 939 $summary[] = array ('<tr><td colspan=2 class=msg_error>Has problems</td></tr>');
8ad59489 940 foreach (getAttrValues ($object_id) as $record)
4969aa31
DO
941 if
942 (
943 strlen ($record['value']) and
944 permitted (NULL, NULL, NULL, array (array ('tag' => '$attr_' . $record['id'])))
945 )
646272be 946 $summary['{sticker}' . $record['name']] = formatAttributeValue ($record);
a2c597ea
AA
947 $summary[] = array (getOutputOf ('printTagTRs',
948 $info,
949 makeHref
950 (
951 array
952 (
953 'page'=>'depot',
954 'tab'=>'default',
955 'andor' => 'and',
956 'cfe' => '{$typeid_' . $info['objtype_id'] . '}',
957 )
958 )."&"
959 ));
646272be 960 renderEntitySummary ($info, 'summary', $summary);
e673ee24 961
59a83bd8 962 if (strlen ($info['comment']))
e673ee24
DO
963 {
964 startPortlet ('Comment');
6cc5d6cd 965 echo '<div class=commentblock>' . string_insert_hrefs ($info['comment']) . '</div>';
e673ee24
DO
966 finishPortlet ();
967 }
968
b5700329
AA
969 $logrecords = getLogRecordsForObject ($_REQUEST['object_id']);
970 if (count ($logrecords))
9a90adc4
DO
971 {
972 startPortlet ('log records');
973 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable width='100%'>";
974 $order = 'odd';
b5700329 975 foreach ($logrecords as $row)
9a90adc4
DO
976 {
977 echo "<tr class=row_${order} valign=top>";
978 echo '<td class=tdleft>' . $row['date'] . '<br>' . $row['user'] . '</td>';
0b8d8309 979 echo '<td class="logentry">' . string_insert_hrefs (htmlspecialchars ($row['content'], ENT_NOQUOTES)) . '</td>';
9a90adc4
DO
980 echo '</tr>';
981 $order = $nextorder[$order];
982 }
983 echo '</table>';
984 finishPortlet();
985 }
986
65e557dd 987 switchportInfoJS ($object_id); // load JS code to make portnames interactive
e1ae3fb4
AD
988 renderFilesPortlet ('object', $object_id);
989
9f75e165 990 if (count ($info['ports']))
e673ee24 991 {
0ab782bc 992 startPortlet ('ports and links');
9f75e165
DO
993 $hl_port_id = 0;
994 if (isset ($_REQUEST['hl_port_id']))
e673ee24 995 {
0cc24e9a 996 assertUIntArg ('hl_port_id');
9f75e165 997 $hl_port_id = $_REQUEST['hl_port_id'];
65e557dd 998 addAutoScrollScript ("port-$hl_port_id");
9f75e165
DO
999 }
1000 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>";
1001 echo '<tr><th class=tdleft>Local name</th><th class=tdleft>Visible label</th>';
0d59a51c 1002 echo '<th class=tdleft>Interface</th><th class=tdleft>L2 address</th>';
0c7c9f8b
DO
1003 echo '<th class=tdcenter colspan=2>Remote object and port</th>';
1004 echo '<th class=tdleft>Cable ID</th></tr>';
9f75e165 1005 foreach ($info['ports'] as $port)
40c9fc94 1006 callHook ('renderObjectPortRow', $port, ($hl_port_id == $port['id']));
fd5edda8 1007 if (permitted (NULL, 'ports', 'set_reserve_comment'))
a8dc2982 1008 addJS ('js/inplace-edit.js');
9f75e165 1009 echo "</table><br>";
e673ee24
DO
1010 finishPortlet();
1011 }
85970da2 1012
21ee3351 1013 if (count ($info['ipv4']) + count ($info['ipv6']))
e673ee24 1014 {
21ee3351 1015 startPortlet ('IP addresses');
e673ee24 1016 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
f0ed1181 1017 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
0b9c98d7 1018 echo "<tr><th>OS interface</th><th>IP address</th><th>network</th><th>routed by</th><th>peers</th></tr>\n";
83fdf85f
DO
1019 else
1020 echo "<tr><th>OS interface</th><th>IP address</th><th>peers</th></tr>\n";
21ee3351
AA
1021
1022 // group IP allocations by interface name instead of address family
1023 $allocs_by_iface = array();
1024 foreach (array ('ipv4', 'ipv6') as $ip_v)
4318ced5
AA
1025 foreach ($info[$ip_v] as $ip_bin => $alloc)
1026 $allocs_by_iface[$alloc['osif']][$ip_bin] = $alloc;
21ee3351
AA
1027
1028 // sort allocs array by portnames
1029 foreach (sortPortList ($allocs_by_iface) as $iface_name => $alloclist)
1030 {
1031 $is_first_row = TRUE;
f3505b35 1032 foreach ($alloclist as $alloc)
b90c3907 1033 {
40c9fc94 1034 $rendered_alloc = callHook ('getRenderedAlloc', $object_id, $alloc);
f3505b35 1035 echo "<tr class='${rendered_alloc['tr_class']}' valign=top>";
21ee3351 1036
f3505b35 1037 // display iface name, same values are grouped into single cell
21ee3351
AA
1038 if ($is_first_row)
1039 {
1040 $rowspan = count ($alloclist) > 1 ? 'rowspan="' . count ($alloclist) . '"' : '';
40c9fc94 1041 echo "<td class=tdleft $rowspan>" . $iface_name . $rendered_alloc['td_name_suffix'] . "</td>";
21ee3351
AA
1042 $is_first_row = FALSE;
1043 }
f3505b35 1044 echo $rendered_alloc['td_ip'];
21ee3351 1045 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
83fdf85f 1046 {
f3505b35
AA
1047 echo $rendered_alloc['td_network'];
1048 echo $rendered_alloc['td_routed_by'];
21ee3351 1049 }
f3505b35
AA
1050 echo $rendered_alloc['td_peers'];
1051
1052 echo "</tr>\n";
b90c3907 1053 }
e673ee24
DO
1054 }
1055 echo "</table><br>\n";
1056 finishPortlet();
1057 }
1058
94fe6370 1059 $forwards = $info['nat4'];
e673ee24
DO
1060 if (count($forwards['in']) or count($forwards['out']))
1061 {
f28fbe8b 1062 startPortlet('NATv4');
e673ee24
DO
1063
1064 if (count($forwards['out']))
1065 {
1066
f28fbe8b 1067 echo "<h3>locally performed NAT</h3>";
e673ee24 1068
105a3bc8 1069 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
f28fbe8b 1070 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
1071
1072 foreach ($forwards['out'] as $pf)
1073 {
2c817354
DO
1074 $class = 'trerror';
1075 $osif = '';
1076 if (isset ($alloclist [$pf['localip']]))
1077 {
1078 $class = $alloclist [$pf['localip']]['addrinfo']['class'];
1079 $osif = $alloclist [$pf['localip']]['osif'] . ': ';
1080 }
e673ee24 1081 echo "<tr class='$class'>";
4fbb5a00
DY
1082 echo "<td>${pf['proto']}</td><td class=tdleft>${osif}<a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['localip']))."'>${pf['localip']}</a>:${pf['localport']}</td>";
1083 echo "<td class=tdleft><a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['remoteip']))."'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
4318ced5 1084 $address = getIPAddress (ip4_parse ($pf['remoteip']));
e673ee24 1085 echo "<td class='description'>";
53ef3908
DO
1086 if (count ($address['allocs']))
1087 foreach($address['allocs'] as $bond)
4fbb5a00 1088 echo "<a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$bond['object_id']))."'>${bond['object_name']}(${bond['name']})</a> ";
59a83bd8 1089 elseif (strlen ($pf['remote_addr_name']))
f28fbe8b 1090 echo '(' . $pf['remote_addr_name'] . ')';
53ef3908 1091 echo "</td><td class='description'>${pf['description']}</td></tr>";
e673ee24
DO
1092 }
1093 echo "</table><br><br>";
1094 }
1095 if (count($forwards['in']))
1096 {
f28fbe8b 1097 echo "<h3>arriving NAT connections</h3>";
105a3bc8 1098 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
f28fbe8b 1099 echo "<tr><th>Matched endpoint</th><th>Source object</th><th>Translated to</th><th>Rule comment</th></tr>\n";
e673ee24
DO
1100 foreach ($forwards['in'] as $pf)
1101 {
1102 echo "<tr>";
4fbb5a00
DY
1103 echo "<td>${pf['proto']}/<a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['localip']))."'>${pf['localip']}</a>:${pf['localport']}</td>";
1104 echo "<td class='description'><a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$pf['object_id']))."'>${pf['object_name']}</a>";
1105 echo "</td><td><a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['remoteip']))."'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
e673ee24
DO
1106 echo "<td class='description'>${pf['description']}</td></tr>";
1107 }
e673ee24
DO
1108 echo "</table><br><br>";
1109 }
1110 finishPortlet();
1111 }
1112
defd92d8 1113 renderSLBTriplets ($info);
e673ee24
DO
1114 echo "</td>\n";
1115
7056988c 1116 // After left column we have (surprise!) right column with rackspace portlet only.
e673ee24 1117 echo "<td class=pcright>";
8dc2a6c8 1118 if (!in_array($info['objtype_id'], $virtual_obj_types))
0682218d
AD
1119 {
1120 // rackspace portlet
1121 startPortlet ('rackspace allocation');
1122 foreach (getResidentRacksData ($object_id, FALSE) as $rack_id)
1123 renderRack ($rack_id, $object_id);
1124 echo '<br>';
1125 finishPortlet();
1126 }
e673ee24
DO
1127 echo "</td></tr>";
1128 echo "</table>\n";
1129}
1130
1131function renderRackMultiSelect ($sname, $racks, $selected)
1132{
04571888
DO
1133 // Transform the given flat list into a list of groups, each representing a rack row.
1134 $rdata = array();
e673ee24 1135 foreach ($racks as $rack)
04571888
DO
1136 if (!isset ($rdata[$rack['row_name']]))
1137 $rdata[$rack['row_name']] = array ($rack['id'] => $rack['name']);
1138 else
1139 $rdata[$rack['row_name']][$rack['id']] = $rack['name'];
4fbb5a00 1140 echo "<select name=${sname} multiple size=" . getConfigVar ('MAXSELSIZE') . " onchange='getElementsByName(\"updateObjectAllocation\")[0].submit()'>\n";
04571888 1141 foreach ($rdata as $optgroup => $racklist)
e673ee24 1142 {
04571888
DO
1143 echo "<optgroup label='${optgroup}'>";
1144 foreach ($racklist as $rack_id => $rack_name)
1145 {
1146 echo "<option value=${rack_id}";
1147 if (!(array_search ($rack_id, $selected) === FALSE))
1148 echo ' selected';
1149 echo">${rack_name}</option>\n";
1150 }
e673ee24
DO
1151 }
1152 echo "</select>\n";
1153}
1154
e673ee24 1155// This function renders a form for port edition.
7e1db771 1156function renderPortsForObject ($object_id)
e673ee24 1157{
3153a326
DO
1158 $prefs = getPortListPrefs();
1159 function printNewItemTR ($prefs)
39b4abd0
DO
1160 {
1161 printOpFormIntro ('addPort');
1162 echo "<tr><td>";
f5ff50f5 1163 printImageHREF ('add', 'add a port', TRUE);
65e557dd 1164 echo "</td><td class='tdleft'><input type=text size=8 name=port_name tabindex=100></td>\n";
cd3775e9
DO
1165 echo "<td><input type=text name=port_label tabindex=101></td><td>";
1166 printNiftySelect (getNewPortTypeOptions(), array ('name' => 'port_type_id', 'tabindex' => 102), $prefs['selected']);
1167 echo "<td><input type=text name=port_l2address tabindex=103 size=18 maxlength=24></td>\n";
318c48a8 1168 echo "<td colspan=4>&nbsp;</td><td>";
9318d2ef
DO
1169 printImageHREF ('add', 'add a port', TRUE, 104);
1170 echo "</td></tr></form>";
39b4abd0 1171 }
a1fc539a 1172 if (getConfigVar('ENABLE_MULTIPORT_FORM') == 'yes' || getConfigVar('ENABLE_BULKPORT_FORM') == 'yes' )
f44fdef9
DO
1173 startPortlet ('Ports and interfaces');
1174 else
1175 echo '<br>';
9f75e165
DO
1176 $object = spotEntity ('object', $object_id);
1177 amplifyCell ($object);
a1fc539a
RF
1178 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes' && getConfigVar('ENABLE_BULKPORT_FORM') == 'yes'){
1179 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
1180 echo "<tr><th>&nbsp;</th><th class=tdleft>Local name</th><th class=tdleft>Visible label</th><th class=tdleft>Interface</th><th class=tdleft>Start Number</th>";
1181 echo "<th class=tdleft>Count</th><th>&nbsp;</th></tr>\n";
1182 printOpFormIntro ('addBulkPorts');
1183 echo "<tr><td>";
1184 printImageHREF ('add', 'add ports', TRUE);
1185 echo "</td><td><input type=text size=8 name=port_name tabindex=105></td>\n";
1186 echo "<td><input type=text name=port_label tabindex=106></td><td>";
1187 printNiftySelect (getNewPortTypeOptions(), array ('name' => 'port_type_id', 'tabindex' => 107), $prefs['selected']);
1188 echo "<td><input type=text name=port_numbering_start tabindex=108 size=3 maxlength=3></td>\n";
1189 echo "<td><input type=text name=port_numbering_count tabindex=109 size=3 maxlength=3></td>\n";
1190 echo "<td>&nbsp;</td><td>";
1191 printImageHREF ('add', 'add ports', TRUE, 110);
1192 echo "</td></tr></form>";
1193 echo "</table><br>\n";
1194 }
1195
e673ee24 1196 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
0d59a51c 1197 echo "<tr><th>&nbsp;</th><th class=tdleft>Local name</th><th class=tdleft>Visible label</th><th class=tdleft>Interface</th><th class=tdleft>L2 address</th>";
318c48a8 1198 echo "<th class=tdcenter colspan=2>Remote object and port</th><th>Cable ID</th><th class=tdcenter>(Un)link or (un)reserve</th><th>&nbsp;</th></tr>\n";
39b4abd0 1199 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
3153a326 1200 printNewItemTR ($prefs);
45ff9012
AA
1201
1202 // clear ports link
1203 echo "<a href='".
1204 makeHrefProcess(array ('op'=>'deleteAll', 'page' => 'object', 'tab' => 'ports', 'object_id' => $object_id)).
1205 "' onclick=\"javascript:return confirm('Are you sure you want to delete all existing ports?')\">" . getImageHREF ('clear', 'Clear port list') . " Clear port list</a>";
1206
00276508
AA
1207 if (isset ($_REQUEST['hl_port_id']))
1208 {
1209 assertUIntArg ('hl_port_id');
1210 $hl_port_id = intval ($_REQUEST['hl_port_id']);
65e557dd 1211 addAutoScrollScript ("port-$hl_port_id");
00276508 1212 }
65e557dd 1213 switchportInfoJS ($object_id); // load JS code to make portnames interactive
9f75e165 1214 foreach ($object['ports'] as $port)
e673ee24 1215 {
00276508 1216 $tr_class = isset ($hl_port_id) && $hl_port_id == $port['id'] ? 'class="port_highlight"' : '';
7056988c 1217 printOpFormIntro ('editPort', array ('port_id' => $port['id']));
10005279 1218 echo "<tr $tr_class><td><a name='port-${port['id']}' href='".makeHrefProcess(array('op'=>'delPort', 'port_id'=>$port['id'], 'object_id'=>$object_id))."'>";
e673ee24
DO
1219 printImageHREF ('delete', 'Unlink and Delete this port');
1220 echo "</a></td>\n";
65e557dd
AA
1221 $a_class = isEthernetPort ($port) ? 'port-menu' : '';
1222 echo "<td class='tdleft' NOWRAP><input type=text name=name class='interactive-portname $a_class' value='${port['name']}' size=8></td>";
cd3775e9 1223 echo "<td><input type=text name=label value='${port['label']}'></td>";
611170af
AD
1224 if (!$port['remote_object_id'])
1225 {
3153a326
DO
1226 echo '<td>';
1227 if ($port['iif_id'] != 1)
1228 echo '<label>' . $port['iif_name'] . ' ';
cd3775e9 1229 printSelect (getExistingPortTypeOptions ($port['id']), array ('name' => 'port_type_id'), $port['oif_id']);
3153a326
DO
1230 if ($port['iif_id'] != 1)
1231 echo '</label>';
1232 echo '</td>';
611170af
AD
1233 }
1234 else
1235 {
045bab87 1236 echo "<input type=hidden name=port_type_id value='${port['oif_id']}'><td class=tdleft>";
e9d357e1 1237 echo formatPortIIFOIF ($port) . '</td>';
611170af 1238 }
cd3775e9
DO
1239 // 18 is enough to fit 6-byte MAC address in its longest form,
1240 // while 24 should be Ok for WWN
1241 echo "<td><input type=text name=l2address value='${port['l2address']}' size=18 maxlength=24></td>\n";
e673ee24
DO
1242 if ($port['remote_object_id'])
1243 {
318c48a8 1244 echo "<td>" .
a2ea559e 1245 formatLoggedSpan ($port['last_log'], formatPortLink ($port['remote_object_id'], $port['remote_object_name'], $port['remote_id'], NULL)) .
5c6225b1
AA
1246 "</td>";
1247 echo "<td> " . formatLoggedSpan ($port['last_log'], $port['remote_name'], 'underline') .
1248 "<input type=hidden name=reservation_comment value=''></td>";
318c48a8 1249 echo "<td><input type=text name=cable value='${port['cableid']}'></td>";
3153a326 1250 echo "<td class=tdcenter><a href='".
4fbb5a00
DY
1251 makeHrefProcess(array(
1252 'op'=>'unlinkPort',
cd3775e9 1253 'port_id'=>$port['id'],
cd3775e9 1254 'object_id'=>$object_id)).
4fbb5a00 1255 "'>";
5ccd99a0 1256 printImageHREF ('cut', 'Unlink this port');
e673ee24
DO
1257 echo "</a></td>";
1258 }
59a83bd8 1259 elseif (strlen ($port['reservation_comment']))
e673ee24 1260 {
5c6225b1 1261 echo "<td>" . formatLoggedSpan ($port['last_log'], 'Reserved:', 'strong underline') . "</td>";
e673ee24 1262 echo "<td><input type=text name=reservation_comment value='${port['reservation_comment']}'></td>";
318c48a8 1263 echo "<td></td>";
3153a326 1264 echo "<td class=tdcenter><a href='".
4fbb5a00
DY
1265 makeHrefProcess(array(
1266 'op'=>'useup',
1267 'port_id'=>$port['id'],
1268 'object_id'=>$object_id)).
1269 "'>";
39be655e 1270 printImageHREF ('clear', 'Use up this port');
e673ee24
DO
1271 echo "</a></td>";
1272 }
1273 else
1274 {
318c48a8 1275 echo "<td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td class=tdcenter><span";
cd3775e9
DO
1276 $helper_args = array
1277 (
1278 'port' => $port['id'],
cd3775e9
DO
1279 );
1280 $popup_args = 'height=700, width=400, location=no, menubar=no, '.
9e214652 1281 'resizable=yes, scrollbars=yes, status=no, titlebar=no, toolbar=no';
cd3775e9
DO
1282 echo " ondblclick='window.open(\"" . makeHrefForHelper ('portlist', $helper_args);
1283 echo "\",\"findlink\",\"${popup_args}\");'";
1284 // end of onclick=
cd3775e9
DO
1285 echo " onclick='window.open(\"" . makeHrefForHelper ('portlist', $helper_args);
1286 echo "\",\"findlink\",\"${popup_args}\");'";
1287 // end of onclick=
1288 echo '>';
1289 // end of <a>
5ccd99a0 1290 printImageHREF ('plug', 'Link this port');
cd3775e9
DO
1291 echo "</span>";
1292 echo " <input type=text name=reservation_comment></td>\n";
e673ee24 1293 }
5bbbeaa2
DO
1294 echo "<td>";
1295 printImageHREF ('save', 'Save changes', TRUE);
1296 echo "</td></form></tr>\n";
e673ee24 1297 }
39b4abd0 1298 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
3153a326 1299 printNewItemTR ($prefs);
e673ee24 1300 echo "</table><br>\n";
a1fc539a
RF
1301 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes' && getConfigVar('ENABLE_BULKPORT_FORM') == 'yes'){
1302 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
1303 echo "<tr><th>&nbsp;</th><th class=tdleft>Local name</th><th class=tdleft>Visible label</th><th class=tdleft>Interface</th><th class=tdleft>Start Number</th>";
1304 echo "<th class=tdleft>Count</th><th>&nbsp;</th></tr>\n";
1305 printOpFormIntro ('addBulkPorts');
1306 echo "<tr><td>";
1307 printImageHREF ('add', 'add ports', TRUE);
1308 echo "</td><td><input type=text size=8 name=port_name tabindex=105></td>\n";
1309 echo "<td><input type=text name=port_label tabindex=106></td><td>";
1310 printNiftySelect (getNewPortTypeOptions(), array ('name' => 'port_type_id', 'tabindex' => 107), $prefs['selected']);
1311 echo "<td><input type=text name=port_numbering_start tabindex=108 size=3 maxlength=3></td>\n";
1312 echo "<td><input type=text name=port_numbering_count tabindex=109 size=3 maxlength=3></td>\n";
1313 echo "<td>&nbsp;</td><td>";
1314 printImageHREF ('add', 'add ports', TRUE, 110);
1315 echo "</td></tr></form>";
1316 echo "</table><br>\n";
1317 }
f44fdef9
DO
1318 if (getConfigVar('ENABLE_MULTIPORT_FORM') == 'yes')
1319 finishPortlet();
1320 if (getConfigVar('ENABLE_MULTIPORT_FORM') != 'yes')
1321 return;
e673ee24
DO
1322
1323 startPortlet ('Add/update multiple ports');
7056988c 1324 printOpFormIntro ('addMultiPorts');
f7a3c94a 1325 echo 'Format: <select name=format tabindex=201>';
e673ee24
DO
1326 echo '<option value=c3600asy>Cisco 3600 async: sh line | inc TTY</option>';
1327 echo '<option value=fiwg selected>Foundry ServerIron/FastIron WorkGroup/Edge: sh int br</option>';
e673ee24 1328 echo '<option value=fisxii>Foundry FastIron SuperX/II4000: sh int br</option>';
351d4dbf 1329 echo '<option value=ssv1>SSV:&lt;interface name&gt; &lt;MAC address&gt;</option>';
e673ee24
DO
1330 echo "</select>";
1331 echo 'Default port type: ';
cd3775e9 1332 printNiftySelect (getNewPortTypeOptions(), array ('name' => 'port_type', 'tabindex' => 202), $prefs['selected']);
f7a3c94a
DO
1333 echo "<input type=submit value='Parse output' tabindex=204><br>\n";
1334 echo "<textarea name=input cols=100 rows=50 tabindex=203></textarea><br>\n";
e673ee24
DO
1335 echo '</form>';
1336 finishPortlet();
1337}
1338
4318ced5 1339function renderIPForObject ($object_id)
e673ee24 1340{
4318ced5 1341 function printNewItemTR ($default_type)
21ee3351
AA
1342 {
1343 global $aat;
4318ced5
AA
1344 printOpFormIntro ('add');
1345 echo "<tr><td>"; // left btn
1346 printImageHREF ('add', 'allocate', TRUE);
21ee3351 1347 echo "</td>";
4318ced5
AA
1348 echo "<td class=tdleft><input type='text' size='10' name='bond_name' tabindex=100></td>\n"; // if-name
1349 echo "<td class=tdleft><input type=text name='ip' tabindex=101></td>\n"; // IP
1350 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
1351 echo "<td colspan=2>&nbsp;</td>"; // network, routed by
1352 echo '<td>';
1353 printSelect ($aat, array ('name' => 'bond_type', 'tabindex' => 102), $default_type); // type
1354 echo "</td><td>&nbsp;</td><td>"; // misc
1355 printImageHREF ('add', 'allocate', TRUE, 103); // right btn
21ee3351
AA
1356 echo "</td></tr></form>";
1357 }
21ee3351
AA
1358 global $aat;
1359 startPortlet ('Allocations');
4318ced5
AA
1360 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'><tr>\n";
1361 echo '<th>&nbsp;</th>';
1362 echo '<th>OS interface</th>';
1363 echo '<th>IP address</th>';
21ee3351 1364 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
4318ced5
AA
1365 {
1366 echo '<th>network</th>';
1367 echo '<th>routed by</th>';
1368 }
1369 echo '<th>type</th>';
1370 echo '<th>misc</th>';
1371 echo '<th>&nbsp</th>';
1372 echo '</tr>';
21ee3351 1373
710ead7e
AA
1374 $alloc_list = ''; // most of the output is stored here
1375 $used_alloc_types = array();
4318ced5 1376 foreach (getObjectIPAllocations ($object_id) as $alloc)
21ee3351 1377 {
710ead7e
AA
1378 if (! isset ($used_alloc_types[$alloc['type']]))
1379 $used_alloc_types[$alloc['type']] = 0;
1380 $used_alloc_types[$alloc['type']]++;
1381
40c9fc94 1382 $rendered_alloc = callHook ('getRenderedAlloc', $object_id, $alloc);
4318ced5 1383 $alloc_list .= getOutputOf ('printOpFormIntro', 'upd', array ('ip' => $alloc['addrinfo']['ip']));
710ead7e 1384 $alloc_list .= "<tr class='${rendered_alloc['tr_class']}' valign=top>";
f3505b35 1385
710ead7e 1386 $alloc_list .= "<td><a href='" .
f3505b35
AA
1387 makeHrefProcess
1388 (
1389 array
1390 (
4318ced5 1391 'op' => 'del',
f3505b35
AA
1392 'ip' => $alloc['addrinfo']['ip'],
1393 'object_id' => $object_id
1394 )
1395 ) . "'>" .
1396 getImageHREF ('delete', 'Delete this IP address') .
1397 "</a></td>";
40c9fc94 1398 $alloc_list .= "<td class=tdleft><input type='text' name='bond_name' value='${alloc['osif']}' size=10>" . $rendered_alloc['td_name_suffix'] . "</td>";
710ead7e 1399 $alloc_list .= $rendered_alloc['td_ip'];
21ee3351
AA
1400 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
1401 {
710ead7e
AA
1402 $alloc_list .= $rendered_alloc['td_network'];
1403 $alloc_list .= $rendered_alloc['td_routed_by'];
21ee3351 1404 }
710ead7e
AA
1405 $alloc_list .= '<td>' . getSelect ($aat, array ('name' => 'bond_type'), $alloc['type']) . "</td>";
1406 $alloc_list .= $rendered_alloc['td_peers'];
1407 $alloc_list .= "<td>" .getImageHREF ('save', 'Save changes', TRUE) . "</td>";
f3505b35 1408
710ead7e 1409 $alloc_list .= "</form></tr>\n";
21ee3351 1410 }
710ead7e
AA
1411 asort ($used_alloc_types, SORT_NUMERIC);
1412 $most_popular_type = empty ($used_alloc_types) ? 'regular' : array_pop (array_keys ($used_alloc_types));
1413
1414 if ($list_on_top = (getConfigVar ('ADDNEW_AT_TOP') != 'yes'))
1415 echo $alloc_list;
4318ced5 1416 printNewItemTR ($most_popular_type);
710ead7e
AA
1417 if (! $list_on_top)
1418 echo $alloc_list;
21ee3351
AA
1419
1420 echo "</table><br>\n";
1421 finishPortlet();
f3505b35
AA
1422}
1423
08408472
AA
1424// This function is deprecated. Do not rely on its internals,
1425// it will probably be removed in the next major relese.
1426// Use new showError, showWarning, showSuccess functions.
a2b16202 1427// Log array is stored in global $log_messages. Its format is simple: plain ordered array
8ab645cf 1428// with values having keys 'c' (both message code and severity) and 'a' (sprintf arguments array)
1cb6adf5 1429function showMessageOrError ()
e673ee24 1430{
a2b16202
AA
1431 global $log_messages;
1432
1433 @session_start();
1434 if (isset ($_SESSION['log']))
1435 {
1436 $log_messages = array_merge ($_SESSION['log'], $log_messages);
1437 unset ($_SESSION['log']);
1438 }
1439 session_commit();
1440
1441 if (empty ($log_messages))
1cb6adf5 1442 return;
8ab645cf
AA
1443 $msginfo = array
1444 (
1445// records 0~99 with success messages
1446 0 => array ('code' => 'success', 'format' => '%s'),
1447 5 => array ('code' => 'success', 'format' => 'added record "%s" successfully'),
1448 6 => array ('code' => 'success', 'format' => 'updated record "%s" successfully'),
1449 7 => array ('code' => 'success', 'format' => 'deleted record "%s" successfully'),
1450 8 => array ('code' => 'success', 'format' => 'Port %s successfully linked with %s'),
1451 10 => array ('code' => 'success', 'format' => 'Added %u ports, updated %u ports, encountered %u errors.'),
1452 21 => array ('code' => 'success', 'format' => 'Generation complete'),
1453 26 => array ('code' => 'success', 'format' => 'updated %u records successfully'),
1454 37 => array ('code' => 'success', 'format' => 'added %u records successfully'),
1455 38 => array ('code' => 'success', 'format' => 'removed %u records successfully'),
8ab645cf
AA
1456 43 => array ('code' => 'success', 'format' => 'Saved successfully.'),
1457 44 => array ('code' => 'success', 'format' => '%s failures and %s successfull changes.'),
1458 48 => array ('code' => 'success', 'format' => 'added a record successfully'),
1459 49 => array ('code' => 'success', 'format' => 'deleted a record successfully'),
1460 51 => array ('code' => 'success', 'format' => 'updated a record successfully'),
1461 57 => array ('code' => 'success', 'format' => 'Reset complete'),
8ab645cf 1462 63 => array ('code' => 'success', 'format' => '%u change request(s) have been processed'),
8ab645cf
AA
1463 67 => array ('code' => 'success', 'format' => "Tag rolling done, %u objects involved"),
1464 71 => array ('code' => 'success', 'format' => 'File "%s" was linked successfully'),
1465 72 => array ('code' => 'success', 'format' => 'File was unlinked successfully'),
8ab645cf
AA
1466 82 => array ('code' => 'success', 'format' => "Bulk port creation was successful. %u ports created, %u failed"),
1467 87 => array ('code' => 'success', 'format' => '802.1Q recalculate: %d ports changed on %d switches'),
8628ae44 1468// records 100~199 with fatal error messages
8ab645cf
AA
1469 100 => array ('code' => 'error', 'format' => '%s'),
1470 109 => array ('code' => 'error', 'format' => 'failed updating a record'),
8ab645cf
AA
1471 131 => array ('code' => 'error', 'format' => 'invalid format requested'),
1472 141 => array ('code' => 'error', 'format' => 'Encountered %u errors, updated %u record(s)'),
1473 149 => array ('code' => 'error', 'format' => 'Turing test failed'),
1474 150 => array ('code' => 'error', 'format' => 'Can only change password under DB authentication.'),
1475 151 => array ('code' => 'error', 'format' => 'Old password doesn\'t match.'),
1476 152 => array ('code' => 'error', 'format' => 'New passwords don\'t match.'),
1477 154 => array ('code' => 'error', 'format' => "Verification error: %s"),
1478 155 => array ('code' => 'error', 'format' => 'Save failed.'),
1479 159 => array ('code' => 'error', 'format' => 'Permission denied moving port %s from VLAN%u to VLAN%u'),
1480 161 => array ('code' => 'error', 'format' => 'Endpoint not found. Please either set FQDN attribute or assign an IP address to the object.'),
1481 162 => array ('code' => 'error', 'format' => 'More than one IP address is assigned to this object, please configure FQDN attribute.'),
8ab645cf
AA
1482 170 => array ('code' => 'error', 'format' => 'There is no network for IP address "%s"'),
1483 172 => array ('code' => 'error', 'format' => 'Malformed request'),
1484 179 => array ('code' => 'error', 'format' => 'Expired form has been declined.'),
1485 188 => array ('code' => 'error', 'format' => "Fatal SNMP failure"),
1486 189 => array ('code' => 'error', 'format' => "Unknown OID '%s'"),
1487 191 => array ('code' => 'error', 'format' => "deploy was blocked due to conflicting configuration versions"),
f0ff4930 1488
8628ae44 1489// records 200~299 with warnings
8ab645cf
AA
1490 200 => array ('code' => 'warning', 'format' => '%s'),
1491 201 => array ('code' => 'warning', 'format' => 'nothing happened...'),
8ab645cf 1492 206 => array ('code' => 'warning', 'format' => 'Rack is not empty'),
7587edca 1493 207 => array ('code' => 'warning', 'format' => 'File upload failed, error: %s'),
57777e4a 1494
24d3182a 1495// records 300~399 with notices
8ab645cf 1496 300 => array ('code' => 'neutral', 'format' => '%s'),
24d3182a 1497
8ab645cf
AA
1498 );
1499 // Handle the arguments. Is there any better way to do it?
a2b16202 1500 foreach ($log_messages as $record)
8ab645cf
AA
1501 {
1502 if (!isset ($record['c']) or !isset ($msginfo[$record['c']]))
1503 {
41152018
AA
1504 $prefix = isset ($record['c']) ? $record['c'] . ': ' : '';
1505 echo "<div class=msg_neutral>(${prefix}this message was lost)</div>";
8ab645cf
AA
1506 continue;
1507 }
1508 if (isset ($record['a']))
1509 switch (count ($record['a']))
baf37d01 1510 {
8ab645cf
AA
1511 case 1:
1512 $msgtext = sprintf
1513 (
1514 $msginfo[$record['c']]['format'],
1515 $record['a'][0]
1516 );
1517 break;
1518 case 2:
1519 $msgtext = sprintf
1520 (
1521 $msginfo[$record['c']]['format'],
1522 $record['a'][0],
1523 $record['a'][1]
1524 );
1525 break;
1526 case 3:
1527 $msgtext = sprintf
1528 (
1529 $msginfo[$record['c']]['format'],
1530 $record['a'][0],
1531 $record['a'][1],
1532 $record['a'][2]
1533 );
1534 break;
1535 case 4:
1536 default:
1537 $msgtext = sprintf
1538 (
1539 $msginfo[$record['c']]['format'],
1540 $record['a'][0],
1541 $record['a'][1],
1542 $record['a'][2],
1543 $record['a'][3]
1544 );
1545 break;
baf37d01 1546 }
8ab645cf
AA
1547 else
1548 $msgtext = $msginfo[$record['c']]['format'];
1549 echo '<div class=msg_' . $msginfo[$record['c']]['code'] . ">${msgtext}</div>";
baf37d01 1550 }
a2b16202 1551 $log_messages = array();
e673ee24
DO
1552}
1553
65e557dd
AA
1554// renders two tables: port link status and learned MAC list
1555function renderPortsInfo($object_id)
1556{
1557 global $nextorder;
1558 echo "<table width='100%'><tr>";
1559
1560 if (permitted (NULL, NULL, 'get_link_status'))
1561 {
1562 try
1563 {
80019a2c 1564 $linkStatus = queryDevice ($object_id, 'getportstatus');
65e557dd
AA
1565 }
1566 catch (RackTablesError $e) {}
1567 if (! empty ($linkStatus))
1568 {
1569 echo "<td valign='top' width='50%'>";
1570 startPortlet('Link status');
1571 echo "<table width='80%' class='widetable' cellspacing=0 cellpadding='5px' align='center'><tr><th>Port<th>Link status<th>Link info</tr>";
1572 $order = 'even';
1573 foreach ($linkStatus as $pn => $link)
1574 {
1575 echo "<tr class='row_$order'>";
1576 $order = $nextorder[$order];
1577 echo '<td>' . $pn;
1578 echo '<td>' . $link['status'];
1579 $info = '';
1580 if (isset ($link['speed']))
1581 $info .= $link['speed'];
1582 if (isset ($link['duplex']))
1583 {
1584 if (! empty ($info))
1585 $info .= ', ';
1586 $info .= $link['duplex'];
1587 }
1588 echo '<td>' . $info;
1589 echo '</tr>';
1590 }
1591 echo "</table></td>";
1592 finishPortlet();
1593 }
1594 }
1595
1596 try
1597 {
80019a2c 1598 $macList = sortPortList (queryDevice ($object_id, 'getmaclist'));
65e557dd
AA
1599 }
1600 catch (RackTablesError $e) {}
1601 if (! empty ($macList))
1602 {
1603 echo "<td valign='top' width='50%'>";
1604 $rendered_macs = '';
1605 $mac_count = 0;
1606 $rendered_macs .= "<table width='80%' class='widetable' cellspacing=0 cellpadding='5px' align='center'><tr><th>MAC<th>Vlan<th>Port</tr>";
1607 $order = 'even';
1608 foreach ($macList as $pn => $list)
1609 {
1610 $order = $nextorder[$order];
1611 foreach ($list as $item)
1612 {
1613 ++$mac_count;
1614 $rendered_macs .= "<tr class='row_$order'>";
1615 $rendered_macs .= '<td style="font-family: monospace">' . $item['mac'];
1616 $rendered_macs .= '<td>' . $item['vid'];
1617 $rendered_macs .= '<td>' . $pn;
1618 $rendered_macs .= '</tr>';
1619 }
1620 }
1621 $rendered_macs .= "</table></td>";
1622
1623 startPortlet("Learned MACs ($mac_count)");
1624 echo $rendered_macs;
1625 finishPortlet();
1626 }
1627
1628 echo "</td></tr></table>";
1629}
1630
e673ee24 1631/*
51c18782 1632The following conditions must be met:
e673ee24
DO
16331. We can mount onto free atoms only. This means: if any record for an atom
1634already exists in RackSpace, it can't be used for mounting.
16352. We can't unmount from 'W' atoms. Operator should review appropriate comments
1636and either delete them before unmounting or refuse to unmount the object.
1637*/
7e1db771 1638function renderRackSpaceForObject ($object_id)
e673ee24 1639{
e673ee24
DO
1640 // Always process occupied racks plus racks chosen by user. First get racks with
1641 // already allocated rackspace...
51c18782 1642 $workingRacksData = getResidentRacksData ($object_id);
e673ee24 1643 // ...and then add those chosen by user (if any).
2135fd83 1644 if (isset($_REQUEST['rackmulti']))
e673ee24 1645 foreach ($_REQUEST['rackmulti'] as $cand_id)
e673ee24
DO
1646 if (!isset ($workingRacksData[$cand_id]))
1647 {
0cc24e9a 1648 $rackData = spotEntity ('rack', $cand_id);
61a1d996 1649 amplifyCell ($rackData);
e673ee24
DO
1650 $workingRacksData[$cand_id] = $rackData;
1651 }
51690ad4 1652
0a7feebb
AD
1653 // Get a list of all of this object's parents,
1654 // then trim the list to only include parents which are racks
1655 $objectParents = getEntityRelatives('parents', 'object', $object_id);
1656 $parentRacks = array();
1657 foreach ($objectParents as $parentData)
1658 if ($parentData['entity_type'] == 'rack')
1659 $parentRacks[] = $parentData['entity_id'];
1660
e673ee24
DO
1661 // Main layout starts.
1662 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0><tr>";
1663
1664 // Left portlet with rack list.
1665 echo "<td class=pcleft height='1%'>";
1666 startPortlet ('Racks');
a8efc03e 1667 $allRacksData = listCells ('rack');
6d42599c
AA
1668
1669 // filter rack list to match only racks having common tags with the object (reducing $allRacksData)
1670 if (! isset ($_REQUEST['show_all_racks']) and getConfigVar ('FILTER_RACKLIST_BY_TAGS') == 'yes')
1671 {
1672 $matching_racks = array();
1673 $object = spotEntity ('object', $object_id);
1674 $matched_tags = array();
1675 foreach ($allRacksData as $rack)
1676 foreach ($object['etags'] as $tag)
1677 if (tagOnChain ($tag, $rack['etags']) or tagOnChain ($tag, $rack['itags']))
1678 {
1679 $matching_racks[$rack['id']] = $rack;
1680 $matched_tags[$tag['id']] = $tag;
1681 break;
1682 }
1683 // add current object's racks even if they dont match filter
1684 foreach ($workingRacksData as $rack_id => $rack)
1685 if (! isset ($matching_racks[$rack_id]))
1686 $matching_racks[$rack_id] = $rack;
1687 // if matching racks found, and rack list is reduced, show 'show all' link
1688 if (count ($matching_racks) and count ($matching_racks) != count ($allRacksData))
1689 {
1690 $filter_text = '';
1691 foreach ($matched_tags as $tag)
1692 $filter_text .= (empty ($filter_text) ? '' : ' or ') . '{' . $tag['tag'] . '}';
1693 $href_show_all = trim($_SERVER['REQUEST_URI'], '&');
1694 $href_show_all .= htmlspecialchars('&show_all_racks=1');
1695 echo "(filtered by <span class='filter-text'>$filter_text</span>, <a href='$href_show_all'>show all</a>)<p>";
1696 $allRacksData = $matching_racks;
1697 }
1698 }
1699
4b8d413e 1700 if (count ($allRacksData) <= getConfigVar ('RACK_PRESELECT_THRESHOLD'))
61a1d996 1701 foreach ($allRacksData as $rack)
51c18782
DO
1702 if (!array_key_exists ($rack['id'], $workingRacksData))
1703 {
1704 amplifyCell ($rack);
1705 $workingRacksData[$rack['id']] = $rack;
1706 }
1707 foreach (array_keys ($workingRacksData) as $rackId)
1708 applyObjectMountMask ($workingRacksData[$rackId], $object_id);
1709 printOpFormIntro ('updateObjectAllocation');
4b8d413e 1710 renderRackMultiSelect ('rackmulti[]', $allRacksData, array_keys ($workingRacksData));
51c18782 1711 echo "<br><br>";
e673ee24
DO
1712 finishPortlet();
1713 echo "</td>";
1714
1715 // Middle portlet with comment and submit.
1716 echo "<td class=pcleft>";
1717 startPortlet ('Comment');
1718 echo "<textarea name=comment rows=10 cols=40></textarea><br>\n";
1719 echo "<input type=submit value='Save' name=got_atoms>\n";
51c18782 1720 echo "<br><br>";
e673ee24
DO
1721 finishPortlet();
1722 echo "</td>";
1723
1724 // Right portlet with rendered racks. If this form submit is not final, we have to
1725 // reflect the former state of the grid in current form.
1726 echo "<td class=pcright rowspan=2 height='1%'>";
1727 startPortlet ('Working copy');
65e557dd 1728 addJS ('js/racktables.js');
e673ee24
DO
1729 echo '<table border=0 cellspacing=10 align=center><tr>';
1730 foreach ($workingRacksData as $rack_id => $rackData)
1731 {
1732 // Order is important here: only original allocation is highlighted.
1733 highlightObject ($rackData, $object_id);
1734 markupAtomGrid ($rackData, 'T');
1735 // If we have a form processed, discard user input and show new database
1736 // contents.
51c18782 1737 if (isset ($_REQUEST['rackmulti'][0])) // is an update
e673ee24
DO
1738 mergeGridFormToRack ($rackData);
1739 echo "<td valign=top>";
1740 echo "<center>\n<h2>${rackData['name']}</h2>\n";
1741 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
57c69e9c 1742 echo "<tr><th width='10%'>&nbsp;</th>";
bd0bfb76
AD
1743 echo "<th width='20%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '0', ${rackData['height']})\">Front</a></th>";
1744 echo "<th width='50%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '1', ${rackData['height']})\">Interior</a></th>";
1745 echo "<th width='20%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '2', ${rackData['height']})\">Back</a></th></tr>\n";
e673ee24 1746 renderAtomGrid ($rackData);
57c69e9c 1747 echo "<tr><th width='10%'>&nbsp;</th>";
bd0bfb76
AD
1748 echo "<th width='20%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '0', ${rackData['height']})\">Front</a></th>";
1749 echo "<th width='50%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '1', ${rackData['height']})\">Interior</a></th>";
1750 echo "<th width='20%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '2', ${rackData['height']})\">Back</a></th></tr>\n";
0a7feebb
AD
1751 echo "</table>\n<br>\n";
1752 // Determine zero-u checkbox status.
1753 // If form has been submitted, use form data, otherwise use DB data.
1754 if (isset($_REQUEST['op']))
1755 $checked = isset($_REQUEST['zerou_'.$rack_id]) ? 'checked' : '';
1756 else
1757 $checked = in_array($rack_id, $parentRacks) ? 'checked' : '';
d141833a 1758 echo "<label for=zerou_${rack_id}>Zero-U:</label> <input type=checkbox ${checked} name=zerou_${rack_id} id=zerou_${rack_id}>\n<br><br>\n";
bd0bfb76 1759 echo "<input type='button' onclick='uncheckAll();' value='Uncheck all'>\n";
0a7feebb 1760 echo '</center></td>';
e673ee24
DO
1761 }
1762 echo "</tr></table>";
1763 finishPortlet();
1764 echo "</td>\n";
1765
1766 echo "</form>\n";
1767 echo "</tr></table>\n";
1768}
1769
1770function renderMolecule ($mdata, $object_id)
1771{
1772 // sort data out
1773 $rackpack = array();
1774 global $loclist;
64b95774 1775 foreach ($mdata as $rua)
e673ee24
DO
1776 {
1777 $rack_id = $rua['rack_id'];
1778 $unit_no = $rua['unit_no'];
1779 $atom = $rua['atom'];
1780 if (!isset ($rackpack[$rack_id]))
1781 {
61a1d996
DO
1782 $rackData = spotEntity ('rack', $rack_id);
1783 amplifyCell ($rackData);
e673ee24
DO
1784 for ($i = $rackData['height']; $i > 0; $i--)
1785 for ($locidx = 0; $locidx < 3; $locidx++)
1786 $rackData[$i][$locidx]['state'] = 'F';
1787 $rackpack[$rack_id] = $rackData;
1788 }
1789 $rackpack[$rack_id][$unit_no][$loclist[$atom]]['state'] = 'T';
1790 $rackpack[$rack_id][$unit_no][$loclist[$atom]]['object_id'] = $object_id;
1791 }
1792 // now we have some racks to render
64b95774 1793 foreach ($rackpack as $rackData)
e673ee24
DO
1794 {
1795 markAllSpans ($rackData);
1796 echo "<table class=molecule cellspacing=0>\n";
1797 echo "<caption>${rackData['name']}</caption>\n";
1798 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>Front</th><th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
1799 for ($i = $rackData['height']; $i > 0; $i--)
1800 {
1801 echo "<tr><th>$i</th>";
1802 for ($locidx = 0; $locidx < 3; $locidx++)
1803 {
1804 $state = $rackData[$i][$locidx]['state'];
65e557dd 1805 echo "<td class='atom state_${state}'>&nbsp;</td>\n";
e673ee24
DO
1806 }
1807 echo "</tr>\n";
1808 }
1809 echo "</table>\n";
1810 }
1811}
1812
23cdc7e9 1813function renderDepot ()
e673ee24 1814{
23cdc7e9 1815 global $pageno, $nextorder;
23cdc7e9
DO
1816 $cellfilter = getCellFilter();
1817 $objects = filterCellList (listCells ('object'), $cellfilter['expression']);
1818
1819 echo "<table border=0 class=objectview>\n";
1820 echo "<tr><td class=pcleft>";
1821
1ebbf889 1822 if (! renderEmptyResults ($cellfilter, 'objects', count($objects)))
e673ee24 1823 {
4899096d 1824 if (count($objects) > 0)
1ebbf889 1825 {
4899096d
AD
1826 startPortlet ('Objects (' . count ($objects) . ')');
1827 echo '<br><br><table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
b09a8280 1828 echo '<tr><th>Common name</th><th>Visible label</th><th>Asset tag</th><th>Row/Rack or Container</th></tr>';
4899096d 1829 $order = 'odd';
3f8a25d6
DO
1830 # gather IDs of all objects and fetch rackspace info in one pass
1831 $idlist = array();
1832 foreach ($objects as $obj)
1833 $idlist[] = $obj['id'];
1834 $mountinfo = getMountInfo ($idlist);
4899096d
AD
1835 foreach ($objects as $obj)
1836 {
4318ced5 1837 echo "<tr class='row_${order} tdleft' valign=top><td><a href='".makeHref(array('page'=>'object', 'object_id'=>$obj['id']))."'><strong>${obj['dname']}</strong></a>";
4899096d
AD
1838 if (count ($obj['etags']))
1839 echo '<br><small>' . serializeTags ($obj['etags'], makeHref(array('page'=>$pageno, 'tab'=>'default')) . '&') . '</small>';
4318ced5
AA
1840 echo "</td><td>${obj['label']}</td>";
1841 echo "<td>${obj['asset_no']}</td>";
3f8a25d6 1842 $places = array();
b09a8280
AD
1843 if ($obj['container_id'])
1844 $places[] = mkA ($obj['container_name'], 'object', $obj['container_id']);
1845 elseif (! array_key_exists ($obj['id'], $mountinfo))
3f8a25d6 1846 $places[] = 'Unmounted';
4899096d 1847 else
3f8a25d6
DO
1848 foreach ($mountinfo[$obj['id']] as $mi)
1849 $places[] = mkA ($mi['row_name'], 'row', $mi['row_id']) . '/' . mkA ($mi['rack_name'], 'rack', $mi['rack_id']);
4318ced5 1850 echo "<td>" . implode (', ', $places) . '</td>';
4899096d
AD
1851 echo '</tr>';
1852 $order = $nextorder[$order];
1853 }
1854 echo '</table>';
1855 finishPortlet();
1ebbf889 1856 }
4899096d
AD
1857 else
1858 echo '<h2>No objects exist</h2>';
e673ee24 1859 }
23cdc7e9
DO
1860
1861 echo "</td><td class=pcright width='25%'>";
1862
95857b5c 1863 renderCellFilterPortlet ($cellfilter, 'object', $objects);
23cdc7e9 1864 echo "</td></tr></table>\n";
e673ee24
DO
1865}
1866
1ebbf889
AA
1867// This function returns TRUE if the result set is too big to be rendered, and no filter is set.
1868// In this case it renders the describing message instead.
1869function renderEmptyResults($cellfilter, $entities_name, $count = NULL)
1870{
1871 if (!$cellfilter['is_empty'])
1872 return FALSE;
1873 if (isset ($_REQUEST['show_all_objects']))
1874 return FALSE;
1875 $max = intval(getConfigVar('MAX_UNFILTERED_ENTITIES'));
1876 if (0 == $max || $count <= $max)
1877 return FALSE;
1878
1879 $href_show_all = trim($_SERVER['REQUEST_URI'], '&');
1880 $href_show_all .= htmlspecialchars('&show_all_objects=1');
1881 $suffix = isset ($count) ? " ($count)" : '';
1882 echo <<<END
1883<p>Please set a filter to display the corresponging $entities_name.
1884<br><a href="$href_show_all">Show all $entities_name$suffix</a>
1885END;
1886 return TRUE;
1887}
1888
e673ee24 1889// History viewer for history-enabled simple dictionaries.
9b8174d7 1890function renderObjectHistory ($object_id)
e673ee24 1891{
e673ee24
DO
1892 $order = 'odd';
1893 global $nextorder;
9b8174d7
AD
1894 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
1895 echo '<tr><th>change time</th><th>author</th><th>name</th><th>visible label</th><th>asset no</th><th>has problems?</th><th>comment</th></tr>';
1896 $result = usePreparedSelectBlade
1897 (
1898 'SELECT ctime, user_name, name, label, asset_no, has_problems, comment FROM ObjectHistory WHERE id=? ORDER BY ctime',
1899 array ($object_id)
1900 );
e673ee24
DO
1901 while ($row = $result->fetch (PDO::FETCH_NUM))
1902 {
1903 echo "<tr class=row_${order}><td>${row[0]}</td>";
9b8174d7 1904 for ($i = 1; $i <= 6; $i++)
e673ee24
DO
1905 echo "<td>" . $row[$i] . "</td>";
1906 echo "</tr>\n";
1907 $order = $nextorder[$order];
1908 }
1909 echo "</table><br>\n";
1910}
1911
1912function renderRackspaceHistory ()
1913{
4fbb5a00 1914 global $nextorder, $pageno, $tabno;
e673ee24
DO
1915 $order = 'odd';
1916 $history = getRackspaceHistory();
1917 // Show the last operation by default.
1918 if (isset ($_REQUEST['op_id']))
1919 $op_id = $_REQUEST['op_id'];
1920 elseif (isset ($history[0]['mo_id']))
1921 $op_id = $history[0]['mo_id'];
1922 else $op_id = NULL;
1923
1924 $omid = NULL;
1925 $nmid = NULL;
1926 $object_id = 1;
1927 if ($op_id)
1928 list ($omid, $nmid) = getOperationMolecules ($op_id);
1929
1930 // Main layout starts.
1931 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
1932
1933 // Left top portlet with old allocation.
1934 echo "<tr><td class=pcleft>";
1935 startPortlet ('Old allocation');
1936 if ($omid)
1937 {
1938 $oldMolecule = getMolecule ($omid);
1939 renderMolecule ($oldMolecule, $object_id);
1940 }
1941 else
1942 echo "nothing";
1943 finishPortlet();
1944
1945 echo '</td><td class=pcright>';
1946
1947 // Right top portlet with new allocation
1948 startPortlet ('New allocation');
1949 if ($nmid)
1950 {
1951 $newMolecule = getMolecule ($nmid);
1952 renderMolecule ($newMolecule, $object_id);
1953 }
1954 else
1955 echo "nothing";
1956 finishPortlet();
737a3f72 1957
e673ee24 1958 echo '</td></tr><tr><td colspan=2>';
737a3f72 1959
e673ee24
DO
1960 // Bottom portlet with list
1961
1962 startPortlet ('Rackspace allocation history');
1963 echo "<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>\n";
7fa7047a 1964 echo "<tr><th>timestamp</th><th>author</th><th>object</th><th>comment</th></tr>\n";
e673ee24
DO
1965 foreach ($history as $row)
1966 {
1967 if ($row['mo_id'] == $op_id)
1968 $class = 'hl';
1969 else
1970 $class = "row_${order}";
4fbb5a00 1971 echo "<tr class=${class}><td><a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'op_id'=>$row['mo_id']))."'>${row['ctime']}</a></td>";
7fa7047a
DO
1972 echo "<td>${row['user_name']}</td><td>";
1973 renderCell (spotEntity ('object', $row['ro_id']));
9c6222ef 1974 echo '</td><td>' . niftyString ($row['comment'], 0) . '</td></tr>';
e673ee24
DO
1975 $order = $nextorder[$order];
1976 }
1977 echo "</table>\n";
1978 finishPortlet();
737a3f72 1979
e673ee24 1980 echo '</td></tr></table>';
e673ee24
DO
1981}
1982
4318ced5 1983function renderIPSpaceRecords ($tree, $baseurl, $target = 0, $level = 1)
d65353ad
DO
1984{
1985 $self = __FUNCTION__;
4318ced5 1986 $knight = (getConfigVar ('IPV4_ENABLE_KNIGHT') == 'yes');
00276508
AA
1987
1988 // scroll page to the highlighted item
1989 if ($target && isset ($_REQUEST['hl_net']))
65e557dd 1990 addAutoScrollScript ("net-$target");
00276508 1991
d65353ad
DO
1992 foreach ($tree as $item)
1993 {
4318ced5
AA
1994 if ($display_routers = (getConfigVar ('IPV4_TREE_RTR_AS_CELL') != 'none'))
1995 loadIPAddrList ($item); // necessary to compute router list and address counter
1996
0137d53c
DO
1997 if (isset ($item['id']))
1998 {
1f54e1ba 1999 $decor = array ('indent' => $level);
fec0c8da 2000 if ($item['symbol'] == 'node-collapsed')
4318ced5 2001 $decor['symbolurl'] = "${baseurl}&eid=${item['id']}&hl_net=1";
fec0c8da 2002 elseif ($item['symbol'] == 'node-expanded')
4318ced5
AA
2003 $decor['symbolurl'] = $baseurl . ($item['parent_id'] ? "&eid=${item['parent_id']}&hl_net=1" : '');
2004 $tr_class = '';
21ee3351 2005 if ($target == $item['id'] && isset ($_REQUEST['hl_net']))
64347dcf 2006 {
4318ced5
AA
2007 $decor['tdclass'] = ' port_highlight';
2008 $tr_class = $decor['tdclass'];
64347dcf 2009 }
4318ced5
AA
2010 echo "<tr valign=top class=\"$tr_class\">";
2011 printIPNetInfoTDs ($item, $decor);
2012
2013 // capacity and usage
2014 echo "<td class=tdcenter>";
2015 echo getRenderedIPNetCapacity ($item);
64347dcf 2016 echo "</td>";
4318ced5
AA
2017
2018 if ($display_routers)
4a47d34b 2019 printRoutersTD (findRouters ($item['addrlist']), getConfigVar ('IPV4_TREE_RTR_AS_CELL'));
0137d53c 2020 echo "</tr>";
fec0c8da 2021 if ($item['symbol'] == 'node-expanded' or $item['symbol'] == 'node-expanded-static')
4318ced5 2022 $self ($item['kids'], $baseurl, $target, $level + 1);
0137d53c
DO
2023 }
2024 else
2025 {
4318ced5 2026 // non-allocated (spare) IP range
0137d53c 2027 echo "<tr valign=top>";
21ee3351 2028 printIPNetInfoTDs ($item, array ('indent' => $level, 'knight' => $knight, 'tdclass' => 'sparenetwork'));
00276508 2029
4318ced5 2030 // capacity and usage
21ee3351 2031 echo "<td class=tdcenter>";
4318ced5 2032 echo getRenderedIPNetCapacity ($item);
21ee3351 2033 echo "</td>";
4318ced5
AA
2034 if ($display_routers)
2035 echo "<td></td>";
21ee3351 2036 echo "</tr>";
21ee3351 2037 }
21ee3351
AA
2038 }
2039}
2040
4318ced5 2041function renderIPSpace()
e673ee24 2042{
4fbb5a00 2043 global $pageno, $tabno;
4318ced5 2044 $realm = ($pageno == 'ipv4space' ? 'ipv4net' : 'ipv6net');
31c941ec 2045 $cellfilter = getCellFilter();
4318ced5
AA
2046 $top = NULL;
2047 $netlist = array();
2048 foreach (listCells ($realm) as $net)
2049 {
2050 if (isset ($top) and IPNetContains ($top, $net))
2051 ;
2052 elseif (! count ($cellfilter['expression']) or judgeCell ($net, $cellfilter['expression']))
2053 $top = $net;
1ebbf889 2054 else
4318ced5
AA
2055 continue;
2056 $netlist[$net['id']] = $net;
5388794d 2057 }
21ee3351
AA
2058 $netcount = count ($netlist);
2059 // expand request can take either natural values or "ALL". Zero means no expanding.
2060 $eid = isset ($_REQUEST['eid']) ? $_REQUEST['eid'] : 0;
4318ced5 2061 $tree = prepareIPTree ($netlist, $eid);
21ee3351
AA
2062
2063 echo "<table border=0 class=objectview>\n";
2064 echo "<tr><td class=pcleft>";
4318ced5 2065 if (! renderEmptyResults($cellfilter, 'IP nets', count($tree)))
21ee3351
AA
2066 {
2067 startPortlet ("networks (${netcount})");
2068 echo '<h4>';
4318ced5
AA
2069 $all = "<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'eid'=>'ALL')) .
2070 $cellfilter['urlextra'] . "'>expand&nbsp;all</a>";
2071 $none = "<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'eid'=>'NONE')) .
2072 $cellfilter['urlextra'] . "'>collapse&nbsp;all</a>";
2073 $auto = "<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno)) .
2074 $cellfilter['urlextra'] . "'>auto-collapse</a>";
2075
21ee3351 2076 if ($eid === 0)
4318ced5 2077 echo 'auto-collapsing at threshold ' . getConfigVar ('TREE_THRESHOLD') . " ($all / $none)";
21ee3351 2078 elseif ($eid === 'ALL')
4318ced5
AA
2079 echo "expanding all ($auto / $none)";
2080 elseif ($eid === 'NONE')
2081 echo "collapsing all ($all / $auto)";
21ee3351
AA
2082 else
2083 {
4318ced5
AA
2084 $netinfo = spotEntity ($realm, $eid);
2085 echo "expanding ${netinfo['ip']}/${netinfo['mask']} ($auto / $all / $none)";
21ee3351
AA
2086 }
2087 echo "</h4><table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2088 echo "<tr><th>prefix</th><th>name/tags</th><th>capacity</th>";
4318ced5 2089 if (getConfigVar ('IPV4_TREE_RTR_AS_CELL') != 'none')
21ee3351
AA
2090 echo "<th>routed by</th>";
2091 echo "</tr>\n";
2092 $baseurl = makeHref(array('page'=>$pageno, 'tab'=>$tabno)) . $cellfilter['urlextra'];
4318ced5 2093 renderIPSpaceRecords ($tree, $baseurl, $eid);
21ee3351
AA
2094 echo "</table>\n";
2095 finishPortlet();
2096 }
2097
2098 echo '</td><td class=pcright>';
4318ced5 2099 renderCellFilterPortlet ($cellfilter, 'ipv4net', $netlist);
21ee3351
AA
2100 echo "</td></tr></table>\n";
2101}
2102
4318ced5 2103function renderIPSpaceEditor()
21ee3351 2104{
4318ced5
AA
2105 global $pageno;
2106 $realm = ($pageno == 'ipv4space' ? 'ipv4net' : 'ipv6net');
2107 $net_page = $realm; // 'ipv4net', 'ipv6net'
2108 $addrspaceList = listCells ($realm);
93a49e5b
AA
2109 startPortlet ('Manage existing (' . count ($addrspaceList) . ')');
2110 if (count ($addrspaceList))
21ee3351 2111 {
21ee3351
AA
2112 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2113 echo "<tr><th>&nbsp;</th><th>prefix</th><th>name</th><th>capacity</th></tr>";
21ee3351
AA
2114 foreach ($addrspaceList as $netinfo)
2115 {
21ee3351 2116 echo "<tr valign=top><td>";
93a49e5b 2117 if (! isIPNetworkEmpty ($netinfo))
21ee3351
AA
2118 printImageHREF ('nodestroy', 'There are ' . count ($netinfo['addrlist']) . ' allocations inside');
2119 else
93a49e5b 2120 echo getOpLink (array ('op' => 'del', 'id' => $netinfo['id']), '', 'destroy', 'Delete this prefix');
4318ced5 2121 echo '</td><td class=tdleft><a href="' . makeHref (array ('page' => $net_page, 'id' => $netinfo['id'])) . '">';
ab1283b7 2122 echo "${netinfo['ip']}/${netinfo['mask']}</a></td>";
1f54e1ba
DO
2123 echo '<td class=tdleft>' . niftyString ($netinfo['name']);
2124 if (count ($netinfo['etags']))
2125 echo '<br><small>' . serializeTags ($netinfo['etags']) . '</small>';
2126 echo '</td><td>';
4318ced5 2127 echo getRenderedIPNetCapacity ($netinfo);
b1e39212 2128 echo '</tr>';
e673ee24 2129 }
04d619d0
DO
2130 echo "</table>";
2131 finishPortlet();
e673ee24 2132 }
93a49e5b
AA
2133}
2134
2135function renderIPNewNetForm ()
2136{
2137 global $pageno;
2138 if ($pageno == 'ipv6space')
2139 {
2140 $realm = 'ipv6net';
3495ec6e 2141 $regexp = '^[a-fA-F0-9:]*:[a-fA-F0-9:\.]*/\d{1,3}$';
93a49e5b
AA
2142 }
2143 else
2144 {
2145 $realm = 'ipv4net';
3495ec6e 2146 $regexp = '^(\d{1,3}\.){3}\d{1,3}/\d{1,2}$';
93a49e5b
AA
2147 }
2148
2149 // IP prefix validator
2150 addJs ('js/live_validation.js');
2151 $regexp = addslashes ($regexp);
2152 addJs (<<<END
2153$(document).ready(function () {
2154 document.add_new_range.range.setAttribute('match', '$regexp');
2155 Validate.init();
2156});
2157END
2158 , TRUE);
2159
2160 startPortlet ('Add new');
2161 echo '<table border=0 cellpadding=10 align=center>';
2162 // This form requires a name, so JavaScript validator can find it.
2163 // No printOpFormIntro() hence
2164 echo "<form method=post name='add_new_range' action='".makeHrefProcess()."'>\n";
2165 echo "<input type=hidden name=op value=add>\n";
2166 // tags column
2167 echo '<tr><td rowspan=5><h3>assign tags</h3>';
2168 renderNewEntityTags ($realm);
2169 echo '</td>';
2170 // inputs column
2171 $prefix_value = empty ($_REQUEST['set-prefix']) ? '' : $_REQUEST['set-prefix'];
2172 echo "<th class=tdright>prefix</th><td class=tdleft><input type=text name='range' size=36 class='live-validate' tabindex=1 value='${prefix_value}'></td>";
2173 echo '<tr><th class=tdright>VLAN</th><td class=tdleft>';
2174 echo getOptionTree ('vlan_ck', getAllVLANOptions(), array ('select_class' => 'vertical', 'tabindex' => 2)) . '</td></tr>';
2175 echo "<tr><th class=tdright>name</th><td class=tdleft><input type=text name='name' size='20' tabindex=3></td></tr>";
2176 echo '<tr><td class=tdright><input type=checkbox name="is_connected" tabindex=4></td><th class=tdleft>reserve subnet-router anycast address</th></tr>';
2177 echo "<tr><td colspan=2>";
2178 printImageHREF ('CREATE', 'Add a new network', TRUE, 5);
2179 echo '</td></tr>';
2180 echo "</form></table><br><br>\n";
2181 finishPortlet();
e673ee24
DO
2182}
2183
4318ced5 2184function getRenderedIPNetBacktrace ($range)
e673ee24 2185{
4318ced5
AA
2186 if (getConfigVar ('EXT_IPV4_VIEW') != 'yes')
2187 return array();
e673ee24 2188
4318ced5
AA
2189 $v = ($range['realm'] == 'ipv4net') ? 4 : 6;
2190 $space = "ipv${v}space"; // ipv4space, ipv6space
2191 $tag = "\$ip${v}netid_"; // $ip4netid_, $ip6netid_
2192
2193 $ret = array();
2194 // Build a backtrace from all parent networks.
2195 $clen = $range['mask'];
2196 $backtrace = array();
2197 $backtrace['&rarr;'] = $range;
2198 $key = '';
2199 while (NULL !== ($upperid = getIPAddressNetworkId ($range['ip_bin'], $clen)))
2200 {
2201 $upperinfo = spotEntity ($range['realm'], $upperid);
2202 $clen = $upperinfo['mask'];
2203 $key .= '&uarr;';
2204 $backtrace[$key] = $upperinfo;
2205 }
2206 foreach (array_reverse ($backtrace) as $arrow => $ainfo)
2207 {
2208 $link = '<a href="' . makeHref (array (
2209 'page' => $space,
2210 'tab' => 'default',
2211 'clear-cf' => '',
2212 'cfe' => '{' . $tag . $ainfo['id'] . '}',
2213 'hl_net' => 1,
2214 'eid' => $range['id'],
2215 )) . '" title="View IP tree with this net as root">' . $arrow . '</a>';
2216 $ret[] = array ($link, getOutputOf ('renderCell', $ainfo));
2217 }
2218 return $ret;
2219}
2220
2221function renderIPNetwork ($id)
2222{
2223 global $pageno;
2224 $realm = $pageno; // 'ipv4net', 'ipv6net'
2225 $range = spotEntity ($realm, $id);
2226 loadIPAddrList ($range);
2034d968 2227 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
99ab184f
DO
2228 echo "<tr><td colspan=2 align=center><h1>${range['ip']}/${range['mask']}</h1><h2>";
2229 echo htmlspecialchars ($range['name'], ENT_QUOTES, 'UTF-8') . "</h2></td></tr>\n";
2034d968
DO
2230
2231 echo "<tr><td class=pcleft width='50%'>";
646272be
AA
2232
2233 // render summary portlet
2234 $summary = array();
4318ced5
AA
2235 $summary['%% used'] = getRenderedIPNetCapacity ($range);
2236 $summary = array_merge ($summary, getRenderedIPNetBacktrace ($range));
2237 if ($realm == 'ipv4net')
001e61fa 2238 {
4318ced5
AA
2239 $summary[] = array ('Netmask:', ip4_format ($range['mask_bin']));
2240 $summary[] = array ('Netmask:', "0x" . strtoupper (implode ('', unpack ('H*', $range['mask_bin']))));
2241 $summary['Wildcard bits'] = ip4_format ( ~ $range['mask_bin']);
001e61fa 2242 }
646272be 2243
a5f9d1ca 2244 foreach ($range['8021q'] as $item)
cbf78395 2245 {
a5f9d1ca 2246 $vlaninfo = getVLANInfo ($item['domain_id'] . '-' . $item['vlan_id']);
646272be 2247 $summary[] = array ('VLAN:', '<a href="' . makeHref (array ('page' => 'vlan', 'vlan_ck' => $vlaninfo['vlan_ck'])) . '">' . formatVLANName ($vlaninfo, 'markup long') . '</a>');
cbf78395 2248 }
3a4f4023 2249 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes' and count ($routers = findRouters ($range['addrlist'])))
04d619d0 2250 {
646272be
AA
2251 $summary['Routed by'] = '';
2252 foreach ($routers as $rtr)
4318ced5 2253 $summary['Routed by'] .= getOutputOf ('renderRouterCell', $rtr['ip_bin'], $rtr['iface'], spotEntity ('object', $rtr['id']));
04d619d0 2254 }
646272be
AA
2255 $summary['tags'] = '';
2256 renderEntitySummary ($range, 'summary', $summary);
e1ae3fb4 2257
99ab184f
DO
2258 if (strlen ($range['comment']))
2259 {
2260 startPortlet ('Comment');
2261 echo '<div class=commentblock>' . string_insert_hrefs (htmlspecialchars ($range['comment'], ENT_QUOTES, 'UTF-8')) . '</div>';
2262 finishPortlet ();
2263 }
2264
4318ced5 2265 renderFilesPortlet ($realm, $id);
2034d968 2266 echo "</td>\n";
e673ee24 2267
2034d968
DO
2268 echo "<td class=pcright>";
2269 startPortlet ('details');
4318ced5
AA
2270 renderIPNetworkAddresses ($range);
2271 finishPortlet();
2272 echo "</td></tr></table>\n";
2273}
e673ee24 2274
4318ced5
AA
2275// Used solely by renderSeparator
2276function renderEmptyIPv6 ($ip_bin, $hl_ip)
2277{
2278 $class = 'tdleft';
2279 if ($ip_bin === $hl_ip)
2280 $class .= ' port_highlight';
2281 $fmt = ip6_format ($ip_bin);
2282 echo "<tr class='$class'><td><a class='ancor' name='ip-$fmt' href='" . makeHref (array ('page' => 'ipaddress', 'ip' => $fmt)) . "'>" . $fmt;
0b8d8309
AA
2283 $editable = permitted ('ipaddress', 'properties', 'editAddress')
2284 ? 'editable'
2285 : '';
2286 echo "</a></td><td><span class='rsvtext $editable id-$fmt op-upd-reservation-ip'></span></td><td>&nbsp;</td></tr>\n";
4318ced5
AA
2287}
2288
2289// Renders empty table line to shrink empty IPv6 address ranges.
2290// If the range consists of single address, renders the address instead of empty line.
2291// Renders address $hl_ip inside the range.
2292// Used solely by renderIPv6NetworkAddresses
2293function renderSeparator ($first, $last, $hl_ip)
2294{
2295 $self = __FUNCTION__;
2296 if (strcmp ($first, $last) > 0)
2297 return;
2298 if ($first == $last)
2299 renderEmptyIPv6 ($first, $hl_ip);
2300 elseif (isset ($hl_ip) && strcmp ($hl_ip, $first) >= 0 && strcmp ($hl_ip, $last) <= 0)
2301 { // $hl_ip is inside the range $first - $last
2302 $self ($first, ip_prev ($hl_ip), $hl_ip);
2303 renderEmptyIPv6 ($hl_ip, $hl_ip);
2304 $self (ip_next ($hl_ip), $last, $hl_ip);
2305 }
2306 else
2307 echo "<tr><td colspan=3 class=tdleft></td></tr>\n";
2308}
2309
2310// calculates page number which contains given $ip (used by renderIPv6NetworkAddresses)
2311function getPageNumOfIPv6 ($list, $ip_bin, $maxperpage)
2312{
2313 if (intval ($maxperpage) <= 0 || count ($list) <= $maxperpage)
2314 return 0;
2315 $keys = array_keys ($list);
2316 for ($i = 1; $i <= count ($keys); $i++)
2317 if (strcmp ($keys[$i-1], $ip_bin) >= 0)
2318 return intval ($i / $maxperpage);
2319 return intval (count ($list) / $maxperpage);
2320}
2321
2322function renderIPNetworkAddresses ($range)
2323{
2324 switch (strlen ($range['ip_bin']))
2325 {
2326 case 4: return renderIPv4NetworkAddresses ($range);
2327 case 16: return renderIPv6NetworkAddresses ($range);
2328 default: throw new InvalidArgException ("range['ip_bin']", $range['ip_bin']);
2329 }
2330}
2331
2332function renderIPv4NetworkAddresses ($range)
2333{
2334 global $pageno, $tabno, $aac2;
2335 $startip = ip4_bin2int ($range['ip_bin']);
2336 $endip = ip4_bin2int (ip_last ($range));
2337
2338 if (isset ($_REQUEST['hl_ip']))
00276508 2339 {
4318ced5
AA
2340 $hl_ip = ip4_bin2int (ip4_parse ($_REQUEST['hl_ip']));
2341 addAutoScrollScript ('ip-' . $_REQUEST['hl_ip']); // scroll page to highlighted ip
00276508
AA
2342 }
2343
79b57b18
AA
2344 // pager
2345 $maxperpage = getConfigVar ('IPV4_ADDRS_PER_PAGE');
2346 $address_count = $endip - $startip + 1;
2347 $page = 0;
446c25c3 2348 $rendered_pager = '';
79b57b18
AA
2349 if ($address_count > $maxperpage && $maxperpage > 0)
2350 {
2351 $page = isset ($_REQUEST['pg']) ? $_REQUEST['pg'] : (isset ($hl_ip) ? intval (($hl_ip - $startip) / $maxperpage) : 0);
2352 if ($numpages = ceil ($address_count / $maxperpage))
2353 {
4318ced5 2354 echo '<h3>' . ip4_format (ip4_int2bin ($startip)) . ' ~ ' . ip4_format (ip4_int2bin ($endip)) . '</h3>';
79b57b18
AA
2355 for ($i = 0; $i < $numpages; $i++)
2356 if ($i == $page)
446c25c3 2357 $rendered_pager .= "<b>$i</b> ";
79b57b18 2358 else
4318ced5 2359 $rendered_pager .= "<a href='".makeHref (array ('page' => $pageno, 'tab' => $tabno, 'id' => $range['id'], 'pg' => $i)) . "'>$i</a> ";
79b57b18
AA
2360 }
2361 $startip = $startip + $page * $maxperpage;
2362 $endip = min ($startip + $maxperpage - 1, $endip);
2363 }
2364
446c25c3 2365 echo $rendered_pager;
beb9e88a 2366 echo "<table class='widetable' border=0 cellspacing=0 cellpadding=5 align='center' width='100%'>\n";
e673ee24
DO
2367 echo "<tr><th>Address</th><th>Name</th><th>Allocation</th></tr>\n";
2368
4318ced5
AA
2369 markupIPAddrList ($range['addrlist']);
2370 for ($ip = $startip; $ip <= $endip; $ip++)
2371 {
2372 $ip_bin = ip4_int2bin ($ip);
2373 $dottedquad = ip4_format ($ip_bin);
2374 $tr_class = (isset ($hl_ip) && $hl_ip == $ip ? 'port_highlight' : '');
2375 if (!isset ($range['addrlist'][$ip_bin]))
e673ee24 2376 {
4318ced5 2377 echo "<tr class='tdleft $tr_class'><td class=tdleft><a class='ancor' name='ip-$dottedquad' href='" . makeHref(array('page'=>'ipaddress', 'ip' => $dottedquad)) . "'>$dottedquad</a></td>";
0b8d8309
AA
2378 $editable = permitted ('ipaddress', 'properties', 'editAddress')
2379 ? 'editable'
2380 : '';
2381 echo "<td><span class='rsvtext $editable id-$dottedquad op-upd-reservation-ip'></span></td><td>&nbsp;</td></tr>\n";
b2035dca
DO
2382 continue;
2383 }
4318ced5 2384 $addr = $range['addrlist'][$ip_bin];
68c91b9c
AA
2385 // render IP change history
2386 $title = '';
2387 $history_class = '';
2388 if (isset ($addr['last_log']))
2389 {
2390 $title = ' title="' . htmlspecialchars ($addr['last_log']['user'] . ', ' . formatAge ($addr['last_log']['time']) , ENT_QUOTES) . '"';
2391 $history_class = 'hover-history underline';
2392 }
4318ced5
AA
2393 $tr_class .= ' ' . $addr['class'];
2394 echo "<tr class='tdleft $tr_class'>";
2395 echo "<td><a class='ancor $history_class' $title name='ip-$dottedquad' href='".makeHref(array('page'=>'ipaddress', 'ip'=>$addr['ip']))."'>${addr['ip']}</a></td>";
0b8d8309
AA
2396 $editable =
2397 (empty ($addr['allocs']) || !empty ($addr['name']))
2398 && permitted ('ipaddress', 'properties', 'editAddress')
2399 ? 'editable'
2400 : '';
2401 echo "<td><span class='rsvtext $editable id-$dottedquad op-upd-reservation-ip'>${addr['name']}</span></td>";
2402 echo "<td>";
b2035dca 2403 $delim = '';
b2035dca
DO
2404 if ( $addr['reserved'] == 'yes')
2405 {
2d318652 2406 echo "<strong>RESERVED</strong> ";
b2035dca
DO
2407 $delim = '; ';
2408 }
212b565a 2409 foreach ($addr['allocs'] as $ref)
b2035dca 2410 {
beb9e88a 2411 echo $delim . $aac2[$ref['type']];
4318ced5 2412 echo "<a href='".makeHref(array('page'=>'object', 'object_id'=>$ref['object_id'], 'tab' => 'default', 'hl_ip'=>$addr['ip']))."'>";
59a83bd8 2413 echo $ref['name'] . (!strlen ($ref['name']) ? '' : '@');
b2035dca
DO
2414 echo "${ref['object_name']}</a>";
2415 $delim = '; ';
2416 }
2417 if ($delim != '')
e0d6e38e 2418 $delim = '<br>';
212b565a
AA
2419 foreach ($addr['vslist'] as $vs_id)
2420 {
2421 $vs = spotEntity ('ipv4vs', $vs_id);
2422 echo "${delim}<a href='".makeHref(array('page'=>'ipv4vs', 'vs_id'=>$vs['id']))."'>";
2423 echo "${vs['name']}:${vs['vport']}/${vs['proto']}</a>&rarr;";
2424 $delim = '<br>';
2425 }
2426 foreach ($addr['rsplist'] as $rsp_id)
2427 {
2428 $rsp = spotEntity ('ipv4rspool', $rsp_id);
2429 echo "${delim}&rarr;<a href='".makeHref(array('page'=>'ipv4rspool', 'pool_id'=>$rsp['id']))."'>";
2430 echo "${rsp['name']}</a>";
2431 $delim = '<br>';
2432 }
b2035dca 2433 echo "</td></tr>\n";
4318ced5 2434 }
2727c7df 2435 // end of iteration
a8dc2982
AA
2436 if (permitted (NULL, NULL, 'set_reserve_comment'))
2437 addJS ('js/inplace-edit.js');
e673ee24
DO
2438
2439 echo "</table>";
446c25c3
AA
2440 if (! empty ($rendered_pager))
2441 echo '<p>' . $rendered_pager . '</p>';
21ee3351
AA
2442}
2443
2444function renderIPv6NetworkAddresses ($netinfo)
2445{
2446 global $pageno, $tabno, $aac2;
2447 echo "<table class='widetable' border=0 cellspacing=0 cellpadding=5 align='center' width='100%'>\n";
2448 echo "<tr><th>Address</th><th>Name</th><th>Allocation</th></tr>\n";
2449
4318ced5
AA
2450 $hl_ip = NULL;
2451 if (isset ($_REQUEST['hl_ip']))
2452 {
2453 $hl_ip = ip6_parse ($_REQUEST['hl_ip']);
2454 addAutoScrollScript ('ip-' . ip6_format ($hl_ip));
2455 }
21ee3351 2456
21ee3351
AA
2457 $addresses = $netinfo['addrlist'];
2458 ksort ($addresses);
4318ced5 2459 markupIPAddrList ($addresses);
21ee3351
AA
2460
2461 // pager
2462 $maxperpage = getConfigVar ('IPV4_ADDRS_PER_PAGE');
2463 if (count ($addresses) > $maxperpage && $maxperpage > 0)
2464 {
2465 $page = isset ($_REQUEST['pg']) ? $_REQUEST['pg'] : (isset ($hl_ip) ? getPageNumOfIPv6 ($addresses, $hl_ip, $maxperpage) : 0);
2466 $numpages = ceil (count ($addresses) / $maxperpage);
2467 echo "<center><h3>$numpages pages:</h3>";
2468 for ($i=0; $i<$numpages; $i++)
2469 {
2470 if ($i == $page)
2471 echo "<b>$i</b> ";
2472 else
2473 echo "<a href='" . makeHref (array ('page' => $pageno, 'tab' => $tabno, 'id' => $netinfo['id'], 'pg' => $i)) . "'>$i</a> ";
2474 }
2475 echo "</center>";
2476 }
2477
2478 $i = 0;
2479 $interruped = FALSE;
4318ced5
AA
2480 $prev_ip = ip_prev ($netinfo['ip_bin']);
2481 foreach ($addresses as $ip_bin => $addr)
21ee3351
AA
2482 {
2483 if (isset ($page))
2484 {
2485 ++$i;
2486 if ($i <= $maxperpage * $page)
2487 continue;
2488 elseif ($i > $maxperpage * ($page + 1))
2489 {
2490 $interruped = TRUE;
2491 break;
2492 }
2493 }
2494
4318ced5
AA
2495 if ($ip_bin != ip_next ($prev_ip))
2496 renderSeparator (ip_next ($prev_ip), ip_prev ($ip_bin), $hl_ip);
2497 $prev_ip = $ip_bin;
2498
2499 // render IP change history
2500 $title = '';
2501 $history_class = '';
2502 if (isset ($addr['last_log']))
2503 {
2504 $title = ' title="' . htmlspecialchars ($addr['last_log']['user'] . ', ' . formatAge ($addr['last_log']['time']) , ENT_QUOTES) . '"';
2505 $history_class = 'hover-history underline';
2506 }
2507
2508 $tr_class = $addr['class'] . ' tdleft' . ($hl_ip === $ip_bin ? ' port_highlight' : '');
2509 echo "<tr class='$tr_class'>";
2510 echo "<td><a class='ancor $history_class' $title name='ip-${addr['ip']}' href='" . makeHref (array ('page' => 'ipaddress', 'ip' => $addr['ip'])) . "'>${addr['ip']}</a></td>";
0b8d8309
AA
2511 $editable =
2512 (empty ($addr['allocs']) || !empty ($addr['name'])
2513 && permitted ('ipaddress', 'properties', 'editAddress')
2514 ? 'editable'
2515 : '');
2516 echo "<td><span class='rsvtext $editable id-${addr['ip']} op-upd-reservation-ip'>${addr['name']}</span></td><td>";
21ee3351 2517 $delim = '';
21ee3351
AA
2518 if ( $addr['reserved'] == 'yes')
2519 {
2520 echo "<strong>RESERVED</strong> ";
2521 $delim = '; ';
2522 }
2523 foreach ($addr['allocs'] as $ref)
2524 {
2525 echo $delim . $aac2[$ref['type']];
71066ef1 2526 echo "<a href='".makeHref(array('page'=>'object', 'object_id'=>$ref['object_id'], 'tab' => 'default', 'hl_ip'=>$addr['ip']))."'>";
21ee3351
AA
2527 echo $ref['name'] . (!strlen ($ref['name']) ? '' : '@');
2528 echo "${ref['object_name']}</a>";
2529 $delim = '; ';
2530 }
2531 if ($delim != '')
71066ef1
AA
2532 $delim = '<br>';
2533 foreach ($addr['vslist'] as $vs_id)
2534 {
2535 $vs = spotEntity ('ipv4vs', $vs_id);
2536 echo "${delim}<a href='".makeHref(array('page'=>'ipv4vs', 'vs_id'=>$vs['id']))."'>";
2537 echo "${vs['name']}:${vs['vport']}/${vs['proto']}</a>&rarr;";
2538 $delim = '<br>';
2539 }
2540 foreach ($addr['rsplist'] as $rsp_id)
21ee3351 2541 {
71066ef1
AA
2542 $rsp = spotEntity ('ipv4rspool', $rsp_id);
2543 echo "${delim}&rarr;<a href='".makeHref(array('page'=>'ipv4rspool', 'pool_id'=>$rsp['id']))."'>";
2544 echo "${rsp['name']}</a>";
2545 $delim = '<br>';
21ee3351
AA
2546 }
2547 echo "</td></tr>\n";
2548 }
2549 if (! $interruped)
4318ced5 2550 renderSeparator (ip_next ($prev_ip), ip_last ($netinfo), $hl_ip);
21ee3351
AA
2551 if (isset ($page))
2552 { // bottom pager
2553 echo "<tr><td colspan=3>";
2554 if ($page > 0)
2555 echo "<a href='" . makeHref (array ('page' => $pageno, 'tab' => $tabno, 'id' => $netinfo['id'], 'pg' => $page - 1)) . "'><< prev</a> ";
2556 if ($page < $numpages - 1)
2557 echo "<a href='" . makeHref (array ('page' => $pageno, 'tab' => $tabno, 'id' => $netinfo['id'], 'pg' => $page + 1)) . "'>next >></a> ";
2558 echo "</td></tr>";
2559 }
2560 echo "</table>";
a8dc2982
AA
2561 if (permitted (NULL, NULL, 'set_reserve_comment'))
2562 addJS ('js/inplace-edit.js');
21ee3351
AA
2563}
2564
2565function renderIPNetworkProperties ($id)
e673ee24 2566{
21ee3351
AA
2567 global $pageno;
2568 $netdata = spotEntity ($pageno, $id);
53ef3908 2569 echo "<center><h1>${netdata['ip']}/${netdata['mask']}</h1></center>\n";
e673ee24 2570 echo "<table border=0 cellpadding=10 cellpadding=1 align='center'>\n";
7056988c 2571 printOpFormIntro ('editRange');
99ab184f
DO
2572 echo '<tr><td class=tdright><label for=nameinput>Name:</label></td>';
2573 echo "<td class=tdleft><input type=text name=name id=nameinput size=80 maxlength=255 value='";
2574 echo htmlspecialchars ($netdata['name'], ENT_QUOTES, 'UTF-8') . "'></tr>";
2575 echo '<tr><td class=tdright><label for=commentinput>Comment:</label></td>';
2576 echo "<td class=tdleft><textarea name=comment id=commentinput cols=80 rows=25>\n";
2577 echo htmlspecialchars ($netdata['comment'], ENT_QUOTES, 'UTF-8') . "</textarea></tr>";
53ef3908
DO
2578 echo "<tr><td colspan=2 class=tdcenter>";
2579 printImageHREF ('SAVE', 'Save changes', TRUE);
2580 echo "</td></form></tr></table>\n";
93a49e5b
AA
2581
2582 echo '<center>';
2583 if (! isIPNetworkEmpty ($netdata))
2584 echo getOpLink (NULL, 'delete this prefix', 'nodestroy', 'There are ' . count ($netdata['addrlist']) . ' allocations inside');
2585 else
2586 echo getOpLink (array('op'=>'del','id'=>$id), 'delete this prefix', 'destroy');
2587 echo '</center>';
e673ee24
DO
2588}
2589
4318ced5 2590function renderIPAddress ($ip)
e673ee24 2591{
46098972 2592 global $aat, $nextorder;
4318ced5 2593 $address = getIPAddress (ip_parse ($ip));
68225375 2594 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
21ee3351 2595 echo "<tr><td colspan=2 align=center><h1>${address['ip']}</h1></td></tr>\n";
e673ee24 2596
68225375 2597 echo "<tr><td class=pcleft>";
defd92d8
AA
2598
2599 $summary = array();
423c4216 2600 if (strlen ($address['name']))
defd92d8
AA
2601 $summary['Comment'] = $address['name'];
2602 $summary['Reserved'] = $address['reserved'];
2603 $summary['Allocations'] = count ($address['allocs']);
4318ced5 2604 if (isset ($address['outpf']))
defd92d8 2605 $summary['Originated NAT connections'] = count ($address['outpf']);
4318ced5 2606 if (isset ($address['inpf']))
defd92d8 2607 $summary['Arriving NAT connections'] = count ($address['inpf']);
defd92d8 2608 renderEntitySummary ($address, 'summary', $summary);
212b565a
AA
2609
2610 // render SLB portlet
4318ced5 2611 if (! empty ($address['vslist']) or ! empty ($address['rsplist']))
212b565a
AA
2612 {
2613 startPortlet ("");
2614 if (! empty ($address['vslist']))
2615 {
2616 printf ("<h2>virtual services (%d):</h2>", count ($address['vslist']));
2617 foreach ($address['vslist'] as $vs_id)
2618 renderSLBEntityCell (spotEntity ('ipv4vs', $vs_id));
2619 }
2620
2621 if (! empty ($address['rsplist']))
2622 {
2623 printf ("<h2>RS pools (%d):</h2>", count ($address['rsplist']));
2624 foreach ($address['rsplist'] as $rsp_id)
2625 renderSLBEntityCell (spotEntity ('ipv4rspool', $rsp_id));
2626 }
2627 finishPortlet();
2628 }
68225375 2629 echo "</td>\n";
e673ee24 2630
68225375 2631 echo "<td class=pcright>";
defd92d8 2632 if (isset ($address['class']) and ! empty ($address['allocs']))
59bebe2b 2633 {
8e700dd1 2634 startPortlet ('allocations');
2d318652
DO
2635 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2636 echo "<tr><th>object</th><th>OS interface</th><th>allocation type</th></tr>\n";
2d318652 2637 // render all allocation records for this address the same way
2d318652 2638 foreach ($address['allocs'] as $bond)
59bebe2b 2639 {
4318ced5 2640 $tr_class = "${address['class']} tdleft";
8e700dd1 2641 if (isset ($_REQUEST['hl_object_id']) and $_REQUEST['hl_object_id'] == $bond['object_id'])
4318ced5
AA
2642 $tr_class .= ' port_highlight';
2643 echo "<tr class='$tr_class'>" .
2644 "<td><a href='" . makeHref (array ('page' => 'object', 'object_id' => $bond['object_id'], 'tab' => 'default', 'hl_ip' => $address['ip'])) . "'>${bond['object_name']}</td>" .
2645 "<td>${bond['name']}</td>" .
2646 "<td><strong>" . $aat[$bond['type']] . "</strong></td>" .
2647 "</tr>\n";
59bebe2b
DO
2648 }
2649 echo "</table><br><br>";
2650 finishPortlet();
2651 }
e673ee24 2652
4318ced5 2653 if (! empty ($address['vslist']) or ! empty ($address['rsplist']))
defd92d8 2654 renderSLBTriplets ($address);
5fe1ed76 2655
21ee3351 2656 if (! empty ($address['outpf']))
68225375 2657 {
105a3bc8 2658 startPortlet ('departing NAT rules');
2d318652 2659 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
105a3bc8
DO
2660 echo "<tr><th>proto</th><th>from</th><th>to</th><th>comment</th></tr>\n";
2661 foreach ($address['outpf'] as $rule)
b62ff880 2662 echo "<tr><td>${rule['proto']}</td><td>${rule['localip']}:${rule['localport']}</td><td>${rule['remoteip']}:${rule['remoteport']}</td><td>${rule['description']}</td></tr>";
105a3bc8 2663 echo "</table>";
68225375
DO
2664 finishPortlet();
2665 }
105a3bc8 2666
21ee3351 2667 if (! empty ($address['inpf']))
105a3bc8
DO
2668 {
2669 startPortlet ('arriving NAT rules');
2d318652 2670 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
105a3bc8
DO
2671 echo "<tr><th>proto</th><th>from</th><th>to</th><th>comment</th></tr>\n";
2672 foreach ($address['inpf'] as $rule)
b62ff880 2673 echo "<tr><td>${rule['proto']}</td><td>${rule['localip']}:${rule['localport']}</td><td>${rule['remoteip']}:${rule['remoteport']}</td><td>${rule['description']}</td></tr>";
105a3bc8
DO
2674 echo "</table>";
2675 finishPortlet();
2676 }
2677
68225375
DO
2678 echo "</td></tr>";
2679 echo "</table>\n";
e673ee24
DO
2680}
2681
4318ced5 2682function renderIPAddressProperties ($ip)
e673ee24 2683{
4318ced5 2684 $address = getIPAddress (ip_parse ($ip));
21ee3351 2685 echo "<center><h1>${address['ip']}</h1></center>\n";
7056988c 2686
1fbc9fd6 2687 startPortlet ('update');
e673ee24 2688 echo "<table border=0 cellpadding=10 cellpadding=1 align='center'>\n";
7056988c 2689 printOpFormIntro ('editAddress');
0186638b
DO
2690 echo '<tr><td class=tdright><label for=id_name>Name:</label></td>';
2691 echo "<td class=tdleft><input type=text name=name id=id_name size=20 value='${address['name']}'></tr>";
2692 echo '<td class=tdright><label for=id_reserved>Reserved:</label></td>';
2693 echo "<td class=tdleft><input type=checkbox name=reserved id=id_reserved size=20 ";
2d318652 2694 echo ($address['reserved']=='yes') ? 'checked' : '';
f3d274bf 2695 echo "></tr><tr><td class=tdleft>";
53ef3908 2696 printImageHREF ('SAVE', 'Save changes', TRUE);
f3d274bf 2697 echo "</td></form><td class=tdright>";
59a83bd8 2698 if (!strlen ($address['name']) and $address['reserved'] == 'no')
f3d274bf
DO
2699 printImageHREF ('CLEAR gray');
2700 else
2701 {
2702 printOpFormIntro ('editAddress', array ('name' => '', 'reserved' => ''));
2703 printImageHREF ('CLEAR', 'Release', TRUE);
2704 echo "</form>";
2705 }
2706 echo "</td></tr></table>\n";
1fbc9fd6 2707 finishPortlet();
e673ee24
DO
2708}
2709
4318ced5 2710function renderIPAddressAllocations ($ip)
e673ee24 2711{
4318ced5 2712 function printNewItemTR ()
39b4abd0
DO
2713 {
2714 global $aat;
4318ced5 2715 printOpFormIntro ('add');
39b4abd0 2716 echo "<tr><td>";
9318d2ef 2717 printImageHREF ('add', 'allocate', TRUE);
8d4f7d18 2718 echo "</td><td>";
31babb65 2719 printSelect (getNarrowObjectList ('IPV4OBJ_LISTSRC'), array ('name' => 'object_id', 'tabindex' => 100));
8d4f7d18 2720 echo "</td><td><input type=text tabindex=101 name=bond_name size=10></td><td>";
01abf1de 2721 printSelect ($aat, array ('name' => 'bond_type', 'tabindex' => 102, 'regular'));
9318d2ef 2722 echo "</td><td>";
f5ff50f5 2723 printImageHREF ('add', 'allocate', TRUE, 103);
9318d2ef 2724 echo "</td></form></tr>";
39b4abd0 2725 }
b82cce3f 2726 global $aat;
e673ee24 2727
4318ced5 2728 $address = getIPAddress (ip_parse ($ip));
21ee3351 2729 echo "<center><h1>${address['ip']}</h1></center>\n";
105a3bc8 2730 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
2d318652 2731 echo "<tr><th>&nbsp;</th><th>object</th><th>OS interface</th><th>allocation type</th><th>&nbsp;</th></tr>\n";
e673ee24 2732
39b4abd0 2733 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
4318ced5 2734 printNewItemTR();
f74d96c6 2735 if (isset ($address['class']))
e673ee24 2736 {
f74d96c6
DO
2737 $class = $address['class'];
2738 if ($address['reserved'] == 'yes')
2739 echo "<tr class='${class}'><td colspan=3>&nbsp;</td><td class=tdleft><strong>RESERVED</strong></td><td>&nbsp;</td></tr>";
2740 foreach ($address['allocs'] as $bond)
2741 {
2742 echo "<tr class='$class'>";
4318ced5 2743 printOpFormIntro ('upd', array ('object_id' => $bond['object_id']));
21ee3351
AA
2744 echo "<td><a href='"
2745 . makeHrefProcess
2746 (
2747 array
2748 (
4318ced5 2749 'op' => 'del',
21ee3351
AA
2750 'ip' => $address['ip'],
2751 'object_id' => $bond['object_id']
2752 )
2753 )
2754 . "'>";
f74d96c6
DO
2755 printImageHREF ('delete', 'Unallocate address');
2756 echo "</a></td>";
4318ced5 2757 echo "<td><a href='" . makeHref (array ('page' => 'object', 'object_id' => $bond['object_id'], 'hl_ip' => $address['ip'])) . "'>${bond['object_name']}</td>";
f74d96c6 2758 echo "<td><input type='text' name='bond_name' value='${bond['name']}' size=10></td><td>";
cd3775e9 2759 printSelect ($aat, array ('name' => 'bond_type'), $bond['type']);
f74d96c6
DO
2760 echo "</td><td>";
2761 printImageHREF ('save', 'Save changes', TRUE);
2762 echo "</td></form></tr>\n";
2763 }
e673ee24 2764 }
39b4abd0 2765 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
4318ced5 2766 printNewItemTR();
e673ee24 2767 echo "</table><br><br>";
e673ee24
DO
2768}
2769
7e1db771 2770function renderNATv4ForObject ($object_id)
e673ee24 2771{
9318d2ef
DO
2772 function printNewItemTR ($alloclist)
2773 {
9318d2ef
DO
2774 printOpFormIntro ('addNATv4Rule');
2775 echo "<tr align='center'><td>";
2776 printImageHREF ('add', 'Add new NAT rule', TRUE);
2777 echo '</td><td>';
cd3775e9 2778 printSelect (array ('TCP' => 'TCP', 'UDP' => 'UDP'), array ('name' => 'proto'));
9318d2ef
DO
2779 echo "<select name='localip' tabindex=1>";
2780
4318ced5 2781 foreach ($alloclist as $ip_bin => $alloc)
9318d2ef 2782 {
4318ced5 2783 $ip = $alloc['addrinfo']['ip'];
43eb71f1
DO
2784 $name = (!isset ($alloc['addrinfo']['name']) or !strlen ($alloc['addrinfo']['name'])) ? '' : (' (' . niftyString ($alloc['addrinfo']['name']) . ')');
2785 $osif = (!isset ($alloc['osif']) or !strlen ($alloc['osif'])) ? '' : ($alloc['osif'] . ': ');
4318ced5 2786 echo "<option value='${ip}'>${osif}${ip}${name}</option>";
9318d2ef
DO
2787 }
2788
2789 echo "</select>:<input type='text' name='localport' size='4' tabindex=2></td>";
2790 echo "<td><input type='text' name='remoteip' id='remoteip' size='10' tabindex=3>";
39106006
DO
2791 echo "<a href='javascript:;' onclick='window.open(\"" . makeHrefForHelper ('inet4list');
2792 echo "\", \"findobjectip\", \"height=700, width=400, location=no, menubar=no, resizable=yes, scrollbars=no, status=no, titlebar=no, toolbar=no\");'>";
9318d2ef
DO
2793 printImageHREF ('find', 'Find object');
2794 echo "</a>";
2795 echo ":<input type='text' name='remoteport' size='4' tabindex=4></td><td></td>";
2796 echo "<td colspan=1><input type='text' name='description' size='20' tabindex=5></td><td>";
f5ff50f5 2797 printImageHREF ('add', 'Add new NAT rule', TRUE, 6);
9318d2ef
DO
2798 echo "</td></tr></form>";
2799 }
e673ee24 2800
94fe6370
DO
2801 $focus = spotEntity ('object', $object_id);
2802 amplifyCell ($focus);
f28fbe8b 2803 echo "<center><h2>locally performed NAT</h2></center>";
e673ee24 2804
105a3bc8 2805 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
d54b9495 2806 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 2807
9318d2ef 2808 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
94fe6370
DO
2809 printNewItemTR ($focus['ipv4']);
2810 foreach ($focus['nat4']['out'] as $pf)
e673ee24 2811 {
2c817354
DO
2812 $class = 'trerror';
2813 $osif = '';
4318ced5
AA
2814 $localip_bin = ip4_parse ($pf['localip']);
2815 if (isset ($focus['ipv4'][$localip_bin]))
2c817354 2816 {
4318ced5
AA
2817 $class = $focus['ipv4'][$localip_bin]['addrinfo']['class'];
2818 $osif = $focus['ipv4'][$localip_bin]['osif'] . ': ';
2c817354 2819 }
e673ee24
DO
2820
2821 echo "<tr class='$class'>";
4fbb5a00
DY
2822 echo "<td><a href='".
2823 makeHrefProcess(array(
2824 'op'=>'delNATv4Rule',
2825 'localip'=>$pf['localip'],
2826 'localport'=>$pf['localport'],
2827 'remoteip'=>$pf['remoteip'],
2828 'remoteport'=>$pf['remoteport'],
2829 'proto'=>$pf['proto'],
2830 'object_id'=>$object_id)).
2831 "'>";
4de22e7e
DO
2832 printImageHREF ('delete', 'Delete NAT rule');
2833 echo "</a></td>";
4fbb5a00 2834 echo "<td>${pf['proto']}/${osif}<a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['localip']))."'>${pf['localip']}</a>:${pf['localport']}";
59a83bd8 2835 if (strlen ($pf['local_addr_name']))
f28fbe8b
DO
2836 echo ' (' . $pf['local_addr_name'] . ')';
2837 echo "</td>";
4fbb5a00 2838 echo "<td><a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['remoteip']))."'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
e673ee24 2839
4318ced5 2840 $address = getIPAddress (ip4_parse ($pf['remoteip']));
e673ee24
DO
2841
2842 echo "<td class='description'>";
53ef3908
DO
2843 if (count ($address['allocs']))
2844 foreach ($address['allocs'] as $bond)
4fbb5a00 2845 echo "<a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$bond['object_id']))."'>${bond['object_name']}(${bond['name']})</a> ";
59a83bd8 2846 elseif (strlen ($pf['remote_addr_name']))
f28fbe8b 2847 echo '(' . $pf['remote_addr_name'] . ')';
7056988c
DO
2848 printOpFormIntro
2849 (
2850 'updNATv4Rule',
2851 array
2852 (
2853 'localip' => $pf['localip'],
2854 'localport' => $pf['localport'],
2855 'remoteip' => $pf['remoteip'],
2856 'remoteport' => $pf['remoteport'],
2857 'proto' => $pf['proto']
2858 )
2859 );
2860 echo "</td><td class='description'>";
d54b9495
DO
2861 echo "<input type='text' name='description' value='${pf['description']}'></td><td>";
2862 printImageHREF ('save', 'Save changes', TRUE);
2863 echo "</td></form></tr>";
e673ee24 2864 }
9318d2ef 2865 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
94fe6370 2866 printNewItemTR ($focus['ipv4']);
e673ee24
DO
2867
2868 echo "</table><br><br>";
94fe6370
DO
2869 if (!count ($focus['nat4']))
2870 return;
e673ee24 2871
f28fbe8b 2872 echo "<center><h2>arriving NAT connections</h2></center>";
105a3bc8 2873 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
e673ee24
DO
2874 echo "<tr><th></th><th>Source</th><th>Source objects</th><th>Target</th><th>Description</th></tr>\n";
2875
94fe6370 2876 foreach ($focus['nat4']['in'] as $pf)
e673ee24 2877 {
4fbb5a00
DY
2878 echo "<tr><td><a href='".
2879 makeHrefProcess(array(
2880 'op'=>'delNATv4Rule',
2881 'localip'=>$pf['localip'],
2882 'localport'=>$pf['localport'],
2883 'remoteip'=>$pf['remoteip'],
2884 'remoteport'=>$pf['remoteport'],
2885 'proto'=>$pf['proto'],
2886 'object_id'=>$pf['object_id']
2887 )).
2888 "'>";
4de22e7e
DO
2889 printImageHREF ('delete', 'Delete NAT rule');
2890 echo "</a></td>";
4fbb5a00
DY
2891 echo "<td>${pf['proto']}/<a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['localip']))."'>${pf['localip']}</a>:${pf['localport']}</td>";
2892 echo "<td class='description'><a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$pf['object_id']))."'>${pf['object_name']}</a>";
2893 echo "</td><td><a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['remoteip']))."'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
e673ee24
DO
2894 echo "<td class='description'>${pf['description']}</td></tr>";
2895 }
2896
e673ee24 2897 echo "</table><br><br>";
e673ee24
DO
2898}
2899
e673ee24
DO
2900function renderAddMultipleObjectsForm ()
2901{
8dc2a6c8 2902 global $location_obj_types, $virtual_obj_types;
7fa7047a 2903 $typelist = readChapter (CHAP_OBJTYPE, 'o');
4c330a14 2904 $typelist[0] = 'select type...';
7fa7047a 2905 $typelist = cookOptgroups ($typelist);
a1886a78
DO
2906 $max = getConfigVar ('MASSCOUNT');
2907 $tabindex = 100;
7f791d1d 2908
9b8174d7
AD
2909 // create a list of object types to exclude (virtual and location-related ones)
2910 $exclude_typelist = array_merge($location_obj_types, $virtual_obj_types);
2911
0682218d
AD
2912 $phys_typelist = $typelist;
2913 foreach ($phys_typelist['other'] as $key => $value)
2914 {
9b8174d7
AD
2915 // remove from list if type should be excluded
2916 if ($key > 0 && in_array($key, $exclude_typelist))
0682218d
AD
2917 unset($phys_typelist['other'][$key]);
2918 }
2b787762 2919 startPortlet ('Physical objects');
42d73cbf 2920 printOpFormIntro ('addObjects');
e673ee24 2921 echo '<table border=0 align=center>';
f60bb422 2922 echo "<tr><th>Object type</th><th>Common name</th><th>Visible label</th>";
dee24af6 2923 echo "<th>Asset tag</th><th>Tags</th></tr>\n";
9c0b0016 2924 for ($i = 0; $i < $max; $i++)
e673ee24 2925 {
7f791d1d 2926 echo '<tr><td>';
e7ade6bf 2927 // Don't employ DEFAULT_OBJECT_TYPE to avoid creating ghost records for pre-selected empty rows.
0682218d 2928 printNiftySelect ($phys_typelist, array ('name' => "${i}_object_type_id", 'tabindex' => $tabindex), 0);
e673ee24 2929 echo '</td>';
a1886a78
DO
2930 echo "<td><input type=text size=30 name=${i}_object_name tabindex=${tabindex}></td>";
2931 echo "<td><input type=text size=30 name=${i}_object_label tabindex=${tabindex}></td>";
2932 echo "<td><input type=text size=20 name=${i}_object_asset_no tabindex=${tabindex}></td>";
f60bb422
DO
2933 if ($i == 0)
2934 {
2935 echo "<td valign=top rowspan=${max}>";
a26a6ccc 2936 renderNewEntityTags ('object');
f60bb422
DO
2937 echo "</td>\n";
2938 }
e673ee24 2939 echo "</tr>\n";
a1886a78 2940 $tabindex++;
e673ee24 2941 }
216c84bb 2942 echo "<tr><td class=submit colspan=5><input type=submit name=got_fast_data value='Go!'></td></tr>\n";
e673ee24
DO
2943 echo "</form></table>\n";
2944 finishPortlet();
7f791d1d 2945
0682218d 2946 // create a list containing only virtual object types
0682218d
AD
2947 $virt_typelist = $typelist;
2948 foreach ($virt_typelist['other'] as $key => $value)
2949 {
2c2ea5f6 2950 if ($key > 0 && !in_array($key, $virtual_obj_types))
0682218d
AD
2951 unset($virt_typelist['other'][$key]);
2952 }
2953 startPortlet ('Virtual objects');
2954 printOpFormIntro ('addObjects');
2955 echo "<input type=hidden name=virtual_objects value=''>\n";
2956 echo '<table border=0 align=center>';
2957 echo "<tr><th>Object type</th><th>Common name</th><th>Tags</th></tr>\n";
2958 for ($i = 0; $i < $max; $i++)
2959 {
2960 echo '<tr><td>';
2961 // Don't employ DEFAULT_OBJECT_TYPE to avoid creating ghost records for pre-selected empty rows.
2962 printNiftySelect ($virt_typelist, array ('name' => "${i}_object_type_id", 'tabindex' => $tabindex), 0);
2963 echo '</td>';
2964 echo "<td><input type=text size=30 name=${i}_object_name tabindex=${tabindex}></td>";
2965 if ($i == 0)
2966 {
2967 echo "<td valign=top rowspan=${max}>";
2968 renderNewEntityTags ('object');
2969 echo "</td>\n";
2970 }
2971 echo "</tr>\n";
2972 $tabindex++;
2973 }
2974 echo "<tr><td class=submit colspan=5><input type=submit name=got_fast_data value='Go!'></td></tr>\n";
2975 echo "</form></table>\n";
2976 finishPortlet();
2977
f60bb422 2978 startPortlet ('Same type, same tags');
42d73cbf 2979 printOpFormIntro ('addLotOfObjects');
f60bb422
DO
2980 echo "<table border=0 align=center><tr><th>names</th><th>type</th></tr>";
2981 echo "<tr><td rowspan=3><textarea name=namelist cols=40 rows=25>\n";
f60bb422 2982 echo "</textarea></td><td valign=top>";
cd3775e9 2983 printNiftySelect ($typelist, array ('name' => 'global_type_id'), getConfigVar ('DEFAULT_OBJECT_TYPE'));
f60bb422
DO
2984 echo "</td></tr>";
2985 echo "<tr><th>Tags</th></tr>";
2986 echo "<tr><td valign=top>";
a26a6ccc 2987 renderNewEntityTags ('object');
f60bb422
DO
2988 echo "</td></tr>";
2989 echo "<tr><td colspan=2><input type=submit name=got_very_fast_data value='Go!'></td></tr></table>\n";
2990 echo "</form>\n";
7f791d1d 2991 finishPortlet();
e673ee24
DO
2992}
2993
671027eb
DO
2994function searchHandler()
2995{
e673ee24 2996 $terms = trim ($_REQUEST['q']);
59a83bd8 2997 if (!strlen ($terms))
0cc24e9a 2998 throw new InvalidRequestArgException('q', $_REQUEST['q'], 'Search string cannot be empty.');
671027eb 2999 renderSearchResults ($terms, searchEntitiesByText ($terms));
09ce7c20 3000}
25e55cab 3001
521cd29a 3002function renderSearchResults ($terms, $summary)
09ce7c20 3003{
521cd29a
AA
3004 // calculate the number of found objects
3005 $nhits = 0;
3006 foreach ($summary as $realm => $list)
3007 $nhits += count ($list);
3008
ea5fc465
DO
3009 if ($nhits == 0)
3010 echo "<center><h2>Nothing found for '${terms}'</h2></center>";
3011 elseif ($nhits == 1)
3012 {
6427286d
AA
3013 foreach ($summary as $realm => $record)
3014 {
3015 if (is_array ($record))
3016 $record = array_shift ($record);
3017 break;
3018 }
521cd29a 3019 switch ($realm)
ea5fc465 3020 {
f3d0cb20 3021 case 'ipv4addressbydq':
521cd29a 3022 if ($record['net_id'] !== NULL)
4318ced5 3023 echo "<script language='Javascript'>document.location='index.php?page=ipv4net&tab=default&id=${record['net_id']}&hl_ip=${record['ip']}';//</script>";
ea5fc465 3024 break;
21ee3351 3025 case 'ipv6addressbydq':
4318ced5 3026 $fmt = ip6_format ($record['ip']);
521cd29a 3027 if ($record['net_id'] !== NULL)
4318ced5 3028 echo "<script language='Javascript'>document.location='index.php?page=ipv6net&tab=default&id=${record['net_id']}&hl_ip=${fmt}';//</script>";
21ee3351 3029 break;
f3d0cb20
DO
3030 case 'ipv4addressbydescr':
3031 $parentnet = getIPv4AddressNetworkId ($record['ip']);
3032 if ($parentnet !== NULL)
4318ced5
AA
3033 {
3034 $fmt = ip4_format ($record['ip']);
3035 echo "<script language='Javascript'>document.location='index.php?page=ipv4net&tab=default&id=${parentnet}&hl_ip=${fmt}';//</script>";
3036 }
ea5fc465 3037 break;
21ee3351 3038 case 'ipv6addressbydescr':
4318ced5 3039 $parentnet = getIPv6AddressNetworkId ($record['ip']);
21ee3351 3040 if ($parentnet !== NULL)
4318ced5
AA
3041 {
3042 $fmt = ip6_format ($record['ip']);
3043 echo "<script language='Javascript'>document.location='index.php?page=ipv6net&tab=default&id=${parentnet}&hl_ip=${fmt}';//</script>";
3044 }
21ee3351 3045 break;
ea5fc465 3046 case 'ipv4network':
790a60e8 3047 echo "<script language='Javascript'>document.location='index.php?page=ipv4net";
ea5fc465
DO
3048 echo "&id=${record['id']}";
3049 echo "';//</script>";
3050 break;
21ee3351
AA
3051 case 'ipv6network':
3052 echo "<script language='Javascript'>document.location='index.php?page=ipv6net";
3053 echo "&id=${record['id']}";
3054 echo "';//</script>";
3055 break;
ea5fc465 3056 case 'object':
1b4a0a6a 3057 if (isset ($record['by_port']) and 1 == count ($record['by_port']))
7e74a507
AA
3058 {
3059 $found_ports_ids = array_keys ($record['by_port']);
3060 $hl = '&hl_port_id=' . $found_ports_ids[0];
3061 }
1b4a0a6a
DO
3062 else
3063 $hl = '';
790a60e8 3064 echo "<script language='Javascript'>document.location='index.php?page=object&object_id=${record['id']}${hl}';//</script>";
ea5fc465 3065 break;
05411ccd 3066 case 'ipv4rspool':
790a60e8 3067 echo "<script language='Javascript'>document.location='index.php?page=ipv4rspool&pool_id=${record['id']}';//</script>";
05411ccd
DO
3068 break;
3069 case 'ipv4vs':
790a60e8 3070 echo "<script language='Javascript'>document.location='index.php?page=ipv4vs&vs_id=${record['id']}';//</script>";
05411ccd 3071 break;
6a88e734 3072 case 'user':
790a60e8 3073 echo "<script language='Javascript'>document.location='index.php?page=user&user_id=${record['user_id']}';//</script>";
6a88e734 3074 break;
e1ae3fb4 3075 case 'file':
790a60e8 3076 echo "<script language='Javascript'>document.location='index.php?page=file&file_id=${record['id']}';//</script>";
e1ae3fb4 3077 break;
e531b4d6 3078 case 'rack':
790a60e8 3079 echo "<script language='Javascript'>document.location='index.php?page=rack&rack_id=${record['id']}';//</script>";
e531b4d6 3080 break;
1f54e1ba
DO
3081 case 'vlan':
3082 echo "<script language='Javascript'>document.location='index.php?page=vlan&vlan_ck=${record}';//</script>";
3083 break;
fc359703
AA
3084 default:
3085 startPortlet($realm);
3086 echo $record;
3087 finishPortlet();
ea5fc465
DO
3088 }
3089 return;
3090 }
3091 else
3092 {
3093 global $nextorder;
3094 $order = 'odd';
3095 echo "<center><h2>${nhits} result(s) found for '${terms}'</h2></center>";
3096 foreach ($summary as $where => $what)
3097 switch ($where)
e673ee24 3098 {
ea5fc465 3099 case 'object':
790a60e8 3100 startPortlet ("<a href='index.php?page=depot'>Objects</a>");
323edbbf
DO
3101 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
3102 echo '<tr><th>what</th><th>why</th></tr>';
3103 foreach ($what as $obj)
3104 {
3105 echo "<tr class=row_${order} valign=top><td>";
9f75e165
DO
3106 $object = spotEntity ('object', $obj['id']);
3107 renderCell ($object);
b1f60545
DO
3108 echo "</td><td class=tdleft>";
3109 if (isset ($obj['by_attr']))
3110 {
3111 // only explain non-obvious reasons for listing
3112 echo '<ul>';
3113 foreach ($obj['by_attr'] as $attr_name)
3114 if ($attr_name != 'name')
3115 echo "<li>${attr_name} matched</li>";
3116 echo '</ul>';
3117 }
323edbbf
DO
3118 if (isset ($obj['by_sticker']))
3119 {
3120 echo '<table>';
3121 $aval = getAttrValues ($obj['id']);
3122 foreach ($obj['by_sticker'] as $attr_id)
3123 {
0794fb66 3124 $record = $aval[$attr_id];
323edbbf 3125 echo "<tr><th width='50%' class=sticker>${record['name']}:</th>";
8ad59489 3126 echo "<td class=sticker>" . formatAttributeValue ($record) . "</td></tr>";
323edbbf
DO
3127 }
3128 echo '</table>';
3129 }
d516d719 3130 if (isset ($obj['by_port']))
323edbbf
DO
3131 {
3132 echo '<table>';
9f75e165 3133 amplifyCell ($object);
1b4a0a6a 3134 foreach ($obj['by_port'] as $port_id => $text)
9f75e165 3135 foreach ($object['ports'] as $port)
323edbbf
DO
3136 if ($port['id'] == $port_id)
3137 {
521cd29a
AA
3138 $port_href = '<a href="' . makeHref (array
3139 (
3140 'page' => 'object',
3141 'object_id' => $object['id'],
3142 'hl_port_id' => $port_id
3143 )) . '">port ' . $port['name'] . '</a>';
3144 echo "<tr><td>${port_href}:</td>";
1b4a0a6a 3145 echo "<td class=tdleft>${text}</td></tr>";
323edbbf
DO
3146 break; // next reason
3147 }
3148 echo '</table>';
3149 }
5fd2a004
DO
3150 if (isset ($obj['by_iface']))
3151 {
3152 echo '<ul>';
3153 foreach ($obj['by_iface'] as $ifname)
3154 echo "<li>interface ${ifname}</li>";
3155 echo '</ul>';
3156 }
3157 if (isset ($obj['by_nat']))
3158 {
3159 echo '<ul>';
3160 foreach ($obj['by_nat'] as $comment)
3161 echo "<li>NAT rule: ${comment}</li>";
3162 echo '</ul>';
3163 }
6a4339ed
DO
3164 if (isset ($obj['by_cableid']))
3165 {
3166 echo '<ul>';
3167 foreach ($obj['by_cableid'] as $cableid)
3168 echo "<li>link cable ID: ${cableid}</li>";
3169 echo '</ul>';
3170 }
323edbbf
DO
3171 echo "</td></tr>";
3172 $order = $nextorder[$order];
ea5fc465
DO
3173 }
3174 echo '</table>';
3175 finishPortlet();
3176 break;
3177 case 'ipv4network':
790a60e8 3178 startPortlet ("<a href='index.php?page=ipv4space'>IPv4 networks</a>");
21ee3351
AA
3179 case 'ipv6network':
3180 if ($where == 'ipv6network')
3181 startPortlet ("<a href='index.php?page=ipv6space'>IPv6 networks</a>");
3182
ea5fc465 3183 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
6df2025d 3184 foreach ($what as $cell)
ea5fc465 3185 {
0b9c98d7 3186 echo "<tr class=row_${order} valign=top><td>";
6df2025d 3187 renderCell ($cell);
0b9c98d7 3188 echo "</td></tr>\n";
ea5fc465
DO
3189 $order = $nextorder[$order];
3190 }
3191 echo '</table>';
3192 finishPortlet();
3193 break;
f3d0cb20 3194 case 'ipv4addressbydescr':
ea5fc465
DO
3195 startPortlet ('IPv4 addresses');
3196 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
f3d0cb20 3197 // FIXME: address, parent network, routers (if extended view is enabled)
e1ae3fb4 3198 echo '<tr><th>Address</th><th>Description</th></t