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