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