r5039 bugfix: removed links to obsoleted pages ipv4vslist and ipv4rsplist
[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
DO
294 echo "<table class=objview border=0 width='100%'><tr><td class=pcleft>";
295 renderCellFilterPortlet ($cellfilter, 'rack', $found_racks);
489a7502 296 echo '</td><td class=pcright>';
1ebbf889
AA
297
298 if (! renderEmptyResults($cellfilter, 'racks', $rackCount))
e673ee24 299 {
1ebbf889
AA
300 echo '<table border=0 cellpadding=10 cellpadding=1>';
301 // generate thumb gallery
302 global $nextorder;
303 $rackwidth = getRackImageWidth();
304 // Zero value effectively disables the limit.
305 $maxPerRow = getConfigVar ('RACKS_PER_ROW');
306 $order = 'odd';
307 foreach ($rows as $row)
308 {
309 $row_id = $row['row_id'];
310 $row_name = $row['row_name'];
311 $rackList = $row['racks'];
312
313 if (!count ($rackList) and count ($cellfilter['expression']))
314 continue;
315 $rackListIdx = 0;
316 echo "<tr class=row_${order}><th class=tdleft>";
317 echo "<a href='".makeHref(array('page'=>'row', 'row_id'=>$row_id))."${cellfilter['urlextra']}'>";
318 echo "${row_name}</a></th><td><table border=0 cellspacing=5><tr>";
319 if (!count ($rackList))
320 echo "<td>(empty row)</td>";
321 else
322 foreach ($rackList as $rack)
48325652 323 {
1ebbf889
AA
324 if ($rackListIdx > 0 and $maxPerRow > 0 and $rackListIdx % $maxPerRow == 0)
325 {
326 echo '</tr></table></tr>';
327 echo "<tr class=row_${order}><th class=tdleft>${row_name} (continued)";
328 echo "</th><td><table border=0 cellspacing=5><tr>";
329 }
a3021995 330 echo "<td align=center valign=bottom><a href='".makeHref(array('page'=>'rack', 'rack_id'=>$rack['id']))."'>";
1ebbf889
AA
331 echo "<img border=0 width=${rackwidth} height=";
332 echo getRackImageHeight ($rack['height']);
333 echo " title='${rack['height']} units'";
4afb4c10 334 echo "src='?module=image&img=minirack&rack_id=${rack['id']}'>";
1ebbf889
AA
335 echo "<br>${rack['name']}</a></td>";
336 $rackListIdx++;
48325652 337 }
1ebbf889
AA
338 $order = $nextorder[$order];
339 echo "</tr></table></tr>\n";
340 }
341 echo "</table>\n";
e673ee24 342 }
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>';
81659c05 1820 echo '<tr><th>Common name</th><th>Visible label</th><th>Asset tag</th><th>Row/Rack</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
DO
1834 $places = array();
1835 if (! array_key_exists ($obj['id'], $mountinfo))
1836 $places[] = 'Unmounted';
4899096d 1837 else
3f8a25d6
DO
1838 foreach ($mountinfo[$obj['id']] as $mi)
1839 $places[] = mkA ($mi['row_name'], 'row', $mi['row_id']) . '/' . mkA ($mi['rack_name'], 'rack', $mi['rack_id']);
4318ced5 1840 echo "<td>" . implode (', ', $places) . '</td>';
4899096d
AD
1841 echo '</tr>';
1842 $order = $nextorder[$order];
1843 }
1844 echo '</table>';
1845 finishPortlet();
1ebbf889 1846 }
4899096d
AD
1847 else
1848 echo '<h2>No objects exist</h2>';
e673ee24 1849 }
23cdc7e9
DO
1850
1851 echo "</td><td class=pcright width='25%'>";
1852
95857b5c 1853 renderCellFilterPortlet ($cellfilter, 'object', $objects);
23cdc7e9 1854 echo "</td></tr></table>\n";
e673ee24
DO
1855}
1856
1ebbf889
AA
1857// This function returns TRUE if the result set is too big to be rendered, and no filter is set.
1858// In this case it renders the describing message instead.
1859function renderEmptyResults($cellfilter, $entities_name, $count = NULL)
1860{
1861 if (!$cellfilter['is_empty'])
1862 return FALSE;
1863 if (isset ($_REQUEST['show_all_objects']))
1864 return FALSE;
1865 $max = intval(getConfigVar('MAX_UNFILTERED_ENTITIES'));
1866 if (0 == $max || $count <= $max)
1867 return FALSE;
1868
1869 $href_show_all = trim($_SERVER['REQUEST_URI'], '&');
1870 $href_show_all .= htmlspecialchars('&show_all_objects=1');
1871 $suffix = isset ($count) ? " ($count)" : '';
1872 echo <<<END
1873<p>Please set a filter to display the corresponging $entities_name.
1874<br><a href="$href_show_all">Show all $entities_name$suffix</a>
1875END;
1876 return TRUE;
1877}
1878
e673ee24 1879// History viewer for history-enabled simple dictionaries.
9b8174d7 1880function renderObjectHistory ($object_id)
e673ee24 1881{
e673ee24
DO
1882 $order = 'odd';
1883 global $nextorder;
9b8174d7
AD
1884 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
1885 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>';
1886 $result = usePreparedSelectBlade
1887 (
1888 'SELECT ctime, user_name, name, label, asset_no, has_problems, comment FROM ObjectHistory WHERE id=? ORDER BY ctime',
1889 array ($object_id)
1890 );
e673ee24
DO
1891 while ($row = $result->fetch (PDO::FETCH_NUM))
1892 {
1893 echo "<tr class=row_${order}><td>${row[0]}</td>";
9b8174d7 1894 for ($i = 1; $i <= 6; $i++)
e673ee24
DO
1895 echo "<td>" . $row[$i] . "</td>";
1896 echo "</tr>\n";
1897 $order = $nextorder[$order];
1898 }
1899 echo "</table><br>\n";
1900}
1901
1902function renderRackspaceHistory ()
1903{
4fbb5a00 1904 global $nextorder, $pageno, $tabno;
e673ee24
DO
1905 $order = 'odd';
1906 $history = getRackspaceHistory();
1907 // Show the last operation by default.
1908 if (isset ($_REQUEST['op_id']))
1909 $op_id = $_REQUEST['op_id'];
1910 elseif (isset ($history[0]['mo_id']))
1911 $op_id = $history[0]['mo_id'];
1912 else $op_id = NULL;
1913
1914 $omid = NULL;
1915 $nmid = NULL;
1916 $object_id = 1;
1917 if ($op_id)
1918 list ($omid, $nmid) = getOperationMolecules ($op_id);
1919
1920 // Main layout starts.
1921 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
1922
1923 // Left top portlet with old allocation.
1924 echo "<tr><td class=pcleft>";
1925 startPortlet ('Old allocation');
1926 if ($omid)
1927 {
1928 $oldMolecule = getMolecule ($omid);
1929 renderMolecule ($oldMolecule, $object_id);
1930 }
1931 else
1932 echo "nothing";
1933 finishPortlet();
1934
1935 echo '</td><td class=pcright>';
1936
1937 // Right top portlet with new allocation
1938 startPortlet ('New allocation');
1939 if ($nmid)
1940 {
1941 $newMolecule = getMolecule ($nmid);
1942 renderMolecule ($newMolecule, $object_id);
1943 }
1944 else
1945 echo "nothing";
1946 finishPortlet();
737a3f72 1947
e673ee24 1948 echo '</td></tr><tr><td colspan=2>';
737a3f72 1949
e673ee24
DO
1950 // Bottom portlet with list
1951
1952 startPortlet ('Rackspace allocation history');
1953 echo "<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>\n";
7fa7047a 1954 echo "<tr><th>timestamp</th><th>author</th><th>object</th><th>comment</th></tr>\n";
e673ee24
DO
1955 foreach ($history as $row)
1956 {
1957 if ($row['mo_id'] == $op_id)
1958 $class = 'hl';
1959 else
1960 $class = "row_${order}";
4fbb5a00 1961 echo "<tr class=${class}><td><a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'op_id'=>$row['mo_id']))."'>${row['ctime']}</a></td>";
7fa7047a
DO
1962 echo "<td>${row['user_name']}</td><td>";
1963 renderCell (spotEntity ('object', $row['ro_id']));
9c6222ef 1964 echo '</td><td>' . niftyString ($row['comment'], 0) . '</td></tr>';
e673ee24
DO
1965 $order = $nextorder[$order];
1966 }
1967 echo "</table>\n";
1968 finishPortlet();
737a3f72 1969
e673ee24 1970 echo '</td></tr></table>';
e673ee24
DO
1971}
1972
4318ced5 1973function renderIPSpaceRecords ($tree, $baseurl, $target = 0, $level = 1)
d65353ad
DO
1974{
1975 $self = __FUNCTION__;
4318ced5 1976 $knight = (getConfigVar ('IPV4_ENABLE_KNIGHT') == 'yes');
00276508
AA
1977
1978 // scroll page to the highlighted item
1979 if ($target && isset ($_REQUEST['hl_net']))
65e557dd 1980 addAutoScrollScript ("net-$target");
00276508 1981
d65353ad
DO
1982 foreach ($tree as $item)
1983 {
4318ced5
AA
1984 if ($display_routers = (getConfigVar ('IPV4_TREE_RTR_AS_CELL') != 'none'))
1985 loadIPAddrList ($item); // necessary to compute router list and address counter
1986
0137d53c
DO
1987 if (isset ($item['id']))
1988 {
1f54e1ba 1989 $decor = array ('indent' => $level);
fec0c8da 1990 if ($item['symbol'] == 'node-collapsed')
4318ced5 1991 $decor['symbolurl'] = "${baseurl}&eid=${item['id']}&hl_net=1";
fec0c8da 1992 elseif ($item['symbol'] == 'node-expanded')
4318ced5
AA
1993 $decor['symbolurl'] = $baseurl . ($item['parent_id'] ? "&eid=${item['parent_id']}&hl_net=1" : '');
1994 $tr_class = '';
21ee3351 1995 if ($target == $item['id'] && isset ($_REQUEST['hl_net']))
64347dcf 1996 {
4318ced5
AA
1997 $decor['tdclass'] = ' port_highlight';
1998 $tr_class = $decor['tdclass'];
64347dcf 1999 }
4318ced5
AA
2000 echo "<tr valign=top class=\"$tr_class\">";
2001 printIPNetInfoTDs ($item, $decor);
2002
2003 // capacity and usage
2004 echo "<td class=tdcenter>";
2005 echo getRenderedIPNetCapacity ($item);
64347dcf 2006 echo "</td>";
4318ced5
AA
2007
2008 if ($display_routers)
4a47d34b 2009 printRoutersTD (findRouters ($item['addrlist']), getConfigVar ('IPV4_TREE_RTR_AS_CELL'));
0137d53c 2010 echo "</tr>";
fec0c8da 2011 if ($item['symbol'] == 'node-expanded' or $item['symbol'] == 'node-expanded-static')
4318ced5 2012 $self ($item['kids'], $baseurl, $target, $level + 1);
0137d53c
DO
2013 }
2014 else
2015 {
4318ced5 2016 // non-allocated (spare) IP range
0137d53c 2017 echo "<tr valign=top>";
21ee3351 2018 printIPNetInfoTDs ($item, array ('indent' => $level, 'knight' => $knight, 'tdclass' => 'sparenetwork'));
00276508 2019
4318ced5 2020 // capacity and usage
21ee3351 2021 echo "<td class=tdcenter>";
4318ced5 2022 echo getRenderedIPNetCapacity ($item);
21ee3351 2023 echo "</td>";
4318ced5
AA
2024 if ($display_routers)
2025 echo "<td></td>";
21ee3351 2026 echo "</tr>";
21ee3351 2027 }
21ee3351
AA
2028 }
2029}
2030
4318ced5 2031function renderIPSpace()
e673ee24 2032{
4fbb5a00 2033 global $pageno, $tabno;
4318ced5 2034 $realm = ($pageno == 'ipv4space' ? 'ipv4net' : 'ipv6net');
31c941ec 2035 $cellfilter = getCellFilter();
4318ced5
AA
2036 $top = NULL;
2037 $netlist = array();
2038 foreach (listCells ($realm) as $net)
2039 {
2040 if (isset ($top) and IPNetContains ($top, $net))
2041 ;
2042 elseif (! count ($cellfilter['expression']) or judgeCell ($net, $cellfilter['expression']))
2043 $top = $net;
1ebbf889 2044 else
4318ced5
AA
2045 continue;
2046 $netlist[$net['id']] = $net;
5388794d 2047 }
21ee3351
AA
2048 $netcount = count ($netlist);
2049 // expand request can take either natural values or "ALL". Zero means no expanding.
2050 $eid = isset ($_REQUEST['eid']) ? $_REQUEST['eid'] : 0;
4318ced5 2051 $tree = prepareIPTree ($netlist, $eid);
21ee3351
AA
2052
2053 echo "<table border=0 class=objectview>\n";
2054 echo "<tr><td class=pcleft>";
4318ced5 2055 if (! renderEmptyResults($cellfilter, 'IP nets', count($tree)))
21ee3351
AA
2056 {
2057 startPortlet ("networks (${netcount})");
2058 echo '<h4>';
4318ced5
AA
2059 $all = "<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'eid'=>'ALL')) .
2060 $cellfilter['urlextra'] . "'>expand&nbsp;all</a>";
2061 $none = "<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'eid'=>'NONE')) .
2062 $cellfilter['urlextra'] . "'>collapse&nbsp;all</a>";
2063 $auto = "<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno)) .
2064 $cellfilter['urlextra'] . "'>auto-collapse</a>";
2065
21ee3351 2066 if ($eid === 0)
4318ced5 2067 echo 'auto-collapsing at threshold ' . getConfigVar ('TREE_THRESHOLD') . " ($all / $none)";
21ee3351 2068 elseif ($eid === 'ALL')
4318ced5
AA
2069 echo "expanding all ($auto / $none)";
2070 elseif ($eid === 'NONE')
2071 echo "collapsing all ($all / $auto)";
21ee3351
AA
2072 else
2073 {
4318ced5
AA
2074 $netinfo = spotEntity ($realm, $eid);
2075 echo "expanding ${netinfo['ip']}/${netinfo['mask']} ($auto / $all / $none)";
21ee3351
AA
2076 }
2077 echo "</h4><table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2078 echo "<tr><th>prefix</th><th>name/tags</th><th>capacity</th>";
4318ced5 2079 if (getConfigVar ('IPV4_TREE_RTR_AS_CELL') != 'none')
21ee3351
AA
2080 echo "<th>routed by</th>";
2081 echo "</tr>\n";
2082 $baseurl = makeHref(array('page'=>$pageno, 'tab'=>$tabno)) . $cellfilter['urlextra'];
4318ced5 2083 renderIPSpaceRecords ($tree, $baseurl, $eid);
21ee3351
AA
2084 echo "</table>\n";
2085 finishPortlet();
2086 }
2087
2088 echo '</td><td class=pcright>';
4318ced5 2089 renderCellFilterPortlet ($cellfilter, 'ipv4net', $netlist);
21ee3351
AA
2090 echo "</td></tr></table>\n";
2091}
2092
4318ced5 2093function renderIPSpaceEditor()
21ee3351 2094{
4318ced5
AA
2095 global $pageno;
2096 $realm = ($pageno == 'ipv4space' ? 'ipv4net' : 'ipv6net');
2097 $net_page = $realm; // 'ipv4net', 'ipv6net'
2098 $addrspaceList = listCells ($realm);
93a49e5b
AA
2099 startPortlet ('Manage existing (' . count ($addrspaceList) . ')');
2100 if (count ($addrspaceList))
21ee3351 2101 {
21ee3351
AA
2102 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2103 echo "<tr><th>&nbsp;</th><th>prefix</th><th>name</th><th>capacity</th></tr>";
21ee3351
AA
2104 foreach ($addrspaceList as $netinfo)
2105 {
21ee3351 2106 echo "<tr valign=top><td>";
93a49e5b 2107 if (! isIPNetworkEmpty ($netinfo))
21ee3351
AA
2108 printImageHREF ('nodestroy', 'There are ' . count ($netinfo['addrlist']) . ' allocations inside');
2109 else
93a49e5b 2110 echo getOpLink (array ('op' => 'del', 'id' => $netinfo['id']), '', 'destroy', 'Delete this prefix');
4318ced5 2111 echo '</td><td class=tdleft><a href="' . makeHref (array ('page' => $net_page, 'id' => $netinfo['id'])) . '">';
ab1283b7 2112 echo "${netinfo['ip']}/${netinfo['mask']}</a></td>";
1f54e1ba
DO
2113 echo '<td class=tdleft>' . niftyString ($netinfo['name']);
2114 if (count ($netinfo['etags']))
2115 echo '<br><small>' . serializeTags ($netinfo['etags']) . '</small>';
2116 echo '</td><td>';
4318ced5 2117 echo getRenderedIPNetCapacity ($netinfo);
b1e39212 2118 echo '</tr>';
e673ee24 2119 }
04d619d0
DO
2120 echo "</table>";
2121 finishPortlet();
e673ee24 2122 }
93a49e5b
AA
2123}
2124
2125function renderIPNewNetForm ()
2126{
2127 global $pageno;
2128 if ($pageno == 'ipv6space')
2129 {
2130 $realm = 'ipv6net';
3495ec6e 2131 $regexp = '^[a-fA-F0-9:]*:[a-fA-F0-9:\.]*/\d{1,3}$';
93a49e5b
AA
2132 }
2133 else
2134 {
2135 $realm = 'ipv4net';
3495ec6e 2136 $regexp = '^(\d{1,3}\.){3}\d{1,3}/\d{1,2}$';
93a49e5b
AA
2137 }
2138
2139 // IP prefix validator
2140 addJs ('js/live_validation.js');
2141 $regexp = addslashes ($regexp);
2142 addJs (<<<END
2143$(document).ready(function () {
2144 document.add_new_range.range.setAttribute('match', '$regexp');
2145 Validate.init();
2146});
2147END
2148 , TRUE);
2149
2150 startPortlet ('Add new');
2151 echo '<table border=0 cellpadding=10 align=center>';
2152 // This form requires a name, so JavaScript validator can find it.
2153 // No printOpFormIntro() hence
2154 echo "<form method=post name='add_new_range' action='".makeHrefProcess()."'>\n";
2155 echo "<input type=hidden name=op value=add>\n";
2156 // tags column
2157 echo '<tr><td rowspan=5><h3>assign tags</h3>';
2158 renderNewEntityTags ($realm);
2159 echo '</td>';
2160 // inputs column
2161 $prefix_value = empty ($_REQUEST['set-prefix']) ? '' : $_REQUEST['set-prefix'];
2162 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>";
2163 echo '<tr><th class=tdright>VLAN</th><td class=tdleft>';
2164 echo getOptionTree ('vlan_ck', getAllVLANOptions(), array ('select_class' => 'vertical', 'tabindex' => 2)) . '</td></tr>';
2165 echo "<tr><th class=tdright>name</th><td class=tdleft><input type=text name='name' size='20' tabindex=3></td></tr>";
2166 echo '<tr><td class=tdright><input type=checkbox name="is_connected" tabindex=4></td><th class=tdleft>reserve subnet-router anycast address</th></tr>';
2167 echo "<tr><td colspan=2>";
2168 printImageHREF ('CREATE', 'Add a new network', TRUE, 5);
2169 echo '</td></tr>';
2170 echo "</form></table><br><br>\n";
2171 finishPortlet();
e673ee24
DO
2172}
2173
4318ced5 2174function getRenderedIPNetBacktrace ($range)
e673ee24 2175{
4318ced5
AA
2176 if (getConfigVar ('EXT_IPV4_VIEW') != 'yes')
2177 return array();
e673ee24 2178
4318ced5
AA
2179 $v = ($range['realm'] == 'ipv4net') ? 4 : 6;
2180 $space = "ipv${v}space"; // ipv4space, ipv6space
2181 $tag = "\$ip${v}netid_"; // $ip4netid_, $ip6netid_
2182
2183 $ret = array();
2184 // Build a backtrace from all parent networks.
2185 $clen = $range['mask'];
2186 $backtrace = array();
2187 $backtrace['&rarr;'] = $range;
2188 $key = '';
2189 while (NULL !== ($upperid = getIPAddressNetworkId ($range['ip_bin'], $clen)))
2190 {
2191 $upperinfo = spotEntity ($range['realm'], $upperid);
2192 $clen = $upperinfo['mask'];
2193 $key .= '&uarr;';
2194 $backtrace[$key] = $upperinfo;
2195 }
2196 foreach (array_reverse ($backtrace) as $arrow => $ainfo)
2197 {
2198 $link = '<a href="' . makeHref (array (
2199 'page' => $space,
2200 'tab' => 'default',
2201 'clear-cf' => '',
2202 'cfe' => '{' . $tag . $ainfo['id'] . '}',
2203 'hl_net' => 1,
2204 'eid' => $range['id'],
2205 )) . '" title="View IP tree with this net as root">' . $arrow . '</a>';
2206 $ret[] = array ($link, getOutputOf ('renderCell', $ainfo));
2207 }
2208 return $ret;
2209}
2210
2211function renderIPNetwork ($id)
2212{
2213 global $pageno;
2214 $realm = $pageno; // 'ipv4net', 'ipv6net'
2215 $range = spotEntity ($realm, $id);
2216 loadIPAddrList ($range);
2034d968 2217 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
99ab184f
DO
2218 echo "<tr><td colspan=2 align=center><h1>${range['ip']}/${range['mask']}</h1><h2>";
2219 echo htmlspecialchars ($range['name'], ENT_QUOTES, 'UTF-8') . "</h2></td></tr>\n";
2034d968
DO
2220
2221 echo "<tr><td class=pcleft width='50%'>";
646272be
AA
2222
2223 // render summary portlet
2224 $summary = array();
4318ced5
AA
2225 $summary['%% used'] = getRenderedIPNetCapacity ($range);
2226 $summary = array_merge ($summary, getRenderedIPNetBacktrace ($range));
2227 if ($realm == 'ipv4net')
001e61fa 2228 {
4318ced5
AA
2229 $summary[] = array ('Netmask:', ip4_format ($range['mask_bin']));
2230 $summary[] = array ('Netmask:', "0x" . strtoupper (implode ('', unpack ('H*', $range['mask_bin']))));
2231 $summary['Wildcard bits'] = ip4_format ( ~ $range['mask_bin']);
001e61fa 2232 }
646272be 2233
a5f9d1ca 2234 foreach ($range['8021q'] as $item)
cbf78395 2235 {
a5f9d1ca 2236 $vlaninfo = getVLANInfo ($item['domain_id'] . '-' . $item['vlan_id']);
646272be 2237 $summary[] = array ('VLAN:', '<a href="' . makeHref (array ('page' => 'vlan', 'vlan_ck' => $vlaninfo['vlan_ck'])) . '">' . formatVLANName ($vlaninfo, 'markup long') . '</a>');
cbf78395 2238 }
3a4f4023 2239 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes' and count ($routers = findRouters ($range['addrlist'])))
04d619d0 2240 {
646272be
AA
2241 $summary['Routed by'] = '';
2242 foreach ($routers as $rtr)
4318ced5 2243 $summary['Routed by'] .= getOutputOf ('renderRouterCell', $rtr['ip_bin'], $rtr['iface'], spotEntity ('object', $rtr['id']));
04d619d0 2244 }
646272be
AA
2245 $summary['tags'] = '';
2246 renderEntitySummary ($range, 'summary', $summary);
e1ae3fb4 2247
99ab184f
DO
2248 if (strlen ($range['comment']))
2249 {
2250 startPortlet ('Comment');
2251 echo '<div class=commentblock>' . string_insert_hrefs (htmlspecialchars ($range['comment'], ENT_QUOTES, 'UTF-8')) . '</div>';
2252 finishPortlet ();
2253 }
2254
4318ced5 2255 renderFilesPortlet ($realm, $id);
2034d968 2256 echo "</td>\n";
e673ee24 2257
2034d968
DO
2258 echo "<td class=pcright>";
2259 startPortlet ('details');
4318ced5
AA
2260 renderIPNetworkAddresses ($range);
2261 finishPortlet();
2262 echo "</td></tr></table>\n";
2263}
e673ee24 2264
4318ced5
AA
2265// Used solely by renderSeparator
2266function renderEmptyIPv6 ($ip_bin, $hl_ip)
2267{
2268 $class = 'tdleft';
2269 if ($ip_bin === $hl_ip)
2270 $class .= ' port_highlight';
2271 $fmt = ip6_format ($ip_bin);
2272 echo "<tr class='$class'><td><a class='ancor' name='ip-$fmt' href='" . makeHref (array ('page' => 'ipaddress', 'ip' => $fmt)) . "'>" . $fmt;
2273 echo "</a></td><td class='rsv-port'><span class='rsvtext'></span></td><td>&nbsp;</td></tr>\n";
2274}
2275
2276// Renders empty table line to shrink empty IPv6 address ranges.
2277// If the range consists of single address, renders the address instead of empty line.
2278// Renders address $hl_ip inside the range.
2279// Used solely by renderIPv6NetworkAddresses
2280function renderSeparator ($first, $last, $hl_ip)
2281{
2282 $self = __FUNCTION__;
2283 if (strcmp ($first, $last) > 0)
2284 return;
2285 if ($first == $last)
2286 renderEmptyIPv6 ($first, $hl_ip);
2287 elseif (isset ($hl_ip) && strcmp ($hl_ip, $first) >= 0 && strcmp ($hl_ip, $last) <= 0)
2288 { // $hl_ip is inside the range $first - $last
2289 $self ($first, ip_prev ($hl_ip), $hl_ip);
2290 renderEmptyIPv6 ($hl_ip, $hl_ip);
2291 $self (ip_next ($hl_ip), $last, $hl_ip);
2292 }
2293 else
2294 echo "<tr><td colspan=3 class=tdleft></td></tr>\n";
2295}
2296
2297// calculates page number which contains given $ip (used by renderIPv6NetworkAddresses)
2298function getPageNumOfIPv6 ($list, $ip_bin, $maxperpage)
2299{
2300 if (intval ($maxperpage) <= 0 || count ($list) <= $maxperpage)
2301 return 0;
2302 $keys = array_keys ($list);
2303 for ($i = 1; $i <= count ($keys); $i++)
2304 if (strcmp ($keys[$i-1], $ip_bin) >= 0)
2305 return intval ($i / $maxperpage);
2306 return intval (count ($list) / $maxperpage);
2307}
2308
2309function renderIPNetworkAddresses ($range)
2310{
2311 switch (strlen ($range['ip_bin']))
2312 {
2313 case 4: return renderIPv4NetworkAddresses ($range);
2314 case 16: return renderIPv6NetworkAddresses ($range);
2315 default: throw new InvalidArgException ("range['ip_bin']", $range['ip_bin']);
2316 }
2317}
2318
2319function renderIPv4NetworkAddresses ($range)
2320{
2321 global $pageno, $tabno, $aac2;
2322 $startip = ip4_bin2int ($range['ip_bin']);
2323 $endip = ip4_bin2int (ip_last ($range));
2324
2325 if (isset ($_REQUEST['hl_ip']))
00276508 2326 {
4318ced5
AA
2327 $hl_ip = ip4_bin2int (ip4_parse ($_REQUEST['hl_ip']));
2328 addAutoScrollScript ('ip-' . $_REQUEST['hl_ip']); // scroll page to highlighted ip
00276508
AA
2329 }
2330
79b57b18
AA
2331 // pager
2332 $maxperpage = getConfigVar ('IPV4_ADDRS_PER_PAGE');
2333 $address_count = $endip - $startip + 1;
2334 $page = 0;
446c25c3 2335 $rendered_pager = '';
79b57b18
AA
2336 if ($address_count > $maxperpage && $maxperpage > 0)
2337 {
2338 $page = isset ($_REQUEST['pg']) ? $_REQUEST['pg'] : (isset ($hl_ip) ? intval (($hl_ip - $startip) / $maxperpage) : 0);
2339 if ($numpages = ceil ($address_count / $maxperpage))
2340 {
4318ced5 2341 echo '<h3>' . ip4_format (ip4_int2bin ($startip)) . ' ~ ' . ip4_format (ip4_int2bin ($endip)) . '</h3>';
79b57b18
AA
2342 for ($i = 0; $i < $numpages; $i++)
2343 if ($i == $page)
446c25c3 2344 $rendered_pager .= "<b>$i</b> ";
79b57b18 2345 else
4318ced5 2346 $rendered_pager .= "<a href='".makeHref (array ('page' => $pageno, 'tab' => $tabno, 'id' => $range['id'], 'pg' => $i)) . "'>$i</a> ";
79b57b18
AA
2347 }
2348 $startip = $startip + $page * $maxperpage;
2349 $endip = min ($startip + $maxperpage - 1, $endip);
2350 }
2351
446c25c3 2352 echo $rendered_pager;
beb9e88a 2353 echo "<table class='widetable' border=0 cellspacing=0 cellpadding=5 align='center' width='100%'>\n";
e673ee24
DO
2354 echo "<tr><th>Address</th><th>Name</th><th>Allocation</th></tr>\n";
2355
4318ced5
AA
2356 markupIPAddrList ($range['addrlist']);
2357 for ($ip = $startip; $ip <= $endip; $ip++)
2358 {
2359 $ip_bin = ip4_int2bin ($ip);
2360 $dottedquad = ip4_format ($ip_bin);
2361 $tr_class = (isset ($hl_ip) && $hl_ip == $ip ? 'port_highlight' : '');
2362 if (!isset ($range['addrlist'][$ip_bin]))
e673ee24 2363 {
4318ced5
AA
2364 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>";
2365 echo "<td class='rsv-port'><span class='rsvtext'></span></td><td>&nbsp;</td></tr>\n";
b2035dca
DO
2366 continue;
2367 }
4318ced5 2368 $addr = $range['addrlist'][$ip_bin];
68c91b9c
AA
2369 // render IP change history
2370 $title = '';
2371 $history_class = '';
2372 if (isset ($addr['last_log']))
2373 {
2374 $title = ' title="' . htmlspecialchars ($addr['last_log']['user'] . ', ' . formatAge ($addr['last_log']['time']) , ENT_QUOTES) . '"';
2375 $history_class = 'hover-history underline';
2376 }
4318ced5
AA
2377 $tr_class .= ' ' . $addr['class'];
2378 echo "<tr class='tdleft $tr_class'>";
2379 echo "<td><a class='ancor $history_class' $title name='ip-$dottedquad' href='".makeHref(array('page'=>'ipaddress', 'ip'=>$addr['ip']))."'>${addr['ip']}</a></td>";
2380 echo "<td class='" .
a8dc2982 2381 (empty ($addr['allocs']) || !empty ($addr['name']) ? 'rsv-port' : '') .
4318ced5 2382 "'><span class='rsvtext'>${addr['name']}</span></td><td>";
b2035dca 2383 $delim = '';
b2035dca
DO
2384 if ( $addr['reserved'] == 'yes')
2385 {
2d318652 2386 echo "<strong>RESERVED</strong> ";
b2035dca
DO
2387 $delim = '; ';
2388 }
212b565a 2389 foreach ($addr['allocs'] as $ref)
b2035dca 2390 {
beb9e88a 2391 echo $delim . $aac2[$ref['type']];
4318ced5 2392 echo "<a href='".makeHref(array('page'=>'object', 'object_id'=>$ref['object_id'], 'tab' => 'default', 'hl_ip'=>$addr['ip']))."'>";
59a83bd8 2393 echo $ref['name'] . (!strlen ($ref['name']) ? '' : '@');
b2035dca
DO
2394 echo "${ref['object_name']}</a>";
2395 $delim = '; ';
2396 }
2397 if ($delim != '')
e0d6e38e 2398 $delim = '<br>';
212b565a
AA
2399 foreach ($addr['vslist'] as $vs_id)
2400 {
2401 $vs = spotEntity ('ipv4vs', $vs_id);
2402 echo "${delim}<a href='".makeHref(array('page'=>'ipv4vs', 'vs_id'=>$vs['id']))."'>";
2403 echo "${vs['name']}:${vs['vport']}/${vs['proto']}</a>&rarr;";
2404 $delim = '<br>';
2405 }
2406 foreach ($addr['rsplist'] as $rsp_id)
2407 {
2408 $rsp = spotEntity ('ipv4rspool', $rsp_id);
2409 echo "${delim}&rarr;<a href='".makeHref(array('page'=>'ipv4rspool', 'pool_id'=>$rsp['id']))."'>";
2410 echo "${rsp['name']}</a>";
2411 $delim = '<br>';
2412 }
b2035dca 2413 echo "</td></tr>\n";
4318ced5 2414 }
2727c7df 2415 // end of iteration
a8dc2982
AA
2416 if (permitted (NULL, NULL, 'set_reserve_comment'))
2417 addJS ('js/inplace-edit.js');
e673ee24
DO
2418
2419 echo "</table>";
446c25c3
AA
2420 if (! empty ($rendered_pager))
2421 echo '<p>' . $rendered_pager . '</p>';
21ee3351
AA
2422}
2423
2424function renderIPv6NetworkAddresses ($netinfo)
2425{
2426 global $pageno, $tabno, $aac2;
2427 echo "<table class='widetable' border=0 cellspacing=0 cellpadding=5 align='center' width='100%'>\n";
2428 echo "<tr><th>Address</th><th>Name</th><th>Allocation</th></tr>\n";
2429
4318ced5
AA
2430 $hl_ip = NULL;
2431 if (isset ($_REQUEST['hl_ip']))
2432 {
2433 $hl_ip = ip6_parse ($_REQUEST['hl_ip']);
2434 addAutoScrollScript ('ip-' . ip6_format ($hl_ip));
2435 }
21ee3351 2436
21ee3351
AA
2437 $addresses = $netinfo['addrlist'];
2438 ksort ($addresses);
4318ced5 2439 markupIPAddrList ($addresses);
21ee3351
AA
2440
2441 // pager
2442 $maxperpage = getConfigVar ('IPV4_ADDRS_PER_PAGE');
2443 if (count ($addresses) > $maxperpage && $maxperpage > 0)
2444 {
2445 $page = isset ($_REQUEST['pg']) ? $_REQUEST['pg'] : (isset ($hl_ip) ? getPageNumOfIPv6 ($addresses, $hl_ip, $maxperpage) : 0);
2446 $numpages = ceil (count ($addresses) / $maxperpage);
2447 echo "<center><h3>$numpages pages:</h3>";
2448 for ($i=0; $i<$numpages; $i++)
2449 {
2450 if ($i == $page)
2451 echo "<b>$i</b> ";
2452 else
2453 echo "<a href='" . makeHref (array ('page' => $pageno, 'tab' => $tabno, 'id' => $netinfo['id'], 'pg' => $i)) . "'>$i</a> ";
2454 }
2455 echo "</center>";
2456 }
2457
2458 $i = 0;
2459 $interruped = FALSE;
4318ced5
AA
2460 $prev_ip = ip_prev ($netinfo['ip_bin']);
2461 foreach ($addresses as $ip_bin => $addr)
21ee3351
AA
2462 {
2463 if (isset ($page))
2464 {
2465 ++$i;
2466 if ($i <= $maxperpage * $page)
2467 continue;
2468 elseif ($i > $maxperpage * ($page + 1))
2469 {
2470 $interruped = TRUE;
2471 break;
2472 }
2473 }
2474
4318ced5
AA
2475 if ($ip_bin != ip_next ($prev_ip))
2476 renderSeparator (ip_next ($prev_ip), ip_prev ($ip_bin), $hl_ip);
2477 $prev_ip = $ip_bin;
2478
2479 // render IP change history
2480 $title = '';
2481 $history_class = '';
2482 if (isset ($addr['last_log']))
2483 {
2484 $title = ' title="' . htmlspecialchars ($addr['last_log']['user'] . ', ' . formatAge ($addr['last_log']['time']) , ENT_QUOTES) . '"';
2485 $history_class = 'hover-history underline';
2486 }
2487
2488 $tr_class = $addr['class'] . ' tdleft' . ($hl_ip === $ip_bin ? ' port_highlight' : '');
2489 echo "<tr class='$tr_class'>";
2490 echo "<td><a class='ancor $history_class' $title name='ip-${addr['ip']}' href='" . makeHref (array ('page' => 'ipaddress', 'ip' => $addr['ip'])) . "'>${addr['ip']}</a></td>";
2491 echo "<td class='" .
a8dc2982 2492 (empty ($addr['allocs']) || !empty ($addr['name']) ? 'rsv-port' : '') .
4318ced5 2493 "'><span class='rsvtext'>${addr['name']}</span></td><td>";
21ee3351 2494 $delim = '';
21ee3351
AA
2495 if ( $addr['reserved'] == 'yes')
2496 {
2497 echo "<strong>RESERVED</strong> ";
2498 $delim = '; ';
2499 }
2500 foreach ($addr['allocs'] as $ref)
2501 {
2502 echo $delim . $aac2[$ref['type']];
71066ef1 2503 echo "<a href='".makeHref(array('page'=>'object', 'object_id'=>$ref['object_id'], 'tab' => 'default', 'hl_ip'=>$addr['ip']))."'>";
21ee3351
AA
2504 echo $ref['name'] . (!strlen ($ref['name']) ? '' : '@');
2505 echo "${ref['object_name']}</a>";
2506 $delim = '; ';
2507 }
2508 if ($delim != '')
71066ef1
AA
2509 $delim = '<br>';
2510 foreach ($addr['vslist'] as $vs_id)
2511 {
2512 $vs = spotEntity ('ipv4vs', $vs_id);
2513 echo "${delim}<a href='".makeHref(array('page'=>'ipv4vs', 'vs_id'=>$vs['id']))."'>";
2514 echo "${vs['name']}:${vs['vport']}/${vs['proto']}</a>&rarr;";
2515 $delim = '<br>';
2516 }
2517 foreach ($addr['rsplist'] as $rsp_id)
21ee3351 2518 {
71066ef1
AA
2519 $rsp = spotEntity ('ipv4rspool', $rsp_id);
2520 echo "${delim}&rarr;<a href='".makeHref(array('page'=>'ipv4rspool', 'pool_id'=>$rsp['id']))."'>";
2521 echo "${rsp['name']}</a>";
2522 $delim = '<br>';
21ee3351
AA
2523 }
2524 echo "</td></tr>\n";
2525 }
2526 if (! $interruped)
4318ced5 2527 renderSeparator (ip_next ($prev_ip), ip_last ($netinfo), $hl_ip);
21ee3351
AA
2528 if (isset ($page))
2529 { // bottom pager
2530 echo "<tr><td colspan=3>";
2531 if ($page > 0)
2532 echo "<a href='" . makeHref (array ('page' => $pageno, 'tab' => $tabno, 'id' => $netinfo['id'], 'pg' => $page - 1)) . "'><< prev</a> ";
2533 if ($page < $numpages - 1)
2534 echo "<a href='" . makeHref (array ('page' => $pageno, 'tab' => $tabno, 'id' => $netinfo['id'], 'pg' => $page + 1)) . "'>next >></a> ";
2535 echo "</td></tr>";
2536 }
2537 echo "</table>";
a8dc2982
AA
2538 if (permitted (NULL, NULL, 'set_reserve_comment'))
2539 addJS ('js/inplace-edit.js');
21ee3351
AA
2540}
2541
2542function renderIPNetworkProperties ($id)
e673ee24 2543{
21ee3351
AA
2544 global $pageno;
2545 $netdata = spotEntity ($pageno, $id);
53ef3908 2546 echo "<center><h1>${netdata['ip']}/${netdata['mask']}</h1></center>\n";
e673ee24 2547 echo "<table border=0 cellpadding=10 cellpadding=1 align='center'>\n";
7056988c 2548 printOpFormIntro ('editRange');
99ab184f
DO
2549 echo '<tr><td class=tdright><label for=nameinput>Name:</label></td>';
2550 echo "<td class=tdleft><input type=text name=name id=nameinput size=80 maxlength=255 value='";
2551 echo htmlspecialchars ($netdata['name'], ENT_QUOTES, 'UTF-8') . "'></tr>";
2552 echo '<tr><td class=tdright><label for=commentinput>Comment:</label></td>';
2553 echo "<td class=tdleft><textarea name=comment id=commentinput cols=80 rows=25>\n";
2554 echo htmlspecialchars ($netdata['comment'], ENT_QUOTES, 'UTF-8') . "</textarea></tr>";
53ef3908
DO
2555 echo "<tr><td colspan=2 class=tdcenter>";
2556 printImageHREF ('SAVE', 'Save changes', TRUE);
2557 echo "</td></form></tr></table>\n";
93a49e5b
AA
2558
2559 echo '<center>';
2560 if (! isIPNetworkEmpty ($netdata))
2561 echo getOpLink (NULL, 'delete this prefix', 'nodestroy', 'There are ' . count ($netdata['addrlist']) . ' allocations inside');
2562 else
2563 echo getOpLink (array('op'=>'del','id'=>$id), 'delete this prefix', 'destroy');
2564 echo '</center>';
e673ee24
DO
2565}
2566
4318ced5 2567function renderIPAddress ($ip)
e673ee24 2568{
46098972 2569 global $aat, $nextorder;
4318ced5 2570 $address = getIPAddress (ip_parse ($ip));
68225375 2571 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
21ee3351 2572 echo "<tr><td colspan=2 align=center><h1>${address['ip']}</h1></td></tr>\n";
e673ee24 2573
68225375 2574 echo "<tr><td class=pcleft>";
defd92d8
AA
2575
2576 $summary = array();
423c4216 2577 if (strlen ($address['name']))
defd92d8
AA
2578 $summary['Comment'] = $address['name'];
2579 $summary['Reserved'] = $address['reserved'];
2580 $summary['Allocations'] = count ($address['allocs']);
4318ced5 2581 if (isset ($address['outpf']))
defd92d8 2582 $summary['Originated NAT connections'] = count ($address['outpf']);
4318ced5 2583 if (isset ($address['inpf']))
defd92d8 2584 $summary['Arriving NAT connections'] = count ($address['inpf']);
defd92d8 2585 renderEntitySummary ($address, 'summary', $summary);
212b565a
AA
2586
2587 // render SLB portlet
4318ced5 2588 if (! empty ($address['vslist']) or ! empty ($address['rsplist']))
212b565a
AA
2589 {
2590 startPortlet ("");
2591 if (! empty ($address['vslist']))
2592 {
2593 printf ("<h2>virtual services (%d):</h2>", count ($address['vslist']));
2594 foreach ($address['vslist'] as $vs_id)
2595 renderSLBEntityCell (spotEntity ('ipv4vs', $vs_id));
2596 }
2597
2598 if (! empty ($address['rsplist']))
2599 {
2600 printf ("<h2>RS pools (%d):</h2>", count ($address['rsplist']));
2601 foreach ($address['rsplist'] as $rsp_id)
2602 renderSLBEntityCell (spotEntity ('ipv4rspool', $rsp_id));
2603 }
2604 finishPortlet();
2605 }
68225375 2606 echo "</td>\n";
e673ee24 2607
68225375 2608 echo "<td class=pcright>";
defd92d8 2609 if (isset ($address['class']) and ! empty ($address['allocs']))
59bebe2b 2610 {
8e700dd1 2611 startPortlet ('allocations');
2d318652
DO
2612 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2613 echo "<tr><th>object</th><th>OS interface</th><th>allocation type</th></tr>\n";
2d318652 2614 // render all allocation records for this address the same way
2d318652 2615 foreach ($address['allocs'] as $bond)
59bebe2b 2616 {
4318ced5 2617 $tr_class = "${address['class']} tdleft";
8e700dd1 2618 if (isset ($_REQUEST['hl_object_id']) and $_REQUEST['hl_object_id'] == $bond['object_id'])
4318ced5
AA
2619 $tr_class .= ' port_highlight';
2620 echo "<tr class='$tr_class'>" .
2621 "<td><a href='" . makeHref (array ('page' => 'object', 'object_id' => $bond['object_id'], 'tab' => 'default', 'hl_ip' => $address['ip'])) . "'>${bond['object_name']}</td>" .
2622 "<td>${bond['name']}</td>" .
2623 "<td><strong>" . $aat[$bond['type']] . "</strong></td>" .
2624 "</tr>\n";
59bebe2b
DO
2625 }
2626 echo "</table><br><br>";
2627 finishPortlet();
2628 }
e673ee24 2629
4318ced5 2630 if (! empty ($address['vslist']) or ! empty ($address['rsplist']))
defd92d8 2631 renderSLBTriplets ($address);
5fe1ed76 2632
21ee3351 2633 if (! empty ($address['outpf']))
68225375 2634 {
105a3bc8 2635 startPortlet ('departing NAT rules');
2d318652 2636 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
105a3bc8
DO
2637 echo "<tr><th>proto</th><th>from</th><th>to</th><th>comment</th></tr>\n";
2638 foreach ($address['outpf'] as $rule)
b62ff880 2639 echo "<tr><td>${rule['proto']}</td><td>${rule['localip']}:${rule['localport']}</td><td>${rule['remoteip']}:${rule['remoteport']}</td><td>${rule['description']}</td></tr>";
105a3bc8 2640 echo "</table>";
68225375
DO
2641 finishPortlet();
2642 }
105a3bc8 2643
21ee3351 2644 if (! empty ($address['inpf']))
105a3bc8
DO
2645 {
2646 startPortlet ('arriving NAT rules');
2d318652 2647 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
105a3bc8
DO
2648 echo "<tr><th>proto</th><th>from</th><th>to</th><th>comment</th></tr>\n";
2649 foreach ($address['inpf'] as $rule)
b62ff880 2650 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
2651 echo "</table>";
2652 finishPortlet();
2653 }
2654
68225375
DO
2655 echo "</td></tr>";
2656 echo "</table>\n";
e673ee24
DO
2657}
2658
4318ced5 2659function renderIPAddressProperties ($ip)
e673ee24 2660{
4318ced5 2661 $address = getIPAddress (ip_parse ($ip));
21ee3351 2662 echo "<center><h1>${address['ip']}</h1></center>\n";
7056988c 2663
1fbc9fd6 2664 startPortlet ('update');
e673ee24 2665 echo "<table border=0 cellpadding=10 cellpadding=1 align='center'>\n";
7056988c 2666 printOpFormIntro ('editAddress');
2d318652
DO
2667 echo "<tr><td class='tdright'>Name:</td><td class='tdleft'><input type=text name=name size=20 value='${address['name']}'></tr>";
2668 echo "<td class='tdright'>Reserved:</td><td class='tdleft'><input type=checkbox name=reserved size=20 ";
2669 echo ($address['reserved']=='yes') ? 'checked' : '';
f3d274bf 2670 echo "></tr><tr><td class=tdleft>";
53ef3908 2671 printImageHREF ('SAVE', 'Save changes', TRUE);
f3d274bf 2672 echo "</td></form><td class=tdright>";
59a83bd8 2673 if (!strlen ($address['name']) and $address['reserved'] == 'no')
f3d274bf
DO
2674 printImageHREF ('CLEAR gray');
2675 else
2676 {
2677 printOpFormIntro ('editAddress', array ('name' => '', 'reserved' => ''));
2678 printImageHREF ('CLEAR', 'Release', TRUE);
2679 echo "</form>";
2680 }
2681 echo "</td></tr></table>\n";
1fbc9fd6 2682 finishPortlet();
e673ee24
DO
2683}
2684
4318ced5 2685function renderIPAddressAllocations ($ip)
e673ee24 2686{
4318ced5 2687 function printNewItemTR ()
39b4abd0
DO
2688 {
2689 global $aat;
4318ced5 2690 printOpFormIntro ('add');
39b4abd0 2691 echo "<tr><td>";
9318d2ef 2692 printImageHREF ('add', 'allocate', TRUE);
8d4f7d18 2693 echo "</td><td>";
31babb65 2694 printSelect (getNarrowObjectList ('IPV4OBJ_LISTSRC'), array ('name' => 'object_id', 'tabindex' => 100));
8d4f7d18 2695 echo "</td><td><input type=text tabindex=101 name=bond_name size=10></td><td>";
01abf1de 2696 printSelect ($aat, array ('name' => 'bond_type', 'tabindex' => 102, 'regular'));
9318d2ef 2697 echo "</td><td>";
f5ff50f5 2698 printImageHREF ('add', 'allocate', TRUE, 103);
9318d2ef 2699 echo "</td></form></tr>";
39b4abd0 2700 }
b82cce3f 2701 global $aat;
e673ee24 2702
4318ced5 2703 $address = getIPAddress (ip_parse ($ip));
21ee3351 2704 echo "<center><h1>${address['ip']}</h1></center>\n";
105a3bc8 2705 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
2d318652 2706 echo "<tr><th>&nbsp;</th><th>object</th><th>OS interface</th><th>allocation type</th><th>&nbsp;</th></tr>\n";
e673ee24 2707
39b4abd0 2708 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
4318ced5 2709 printNewItemTR();
f74d96c6 2710 if (isset ($address['class']))
e673ee24 2711 {
f74d96c6
DO
2712 $class = $address['class'];
2713 if ($address['reserved'] == 'yes')
2714 echo "<tr class='${class}'><td colspan=3>&nbsp;</td><td class=tdleft><strong>RESERVED</strong></td><td>&nbsp;</td></tr>";
2715 foreach ($address['allocs'] as $bond)
2716 {
2717 echo "<tr class='$class'>";
4318ced5 2718 printOpFormIntro ('upd', array ('object_id' => $bond['object_id']));
21ee3351
AA
2719 echo "<td><a href='"
2720 . makeHrefProcess
2721 (
2722 array
2723 (
4318ced5 2724 'op' => 'del',
21ee3351
AA
2725 'ip' => $address['ip'],
2726 'object_id' => $bond['object_id']
2727 )
2728 )
2729 . "'>";
f74d96c6
DO
2730 printImageHREF ('delete', 'Unallocate address');
2731 echo "</a></td>";
4318ced5 2732 echo "<td><a href='" . makeHref (array ('page' => 'object', 'object_id' => $bond['object_id'], 'hl_ip' => $address['ip'])) . "'>${bond['object_name']}</td>";
f74d96c6 2733 echo "<td><input type='text' name='bond_name' value='${bond['name']}' size=10></td><td>";
cd3775e9 2734 printSelect ($aat, array ('name' => 'bond_type'), $bond['type']);
f74d96c6
DO
2735 echo "</td><td>";
2736 printImageHREF ('save', 'Save changes', TRUE);
2737 echo "</td></form></tr>\n";
2738 }
e673ee24 2739 }
39b4abd0 2740 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
4318ced5 2741 printNewItemTR();
e673ee24 2742 echo "</table><br><br>";
e673ee24
DO
2743}
2744
7e1db771 2745function renderNATv4ForObject ($object_id)
e673ee24 2746{
9318d2ef
DO
2747 function printNewItemTR ($alloclist)
2748 {
9318d2ef
DO
2749 printOpFormIntro ('addNATv4Rule');
2750 echo "<tr align='center'><td>";
2751 printImageHREF ('add', 'Add new NAT rule', TRUE);
2752 echo '</td><td>';
cd3775e9 2753 printSelect (array ('TCP' => 'TCP', 'UDP' => 'UDP'), array ('name' => 'proto'));
9318d2ef
DO
2754 echo "<select name='localip' tabindex=1>";
2755
4318ced5 2756 foreach ($alloclist as $ip_bin => $alloc)
9318d2ef 2757 {
4318ced5 2758 $ip = $alloc['addrinfo']['ip'];
43eb71f1
DO
2759 $name = (!isset ($alloc['addrinfo']['name']) or !strlen ($alloc['addrinfo']['name'])) ? '' : (' (' . niftyString ($alloc['addrinfo']['name']) . ')');
2760 $osif = (!isset ($alloc['osif']) or !strlen ($alloc['osif'])) ? '' : ($alloc['osif'] . ': ');
4318ced5 2761 echo "<option value='${ip}'>${osif}${ip}${name}</option>";
9318d2ef
DO
2762 }
2763
2764 echo "</select>:<input type='text' name='localport' size='4' tabindex=2></td>";
2765 echo "<td><input type='text' name='remoteip' id='remoteip' size='10' tabindex=3>";
39106006
DO
2766 echo "<a href='javascript:;' onclick='window.open(\"" . makeHrefForHelper ('inet4list');
2767 echo "\", \"findobjectip\", \"height=700, width=400, location=no, menubar=no, resizable=yes, scrollbars=no, status=no, titlebar=no, toolbar=no\");'>";
9318d2ef
DO
2768 printImageHREF ('find', 'Find object');
2769 echo "</a>";
2770 echo ":<input type='text' name='remoteport' size='4' tabindex=4></td><td></td>";
2771 echo "<td colspan=1><input type='text' name='description' size='20' tabindex=5></td><td>";
f5ff50f5 2772 printImageHREF ('add', 'Add new NAT rule', TRUE, 6);
9318d2ef
DO
2773 echo "</td></tr></form>";
2774 }
e673ee24 2775
94fe6370
DO
2776 $focus = spotEntity ('object', $object_id);
2777 amplifyCell ($focus);
f28fbe8b 2778 echo "<center><h2>locally performed NAT</h2></center>";
e673ee24 2779
105a3bc8 2780 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
d54b9495 2781 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 2782
9318d2ef 2783 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
94fe6370
DO
2784 printNewItemTR ($focus['ipv4']);
2785 foreach ($focus['nat4']['out'] as $pf)
e673ee24 2786 {
2c817354
DO
2787 $class = 'trerror';
2788 $osif = '';
4318ced5
AA
2789 $localip_bin = ip4_parse ($pf['localip']);
2790 if (isset ($focus['ipv4'][$localip_bin]))
2c817354 2791 {
4318ced5
AA
2792 $class = $focus['ipv4'][$localip_bin]['addrinfo']['class'];
2793 $osif = $focus['ipv4'][$localip_bin]['osif'] . ': ';
2c817354 2794 }
e673ee24
DO
2795
2796 echo "<tr class='$class'>";
4fbb5a00
DY
2797 echo "<td><a href='".
2798 makeHrefProcess(array(
2799 'op'=>'delNATv4Rule',
2800 'localip'=>$pf['localip'],
2801 'localport'=>$pf['localport'],
2802 'remoteip'=>$pf['remoteip'],
2803 'remoteport'=>$pf['remoteport'],
2804 'proto'=>$pf['proto'],
2805 'object_id'=>$object_id)).
2806 "'>";
4de22e7e
DO
2807 printImageHREF ('delete', 'Delete NAT rule');
2808 echo "</a></td>";
4fbb5a00 2809 echo "<td>${pf['proto']}/${osif}<a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['localip']))."'>${pf['localip']}</a>:${pf['localport']}";
59a83bd8 2810 if (strlen ($pf['local_addr_name']))
f28fbe8b
DO
2811 echo ' (' . $pf['local_addr_name'] . ')';
2812 echo "</td>";
4fbb5a00 2813 echo "<td><a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['remoteip']))."'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
e673ee24 2814
4318ced5 2815 $address = getIPAddress (ip4_parse ($pf['remoteip']));
e673ee24
DO
2816
2817 echo "<td class='description'>";
53ef3908
DO
2818 if (count ($address['allocs']))
2819 foreach ($address['allocs'] as $bond)
4fbb5a00 2820 echo "<a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$bond['object_id']))."'>${bond['object_name']}(${bond['name']})</a> ";
59a83bd8 2821 elseif (strlen ($pf['remote_addr_name']))
f28fbe8b 2822 echo '(' . $pf['remote_addr_name'] . ')';
7056988c
DO
2823 printOpFormIntro
2824 (
2825 'updNATv4Rule',
2826 array
2827 (
2828 'localip' => $pf['localip'],
2829 'localport' => $pf['localport'],
2830 'remoteip' => $pf['remoteip'],
2831 'remoteport' => $pf['remoteport'],
2832 'proto' => $pf['proto']
2833 )
2834 );
2835 echo "</td><td class='description'>";
d54b9495
DO
2836 echo "<input type='text' name='description' value='${pf['description']}'></td><td>";
2837 printImageHREF ('save', 'Save changes', TRUE);
2838 echo "</td></form></tr>";
e673ee24 2839 }
9318d2ef 2840 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
94fe6370 2841 printNewItemTR ($focus['ipv4']);
e673ee24
DO
2842
2843 echo "</table><br><br>";
94fe6370
DO
2844 if (!count ($focus['nat4']))
2845 return;
e673ee24 2846
f28fbe8b 2847 echo "<center><h2>arriving NAT connections</h2></center>";
105a3bc8 2848 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
e673ee24
DO
2849 echo "<tr><th></th><th>Source</th><th>Source objects</th><th>Target</th><th>Description</th></tr>\n";
2850
94fe6370 2851 foreach ($focus['nat4']['in'] as $pf)
e673ee24 2852 {
4fbb5a00
DY
2853 echo "<tr><td><a href='".
2854 makeHrefProcess(array(
2855 'op'=>'delNATv4Rule',
2856 'localip'=>$pf['localip'],
2857 'localport'=>$pf['localport'],
2858 'remoteip'=>$pf['remoteip'],
2859 'remoteport'=>$pf['remoteport'],
2860 'proto'=>$pf['proto'],
2861 'object_id'=>$pf['object_id']
2862 )).
2863 "'>";
4de22e7e
DO
2864 printImageHREF ('delete', 'Delete NAT rule');
2865 echo "</a></td>";
4fbb5a00
DY
2866 echo "<td>${pf['proto']}/<a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['localip']))."'>${pf['localip']}</a>:${pf['localport']}</td>";
2867 echo "<td class='description'><a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$pf['object_id']))."'>${pf['object_name']}</a>";
2868 echo "</td><td><a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['remoteip']))."'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
e673ee24
DO
2869 echo "<td class='description'>${pf['description']}</td></tr>";
2870 }
2871
e673ee24 2872 echo "</table><br><br>";
e673ee24
DO
2873}
2874
e673ee24
DO
2875function renderAddMultipleObjectsForm ()
2876{
8dc2a6c8 2877 global $location_obj_types, $virtual_obj_types;
7fa7047a 2878 $typelist = readChapter (CHAP_OBJTYPE, 'o');
4c330a14 2879 $typelist[0] = 'select type...';
7fa7047a 2880 $typelist = cookOptgroups ($typelist);
a1886a78
DO
2881 $max = getConfigVar ('MASSCOUNT');
2882 $tabindex = 100;
7f791d1d 2883
9b8174d7
AD
2884 // create a list of object types to exclude (virtual and location-related ones)
2885 $exclude_typelist = array_merge($location_obj_types, $virtual_obj_types);
2886
0682218d
AD
2887 $phys_typelist = $typelist;
2888 foreach ($phys_typelist['other'] as $key => $value)
2889 {
9b8174d7
AD
2890 // remove from list if type should be excluded
2891 if ($key > 0 && in_array($key, $exclude_typelist))
0682218d
AD
2892 unset($phys_typelist['other'][$key]);
2893 }
2b787762 2894 startPortlet ('Physical objects');
42d73cbf 2895 printOpFormIntro ('addObjects');
e673ee24 2896 echo '<table border=0 align=center>';
f60bb422 2897 echo "<tr><th>Object type</th><th>Common name</th><th>Visible label</th>";
dee24af6 2898 echo "<th>Asset tag</th><th>Tags</th></tr>\n";
9c0b0016 2899 for ($i = 0; $i < $max; $i++)
e673ee24 2900 {
7f791d1d 2901 echo '<tr><td>';
e7ade6bf 2902 // Don't employ DEFAULT_OBJECT_TYPE to avoid creating ghost records for pre-selected empty rows.
0682218d 2903 printNiftySelect ($phys_typelist, array ('name' => "${i}_object_type_id", 'tabindex' => $tabindex), 0);
e673ee24 2904 echo '</td>';
a1886a78
DO
2905 echo "<td><input type=text size=30 name=${i}_object_name tabindex=${tabindex}></td>";
2906 echo "<td><input type=text size=30 name=${i}_object_label tabindex=${tabindex}></td>";
2907 echo "<td><input type=text size=20 name=${i}_object_asset_no tabindex=${tabindex}></td>";
f60bb422
DO
2908 if ($i == 0)
2909 {
2910 echo "<td valign=top rowspan=${max}>";
a26a6ccc 2911 renderNewEntityTags ('object');
f60bb422
DO
2912 echo "</td>\n";
2913 }
e673ee24 2914 echo "</tr>\n";
a1886a78 2915 $tabindex++;
e673ee24 2916 }
216c84bb 2917 echo "<tr><td class=submit colspan=5><input type=submit name=got_fast_data value='Go!'></td></tr>\n";
e673ee24
DO
2918 echo "</form></table>\n";
2919 finishPortlet();
7f791d1d 2920
0682218d 2921 // create a list containing only virtual object types
0682218d
AD
2922 $virt_typelist = $typelist;
2923 foreach ($virt_typelist['other'] as $key => $value)
2924 {
2c2ea5f6 2925 if ($key > 0 && !in_array($key, $virtual_obj_types))
0682218d
AD
2926 unset($virt_typelist['other'][$key]);
2927 }
2928 startPortlet ('Virtual objects');
2929 printOpFormIntro ('addObjects');
2930 echo "<input type=hidden name=virtual_objects value=''>\n";
2931 echo '<table border=0 align=center>';
2932 echo "<tr><th>Object type</th><th>Common name</th><th>Tags</th></tr>\n";
2933 for ($i = 0; $i < $max; $i++)
2934 {
2935 echo '<tr><td>';
2936 // Don't employ DEFAULT_OBJECT_TYPE to avoid creating ghost records for pre-selected empty rows.
2937 printNiftySelect ($virt_typelist, array ('name' => "${i}_object_type_id", 'tabindex' => $tabindex), 0);
2938 echo '</td>';
2939 echo "<td><input type=text size=30 name=${i}_object_name tabindex=${tabindex}></td>";
2940 if ($i == 0)
2941 {
2942 echo "<td valign=top rowspan=${max}>";
2943 renderNewEntityTags ('object');
2944 echo "</td>\n";
2945 }
2946 echo "</tr>\n";
2947 $tabindex++;
2948 }
2949 echo "<tr><td class=submit colspan=5><input type=submit name=got_fast_data value='Go!'></td></tr>\n";
2950 echo "</form></table>\n";
2951 finishPortlet();
2952
f60bb422 2953 startPortlet ('Same type, same tags');
42d73cbf 2954 printOpFormIntro ('addLotOfObjects');
f60bb422
DO
2955 echo "<table border=0 align=center><tr><th>names</th><th>type</th></tr>";
2956 echo "<tr><td rowspan=3><textarea name=namelist cols=40 rows=25>\n";
f60bb422 2957 echo "</textarea></td><td valign=top>";
cd3775e9 2958 printNiftySelect ($typelist, array ('name' => 'global_type_id'), getConfigVar ('DEFAULT_OBJECT_TYPE'));
f60bb422
DO
2959 echo "</td></tr>";
2960 echo "<tr><th>Tags</th></tr>";
2961 echo "<tr><td valign=top>";
a26a6ccc 2962 renderNewEntityTags ('object');
f60bb422
DO
2963 echo "</td></tr>";
2964 echo "<tr><td colspan=2><input type=submit name=got_very_fast_data value='Go!'></td></tr></table>\n";
2965 echo "</form>\n";
7f791d1d 2966 finishPortlet();
e673ee24
DO
2967}
2968
671027eb
DO
2969function searchHandler()
2970{
e673ee24 2971 $terms = trim ($_REQUEST['q']);
59a83bd8 2972 if (!strlen ($terms))
0cc24e9a 2973 throw new InvalidRequestArgException('q', $_REQUEST['q'], 'Search string cannot be empty.');
671027eb 2974 renderSearchResults ($terms, searchEntitiesByText ($terms));
09ce7c20 2975}
25e55cab 2976
521cd29a 2977function renderSearchResults ($terms, $summary)
09ce7c20 2978{
521cd29a
AA
2979 // calculate the number of found objects
2980 $nhits = 0;
2981 foreach ($summary as $realm => $list)
2982 $nhits += count ($list);
2983
ea5fc465
DO
2984 if ($nhits == 0)
2985 echo "<center><h2>Nothing found for '${terms}'</h2></center>";
2986 elseif ($nhits == 1)
2987 {
6427286d
AA
2988 foreach ($summary as $realm => $record)
2989 {
2990 if (is_array ($record))
2991 $record = array_shift ($record);
2992 break;
2993 }
521cd29a 2994 switch ($realm)
ea5fc465 2995 {
f3d0cb20 2996 case 'ipv4addressbydq':
521cd29a 2997 if ($record['net_id'] !== NULL)
4318ced5 2998 echo "<script language='Javascript'>document.location='index.php?page=ipv4net&tab=default&id=${record['net_id']}&hl_ip=${record['ip']}';//</script>";
ea5fc465 2999 break;
21ee3351 3000 case 'ipv6addressbydq':
4318ced5 3001 $fmt = ip6_format ($record['ip']);
521cd29a 3002 if ($record['net_id'] !== NULL)
4318ced5 3003 echo "<script language='Javascript'>document.location='index.php?page=ipv6net&tab=default&id=${record['net_id']}&hl_ip=${fmt}';//</script>";
21ee3351 3004 break;
f3d0cb20
DO
3005 case 'ipv4addressbydescr':
3006 $parentnet = getIPv4AddressNetworkId ($record['ip']);
3007 if ($parentnet !== NULL)
4318ced5
AA
3008 {
3009 $fmt = ip4_format ($record['ip']);
3010 echo "<script language='Javascript'>document.location='index.php?page=ipv4net&tab=default&id=${parentnet}&hl_ip=${fmt}';//</script>";
3011 }
ea5fc465 3012 break;
21ee3351 3013 case 'ipv6addressbydescr':
4318ced5 3014 $parentnet = getIPv6AddressNetworkId ($record['ip']);
21ee3351 3015 if ($parentnet !== NULL)
4318ced5
AA
3016 {
3017 $fmt = ip6_format ($record['ip']);
3018 echo "<script language='Javascript'>document.location='index.php?page=ipv6net&tab=default&id=${parentnet}&hl_ip=${fmt}';//</script>";
3019 }
21ee3351 3020 break;
ea5fc465 3021 case 'ipv4network':
790a60e8 3022 echo "<script language='Javascript'>document.location='index.php?page=ipv4net";
ea5fc465
DO
3023 echo "&id=${record['id']}";
3024 echo "';//</script>";
3025 break;
21ee3351
AA
3026 case 'ipv6network':
3027 echo "<script language='Javascript'>document.location='index.php?page=ipv6net";
3028 echo "&id=${record['id']}";
3029 echo "';//</script>";
3030 break;
ea5fc465 3031 case 'object':
1b4a0a6a 3032 if (isset ($record['by_port']) and 1 == count ($record['by_port']))
7e74a507
AA
3033 {
3034 $found_ports_ids = array_keys ($record['by_port']);
3035 $hl = '&hl_port_id=' . $found_ports_ids[0];
3036 }
1b4a0a6a
DO
3037 else
3038 $hl = '';
790a60e8 3039 echo "<script language='Javascript'>document.location='index.php?page=object&object_id=${record['id']}${hl}';//</script>";
ea5fc465 3040 break;
05411ccd 3041 case 'ipv4rspool':
790a60e8 3042 echo "<script language='Javascript'>document.location='index.php?page=ipv4rspool&pool_id=${record['id']}';//</script>";
05411ccd
DO
3043 break;
3044 case 'ipv4vs':
790a60e8 3045 echo "<script language='Javascript'>document.location='index.php?page=ipv4vs&vs_id=${record['id']}';//</script>";
05411ccd 3046 break;
6a88e734 3047 case 'user':
790a60e8 3048 echo "<script language='Javascript'>document.location='index.php?page=user&user_id=${record['user_id']}';//</script>";
6a88e734 3049 break;
e1ae3fb4 3050 case 'file':
790a60e8 3051 echo "<script language='Javascript'>document.location='index.php?page=file&file_id=${record['id']}';//</script>";
e1ae3fb4 3052 break;
e531b4d6 3053 case 'rack':
790a60e8 3054 echo "<script language='Javascript'>document.location='index.php?page=rack&rack_id=${record['id']}';//</script>";
e531b4d6 3055 break;
1f54e1ba
DO
3056 case 'vlan':
3057 echo "<script language='Javascript'>document.location='index.php?page=vlan&vlan_ck=${record}';//</script>";
3058 break;
fc359703
AA
3059 default:
3060 startPortlet($realm);
3061 echo $record;
3062 finishPortlet();
ea5fc465
DO
3063 }
3064 return;
3065 }
3066 else
3067 {
3068 global $nextorder;
3069 $order = 'odd';
3070 echo "<center><h2>${nhits} result(s) found for '${terms}'</h2></center>";
3071 foreach ($summary as $where => $what)
3072 switch ($where)
e673ee24 3073 {
ea5fc465 3074 case 'object':
790a60e8 3075 startPortlet ("<a href='index.php?page=depot'>Objects</a>");
323edbbf
DO
3076 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
3077 echo '<tr><th>what</th><th>why</th></tr>';
3078 foreach ($what as $obj)
3079 {
3080 echo "<tr class=row_${order} valign=top><td>";
9f75e165
DO
3081 $object = spotEntity ('object', $obj['id']);
3082 renderCell ($object);
b1f60545
DO
3083 echo "</td><td class=tdleft>";
3084 if (isset ($obj['by_attr']))
3085 {
3086 // only explain non-obvious reasons for listing
3087 echo '<ul>';
3088 foreach ($obj['by_attr'] as $attr_name)
3089 if ($attr_name != 'name')
3090 echo "<li>${attr_name} matched</li>";
3091 echo '</ul>';
3092 }
323edbbf
DO
3093 if (isset ($obj['by_sticker']))
3094 {
3095 echo '<table>';
3096 $aval = getAttrValues ($obj['id']);
3097 foreach ($obj['by_sticker'] as $attr_id)
3098 {
0794fb66 3099 $record = $aval[$attr_id];
323edbbf 3100 echo "<tr><th width='50%' class=sticker>${record['name']}:</th>";
8ad59489 3101 echo "<td class=sticker>" . formatAttributeValue ($record) . "</td></tr>";
323edbbf
DO
3102 }
3103 echo '</table>';
3104 }
d516d719 3105 if (isset ($obj['by_port']))
323edbbf
DO
3106 {
3107 echo '<table>';
9f75e165 3108 amplifyCell ($object);
1b4a0a6a 3109 foreach ($obj['by_port'] as $port_id => $text)
9f75e165 3110 foreach ($object['ports'] as $port)
323edbbf
DO
3111 if ($port['id'] == $port_id)
3112 {
521cd29a
AA
3113 $port_href = '<a href="' . makeHref (array
3114 (
3115 'page' => 'object',
3116 'object_id' => $object['id'],
3117 'hl_port_id' => $port_id
3118 )) . '">port ' . $port['name'] . '</a>';
3119 echo "<tr><td>${port_href}:</td>";
1b4a0a6a 3120 echo "<td class=tdleft>${text}</td></tr>";
323edbbf
DO
3121 break; // next reason
3122 }
3123 echo '</table>';
3124 }
5fd2a004
DO
3125 if (isset ($obj['by_iface']))
3126 {
3127 echo '<ul>';
3128 foreach ($obj['by_iface'] as $ifname)
3129 echo "<li>interface ${ifname}</li>";
3130 echo '</ul>';
3131 }
3132 if (isset ($obj['by_nat']))
3133 {
3134 echo '<ul>';
3135 foreach ($obj['by_nat'] as $comment)
3136 echo "<li>NAT rule: ${comment}</li>";
3137 echo '</ul>';
3138 }
6a4339ed
DO
3139 if (isset ($obj['by_cableid']))
3140 {
3141 echo '<ul>';
3142 foreach ($obj['by_cableid'] as $cableid)
3143 echo "<li>link cable ID: ${cableid}</li>";
3144 echo '</ul>';
3145 }
323edbbf
DO
3146 echo "</td></tr>";
3147 $order = $nextorder[$order];
ea5fc465
DO
3148 }
3149 echo '</table>';
3150 finishPortlet();
3151 break;
3152 case 'ipv4network':
790a60e8 3153 startPortlet ("<a href='index.php?page=ipv4space'>IPv4 networks</a>");
21ee3351
AA
3154 case 'ipv6network':
3155 if ($where == 'ipv6network')
3156 startPortlet ("<a href='index.php?page=ipv6space'>IPv6 networks</a>");
3157
ea5fc465 3158 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
6df2025d 3159 foreach ($what as $cell)
ea5fc465 3160 {
0b9c98d7 3161 echo "<tr class=row_${order} valign=top><td>";
6df2025d 3162 renderCell ($cell);
0b9c98d7 3163 echo "</td></tr>\n";
ea5fc465
DO
3164 $order = $nextorder[$order];
3165 }
3166 echo '</table>';
3167 finishPortlet();
3168 break;
f3d0cb20 3169 case 'ipv4addressbydescr':
ea5fc465
DO
3170 startPortlet ('IPv4 addresses');
3171 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
f3d0cb20 3172 // FIXME: address, parent network, routers (if extended view is enabled)
e1ae3fb4 3173 echo '<tr><th>Address</th><th>Description</th></tr>';
ea5fc465
DO
3174 foreach ($what as $addr)
3175 {
f3d0cb20 3176 echo "<tr class=row_${order}><td class=tdleft>";
4318ced5 3177 $fmt = ip4_format ($addr['ip']);
f3d0cb20
DO
3178 $parentnet = getIPv4AddressNetworkId ($addr['ip']);
3179 if ($parentnet !== NULL)
4318ced5 3180 echo "<a href='index.php?page=ipv4net&tab=default&id=${parentnet}&hl_ip=${fmt}'>${fmt}</a></td>";
f3d0cb20 3181 else
4318ced5 3182 echo "<a href='index.php?page=ipaddress&ip=${fmt}'>${fmt}</a></td>";
ea5fc465
DO
3183 echo "<td class=tdleft>${addr['name']}</td></tr>";
3184 $order = $nextorder[$order];
3185 }
3186 echo '</table>';
3187 finishPortlet();
3188 break;
21ee3351
AA
3189 case 'ipv6addressbydescr':
3190 startPortlet ('IPv6 addresses');
3191 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
3192 // FIXME: address, parent network, routers (if extended view is enabled)
3193 echo '<tr><th>Address</th><th>Description</th></tr>';
3194 foreach ($what as $addr)
3195 {
3196 echo "<tr class=row_${order}><td class=tdleft>";
4318ced5
AA
3197 $fmt = ip6_format ($addr['ip']);
3198 $parentnet = getIPv6AddressNetworkId ($addr['ip']);
21ee3351 3199 if ($parentnet !== NULL)
4318ced5 3200 echo "<a href='index.php?page=ipv6net&tab=default&id=${parentnet}&hl_ip=${fmt}'>${fmt}</a></td>";