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