r5079 bugfix: running VLAN list was not always correct with ios12 and nxos4 gateways
[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>";
884 echo "<td class='tdleft rsvtext'>${port['cableid']}</td>";
885 }
886 else
887 echo implode ('', formatPortReservation ($port)) . '<td></td>';
888 echo "</tr>";
889}
890
9b8174d7 891function renderObject ($object_id)
e673ee24 892{
8dc2a6c8 893 global $nextorder, $virtual_obj_types;
fb6e2f57 894 $info = spotEntity ('object', $object_id);
94fe6370 895 amplifyCell ($info);
e673ee24
DO
896 // Main layout starts.
897 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
898 echo "<tr><td colspan=2 align=center><h1>${info['dname']}</h1></td></tr>\n";
899 // left column with uknown number of portlets
900 echo "<tr><td class=pcleft>";
646272be
AA
901
902 // display summary portlet
903 $summary = array();
59a83bd8 904 if (strlen ($info['name']))
646272be 905 $summary['Common name'] = $info['name'];
94fe6370 906 elseif (considerConfiguredConstraint ($info, 'NAMEWARN_LISTSRC'))
646272be
AA
907 $summary[] = array ('<tr><td colspan=2 class=msg_error>Common name is missing.</td></tr>');
908 $summary['Object type'] = '<a href="' . makeHref (array (
341fd895
DO
909 'page' => 'depot',
910 'tab' => 'default',
911 'cfe' => '{$typeid_' . $info['objtype_id'] . '}'
646272be 912 )) . '">' . decodeObjectType ($info['objtype_id'], 'o') . '</a>';
9b8174d7 913 if (strlen ($info['label']))
646272be 914 $summary['Visible label'] = $info['label'];
59a83bd8 915 if (strlen ($info['asset_no']))
646272be 916 $summary['Asset tag'] = $info['asset_no'];
d4e8ddeb 917 elseif (considerConfiguredConstraint ($info, 'ASSETWARN_LISTSRC'))
646272be
AA
918 $summary[] = array ('<tr><td colspan=2 class=msg_error>Asset tag is missing.</td></tr>');
919 $parents = getEntityRelatives ('parents', 'object', $object_id);
920 if (count ($parents))
0682218d 921 {
646272be 922 $fmt_parents = array();
0682218d 923 foreach ($parents as $parent)
8023ee39
AA
924 $fmt_parents[] = "<a href='".makeHref(array('page'=>$parent['page'], $parent['id_name'] => $parent['entity_id']))."'>${parent['name']}</a>";
925 $summary[count($parents) > 1 ? 'Containers' : 'Container'] = implode ('<br>', $fmt_parents);
0682218d 926 }
646272be
AA
927 $children = getEntityRelatives ('children', 'object', $object_id);
928 if (count ($children))
0682218d 929 {
646272be 930 $fmt_children = array();
0682218d 931 foreach ($children as $child)
8023ee39 932 $fmt_children[] = "<a href='".makeHref(array('page'=>$child['page'], $child['id_name']=>$child['entity_id']))."'>${child['name']}</a>";
dcde9835 933 $summary['Contains'] = implode ('<br>', $fmt_children);
0682218d 934 }
e673ee24 935 if ($info['has_problems'] == 'yes')
646272be 936 $summary[] = array ('<tr><td colspan=2 class=msg_error>Has problems</td></tr>');
8ad59489 937 foreach (getAttrValues ($object_id) as $record)
4969aa31
DO
938 if
939 (
940 strlen ($record['value']) and
941 permitted (NULL, NULL, NULL, array (array ('tag' => '$attr_' . $record['id'])))
942 )
646272be 943 $summary['{sticker}' . $record['name']] = formatAttributeValue ($record);
a2c597ea
AA
944 $summary[] = array (getOutputOf ('printTagTRs',
945 $info,
946 makeHref
947 (
948 array
949 (
950 'page'=>'depot',
951 'tab'=>'default',
952 'andor' => 'and',
953 'cfe' => '{$typeid_' . $info['objtype_id'] . '}',
954 )
955 )."&"
956 ));
646272be 957 renderEntitySummary ($info, 'summary', $summary);
e673ee24 958
59a83bd8 959 if (strlen ($info['comment']))
e673ee24
DO
960 {
961 startPortlet ('Comment');
6cc5d6cd 962 echo '<div class=commentblock>' . string_insert_hrefs ($info['comment']) . '</div>';
e673ee24
DO
963 finishPortlet ();
964 }
965
b5700329
AA
966 $logrecords = getLogRecordsForObject ($_REQUEST['object_id']);
967 if (count ($logrecords))
9a90adc4
DO
968 {
969 startPortlet ('log records');
970 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable width='100%'>";
971 $order = 'odd';
b5700329 972 foreach ($logrecords as $row)
9a90adc4
DO
973 {
974 echo "<tr class=row_${order} valign=top>";
975 echo '<td class=tdleft>' . $row['date'] . '<br>' . $row['user'] . '</td>';
c14b5720 976 echo '<td class="slbconf rsvtext">' . string_insert_hrefs (htmlspecialchars ($row['content'], ENT_NOQUOTES)) . '</td>';
9a90adc4
DO
977 echo '</tr>';
978 $order = $nextorder[$order];
979 }
980 echo '</table>';
981 finishPortlet();
982 }
983
65e557dd 984 switchportInfoJS ($object_id); // load JS code to make portnames interactive
e1ae3fb4
AD
985 renderFilesPortlet ('object', $object_id);
986
9f75e165 987 if (count ($info['ports']))
e673ee24 988 {
0ab782bc 989 startPortlet ('ports and links');
9f75e165
DO
990 $hl_port_id = 0;
991 if (isset ($_REQUEST['hl_port_id']))
e673ee24 992 {
0cc24e9a 993 assertUIntArg ('hl_port_id');
9f75e165 994 $hl_port_id = $_REQUEST['hl_port_id'];
65e557dd 995 addAutoScrollScript ("port-$hl_port_id");
9f75e165
DO
996 }
997 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>";
998 echo '<tr><th class=tdleft>Local name</th><th class=tdleft>Visible label</th>';
0d59a51c 999 echo '<th class=tdleft>Interface</th><th class=tdleft>L2 address</th>';
0c7c9f8b
DO
1000 echo '<th class=tdcenter colspan=2>Remote object and port</th>';
1001 echo '<th class=tdleft>Cable ID</th></tr>';
9f75e165 1002 foreach ($info['ports'] as $port)
40c9fc94 1003 callHook ('renderObjectPortRow', $port, ($hl_port_id == $port['id']));
fd5edda8 1004 if (permitted (NULL, 'ports', 'set_reserve_comment'))
a8dc2982 1005 addJS ('js/inplace-edit.js');
9f75e165 1006 echo "</table><br>";
e673ee24
DO
1007 finishPortlet();
1008 }
85970da2 1009
21ee3351 1010 if (count ($info['ipv4']) + count ($info['ipv6']))
e673ee24 1011 {
21ee3351 1012 startPortlet ('IP addresses');
e673ee24 1013 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
f0ed1181 1014 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
0b9c98d7 1015 echo "<tr><th>OS interface</th><th>IP address</th><th>network</th><th>routed by</th><th>peers</th></tr>\n";
83fdf85f
DO
1016 else
1017 echo "<tr><th>OS interface</th><th>IP address</th><th>peers</th></tr>\n";
21ee3351
AA
1018
1019 // group IP allocations by interface name instead of address family
1020 $allocs_by_iface = array();
1021 foreach (array ('ipv4', 'ipv6') as $ip_v)
4318ced5
AA
1022 foreach ($info[$ip_v] as $ip_bin => $alloc)
1023 $allocs_by_iface[$alloc['osif']][$ip_bin] = $alloc;
21ee3351
AA
1024
1025 // sort allocs array by portnames
1026 foreach (sortPortList ($allocs_by_iface) as $iface_name => $alloclist)
1027 {
1028 $is_first_row = TRUE;
f3505b35 1029 foreach ($alloclist as $alloc)
b90c3907 1030 {
40c9fc94 1031 $rendered_alloc = callHook ('getRenderedAlloc', $object_id, $alloc);
f3505b35 1032 echo "<tr class='${rendered_alloc['tr_class']}' valign=top>";
21ee3351 1033
f3505b35 1034 // display iface name, same values are grouped into single cell
21ee3351
AA
1035 if ($is_first_row)
1036 {
1037 $rowspan = count ($alloclist) > 1 ? 'rowspan="' . count ($alloclist) . '"' : '';
40c9fc94 1038 echo "<td class=tdleft $rowspan>" . $iface_name . $rendered_alloc['td_name_suffix'] . "</td>";
21ee3351
AA
1039 $is_first_row = FALSE;
1040 }
f3505b35 1041 echo $rendered_alloc['td_ip'];
21ee3351 1042 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
83fdf85f 1043 {
f3505b35
AA
1044 echo $rendered_alloc['td_network'];
1045 echo $rendered_alloc['td_routed_by'];
21ee3351 1046 }
f3505b35
AA
1047 echo $rendered_alloc['td_peers'];
1048
1049 echo "</tr>\n";
b90c3907 1050 }
e673ee24
DO
1051 }
1052 echo "</table><br>\n";
1053 finishPortlet();
1054 }
1055
94fe6370 1056 $forwards = $info['nat4'];
e673ee24
DO
1057 if (count($forwards['in']) or count($forwards['out']))
1058 {
f28fbe8b 1059 startPortlet('NATv4');
e673ee24
DO
1060
1061 if (count($forwards['out']))
1062 {
1063
f28fbe8b 1064 echo "<h3>locally performed NAT</h3>";
e673ee24 1065
105a3bc8 1066 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
f28fbe8b 1067 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
1068
1069 foreach ($forwards['out'] as $pf)
1070 {
2c817354
DO
1071 $class = 'trerror';
1072 $osif = '';
1073 if (isset ($alloclist [$pf['localip']]))
1074 {
1075 $class = $alloclist [$pf['localip']]['addrinfo']['class'];
1076 $osif = $alloclist [$pf['localip']]['osif'] . ': ';
1077 }
e673ee24 1078 echo "<tr class='$class'>";
4fbb5a00
DY
1079 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>";
1080 echo "<td class=tdleft><a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['remoteip']))."'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
4318ced5 1081 $address = getIPAddress (ip4_parse ($pf['remoteip']));
e673ee24 1082 echo "<td class='description'>";
53ef3908
DO
1083 if (count ($address['allocs']))
1084 foreach($address['allocs'] as $bond)
4fbb5a00 1085 echo "<a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$bond['object_id']))."'>${bond['object_name']}(${bond['name']})</a> ";
59a83bd8 1086 elseif (strlen ($pf['remote_addr_name']))
f28fbe8b 1087 echo '(' . $pf['remote_addr_name'] . ')';
53ef3908 1088 echo "</td><td class='description'>${pf['description']}</td></tr>";
e673ee24
DO
1089 }
1090 echo "</table><br><br>";
1091 }
1092 if (count($forwards['in']))
1093 {
f28fbe8b 1094 echo "<h3>arriving NAT connections</h3>";
105a3bc8 1095 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
f28fbe8b 1096 echo "<tr><th>Matched endpoint</th><th>Source object</th><th>Translated to</th><th>Rule comment</th></tr>\n";
e673ee24
DO
1097 foreach ($forwards['in'] as $pf)
1098 {
1099 echo "<tr>";
4fbb5a00
DY
1100 echo "<td>${pf['proto']}/<a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['localip']))."'>${pf['localip']}</a>:${pf['localport']}</td>";
1101 echo "<td class='description'><a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$pf['object_id']))."'>${pf['object_name']}</a>";
1102 echo "</td><td><a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['remoteip']))."'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
e673ee24
DO
1103 echo "<td class='description'>${pf['description']}</td></tr>";
1104 }
e673ee24
DO
1105 echo "</table><br><br>";
1106 }
1107 finishPortlet();
1108 }
1109
defd92d8 1110 renderSLBTriplets ($info);
e673ee24
DO
1111 echo "</td>\n";
1112
7056988c 1113 // After left column we have (surprise!) right column with rackspace portlet only.
e673ee24 1114 echo "<td class=pcright>";
8dc2a6c8 1115 if (!in_array($info['objtype_id'], $virtual_obj_types))
0682218d
AD
1116 {
1117 // rackspace portlet
1118 startPortlet ('rackspace allocation');
1119 foreach (getResidentRacksData ($object_id, FALSE) as $rack_id)
1120 renderRack ($rack_id, $object_id);
1121 echo '<br>';
1122 finishPortlet();
1123 }
e673ee24
DO
1124 echo "</td></tr>";
1125 echo "</table>\n";
1126}
1127
1128function renderRackMultiSelect ($sname, $racks, $selected)
1129{
04571888
DO
1130 // Transform the given flat list into a list of groups, each representing a rack row.
1131 $rdata = array();
e673ee24 1132 foreach ($racks as $rack)
04571888
DO
1133 if (!isset ($rdata[$rack['row_name']]))
1134 $rdata[$rack['row_name']] = array ($rack['id'] => $rack['name']);
1135 else
1136 $rdata[$rack['row_name']][$rack['id']] = $rack['name'];
4fbb5a00 1137 echo "<select name=${sname} multiple size=" . getConfigVar ('MAXSELSIZE') . " onchange='getElementsByName(\"updateObjectAllocation\")[0].submit()'>\n";
04571888 1138 foreach ($rdata as $optgroup => $racklist)
e673ee24 1139 {
04571888
DO
1140 echo "<optgroup label='${optgroup}'>";
1141 foreach ($racklist as $rack_id => $rack_name)
1142 {
1143 echo "<option value=${rack_id}";
1144 if (!(array_search ($rack_id, $selected) === FALSE))
1145 echo ' selected';
1146 echo">${rack_name}</option>\n";
1147 }
e673ee24
DO
1148 }
1149 echo "</select>\n";
1150}
1151
e673ee24 1152// This function renders a form for port edition.
7e1db771 1153function renderPortsForObject ($object_id)
e673ee24 1154{
3153a326
DO
1155 $prefs = getPortListPrefs();
1156 function printNewItemTR ($prefs)
39b4abd0
DO
1157 {
1158 printOpFormIntro ('addPort');
1159 echo "<tr><td>";
f5ff50f5 1160 printImageHREF ('add', 'add a port', TRUE);
65e557dd 1161 echo "</td><td class='tdleft'><input type=text size=8 name=port_name tabindex=100></td>\n";
cd3775e9
DO
1162 echo "<td><input type=text name=port_label tabindex=101></td><td>";
1163 printNiftySelect (getNewPortTypeOptions(), array ('name' => 'port_type_id', 'tabindex' => 102), $prefs['selected']);
1164 echo "<td><input type=text name=port_l2address tabindex=103 size=18 maxlength=24></td>\n";
318c48a8 1165 echo "<td colspan=4>&nbsp;</td><td>";
9318d2ef
DO
1166 printImageHREF ('add', 'add a port', TRUE, 104);
1167 echo "</td></tr></form>";
39b4abd0 1168 }
a1fc539a 1169 if (getConfigVar('ENABLE_MULTIPORT_FORM') == 'yes' || getConfigVar('ENABLE_BULKPORT_FORM') == 'yes' )
f44fdef9
DO
1170 startPortlet ('Ports and interfaces');
1171 else
1172 echo '<br>';
9f75e165
DO
1173 $object = spotEntity ('object', $object_id);
1174 amplifyCell ($object);
a1fc539a
RF
1175 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes' && getConfigVar('ENABLE_BULKPORT_FORM') == 'yes'){
1176 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
1177 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>";
1178 echo "<th class=tdleft>Count</th><th>&nbsp;</th></tr>\n";
1179 printOpFormIntro ('addBulkPorts');
1180 echo "<tr><td>";
1181 printImageHREF ('add', 'add ports', TRUE);
1182 echo "</td><td><input type=text size=8 name=port_name tabindex=105></td>\n";
1183 echo "<td><input type=text name=port_label tabindex=106></td><td>";
1184 printNiftySelect (getNewPortTypeOptions(), array ('name' => 'port_type_id', 'tabindex' => 107), $prefs['selected']);
1185 echo "<td><input type=text name=port_numbering_start tabindex=108 size=3 maxlength=3></td>\n";
1186 echo "<td><input type=text name=port_numbering_count tabindex=109 size=3 maxlength=3></td>\n";
1187 echo "<td>&nbsp;</td><td>";
1188 printImageHREF ('add', 'add ports', TRUE, 110);
1189 echo "</td></tr></form>";
1190 echo "</table><br>\n";
1191 }
1192
e673ee24 1193 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
0d59a51c 1194 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 1195 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 1196 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
3153a326 1197 printNewItemTR ($prefs);
45ff9012
AA
1198
1199 // clear ports link
1200 echo "<a href='".
1201 makeHrefProcess(array ('op'=>'deleteAll', 'page' => 'object', 'tab' => 'ports', 'object_id' => $object_id)).
1202 "' onclick=\"javascript:return confirm('Are you sure you want to delete all existing ports?')\">" . getImageHREF ('clear', 'Clear port list') . " Clear port list</a>";
1203
00276508
AA
1204 if (isset ($_REQUEST['hl_port_id']))
1205 {
1206 assertUIntArg ('hl_port_id');
1207 $hl_port_id = intval ($_REQUEST['hl_port_id']);
65e557dd 1208 addAutoScrollScript ("port-$hl_port_id");
00276508 1209 }
65e557dd 1210 switchportInfoJS ($object_id); // load JS code to make portnames interactive
9f75e165 1211 foreach ($object['ports'] as $port)
e673ee24 1212 {
00276508 1213 $tr_class = isset ($hl_port_id) && $hl_port_id == $port['id'] ? 'class="port_highlight"' : '';
7056988c 1214 printOpFormIntro ('editPort', array ('port_id' => $port['id']));
10005279 1215 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
1216 printImageHREF ('delete', 'Unlink and Delete this port');
1217 echo "</a></td>\n";
65e557dd
AA
1218 $a_class = isEthernetPort ($port) ? 'port-menu' : '';
1219 echo "<td class='tdleft' NOWRAP><input type=text name=name class='interactive-portname $a_class' value='${port['name']}' size=8></td>";
cd3775e9 1220 echo "<td><input type=text name=label value='${port['label']}'></td>";
611170af
AD
1221 if (!$port['remote_object_id'])
1222 {
3153a326
DO
1223 echo '<td>';
1224 if ($port['iif_id'] != 1)
1225 echo '<label>' . $port['iif_name'] . ' ';
cd3775e9 1226 printSelect (getExistingPortTypeOptions ($port['id']), array ('name' => 'port_type_id'), $port['oif_id']);
3153a326
DO
1227 if ($port['iif_id'] != 1)
1228 echo '</label>';
1229 echo '</td>';
611170af
AD
1230 }
1231 else
1232 {
045bab87 1233 echo "<input type=hidden name=port_type_id value='${port['oif_id']}'><td class=tdleft>";
e9d357e1 1234 echo formatPortIIFOIF ($port) . '</td>';
611170af 1235 }
cd3775e9
DO
1236 // 18 is enough to fit 6-byte MAC address in its longest form,
1237 // while 24 should be Ok for WWN
1238 echo "<td><input type=text name=l2address value='${port['l2address']}' size=18 maxlength=24></td>\n";
e673ee24
DO
1239 if ($port['remote_object_id'])
1240 {
318c48a8 1241 echo "<td>" .
a2ea559e 1242 formatLoggedSpan ($port['last_log'], formatPortLink ($port['remote_object_id'], $port['remote_object_name'], $port['remote_id'], NULL)) .
5c6225b1
AA
1243 "</td>";
1244 echo "<td> " . formatLoggedSpan ($port['last_log'], $port['remote_name'], 'underline') .
1245 "<input type=hidden name=reservation_comment value=''></td>";
318c48a8 1246 echo "<td><input type=text name=cable value='${port['cableid']}'></td>";
3153a326 1247 echo "<td class=tdcenter><a href='".
4fbb5a00
DY
1248 makeHrefProcess(array(
1249 'op'=>'unlinkPort',
cd3775e9 1250 'port_id'=>$port['id'],
cd3775e9 1251 'object_id'=>$object_id)).
4fbb5a00 1252 "'>";
5ccd99a0 1253 printImageHREF ('cut', 'Unlink this port');
e673ee24
DO
1254 echo "</a></td>";
1255 }
59a83bd8 1256 elseif (strlen ($port['reservation_comment']))
e673ee24 1257 {
5c6225b1 1258 echo "<td>" . formatLoggedSpan ($port['last_log'], 'Reserved:', 'strong underline') . "</td>";
e673ee24 1259 echo "<td><input type=text name=reservation_comment value='${port['reservation_comment']}'></td>";
318c48a8 1260 echo "<td></td>";
3153a326 1261 echo "<td class=tdcenter><a href='".
4fbb5a00
DY
1262 makeHrefProcess(array(
1263 'op'=>'useup',
1264 'port_id'=>$port['id'],
1265 'object_id'=>$object_id)).
1266 "'>";
39be655e 1267 printImageHREF ('clear', 'Use up this port');
e673ee24
DO
1268 echo "</a></td>";
1269 }
1270 else
1271 {
318c48a8 1272 echo "<td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td class=tdcenter><span";
cd3775e9
DO
1273 $helper_args = array
1274 (
1275 'port' => $port['id'],
cd3775e9
DO
1276 );
1277 $popup_args = 'height=700, width=400, location=no, menubar=no, '.
9e214652 1278 'resizable=yes, scrollbars=yes, status=no, titlebar=no, toolbar=no';
cd3775e9
DO
1279 echo " ondblclick='window.open(\"" . makeHrefForHelper ('portlist', $helper_args);
1280 echo "\",\"findlink\",\"${popup_args}\");'";
1281 // end of onclick=
cd3775e9
DO
1282 echo " onclick='window.open(\"" . makeHrefForHelper ('portlist', $helper_args);
1283 echo "\",\"findlink\",\"${popup_args}\");'";
1284 // end of onclick=
1285 echo '>';
1286 // end of <a>
5ccd99a0 1287 printImageHREF ('plug', 'Link this port');
cd3775e9
DO
1288 echo "</span>";
1289 echo " <input type=text name=reservation_comment></td>\n";
e673ee24 1290 }
5bbbeaa2
DO
1291 echo "<td>";
1292 printImageHREF ('save', 'Save changes', TRUE);
1293 echo "</td></form></tr>\n";
e673ee24 1294 }
39b4abd0 1295 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
3153a326 1296 printNewItemTR ($prefs);
e673ee24 1297 echo "</table><br>\n";
a1fc539a
RF
1298 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes' && getConfigVar('ENABLE_BULKPORT_FORM') == 'yes'){
1299 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
1300 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>";
1301 echo "<th class=tdleft>Count</th><th>&nbsp;</th></tr>\n";
1302 printOpFormIntro ('addBulkPorts');
1303 echo "<tr><td>";
1304 printImageHREF ('add', 'add ports', TRUE);
1305 echo "</td><td><input type=text size=8 name=port_name tabindex=105></td>\n";
1306 echo "<td><input type=text name=port_label tabindex=106></td><td>";
1307 printNiftySelect (getNewPortTypeOptions(), array ('name' => 'port_type_id', 'tabindex' => 107), $prefs['selected']);
1308 echo "<td><input type=text name=port_numbering_start tabindex=108 size=3 maxlength=3></td>\n";
1309 echo "<td><input type=text name=port_numbering_count tabindex=109 size=3 maxlength=3></td>\n";
1310 echo "<td>&nbsp;</td><td>";
1311 printImageHREF ('add', 'add ports', TRUE, 110);
1312 echo "</td></tr></form>";
1313 echo "</table><br>\n";
1314 }
f44fdef9
DO
1315 if (getConfigVar('ENABLE_MULTIPORT_FORM') == 'yes')
1316 finishPortlet();
1317 if (getConfigVar('ENABLE_MULTIPORT_FORM') != 'yes')
1318 return;
e673ee24
DO
1319
1320 startPortlet ('Add/update multiple ports');
7056988c 1321 printOpFormIntro ('addMultiPorts');
f7a3c94a 1322 echo 'Format: <select name=format tabindex=201>';
e673ee24
DO
1323 echo '<option value=c3600asy>Cisco 3600 async: sh line | inc TTY</option>';
1324 echo '<option value=fiwg selected>Foundry ServerIron/FastIron WorkGroup/Edge: sh int br</option>';
e673ee24 1325 echo '<option value=fisxii>Foundry FastIron SuperX/II4000: sh int br</option>';
351d4dbf 1326 echo '<option value=ssv1>SSV:&lt;interface name&gt; &lt;MAC address&gt;</option>';
e673ee24
DO
1327 echo "</select>";
1328 echo 'Default port type: ';
cd3775e9 1329 printNiftySelect (getNewPortTypeOptions(), array ('name' => 'port_type', 'tabindex' => 202), $prefs['selected']);
f7a3c94a
DO
1330 echo "<input type=submit value='Parse output' tabindex=204><br>\n";
1331 echo "<textarea name=input cols=100 rows=50 tabindex=203></textarea><br>\n";
e673ee24
DO
1332 echo '</form>';
1333 finishPortlet();
1334}
1335
4318ced5 1336function renderIPForObject ($object_id)
e673ee24 1337{
4318ced5 1338 function printNewItemTR ($default_type)
21ee3351
AA
1339 {
1340 global $aat;
4318ced5
AA
1341 printOpFormIntro ('add');
1342 echo "<tr><td>"; // left btn
1343 printImageHREF ('add', 'allocate', TRUE);
21ee3351 1344 echo "</td>";
4318ced5
AA
1345 echo "<td class=tdleft><input type='text' size='10' name='bond_name' tabindex=100></td>\n"; // if-name
1346 echo "<td class=tdleft><input type=text name='ip' tabindex=101></td>\n"; // IP
1347 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
1348 echo "<td colspan=2>&nbsp;</td>"; // network, routed by
1349 echo '<td>';
1350 printSelect ($aat, array ('name' => 'bond_type', 'tabindex' => 102), $default_type); // type
1351 echo "</td><td>&nbsp;</td><td>"; // misc
1352 printImageHREF ('add', 'allocate', TRUE, 103); // right btn
21ee3351
AA
1353 echo "</td></tr></form>";
1354 }
21ee3351
AA
1355 global $aat;
1356 startPortlet ('Allocations');
4318ced5
AA
1357 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'><tr>\n";
1358 echo '<th>&nbsp;</th>';
1359 echo '<th>OS interface</th>';
1360 echo '<th>IP address</th>';
21ee3351 1361 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
4318ced5
AA
1362 {
1363 echo '<th>network</th>';
1364 echo '<th>routed by</th>';
1365 }
1366 echo '<th>type</th>';
1367 echo '<th>misc</th>';
1368 echo '<th>&nbsp</th>';
1369 echo '</tr>';
21ee3351 1370
710ead7e
AA
1371 $alloc_list = ''; // most of the output is stored here
1372 $used_alloc_types = array();
4318ced5 1373 foreach (getObjectIPAllocations ($object_id) as $alloc)
21ee3351 1374 {
710ead7e
AA
1375 if (! isset ($used_alloc_types[$alloc['type']]))
1376 $used_alloc_types[$alloc['type']] = 0;
1377 $used_alloc_types[$alloc['type']]++;
1378
40c9fc94 1379 $rendered_alloc = callHook ('getRenderedAlloc', $object_id, $alloc);
4318ced5 1380 $alloc_list .= getOutputOf ('printOpFormIntro', 'upd', array ('ip' => $alloc['addrinfo']['ip']));
710ead7e 1381 $alloc_list .= "<tr class='${rendered_alloc['tr_class']}' valign=top>";
f3505b35 1382
710ead7e 1383 $alloc_list .= "<td><a href='" .
f3505b35
AA
1384 makeHrefProcess
1385 (
1386 array
1387 (
4318ced5 1388 'op' => 'del',
f3505b35
AA
1389 'ip' => $alloc['addrinfo']['ip'],
1390 'object_id' => $object_id
1391 )
1392 ) . "'>" .
1393 getImageHREF ('delete', 'Delete this IP address') .
1394 "</a></td>";
40c9fc94 1395 $alloc_list .= "<td class=tdleft><input type='text' name='bond_name' value='${alloc['osif']}' size=10>" . $rendered_alloc['td_name_suffix'] . "</td>";
710ead7e 1396 $alloc_list .= $rendered_alloc['td_ip'];
21ee3351
AA
1397 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
1398 {
710ead7e
AA
1399 $alloc_list .= $rendered_alloc['td_network'];
1400 $alloc_list .= $rendered_alloc['td_routed_by'];
21ee3351 1401 }
710ead7e
AA
1402 $alloc_list .= '<td>' . getSelect ($aat, array ('name' => 'bond_type'), $alloc['type']) . "</td>";
1403 $alloc_list .= $rendered_alloc['td_peers'];
1404 $alloc_list .= "<td>" .getImageHREF ('save', 'Save changes', TRUE) . "</td>";
f3505b35 1405
710ead7e 1406 $alloc_list .= "</form></tr>\n";
21ee3351 1407 }
710ead7e
AA
1408 asort ($used_alloc_types, SORT_NUMERIC);
1409 $most_popular_type = empty ($used_alloc_types) ? 'regular' : array_pop (array_keys ($used_alloc_types));
1410
1411 if ($list_on_top = (getConfigVar ('ADDNEW_AT_TOP') != 'yes'))
1412 echo $alloc_list;
4318ced5 1413 printNewItemTR ($most_popular_type);
710ead7e
AA
1414 if (! $list_on_top)
1415 echo $alloc_list;
21ee3351
AA
1416
1417 echo "</table><br>\n";
1418 finishPortlet();
f3505b35
AA
1419}
1420
08408472
AA
1421// This function is deprecated. Do not rely on its internals,
1422// it will probably be removed in the next major relese.
1423// Use new showError, showWarning, showSuccess functions.
a2b16202 1424// Log array is stored in global $log_messages. Its format is simple: plain ordered array
8ab645cf 1425// with values having keys 'c' (both message code and severity) and 'a' (sprintf arguments array)
1cb6adf5 1426function showMessageOrError ()
e673ee24 1427{
a2b16202
AA
1428 global $log_messages;
1429
1430 @session_start();
1431 if (isset ($_SESSION['log']))
1432 {
1433 $log_messages = array_merge ($_SESSION['log'], $log_messages);
1434 unset ($_SESSION['log']);
1435 }
1436 session_commit();
1437
1438 if (empty ($log_messages))
1cb6adf5 1439 return;
8ab645cf
AA
1440 $msginfo = array
1441 (
1442// records 0~99 with success messages
1443 0 => array ('code' => 'success', 'format' => '%s'),
1444 5 => array ('code' => 'success', 'format' => 'added record "%s" successfully'),
1445 6 => array ('code' => 'success', 'format' => 'updated record "%s" successfully'),
1446 7 => array ('code' => 'success', 'format' => 'deleted record "%s" successfully'),
1447 8 => array ('code' => 'success', 'format' => 'Port %s successfully linked with %s'),
1448 10 => array ('code' => 'success', 'format' => 'Added %u ports, updated %u ports, encountered %u errors.'),
1449 21 => array ('code' => 'success', 'format' => 'Generation complete'),
1450 26 => array ('code' => 'success', 'format' => 'updated %u records successfully'),
1451 37 => array ('code' => 'success', 'format' => 'added %u records successfully'),
1452 38 => array ('code' => 'success', 'format' => 'removed %u records successfully'),
8ab645cf
AA
1453 43 => array ('code' => 'success', 'format' => 'Saved successfully.'),
1454 44 => array ('code' => 'success', 'format' => '%s failures and %s successfull changes.'),
1455 48 => array ('code' => 'success', 'format' => 'added a record successfully'),
1456 49 => array ('code' => 'success', 'format' => 'deleted a record successfully'),
1457 51 => array ('code' => 'success', 'format' => 'updated a record successfully'),
1458 57 => array ('code' => 'success', 'format' => 'Reset complete'),
8ab645cf 1459 63 => array ('code' => 'success', 'format' => '%u change request(s) have been processed'),
8ab645cf
AA
1460 67 => array ('code' => 'success', 'format' => "Tag rolling done, %u objects involved"),
1461 71 => array ('code' => 'success', 'format' => 'File "%s" was linked successfully'),
1462 72 => array ('code' => 'success', 'format' => 'File was unlinked successfully'),
8ab645cf
AA
1463 82 => array ('code' => 'success', 'format' => "Bulk port creation was successful. %u ports created, %u failed"),
1464 87 => array ('code' => 'success', 'format' => '802.1Q recalculate: %d ports changed on %d switches'),
8628ae44 1465// records 100~199 with fatal error messages
8ab645cf
AA
1466 100 => array ('code' => 'error', 'format' => '%s'),
1467 109 => array ('code' => 'error', 'format' => 'failed updating a record'),
8ab645cf
AA
1468 131 => array ('code' => 'error', 'format' => 'invalid format requested'),
1469 141 => array ('code' => 'error', 'format' => 'Encountered %u errors, updated %u record(s)'),
1470 149 => array ('code' => 'error', 'format' => 'Turing test failed'),
1471 150 => array ('code' => 'error', 'format' => 'Can only change password under DB authentication.'),
1472 151 => array ('code' => 'error', 'format' => 'Old password doesn\'t match.'),
1473 152 => array ('code' => 'error', 'format' => 'New passwords don\'t match.'),
1474 154 => array ('code' => 'error', 'format' => "Verification error: %s"),
1475 155 => array ('code' => 'error', 'format' => 'Save failed.'),
1476 159 => array ('code' => 'error', 'format' => 'Permission denied moving port %s from VLAN%u to VLAN%u'),
1477 161 => array ('code' => 'error', 'format' => 'Endpoint not found. Please either set FQDN attribute or assign an IP address to the object.'),
1478 162 => array ('code' => 'error', 'format' => 'More than one IP address is assigned to this object, please configure FQDN attribute.'),
8ab645cf
AA
1479 170 => array ('code' => 'error', 'format' => 'There is no network for IP address "%s"'),
1480 172 => array ('code' => 'error', 'format' => 'Malformed request'),
1481 179 => array ('code' => 'error', 'format' => 'Expired form has been declined.'),
1482 188 => array ('code' => 'error', 'format' => "Fatal SNMP failure"),
1483 189 => array ('code' => 'error', 'format' => "Unknown OID '%s'"),
1484 191 => array ('code' => 'error', 'format' => "deploy was blocked due to conflicting configuration versions"),
f0ff4930 1485
8628ae44 1486// records 200~299 with warnings
8ab645cf
AA
1487 200 => array ('code' => 'warning', 'format' => '%s'),
1488 201 => array ('code' => 'warning', 'format' => 'nothing happened...'),
8ab645cf 1489 206 => array ('code' => 'warning', 'format' => 'Rack is not empty'),
7587edca 1490 207 => array ('code' => 'warning', 'format' => 'File upload failed, error: %s'),
57777e4a 1491
24d3182a 1492// records 300~399 with notices
8ab645cf 1493 300 => array ('code' => 'neutral', 'format' => '%s'),
24d3182a 1494
8ab645cf
AA
1495 );
1496 // Handle the arguments. Is there any better way to do it?
a2b16202 1497 foreach ($log_messages as $record)
8ab645cf
AA
1498 {
1499 if (!isset ($record['c']) or !isset ($msginfo[$record['c']]))
1500 {
41152018
AA
1501 $prefix = isset ($record['c']) ? $record['c'] . ': ' : '';
1502 echo "<div class=msg_neutral>(${prefix}this message was lost)</div>";
8ab645cf
AA
1503 continue;
1504 }
1505 if (isset ($record['a']))
1506 switch (count ($record['a']))
baf37d01 1507 {
8ab645cf
AA
1508 case 1:
1509 $msgtext = sprintf
1510 (
1511 $msginfo[$record['c']]['format'],
1512 $record['a'][0]
1513 );
1514 break;
1515 case 2:
1516 $msgtext = sprintf
1517 (
1518 $msginfo[$record['c']]['format'],
1519 $record['a'][0],
1520 $record['a'][1]
1521 );
1522 break;
1523 case 3:
1524 $msgtext = sprintf
1525 (
1526 $msginfo[$record['c']]['format'],
1527 $record['a'][0],
1528 $record['a'][1],
1529 $record['a'][2]
1530 );
1531 break;
1532 case 4:
1533 default:
1534 $msgtext = sprintf
1535 (
1536 $msginfo[$record['c']]['format'],
1537 $record['a'][0],
1538 $record['a'][1],
1539 $record['a'][2],
1540 $record['a'][3]
1541 );
1542 break;
baf37d01 1543 }
8ab645cf
AA
1544 else
1545 $msgtext = $msginfo[$record['c']]['format'];
1546 echo '<div class=msg_' . $msginfo[$record['c']]['code'] . ">${msgtext}</div>";
baf37d01 1547 }
a2b16202 1548 $log_messages = array();
e673ee24
DO
1549}
1550
65e557dd
AA
1551// renders two tables: port link status and learned MAC list
1552function renderPortsInfo($object_id)
1553{
1554 global $nextorder;
1555 echo "<table width='100%'><tr>";
1556
1557 if (permitted (NULL, NULL, 'get_link_status'))
1558 {
1559 try
1560 {
80019a2c 1561 $linkStatus = queryDevice ($object_id, 'getportstatus');
65e557dd
AA
1562 }
1563 catch (RackTablesError $e) {}
1564 if (! empty ($linkStatus))
1565 {
1566 echo "<td valign='top' width='50%'>";
1567 startPortlet('Link status');
1568 echo "<table width='80%' class='widetable' cellspacing=0 cellpadding='5px' align='center'><tr><th>Port<th>Link status<th>Link info</tr>";
1569 $order = 'even';
1570 foreach ($linkStatus as $pn => $link)
1571 {
1572 echo "<tr class='row_$order'>";
1573 $order = $nextorder[$order];
1574 echo '<td>' . $pn;
1575 echo '<td>' . $link['status'];
1576 $info = '';
1577 if (isset ($link['speed']))
1578 $info .= $link['speed'];
1579 if (isset ($link['duplex']))
1580 {
1581 if (! empty ($info))
1582 $info .= ', ';
1583 $info .= $link['duplex'];
1584 }
1585 echo '<td>' . $info;
1586 echo '</tr>';
1587 }
1588 echo "</table></td>";
1589 finishPortlet();
1590 }
1591 }
1592
1593 try
1594 {
80019a2c 1595 $macList = sortPortList (queryDevice ($object_id, 'getmaclist'));
65e557dd
AA
1596 }
1597 catch (RackTablesError $e) {}
1598 if (! empty ($macList))
1599 {
1600 echo "<td valign='top' width='50%'>";
1601 $rendered_macs = '';
1602 $mac_count = 0;
1603 $rendered_macs .= "<table width='80%' class='widetable' cellspacing=0 cellpadding='5px' align='center'><tr><th>MAC<th>Vlan<th>Port</tr>";
1604 $order = 'even';
1605 foreach ($macList as $pn => $list)
1606 {
1607 $order = $nextorder[$order];
1608 foreach ($list as $item)
1609 {
1610 ++$mac_count;
1611 $rendered_macs .= "<tr class='row_$order'>";
1612 $rendered_macs .= '<td style="font-family: monospace">' . $item['mac'];
1613 $rendered_macs .= '<td>' . $item['vid'];
1614 $rendered_macs .= '<td>' . $pn;
1615 $rendered_macs .= '</tr>';
1616 }
1617 }
1618 $rendered_macs .= "</table></td>";
1619
1620 startPortlet("Learned MACs ($mac_count)");
1621 echo $rendered_macs;
1622 finishPortlet();
1623 }
1624
1625 echo "</td></tr></table>";
1626}
1627
e673ee24 1628/*
51c18782 1629The following conditions must be met:
e673ee24
DO
16301. We can mount onto free atoms only. This means: if any record for an atom
1631already exists in RackSpace, it can't be used for mounting.
16322. We can't unmount from 'W' atoms. Operator should review appropriate comments
1633and either delete them before unmounting or refuse to unmount the object.
1634*/
7e1db771 1635function renderRackSpaceForObject ($object_id)
e673ee24 1636{
e673ee24
DO
1637 // Always process occupied racks plus racks chosen by user. First get racks with
1638 // already allocated rackspace...
51c18782 1639 $workingRacksData = getResidentRacksData ($object_id);
e673ee24 1640 // ...and then add those chosen by user (if any).
2135fd83 1641 if (isset($_REQUEST['rackmulti']))
e673ee24 1642 foreach ($_REQUEST['rackmulti'] as $cand_id)
e673ee24
DO
1643 if (!isset ($workingRacksData[$cand_id]))
1644 {
0cc24e9a 1645 $rackData = spotEntity ('rack', $cand_id);
61a1d996 1646 amplifyCell ($rackData);
e673ee24
DO
1647 $workingRacksData[$cand_id] = $rackData;
1648 }
51690ad4 1649
0a7feebb
AD
1650 // Get a list of all of this object's parents,
1651 // then trim the list to only include parents which are racks
1652 $objectParents = getEntityRelatives('parents', 'object', $object_id);
1653 $parentRacks = array();
1654 foreach ($objectParents as $parentData)
1655 if ($parentData['entity_type'] == 'rack')
1656 $parentRacks[] = $parentData['entity_id'];
1657
e673ee24
DO
1658 // Main layout starts.
1659 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0><tr>";
1660
1661 // Left portlet with rack list.
1662 echo "<td class=pcleft height='1%'>";
1663 startPortlet ('Racks');
a8efc03e 1664 $allRacksData = listCells ('rack');
6d42599c
AA
1665
1666 // filter rack list to match only racks having common tags with the object (reducing $allRacksData)
1667 if (! isset ($_REQUEST['show_all_racks']) and getConfigVar ('FILTER_RACKLIST_BY_TAGS') == 'yes')
1668 {
1669 $matching_racks = array();
1670 $object = spotEntity ('object', $object_id);
1671 $matched_tags = array();
1672 foreach ($allRacksData as $rack)
1673 foreach ($object['etags'] as $tag)
1674 if (tagOnChain ($tag, $rack['etags']) or tagOnChain ($tag, $rack['itags']))
1675 {
1676 $matching_racks[$rack['id']] = $rack;
1677 $matched_tags[$tag['id']] = $tag;
1678 break;
1679 }
1680 // add current object's racks even if they dont match filter
1681 foreach ($workingRacksData as $rack_id => $rack)
1682 if (! isset ($matching_racks[$rack_id]))
1683 $matching_racks[$rack_id] = $rack;
1684 // if matching racks found, and rack list is reduced, show 'show all' link
1685 if (count ($matching_racks) and count ($matching_racks) != count ($allRacksData))
1686 {
1687 $filter_text = '';
1688 foreach ($matched_tags as $tag)
1689 $filter_text .= (empty ($filter_text) ? '' : ' or ') . '{' . $tag['tag'] . '}';
1690 $href_show_all = trim($_SERVER['REQUEST_URI'], '&');
1691 $href_show_all .= htmlspecialchars('&show_all_racks=1');
1692 echo "(filtered by <span class='filter-text'>$filter_text</span>, <a href='$href_show_all'>show all</a>)<p>";
1693 $allRacksData = $matching_racks;
1694 }
1695 }
1696
4b8d413e 1697 if (count ($allRacksData) <= getConfigVar ('RACK_PRESELECT_THRESHOLD'))
61a1d996 1698 foreach ($allRacksData as $rack)
51c18782
DO
1699 if (!array_key_exists ($rack['id'], $workingRacksData))
1700 {
1701 amplifyCell ($rack);
1702 $workingRacksData[$rack['id']] = $rack;
1703 }
1704 foreach (array_keys ($workingRacksData) as $rackId)
1705 applyObjectMountMask ($workingRacksData[$rackId], $object_id);
1706 printOpFormIntro ('updateObjectAllocation');
4b8d413e 1707 renderRackMultiSelect ('rackmulti[]', $allRacksData, array_keys ($workingRacksData));
51c18782 1708 echo "<br><br>";
e673ee24
DO
1709 finishPortlet();
1710 echo "</td>";
1711
1712 // Middle portlet with comment and submit.
1713 echo "<td class=pcleft>";
1714 startPortlet ('Comment');
1715 echo "<textarea name=comment rows=10 cols=40></textarea><br>\n";
1716 echo "<input type=submit value='Save' name=got_atoms>\n";
51c18782 1717 echo "<br><br>";
e673ee24
DO
1718 finishPortlet();
1719 echo "</td>";
1720
1721 // Right portlet with rendered racks. If this form submit is not final, we have to
1722 // reflect the former state of the grid in current form.
1723 echo "<td class=pcright rowspan=2 height='1%'>";
1724 startPortlet ('Working copy');
65e557dd 1725 addJS ('js/racktables.js');
e673ee24
DO
1726 echo '<table border=0 cellspacing=10 align=center><tr>';
1727 foreach ($workingRacksData as $rack_id => $rackData)
1728 {
1729 // Order is important here: only original allocation is highlighted.
1730 highlightObject ($rackData, $object_id);
1731 markupAtomGrid ($rackData, 'T');
1732 // If we have a form processed, discard user input and show new database
1733 // contents.
51c18782 1734 if (isset ($_REQUEST['rackmulti'][0])) // is an update
e673ee24
DO
1735 mergeGridFormToRack ($rackData);
1736 echo "<td valign=top>";
1737 echo "<center>\n<h2>${rackData['name']}</h2>\n";
1738 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
57c69e9c 1739 echo "<tr><th width='10%'>&nbsp;</th>";
bd0bfb76
AD
1740 echo "<th width='20%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '0', ${rackData['height']})\">Front</a></th>";
1741 echo "<th width='50%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '1', ${rackData['height']})\">Interior</a></th>";
1742 echo "<th width='20%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '2', ${rackData['height']})\">Back</a></th></tr>\n";
e673ee24 1743 renderAtomGrid ($rackData);
57c69e9c 1744 echo "<tr><th width='10%'>&nbsp;</th>";
bd0bfb76
AD
1745 echo "<th width='20%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '0', ${rackData['height']})\">Front</a></th>";
1746 echo "<th width='50%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '1', ${rackData['height']})\">Interior</a></th>";
1747 echo "<th width='20%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '2', ${rackData['height']})\">Back</a></th></tr>\n";
0a7feebb
AD
1748 echo "</table>\n<br>\n";
1749 // Determine zero-u checkbox status.
1750 // If form has been submitted, use form data, otherwise use DB data.
1751 if (isset($_REQUEST['op']))
1752 $checked = isset($_REQUEST['zerou_'.$rack_id]) ? 'checked' : '';
1753 else
1754 $checked = in_array($rack_id, $parentRacks) ? 'checked' : '';
d141833a 1755 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 1756 echo "<input type='button' onclick='uncheckAll();' value='Uncheck all'>\n";
0a7feebb 1757 echo '</center></td>';
e673ee24
DO
1758 }
1759 echo "</tr></table>";
1760 finishPortlet();
1761 echo "</td>\n";
1762
1763 echo "</form>\n";
1764 echo "</tr></table>\n";
1765}
1766
1767function renderMolecule ($mdata, $object_id)
1768{
1769 // sort data out
1770 $rackpack = array();
1771 global $loclist;
64b95774 1772 foreach ($mdata as $rua)
e673ee24
DO
1773 {
1774 $rack_id = $rua['rack_id'];
1775 $unit_no = $rua['unit_no'];
1776 $atom = $rua['atom'];
1777 if (!isset ($rackpack[$rack_id]))
1778 {
61a1d996
DO
1779 $rackData = spotEntity ('rack', $rack_id);
1780 amplifyCell ($rackData);
e673ee24
DO
1781 for ($i = $rackData['height']; $i > 0; $i--)
1782 for ($locidx = 0; $locidx < 3; $locidx++)
1783 $rackData[$i][$locidx]['state'] = 'F';
1784 $rackpack[$rack_id] = $rackData;
1785 }
1786 $rackpack[$rack_id][$unit_no][$loclist[$atom]]['state'] = 'T';
1787 $rackpack[$rack_id][$unit_no][$loclist[$atom]]['object_id'] = $object_id;
1788 }
1789 // now we have some racks to render
64b95774 1790 foreach ($rackpack as $rackData)
e673ee24
DO
1791 {
1792 markAllSpans ($rackData);
1793 echo "<table class=molecule cellspacing=0>\n";
1794 echo "<caption>${rackData['name']}</caption>\n";
1795 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>Front</th><th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
1796 for ($i = $rackData['height']; $i > 0; $i--)
1797 {
1798 echo "<tr><th>$i</th>";
1799 for ($locidx = 0; $locidx < 3; $locidx++)
1800 {
1801 $state = $rackData[$i][$locidx]['state'];
65e557dd 1802 echo "<td class='atom state_${state}'>&nbsp;</td>\n";
e673ee24
DO
1803 }
1804 echo "</tr>\n";
1805 }
1806 echo "</table>\n";
1807 }
1808}
1809
23cdc7e9 1810function renderDepot ()
e673ee24 1811{
23cdc7e9 1812 global $pageno, $nextorder;
23cdc7e9
DO
1813 $cellfilter = getCellFilter();
1814 $objects = filterCellList (listCells ('object'), $cellfilter['expression']);
1815
1816 echo "<table border=0 class=objectview>\n";
1817 echo "<tr><td class=pcleft>";
1818
1ebbf889 1819 if (! renderEmptyResults ($cellfilter, 'objects', count($objects)))
e673ee24 1820 {
4899096d 1821 if (count($objects) > 0)
1ebbf889 1822 {
4899096d
AD
1823 startPortlet ('Objects (' . count ($objects) . ')');
1824 echo '<br><br><table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
b09a8280 1825 echo '<tr><th>Common name</th><th>Visible label</th><th>Asset tag</th><th>Row/Rack or Container</th></tr>';
4899096d 1826 $order = 'odd';
3f8a25d6
DO
1827 # gather IDs of all objects and fetch rackspace info in one pass
1828 $idlist = array();
1829 foreach ($objects as $obj)
1830 $idlist[] = $obj['id'];
1831 $mountinfo = getMountInfo ($idlist);
4899096d
AD
1832 foreach ($objects as $obj)
1833 {
4318ced5 1834 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
1835 if (count ($obj['etags']))
1836 echo '<br><small>' . serializeTags ($obj['etags'], makeHref(array('page'=>$pageno, 'tab'=>'default')) . '&') . '</small>';
4318ced5
AA
1837 echo "</td><td>${obj['label']}</td>";
1838 echo "<td>${obj['asset_no']}</td>";
3f8a25d6 1839 $places = array();
b09a8280
AD
1840 if ($obj['container_id'])
1841 $places[] = mkA ($obj['container_name'], 'object', $obj['container_id']);
1842 elseif (! array_key_exists ($obj['id'], $mountinfo))
3f8a25d6 1843 $places[] = 'Unmounted';
4899096d 1844 else
3f8a25d6
DO
1845 foreach ($mountinfo[$obj['id']] as $mi)
1846 $places[] = mkA ($mi['row_name'], 'row', $mi['row_id']) . '/' . mkA ($mi['rack_name'], 'rack', $mi['rack_id']);
4318ced5 1847 echo "<td>" . implode (', ', $places) . '</td>';
4899096d
AD
1848 echo '</tr>';
1849 $order = $nextorder[$order];
1850 }
1851 echo '</table>';
1852 finishPortlet();
1ebbf889 1853 }
4899096d
AD
1854 else
1855 echo '<h2>No objects exist</h2>';
e673ee24 1856 }
23cdc7e9
DO
1857
1858 echo "</td><td class=pcright width='25%'>";
1859
95857b5c 1860 renderCellFilterPortlet ($cellfilter, 'object', $objects);
23cdc7e9 1861 echo "</td></tr></table>\n";
e673ee24
DO
1862}
1863
1ebbf889
AA
1864// This function returns TRUE if the result set is too big to be rendered, and no filter is set.
1865// In this case it renders the describing message instead.
1866function renderEmptyResults($cellfilter, $entities_name, $count = NULL)
1867{
1868 if (!$cellfilter['is_empty'])
1869 return FALSE;
1870 if (isset ($_REQUEST['show_all_objects']))
1871 return FALSE;
1872 $max = intval(getConfigVar('MAX_UNFILTERED_ENTITIES'));
1873 if (0 == $max || $count <= $max)
1874 return FALSE;
1875
1876 $href_show_all = trim($_SERVER['REQUEST_URI'], '&');
1877 $href_show_all .= htmlspecialchars('&show_all_objects=1');
1878 $suffix = isset ($count) ? " ($count)" : '';
1879 echo <<<END
1880<p>Please set a filter to display the corresponging $entities_name.
1881<br><a href="$href_show_all">Show all $entities_name$suffix</a>
1882END;
1883 return TRUE;
1884}
1885
e673ee24 1886// History viewer for history-enabled simple dictionaries.
9b8174d7 1887function renderObjectHistory ($object_id)
e673ee24 1888{
e673ee24
DO
1889 $order = 'odd';
1890 global $nextorder;
9b8174d7
AD
1891 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
1892 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>';
1893 $result = usePreparedSelectBlade
1894 (
1895 'SELECT ctime, user_name, name, label, asset_no, has_problems, comment FROM ObjectHistory WHERE id=? ORDER BY ctime',
1896 array ($object_id)
1897 );
e673ee24
DO
1898 while ($row = $result->fetch (PDO::FETCH_NUM))
1899 {
1900 echo "<tr class=row_${order}><td>${row[0]}</td>";
9b8174d7 1901 for ($i = 1; $i <= 6; $i++)
e673ee24
DO
1902 echo "<td>" . $row[$i] . "</td>";
1903 echo "</tr>\n";
1904 $order = $nextorder[$order];
1905 }
1906 echo "</table><br>\n";
1907}
1908
1909function renderRackspaceHistory ()
1910{
4fbb5a00 1911 global $nextorder, $pageno, $tabno;
e673ee24
DO
1912 $order = 'odd';
1913 $history = getRackspaceHistory();
1914 // Show the last operation by default.
1915 if (isset ($_REQUEST['op_id']))
1916 $op_id = $_REQUEST['op_id'];
1917 elseif (isset ($history[0]['mo_id']))
1918 $op_id = $history[0]['mo_id'];
1919 else $op_id = NULL;
1920
1921 $omid = NULL;
1922 $nmid = NULL;
1923 $object_id = 1;
1924 if ($op_id)
1925 list ($omid, $nmid) = getOperationMolecules ($op_id);
1926
1927 // Main layout starts.
1928 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
1929
1930 // Left top portlet with old allocation.
1931 echo "<tr><td class=pcleft>";
1932 startPortlet ('Old allocation');
1933 if ($omid)
1934 {
1935 $oldMolecule = getMolecule ($omid);
1936 renderMolecule ($oldMolecule, $object_id);
1937 }
1938 else
1939 echo "nothing";
1940 finishPortlet();
1941
1942 echo '</td><td class=pcright>';
1943
1944 // Right top portlet with new allocation
1945 startPortlet ('New allocation');
1946 if ($nmid)
1947 {
1948 $newMolecule = getMolecule ($nmid);
1949 renderMolecule ($newMolecule, $object_id);
1950 }
1951 else
1952 echo "nothing";
1953 finishPortlet();
737a3f72 1954
e673ee24 1955 echo '</td></tr><tr><td colspan=2>';
737a3f72 1956
e673ee24
DO
1957 // Bottom portlet with list
1958
1959 startPortlet ('Rackspace allocation history');
1960 echo "<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>\n";
7fa7047a 1961 echo "<tr><th>timestamp</th><th>author</th><th>object</th><th>comment</th></tr>\n";
e673ee24
DO
1962 foreach ($history as $row)
1963 {
1964 if ($row['mo_id'] == $op_id)
1965 $class = 'hl';
1966 else
1967 $class = "row_${order}";
4fbb5a00 1968 echo "<tr class=${class}><td><a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'op_id'=>$row['mo_id']))."'>${row['ctime']}</a></td>";
7fa7047a
DO
1969 echo "<td>${row['user_name']}</td><td>";
1970 renderCell (spotEntity ('object', $row['ro_id']));
9c6222ef 1971 echo '</td><td>' . niftyString ($row['comment'], 0) . '</td></tr>';
e673ee24
DO
1972 $order = $nextorder[$order];
1973 }
1974 echo "</table>\n";
1975 finishPortlet();
737a3f72 1976
e673ee24 1977 echo '</td></tr></table>';
e673ee24
DO
1978}
1979
4318ced5 1980function renderIPSpaceRecords ($tree, $baseurl, $target = 0, $level = 1)
d65353ad
DO
1981{
1982 $self = __FUNCTION__;
4318ced5 1983 $knight = (getConfigVar ('IPV4_ENABLE_KNIGHT') == 'yes');
00276508
AA
1984
1985 // scroll page to the highlighted item
1986 if ($target && isset ($_REQUEST['hl_net']))
65e557dd 1987 addAutoScrollScript ("net-$target");
00276508 1988
d65353ad
DO
1989 foreach ($tree as $item)
1990 {
4318ced5
AA
1991 if ($display_routers = (getConfigVar ('IPV4_TREE_RTR_AS_CELL') != 'none'))
1992 loadIPAddrList ($item); // necessary to compute router list and address counter
1993
0137d53c
DO
1994 if (isset ($item['id']))
1995 {
1f54e1ba 1996 $decor = array ('indent' => $level);
fec0c8da 1997 if ($item['symbol'] == 'node-collapsed')
4318ced5 1998 $decor['symbolurl'] = "${baseurl}&eid=${item['id']}&hl_net=1";
fec0c8da 1999 elseif ($item['symbol'] == 'node-expanded')
4318ced5
AA
2000 $decor['symbolurl'] = $baseurl . ($item['parent_id'] ? "&eid=${item['parent_id']}&hl_net=1" : '');
2001 $tr_class = '';
21ee3351 2002 if ($target == $item['id'] && isset ($_REQUEST['hl_net']))
64347dcf 2003 {
4318ced5
AA
2004 $decor['tdclass'] = ' port_highlight';
2005 $tr_class = $decor['tdclass'];
64347dcf 2006 }
4318ced5
AA
2007 echo "<tr valign=top class=\"$tr_class\">";
2008 printIPNetInfoTDs ($item, $decor);
2009
2010 // capacity and usage
2011 echo "<td class=tdcenter>";
2012 echo getRenderedIPNetCapacity ($item);
64347dcf 2013 echo "</td>";
4318ced5
AA
2014
2015 if ($display_routers)
4a47d34b 2016 printRoutersTD (findRouters ($item['addrlist']), getConfigVar ('IPV4_TREE_RTR_AS_CELL'));
0137d53c 2017 echo "</tr>";
fec0c8da 2018 if ($item['symbol'] == 'node-expanded' or $item['symbol'] == 'node-expanded-static')
4318ced5 2019 $self ($item['kids'], $baseurl, $target, $level + 1);
0137d53c
DO
2020 }
2021 else
2022 {
4318ced5 2023 // non-allocated (spare) IP range
0137d53c 2024 echo "<tr valign=top>";
21ee3351 2025 printIPNetInfoTDs ($item, array ('indent' => $level, 'knight' => $knight, 'tdclass' => 'sparenetwork'));
00276508 2026
4318ced5 2027 // capacity and usage
21ee3351 2028 echo "<td class=tdcenter>";
4318ced5 2029 echo getRenderedIPNetCapacity ($item);
21ee3351 2030 echo "</td>";
4318ced5
AA
2031 if ($display_routers)
2032 echo "<td></td>";
21ee3351 2033 echo "</tr>";
21ee3351 2034 }
21ee3351
AA
2035 }
2036}
2037
4318ced5 2038function renderIPSpace()
e673ee24 2039{
4fbb5a00 2040 global $pageno, $tabno;
4318ced5 2041 $realm = ($pageno == 'ipv4space' ? 'ipv4net' : 'ipv6net');
31c941ec 2042 $cellfilter = getCellFilter();
4318ced5
AA
2043 $top = NULL;
2044 $netlist = array();
2045 foreach (listCells ($realm) as $net)
2046 {
2047 if (isset ($top) and IPNetContains ($top, $net))
2048 ;
2049 elseif (! count ($cellfilter['expression']) or judgeCell ($net, $cellfilter['expression']))
2050 $top = $net;
1ebbf889 2051 else
4318ced5
AA
2052 continue;
2053 $netlist[$net['id']] = $net;
5388794d 2054 }
21ee3351
AA
2055 $netcount = count ($netlist);
2056 // expand request can take either natural values or "ALL". Zero means no expanding.
2057 $eid = isset ($_REQUEST['eid']) ? $_REQUEST['eid'] : 0;
4318ced5 2058 $tree = prepareIPTree ($netlist, $eid);
21ee3351
AA
2059
2060 echo "<table border=0 class=objectview>\n";
2061 echo "<tr><td class=pcleft>";
4318ced5 2062 if (! renderEmptyResults($cellfilter, 'IP nets', count($tree)))
21ee3351
AA
2063 {
2064 startPortlet ("networks (${netcount})");
2065 echo '<h4>';
4318ced5
AA
2066 $all = "<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'eid'=>'ALL')) .
2067 $cellfilter['urlextra'] . "'>expand&nbsp;all</a>";
2068 $none = "<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'eid'=>'NONE')) .
2069 $cellfilter['urlextra'] . "'>collapse&nbsp;all</a>";
2070 $auto = "<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno)) .
2071 $cellfilter['urlextra'] . "'>auto-collapse</a>";
2072
21ee3351 2073 if ($eid === 0)
4318ced5 2074 echo 'auto-collapsing at threshold ' . getConfigVar ('TREE_THRESHOLD') . " ($all / $none)";
21ee3351 2075 elseif ($eid === 'ALL')
4318ced5
AA
2076 echo "expanding all ($auto / $none)";
2077 elseif ($eid === 'NONE')
2078 echo "collapsing all ($all / $auto)";
21ee3351
AA
2079 else
2080 {
4318ced5
AA
2081 $netinfo = spotEntity ($realm, $eid);
2082 echo "expanding ${netinfo['ip']}/${netinfo['mask']} ($auto / $all / $none)";
21ee3351
AA
2083 }
2084 echo "</h4><table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2085 echo "<tr><th>prefix</th><th>name/tags</th><th>capacity</th>";
4318ced5 2086 if (getConfigVar ('IPV4_TREE_RTR_AS_CELL') != 'none')
21ee3351
AA
2087 echo "<th>routed by</th>";
2088 echo "</tr>\n";
2089 $baseurl = makeHref(array('page'=>$pageno, 'tab'=>$tabno)) . $cellfilter['urlextra'];
4318ced5 2090 renderIPSpaceRecords ($tree, $baseurl, $eid);
21ee3351
AA
2091 echo "</table>\n";
2092 finishPortlet();
2093 }
2094
2095 echo '</td><td class=pcright>';
4318ced5 2096 renderCellFilterPortlet ($cellfilter, 'ipv4net', $netlist);
21ee3351
AA
2097 echo "</td></tr></table>\n";
2098}
2099
4318ced5 2100function renderIPSpaceEditor()
21ee3351 2101{
4318ced5
AA
2102 global $pageno;
2103 $realm = ($pageno == 'ipv4space' ? 'ipv4net' : 'ipv6net');
2104 $net_page = $realm; // 'ipv4net', 'ipv6net'
2105 $addrspaceList = listCells ($realm);
93a49e5b
AA
2106 startPortlet ('Manage existing (' . count ($addrspaceList) . ')');
2107 if (count ($addrspaceList))
21ee3351 2108 {
21ee3351
AA
2109 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2110 echo "<tr><th>&nbsp;</th><th>prefix</th><th>name</th><th>capacity</th></tr>";
21ee3351
AA
2111 foreach ($addrspaceList as $netinfo)
2112 {
21ee3351 2113 echo "<tr valign=top><td>";
93a49e5b 2114 if (! isIPNetworkEmpty ($netinfo))
21ee3351
AA
2115 printImageHREF ('nodestroy', 'There are ' . count ($netinfo['addrlist']) . ' allocations inside');
2116 else
93a49e5b 2117 echo getOpLink (array ('op' => 'del', 'id' => $netinfo['id']), '', 'destroy', 'Delete this prefix');
4318ced5 2118 echo '</td><td class=tdleft><a href="' . makeHref (array ('page' => $net_page, 'id' => $netinfo['id'])) . '">';
ab1283b7 2119 echo "${netinfo['ip']}/${netinfo['mask']}</a></td>";
1f54e1ba
DO
2120 echo '<td class=tdleft>' . niftyString ($netinfo['name']);
2121 if (count ($netinfo['etags']))
2122 echo '<br><small>' . serializeTags ($netinfo['etags']) . '</small>';
2123 echo '</td><td>';
4318ced5 2124 echo getRenderedIPNetCapacity ($netinfo);
b1e39212 2125 echo '</tr>';
e673ee24 2126 }
04d619d0
DO
2127 echo "</table>";
2128 finishPortlet();
e673ee24 2129 }
93a49e5b
AA
2130}
2131
2132function renderIPNewNetForm ()
2133{
2134 global $pageno;
2135 if ($pageno == 'ipv6space')
2136 {
2137 $realm = 'ipv6net';
3495ec6e 2138 $regexp = '^[a-fA-F0-9:]*:[a-fA-F0-9:\.]*/\d{1,3}$';
93a49e5b
AA
2139 }
2140 else
2141 {
2142 $realm = 'ipv4net';
3495ec6e 2143 $regexp = '^(\d{1,3}\.){3}\d{1,3}/\d{1,2}$';
93a49e5b
AA
2144 }
2145
2146 // IP prefix validator
2147 addJs ('js/live_validation.js');
2148 $regexp = addslashes ($regexp);
2149 addJs (<<<END
2150$(document).ready(function () {
2151 document.add_new_range.range.setAttribute('match', '$regexp');
2152 Validate.init();
2153});
2154END
2155 , TRUE);
2156
2157 startPortlet ('Add new');
2158 echo '<table border=0 cellpadding=10 align=center>';
2159 // This form requires a name, so JavaScript validator can find it.
2160 // No printOpFormIntro() hence
2161 echo "<form method=post name='add_new_range' action='".makeHrefProcess()."'>\n";
2162 echo "<input type=hidden name=op value=add>\n";
2163 // tags column
2164 echo '<tr><td rowspan=5><h3>assign tags</h3>';
2165 renderNewEntityTags ($realm);
2166 echo '</td>';
2167 // inputs column
2168 $prefix_value = empty ($_REQUEST['set-prefix']) ? '' : $_REQUEST['set-prefix'];
2169 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>";
2170 echo '<tr><th class=tdright>VLAN</th><td class=tdleft>';
2171 echo getOptionTree ('vlan_ck', getAllVLANOptions(), array ('select_class' => 'vertical', 'tabindex' => 2)) . '</td></tr>';
2172 echo "<tr><th class=tdright>name</th><td class=tdleft><input type=text name='name' size='20' tabindex=3></td></tr>";
2173 echo '<tr><td class=tdright><input type=checkbox name="is_connected" tabindex=4></td><th class=tdleft>reserve subnet-router anycast address</th></tr>';
2174 echo "<tr><td colspan=2>";
2175 printImageHREF ('CREATE', 'Add a new network', TRUE, 5);
2176 echo '</td></tr>';
2177 echo "</form></table><br><br>\n";
2178 finishPortlet();
e673ee24
DO
2179}
2180
4318ced5 2181function getRenderedIPNetBacktrace ($range)
e673ee24 2182{
4318ced5
AA
2183 if (getConfigVar ('EXT_IPV4_VIEW') != 'yes')
2184 return array();
e673ee24 2185
4318ced5
AA
2186 $v = ($range['realm'] == 'ipv4net') ? 4 : 6;
2187 $space = "ipv${v}space"; // ipv4space, ipv6space
2188 $tag = "\$ip${v}netid_"; // $ip4netid_, $ip6netid_
2189
2190 $ret = array();
2191 // Build a backtrace from all parent networks.
2192 $clen = $range['mask'];
2193 $backtrace = array();
2194 $backtrace['&rarr;'] = $range;
2195 $key = '';
2196 while (NULL !== ($upperid = getIPAddressNetworkId ($range['ip_bin'], $clen)))
2197 {
2198 $upperinfo = spotEntity ($range['realm'], $upperid);
2199 $clen = $upperinfo['mask'];
2200 $key .= '&uarr;';
2201 $backtrace[$key] = $upperinfo;
2202 }
2203 foreach (array_reverse ($backtrace) as $arrow => $ainfo)
2204 {
2205 $link = '<a href="' . makeHref (array (
2206 'page' => $space,
2207 'tab' => 'default',
2208 'clear-cf' => '',
2209 'cfe' => '{' . $tag . $ainfo['id'] . '}',
2210 'hl_net' => 1,
2211 'eid' => $range['id'],
2212 )) . '" title="View IP tree with this net as root">' . $arrow . '</a>';
2213 $ret[] = array ($link, getOutputOf ('renderCell', $ainfo));
2214 }
2215 return $ret;
2216}
2217
2218function renderIPNetwork ($id)
2219{
2220 global $pageno;
2221 $realm = $pageno; // 'ipv4net', 'ipv6net'
2222 $range = spotEntity ($realm, $id);
2223 loadIPAddrList ($range);
2034d968 2224 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
99ab184f
DO
2225 echo "<tr><td colspan=2 align=center><h1>${range['ip']}/${range['mask']}</h1><h2>";
2226 echo htmlspecialchars ($range['name'], ENT_QUOTES, 'UTF-8') . "</h2></td></tr>\n";
2034d968
DO
2227
2228 echo "<tr><td class=pcleft width='50%'>";
646272be
AA
2229
2230 // render summary portlet
2231 $summary = array();
4318ced5
AA
2232 $summary['%% used'] = getRenderedIPNetCapacity ($range);
2233 $summary = array_merge ($summary, getRenderedIPNetBacktrace ($range));
2234 if ($realm == 'ipv4net')
001e61fa 2235 {
4318ced5
AA
2236 $summary[] = array ('Netmask:', ip4_format ($range['mask_bin']));
2237 $summary[] = array ('Netmask:', "0x" . strtoupper (implode ('', unpack ('H*', $range['mask_bin']))));
2238 $summary['Wildcard bits'] = ip4_format ( ~ $range['mask_bin']);
001e61fa 2239 }
646272be 2240
a5f9d1ca 2241 foreach ($range['8021q'] as $item)
cbf78395 2242 {
a5f9d1ca 2243 $vlaninfo = getVLANInfo ($item['domain_id'] . '-' . $item['vlan_id']);
646272be 2244 $summary[] = array ('VLAN:', '<a href="' . makeHref (array ('page' => 'vlan', 'vlan_ck' => $vlaninfo['vlan_ck'])) . '">' . formatVLANName ($vlaninfo, 'markup long') . '</a>');
cbf78395 2245 }
3a4f4023 2246 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes' and count ($routers = findRouters ($range['addrlist'])))
04d619d0 2247 {
646272be
AA
2248 $summary['Routed by'] = '';
2249 foreach ($routers as $rtr)
4318ced5 2250 $summary['Routed by'] .= getOutputOf ('renderRouterCell', $rtr['ip_bin'], $rtr['iface'], spotEntity ('object', $rtr['id']));
04d619d0 2251 }
646272be
AA
2252 $summary['tags'] = '';
2253 renderEntitySummary ($range, 'summary', $summary);
e1ae3fb4 2254
99ab184f
DO
2255 if (strlen ($range['comment']))
2256 {
2257 startPortlet ('Comment');
2258 echo '<div class=commentblock>' . string_insert_hrefs (htmlspecialchars ($range['comment'], ENT_QUOTES, 'UTF-8')) . '</div>';
2259 finishPortlet ();
2260 }
2261
4318ced5 2262 renderFilesPortlet ($realm, $id);
2034d968 2263 echo "</td>\n";
e673ee24 2264
2034d968
DO
2265 echo "<td class=pcright>";
2266 startPortlet ('details');
4318ced5
AA
2267 renderIPNetworkAddresses ($range);
2268 finishPortlet();
2269 echo "</td></tr></table>\n";
2270}
e673ee24 2271
4318ced5
AA
2272// Used solely by renderSeparator
2273function renderEmptyIPv6 ($ip_bin, $hl_ip)
2274{
2275 $class = 'tdleft';
2276 if ($ip_bin === $hl_ip)
2277 $class .= ' port_highlight';
2278 $fmt = ip6_format ($ip_bin);
2279 echo "<tr class='$class'><td><a class='ancor' name='ip-$fmt' href='" . makeHref (array ('page' => 'ipaddress', 'ip' => $fmt)) . "'>" . $fmt;
2280 echo "</a></td><td class='rsv-port'><span class='rsvtext'></span></td><td>&nbsp;</td></tr>\n";
2281}
2282
2283// Renders empty table line to shrink empty IPv6 address ranges.
2284// If the range consists of single address, renders the address instead of empty line.
2285// Renders address $hl_ip inside the range.
2286// Used solely by renderIPv6NetworkAddresses
2287function renderSeparator ($first, $last, $hl_ip)
2288{
2289 $self = __FUNCTION__;
2290 if (strcmp ($first, $last) > 0)
2291 return;
2292 if ($first == $last)
2293 renderEmptyIPv6 ($first, $hl_ip);
2294 elseif (isset ($hl_ip) && strcmp ($hl_ip, $first) >= 0 && strcmp ($hl_ip, $last) <= 0)
2295 { // $hl_ip is inside the range $first - $last
2296 $self ($first, ip_prev ($hl_ip), $hl_ip);
2297 renderEmptyIPv6 ($hl_ip, $hl_ip);
2298 $self (ip_next ($hl_ip), $last, $hl_ip);
2299 }
2300 else
2301 echo "<tr><td colspan=3 class=tdleft></td></tr>\n";
2302}
2303
2304// calculates page number which contains given $ip (used by renderIPv6NetworkAddresses)
2305function getPageNumOfIPv6 ($list, $ip_bin, $maxperpage)
2306{
2307 if (intval ($maxperpage) <= 0 || count ($list) <= $maxperpage)
2308 return 0;
2309 $keys = array_keys ($list);
2310 for ($i = 1; $i <= count ($keys); $i++)
2311 if (strcmp ($keys[$i-1], $ip_bin) >= 0)
2312 return intval ($i / $maxperpage);
2313 return intval (count ($list) / $maxperpage);
2314}
2315
2316function renderIPNetworkAddresses ($range)
2317{
2318 switch (strlen ($range['ip_bin']))
2319 {
2320 case 4: return renderIPv4NetworkAddresses ($range);
2321 case 16: return renderIPv6NetworkAddresses ($range);
2322 default: throw new InvalidArgException ("range['ip_bin']", $range['ip_bin']);
2323 }
2324}
2325
2326function renderIPv4NetworkAddresses ($range)
2327{
2328 global $pageno, $tabno, $aac2;
2329 $startip = ip4_bin2int ($range['ip_bin']);
2330 $endip = ip4_bin2int (ip_last ($range));
2331
2332 if (isset ($_REQUEST['hl_ip']))
00276508 2333 {
4318ced5
AA
2334 $hl_ip = ip4_bin2int (ip4_parse ($_REQUEST['hl_ip']));
2335 addAutoScrollScript ('ip-' . $_REQUEST['hl_ip']); // scroll page to highlighted ip
00276508
AA
2336 }
2337
79b57b18
AA
2338 // pager
2339 $maxperpage = getConfigVar ('IPV4_ADDRS_PER_PAGE');
2340 $address_count = $endip - $startip + 1;
2341 $page = 0;
446c25c3 2342 $rendered_pager = '';
79b57b18
AA
2343 if ($address_count > $maxperpage && $maxperpage > 0)
2344 {
2345 $page = isset ($_REQUEST['pg']) ? $_REQUEST['pg'] : (isset ($hl_ip) ? intval (($hl_ip - $startip) / $maxperpage) : 0);
2346 if ($numpages = ceil ($address_count / $maxperpage))
2347 {
4318ced5 2348 echo '<h3>' . ip4_format (ip4_int2bin ($startip)) . ' ~ ' . ip4_format (ip4_int2bin ($endip)) . '</h3>';
79b57b18
AA
2349 for ($i = 0; $i < $numpages; $i++)
2350 if ($i == $page)
446c25c3 2351 $rendered_pager .= "<b>$i</b> ";
79b57b18 2352 else
4318ced5 2353 $rendered_pager .= "<a href='".makeHref (array ('page' => $pageno, 'tab' => $tabno, 'id' => $range['id'], 'pg' => $i)) . "'>$i</a> ";
79b57b18
AA
2354 }
2355 $startip = $startip + $page * $maxperpage;
2356 $endip = min ($startip + $maxperpage - 1, $endip);
2357 }
2358
446c25c3 2359 echo $rendered_pager;
beb9e88a 2360 echo "<table class='widetable' border=0 cellspacing=0 cellpadding=5 align='center' width='100%'>\n";
e673ee24
DO
2361 echo "<tr><th>Address</th><th>Name</th><th>Allocation</th></tr>\n";
2362
4318ced5
AA
2363 markupIPAddrList ($range['addrlist']);
2364 for ($ip = $startip; $ip <= $endip; $ip++)
2365 {
2366 $ip_bin = ip4_int2bin ($ip);
2367 $dottedquad = ip4_format ($ip_bin);
2368 $tr_class = (isset ($hl_ip) && $hl_ip == $ip ? 'port_highlight' : '');
2369 if (!isset ($range['addrlist'][$ip_bin]))
e673ee24 2370 {
4318ced5
AA
2371 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>";
2372 echo "<td class='rsv-port'><span class='rsvtext'></span></td><td>&nbsp;</td></tr>\n";
b2035dca
DO
2373 continue;
2374 }
4318ced5 2375 $addr = $range['addrlist'][$ip_bin];
68c91b9c
AA
2376 // render IP change history
2377 $title = '';
2378 $history_class = '';
2379 if (isset ($addr['last_log']))
2380 {
2381 $title = ' title="' . htmlspecialchars ($addr['last_log']['user'] . ', ' . formatAge ($addr['last_log']['time']) , ENT_QUOTES) . '"';
2382 $history_class = 'hover-history underline';
2383 }
4318ced5
AA
2384 $tr_class .= ' ' . $addr['class'];
2385 echo "<tr class='tdleft $tr_class'>";
2386 echo "<td><a class='ancor $history_class' $title name='ip-$dottedquad' href='".makeHref(array('page'=>'ipaddress', 'ip'=>$addr['ip']))."'>${addr['ip']}</a></td>";
2387 echo "<td class='" .
a8dc2982 2388 (empty ($addr['allocs']) || !empty ($addr['name']) ? 'rsv-port' : '') .
4318ced5 2389 "'><span class='rsvtext'>${addr['name']}</span></td><td>";
b2035dca 2390 $delim = '';
b2035dca
DO
2391 if ( $addr['reserved'] == 'yes')
2392 {
2d318652 2393 echo "<strong>RESERVED</strong> ";
b2035dca
DO
2394 $delim = '; ';
2395 }
212b565a 2396 foreach ($addr['allocs'] as $ref)
b2035dca 2397 {
beb9e88a 2398 echo $delim . $aac2[$ref['type']];
4318ced5 2399 echo "<a href='".makeHref(array('page'=>'object', 'object_id'=>$ref['object_id'], 'tab' => 'default', 'hl_ip'=>$addr['ip']))."'>";
59a83bd8 2400 echo $ref['name'] . (!strlen ($ref['name']) ? '' : '@');
b2035dca
DO
2401 echo "${ref['object_name']}</a>";
2402 $delim = '; ';
2403 }
2404 if ($delim != '')
e0d6e38e 2405 $delim = '<br>';
212b565a
AA
2406 foreach ($addr['vslist'] as $vs_id)
2407 {
2408 $vs = spotEntity ('ipv4vs', $vs_id);
2409 echo "${delim}<a href='".makeHref(array('page'=>'ipv4vs', 'vs_id'=>$vs['id']))."'>";
2410 echo "${vs['name']}:${vs['vport']}/${vs['proto']}</a>&rarr;";
2411 $delim = '<br>';
2412 }
2413 foreach ($addr['rsplist'] as $rsp_id)
2414 {
2415 $rsp = spotEntity ('ipv4rspool', $rsp_id);
2416 echo "${delim}&rarr;<a href='".makeHref(array('page'=>'ipv4rspool', 'pool_id'=>$rsp['id']))."'>";
2417 echo "${rsp['name']}</a>";
2418 $delim = '<br>';
2419 }
b2035dca 2420 echo "</td></tr>\n";
4318ced5 2421 }
2727c7df 2422 // end of iteration
a8dc2982
AA
2423 if (permitted (NULL, NULL, 'set_reserve_comment'))
2424 addJS ('js/inplace-edit.js');
e673ee24
DO
2425
2426 echo "</table>";
446c25c3
AA
2427 if (! empty ($rendered_pager))
2428 echo '<p>' . $rendered_pager . '</p>';
21ee3351
AA
2429}
2430
2431function renderIPv6NetworkAddresses ($netinfo)
2432{
2433 global $pageno, $tabno, $aac2;
2434 echo "<table class='widetable' border=0 cellspacing=0 cellpadding=5 align='center' width='100%'>\n";
2435 echo "<tr><th>Address</th><th>Name</th><th>Allocation</th></tr>\n";
2436
4318ced5
AA
2437 $hl_ip = NULL;
2438 if (isset ($_REQUEST['hl_ip']))
2439 {
2440 $hl_ip = ip6_parse ($_REQUEST['hl_ip']);
2441 addAutoScrollScript ('ip-' . ip6_format ($hl_ip));
2442 }
21ee3351 2443
21ee3351
AA
2444 $addresses = $netinfo['addrlist'];
2445 ksort ($addresses);
4318ced5 2446 markupIPAddrList ($addresses);
21ee3351
AA
2447
2448 // pager
2449 $maxperpage = getConfigVar ('IPV4_ADDRS_PER_PAGE');
2450 if (count ($addresses) > $maxperpage && $maxperpage > 0)
2451 {
2452 $page = isset ($_REQUEST['pg']) ? $_REQUEST['pg'] : (isset ($hl_ip) ? getPageNumOfIPv6 ($addresses, $hl_ip, $maxperpage) : 0);
2453 $numpages = ceil (count ($addresses) / $maxperpage);
2454 echo "<center><h3>$numpages pages:</h3>";
2455 for ($i=0; $i<$numpages; $i++)
2456 {
2457 if ($i == $page)
2458 echo "<b>$i</b> ";
2459 else
2460 echo "<a href='" . makeHref (array ('page' => $pageno, 'tab' => $tabno, 'id' => $netinfo['id'], 'pg' => $i)) . "'>$i</a> ";
2461 }
2462 echo "</center>";
2463 }
2464
2465 $i = 0;
2466 $interruped = FALSE;
4318ced5
AA
2467 $prev_ip = ip_prev ($netinfo['ip_bin']);
2468 foreach ($addresses as $ip_bin => $addr)
21ee3351
AA
2469 {
2470 if (isset ($page))
2471 {
2472 ++$i;
2473 if ($i <= $maxperpage * $page)
2474 continue;
2475 elseif ($i > $maxperpage * ($page + 1))
2476 {
2477 $interruped = TRUE;
2478 break;
2479 }
2480 }
2481
4318ced5
AA
2482 if ($ip_bin != ip_next ($prev_ip))
2483 renderSeparator (ip_next ($prev_ip), ip_prev ($ip_bin), $hl_ip);
2484 $prev_ip = $ip_bin;
2485
2486 // render IP change history
2487 $title = '';
2488 $history_class = '';
2489 if (isset ($addr['last_log']))
2490 {
2491 $title = ' title="' . htmlspecialchars ($addr['last_log']['user'] . ', ' . formatAge ($addr['last_log']['time']) , ENT_QUOTES) . '"';
2492 $history_class = 'hover-history underline';
2493 }
2494
2495 $tr_class = $addr['class'] . ' tdleft' . ($hl_ip === $ip_bin ? ' port_highlight' : '');
2496 echo "<tr class='$tr_class'>";
2497 echo "<td><a class='ancor $history_class' $title name='ip-${addr['ip']}' href='" . makeHref (array ('page' => 'ipaddress', 'ip' => $addr['ip'])) . "'>${addr['ip']}</a></td>";
2498 echo "<td class='" .
a8dc2982 2499 (empty ($addr['allocs']) || !empty ($addr['name']) ? 'rsv-port' : '') .
4318ced5 2500 "'><span class='rsvtext'>${addr['name']}</span></td><td>";
21ee3351 2501 $delim = '';
21ee3351
AA
2502 if ( $addr['reserved'] == 'yes')
2503 {
2504 echo "<strong>RESERVED</strong> ";
2505 $delim = '; ';
2506 }
2507 foreach ($addr['allocs'] as $ref)
2508 {
2509 echo $delim . $aac2[$ref['type']];
71066ef1 2510 echo "<a href='".makeHref(array('page'=>'object', 'object_id'=>$ref['object_id'], 'tab' => 'default', 'hl_ip'=>$addr['ip']))."'>";
21ee3351
AA
2511 echo $ref['name'] . (!strlen ($ref['name']) ? '' : '@');
2512 echo "${ref['object_name']}</a>";
2513 $delim = '; ';
2514 }
2515 if ($delim != '')
71066ef1
AA
2516 $delim = '<br>';
2517 foreach ($addr['vslist'] as $vs_id)
2518 {
2519 $vs = spotEntity ('ipv4vs', $vs_id);
2520 echo "${delim}<a href='".makeHref(array('page'=>'ipv4vs', 'vs_id'=>$vs['id']))."'>";
2521 echo "${vs['name']}:${vs['vport']}/${vs['proto']}</a>&rarr;";
2522 $delim = '<br>';
2523 }
2524 foreach ($addr['rsplist'] as $rsp_id)
21ee3351 2525 {
71066ef1
AA
2526 $rsp = spotEntity ('ipv4rspool', $rsp_id);
2527 echo "${delim}&rarr;<a href='".makeHref(array('page'=>'ipv4rspool', 'pool_id'=>$rsp['id']))."'>";
2528 echo "${rsp['name']}</a>";
2529 $delim = '<br>';
21ee3351
AA
2530 }
2531 echo "</td></tr>\n";
2532 }
2533 if (! $interruped)
4318ced5 2534 renderSeparator (ip_next ($prev_ip), ip_last ($netinfo), $hl_ip);
21ee3351
AA
2535 if (isset ($page))
2536 { // bottom pager
2537 echo "<tr><td colspan=3>";
2538 if ($page > 0)
2539 echo "<a href='" . makeHref (array ('page' => $pageno, 'tab' => $tabno, 'id' => $netinfo['id'], 'pg' => $page - 1)) . "'><< prev</a> ";
2540 if ($page < $numpages - 1)
2541 echo "<a href='" . makeHref (array ('page' => $pageno, 'tab' => $tabno, 'id' => $netinfo['id'], 'pg' => $page + 1)) . "'>next >></a> ";
2542 echo "</td></tr>";
2543 }
2544 echo "</table>";
a8dc2982
AA
2545 if (permitted (NULL, NULL, 'set_reserve_comment'))
2546 addJS ('js/inplace-edit.js');
21ee3351
AA
2547}
2548
2549function renderIPNetworkProperties ($id)
e673ee24 2550{
21ee3351
AA
2551 global $pageno;
2552 $netdata = spotEntity ($pageno, $id);
53ef3908 2553 echo "<center><h1>${netdata['ip']}/${netdata['mask']}</h1></center>\n";
e673ee24 2554 echo "<table border=0 cellpadding=10 cellpadding=1 align='center'>\n";
7056988c 2555 printOpFormIntro ('editRange');
99ab184f
DO
2556 echo '<tr><td class=tdright><label for=nameinput>Name:</label></td>';
2557 echo "<td class=tdleft><input type=text name=name id=nameinput size=80 maxlength=255 value='";
2558 echo htmlspecialchars ($netdata['name'], ENT_QUOTES, 'UTF-8') . "'></tr>";
2559 echo '<tr><td class=tdright><label for=commentinput>Comment:</label></td>';
2560 echo "<td class=tdleft><textarea name=comment id=commentinput cols=80 rows=25>\n";
2561 echo htmlspecialchars ($netdata['comment'], ENT_QUOTES, 'UTF-8') . "</textarea></tr>";
53ef3908
DO
2562 echo "<tr><td colspan=2 class=tdcenter>";
2563 printImageHREF ('SAVE', 'Save changes', TRUE);
2564 echo "</td></form></tr></table>\n";
93a49e5b
AA
2565
2566 echo '<center>';
2567 if (! isIPNetworkEmpty ($netdata))
2568 echo getOpLink (NULL, 'delete this prefix', 'nodestroy', 'There are ' . count ($netdata['addrlist']) . ' allocations inside');
2569 else
2570 echo getOpLink (array('op'=>'del','id'=>$id), 'delete this prefix', 'destroy');
2571 echo '</center>';
e673ee24
DO
2572}
2573
4318ced5 2574function renderIPAddress ($ip)
e673ee24 2575{
46098972 2576 global $aat, $nextorder;
4318ced5 2577 $address = getIPAddress (ip_parse ($ip));
68225375 2578 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
21ee3351 2579 echo "<tr><td colspan=2 align=center><h1>${address['ip']}</h1></td></tr>\n";
e673ee24 2580
68225375 2581 echo "<tr><td class=pcleft>";
defd92d8
AA
2582
2583 $summary = array();
423c4216 2584 if (strlen ($address['name']))
defd92d8
AA
2585 $summary['Comment'] = $address['name'];
2586 $summary['Reserved'] = $address['reserved'];
2587 $summary['Allocations'] = count ($address['allocs']);
4318ced5 2588 if (isset ($address['outpf']))
defd92d8 2589 $summary['Originated NAT connections'] = count ($address['outpf']);
4318ced5 2590 if (isset ($address['inpf']))
defd92d8 2591 $summary['Arriving NAT connections'] = count ($address['inpf']);
defd92d8 2592 renderEntitySummary ($address, 'summary', $summary);
212b565a
AA
2593
2594 // render SLB portlet
4318ced5 2595 if (! empty ($address['vslist']) or ! empty ($address['rsplist']))
212b565a
AA
2596 {
2597 startPortlet ("");
2598 if (! empty ($address['vslist']))
2599 {
2600 printf ("<h2>virtual services (%d):</h2>", count ($address['vslist']));
2601 foreach ($address['vslist'] as $vs_id)
2602 renderSLBEntityCell (spotEntity ('ipv4vs', $vs_id));
2603 }
2604
2605 if (! empty ($address['rsplist']))
2606 {
2607 printf ("<h2>RS pools (%d):</h2>", count ($address['rsplist']));
2608 foreach ($address['rsplist'] as $rsp_id)
2609 renderSLBEntityCell (spotEntity ('ipv4rspool', $rsp_id));
2610 }
2611 finishPortlet();
2612 }
68225375 2613 echo "</td>\n";
e673ee24 2614
68225375 2615 echo "<td class=pcright>";
defd92d8 2616 if (isset ($address['class']) and ! empty ($address['allocs']))
59bebe2b 2617 {
8e700dd1 2618 startPortlet ('allocations');
2d318652
DO
2619 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2620 echo "<tr><th>object</th><th>OS interface</th><th>allocation type</th></tr>\n";
2d318652 2621 // render all allocation records for this address the same way
2d318652 2622 foreach ($address['allocs'] as $bond)
59bebe2b 2623 {
4318ced5 2624 $tr_class = "${address['class']} tdleft";
8e700dd1 2625 if (isset ($_REQUEST['hl_object_id']) and $_REQUEST['hl_object_id'] == $bond['object_id'])
4318ced5
AA
2626 $tr_class .= ' port_highlight';
2627 echo "<tr class='$tr_class'>" .
2628 "<td><a href='" . makeHref (array ('page' => 'object', 'object_id' => $bond['object_id'], 'tab' => 'default', 'hl_ip' => $address['ip'])) . "'>${bond['object_name']}</td>" .
2629 "<td>${bond['name']}</td>" .
2630 "<td><strong>" . $aat[$bond['type']] . "</strong></td>" .
2631 "</tr>\n";
59bebe2b
DO
2632 }
2633 echo "</table><br><br>";
2634 finishPortlet();
2635 }
e673ee24 2636
4318ced5 2637 if (! empty ($address['vslist']) or ! empty ($address['rsplist']))
defd92d8 2638 renderSLBTriplets ($address);
5fe1ed76 2639
21ee3351 2640 if (! empty ($address['outpf']))
68225375 2641 {
105a3bc8 2642 startPortlet ('departing NAT rules');
2d318652 2643 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
105a3bc8
DO
2644 echo "<tr><th>proto</th><th>from</th><th>to</th><th>comment</th></tr>\n";
2645 foreach ($address['outpf'] as $rule)
b62ff880 2646 echo "<tr><td>${rule['proto']}</td><td>${rule['localip']}:${rule['localport']}</td><td>${rule['remoteip']}:${rule['remoteport']}</td><td>${rule['description']}</td></tr>";
105a3bc8 2647 echo "</table>";
68225375
DO
2648 finishPortlet();
2649 }
105a3bc8 2650
21ee3351 2651 if (! empty ($address['inpf']))
105a3bc8
DO
2652 {
2653 startPortlet ('arriving NAT rules');
2d318652 2654 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
105a3bc8
DO
2655 echo "<tr><th>proto</th><th>from</th><th>to</th><th>comment</th></tr>\n";
2656 foreach ($address['inpf'] as $rule)
b62ff880 2657 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
2658 echo "</table>";
2659 finishPortlet();
2660 }
2661
68225375
DO
2662 echo "</td></tr>";
2663 echo "</table>\n";
e673ee24
DO
2664}
2665
4318ced5 2666function renderIPAddressProperties ($ip)
e673ee24 2667{
4318ced5 2668 $address = getIPAddress (ip_parse ($ip));
21ee3351 2669 echo "<center><h1>${address['ip']}</h1></center>\n";
7056988c 2670
1fbc9fd6 2671 startPortlet ('update');
e673ee24 2672 echo "<table border=0 cellpadding=10 cellpadding=1 align='center'>\n";
7056988c 2673 printOpFormIntro ('editAddress');
0186638b
DO
2674 echo '<tr><td class=tdright><label for=id_name>Name:</label></td>';
2675 echo "<td class=tdleft><input type=text name=name id=id_name size=20 value='${address['name']}'></tr>";
2676 echo '<td class=tdright><label for=id_reserved>Reserved:</label></td>';
2677 echo "<td class=tdleft><input type=checkbox name=reserved id=id_reserved size=20 ";
2d318652 2678 echo ($address['reserved']=='yes') ? 'checked' : '';
f3d274bf 2679 echo "></tr><tr><td class=tdleft>";
53ef3908 2680 printImageHREF ('SAVE', 'Save changes', TRUE);
f3d274bf 2681 echo "</td></form><td class=tdright>";
59a83bd8 2682 if (!strlen ($address['name']) and $address['reserved'] == 'no')
f3d274bf
DO
2683 printImageHREF ('CLEAR gray');
2684 else
2685 {
2686 printOpFormIntro ('editAddress', array ('name' => '', 'reserved' => ''));
2687 printImageHREF ('CLEAR', 'Release', TRUE);
2688 echo "</form>";
2689 }
2690 echo "</td></tr></table>\n";
1fbc9fd6 2691 finishPortlet();
e673ee24
DO
2692}
2693
4318ced5 2694function renderIPAddressAllocations ($ip)
e673ee24 2695{
4318ced5 2696 function printNewItemTR ()
39b4abd0
DO
2697 {
2698 global $aat;
4318ced5 2699 printOpFormIntro ('add');
39b4abd0 2700 echo "<tr><td>";
9318d2ef 2701 printImageHREF ('add', 'allocate', TRUE);
8d4f7d18 2702 echo "</td><td>";
31babb65 2703 printSelect (getNarrowObjectList ('IPV4OBJ_LISTSRC'), array ('name' => 'object_id', 'tabindex' => 100));
8d4f7d18 2704 echo "</td><td><input type=text tabindex=101 name=bond_name size=10></td><td>";
01abf1de 2705 printSelect ($aat, array ('name' => 'bond_type', 'tabindex' => 102, 'regular'));
9318d2ef 2706 echo "</td><td>";
f5ff50f5 2707 printImageHREF ('add', 'allocate', TRUE, 103);
9318d2ef 2708 echo "</td></form></tr>";
39b4abd0 2709 }
b82cce3f 2710 global $aat;
e673ee24 2711
4318ced5 2712 $address = getIPAddress (ip_parse ($ip));
21ee3351 2713 echo "<center><h1>${address['ip']}</h1></center>\n";
105a3bc8 2714 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
2d318652 2715 echo "<tr><th>&nbsp;</th><th>object</th><th>OS interface</th><th>allocation type</th><th>&nbsp;</th></tr>\n";
e673ee24 2716
39b4abd0 2717 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
4318ced5 2718 printNewItemTR();
f74d96c6 2719 if (isset ($address['class']))
e673ee24 2720 {
f74d96c6
DO
2721 $class = $address['class'];
2722 if ($address['reserved'] == 'yes')
2723 echo "<tr class='${class}'><td colspan=3>&nbsp;</td><td class=tdleft><strong>RESERVED</strong></td><td>&nbsp;</td></tr>";
2724 foreach ($address['allocs'] as $bond)
2725 {
2726 echo "<tr class='$class'>";
4318ced5 2727 printOpFormIntro ('upd', array ('object_id' => $bond['object_id']));
21ee3351
AA
2728 echo "<td><a href='"
2729 . makeHrefProcess
2730 (
2731 array
2732 (
4318ced5 2733 'op' => 'del',
21ee3351
AA
2734 'ip' => $address['ip'],
2735 'object_id' => $bond['object_id']
2736 )
2737 )
2738 . "'>";
f74d96c6
DO
2739 printImageHREF ('delete', 'Unallocate address');
2740 echo "</a></td>";
4318ced5 2741 echo "<td><a href='" . makeHref (array ('page' => 'object', 'object_id' => $bond['object_id'], 'hl_ip' => $address['ip'])) . "'>${bond['object_name']}</td>";
f74d96c6 2742 echo "<td><input type='text' name='bond_name' value='${bond['name']}' size=10></td><td>";
cd3775e9 2743 printSelect ($aat, array ('name' => 'bond_type'), $bond['type']);
f74d96c6
DO
2744 echo "</td><td>";
2745 printImageHREF ('save', 'Save changes', TRUE);
2746 echo "</td></form></tr>\n";
2747 }
e673ee24 2748 }
39b4abd0 2749 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
4318ced5 2750 printNewItemTR();
e673ee24 2751 echo "</table><br><br>";
e673ee24
DO
2752}
2753
7e1db771 2754function renderNATv4ForObject ($object_id)
e673ee24 2755{
9318d2ef
DO
2756 function printNewItemTR ($alloclist)
2757 {
9318d2ef
DO
2758 printOpFormIntro ('addNATv4Rule');
2759 echo "<tr align='center'><td>";
2760 printImageHREF ('add', 'Add new NAT rule', TRUE);
2761 echo '</td><td>';
cd3775e9 2762 printSelect (array ('TCP' => 'TCP', 'UDP' => 'UDP'), array ('name' => 'proto'));
9318d2ef
DO
2763 echo "<select name='localip' tabindex=1>";
2764
4318ced5 2765 foreach ($alloclist as $ip_bin => $alloc)
9318d2ef 2766 {
4318ced5 2767 $ip = $alloc['addrinfo']['ip'];
43eb71f1
DO
2768 $name = (!isset ($alloc['addrinfo']['name']) or !strlen ($alloc['addrinfo']['name'])) ? '' : (' (' . niftyString ($alloc['addrinfo']['name']) . ')');
2769 $osif = (!isset ($alloc['osif']) or !strlen ($alloc['osif'])) ? '' : ($alloc['osif'] . ': ');
4318ced5 2770 echo "<option value='${ip}'>${osif}${ip}${name}</option>";
9318d2ef
DO
2771 }
2772
2773 echo "</select>:<input type='text' name='localport' size='4' tabindex=2></td>";
2774 echo "<td><input type='text' name='remoteip' id='remoteip' size='10' tabindex=3>";
39106006
DO
2775 echo "<a href='javascript:;' onclick='window.open(\"" . makeHrefForHelper ('inet4list');
2776 echo "\", \"findobjectip\", \"height=700, width=400, location=no, menubar=no, resizable=yes, scrollbars=no, status=no, titlebar=no, toolbar=no\");'>";
9318d2ef
DO
2777 printImageHREF ('find', 'Find object');
2778 echo "</a>";
2779 echo ":<input type='text' name='remoteport' size='4' tabindex=4></td><td></td>";
2780 echo "<td colspan=1><input type='text' name='description' size='20' tabindex=5></td><td>";
f5ff50f5 2781 printImageHREF ('add', 'Add new NAT rule', TRUE, 6);
9318d2ef
DO
2782 echo "</td></tr></form>";
2783 }
e673ee24 2784
94fe6370
DO
2785 $focus = spotEntity ('object', $object_id);
2786 amplifyCell ($focus);
f28fbe8b 2787 echo "<center><h2>locally performed NAT</h2></center>";
e673ee24 2788
105a3bc8 2789 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
d54b9495 2790 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 2791
9318d2ef 2792 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
94fe6370
DO
2793 printNewItemTR ($focus['ipv4']);
2794 foreach ($focus['nat4']['out'] as $pf)
e673ee24 2795 {
2c817354
DO
2796 $class = 'trerror';
2797 $osif = '';
4318ced5
AA
2798 $localip_bin = ip4_parse ($pf['localip']);
2799 if (isset ($focus['ipv4'][$localip_bin]))
2c817354 2800 {
4318ced5
AA
2801 $class = $focus['ipv4'][$localip_bin]['addrinfo']['class'];
2802 $osif = $focus['ipv4'][$localip_bin]['osif'] . ': ';
2c817354 2803 }
e673ee24
DO
2804
2805 echo "<tr class='$class'>";
4fbb5a00
DY
2806 echo "<td><a href='".
2807 makeHrefProcess(array(
2808 'op'=>'delNATv4Rule',
2809 'localip'=>$pf['localip'],
2810 'localport'=>$pf['localport'],
2811 'remoteip'=>$pf['remoteip'],
2812 'remoteport'=>$pf['remoteport'],
2813 'proto'=>$pf['proto'],
2814 'object_id'=>$object_id)).
2815 "'>";
4de22e7e
DO
2816 printImageHREF ('delete', 'Delete NAT rule');
2817 echo "</a></td>";
4fbb5a00 2818 echo "<td>${pf['proto']}/${osif}<a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['localip']))."'>${pf['localip']}</a>:${pf['localport']}";
59a83bd8 2819 if (strlen ($pf['local_addr_name']))
f28fbe8b
DO
2820 echo ' (' . $pf['local_addr_name'] . ')';
2821 echo "</td>";
4fbb5a00 2822 echo "<td><a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['remoteip']))."'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
e673ee24 2823
4318ced5 2824 $address = getIPAddress (ip4_parse ($pf['remoteip']));
e673ee24
DO
2825
2826 echo "<td class='description'>";
53ef3908
DO
2827 if (count ($address['allocs']))
2828 foreach ($address['allocs'] as $bond)
4fbb5a00 2829 echo "<a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$bond['object_id']))."'>${bond['object_name']}(${bond['name']})</a> ";
59a83bd8 2830 elseif (strlen ($pf['remote_addr_name']))
f28fbe8b 2831 echo '(' . $pf['remote_addr_name'] . ')';
7056988c
DO
2832 printOpFormIntro
2833 (
2834 'updNATv4Rule',
2835 array
2836 (
2837 'localip' => $pf['localip'],
2838 'localport' => $pf['localport'],
2839 'remoteip' => $pf['remoteip'],
2840 'remoteport' => $pf['remoteport'],
2841 'proto' => $pf['proto']
2842 )
2843 );
2844 echo "</td><td class='description'>";
d54b9495
DO
2845 echo "<input type='text' name='description' value='${pf['description']}'></td><td>";
2846 printImageHREF ('save', 'Save changes', TRUE);
2847 echo "</td></form></tr>";
e673ee24 2848 }
9318d2ef 2849 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
94fe6370 2850 printNewItemTR ($focus['ipv4']);
e673ee24
DO
2851
2852 echo "</table><br><br>";
94fe6370
DO
2853 if (!count ($focus['nat4']))
2854 return;
e673ee24 2855
f28fbe8b 2856 echo "<center><h2>arriving NAT connections</h2></center>";
105a3bc8 2857 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
e673ee24
DO
2858 echo "<tr><th></th><th>Source</th><th>Source objects</th><th>Target</th><th>Description</th></tr>\n";
2859
94fe6370 2860 foreach ($focus['nat4']['in'] as $pf)
e673ee24 2861 {
4fbb5a00
DY
2862 echo "<tr><td><a href='".
2863 makeHrefProcess(array(
2864 'op'=>'delNATv4Rule',
2865 'localip'=>$pf['localip'],
2866 'localport'=>$pf['localport'],
2867 'remoteip'=>$pf['remoteip'],
2868 'remoteport'=>$pf['remoteport'],
2869 'proto'=>$pf['proto'],
2870 'object_id'=>$pf['object_id']
2871 )).
2872 "'>";
4de22e7e
DO
2873 printImageHREF ('delete', 'Delete NAT rule');
2874 echo "</a></td>";
4fbb5a00
DY
2875 echo "<td>${pf['proto']}/<a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['localip']))."'>${pf['localip']}</a>:${pf['localport']}</td>";
2876 echo "<td class='description'><a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$pf['object_id']))."'>${pf['object_name']}</a>";
2877 echo "</td><td><a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['remoteip']))."'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
e673ee24
DO
2878 echo "<td class='description'>${pf['description']}</td></tr>";
2879 }
2880
e673ee24 2881 echo "</table><br><br>";
e673ee24
DO
2882}
2883
e673ee24
DO
2884function renderAddMultipleObjectsForm ()
2885{
8dc2a6c8 2886 global $location_obj_types, $virtual_obj_types;
7fa7047a 2887 $typelist = readChapter (CHAP_OBJTYPE, 'o');
4c330a14 2888 $typelist[0] = 'select type...';
7fa7047a 2889 $typelist = cookOptgroups ($typelist);
a1886a78
DO
2890 $max = getConfigVar ('MASSCOUNT');
2891 $tabindex = 100;
7f791d1d 2892
9b8174d7
AD
2893 // create a list of object types to exclude (virtual and location-related ones)
2894 $exclude_typelist = array_merge($location_obj_types, $virtual_obj_types);
2895
0682218d
AD
2896 $phys_typelist = $typelist;
2897 foreach ($phys_typelist['other'] as $key => $value)
2898 {
9b8174d7
AD
2899 // remove from list if type should be excluded
2900 if ($key > 0 && in_array($key, $exclude_typelist))
0682218d
AD
2901 unset($phys_typelist['other'][$key]);
2902 }
2b787762 2903 startPortlet ('Physical objects');
42d73cbf 2904 printOpFormIntro ('addObjects');
e673ee24 2905 echo '<table border=0 align=center>';
f60bb422 2906 echo "<tr><th>Object type</th><th>Common name</th><th>Visible label</th>";
dee24af6 2907 echo "<th>Asset tag</th><th>Tags</th></tr>\n";
9c0b0016 2908 for ($i = 0; $i < $max; $i++)
e673ee24 2909 {
7f791d1d 2910 echo '<tr><td>';
e7ade6bf 2911 // Don't employ DEFAULT_OBJECT_TYPE to avoid creating ghost records for pre-selected empty rows.
0682218d 2912 printNiftySelect ($phys_typelist, array ('name' => "${i}_object_type_id", 'tabindex' => $tabindex), 0);
e673ee24 2913 echo '</td>';
a1886a78
DO
2914 echo "<td><input type=text size=30 name=${i}_object_name tabindex=${tabindex}></td>";
2915 echo "<td><input type=text size=30 name=${i}_object_label tabindex=${tabindex}></td>";
2916 echo "<td><input type=text size=20 name=${i}_object_asset_no tabindex=${tabindex}></td>";
f60bb422
DO
2917 if ($i == 0)
2918 {
2919 echo "<td valign=top rowspan=${max}>";
a26a6ccc 2920 renderNewEntityTags ('object');
f60bb422
DO
2921 echo "</td>\n";
2922 }
e673ee24 2923 echo "</tr>\n";
a1886a78 2924 $tabindex++;
e673ee24 2925 }
216c84bb 2926 echo "<tr><td class=submit colspan=5><input type=submit name=got_fast_data value='Go!'></td></tr>\n";
e673ee24
DO
2927 echo "</form></table>\n";
2928 finishPortlet();
7f791d1d 2929
0682218d 2930 // create a list containing only virtual object types
0682218d
AD
2931 $virt_typelist = $typelist;
2932 foreach ($virt_typelist['other'] as $key => $value)
2933 {
2c2ea5f6 2934 if ($key > 0 && !in_array($key, $virtual_obj_types))
0682218d
AD
2935 unset($virt_typelist['other'][$key]);
2936 }
2937 startPortlet ('Virtual objects');
2938 printOpFormIntro ('addObjects');
2939 echo "<input type=hidden name=virtual_objects value=''>\n";
2940 echo '<table border=0 align=center>';
2941 echo "<tr><th>Object type</th><th>Common name</th><th>Tags</th></tr>\n";
2942 for ($i = 0; $i < $max; $i++)
2943 {
2944 echo '<tr><td>';
2945 // Don't employ DEFAULT_OBJECT_TYPE to avoid creating ghost records for pre-selected empty rows.
2946 printNiftySelect ($virt_typelist, array ('name' => "${i}_object_type_id", 'tabindex' => $tabindex), 0);
2947 echo '</td>';
2948 echo "<td><input type=text size=30 name=${i}_object_name tabindex=${tabindex}></td>";
2949 if ($i == 0)
2950 {
2951 echo "<td valign=top rowspan=${max}>";
2952 renderNewEntityTags ('object');
2953 echo "</td>\n";
2954 }
2955 echo "</tr>\n";
2956 $tabindex++;
2957 }
2958 echo "<tr><td class=submit colspan=5><input type=submit name=got_fast_data value='Go!'></td></tr>\n";
2959 echo "</form></table>\n";
2960 finishPortlet();
2961
f60bb422 2962 startPortlet ('Same type, same tags');
42d73cbf 2963 printOpFormIntro ('addLotOfObjects');
f60bb422
DO
2964 echo "<table border=0 align=center><tr><th>names</th><th>type</th></tr>";
2965 echo "<tr><td rowspan=3><textarea name=namelist cols=40 rows=25>\n";
f60bb422 2966 echo "</textarea></td><td valign=top>";
cd3775e9 2967 printNiftySelect ($typelist, array ('name' => 'global_type_id'), getConfigVar ('DEFAULT_OBJECT_TYPE'));
f60bb422
DO
2968 echo "</td></tr>";
2969 echo "<tr><th>Tags</th></tr>";
2970 echo "<tr><td valign=top>";
a26a6ccc 2971 renderNewEntityTags ('object');
f60bb422
DO
2972 echo "</td></tr>";
2973 echo "<tr><td colspan=2><input type=submit name=got_very_fast_data value='Go!'></td></tr></table>\n";
2974 echo "</form>\n";
7f791d1d 2975 finishPortlet();
e673ee24
DO
2976}
2977
671027eb
DO
2978function searchHandler()
2979{
e673ee24 2980 $terms = trim ($_REQUEST['q']);
59a83bd8 2981 if (!strlen ($terms))
0cc24e9a 2982 throw new InvalidRequestArgException('q', $_REQUEST['q'], 'Search string cannot be empty.');
671027eb 2983 renderSearchResults ($terms, searchEntitiesByText ($terms));
09ce7c20 2984}
25e55cab 2985
521cd29a 2986function renderSearchResults ($terms, $summary)
09ce7c20 2987{
521cd29a
AA
2988 // calculate the number of found objects
2989 $nhits = 0;
2990 foreach ($summary as $realm => $list)
2991 $nhits += count ($list);
2992
ea5fc465
DO
2993 if ($nhits == 0)
2994 echo "<center><h2>Nothing found for '${terms}'</h2></center>";
2995 elseif ($nhits == 1)
2996 {
6427286d
AA
2997 foreach ($summary as $realm => $record)
2998 {
2999 if (is_array ($record))
3000 $record = array_shift ($record);
3001 break;
3002 }
521cd29a 3003 switch ($realm)
ea5fc465 3004 {
f3d0cb20 3005 case 'ipv4addressbydq':
521cd29a 3006 if ($record['net_id'] !== NULL)
4318ced5 3007 echo "<script language='Javascript'>document.location='index.php?page=ipv4net&tab=default&id=${record['net_id']}&hl_ip=${record['ip']}';//</script>";
ea5fc465 3008 break;
21ee3351 3009 case 'ipv6addressbydq':
4318ced5 3010 $fmt = ip6_format ($record['ip']);
521cd29a 3011 if ($record['net_id'] !== NULL)
4318ced5 3012 echo "<script language='Javascript'>document.location='index.php?page=ipv6net&tab=default&id=${record['net_id']}&hl_ip=${fmt}';//</script>";
21ee3351 3013 break;
f3d0cb20
DO
3014 case 'ipv4addressbydescr':
3015 $parentnet = getIPv4AddressNetworkId ($record['ip']);
3016 if ($parentnet !== NULL)
4318ced5
AA
3017 {
3018 $fmt = ip4_format ($record['ip']);
3019 echo "<script language='Javascript'>document.location='index.php?page=ipv4net&tab=default&id=${parentnet}&hl_ip=${fmt}';//</script>";
3020 }
ea5fc465 3021 break;
21ee3351 3022 case 'ipv6addressbydescr':
4318ced5 3023 $parentnet = getIPv6AddressNetworkId ($record['ip']);
21ee3351 3024 if ($parentnet !== NULL)
4318ced5
AA
3025 {
3026 $fmt = ip6_format ($record['ip']);
3027 echo "<script language='Javascript'>document.location='index.php?page=ipv6net&tab=default&id=${parentnet}&hl_ip=${fmt}';//</script>";
3028 }
21ee3351 3029 break;
ea5fc465 3030 case 'ipv4network':
790a60e8 3031 echo "<script language='Javascript'>document.location='index.php?page=ipv4net";
ea5fc465
DO
3032 echo "&id=${record['id']}";
3033 echo "';//</script>";
3034 break;
21ee3351
AA
3035 case 'ipv6network':
3036 echo "<script language='Javascript'>document.location='index.php?page=ipv6net";
3037 echo "&id=${record['id']}";
3038 echo "';//</script>";
3039 break;
ea5fc465 3040 case 'object':
1b4a0a6a 3041 if (isset ($record['by_port']) and 1 == count ($record['by_port']))
7e74a507
AA
3042 {
3043 $found_ports_ids = array_keys ($record['by_port']);
3044 $hl = '&hl_port_id=' . $found_ports_ids[0];
3045 }
1b4a0a6a
DO
3046 else
3047 $hl = '';
790a60e8 3048 echo "<script language='Javascript'>document.location='index.php?page=object&object_id=${record['id']}${hl}';//</script>";
ea5fc465 3049 break;
05411ccd 3050 case 'ipv4rspool':
790a60e8 3051 echo "<script language='Javascript'>document.location='index.php?page=ipv4rspool&pool_id=${record['id']}';//</script>";
05411ccd
DO
3052 break;
3053 case 'ipv4vs':
790a60e8 3054 echo "<script language='Javascript'>document.location='index.php?page=ipv4vs&vs_id=${record['id']}';//</script>";
05411ccd 3055 break;
6a88e734 3056 case 'user':
790a60e8 3057 echo "<script language='Javascript'>document.location='index.php?page=user&user_id=${record['user_id']}';//</script>";
6a88e734 3058 break;
e1ae3fb4 3059 case 'file':
790a60e8 3060 echo "<script language='Javascript'>document.location='index.php?page=file&file_id=${record['id']}';//</script>";
e1ae3fb4 3061 break;
e531b4d6 3062 case 'rack':
790a60e8 3063 echo "<script language='Javascript'>document.location='index.php?page=rack&rack_id=${record['id']}';//</script>";
e531b4d6 3064 break;
1f54e1ba
DO
3065 case 'vlan':
3066 echo "<script language='Javascript'>document.location='index.php?page=vlan&vlan_ck=${record}';//</script>";
3067 break;
fc359703
AA
3068 default:
3069 startPortlet($realm);
3070 echo $record;
3071 finishPortlet();
ea5fc465
DO
3072 }
3073 return;
3074 }
3075 else
3076 {
3077 global $nextorder;
3078 $order = 'odd';
3079 echo "<center><h2>${nhits} result(s) found for '${terms}'</h2></center>";
3080 foreach ($summary as $where => $what)
3081 switch ($where)
e673ee24 3082 {
ea5fc465 3083 case 'object':
790a60e8 3084 startPortlet ("<a href='index.php?page=depot'>Objects</a>");
323edbbf
DO
3085 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
3086 echo '<tr><th>what</th><th>why</th></tr>';
3087 foreach ($what as $obj)
3088 {
3089 echo "<tr class=row_${order} valign=top><td>";
9f75e165
DO
3090 $object = spotEntity ('object', $obj['id']);
3091 renderCell ($object);
b1f60545
DO
3092 echo "</td><td class=tdleft>";
3093 if (isset ($obj['by_attr']))
3094 {
3095 // only explain non-obvious reasons for listing
3096 echo '<ul>';
3097 foreach ($obj['by_attr'] as $attr_name)
3098 if ($attr_name != 'name')
3099 echo "<li>${attr_name} matched</li>";
3100 echo '</ul>';
3101 }
323edbbf
DO
3102 if (isset ($obj['by_sticker']))
3103 {
3104 echo '<table>';
3105 $aval = getAttrValues ($obj['id']);
3106 foreach ($obj['by_sticker'] as $attr_id)
3107 {
0794fb66 3108 $record = $aval[$attr_id];
323edbbf 3109 echo "<tr><th width='50%' class=sticker>${record['name']}:</th>";
8ad59489 3110 echo "<td class=sticker>" . formatAttributeValue ($record) . "</td></tr>";
323edbbf
DO
3111 }
3112 echo '</table>';
3113 }
d516d719 3114 if (isset ($obj['by_port']))
323edbbf
DO
3115 {
3116 echo '<table>';
9f75e165 3117 amplifyCell ($object);
1b4a0a6a 3118 foreach ($obj['by_port'] as $port_id => $text)
9f75e165 3119 foreach ($object['ports'] as $port)
323edbbf
DO
3120 if ($port['id'] == $port_id)
3121 {
521cd29a
AA
3122 $port_href = '<a href="' . makeHref (array
3123 (
3124 'page' => 'object',
3125 'object_id' => $object['id'],
3126 'hl_port_id' => $port_id
3127 )) . '">port ' . $port['name'] . '</a>';
3128 echo "<tr><td>${port_href}:</td>";
1b4a0a6a 3129 echo "<td class=tdleft>${text}</td></tr>";
323edbbf
DO
3130 break; // next reason
3131 }
3132 echo '</table>';
3133 }
5fd2a004
DO
3134 if (isset ($obj['by_iface']))
3135 {
3136 echo '<ul>';
3137 foreach ($obj['by_iface'] as $ifname)
3138 echo "<li>interface ${ifname}</li>";
3139 echo '</ul>';
3140 }
3141 if (isset ($obj['by_nat']))
3142 {
3143 echo '<ul>';
3144 foreach ($obj['by_nat'] as $comment)
3145 echo "<li>NAT rule: ${comment}</li>";
3146 echo '</ul>';
3147 }
6a4339ed
DO
3148 if (isset ($obj['by_cableid']))
3149 {
3150 echo '<ul>';
3151 foreach ($obj['by_cableid'] as $cableid)
3152 echo "<li>link cable ID: ${cableid}</li>";
3153 echo '</ul>';
3154 }
323edbbf
DO
3155 echo "</td></tr>";
3156 $order = $nextorder[$order];
ea5fc465
DO
3157 }
3158 echo '</table>';
3159 finishPortlet();
3160 break;
3161 case 'ipv4network':
790a60e8 3162 startPortlet ("<a href='index.php?page=ipv4space'>IPv4 networks</a>");
21ee3351
AA
3163 case 'ipv6network':
3164 if ($where == 'ipv6network')
3165 startPortlet ("<a href='index.php?page=ipv6space'>IPv6 networks</a>");
3166
ea5fc465 3167 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
6df2025d 3168 foreach ($what as $cell)
ea5fc465 3169 {
0b9c98d7 3170 echo "<tr class=row_${order} valign=top><td>";
6df2025d 3171 renderCell ($cell);
0b9c98d7 3172 echo "</td></tr>\n";
ea5fc465
DO
3173 $order = $nextorder[$order];
3174 }
3175 echo '</table>';
3176 finishPortlet();
3177 break;
f3d0cb20 3178 case 'ipv4addressbydescr':
ea5fc465
DO
3179 startPortlet ('IPv4 addresses');
3180 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
f3d0cb20 3181 // FIXME: address, parent network, routers (if extended view is enabled)
e1ae3fb4 3182 echo '<tr><th>Address</th><th>Description</th></tr>';
ea5fc465
DO
3183 foreach ($what as $addr)
3184 {
f3d0cb20 3185 echo "<tr class=row_${order}><td class=tdleft>";
4318ced5 3186 $fmt = ip4_format ($addr['ip']);
f3d0cb20
DO
3187 $parentnet = getIPv4AddressNetworkId ($addr['ip']);
3188 if ($parentnet !== NULL)
4318ced5 3189 echo "<a href='index.php?page=ipv4net&tab=default&id=${parentnet}&hl_ip=${fmt}'>${fmt}</a></td>";
f3d0cb20 3190 else
4318ced5 3191 echo "<a href='index.php?page=ipaddress&ip=${fmt}'>${fmt}</a></td>";
ea5fc465
DO
3192 echo "<td class=tdleft>${addr['name']}</td></tr>";
3193 $order = $nextorder[$order];
3194 }