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