r4863 release notes about new delete operations locations
[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)
8023ee39
AA
912 $fmt_parents[] = "<a href='".makeHref(array('page'=>$parent['page'], $parent['id_name'] => $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)
8023ee39 920 $fmt_children[] = "<a href='".makeHref(array('page'=>$child['page'], $child['id_name']=>$child['entity_id']))."'>${child['name']}</a>";
646272be 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.
a2b16202 1445// Log array is stored in global $log_messages. Its format is simple: plain ordered array
8ab645cf 1446// with values having keys 'c' (both message code and severity) and 'a' (sprintf arguments array)
1cb6adf5 1447function showMessageOrError ()
e673ee24 1448{
a2b16202
AA
1449 global $log_messages;
1450
1451 @session_start();
1452 if (isset ($_SESSION['log']))
1453 {
1454 $log_messages = array_merge ($_SESSION['log'], $log_messages);
1455 unset ($_SESSION['log']);
1456 }
1457 session_commit();
1458
1459 if (empty ($log_messages))
1cb6adf5 1460 return;
8ab645cf
AA
1461 $msginfo = array
1462 (
1463// records 0~99 with success messages
1464 0 => array ('code' => 'success', 'format' => '%s'),
1465 5 => array ('code' => 'success', 'format' => 'added record "%s" successfully'),
1466 6 => array ('code' => 'success', 'format' => 'updated record "%s" successfully'),
1467 7 => array ('code' => 'success', 'format' => 'deleted record "%s" successfully'),
1468 8 => array ('code' => 'success', 'format' => 'Port %s successfully linked with %s'),
1469 10 => array ('code' => 'success', 'format' => 'Added %u ports, updated %u ports, encountered %u errors.'),
1470 21 => array ('code' => 'success', 'format' => 'Generation complete'),
1471 26 => array ('code' => 'success', 'format' => 'updated %u records successfully'),
1472 37 => array ('code' => 'success', 'format' => 'added %u records successfully'),
1473 38 => array ('code' => 'success', 'format' => 'removed %u records successfully'),
8ab645cf
AA
1474 43 => array ('code' => 'success', 'format' => 'Saved successfully.'),
1475 44 => array ('code' => 'success', 'format' => '%s failures and %s successfull changes.'),
1476 48 => array ('code' => 'success', 'format' => 'added a record successfully'),
1477 49 => array ('code' => 'success', 'format' => 'deleted a record successfully'),
1478 51 => array ('code' => 'success', 'format' => 'updated a record successfully'),
1479 57 => array ('code' => 'success', 'format' => 'Reset complete'),
8ab645cf 1480 63 => array ('code' => 'success', 'format' => '%u change request(s) have been processed'),
8ab645cf
AA
1481 67 => array ('code' => 'success', 'format' => "Tag rolling done, %u objects involved"),
1482 71 => array ('code' => 'success', 'format' => 'File "%s" was linked successfully'),
1483 72 => array ('code' => 'success', 'format' => 'File was unlinked successfully'),
8ab645cf
AA
1484 82 => array ('code' => 'success', 'format' => "Bulk port creation was successful. %u ports created, %u failed"),
1485 87 => array ('code' => 'success', 'format' => '802.1Q recalculate: %d ports changed on %d switches'),
8628ae44 1486// records 100~199 with fatal error messages
8ab645cf
AA
1487 100 => array ('code' => 'error', 'format' => '%s'),
1488 109 => array ('code' => 'error', 'format' => 'failed updating a record'),
8ab645cf
AA
1489 131 => array ('code' => 'error', 'format' => 'invalid format requested'),
1490 141 => array ('code' => 'error', 'format' => 'Encountered %u errors, updated %u record(s)'),
1491 149 => array ('code' => 'error', 'format' => 'Turing test failed'),
1492 150 => array ('code' => 'error', 'format' => 'Can only change password under DB authentication.'),
1493 151 => array ('code' => 'error', 'format' => 'Old password doesn\'t match.'),
1494 152 => array ('code' => 'error', 'format' => 'New passwords don\'t match.'),
1495 154 => array ('code' => 'error', 'format' => "Verification error: %s"),
1496 155 => array ('code' => 'error', 'format' => 'Save failed.'),
1497 159 => array ('code' => 'error', 'format' => 'Permission denied moving port %s from VLAN%u to VLAN%u'),
1498 161 => array ('code' => 'error', 'format' => 'Endpoint not found. Please either set FQDN attribute or assign an IP address to the object.'),
1499 162 => array ('code' => 'error', 'format' => 'More than one IP address is assigned to this object, please configure FQDN attribute.'),
8ab645cf
AA
1500 170 => array ('code' => 'error', 'format' => 'There is no network for IP address "%s"'),
1501 172 => array ('code' => 'error', 'format' => 'Malformed request'),
1502 179 => array ('code' => 'error', 'format' => 'Expired form has been declined.'),
1503 188 => array ('code' => 'error', 'format' => "Fatal SNMP failure"),
1504 189 => array ('code' => 'error', 'format' => "Unknown OID '%s'"),
1505 191 => array ('code' => 'error', 'format' => "deploy was blocked due to conflicting configuration versions"),
f0ff4930 1506
8628ae44 1507// records 200~299 with warnings
8ab645cf
AA
1508 200 => array ('code' => 'warning', 'format' => '%s'),
1509 201 => array ('code' => 'warning', 'format' => 'nothing happened...'),
8ab645cf 1510 206 => array ('code' => 'warning', 'format' => 'Rack is not empty'),
57777e4a 1511
24d3182a 1512// records 300~399 with notices
8ab645cf 1513 300 => array ('code' => 'neutral', 'format' => '%s'),
24d3182a 1514
8ab645cf
AA
1515 );
1516 // Handle the arguments. Is there any better way to do it?
a2b16202 1517 foreach ($log_messages as $record)
8ab645cf
AA
1518 {
1519 if (!isset ($record['c']) or !isset ($msginfo[$record['c']]))
1520 {
41152018
AA
1521 $prefix = isset ($record['c']) ? $record['c'] . ': ' : '';
1522 echo "<div class=msg_neutral>(${prefix}this message was lost)</div>";
8ab645cf
AA
1523 continue;
1524 }
1525 if (isset ($record['a']))
1526 switch (count ($record['a']))
baf37d01 1527 {
8ab645cf
AA
1528 case 1:
1529 $msgtext = sprintf
1530 (
1531 $msginfo[$record['c']]['format'],
1532 $record['a'][0]
1533 );
1534 break;
1535 case 2:
1536 $msgtext = sprintf
1537 (
1538 $msginfo[$record['c']]['format'],
1539 $record['a'][0],
1540 $record['a'][1]
1541 );
1542 break;
1543 case 3:
1544 $msgtext = sprintf
1545 (
1546 $msginfo[$record['c']]['format'],
1547 $record['a'][0],
1548 $record['a'][1],
1549 $record['a'][2]
1550 );
1551 break;
1552 case 4:
1553 default:
1554 $msgtext = sprintf
1555 (
1556 $msginfo[$record['c']]['format'],
1557 $record['a'][0],
1558 $record['a'][1],
1559 $record['a'][2],
1560 $record['a'][3]
1561 );
1562 break;
baf37d01 1563 }
8ab645cf
AA
1564 else
1565 $msgtext = $msginfo[$record['c']]['format'];
1566 echo '<div class=msg_' . $msginfo[$record['c']]['code'] . ">${msgtext}</div>";
baf37d01 1567 }
a2b16202 1568 $log_messages = array();
e673ee24
DO
1569}
1570
65e557dd
AA
1571// renders two tables: port link status and learned MAC list
1572function renderPortsInfo($object_id)
1573{
1574 global $nextorder;
1575 echo "<table width='100%'><tr>";
1576
1577 if (permitted (NULL, NULL, 'get_link_status'))
1578 {
1579 try
1580 {
80019a2c 1581 $linkStatus = queryDevice ($object_id, 'getportstatus');
65e557dd
AA
1582 }
1583 catch (RackTablesError $e) {}
1584 if (! empty ($linkStatus))
1585 {
1586 echo "<td valign='top' width='50%'>";
1587 startPortlet('Link status');
1588 echo "<table width='80%' class='widetable' cellspacing=0 cellpadding='5px' align='center'><tr><th>Port<th>Link status<th>Link info</tr>";
1589 $order = 'even';
1590 foreach ($linkStatus as $pn => $link)
1591 {
1592 echo "<tr class='row_$order'>";
1593 $order = $nextorder[$order];
1594 echo '<td>' . $pn;
1595 echo '<td>' . $link['status'];
1596 $info = '';
1597 if (isset ($link['speed']))
1598 $info .= $link['speed'];
1599 if (isset ($link['duplex']))
1600 {
1601 if (! empty ($info))
1602 $info .= ', ';
1603 $info .= $link['duplex'];
1604 }
1605 echo '<td>' . $info;
1606 echo '</tr>';
1607 }
1608 echo "</table></td>";
1609 finishPortlet();
1610 }
1611 }
1612
1613 try
1614 {
80019a2c 1615 $macList = sortPortList (queryDevice ($object_id, 'getmaclist'));
65e557dd
AA
1616 }
1617 catch (RackTablesError $e) {}
1618 if (! empty ($macList))
1619 {
1620 echo "<td valign='top' width='50%'>";
1621 $rendered_macs = '';
1622 $mac_count = 0;
1623 $rendered_macs .= "<table width='80%' class='widetable' cellspacing=0 cellpadding='5px' align='center'><tr><th>MAC<th>Vlan<th>Port</tr>";
1624 $order = 'even';
1625 foreach ($macList as $pn => $list)
1626 {
1627 $order = $nextorder[$order];
1628 foreach ($list as $item)
1629 {
1630 ++$mac_count;
1631 $rendered_macs .= "<tr class='row_$order'>";
1632 $rendered_macs .= '<td style="font-family: monospace">' . $item['mac'];
1633 $rendered_macs .= '<td>' . $item['vid'];
1634 $rendered_macs .= '<td>' . $pn;
1635 $rendered_macs .= '</tr>';
1636 }
1637 }
1638 $rendered_macs .= "</table></td>";
1639
1640 startPortlet("Learned MACs ($mac_count)");
1641 echo $rendered_macs;
1642 finishPortlet();
1643 }
1644
1645 echo "</td></tr></table>";
1646}
1647
e673ee24 1648/*
51c18782 1649The following conditions must be met:
e673ee24
DO
16501. We can mount onto free atoms only. This means: if any record for an atom
1651already exists in RackSpace, it can't be used for mounting.
16522. We can't unmount from 'W' atoms. Operator should review appropriate comments
1653and either delete them before unmounting or refuse to unmount the object.
1654*/
7e1db771 1655function renderRackSpaceForObject ($object_id)
e673ee24 1656{
e673ee24
DO
1657 // Always process occupied racks plus racks chosen by user. First get racks with
1658 // already allocated rackspace...
51c18782 1659 $workingRacksData = getResidentRacksData ($object_id);
e673ee24 1660 // ...and then add those chosen by user (if any).
2135fd83 1661 if (isset($_REQUEST['rackmulti']))
e673ee24 1662 foreach ($_REQUEST['rackmulti'] as $cand_id)
e673ee24
DO
1663 if (!isset ($workingRacksData[$cand_id]))
1664 {
0cc24e9a 1665 $rackData = spotEntity ('rack', $cand_id);
61a1d996 1666 amplifyCell ($rackData);
e673ee24
DO
1667 $workingRacksData[$cand_id] = $rackData;
1668 }
51690ad4 1669
0a7feebb
AD
1670 // Get a list of all of this object's parents,
1671 // then trim the list to only include parents which are racks
1672 $objectParents = getEntityRelatives('parents', 'object', $object_id);
1673 $parentRacks = array();
1674 foreach ($objectParents as $parentData)
1675 if ($parentData['entity_type'] == 'rack')
1676 $parentRacks[] = $parentData['entity_id'];
1677
e673ee24
DO
1678 // Main layout starts.
1679 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0><tr>";
1680
1681 // Left portlet with rack list.
1682 echo "<td class=pcleft height='1%'>";
1683 startPortlet ('Racks');
a8efc03e 1684 $allRacksData = listCells ('rack');
6d42599c
AA
1685
1686 // filter rack list to match only racks having common tags with the object (reducing $allRacksData)
1687 if (! isset ($_REQUEST['show_all_racks']) and getConfigVar ('FILTER_RACKLIST_BY_TAGS') == 'yes')
1688 {
1689 $matching_racks = array();
1690 $object = spotEntity ('object', $object_id);
1691 $matched_tags = array();
1692 foreach ($allRacksData as $rack)
1693 foreach ($object['etags'] as $tag)
1694 if (tagOnChain ($tag, $rack['etags']) or tagOnChain ($tag, $rack['itags']))
1695 {
1696 $matching_racks[$rack['id']] = $rack;
1697 $matched_tags[$tag['id']] = $tag;
1698 break;
1699 }
1700 // add current object's racks even if they dont match filter
1701 foreach ($workingRacksData as $rack_id => $rack)
1702 if (! isset ($matching_racks[$rack_id]))
1703 $matching_racks[$rack_id] = $rack;
1704 // if matching racks found, and rack list is reduced, show 'show all' link
1705 if (count ($matching_racks) and count ($matching_racks) != count ($allRacksData))
1706 {
1707 $filter_text = '';
1708 foreach ($matched_tags as $tag)
1709 $filter_text .= (empty ($filter_text) ? '' : ' or ') . '{' . $tag['tag'] . '}';
1710 $href_show_all = trim($_SERVER['REQUEST_URI'], '&');
1711 $href_show_all .= htmlspecialchars('&show_all_racks=1');
1712 echo "(filtered by <span class='filter-text'>$filter_text</span>, <a href='$href_show_all'>show all</a>)<p>";
1713 $allRacksData = $matching_racks;
1714 }
1715 }
1716
4b8d413e 1717 if (count ($allRacksData) <= getConfigVar ('RACK_PRESELECT_THRESHOLD'))
61a1d996 1718 foreach ($allRacksData as $rack)
51c18782
DO
1719 if (!array_key_exists ($rack['id'], $workingRacksData))
1720 {
1721 amplifyCell ($rack);
1722 $workingRacksData[$rack['id']] = $rack;
1723 }
1724 foreach (array_keys ($workingRacksData) as $rackId)
1725 applyObjectMountMask ($workingRacksData[$rackId], $object_id);
1726 printOpFormIntro ('updateObjectAllocation');
4b8d413e 1727 renderRackMultiSelect ('rackmulti[]', $allRacksData, array_keys ($workingRacksData));
51c18782 1728 echo "<br><br>";
e673ee24
DO
1729 finishPortlet();
1730 echo "</td>";
1731
1732 // Middle portlet with comment and submit.
1733 echo "<td class=pcleft>";
1734 startPortlet ('Comment');
1735 echo "<textarea name=comment rows=10 cols=40></textarea><br>\n";
1736 echo "<input type=submit value='Save' name=got_atoms>\n";
51c18782 1737 echo "<br><br>";
e673ee24
DO
1738 finishPortlet();
1739 echo "</td>";
1740
1741 // Right portlet with rendered racks. If this form submit is not final, we have to
1742 // reflect the former state of the grid in current form.
1743 echo "<td class=pcright rowspan=2 height='1%'>";
1744 startPortlet ('Working copy');
65e557dd 1745 addJS ('js/racktables.js');
e673ee24
DO
1746 echo '<table border=0 cellspacing=10 align=center><tr>';
1747 foreach ($workingRacksData as $rack_id => $rackData)
1748 {
1749 // Order is important here: only original allocation is highlighted.
1750 highlightObject ($rackData, $object_id);
1751 markupAtomGrid ($rackData, 'T');
1752 // If we have a form processed, discard user input and show new database
1753 // contents.
51c18782 1754 if (isset ($_REQUEST['rackmulti'][0])) // is an update
e673ee24
DO
1755 mergeGridFormToRack ($rackData);
1756 echo "<td valign=top>";
1757 echo "<center>\n<h2>${rackData['name']}</h2>\n";
1758 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
57c69e9c 1759 echo "<tr><th width='10%'>&nbsp;</th>";
64259015
DO
1760 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>";
1761 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>";
1762 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 1763 renderAtomGrid ($rackData);
57c69e9c 1764 echo "<tr><th width='10%'>&nbsp;</th>";
64259015
DO
1765 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>";
1766 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>";
1767 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
1768 echo "</table>\n<br>\n";
1769 // Determine zero-u checkbox status.
1770 // If form has been submitted, use form data, otherwise use DB data.
1771 if (isset($_REQUEST['op']))
1772 $checked = isset($_REQUEST['zerou_'.$rack_id]) ? 'checked' : '';
1773 else
1774 $checked = in_array($rack_id, $parentRacks) ? 'checked' : '';
1775 echo "Zero-U: <input type=checkbox ${checked} name=zerou_${rack_id} id=zerou_${rack_id}>";
1776 echo '</center></td>';
e673ee24
DO
1777 }
1778 echo "</tr></table>";
1779 finishPortlet();
1780 echo "</td>\n";
1781
1782 echo "</form>\n";
1783 echo "</tr></table>\n";
1784}
1785
1786function renderMolecule ($mdata, $object_id)
1787{
1788 // sort data out
1789 $rackpack = array();
1790 global $loclist;
64b95774 1791 foreach ($mdata as $rua)
e673ee24
DO
1792 {
1793 $rack_id = $rua['rack_id'];
1794 $unit_no = $rua['unit_no'];
1795 $atom = $rua['atom'];
1796 if (!isset ($rackpack[$rack_id]))
1797 {
61a1d996
DO
1798 $rackData = spotEntity ('rack', $rack_id);
1799 amplifyCell ($rackData);
e673ee24
DO
1800 for ($i = $rackData['height']; $i > 0; $i--)
1801 for ($locidx = 0; $locidx < 3; $locidx++)
1802 $rackData[$i][$locidx]['state'] = 'F';
1803 $rackpack[$rack_id] = $rackData;
1804 }
1805 $rackpack[$rack_id][$unit_no][$loclist[$atom]]['state'] = 'T';
1806 $rackpack[$rack_id][$unit_no][$loclist[$atom]]['object_id'] = $object_id;
1807 }
1808 // now we have some racks to render
65e557dd 1809 addAtomCSS();
64b95774 1810 foreach ($rackpack as $rackData)
e673ee24
DO
1811 {
1812 markAllSpans ($rackData);
1813 echo "<table class=molecule cellspacing=0>\n";
1814 echo "<caption>${rackData['name']}</caption>\n";
1815 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>Front</th><th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
1816 for ($i = $rackData['height']; $i > 0; $i--)
1817 {
1818 echo "<tr><th>$i</th>";
1819 for ($locidx = 0; $locidx < 3; $locidx++)
1820 {
1821 $state = $rackData[$i][$locidx]['state'];
65e557dd 1822 echo "<td class='atom state_${state}'>&nbsp;</td>\n";
e673ee24
DO
1823 }
1824 echo "</tr>\n";
1825 }
1826 echo "</table>\n";
1827 }
1828}
1829
23cdc7e9 1830function renderDepot ()
e673ee24 1831{
23cdc7e9 1832 global $pageno, $nextorder;
23cdc7e9
DO
1833 $cellfilter = getCellFilter();
1834 $objects = filterCellList (listCells ('object'), $cellfilter['expression']);
1835
1836 echo "<table border=0 class=objectview>\n";
1837 echo "<tr><td class=pcleft>";
1838
1ebbf889 1839 if (! renderEmptyResults ($cellfilter, 'objects', count($objects)))
e673ee24 1840 {
4899096d 1841 if (count($objects) > 0)
1ebbf889 1842 {
4899096d
AD
1843 startPortlet ('Objects (' . count ($objects) . ')');
1844 echo '<br><br><table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
81659c05 1845 echo '<tr><th>Common name</th><th>Visible label</th><th>Asset tag</th><th>Row/Rack</th></tr>';
4899096d 1846 $order = 'odd';
3f8a25d6
DO
1847 # gather IDs of all objects and fetch rackspace info in one pass
1848 $idlist = array();
1849 foreach ($objects as $obj)
1850 $idlist[] = $obj['id'];
1851 $mountinfo = getMountInfo ($idlist);
4899096d
AD
1852 foreach ($objects as $obj)
1853 {
1854 if (isset ($_REQUEST['hl_object_id']) and $_REQUEST['hl_object_id'] == $obj['id'])
1855 $secondclass = 'tdleft port_highlight';
1856 else
1857 $secondclass = 'tdleft';
1858 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>";
1859 if (count ($obj['etags']))
1860 echo '<br><small>' . serializeTags ($obj['etags'], makeHref(array('page'=>$pageno, 'tab'=>'default')) . '&') . '</small>';
1861 echo "</td><td class='${secondclass}'>${obj['label']}</td>";
1862 echo "<td class='${secondclass}'>${obj['asset_no']}</td>";
3f8a25d6
DO
1863 $places = array();
1864 if (! array_key_exists ($obj['id'], $mountinfo))
1865 $places[] = 'Unmounted';
4899096d 1866 else
3f8a25d6
DO
1867 foreach ($mountinfo[$obj['id']] as $mi)
1868 $places[] = mkA ($mi['row_name'], 'row', $mi['row_id']) . '/' . mkA ($mi['rack_name'], 'rack', $mi['rack_id']);
1869 echo "<td class='${secondclass}'>" . implode (', ', $places) . '</td>';
4899096d
AD
1870 echo '</tr>';
1871 $order = $nextorder[$order];
1872 }
1873 echo '</table>';
1874 finishPortlet();
1ebbf889 1875 }
4899096d
AD
1876 else
1877 echo '<h2>No objects exist</h2>';
e673ee24 1878 }
23cdc7e9
DO
1879
1880 echo "</td><td class=pcright width='25%'>";
1881
95857b5c 1882 renderCellFilterPortlet ($cellfilter, 'object', $objects);
23cdc7e9 1883 echo "</td></tr></table>\n";
e673ee24
DO
1884}
1885
1ebbf889
AA
1886// This function returns TRUE if the result set is too big to be rendered, and no filter is set.
1887// In this case it renders the describing message instead.
1888function renderEmptyResults($cellfilter, $entities_name, $count = NULL)
1889{
1890 if (!$cellfilter['is_empty'])
1891 return FALSE;
1892 if (isset ($_REQUEST['show_all_objects']))
1893 return FALSE;
1894 $max = intval(getConfigVar('MAX_UNFILTERED_ENTITIES'));
1895 if (0 == $max || $count <= $max)
1896 return FALSE;
1897
1898 $href_show_all = trim($_SERVER['REQUEST_URI'], '&');
1899 $href_show_all .= htmlspecialchars('&show_all_objects=1');
1900 $suffix = isset ($count) ? " ($count)" : '';
1901 echo <<<END
1902<p>Please set a filter to display the corresponging $entities_name.
1903<br><a href="$href_show_all">Show all $entities_name$suffix</a>
1904END;
1905 return TRUE;
1906}
1907
e673ee24 1908// History viewer for history-enabled simple dictionaries.
9b8174d7 1909function renderObjectHistory ($object_id)
e673ee24 1910{
e673ee24
DO
1911 $order = 'odd';
1912 global $nextorder;
9b8174d7
AD
1913 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
1914 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>';
1915 $result = usePreparedSelectBlade
1916 (
1917 'SELECT ctime, user_name, name, label, asset_no, has_problems, comment FROM ObjectHistory WHERE id=? ORDER BY ctime',
1918 array ($object_id)
1919 );
e673ee24
DO
1920 while ($row = $result->fetch (PDO::FETCH_NUM))
1921 {
1922 echo "<tr class=row_${order}><td>${row[0]}</td>";
9b8174d7 1923 for ($i = 1; $i <= 6; $i++)
e673ee24
DO
1924 echo "<td>" . $row[$i] . "</td>";
1925 echo "</tr>\n";
1926 $order = $nextorder[$order];
1927 }
1928 echo "</table><br>\n";
1929}
1930
1931function renderRackspaceHistory ()
1932{
4fbb5a00 1933 global $nextorder, $pageno, $tabno;
e673ee24
DO
1934 $order = 'odd';
1935 $history = getRackspaceHistory();
1936 // Show the last operation by default.
1937 if (isset ($_REQUEST['op_id']))
1938 $op_id = $_REQUEST['op_id'];
1939 elseif (isset ($history[0]['mo_id']))
1940 $op_id = $history[0]['mo_id'];
1941 else $op_id = NULL;
1942
1943 $omid = NULL;
1944 $nmid = NULL;
1945 $object_id = 1;
1946 if ($op_id)
1947 list ($omid, $nmid) = getOperationMolecules ($op_id);
1948
1949 // Main layout starts.
1950 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
1951
1952 // Left top portlet with old allocation.
1953 echo "<tr><td class=pcleft>";
1954 startPortlet ('Old allocation');
1955 if ($omid)
1956 {
1957 $oldMolecule = getMolecule ($omid);
1958 renderMolecule ($oldMolecule, $object_id);
1959 }
1960 else
1961 echo "nothing";
1962 finishPortlet();
1963
1964 echo '</td><td class=pcright>';
1965
1966 // Right top portlet with new allocation
1967 startPortlet ('New allocation');
1968 if ($nmid)
1969 {
1970 $newMolecule = getMolecule ($nmid);
1971 renderMolecule ($newMolecule, $object_id);
1972 }
1973 else
1974 echo "nothing";
1975 finishPortlet();
737a3f72 1976
e673ee24 1977 echo '</td></tr><tr><td colspan=2>';
737a3f72 1978
e673ee24
DO
1979 // Bottom portlet with list
1980
1981 startPortlet ('Rackspace allocation history');
1982 echo "<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>\n";
7fa7047a 1983 echo "<tr><th>timestamp</th><th>author</th><th>object</th><th>comment</th></tr>\n";
e673ee24
DO
1984 foreach ($history as $row)
1985 {
1986 if ($row['mo_id'] == $op_id)
1987 $class = 'hl';
1988 else
1989 $class = "row_${order}";
4fbb5a00 1990 echo "<tr class=${class}><td><a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'op_id'=>$row['mo_id']))."'>${row['ctime']}</a></td>";
7fa7047a
DO
1991 echo "<td>${row['user_name']}</td><td>";
1992 renderCell (spotEntity ('object', $row['ro_id']));
9c6222ef 1993 echo '</td><td>' . niftyString ($row['comment'], 0) . '</td></tr>';
e673ee24
DO
1994 $order = $nextorder[$order];
1995 }
1996 echo "</table>\n";
1997 finishPortlet();
737a3f72 1998
e673ee24 1999 echo '</td></tr></table>';
e673ee24
DO
2000}
2001
1f54e1ba 2002function renderIPv4SpaceRecords ($tree, $baseurl, $target = 0, $knight, $level = 1)
d65353ad
DO
2003{
2004 $self = __FUNCTION__;
ca4eb604
DO
2005 static $vdomlist = NULL;
2006 if ($vdomlist == NULL and getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
e829e76b 2007 $vdomlist = getVLANDomainOptions();
00276508
AA
2008
2009 // scroll page to the highlighted item
2010 if ($target && isset ($_REQUEST['hl_net']))
65e557dd 2011 addAutoScrollScript ("net-$target");
00276508 2012
d65353ad
DO
2013 foreach ($tree as $item)
2014 {
64347dcf 2015 if (getConfigVar ('IPV4_TREE_SHOW_USAGE') == 'yes')
64347dcf 2016 loadIPv4AddrList ($item); // necessary to compute router list and address counter
64347dcf
DO
2017 else
2018 {
2019 $item['addrlist'] = array();
2020 $item['addrc'] = 0;
2021 }
b1e39212
DO
2022 $used = $item['addrc'];
2023 $maxdirect = $item['addrt'];
2024 $maxtotal = binInvMaskFromDec ($item['mask']) + 1;
0137d53c
DO
2025 if (isset ($item['id']))
2026 {
1f54e1ba 2027 $decor = array ('indent' => $level);
fec0c8da 2028 if ($item['symbol'] == 'node-collapsed')
00276508 2029 $decor['symbolurl'] = "${baseurl}&eid=" . $item['id'];
fec0c8da 2030 elseif ($item['symbol'] == 'node-expanded')
00276508 2031 $decor['symbolurl'] = $baseurl . ($item['parent_id'] ? "&eid=${item['parent_id']}" : '');
0137d53c 2032 echo "<tr valign=top>";
21ee3351 2033 if ($target == $item['id'] && isset ($_REQUEST['hl_net']))
ee8688c4 2034 $decor['tdclass'] = 'port_highlight';
21ee3351 2035 printIPNetInfoTDs ($item, $decor);
0137d53c 2036 echo "<td class=tdcenter>";
64347dcf
DO
2037 if (getConfigVar ('IPV4_TREE_SHOW_USAGE') == 'yes')
2038 {
b1e39212
DO
2039 renderProgressBar ($maxdirect ? $used/$maxdirect : 0);
2040 echo "<br><small>${used}/${maxdirect}" . ($maxdirect == $maxtotal ? '' : "/${maxtotal}") . '</small>';
64347dcf
DO
2041 }
2042 else
b1e39212 2043 echo "<small>${maxdirect}</small>";
64347dcf 2044 echo "</td>";
ca4eb604
DO
2045 if (getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2046 {
a5f9d1ca
DO
2047 echo '<td class=tdleft>';
2048 if (count ($item['8021q']))
ca4eb604 2049 {
a5f9d1ca
DO
2050 echo '<ul>';
2051 foreach ($item['8021q'] as $binding)
2052 {
2053 echo '<li><a href="' . makeHref (array ('page' => 'vlan', 'vlan_ck' => $binding['domain_id'] . '-' . $binding['vlan_id'])) . '">';
e829e76b
DO
2054 // FIXME: would formatVLANName() do this?
2055 echo $binding['vlan_id'] . '@' . niftyString ($vdomlist[$binding['domain_id']], 15) . '</a></li>';
a5f9d1ca
DO
2056 }
2057 echo '</ul>';
ca4eb604
DO
2058 }
2059 echo '</td>';
2060 }
0137d53c 2061 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
4a47d34b 2062 printRoutersTD (findRouters ($item['addrlist']), getConfigVar ('IPV4_TREE_RTR_AS_CELL'));
0137d53c 2063 echo "</tr>";
fec0c8da 2064 if ($item['symbol'] == 'node-expanded' or $item['symbol'] == 'node-expanded-static')
1f54e1ba 2065 $self ($item['kids'], $baseurl, $target, $knight, $level + 1);
0137d53c
DO
2066 }
2067 else
2068 {
0137d53c 2069 echo "<tr valign=top>";
21ee3351 2070 printIPNetInfoTDs ($item, array ('indent' => $level, 'knight' => $knight, 'tdclass' => 'sparenetwork'));
0137d53c 2071 echo "<td class=tdcenter>";
64347dcf
DO
2072 if (getConfigVar ('IPV4_TREE_SHOW_USAGE') == 'yes')
2073 {
b1e39212
DO
2074 renderProgressBar ($used/$maxtotal, 'sparenetwork');
2075 echo "<br><small>${used}/${maxtotal}</small>";
64347dcf
DO
2076 }
2077 else
b1e39212 2078 echo "<small>${maxtotal}</small>";
ee3eac34
DO
2079 if (getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2080 echo '</td><td>&nbsp;</td>';
64347dcf 2081 echo "</td><td>&nbsp;</td></tr>";
0137d53c 2082 }
d65353ad
DO
2083 }
2084}
2085
21ee3351
AA
2086function renderIPv6SpaceRecords ($tree, $baseurl, $target = 0, $knight, $level = 1)
2087{
2088 $self = __FUNCTION__;
2089 static $vdomlist = NULL;
2090 if ($vdomlist == NULL and getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2091 $vdomlist = getVLANDomainOptions();
00276508
AA
2092
2093 // scroll page to the highlighted item
2094 if ($target && isset ($_REQUEST['hl_net']))
65e557dd 2095 addAutoScrollScript ("net-$target");
00276508 2096
21ee3351
AA
2097 foreach ($tree as $item)
2098 {
2099 if (getConfigVar ('IPV4_TREE_SHOW_USAGE') == 'yes')
2100 loadIPv6AddrList ($item); // necessary to compute router list and address counter
2101 else
2102 {
2103 $item['addrlist'] = array();
2104 $item['addrc'] = 0;
2105 }
2106 if (isset ($item['id']))
2107 {
2108 $decor = array ('indent' => $level);
2109 if ($item['symbol'] == 'node-collapsed')
00276508 2110 $decor['symbolurl'] = "${baseurl}&eid=" . $item['id'];
21ee3351
AA
2111 elseif ($item['symbol'] == 'node-expanded')
2112 $decor['symbolurl'] = $baseurl . ($item['parent_id'] ? "&eid=${item['parent_id']}#net6id${item['parent_id']}" : '');
2113 echo "<tr valign=top>";
2114 if ($target == $item['id'] && isset ($_REQUEST['hl_net']))
88317562 2115 $decor['tdclass'] = ' port_highlight';
21ee3351
AA
2116 printIPNetInfoTDs ($item, $decor);
2117 echo "<td class=tdcenter>";
21ee3351
AA
2118 // show net usage
2119 echo formatIPv6NetUsage ($item['addrc'], $item['mask']);
2120 echo "</td>";
2121 if (getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2122 {
2123 echo '<td class=tdleft>';
2124 if (count ($item['8021q']))
2125 {
2126 echo '<ul>';
2127 foreach ($item['8021q'] as $binding)
2128 {
2129 echo '<li><a href="' . makeHref (array ('page' => 'vlan', 'vlan_ck' => $binding['domain_id'] . '-' . $binding['vlan_id'])) . '">';
2130 // FIXME: would formatVLANName() do this?
2131 echo $binding['vlan_id'] . '@' . niftyString ($vdomlist[$binding['domain_id']], 15) . '</a></li>';
2132 }
2133 echo '</ul>';
2134 }
2135 echo '</td>';
2136 }
2137 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2138 printRoutersTD (findRouters ($item['addrlist']), getConfigVar ('IPV4_TREE_RTR_AS_CELL'));
2139 echo "</tr>";
2140 if ($item['symbol'] == 'node-expanded' or $item['symbol'] == 'node-expanded-static')
2141 $self ($item['kids'], $baseurl, $target, $knight, $level + 1);
2142 }
2143 /* do not display spare networks
2144 else
2145 { // display spare networks
2146 echo "<tr valign=top>";
2147 printIPNetInfoTDs ($item, array ('indent' => $level, 'knight' => $knight, 'tdclass' => 'sparenetwork'));
2148 echo "<td class=tdcenter>";
2149 echo formatIPv6NetUsage ($item['addrc'], $item['mask']);
2150 if (getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2151 echo '</td><td>&nbsp;</td>';
2152 echo "</td><td>&nbsp;</td></tr>";
2153 }*/
2154 }
2155}
2156
2157// if $used is NULL, returns only human-formatted mask.
2158// Otherwise returns "$used in/of " . human-formatted-mask
2159function formatIPv6NetUsage ($used, $mask)
2160{
2161 $prefixes = array
2162 (
2163 0 => '',
2164 3 => 'k',
2165 6 => 'M',
2166 9 => 'G',
2167 12 => 'T',
2168 15 => 'P',
2169 18 => 'E',
2170 21 => 'Z',
2171 24 => 'Y',
2172 );
2173
2174 if ($mask <= 64)
2175 {
2176 $what = '/64 net';
2177 $preposition = 'in';
2178 $mask += 64;
2179 }
2180 else
2181 {
2182 $what = 'IP';
2183 $preposition = 'of';
2184 }
2185 $what .= (0 == $mask % 64 ? '' : 's');
2186 $addrc = isset ($used) ? "$used $preposition " : '';
2187
2188 $dec_order = intval ((128 - $mask) / 10) * 3;
2189 $mult = isset ($prefixes[$dec_order]) ? $prefixes[$dec_order] : '??';
2190
2191 $cnt = 1 << ((128 - $mask) % 10);
2192 if ($cnt == 1 && $mult == '')
2193 $cnt = 'single';
2194
2195 return "<small>${addrc}${cnt}${mult} ${what}</small>";
2196}
2197
04d619d0 2198function renderIPv4Space ()
e673ee24 2199{
4fbb5a00 2200 global $pageno, $tabno;
31c941ec 2201 $cellfilter = getCellFilter();
1f54e1ba
DO
2202 $netlist = listCells ('ipv4net');
2203 $allcount = count ($netlist);
2204 $netlist = filterCellList ($netlist, $cellfilter['expression']);
573214e0 2205 array_walk ($netlist, 'amplifyCell');
4fbb5a00 2206
94a40058 2207 $netcount = count ($netlist);
5388794d
DO
2208 // expand request can take either natural values or "ALL". Zero means no expanding.
2209 $eid = isset ($_REQUEST['eid']) ? $_REQUEST['eid'] : 0;
2210 $tree = prepareIPv4Tree ($netlist, $eid);
3630d1fb
DO
2211
2212 echo "<table border=0 class=objectview>\n";
2213 echo "<tr><td class=pcleft>";
1ebbf889
AA
2214 if (! renderEmptyResults($cellfilter, 'IPv4 nets', count($tree)))
2215 {
2216 startPortlet ("networks (${netcount})");
2217 echo '<h4>';
2218 if ($eid === 0)
2219 echo 'auto-collapsing at threshold ' . getConfigVar ('TREE_THRESHOLD') .
2220 " (<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'eid'=>'ALL')) .
2221 $cellfilter['urlextra'] . "'>expand all</a>)";
2222 elseif ($eid === 'ALL')
2223 echo "expanding all (<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno)) .
2224 $cellfilter['urlextra'] . "'>auto-collapse</a>)";
2225 else
2226 {
2227 $netinfo = spotEntity ('ipv4net', $eid);
2228 echo "expanding ${netinfo['ip']}/${netinfo['mask']} (<a href='" .
2229 makeHref (array ('page' => $pageno, 'tab' => $tabno)) .
2230 $cellfilter['urlextra'] . "'>auto-collapse</a> / <a href='" .
2231 makeHref (array ('page' => $pageno, 'tab' => $tabno, 'eid' => 'ALL')) .
2232 $cellfilter['urlextra'] . "'>expand&nbsp;all</a>)";
2233 }
2234 echo "</h4><table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2235 echo "<tr><th>prefix</th><th>name/tags</th><th>capacity</th>";
2236 if (getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2237 echo '<th>VLAN</th>';
2238 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2239 echo "<th>routed by</th>";
2240 echo "</tr>\n";
2241 $baseurl = makeHref(array('page'=>$pageno, 'tab'=>$tabno)) . $cellfilter['urlextra'];
2242 renderIPv4SpaceRecords ($tree, $baseurl, $eid, $netcount == $allcount and getConfigVar ('IPV4_ENABLE_KNIGHT') == 'yes');
2243 echo "</table>\n";
2244 finishPortlet();
5388794d 2245 }
1ebbf889 2246
74ccacff 2247 echo '</td><td class=pcright>';
95857b5c 2248 renderCellFilterPortlet ($cellfilter, 'ipv4net', $netlist);
74ccacff 2249 echo "</td></tr></table>\n";
f973f491 2250}
a7fe7729 2251
21ee3351
AA
2252function renderIPv6Space ()
2253{
2254 global $pageno, $tabno;
2255 $cellfilter = getCellFilter();
2256 $netlist = listCells ('ipv6net');
2257 $allcount = count ($netlist);
2258 $netlist = filterCellList ($netlist, $cellfilter['expression']);
2259 array_walk ($netlist, 'amplifyCell');
2260
2261 $netcount = count ($netlist);
2262 // expand request can take either natural values or "ALL". Zero means no expanding.
2263 $eid = isset ($_REQUEST['eid']) ? $_REQUEST['eid'] : 0;
2264 $tree = prepareIPv6Tree ($netlist, $eid);
2265
2266 echo "<table border=0 class=objectview>\n";
2267 echo "<tr><td class=pcleft>";
2268 if (! renderEmptyResults($cellfilter, 'IPv6 nets', count($tree)))
2269 {
2270 startPortlet ("networks (${netcount})");
2271 echo '<h4>';
2272 if ($eid === 0)
2273 echo 'auto-collapsing at threshold ' . getConfigVar ('TREE_THRESHOLD') .
2274 " (<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'eid'=>'ALL')) .
2275 $cellfilter['urlextra'] . "'>expand all</a>)";
2276 elseif ($eid === 'ALL')
2277 echo "expanding all (<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno)) .
2278 $cellfilter['urlextra'] . "'>auto-collapse</a>)";
2279 else
2280 {
2281 $netinfo = spotEntity ('ipv6net', $eid);
2282 echo "expanding ${netinfo['ip']}/${netinfo['mask']} (<a href='" .
2283 makeHref (array ('page' => $pageno, 'tab' => $tabno)) .
2284 $cellfilter['urlextra'] . "'>auto-collapse</a> / <a href='" .
2285 makeHref (array ('page' => $pageno, 'tab' => $tabno, 'eid' => 'ALL')) .
2286 $cellfilter['urlextra'] . "'>expand&nbsp;all</a>)";
2287 }
2288 echo "</h4><table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2289 echo "<tr><th>prefix</th><th>name/tags</th><th>capacity</th>";
2290 if (getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2291 echo '<th>VLAN</th>';
2292 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2293 echo "<th>routed by</th>";
2294 echo "</tr>\n";
2295 $baseurl = makeHref(array('page'=>$pageno, 'tab'=>$tabno)) . $cellfilter['urlextra'];
2296 renderIPv6SpaceRecords ($tree, $baseurl, $eid, $netcount == $allcount and getConfigVar ('IPV4_ENABLE_KNIGHT') == 'yes');
2297 echo "</table>\n";
2298 finishPortlet();
2299 }
2300
2301 echo '</td><td class=pcright>';
2302 renderCellFilterPortlet ($cellfilter, 'ipv6net', $netlist);
2303 echo "</td></tr></table>\n";
2304}
2305
04d619d0 2306function renderIPv4SpaceEditor ()
e673ee24 2307{
93a49e5b
AA
2308 $addrspaceList = listCells ('ipv4net');
2309 startPortlet ('Manage existing (' . count ($addrspaceList) . ')');
2310 if (count ($addrspaceList))
f857f71f 2311 {
04d619d0 2312 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
b1e39212 2313 echo "<tr><th>&nbsp;</th><th>prefix</th><th>name</th><th>capacity</th></tr>";
d3dcdfbb
DO
2314 array_walk ($addrspaceList, 'amplifyCell');
2315 $tree = prepareIPv4Tree ($addrspaceList, 'ALL');
2316 // this is only called for having "trace" set
2317 treeFromList ($addrspaceList);
0c16ef0c 2318 foreach ($addrspaceList as $netinfo)
e673ee24 2319 {
b1e39212
DO
2320 $netinfo = peekNode ($tree, $netinfo['trace'], $netinfo['id']);
2321 // now we have all subnets listed in netinfo
2322 loadIPv4AddrList ($netinfo);
2323 $used = $netinfo['addrc'];
2324 $maxdirect = $netinfo['addrt'];
2325 $maxtotal = binInvMaskFromDec ($netinfo['mask']) + 1;
e43a2de4 2326 echo "<tr valign=top><td>";
93a49e5b 2327 if (! isIPNetworkEmpty ($netinfo))
21ee3351
AA
2328 printImageHREF ('nodestroy', 'There are ' . count ($netinfo['addrlist']) . ' allocations inside');
2329 else
93a49e5b 2330 echo getOpLink (array ('op' => 'del', 'id' => $netinfo['id']), '', 'destroy', 'Delete this prefix');
21ee3351
AA
2331 echo '</td><td class=tdleft><a href="' . makeHref (array ('page' => 'ipv4net', 'id' => $netinfo['id'])) . '">';
2332 echo "${netinfo['ip']}/${netinfo['mask']}</a></td>";
2333 echo '<td class=tdleft>' . niftyString ($netinfo['name']);
2334 if (count ($netinfo['etags']))
2335 echo '<br><small>' . serializeTags ($netinfo['etags']) . '</small>';
2336 echo '</td><td>';
2337 renderProgressBar ($maxdirect ? $used/$maxdirect : 0);
2338 echo "<br><small>${used}/${maxdirect}" . ($maxdirect == $maxtotal ? '' : "/${maxtotal}") . '</small></td>';
2339 echo '</tr>';
2340 }
2341 echo "</table>";
2342 finishPortlet();
2343 }
21ee3351 2344}
e43a2de4 2345
21ee3351
AA
2346function renderIPv6SpaceEditor ()
2347{
93a49e5b
AA
2348 $addrspaceList = listCells ('ipv6net');
2349 startPortlet ('Manage existing (' . count ($addrspaceList) . ')');
2350 if (count ($addrspaceList))
21ee3351 2351 {
21ee3351
AA
2352 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2353 echo "<tr><th>&nbsp;</th><th>prefix</th><th>name</th><th>capacity</th></tr>";
2354 array_walk ($addrspaceList, 'amplifyCell');
2355 $tree = prepareIPv6Tree ($addrspaceList, 'ALL');
2356 // this is only called for having "trace" set
2357 treeFromList ($addrspaceList);
2358 foreach ($addrspaceList as $netinfo)
2359 {
2360 $netinfo = peekNode ($tree, $netinfo['trace'], $netinfo['id']);
2361 // now we have all subnets listed in netinfo
2362 loadIPv6AddrList ($netinfo);
2363 echo "<tr valign=top><td>";
93a49e5b 2364 if (! isIPNetworkEmpty ($netinfo))
21ee3351
AA
2365 printImageHREF ('nodestroy', 'There are ' . count ($netinfo['addrlist']) . ' allocations inside');
2366 else
93a49e5b 2367 echo getOpLink (array ('op' => 'del', 'id' => $netinfo['id']), '', 'destroy', 'Delete this prefix');
21ee3351 2368 echo '</td><td class=tdleft><a href="' . makeHref (array ('page' => 'ipv6net', 'id' => $netinfo['id'])) . '">';
ab1283b7 2369 echo "${netinfo['ip']}/${netinfo['mask']}</a></td>";
1f54e1ba
DO
2370 echo '<td class=tdleft>' . niftyString ($netinfo['name']);
2371 if (count ($netinfo['etags']))
2372 echo '<br><small>' . serializeTags ($netinfo['etags']) . '</small>';
2373 echo '</td><td>';
21ee3351 2374 echo formatIPv6NetUsage ($netinfo['addrc'], $netinfo['mask']);
b1e39212 2375 echo '</tr>';
e673ee24 2376 }
04d619d0
DO
2377 echo "</table>";
2378 finishPortlet();
e673ee24 2379 }
93a49e5b
AA
2380}
2381
2382function renderIPNewNetForm ()
2383{
2384 global $pageno;
2385 if ($pageno == 'ipv6space')
2386 {
2387 $realm = 'ipv6net';
2388 $regexp = addslashes ('^[a-fA-F0-9:]*:[a-fA-F0-9:\.]*/\d{1,3}$');
2389 }
2390 else
2391 {
2392 $realm = 'ipv4net';
2393 $regexp = addslashes ('^(\d{1,3}\.){3}\d{1,3}/\d{1,2}$');
2394 }
2395
2396 // IP prefix validator
2397 addJs ('js/live_validation.js');
2398 $regexp = addslashes ($regexp);
2399 addJs (<<<END
2400$(document).ready(function () {
2401 document.add_new_range.range.setAttribute('match', '$regexp');
2402 Validate.init();
2403});
2404END
2405 , TRUE);
2406
2407 startPortlet ('Add new');
2408 echo '<table border=0 cellpadding=10 align=center>';
2409 // This form requires a name, so JavaScript validator can find it.
2410 // No printOpFormIntro() hence
2411 echo "<form method=post name='add_new_range' action='".makeHrefProcess()."'>\n";
2412 echo "<input type=hidden name=op value=add>\n";
2413 // tags column
2414 echo '<tr><td rowspan=5><h3>assign tags</h3>';
2415 renderNewEntityTags ($realm);
2416 echo '</td>';
2417 // inputs column
2418 $prefix_value = empty ($_REQUEST['set-prefix']) ? '' : $_REQUEST['set-prefix'];
2419 echo "<th class=tdright>prefix</th><td class=tdleft><input type=text name='range' size=36 class='live-validate' tabindex=1 value='${prefix_value}'></td>";
2420 echo '<tr><th class=tdright>VLAN</th><td class=tdleft>';
2421 echo getOptionTree ('vlan_ck', getAllVLANOptions(), array ('select_class' => 'vertical', 'tabindex' => 2)) . '</td></tr>';
2422 echo "<tr><th class=tdright>name</th><td class=tdleft><input type=text name='name' size='20' tabindex=3></td></tr>";
2423 echo '<tr><td class=tdright><input type=checkbox name="is_connected" tabindex=4></td><th class=tdleft>reserve subnet-router anycast address</th></tr>';
2424 echo "<tr><td colspan=2>";
2425 printImageHREF ('CREATE', 'Add a new network', TRUE, 5);
2426 echo '</td></tr>';
2427 echo "</form></table><br><br>\n";
2428 finishPortlet();
e673ee24
DO
2429}
2430
beb9e88a 2431function renderIPv4Network ($id)
e673ee24 2432{
c8824ff4 2433 global $pageno, $tabno, $aac2, $netmaskbylen, $wildcardbylen;
e673ee24 2434
d724d290 2435 $range = spotEntity ('ipv4net', $id);
a5f9d1ca 2436 amplifyCell ($range);
b6b87070 2437 loadIPv4AddrList ($range);
2034d968 2438 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
99ab184f
DO
2439 echo "<tr><td colspan=2 align=center><h1>${range['ip']}/${range['mask']}</h1><h2>";
2440 echo htmlspecialchars ($range['name'], ENT_QUOTES, 'UTF-8') . "</h2></td></tr>\n";
2034d968
DO
2441
2442 echo "<tr><td class=pcleft width='50%'>";
646272be
AA
2443
2444 // render summary portlet
2445 $summary = array();
2034d968
DO
2446 $total = ($range['ip_bin'] | $range['mask_bin_inv']) - ($range['ip_bin'] & $range['mask_bin']) + 1;
2447 $used = count ($range['addrlist']);
646272be 2448 $summary['%% used'] = getProgressBar ($used/$total) . "&nbsp;${used}/${total}";
001e61fa
DO
2449 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2450 {
3444ecf2
DO
2451 // Build a backtrace from all parent networks.
2452 $clen = $range['mask'];
2453 $backtrace = array();
2454 while (NULL !== ($upperid = getIPv4AddressNetworkId ($range['ip'], $clen)))
2455 {
d724d290 2456 $upperinfo = spotEntity ('ipv4net', $upperid);
3444ecf2 2457 $clen = $upperinfo['mask'];
d724d290 2458 $backtrace[] = $upperinfo;
3444ecf2
DO
2459 }
2460 $arrows = count ($backtrace);
d724d290 2461 foreach (array_reverse ($backtrace) as $ainfo)
001e61fa 2462 {
646272be 2463 $name = '';
3444ecf2 2464 for ($i = 0; $i < $arrows; $i++)
646272be 2465 $name .= '&uarr;';
3444ecf2 2466 $arrows--;
646272be 2467 $summary[] = array ($name, getOutputOf ('renderCell', $ainfo));
001e61fa 2468 }
646272be 2469 $summary[] = array ('&rarr;', getOutputOf ('renderCell', $range));
001e61fa
DO
2470 // FIXME: get and display nested networks
2471 // $theitem = pickLeaf ($ipv4tree, $id);
2472 }
646272be
AA
2473 $summary[] = array ('Netmask:', $netmaskbylen[$range['mask']]);
2474 $summary[] = array ('Netmask:', sprintf ('0x%08X', binMaskFromDec ($range['mask'])));
2475 $summary['Wildcard bits'] = $wildcardbylen[$range['mask']];
2476
a5f9d1ca 2477 foreach ($range['8021q'] as $item)
cbf78395 2478 {
a5f9d1ca 2479 $vlaninfo = getVLANInfo ($item['domain_id'] . '-' . $item['vlan_id']);
646272be 2480 $summary[] = array ('VLAN:', '<a href="' . makeHref (array ('page' => 'vlan', 'vlan_ck' => $vlaninfo['vlan_ck'])) . '">' . formatVLANName ($vlaninfo, 'markup long') . '</a>');
cbf78395 2481 }
3a4f4023 2482 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes' and count ($routers = findRouters ($range['addrlist'])))
04d619d0 2483 {
646272be
AA
2484 $summary['Routed by'] = '';
2485 foreach ($routers as $rtr)
2486 $summary['Routed by'] .= getOutputOf ('renderRouterCell', $rtr['addr'], $rtr['iface'], spotEntity ('object', $rtr['id']));
04d619d0 2487 }
646272be
AA
2488 $summary['tags'] = '';
2489 renderEntitySummary ($range, 'summary', $summary);
e1ae3fb4 2490
99ab184f
DO
2491 if (strlen ($range['comment']))
2492 {
2493 startPortlet ('Comment');
2494 echo '<div class=commentblock>' . string_insert_hrefs (htmlspecialchars ($range['comment'], ENT_QUOTES, 'UTF-8')) . '</div>';
2495 finishPortlet ();
2496 }
2497
e1ae3fb4 2498 renderFilesPortlet ('ipv4net', $id);
2034d968 2499 echo "</td>\n";
e673ee24 2500
2034d968
DO
2501 echo "<td class=pcright>";
2502 startPortlet ('details');
e673ee24
DO
2503 $startip = $range['ip_bin'] & $range['mask_bin'];
2504 $endip = $range['ip_bin'] | $range['mask_bin_inv'];
2505 $realstartip = $startip;
2506 $realendip = $endip;
e673ee24 2507
00276508
AA
2508 if (isset ($_REQUEST['hl_ipv4_addr']))
2509 {
2510 $hl_ip = ip2long ($_REQUEST['hl_ipv4_addr']);
2511 $hl_dottedquad = ip_long2quad ($hl_ip);
65e557dd 2512 addAutoScrollScript ("ip-$hl_dottedquad"); // scroll page to highlighted ip
00276508
AA
2513 }
2514
79b57b18
AA
2515 // pager
2516 $maxperpage = getConfigVar ('IPV4_ADDRS_PER_PAGE');
2517 $address_count = $endip - $startip + 1;
2518 $page = 0;
446c25c3 2519 $rendered_pager = '';
79b57b18
AA
2520 if ($address_count > $maxperpage && $maxperpage > 0)
2521 {
2522 $page = isset ($_REQUEST['pg']) ? $_REQUEST['pg'] : (isset ($hl_ip) ? intval (($hl_ip - $startip) / $maxperpage) : 0);
2523 if ($numpages = ceil ($address_count / $maxperpage))
2524 {
79b57b18
AA
2525 echo '<h3>' . long2ip ($startip) . ' ~ ' . long2ip ($endip) . '</h3>';
2526 for ($i = 0; $i < $numpages; $i++)
2527 if ($i == $page)
446c25c3 2528 $rendered_pager .= "<b>$i</b> ";
79b57b18 2529 else
446c25c3 2530 $rendered_pager .= "<a href='".makeHref (array ('page' => $pageno, 'tab' => $tabno, 'id' => $id, 'pg' => $i)) . "'>$i</a> ";
79b57b18
AA
2531 }
2532 $startip = $startip + $page * $maxperpage;
2533 $endip = min ($startip + $maxperpage - 1, $endip);
2534 }
2535
446c25c3 2536 echo $rendered_pager;
beb9e88a 2537 echo "<table class='widetable' border=0 cellspacing=0 cellpadding=5 align='center' width='100%'>\n";
e673ee24
DO
2538 echo "<tr><th>Address</th><th>Name</th><th>Allocation</th></tr>\n";
2539
b2035dca 2540 for ($ip = $startip; $ip <= $endip; $ip++) :
00276508
AA
2541 $dottedquad = ip_long2quad($ip);
2542 $secondstyle = 'tdleft' . (isset ($hl_ip) && $hl_ip == $ip ? ' port_highlight' : '');
b2035dca 2543 if (!isset ($range['addrlist'][$ip]))
e673ee24 2544 {
a8dc2982
AA
2545 echo "<tr><td class=tdleft><a class='ancor' name='ip-$dottedquad' href='" . makeHref(array('page'=>'ipaddress', 'ip' => $dottedquad)) . "'>$dottedquad</a></td>";
2546 echo "<td class='rsv-port ${secondstyle}'><span class='rsvtext'></span></td><td class='${secondstyle}'>&nbsp;</td></tr>\n";
b2035dca
DO
2547 continue;
2548 }
b2035dca 2549 $addr = $range['addrlist'][$ip];
68c91b9c
AA
2550 // render IP change history
2551 $title = '';
2552 $history_class = '';
2553 if (isset ($addr['last_log']))
2554 {
2555 $title = ' title="' . htmlspecialchars ($addr['last_log']['user'] . ', ' . formatAge ($addr['last_log']['time']) , ENT_QUOTES) . '"';
2556 $history_class = 'hover-history underline';
2557 }
2d318652 2558 echo "<tr class='${addr['class']}'>";
68c91b9c 2559 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
2560 echo "<td class='${secondstyle} " .
2561 (empty ($addr['allocs']) || !empty ($addr['name']) ? 'rsv-port' : '') .
2562 "'><span class='rsvtext'>${addr['name']}</span></td><td class='${secondstyle}'>";
b2035dca 2563 $delim = '';
b2035dca
DO
2564 if ( $addr['reserved'] == 'yes')
2565 {
2d318652 2566 echo "<strong>RESERVED</strong> ";
b2035dca
DO
2567 $delim = '; ';
2568 }
212b565a 2569 foreach ($addr['allocs'] as $ref)
b2035dca 2570 {
beb9e88a 2571 echo $delim . $aac2[$ref['type']];
68c91b9c 2572 echo "<a href='".makeHref(array('page'=>'object', 'object_id'=>$ref['object_id'], 'tab' => 'default', 'hl_ipv4_addr'=>$addr['ip']))."'>";
59a83bd8 2573 echo $ref['name'] . (!strlen ($ref['name']) ? '' : '@');
b2035dca
DO
2574 echo "${ref['object_name']}</a>";
2575 $delim = '; ';
2576 }
2577 if ($delim != '')
e0d6e38e 2578 $delim = '<br>';
212b565a
AA
2579 foreach ($addr['vslist'] as $vs_id)
2580 {
2581 $vs = spotEntity ('ipv4vs', $vs_id);
2582 echo "${delim}<a href='".makeHref(array('page'=>'ipv4vs', 'vs_id'=>$vs['id']))."'>";
2583 echo "${vs['name']}:${vs['vport']}/${vs['proto']}</a>&rarr;";
2584 $delim = '<br>';
2585 }
2586 foreach ($addr['rsplist'] as $rsp_id)
2587 {
2588 $rsp = spotEntity ('ipv4rspool', $rsp_id);
2589 echo "${delim}&rarr;<a href='".makeHref(array('page'=>'ipv4rspool', 'pool_id'=>$rsp['id']))."'>";
2590 echo "${rsp['name']}</a>";
2591 $delim = '<br>';
2592 }
b2035dca
DO
2593 echo "</td></tr>\n";
2594 endfor;
2727c7df 2595 // end of iteration
a8dc2982
AA
2596 if (permitted (NULL, NULL, 'set_reserve_comment'))
2597 addJS ('js/inplace-edit.js');
e673ee24
DO
2598
2599 echo "</table>";
446c25c3
AA
2600 if (! empty ($rendered_pager))
2601 echo '<p>' . $rendered_pager . '</p>';
2602
2034d968
DO
2603 finishPortlet();
2604 echo "</td></tr></table>\n";
e673ee24
DO
2605}
2606
21ee3351
AA
2607// based on renderIPv4Network
2608function renderIPv6Network ($id)
2609{
2610 $range = spotEntity ('ipv6net', $id);
2611 amplifyCell ($range);
2612 loadIPv6AddrList ($range);
2613 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
2614 echo "<tr><td colspan=2 align=center><h1>${range['ip']}/${range['mask']}</h1><h2>";
2615 echo htmlspecialchars ($range['name'], ENT_QUOTES, 'UTF-8') . "</h2></td></tr>\n";
2616
2617 echo "<tr><td class=pcleft width='50%'>";
21ee3351 2618
646272be
AA
2619 // render summary portlet
2620 $summary = array();
2621 $summary['%% used'] = formatIPv6NetUsage (count ($range['addrlist']), $range['mask']);
21ee3351
AA
2622 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2623 {
2624 // Build a backtrace from all parent networks.
2625 $backtrace = array();
2626 $current = $range;
2627 while ($current['parent_id'])
2628 {
2629 $current = spotEntity ('ipv6net', $current['parent_id']);
2630 $backtrace[] = $current;
2631 }
2632 $arrows = count ($backtrace);
2633 foreach (array_reverse ($backtrace) as $ainfo)
2634 {
646272be 2635 $name = '';
21ee3351 2636 for ($i = 0; $i < $arrows; $i++)
646272be 2637 $name .= '&uarr;';
21ee3351 2638 $arrows--;
646272be 2639 $summary[] = array ($name, getOutputOf ('renderCell', $ainfo));
21ee3351 2640 }
646272be 2641 $summary[] = array ('&rarr;', getOutputOf ('renderCell', $range));
21ee3351
AA
2642 // FIXME: get and display nested networks
2643 }
2644
2645 foreach ($range['8021q'] as $item)
2646 {
2647 $vlaninfo = getVLANInfo ($item['domain_id'] . '-' . $item['vlan_id']);
646272be 2648 $summary[] = array ('VLAN:', '<a href="' . makeHref (array ('page' => 'vlan', 'vlan_ck' => $vlaninfo['vlan_ck'])) . '">' . formatVLANName ($vlaninfo, 'markup long') . '</a>');
21ee3351
AA
2649 }
2650 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes' and count ($routers = findRouters ($range['addrlist'])))
2651 {
646272be
AA
2652 $summary['Routed by'] = '';
2653 foreach ($routers as $rtr)
2654 $summary['Routed by'] .= getOutputOf ('renderRouterCell', $rtr['addr'], $rtr['iface'], spotEntity ('object', $rtr['id']));
21ee3351 2655 }
646272be
AA
2656 $summary['tags'] = '';
2657 renderEntitySummary ($range, 'summary', $summary);
21ee3351
AA
2658
2659 if (strlen ($range['comment']))
2660 {
2661 startPortlet ('Comment');
2662 echo '<div class=commentblock>' . string_insert_hrefs (htmlspecialchars ($range['comment'], ENT_QUOTES, 'UTF-8')) . '</div>';
2663 finishPortlet ();
2664 }
2665
2666 renderFilesPortlet ('ipv6net', $id);
2667 echo "</td>\n";
2668
2669 // render address list
2670 echo "<td class=pcright>";
2671 startPortlet ('details');
2672 renderIPv6NetworkAddresses ($range);
2673 finishPortlet();
2674 echo "</td></tr></table>\n";
2675}
2676
2677// Used solely by renderSeparator
2678function renderEmptyIPv6 ($ip, $hl_ip)
2679{
2680 $class = 'tdleft';
2681 if (isset ($hl_ip) && $ip == $hl_ip)
2682 $class .= ' port_highlight';
2683 $fmt = $ip->format();
a8dc2982
AA
2684 echo "<tr><td class=tdleft><a class='ancor' name='ip-$fmt' href='" . makeHref (array ('page' => 'ipv6address', 'ip' => $fmt)) . "'>" . $fmt;
2685 echo "</a></td><td class='${class} rsv-port'><span class='rsvtext'></span></td><td class='${class}'>&nbsp;</td></tr>\n";
21ee3351
AA
2686}
2687
2688// Renders empty table line to shrink empty IPv6 address ranges.
2689// If the range consists of single address, renders the address instead of empty line.
2690// Renders address $hl_ip inside the range.
2691// Used solely by renderIPv6NetworkAddresses
2692function renderSeparator ($first, $after, $hl_ip)
2693{
2694 $self = __FUNCTION__;
522b6f90 2695 if (strcmp ($first->getBin(), $after->getBin()) >= 0)
21ee3351
AA
2696 return;
2697 if ($first->next() == $after)
2698 renderEmptyIPv6 ($first, $hl_ip);
522b6f90 2699 elseif (isset ($hl_ip) && strcmp ($hl_ip->getBin(), $first->getBin()) >= 0 && strcmp ($hl_ip->getBin(), $after->getBin()) < 0)
21ee3351
AA
2700 { // $hl_ip is inside the range $first - ($after-1)
2701 $self ($first, $hl_ip, $hl_ip);
2702 renderEmptyIPv6 ($hl_ip, $hl_ip);
2703 $self ($hl_ip->next(), $after, $hl_ip);
2704 }
2705 else
2706 echo "<tr><td colspan=3 class=tdleft></td></tr>\n";
2707}
2708
2709// calculates page number which contains given $ip (used by renderIPv6NetworkAddresses)
2710function getPageNumOfIPv6 ($list, $ip, $maxperpage)
2711{
2712 if (intval ($maxperpage) <= 0 || count ($list) <= $maxperpage)
2713 return 0;
522b6f90 2714 $bin_ip = $ip->getBin();
21ee3351
AA
2715 $keys = array_keys ($list);
2716 for ($i = 1; $i <= count ($keys); $i++)
2717 if (strcmp ($keys[$i-1], $bin_ip) >= 0)
2718 return intval ($i / $maxperpage);
2719 return intval (count ($list) / $maxperpage);
2720}
2721
2722function renderIPv6NetworkAddresses ($netinfo)
2723{
2724 global $pageno, $tabno, $aac2;
2725 echo "<table class='widetable' border=0 cellspacing=0 cellpadding=5 align='center' width='100%'>\n";
2726 echo "<tr><th>Address</th><th>Name</th><th>Allocation</th></tr>\n";
2727
2728 $hl_ip = new IPv6Address;
2729 if (! isset ($_REQUEST['hl_ipv6_addr']) || ! $hl_ip->parse ($_REQUEST['hl_ipv6_addr']))
2730 $hl_ip = NULL;
00276508 2731 else
65e557dd 2732 addAutoScrollScript ('ip-' . $hl_ip->format());
21ee3351
AA
2733
2734 $prev_ip = $netinfo['ip_bin']; // really this is the next to previosly seen ip.
2735 $addresses = $netinfo['addrlist'];
2736 ksort ($addresses);
2737
2738 // pager
2739 $maxperpage = getConfigVar ('IPV4_ADDRS_PER_PAGE');
2740 if (count ($addresses) > $maxperpage && $maxperpage > 0)
2741 {
2742 $page = isset ($_REQUEST['pg']) ? $_REQUEST['pg'] : (isset ($hl_ip) ? getPageNumOfIPv6 ($addresses, $hl_ip, $maxperpage) : 0);
2743 $numpages = ceil (count ($addresses) / $maxperpage);
2744 echo "<center><h3>$numpages pages:</h3>";
2745 for ($i=0; $i<$numpages; $i++)
2746 {
2747 if ($i == $page)
2748 echo "<b>$i</b> ";
2749 else
2750 echo "<a href='" . makeHref (array ('page' => $pageno, 'tab' => $tabno, 'id' => $netinfo['id'], 'pg' => $i)) . "'>$i</a> ";
2751 }
2752 echo "</center>";
2753 }
2754
2755 $i = 0;
2756 $interruped = FALSE;
2757 foreach ($addresses as $bin_ip => $addr)
2758 {
2759 if (isset ($page))
2760 {
2761 ++$i;
2762 if ($i <= $maxperpage * $page)
2763 continue;
2764 elseif ($i > $maxperpage * ($page + 1))
2765 {
2766 $interruped = TRUE;
2767 break;
2768 }
2769 }
2770
2771 $ipv6 = new IPv6Address ($bin_ip);
2772 if ($ipv6 != $prev_ip)
2773 renderSeparator ($prev_ip, $ipv6, $hl_ip);
2774 $prev_ip = $ipv6->next();
2775
2776 $secondstyle = 'tdleft';
2777 if (isset ($hl_ip) && $hl_ip == $ipv6)
2778 $secondstyle .= ' port_highlight';
2779 echo "<tr class='${addr['class']}'>";
a8dc2982
AA
2780 echo "<td class=tdleft><a class='ancor' name='ip-${addr['ip']}' href='" . makeHref (array ('page' => 'ipv6address', 'ip' => $addr['ip'])) . "'>${addr['ip']}</a></td>";
2781 echo "<td class='${secondstyle} " .
2782 (empty ($addr['allocs']) || !empty ($addr['name']) ? 'rsv-port' : '') .
2783 "'><span class='rsvtext'>${addr['name']}</span></td><td class='${secondstyle}'>";
21ee3351
AA
2784 $delim = '';
2785 $prologue = '';
2786 if ( $addr['reserved'] == 'yes')
2787 {
2788 echo "<strong>RESERVED</strong> ";
2789 $delim = '; ';
2790 }
2791 foreach ($addr['allocs'] as $ref)
2792 {
2793 echo $delim . $aac2[$ref['type']];
2794 echo "<a href='" . makeHref (array ('page' => 'object', 'object_id' => $ref['object_id'], 'hl_ipv6_addr' => $addr['ip'])) . "'>";
2795 echo $ref['name'] . (!strlen ($ref['name']) ? '' : '@');
2796 echo "${ref['object_name']}</a>";
2797 $delim = '; ';
2798 }
2799 if ($delim != '')
2800 {
2801 $delim = '';
2802 $prologue = '<br>';
2803 }
2804 echo "</td></tr>\n";
2805 }
2806 if (! $interruped)
2807 renderSeparator ($prev_ip, $netinfo['ip_bin']->get_last_subnet_address ($netinfo['mask'])->next(), $hl_ip);
2808 if (isset ($page))
2809 { // bottom pager
2810 echo "<tr><td colspan=3>";
2811 if ($page > 0)
2812 echo "<a href='" . makeHref (array ('page' => $pageno, 'tab' => $tabno, 'id' => $netinfo['id'], 'pg' => $page - 1)) . "'><< prev</a> ";
2813 if ($page < $numpages - 1)
2814 echo "<a href='" . makeHref (array ('page' => $pageno, 'tab' => $tabno, 'id' => $netinfo['id'], 'pg' => $page + 1)) . "'>next >></a> ";
2815 echo "</td></tr>";
2816 }
2817 echo "</table>";
a8dc2982
AA
2818 if (permitted (NULL, NULL, 'set_reserve_comment'))
2819 addJS ('js/inplace-edit.js');
21ee3351
AA
2820}
2821
2822function renderIPNetworkProperties ($id)
e673ee24 2823{
21ee3351
AA
2824 global $pageno;
2825 $netdata = spotEntity ($pageno, $id);
53ef3908 2826 echo "<center><h1>${netdata['ip']}/${netdata['mask']}</h1></center>\n";
e673ee24 2827 echo "<table border=0 cellpadding=10 cellpadding=1 align='center'>\n";
7056988c 2828 printOpFormIntro ('editRange');
99ab184f
DO
2829 echo '<tr><td class=tdright><label for=nameinput>Name:</label></td>';
2830 echo "<td class=tdleft><input type=text name=name id=nameinput size=80 maxlength=255 value='";
2831 echo htmlspecialchars ($netdata['name'], ENT_QUOTES, 'UTF-8') . "'></tr>";
2832 echo '<tr><td class=tdright><label for=commentinput>Comment:</label></td>';
2833 echo "<td class=tdleft><textarea name=comment id=commentinput cols=80 rows=25>\n";
2834 echo htmlspecialchars ($netdata['comment'], ENT_QUOTES, 'UTF-8') . "</textarea></tr>";
53ef3908
DO
2835 echo "<tr><td colspan=2 class=tdcenter>";
2836 printImageHREF ('SAVE', 'Save changes', TRUE);
2837 echo "</td></form></tr></table>\n";
93a49e5b
AA
2838
2839 echo '<center>';
2840 if (! isIPNetworkEmpty ($netdata))
2841 echo getOpLink (NULL, 'delete this prefix', 'nodestroy', 'There are ' . count ($netdata['addrlist']) . ' allocations inside');
2842 else
2843 echo getOpLink (array('op'=>'del','id'=>$id), 'delete this prefix', 'destroy');
2844 echo '</center>';
e673ee24
DO
2845}
2846
21ee3351 2847function renderIPAddress ($dottedquad)
e673ee24 2848{
46098972 2849 global $aat, $nextorder;
21ee3351 2850 $address = getIPAddress ($dottedquad);
68225375 2851 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
21ee3351 2852 echo "<tr><td colspan=2 align=center><h1>${address['ip']}</h1></td></tr>\n";
e673ee24 2853
68225375 2854 echo "<tr><td class=pcleft>";
defd92d8
AA
2855
2856 $summary = array();
423c4216 2857 if (strlen ($address['name']))
defd92d8
AA
2858 $summary['Comment'] = $address['name'];
2859 $summary['Reserved'] = $address['reserved'];
2860 $summary['Allocations'] = count ($address['allocs']);
21ee3351
AA
2861 if ($address['version'] == 4)
2862 {
defd92d8
AA
2863 $summary['Originated NAT connections'] = count ($address['outpf']);
2864 $summary['Arriving NAT connections'] = count ($address['inpf']);
21ee3351 2865 }
defd92d8 2866 renderEntitySummary ($address, 'summary', $summary);
212b565a
AA
2867
2868 // render SLB portlet
2869 if ($address['version'] == 4 and (! empty ($address['vslist']) or ! empty ($address['rsplist'])))
2870 {
2871 startPortlet ("");
2872 if (! empty ($address['vslist']))
2873 {
2874 printf ("<h2>virtual services (%d):</h2>", count ($address['vslist']));
2875 foreach ($address['vslist'] as $vs_id)
2876 renderSLBEntityCell (spotEntity ('ipv4vs', $vs_id));
2877 }
2878
2879 if (! empty ($address['rsplist']))
2880 {
2881 printf ("<h2>RS pools (%d):</h2>", count ($address['rsplist']));
2882 foreach ($address['rsplist'] as $rsp_id)
2883 renderSLBEntityCell (spotEntity ('ipv4rspool', $rsp_id));
2884 }
2885 finishPortlet();
2886 }
68225375 2887 echo "</td>\n";
e673ee24 2888
68225375 2889 echo "<td class=pcright>";
defd92d8 2890 if (isset ($address['class']) and ! empty ($address['allocs']))
59bebe2b 2891 {
8e700dd1 2892 startPortlet ('allocations');
2d318652
DO
2893 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2894 echo "<tr><th>object</th><th>OS interface</th><th>allocation type</th></tr>\n";
2895 $class = $address['class'];
2896 // render all allocation records for this address the same way
2d318652 2897 foreach ($address['allocs'] as $bond)
59bebe2b 2898 {
8e700dd1
DO
2899 if (isset ($_REQUEST['hl_object_id']) and $_REQUEST['hl_object_id'] == $bond['object_id'])
2900 $secondclass = 'tdleft port_highlight';
2901 else
2902 $secondclass = 'tdleft';
68c91b9c 2903 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
2904 echo $aat[$bond['type']];
2905 echo "</strong></td></tr>\n";
59bebe2b
DO
2906 }
2907 echo "</table><br><br>";
2908 finishPortlet();
2909 }
e673ee24 2910
defd92d8
AA
2911 if ($address['version'] == 4)
2912 renderSLBTriplets ($address);
5fe1ed76 2913
21ee3351 2914 if (! empty ($address['outpf']))
68225375 2915 {
105a3bc8 2916 startPortlet ('departing NAT rules');
2d318652 2917 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
105a3bc8
DO
2918 echo "<tr><th>proto</th><th>from</th><th>to</th><th>comment</th></tr>\n";
2919 foreach ($address['outpf'] as $rule)
b62ff880 2920 echo "<tr><td>${rule['proto']}</td><td>${rule['localip']}:${rule['localport']}</td><td>${rule['remoteip']}:${rule['remoteport']}</td><td>${rule['description']}</td></tr>";
105a3bc8 2921 echo "</table>";
68225375
DO
2922 finishPortlet();
2923 }
105a3bc8 2924
21ee3351 2925 if (! empty ($address['inpf']))
105a3bc8
DO
2926 {
2927 startPortlet ('arriving NAT rules');
2d318652 2928 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
105a3bc8
DO
2929 echo "<tr><th>proto</th><th>from</th><th>to</th><th>comment</th></tr>\n";
2930 foreach ($address['inpf'] as $rule)
b62ff880 2931 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
2932 echo "</table>";
2933 finishPortlet();
2934 }
2935
68225375
DO
2936 echo "</td></tr>";
2937 echo "</table>\n";
e673ee24
DO
2938}
2939
21ee3351 2940function renderIPAddressProperties ($dottedquad)
e673ee24 2941{
21ee3351
AA
2942 $address = getIPAddress ($dottedquad);
2943 echo "<center><h1>${address['ip']}</h1></center>\n";
7056988c 2944
1fbc9fd6 2945 startPortlet ('update');
e673ee24 2946 echo "<table border=0 cellpadding=10 cellpadding=1 align='center'>\n";
7056988c 2947 printOpFormIntro ('editAddress');
2d318652
DO
2948 echo "<tr><td class='tdright'>Name:</td><td class='tdleft'><input type=text name=name size=20 value='${address['name']}'></tr>";
2949 echo "<td class='tdright'>Reserved:</td><td class='tdleft'><input type=checkbox name=reserved size=20 ";
2950 echo ($address['reserved']=='yes') ? 'checked' : '';
f3d274bf 2951 echo "></tr><tr><td class=tdleft>";
53ef3908 2952 printImageHREF ('SAVE', 'Save changes', TRUE);
f3d274bf 2953 echo "</td></form><td class=tdright>";
59a83bd8 2954 if (!strlen ($address['name']) and $address['reserved'] == 'no')
f3d274bf
DO
2955 printImageHREF ('CLEAR gray');
2956 else
2957 {
2958 printOpFormIntro ('editAddress', array ('name' => '', 'reserved' => ''));
2959 printImageHREF ('CLEAR', 'Release', TRUE);
2960 echo "</form>";
2961 }
2962 echo "</td></tr></table>\n";
1fbc9fd6 2963 finishPortlet();
e673ee24
DO
2964}
2965
21ee3351 2966function renderIPAddressAllocations ($dottedquad)
e673ee24 2967{
21ee3351 2968 function printNewItemTR ($opname)
39b4abd0
DO
2969 {
2970 global $aat;
21ee3351 2971 printOpFormIntro ($opname);
39b4abd0 2972 echo "<tr><td>";
9318d2ef 2973 printImageHREF ('add', 'allocate', TRUE);
8d4f7d18 2974 echo "</td><td>";
31babb65 2975 printSelect (getNarrowObjectList ('IPV4OBJ_LISTSRC'), array ('name' => 'object_id', 'tabindex' => 100));
8d4f7d18 2976 echo "</td><td><input type=text tabindex=101 name=bond_name size=10></td><td>";
01abf1de 2977 printSelect ($aat, array ('name' => 'bond_type', 'tabindex' => 102, 'regular'));
9318d2ef 2978 echo "</td><td>";
f5ff50f5 2979 printImageHREF ('add', 'allocate', TRUE, 103);
9318d2ef 2980 echo "</td></form></tr>";
39b4abd0 2981 }
b82cce3f 2982 global $aat;
e673ee24 2983
21ee3351
AA
2984 $address = getIPAddress ($dottedquad);
2985 $opname = $address['version'] == 6 ? 'addIPv6Allocation' : 'addIPv4Allocation';
2986 echo "<center><h1>${address['ip']}</h1></center>\n";
105a3bc8 2987 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
2d318652 2988 echo "<tr><th>&nbsp;</th><th>object</th><th>OS interface</th><th>allocation type</th><th>&nbsp;</th></tr>\n";
e673ee24 2989
39b4abd0 2990 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
21ee3351 2991 printNewItemTR($opname);
f74d96c6 2992 if (isset ($address['class']))
e673ee24 2993 {
f74d96c6
DO
2994 $class = $address['class'];
2995 if ($address['reserved'] == 'yes')
2996 echo "<tr class='${class}'><td colspan=3>&nbsp;</td><td class=tdleft><strong>RESERVED</strong></td><td>&nbsp;</td></tr>";
2997 foreach ($address['allocs'] as $bond)
2998 {
2999 echo "<tr class='$class'>";
21ee3351
AA
3000 printOpFormIntro
3001 (
3002 $address['version'] == 6 ? 'updIPv6Allocation' : 'updIPv4Allocation',
3003 array ('object_id' => $bond['object_id'])
3004 );
3005 echo "<td><a href='"
3006 . makeHrefProcess
3007 (
3008 array
3009 (
3010 'op' => $address['version'] == 6 ? 'delIPv6Allocation' : 'delIPv4Allocation',
3011 'ip' => $address['ip'],
3012 'object_id' => $bond['object_id']
3013 )
3014 )
3015 . "'>";
f74d96c6
DO
3016 printImageHREF ('delete', 'Unallocate address');
3017 echo "</a></td>";
21ee3351 3018 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 3019 echo "<td><input type='text' name='bond_name' value='${bond['name']}' size=10></td><td>";
cd3775e9 3020 printSelect ($aat, array ('name' => 'bond_type'), $bond['type']);
f74d96c6
DO
3021 echo "</td><td>";
3022 printImageHREF ('save', 'Save changes', TRUE);
3023 echo "</td></form></tr>\n";
3024 }
e673ee24 3025 }
39b4abd0 3026 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
21ee3351 3027 printNewItemTR($opname);
e673ee24 3028 echo "</table><br><br>";
e673ee24
DO
3029}
3030
7e1db771 3031function renderNATv4ForObject ($object_id)
e673ee24 3032{
9318d2ef
DO
3033 function printNewItemTR ($alloclist)
3034 {
9318d2ef
DO
3035 printOpFormIntro ('addNATv4Rule');
3036 echo "<tr align='center'><td>";
3037 printImageHREF ('add', 'Add new NAT rule', TRUE);
3038 echo '</td><td>';
cd3775e9 3039 printSelect (array ('TCP' => 'TCP', 'UDP' => 'UDP'), array ('name' => 'proto'));
9318d2ef
DO
3040 echo "<select name='localip' tabindex=1>";
3041
3042 foreach ($alloclist as $dottedquad => $alloc)
3043 {
43eb71f1
DO
3044 $name = (!isset ($alloc['addrinfo']['name']) or !strlen ($alloc['addrinfo']['name'])) ? '' : (' (' . niftyString ($alloc['addrinfo']['name']) . ')');
3045 $osif = (!isset ($alloc['osif']) or !strlen ($alloc['osif'])) ? '' : ($alloc['osif'] . ': ');
9318d2ef
DO
3046 echo "<option value='${dottedquad}'>${osif}${dottedquad}${name}</option>";
3047 }
3048
3049 echo "</select>:<input type='text' name='localport' size='4' tabindex=2></td>";
3050 echo "<td><input type='text' name='remoteip' id='remoteip' size='10' tabindex=3>";
39106006
DO
3051 echo "<a href='javascript:;' onclick='window.open(\"" . makeHrefForHelper ('inet4list');
3052 echo "\", \"findobjectip\", \"height=700, width=400, location=no, menubar=no, resizable=yes, scrollbars=no, status=no, titlebar=no, toolbar=no\");'>";
9318d2ef
DO
3053 printImageHREF ('find', 'Find object');
3054 echo "</a>";
3055 echo ":<input type='text' name='remoteport' size='4' tabindex=4></td><td></td>";
3056 echo "<td colspan=1><input type='text' name='description' size='20' tabindex=5></td><td>";
f5ff50f5 3057 printImageHREF ('add', 'Add new NAT rule', TRUE, 6);
9318d2ef
DO
3058 echo "</td></tr></form>";
3059 }
e673ee24 3060
94fe6370
DO
3061 $focus = spotEntity ('object', $object_id);
3062 amplifyCell ($focus);
f28fbe8b 3063 echo "<center><h2>locally performed NAT</h2></center>";
e673ee24 3064
105a3bc8 3065 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
d54b9495 3066 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 3067
9318d2ef 3068 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
94fe6370
DO
3069 printNewItemTR ($focus['ipv4']);
3070 foreach ($focus['nat4']['out'] as $pf)
e673ee24 3071 {
2c817354
DO
3072 $class = 'trerror';
3073 $osif = '';
94fe6370 3074 if (isset ($focus['ipv4'][$pf['localip']]))
2c817354 3075 {
94fe6370
DO
3076 $class = $focus['ipv4'][$pf['localip']]['addrinfo']['class'];
3077 $osif = $focus['ipv4'][$pf['localip']]['osif'] . ': ';
2c817354 3078 }
e673ee24
DO
3079
3080 echo "<tr class='$class'>";
4fbb5a00
DY
3081 echo "<td><a href='".
3082 makeHrefProcess(array(
3083 'op'=>'delNATv4Rule',
3084 'localip'=>$pf['localip'],
3085 'localport'=>$pf['localport'],
3086 'remoteip'=>$pf['remoteip'],
3087 'remoteport'=>$pf['remoteport'],
3088 'proto'=>$pf['proto'],
3089 'object_id'=>$object_id)).
3090 "'>";
4de22e7e
DO
3091 printImageHREF ('delete', 'Delete NAT rule');
3092 echo "</a></td>";
4fbb5a00 3093 echo "<td>${pf['proto']}/${osif}<a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['localip']))."'>${pf['localip']}</a>:${pf['localport']}";
59a83bd8 3094 if (strlen ($pf['local_addr_name']))
f28fbe8b
DO
3095 echo ' (' . $pf['local_addr_name'] . ')';
3096 echo "</td>";
4fbb5a00 3097 echo "<td><a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['remoteip']))."'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
e673ee24 3098
53ef3908 3099 $address = getIPv4Address ($pf['remoteip']);
e673ee24
DO
3100
3101 echo "<td class='description'>";
53ef3908
DO
3102 if (count ($address['allocs']))
3103 foreach ($address['allocs'] as $bond)
4fbb5a00 3104 echo "<a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$bond['object_id']))."'>${bond['object_name']}(${bond['name']})</a> ";
59a83bd8 3105 elseif (strlen ($pf['remote_addr_name']))
f28fbe8b 3106 echo '(' . $pf['remote_addr_name'] . ')';
7056988c
DO
3107 printOpFormIntro
3108 (
3109 'updNATv4Rule',
3110 array
3111 (
3112 'localip' => $pf['localip'],
3113 'localport' => $pf['localport'],
3114 'remoteip' => $pf['remoteip'],
3115 'remoteport' => $pf['remoteport'],
3116 'proto' => $pf['proto']
3117 )
3118 );
3119 echo "</td><td class='description'>";
d54b9495
DO
3120 echo "<input type='text' name='description' value='${pf['description']}'></td><td>";
3121 printImageHREF ('save', 'Save changes', TRUE);
3122 echo "</td></form></tr>";
e673ee24 3123 }
9318d2ef 3124 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
94fe6370 3125 printNewItemTR ($focus['ipv4']);
e673ee24
DO
3126
3127 echo "</table><br><br>";
94fe6370
DO
3128 if (!count ($focus['nat4']))
3129 return;
e673ee24 3130
f28fbe8b 3131 echo "<center><h2>arriving NAT connections</h2></center>";
105a3bc8 3132 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
e673ee24
DO
3133 echo "<tr><th></th><th>Source</th><th>Source objects</th><th>Target</th><th>Description</th></tr>\n";
3134
94fe6370 3135 foreach ($focus['nat4']['in'] as $pf)
e673ee24 3136 {
4fbb5a00
DY
3137 echo "<tr><td><a href='".
3138 makeHrefProcess(array(
3139 'op'=>'delNATv4Rule',
3140 'localip'=>$pf['localip'],
3141 'localport'=>$pf['localport'],
3142 'remoteip'=>$pf['remoteip'],
3143 'remoteport'=>$pf['remoteport'],
3144 'proto'=>$pf['proto'],
3145 'object_id'=>$pf['object_id']
3146 )).
3147 "'>";
4de22e7e
DO
3148 printImageHREF ('delete', 'Delete NAT rule');
3149 echo "</a></td>";
4fbb5a00
DY
3150 echo "<td>${pf['proto']}/<a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['localip']))."'>${pf['localip']}</a>:${pf['localport']}</td>";
3151 echo "<td class='description'><a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$pf['object_id']))."'>${pf['object_name']}</a>";
3152 echo "</td><td><a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['remoteip']))."'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
e673ee24
DO
3153 echo "<td class='description'>${pf['description']}</td></tr>";
3154 }
3155
e673ee24 3156 echo "</table><br><br>";
e673ee24
DO
3157}
3158
e673ee24
DO
3159function renderAddMultipleObjectsForm ()
3160{
9b8174d7 3161 global $location_obj_types, $virtual_obj_types;
7fa7047a 3162 $typelist = readChapter (CHAP_OBJTYPE, 'o');
4c330a14 3163 $typelist[0] = 'select type...';
7fa7047a 3164 $typelist = cookOptgroups ($typelist);
a1886a78
DO
3165 $max = getConfigVar ('MASSCOUNT');
3166 $tabindex = 100;
7f791d1d 3167
9b8174d7
AD
3168 // create a list of object types to exclude (virtual and location-related ones)
3169 $exclude_typelist = array_merge($location_obj_types, $virtual_obj_types);
3170
0682218d
AD
3171 $phys_typelist = $typelist;
3172 foreach ($phys_typelist['other'] as $key => $value)
3173 {
9b8174d7
AD
3174 // remove from list if type should be excluded
3175 if ($key > 0 && in_array($key, $exclude_typelist))
0682218d
AD
3176 unset($phys_typelist['other'][$key]);
3177 }
2b787762 3178 startPortlet ('Physical objects');
42d73cbf 3179 printOpFormIntro ('addObjects');
e673ee24 3180 echo '<table border=0 align=center>';
f60bb422 3181 echo "<tr><th>Object type</th><th>Common name</th><th>Visible label</th>";
dee24af6 3182 echo "<th>Asset tag</th><th>Tags</th></tr>\n";
9c0b0016 3183 for ($i = 0; $i < $max; $i++)
e673ee24 3184 {
7f791d1d 3185 echo '<tr><td>';
e7ade6bf 3186 // Don't employ DEFAULT_OBJECT_TYPE to avoid creating ghost records for pre-selected empty rows.
0682218d 3187 printNiftySelect ($phys_typelist, array ('name' => "${i}_object_type_id", 'tabindex' => $tabindex), 0);
e673ee24 3188 echo '</td>';
a1886a78
DO
3189 echo "<td><input type=text size=30 name=${i}_object_name tabindex=${tabindex}></td>";
3190 echo "<td><input type=text size=30 name=${i}_object_label tabindex=${tabindex}></td>";
3191 echo "<td><input type=text size=20 name=${i}_object_asset_no tabindex=${tabindex}></td>";
f60bb422
DO
3192 if ($i == 0)
3193 {
3194 echo "<td valign=top rowspan=${max}>";
a26a6ccc 3195 renderNewEntityTags ('object');
f60bb422
DO
3196 echo "</td>\n";
3197 }
e673ee24 3198 echo "</tr>\n";
a1886a78 3199 $tabindex++;
e673ee24 3200 }
216c84bb 3201 echo "<tr><td class=submit colspan=5><input type=submit name=got_fast_data value='Go!'></td></tr>\n";
e673ee24
DO
3202 echo "</form></table>\n";
3203 finishPortlet();
7f791d1d 3204
0682218d 3205 // create a list containing only virtual object types
0682218d
AD
3206 $virt_typelist = $typelist;
3207 foreach ($virt_typelist['other'] as $key => $value)
3208 {
2c2ea5f6 3209 if ($key > 0 && !in_array($key, $virtual_obj_types))
0682218d
AD
3210 unset($virt_typelist['other'][$key]);
3211 }
3212 startPortlet ('Virtual objects');
3213 printOpFormIntro ('addObjects');
3214 echo "<input type=hidden name=virtual_objects value=''>\n";
3215 echo '<table border=0 align=center>';
3216 echo "<tr><th>Object type</th><th>Common name</th><th>Tags</th></tr>\n";
3217 for ($i = 0; $i < $max; $i++)
3218 {
3219 echo '<tr><td>';
3220 // Don't employ DEFAULT_OBJECT_TYPE to avoid creating ghost records for pre-selected empty rows.
3221 printNiftySelect ($virt_typelist, array ('name' => "${i}_object_type_id", 'tabindex' => $tabindex), 0);
3222 echo '</td>';
3223 echo "<td><input type=text size=30 name=${i}_object_name tabindex=${tabindex}></td>";
3224 if ($i == 0)
3225 {
3226 echo "<td valign=top rowspan=${max}>";
3227 renderNewEntityTags ('object');
3228 echo "</td>\n";
3229 }
3230 echo "</tr>\n";
3231 $tabindex++;
3232 }
3233 echo "<tr><td class=submit colspan=5><input type=submit name=got_fast_data value='Go!'></td></tr>\n";
3234 echo "</form></table>\n";
3235 finishPortlet();
3236
f60bb422 3237 startPortlet ('Same type, same tags');
42d73cbf 3238 printOpFormIntro ('addLotOfObjects');
f60bb422
DO
3239 echo "<table border=0 align=center><tr><th>names</th><th>type</th></tr>";
3240 echo "<tr><td rowspan=3><textarea name=namelist cols=40 rows=25>\n";
f60bb422 3241 echo "</textarea></td><td valign=top>";
cd3775e9 3242 printNiftySelect ($typelist, array ('name' => 'global_type_id'), getConfigVar ('DEFAULT_OBJECT_TYPE'));
f60bb422
DO
3243 echo "</td></tr>";
3244 echo "<tr><th>Tags</th></tr>";
3245 echo "<tr><td valign=top>";
a26a6ccc 3246 renderNewEntityTags ('object');
f60bb422
DO
3247 echo "</td></tr>";
3248 echo "<tr><td colspan=2><input type=submit name=got_very_fast_data value='Go!'></td></tr></table>\n";
3249 echo "</form>\n";
7f791d1d 3250 finishPortlet();
e673ee24
DO
3251}
3252
671027eb
DO
3253function searchHandler()
3254{
e673ee24 3255 $terms = trim ($_REQUEST['q']);
59a83bd8 3256 if (!strlen ($terms))
0cc24e9a 3257 throw new InvalidRequestArgException('q', $_REQUEST['q'], 'Search string cannot be empty.');
671027eb 3258 renderSearchResults ($terms, searchEntitiesByText ($terms));
09ce7c20 3259}
25e55cab 3260
521cd29a 3261function renderSearchResults ($terms, $summary)
09ce7c20 3262{
521cd29a
AA
3263 // calculate the number of found objects
3264 $nhits = 0;
3265 foreach ($summary as $realm => $list)
3266 $nhits += count ($list);
3267
ea5fc465
DO
3268 if ($nhits == 0)
3269 echo "<center><h2>Nothing found for '${terms}'</h2></center>";
3270 elseif ($nhits == 1)
3271 {
6427286d
AA
3272 foreach ($summary as $realm => $record)