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