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