r4996 add UNIX socket support to installer
[racktables] / wwwroot / inc / interface.php
CommitLineData
b325120a 1<?php
e673ee24
DO
2/*
3*
4* This file contains frontend functions for RackTables.
5*
6*/
7
e82deb48 8require_once 'ajax-interface.php';
defd92d8 9require_once 'slb-interface.php';
65e557dd 10
9c0b0016
DO
11// Interface function's special.
12$nextorder['odd'] = 'even';
13$nextorder['even'] = 'odd';
14
52c836b1
DO
15// address allocation type
16$aat = array
17(
18 'regular' => 'Connected',
19 'virtual' => 'Loopback',
20 'shared' => 'Shared',
21 'router' => 'Router',
22);
beb9e88a 23// address allocation code, IPv4 addresses and objects view
52c836b1
DO
24$aac = array
25(
26 'regular' => '',
27 'virtual' => '<strong>L</strong>',
28 'shared' => '<strong>S</strong>',
29 'router' => '<strong>R</strong>',
30);
beb9e88a
DO
31// address allocation code, IPv4 networks view
32$aac2 = array
33(
34 'regular' => '',
35 'virtual' => '<strong>L:</strong>',
29025f8e 36 'shared' => '<strong>S:</strong>',
beb9e88a
DO
37 'router' => '<strong>R:</strong>',
38);
52c836b1 39
0dabdc53
DO
40$vtdecoder = array
41(
42 'ondemand' => '',
54b7ced3
DO
43 'compulsory' => 'P',
44# 'alien' => 'NT',
0dabdc53
DO
45);
46
47$vtoptions = array
48(
54b7ced3
DO
49 'ondemand' => 'auto',
50 'compulsory' => 'permanent',
51# 'alien' => 'never touch',
0dabdc53
DO
52);
53
e5c4506d
DO
54// This may be populated later onsite, report rendering function will use it.
55// See the $systemreport for structure.
56$localreports = array();
d6adad3e 57
9db67d95
DO
58$CodePressMap = array
59(
60 'sql' => 'sql',
61 'php' => 'php',
62 'html' => 'html',
63 'css' => 'css',
64 'js' => 'javascript',
65);
e5c4506d 66
8d4f7d18
DO
67$attrtypes = array
68(
69 'uint' => '[U] unsigned integer',
70 'float' => '[F] floating point',
71 'string' => '[S] string',
72 'dict' => '[D] dictionary record'
73);
74
a1d72d2e
AA
75$quick_links = NULL; // you can override this in your local.php, but first initialize it with getConfiguredQuickLinks()
76
77function renderQuickLinks()
78{
79 global $quick_links;
80 if (! isset ($quick_links))
81 $quick_links = getConfiguredQuickLinks();
82 echo '<ul class="qlinks">';
83 foreach ($quick_links as $link)
84 echo '<li><a href="' . $link['href'] . '">' . str_replace (' ', '&nbsp;', $link['title']) . '</a></li>';
85 echo '</ul>';
86}
87
f97df464
DO
88function renderInterfaceHTML ($pageno, $tabno, $payload)
89{
90?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
91<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
92<head><title><?php echo getTitle ($pageno); ?></title>
93<?php printPageHeaders(); ?>
94</head>
95<body>
96<table border=0 cellpadding=0 cellspacing=0 width="100%" height="100%" class="maintable">
97 <tr class="mainheader"><td>
a1d72d2e
AA
98 <?php echo getConfigVar ('enterprise') ?> RackTables <a href="http://racktables.org" title="Visit RackTables site"><?php echo CODE_VERSION ?></a><?php renderQuickLinks() ?>
99 <div style="float: right" class=greeting><a href='index.php?page=myaccount&tab=default'><?php global $remote_displayname; echo $remote_displayname ?></a> [ <a href='?logout'>logout</a> ]</div>
f97df464
DO
100 </td></tr>
101 <tr><td class="menubar">
102 <table border="0" width="100%" cellpadding="3" cellspacing="0">
103 <tr><?php showPathAndSearch ($pageno); ?></tr>
104 </table>
105 </td></tr>
106 <tr><td><?php showTabs ($pageno, $tabno); ?></td></tr>
107 <tr><td><?php showMessageOrError(); ?></td></tr>
108 <tr><td><?php echo $payload; ?></td></tr>
109</table>
110</body>
111</html>
112<?php
113}
114
e673ee24 115// Main menu.
4b680876
DO
116function renderIndexItem ($ypageno) {
117 global $page;
118 if (permitted($ypageno)) {
a1d72d2e
AA
119 $title = getPageName ($ypageno);
120 print " <td>\n";
21ee3351 121 print " <h1><a href='".makeHref(array('page'=>$ypageno))."'>".$title."<br>\n";
4b680876
DO
122 printImageHREF ($ypageno);
123 print "</a></h1>\n";
124 print " </td>\n";
125 } else {
126 print " <td>&nbsp;</td>\n";
127 }
128}
129
e673ee24
DO
130function renderIndex ()
131{
67c5c049 132 global $indexlayout;
e673ee24
DO
133?>
134<table border=0 cellpadding=0 cellspacing=0 width='100%'>
135 <tr>
136 <td>
137 <div style='text-align: center; margin: 10px; '>
a544d2c4 138 <table width='100%' cellspacing=0 cellpadding=20 class=mainmenu border=0>
4b680876 139<?php
67c5c049
DO
140foreach ($indexlayout as $row)
141{
142 echo '<tr>';
143 foreach ($row as $column)
144 if ($column === NULL)
145 echo '<td>&nbsp;</td>';
146 else
147 renderIndexItem ($column);
148 echo '</tr>';
149}
150?>
e673ee24
DO
151 </table>
152 </div>
153 </td>
154 </tr>
155</table>
b325120a 156<?php
e673ee24
DO
157}
158
f3505b35
AA
159function getRenderedAlloc ($object_id, $alloc)
160{
161 $ret = array
162 (
163 'tr_class' => '',
40c9fc94 164 'td_name_suffix' => '',
f3505b35
AA
165 'td_ip' => '',
166 'td_network' => '',
167 'td_routed_by' => '',
168 'td_peers' => '',
169 );
170 $dottedquad = $alloc['addrinfo']['ip'];
171
172 $hl_ip_addr = '';
173 if (isset ($_REQUEST['hl_ipv6_addr']))
174 {
175 if ($hl_ipv6 = assertIPv6Arg ('hl_ipv6_addr'))
176 $hl_ip_addr = $hl_ipv6->format();
177 }
178 elseif (isset ($_REQUEST['hl_ipv4_addr']))
179 $hl_ip_addr = $_REQUEST['hl_ipv4_addr'];
180 if ($hl_ip_addr)
181 addAutoScrollScript ("ip-$hl_ip_addr");
182
183 // prepare realm and network info
184 if ($alloc['addrinfo']['version'] == 6)
185 {
186 $ipv6_address = new IPv6Address();
187 $ipv6_address->parse ($dottedquad);
188 $addr_page_name = 'ipv6address';
189 if ($netid = getIPv6AddressNetworkId ($ipv6_address))
190 {
191 $netinfo = spotEntity ('ipv6net', $netid);
192 loadIPv6AddrList ($netinfo);
193 }
194 }
195 else
196 {
197 $addr_page_name = 'ipaddress';
198 if ($netid = getIPv4AddressNetworkId ($dottedquad))
199 {
200 $netinfo = spotEntity ('ipv4net', $netid);
201 loadIPv4AddrList ($netinfo);
202 }
203 }
204
205 $ret['tr_class'] = $alloc['addrinfo']['class'];
206 $td_class = 'tdleft';
207 if ($hl_ip_addr == $dottedquad)
208 $td_class .= ' port_highlight';
209
68c91b9c
AA
210 // render IP change history
211 $ip_title = '';
212 $ip_class = '';
213 if (isset ($alloc['addrinfo']['last_log']))
214 {
215 $log = $alloc['addrinfo']['last_log'];
216 $ip_title = "title='" .
217 htmlspecialchars
218 (
219 $log['user'] . ', ' . formatAge ($log['time']),
220 ENT_QUOTES
221 ) . "'";
222 $ip_class = 'hover-history underline';
223 }
224
f3505b35
AA
225 // render IP address td
226 global $aac;
227 $ret['td_ip'] = "<td class='$td_class'>";
228 if (NULL !== $netid)
68c91b9c 229 $ret['td_ip'] .= "<a name='ip-$dottedquad' class='$ip_class' $ip_title href='" .
f3505b35
AA
230 makeHref (
231 array
232 (
233 'page' => $addr_page_name,
234 'hl_object_id' => $object_id,
235 'ip' => $dottedquad,
236 )
237 ) . "'>" . $dottedquad . "</a>";
238 else
68c91b9c 239 $ret['td_ip'] .= "<span class='$ip_class' $ip_title>$dottedquad</span>";
f3505b35
AA
240 if (getConfigVar ('EXT_IPV4_VIEW') != 'yes')
241 $ret['td_ip'] .= '<small>/' . (NULL === $netid ? '??' : $netinfo['mask']) . '</small>';
242 $ret['td_ip'] .= '&nbsp;' . $aac[$alloc['type']];
243 if (strlen ($alloc['addrinfo']['name']))
244 $ret['td_ip'] .= ' (' . niftyString ($alloc['addrinfo']['name']) . ')';
245 $ret['td_ip'] .= '</td>';
246
247 // render network and routed_by tds
248 if (NULL === $netid)
249 {
250 $ret['td_network'] = "<td class='$td_class sparenetwork'>N/A</td>";
251 $ret['td_routed_by'] = $ret['td_network'];
252 }
253 else
254 {
255 $ret['td_network'] = "<td class='$td_class'>" .
256 getOutputOf ('renderCell', $netinfo) . '</td>';
257
258 // filter out self-allocation
259 $other_routers = array();
260 foreach (findRouters ($netinfo['addrlist']) as $router)
261 if ($router['id'] != $object_id)
262 $other_routers[] = $router;
263 if (count ($other_routers))
264 $ret['td_routed_by'] = getOutputOf ('printRoutersTD', $other_routers);
265 else
266 $ret['td_routed_by'] = "<td class='$td_class'>&nbsp;</td>";
267 }
268
269 // render peers td
270 $ret['td_peers'] = "<td class='$td_class'>";
271 $prefix = '';
272 if ($alloc['addrinfo']['reserved'] == 'yes')
273 {
274 $ret['td_peers'] .= $prefix . '<strong>RESERVED</strong>';
275 $prefix = '; ';
276 }
277 foreach ($alloc['addrinfo']['allocs'] as $allocpeer)
278 {
279 if ($allocpeer['object_id'] == $object_id)
280 continue;
281 $ret['td_peers'] .= $prefix . "<a href='" . makeHref (array ('page' => 'object', 'object_id' => $allocpeer['object_id'])) . "'>";
282 if (isset ($allocpeer['osif']) and strlen ($allocpeer['osif']))
283 $ret['td_peers'] .= $allocpeer['osif'] . '@';
284 $ret['td_peers'] .= $allocpeer['object_name'] . '</a>';
285 $prefix = '; ';
286 }
287 $ret['td_peers'] .= '</td>';
288
289 return $ret;
290}
291
e673ee24
DO
292function renderRackspace ()
293{
95857b5c
DO
294 $found_racks = array();
295 $rows = array();
a8efc03e 296 $cellfilter = getCellFilter();
1ebbf889 297 $rackCount = 0;
9b8174d7 298 foreach (getRows() as $row_id => $row_name) {
95857b5c
DO
299 $rackList = filterCellList (listCells ('rack', $row_id), $cellfilter['expression']);
300 $found_racks = array_merge($found_racks, $rackList);
301 $rows[] = array(
302 'row_id' => $row_id,
303 'row_name' => $row_name,
304 'racks' => $rackList
305 );
1ebbf889 306 $rackCount += count($rackList);
95857b5c 307 }
1ebbf889 308
95857b5c
DO
309 echo "<table class=objview border=0 width='100%'><tr><td class=pcleft>";
310 renderCellFilterPortlet ($cellfilter, 'rack', $found_racks);
489a7502 311 echo '</td><td class=pcright>';
1ebbf889
AA
312
313 if (! renderEmptyResults($cellfilter, 'racks', $rackCount))
e673ee24 314 {
1ebbf889
AA
315 echo '<table border=0 cellpadding=10 cellpadding=1>';
316 // generate thumb gallery
317 global $nextorder;
318 $rackwidth = getRackImageWidth();
319 // Zero value effectively disables the limit.
320 $maxPerRow = getConfigVar ('RACKS_PER_ROW');
321 $order = 'odd';
322 foreach ($rows as $row)
323 {
324 $row_id = $row['row_id'];
325 $row_name = $row['row_name'];
326 $rackList = $row['racks'];
327
328 if (!count ($rackList) and count ($cellfilter['expression']))
329 continue;
330 $rackListIdx = 0;
331 echo "<tr class=row_${order}><th class=tdleft>";
332 echo "<a href='".makeHref(array('page'=>'row', 'row_id'=>$row_id))."${cellfilter['urlextra']}'>";
333 echo "${row_name}</a></th><td><table border=0 cellspacing=5><tr>";
334 if (!count ($rackList))
335 echo "<td>(empty row)</td>";
336 else
337 foreach ($rackList as $rack)
48325652 338 {
1ebbf889
AA
339 if ($rackListIdx > 0 and $maxPerRow > 0 and $rackListIdx % $maxPerRow == 0)
340 {
341 echo '</tr></table></tr>';
342 echo "<tr class=row_${order}><th class=tdleft>${row_name} (continued)";
343 echo "</th><td><table border=0 cellspacing=5><tr>";
344 }
a3021995 345 echo "<td align=center valign=bottom><a href='".makeHref(array('page'=>'rack', 'rack_id'=>$rack['id']))."'>";
1ebbf889
AA
346 echo "<img border=0 width=${rackwidth} height=";
347 echo getRackImageHeight ($rack['height']);
348 echo " title='${rack['height']} units'";
4afb4c10 349 echo "src='?module=image&img=minirack&rack_id=${rack['id']}'>";
1ebbf889
AA
350 echo "<br>${rack['name']}</a></td>";
351 $rackListIdx++;
48325652 352 }
1ebbf889
AA
353 $order = $nextorder[$order];
354 echo "</tr></table></tr>\n";
355 }
356 echo "</table>\n";
e673ee24 357 }
489a7502 358 echo "</td></tr></table>\n";
e673ee24
DO
359}
360
345fd640
AD
361function renderRackspaceRowEditor ()
362{
363 function printNewItemTR ()
364 {
365 printOpFormIntro ('addRow');
1f02e311 366 echo "<input type=hidden name=objtype_id value=1561>\n";
7be51fea
DO
367 echo "<tr><td>";
368 printImageHREF ('create', 'Add new row', TRUE);
369 echo "</td><td><input type=text name=name tabindex=100></td><td>";
345fd640 370 printImageHREF ('create', 'Add new row', TRUE, 101);
7be51fea 371 echo "</td></tr></form>";
345fd640 372 }
d732e47e 373 startPortlet ('Rows');
345fd640 374 echo "<table border=0 cellspacing=0 cellpadding=5 align=center class=widetable>\n";
7be51fea 375 echo "<tr><th>&nbsp;</th><th>Name</th><th>&nbsp;</th></tr>\n";
345fd640
AD
376 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
377 printNewItemTR();
9b8174d7 378 foreach (getRows() as $row_id => $row_name)
345fd640 379 {
7be51fea 380 echo "<tr><td>";
a8efc03e 381 if ($rc = count (listCells ('rack', $row_id)))
6c18dd08 382 printImageHREF ('nodestroy', "${rc} rack(s) here");
7be51fea 383 else
5af82683 384 {
1f02e311 385 echo "<a href=\"".makeHrefProcess(array('op'=>'deleteRow', 'row_id'=>$row_id))."\">";
7be51fea 386 printImageHREF ('destroy', 'Delete row');
5af82683
DY
387 echo "</a>";
388 }
c40666f5
DO
389 printOpFormIntro ('updateRow', array ('row_id' => $row_id));
390 echo "</td><td><input type=text name=name value='${row_name}'></td><td>";
7be51fea
DO
391 printImageHREF ('save', 'Save changes', TRUE);
392 echo "</form></td></tr>\n";
345fd640
AD
393 }
394 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
395 printNewItemTR();
396 echo "</table><br>\n";
397 finishPortlet();
398}
399
7e1db771 400function renderRow ($row_id)
e673ee24 401{
9b8174d7 402 $rowInfo = getRowInfo ($row_id);
a8efc03e
DO
403 $cellfilter = getCellFilter();
404 $rackList = filterCellList (listCells ('rack', $row_id), $cellfilter['expression']);
e673ee24
DO
405 // Main layout starts.
406 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
407
408 // Left portlet with row information.
409 echo "<tr><td class=pcleft>";
a8ce7234 410 startPortlet ($rowInfo['name']);
e673ee24 411 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
5af82683
DY
412 echo "<tr><th width='50%' class=tdright>Racks:</th><td class=tdleft>${rowInfo['count']}</td></tr>\n";
413 echo "<tr><th width='50%' class=tdright>Units:</th><td class=tdleft>${rowInfo['sum']}</td></tr>\n";
9b8174d7
AD
414 echo "<tr><th width='50%' class=tdright>% used:</th><td class=tdleft>";
415 renderProgressBar (getRSUforRow ($rackList));
114e50af 416 echo "</td></tr>\n";
e673ee24
DO
417 echo "</table><br>\n";
418 finishPortlet();
95857b5c 419 renderCellFilterPortlet ($cellfilter, 'rack', $rackList, 'row_id', $row_id);
e673ee24 420
48325652 421 echo "</td><td class=pcright>";
e673ee24 422
4fbb5a00 423 global $nextorder;
d5157018 424 $rackwidth = getRackImageWidth() * getConfigVar ('ROW_SCALE');
f5883ec1
DO
425 // Maximum number of racks per row is proportionally less, but at least 1.
426 $maxPerRow = max (floor (getConfigVar ('RACKS_PER_ROW') / getConfigVar ('ROW_SCALE')), 1);
427 $rackListIdx = 0;
e673ee24
DO
428 $order = 'odd';
429 startPortlet ('Racks');
430 echo "<table border=0 cellspacing=5 align='center'><tr>";
64b95774 431 foreach ($rackList as $rack)
e673ee24 432 {
f5883ec1
DO
433 if ($rackListIdx % $maxPerRow == 0)
434 {
435 if ($rackListIdx > 0)
436 echo '</tr>';
437 echo '<tr>';
438 }
9b8174d7 439 $class = ($rack['has_problems'] == 'yes') ? 'error' : $order;
d69e5d6f 440 echo "<td align=center valign=bottom class=row_${class}><a href='".makeHref(array('page'=>'rack', 'rack_id'=>$rack['id']))."'>";
d5157018 441 echo "<img border=0 width=${rackwidth} height=" . (getRackImageHeight ($rack['height']) * getConfigVar ('ROW_SCALE'));
e673ee24 442 echo " title='${rack['height']} units'";
4afb4c10 443 echo "src='?module=image&img=minirack&rack_id=${rack['id']}'>";
e673ee24
DO
444 echo "<br>${rack['name']}</a></td>";
445 $order = $nextorder[$order];
f5883ec1 446 $rackListIdx++;
e673ee24
DO
447 }
448 echo "</tr></table>\n";
449 finishPortlet();
e673ee24
DO
450 echo "</td></tr></table>";
451}
452
0a7feebb
AD
453// Used by renderRack()
454function printObjectDetailsForRenderRack ($object_id)
455{
456 $objectData = spotEntity ('object', $object_id);
457 if (strlen ($objectData['asset_no']))
458 $prefix = "<div title='${objectData['asset_no']}";
459 else
460 $prefix = "<div title='no asset tag";
461 // Don't tell about label, if it matches common name.
462 $body = '';
463 if ($objectData['name'] != $objectData['label'] and strlen ($objectData['label']))
464 $body = ", visible label is \"${objectData['label']}\"";
465 // Display list of child objects, if any
466 $objectChildren = getEntityRelatives ('children', 'object', $objectData['id']);
467 if (count($objectChildren) > 0)
468 {
469 foreach ($objectChildren as $child)
470 $childNames[] = $child['name'];
471 natsort($childNames);
472 $suffix = sprintf(", contains %s'>", implode(', ', $childNames));
473 }
474 else
475 $suffix = "'>";
476 echo $prefix . $body . $suffix;
477 echo "<a href='".makeHref(array('page'=>'object', 'object_id'=>$objectData['id']))."'>${objectData['dname']}</a></div>";
478}
479
e673ee24 480// This function renders rack as HTML table.
7e1db771 481function renderRack ($rack_id, $hl_obj_id = 0)
e673ee24 482{
61a1d996
DO
483 $rackData = spotEntity ('rack', $rack_id);
484 amplifyCell ($rackData);
e673ee24
DO
485 markAllSpans ($rackData);
486 if ($hl_obj_id > 0)
487 highlightObject ($rackData, $hl_obj_id);
488 markupObjectProblems ($rackData);
489 $prev_id = getPrevIDforRack ($rackData['row_id'], $rack_id);
490 $next_id = getNextIDforRack ($rackData['row_id'], $rack_id);
d48d8820 491 echo "<center><table border=0><tr valign=middle>";
4fbb5a00 492 echo "<td><h2><a href='".makeHref(array('page'=>'row', 'row_id'=>$rackData['row_id']))."'>${rackData['row_name']}</a> :</h2></td>";
e673ee24
DO
493 // FIXME: use 'bypass'?
494 if ($prev_id != NULL)
9803c56c 495 {
4fbb5a00 496 echo "<td><a href='".makeHref(array('page'=>'rack', 'rack_id'=>$prev_id))."'>";
9803c56c 497 printImageHREF ('prev', 'previous rack');
d48d8820 498 echo "</a></td>";
9803c56c 499 }
4fbb5a00 500 echo "<td><h2><a href='".makeHref(array('page'=>'rack', 'rack_id'=>$rackData['id']))."'>${rackData['name']}</a></h2></td>";
e673ee24 501 if ($next_id != NULL)
9803c56c 502 {
4fbb5a00 503 echo "<td><a href='".makeHref(array('page'=>'rack', 'rack_id'=>$next_id))."'>";
f444c095 504 printImageHREF ('next', 'next rack');
d48d8820 505 echo "</a></td>";
9803c56c 506 }
d48d8820 507 echo "</h2></td></tr></table>\n";
e673ee24 508 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
d08147d6
DO
509 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>Front</th>";
510 echo "<th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
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{
8dc2a6c8 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";
8dc2a6c8 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>";
bd0bfb76
AD
857 echo "<th width='20%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '0', ${rackData['height']})\">Front</a></th>";
858 echo "<th width='50%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '1', ${rackData['height']})\">Interior</a></th>";
859 echo "<th width='20%'><a href='javascript:;' 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
40c9fc94
AA
879function renderObjectPortRow ($port, $is_highlighted)
880{
881 echo '<tr';
882 if ($is_highlighted)
883 echo ' class=port_highlight';
884 $a_class = isEthernetPort ($port) ? 'port-menu' : '';
885 echo "><td class='tdleft' NOWRAP><a name='port-${port['id']}' class='ancor interactive-portname nolink $a_class'>${port['name']}</a></td>";
886 echo "<td class=tdleft>${port['label']}</td>";
887 echo "<td class=tdleft>" . formatPortIIFOIF ($port) . "</td><td class=tdleft><tt>${port['l2address']}</tt></td>";
888 if ($port['remote_object_id'])
889 {
890 echo "<td class=tdleft>" .
891 formatPortLink ($port['remote_object_id'], $port['remote_object_name'], $port['remote_id'], NULL) .
892 "</td>";
893 echo "<td class=tdleft>" . formatLoggedSpan ($port['last_log'], $port['remote_name'], 'underline') . "</td>";
894 echo "<td class='tdleft rsvtext'>${port['cableid']}</td>";
895 }
896 else
897 echo implode ('', formatPortReservation ($port)) . '<td></td>';
898 echo "</tr>";
899}
900
9b8174d7 901function renderObject ($object_id)
e673ee24 902{
8dc2a6c8 903 global $nextorder, $virtual_obj_types;
fb6e2f57 904 $info = spotEntity ('object', $object_id);
94fe6370 905 amplifyCell ($info);
e673ee24
DO
906 // Main layout starts.
907 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
908 echo "<tr><td colspan=2 align=center><h1>${info['dname']}</h1></td></tr>\n";
909 // left column with uknown number of portlets
910 echo "<tr><td class=pcleft>";
646272be
AA
911
912 // display summary portlet
913 $summary = array();
59a83bd8 914 if (strlen ($info['name']))
646272be 915 $summary['Common name'] = $info['name'];
94fe6370 916 elseif (considerConfiguredConstraint ($info, 'NAMEWARN_LISTSRC'))
646272be
AA
917 $summary[] = array ('<tr><td colspan=2 class=msg_error>Common name is missing.</td></tr>');
918 $summary['Object type'] = '<a href="' . makeHref (array (
341fd895
DO
919 'page' => 'depot',
920 'tab' => 'default',
921 'cfe' => '{$typeid_' . $info['objtype_id'] . '}'
646272be 922 )) . '">' . decodeObjectType ($info['objtype_id'], 'o') . '</a>';
9b8174d7 923 if (strlen ($info['label']))
646272be 924 $summary['Visible label'] = $info['label'];
59a83bd8 925 if (strlen ($info['asset_no']))
646272be 926 $summary['Asset tag'] = $info['asset_no'];
d4e8ddeb 927 elseif (considerConfiguredConstraint ($info, 'ASSETWARN_LISTSRC'))
646272be
AA
928 $summary[] = array ('<tr><td colspan=2 class=msg_error>Asset tag is missing.</td></tr>');
929 $parents = getEntityRelatives ('parents', 'object', $object_id);
930 if (count ($parents))
0682218d 931 {
646272be 932 $fmt_parents = array();
0682218d 933 foreach ($parents as $parent)
8023ee39
AA
934 $fmt_parents[] = "<a href='".makeHref(array('page'=>$parent['page'], $parent['id_name'] => $parent['entity_id']))."'>${parent['name']}</a>";
935 $summary[count($parents) > 1 ? 'Containers' : 'Container'] = implode ('<br>', $fmt_parents);
0682218d 936 }
646272be
AA
937 $children = getEntityRelatives ('children', 'object', $object_id);
938 if (count ($children))
0682218d 939 {
646272be 940 $fmt_children = array();
0682218d 941 foreach ($children as $child)
8023ee39 942 $fmt_children[] = "<a href='".makeHref(array('page'=>$child['page'], $child['id_name']=>$child['entity_id']))."'>${child['name']}</a>";
dcde9835 943 $summary['Contains'] = implode ('<br>', $fmt_children);
0682218d 944 }
e673ee24 945 if ($info['has_problems'] == 'yes')
646272be 946 $summary[] = array ('<tr><td colspan=2 class=msg_error>Has problems</td></tr>');
8ad59489 947 foreach (getAttrValues ($object_id) as $record)
4969aa31
DO
948 if
949 (
950 strlen ($record['value']) and
951 permitted (NULL, NULL, NULL, array (array ('tag' => '$attr_' . $record['id'])))
952 )
646272be 953 $summary['{sticker}' . $record['name']] = formatAttributeValue ($record);
a2c597ea
AA
954 $summary[] = array (getOutputOf ('printTagTRs',
955 $info,
956 makeHref
957 (
958 array
959 (
960 'page'=>'depot',
961 'tab'=>'default',
962 'andor' => 'and',
963 'cfe' => '{$typeid_' . $info['objtype_id'] . '}',
964 )
965 )."&"
966 ));
646272be 967 renderEntitySummary ($info, 'summary', $summary);
e673ee24 968
59a83bd8 969 if (strlen ($info['comment']))
e673ee24
DO
970 {
971 startPortlet ('Comment');
6cc5d6cd 972 echo '<div class=commentblock>' . string_insert_hrefs ($info['comment']) . '</div>';
e673ee24
DO
973 finishPortlet ();
974 }
975
b5700329
AA
976 $logrecords = getLogRecordsForObject ($_REQUEST['object_id']);
977 if (count ($logrecords))
9a90adc4
DO
978 {
979 startPortlet ('log records');
980 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable width='100%'>";
981 $order = 'odd';
b5700329 982 foreach ($logrecords as $row)
9a90adc4
DO
983 {
984 echo "<tr class=row_${order} valign=top>";
985 echo '<td class=tdleft>' . $row['date'] . '<br>' . $row['user'] . '</td>';
c14b5720 986 echo '<td class="slbconf rsvtext">' . string_insert_hrefs (htmlspecialchars ($row['content'], ENT_NOQUOTES)) . '</td>';
9a90adc4
DO
987 echo '</tr>';
988 $order = $nextorder[$order];
989 }
990 echo '</table>';
991 finishPortlet();
992 }
993
65e557dd 994 switchportInfoJS ($object_id); // load JS code to make portnames interactive
e1ae3fb4
AD
995 renderFilesPortlet ('object', $object_id);
996
9f75e165 997 if (count ($info['ports']))
e673ee24 998 {
0ab782bc 999 startPortlet ('ports and links');
9f75e165
DO
1000 $hl_port_id = 0;
1001 if (isset ($_REQUEST['hl_port_id']))
e673ee24 1002 {
0cc24e9a 1003 assertUIntArg ('hl_port_id');
9f75e165 1004 $hl_port_id = $_REQUEST['hl_port_id'];
65e557dd 1005 addAutoScrollScript ("port-$hl_port_id");
9f75e165
DO
1006 }
1007 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>";
1008 echo '<tr><th class=tdleft>Local name</th><th class=tdleft>Visible label</th>';
0d59a51c 1009 echo '<th class=tdleft>Interface</th><th class=tdleft>L2 address</th>';
0c7c9f8b
DO
1010 echo '<th class=tdcenter colspan=2>Remote object and port</th>';
1011 echo '<th class=tdleft>Cable ID</th></tr>';
9f75e165 1012 foreach ($info['ports'] as $port)
40c9fc94 1013 callHook ('renderObjectPortRow', $port, ($hl_port_id == $port['id']));
fd5edda8 1014 if (permitted (NULL, 'ports', 'set_reserve_comment'))
a8dc2982 1015 addJS ('js/inplace-edit.js');
9f75e165 1016 echo "</table><br>";
e673ee24
DO
1017 finishPortlet();
1018 }
85970da2 1019
21ee3351 1020 if (count ($info['ipv4']) + count ($info['ipv6']))
e673ee24 1021 {
21ee3351 1022 startPortlet ('IP addresses');
e673ee24 1023 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
f0ed1181 1024 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
0b9c98d7 1025 echo "<tr><th>OS interface</th><th>IP address</th><th>network</th><th>routed by</th><th>peers</th></tr>\n";
83fdf85f
DO
1026 else
1027 echo "<tr><th>OS interface</th><th>IP address</th><th>peers</th></tr>\n";
21ee3351
AA
1028
1029 // group IP allocations by interface name instead of address family
1030 $allocs_by_iface = array();
1031 foreach (array ('ipv4', 'ipv6') as $ip_v)
1032 foreach ($info[$ip_v] as $dottedquad => $alloc)
1033 $allocs_by_iface[$alloc['osif']][$dottedquad] = $alloc;
1034
1035 // sort allocs array by portnames
1036 foreach (sortPortList ($allocs_by_iface) as $iface_name => $alloclist)
1037 {
1038 $is_first_row = TRUE;
f3505b35 1039 foreach ($alloclist as $alloc)
b90c3907 1040 {
40c9fc94 1041 $rendered_alloc = callHook ('getRenderedAlloc', $object_id, $alloc);
f3505b35 1042 echo "<tr class='${rendered_alloc['tr_class']}' valign=top>";
21ee3351 1043
f3505b35 1044 // display iface name, same values are grouped into single cell
21ee3351
AA
1045 if ($is_first_row)
1046 {
1047 $rowspan = count ($alloclist) > 1 ? 'rowspan="' . count ($alloclist) . '"' : '';
40c9fc94 1048 echo "<td class=tdleft $rowspan>" . $iface_name . $rendered_alloc['td_name_suffix'] . "</td>";
21ee3351
AA
1049 $is_first_row = FALSE;
1050 }
f3505b35 1051 echo $rendered_alloc['td_ip'];
21ee3351 1052 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
83fdf85f 1053 {
f3505b35
AA
1054 echo $rendered_alloc['td_network'];
1055 echo $rendered_alloc['td_routed_by'];
21ee3351 1056 }
f3505b35
AA
1057 echo $rendered_alloc['td_peers'];
1058
1059 echo "</tr>\n";
b90c3907 1060 }
e673ee24
DO
1061 }
1062 echo "</table><br>\n";
1063 finishPortlet();
1064 }
1065
94fe6370 1066 $forwards = $info['nat4'];
e673ee24
DO
1067 if (count($forwards['in']) or count($forwards['out']))
1068 {
f28fbe8b 1069 startPortlet('NATv4');
e673ee24
DO
1070
1071 if (count($forwards['out']))
1072 {
1073
f28fbe8b 1074 echo "<h3>locally performed NAT</h3>";
e673ee24 1075
105a3bc8 1076 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
f28fbe8b 1077 echo "<tr><th>Proto</th><th>Match endpoint</th><th>Translate to</th><th>Target object</th><th>Rule comment</th></tr>\n";
e673ee24
DO
1078
1079 foreach ($forwards['out'] as $pf)
1080 {
2c817354
DO
1081 $class = 'trerror';
1082 $osif = '';
1083 if (isset ($alloclist [$pf['localip']]))
1084 {
1085 $class = $alloclist [$pf['localip']]['addrinfo']['class'];
1086 $osif = $alloclist [$pf['localip']]['osif'] . ': ';
1087 }
e673ee24 1088 echo "<tr class='$class'>";
4fbb5a00
DY
1089 echo "<td>${pf['proto']}</td><td class=tdleft>${osif}<a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['localip']))."'>${pf['localip']}</a>:${pf['localport']}</td>";
1090 echo "<td class=tdleft><a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['remoteip']))."'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
53ef3908 1091 $address = getIPv4Address ($pf['remoteip']);
e673ee24 1092 echo "<td class='description'>";
53ef3908
DO
1093 if (count ($address['allocs']))
1094 foreach($address['allocs'] as $bond)
4fbb5a00 1095 echo "<a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$bond['object_id']))."'>${bond['object_name']}(${bond['name']})</a> ";
59a83bd8 1096 elseif (strlen ($pf['remote_addr_name']))
f28fbe8b 1097 echo '(' . $pf['remote_addr_name'] . ')';
53ef3908 1098 echo "</td><td class='description'>${pf['description']}</td></tr>";
e673ee24
DO
1099 }
1100 echo "</table><br><br>";
1101 }
1102 if (count($forwards['in']))
1103 {
f28fbe8b 1104 echo "<h3>arriving NAT connections</h3>";
105a3bc8 1105 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
f28fbe8b 1106 echo "<tr><th>Matched endpoint</th><th>Source object</th><th>Translated to</th><th>Rule comment</th></tr>\n";
e673ee24
DO
1107 foreach ($forwards['in'] as $pf)
1108 {
1109 echo "<tr>";
4fbb5a00
DY
1110 echo "<td>${pf['proto']}/<a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['localip']))."'>${pf['localip']}</a>:${pf['localport']}</td>";
1111 echo "<td class='description'><a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$pf['object_id']))."'>${pf['object_name']}</a>";
1112 echo "</td><td><a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['remoteip']))."'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
e673ee24
DO
1113 echo "<td class='description'>${pf['description']}</td></tr>";
1114 }
e673ee24
DO
1115 echo "</table><br><br>";
1116 }
1117 finishPortlet();
1118 }
1119
defd92d8 1120 renderSLBTriplets ($info);
e673ee24
DO
1121 echo "</td>\n";
1122
7056988c 1123 // After left column we have (surprise!) right column with rackspace portlet only.
e673ee24 1124 echo "<td class=pcright>";
8dc2a6c8 1125 if (!in_array($info['objtype_id'], $virtual_obj_types))
0682218d
AD
1126 {
1127 // rackspace portlet
1128 startPortlet ('rackspace allocation');
1129 foreach (getResidentRacksData ($object_id, FALSE) as $rack_id)
1130 renderRack ($rack_id, $object_id);
1131 echo '<br>';
1132 finishPortlet();
1133 }
e673ee24
DO
1134 echo "</td></tr>";
1135 echo "</table>\n";
1136}
1137
1138function renderRackMultiSelect ($sname, $racks, $selected)
1139{
04571888
DO
1140 // Transform the given flat list into a list of groups, each representing a rack row.
1141 $rdata = array();
e673ee24 1142 foreach ($racks as $rack)
04571888
DO
1143 if (!isset ($rdata[$rack['row_name']]))
1144 $rdata[$rack['row_name']] = array ($rack['id'] => $rack['name']);
1145 else
1146 $rdata[$rack['row_name']][$rack['id']] = $rack['name'];
4fbb5a00 1147 echo "<select name=${sname} multiple size=" . getConfigVar ('MAXSELSIZE') . " onchange='getElementsByName(\"updateObjectAllocation\")[0].submit()'>\n";
04571888 1148 foreach ($rdata as $optgroup => $racklist)
e673ee24 1149 {
04571888
DO
1150 echo "<optgroup label='${optgroup}'>";
1151 foreach ($racklist as $rack_id => $rack_name)
1152 {
1153 echo "<option value=${rack_id}";
1154 if (!(array_search ($rack_id, $selected) === FALSE))
1155 echo ' selected';
1156 echo">${rack_name}</option>\n";
1157 }
e673ee24
DO
1158 }
1159 echo "</select>\n";
1160}
1161
e673ee24 1162// This function renders a form for port edition.
7e1db771 1163function renderPortsForObject ($object_id)
e673ee24 1164{
3153a326
DO
1165 $prefs = getPortListPrefs();
1166 function printNewItemTR ($prefs)
39b4abd0
DO
1167 {
1168 printOpFormIntro ('addPort');
1169 echo "<tr><td>";
f5ff50f5 1170 printImageHREF ('add', 'add a port', TRUE);
65e557dd 1171 echo "</td><td class='tdleft'><input type=text size=8 name=port_name tabindex=100></td>\n";
cd3775e9
DO
1172 echo "<td><input type=text name=port_label tabindex=101></td><td>";
1173 printNiftySelect (getNewPortTypeOptions(), array ('name' => 'port_type_id', 'tabindex' => 102), $prefs['selected']);
1174 echo "<td><input type=text name=port_l2address tabindex=103 size=18 maxlength=24></td>\n";
318c48a8 1175 echo "<td colspan=4>&nbsp;</td><td>";
9318d2ef
DO
1176 printImageHREF ('add', 'add a port', TRUE, 104);
1177 echo "</td></tr></form>";
39b4abd0 1178 }
a1fc539a 1179 if (getConfigVar('ENABLE_MULTIPORT_FORM') == 'yes' || getConfigVar('ENABLE_BULKPORT_FORM') == 'yes' )
f44fdef9
DO
1180 startPortlet ('Ports and interfaces');
1181 else
1182 echo '<br>';
9f75e165
DO
1183 $object = spotEntity ('object', $object_id);
1184 amplifyCell ($object);
a1fc539a
RF
1185 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes' && getConfigVar('ENABLE_BULKPORT_FORM') == 'yes'){
1186 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
1187 echo "<tr><th>&nbsp;</th><th class=tdleft>Local name</th><th class=tdleft>Visible label</th><th class=tdleft>Interface</th><th class=tdleft>Start Number</th>";
1188 echo "<th class=tdleft>Count</th><th>&nbsp;</th></tr>\n";
1189 printOpFormIntro ('addBulkPorts');
1190 echo "<tr><td>";
1191 printImageHREF ('add', 'add ports', TRUE);
1192 echo "</td><td><input type=text size=8 name=port_name tabindex=105></td>\n";
1193 echo "<td><input type=text name=port_label tabindex=106></td><td>";
1194 printNiftySelect (getNewPortTypeOptions(), array ('name' => 'port_type_id', 'tabindex' => 107), $prefs['selected']);
1195 echo "<td><input type=text name=port_numbering_start tabindex=108 size=3 maxlength=3></td>\n";
1196 echo "<td><input type=text name=port_numbering_count tabindex=109 size=3 maxlength=3></td>\n";
1197 echo "<td>&nbsp;</td><td>";
1198 printImageHREF ('add', 'add ports', TRUE, 110);
1199 echo "</td></tr></form>";
1200 echo "</table><br>\n";
1201 }
1202
e673ee24 1203 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
0d59a51c 1204 echo "<tr><th>&nbsp;</th><th class=tdleft>Local name</th><th class=tdleft>Visible label</th><th class=tdleft>Interface</th><th class=tdleft>L2 address</th>";
318c48a8 1205 echo "<th class=tdcenter colspan=2>Remote object and port</th><th>Cable ID</th><th class=tdcenter>(Un)link or (un)reserve</th><th>&nbsp;</th></tr>\n";
39b4abd0 1206 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
3153a326 1207 printNewItemTR ($prefs);
45ff9012
AA
1208
1209 // clear ports link
1210 echo "<a href='".
1211 makeHrefProcess(array ('op'=>'deleteAll', 'page' => 'object', 'tab' => 'ports', 'object_id' => $object_id)).
1212 "' onclick=\"javascript:return confirm('Are you sure you want to delete all existing ports?')\">" . getImageHREF ('clear', 'Clear port list') . " Clear port list</a>";
1213
00276508
AA
1214 if (isset ($_REQUEST['hl_port_id']))
1215 {
1216 assertUIntArg ('hl_port_id');
1217 $hl_port_id = intval ($_REQUEST['hl_port_id']);
65e557dd 1218 addAutoScrollScript ("port-$hl_port_id");
00276508 1219 }
65e557dd 1220 switchportInfoJS ($object_id); // load JS code to make portnames interactive
9f75e165 1221 foreach ($object['ports'] as $port)
e673ee24 1222 {
00276508 1223 $tr_class = isset ($hl_port_id) && $hl_port_id == $port['id'] ? 'class="port_highlight"' : '';
7056988c 1224 printOpFormIntro ('editPort', array ('port_id' => $port['id']));
10005279 1225 echo "<tr $tr_class><td><a name='port-${port['id']}' href='".makeHrefProcess(array('op'=>'delPort', 'port_id'=>$port['id'], 'object_id'=>$object_id))."'>";
e673ee24
DO
1226 printImageHREF ('delete', 'Unlink and Delete this port');
1227 echo "</a></td>\n";
65e557dd
AA
1228 $a_class = isEthernetPort ($port) ? 'port-menu' : '';
1229 echo "<td class='tdleft' NOWRAP><input type=text name=name class='interactive-portname $a_class' value='${port['name']}' size=8></td>";
cd3775e9 1230 echo "<td><input type=text name=label value='${port['label']}'></td>";
611170af
AD
1231 if (!$port['remote_object_id'])
1232 {
3153a326
DO
1233 echo '<td>';
1234 if ($port['iif_id'] != 1)
1235 echo '<label>' . $port['iif_name'] . ' ';
cd3775e9 1236 printSelect (getExistingPortTypeOptions ($port['id']), array ('name' => 'port_type_id'), $port['oif_id']);
3153a326
DO
1237 if ($port['iif_id'] != 1)
1238 echo '</label>';
1239 echo '</td>';
611170af
AD
1240 }
1241 else
1242 {
045bab87 1243 echo "<input type=hidden name=port_type_id value='${port['oif_id']}'><td class=tdleft>";
e9d357e1 1244 echo formatPortIIFOIF ($port) . '</td>';
611170af 1245 }
cd3775e9
DO
1246 // 18 is enough to fit 6-byte MAC address in its longest form,
1247 // while 24 should be Ok for WWN
1248 echo "<td><input type=text name=l2address value='${port['l2address']}' size=18 maxlength=24></td>\n";
e673ee24
DO
1249 if ($port['remote_object_id'])
1250 {
318c48a8 1251 echo "<td>" .
a2ea559e 1252 formatLoggedSpan ($port['last_log'], formatPortLink ($port['remote_object_id'], $port['remote_object_name'], $port['remote_id'], NULL)) .
5c6225b1
AA
1253 "</td>";
1254 echo "<td> " . formatLoggedSpan ($port['last_log'], $port['remote_name'], 'underline') .
1255 "<input type=hidden name=reservation_comment value=''></td>";
318c48a8 1256 echo "<td><input type=text name=cable value='${port['cableid']}'></td>";
3153a326 1257 echo "<td class=tdcenter><a href='".
4fbb5a00
DY
1258 makeHrefProcess(array(
1259 'op'=>'unlinkPort',
cd3775e9 1260 'port_id'=>$port['id'],
cd3775e9 1261 'object_id'=>$object_id)).
4fbb5a00 1262 "'>";
5ccd99a0 1263 printImageHREF ('cut', 'Unlink this port');
e673ee24
DO
1264 echo "</a></td>";
1265 }
59a83bd8 1266 elseif (strlen ($port['reservation_comment']))
e673ee24 1267 {
5c6225b1 1268 echo "<td>" . formatLoggedSpan ($port['last_log'], 'Reserved:', 'strong underline') . "</td>";
e673ee24 1269 echo "<td><input type=text name=reservation_comment value='${port['reservation_comment']}'></td>";
318c48a8 1270 echo "<td></td>";
3153a326 1271 echo "<td class=tdcenter><a href='".
4fbb5a00
DY
1272 makeHrefProcess(array(
1273 'op'=>'useup',
1274 'port_id'=>$port['id'],
1275 'object_id'=>$object_id)).
1276 "'>";
39be655e 1277 printImageHREF ('clear', 'Use up this port');
e673ee24
DO
1278 echo "</a></td>";
1279 }
1280 else
1281 {
318c48a8 1282 echo "<td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td class=tdcenter><span";
cd3775e9
DO
1283 $helper_args = array
1284 (
1285 'port' => $port['id'],
cd3775e9
DO
1286 );
1287 $popup_args = 'height=700, width=400, location=no, menubar=no, '.
9e214652 1288 'resizable=yes, scrollbars=yes, status=no, titlebar=no, toolbar=no';
cd3775e9
DO
1289 echo " ondblclick='window.open(\"" . makeHrefForHelper ('portlist', $helper_args);
1290 echo "\",\"findlink\",\"${popup_args}\");'";
1291 // end of onclick=
cd3775e9
DO
1292 echo " onclick='window.open(\"" . makeHrefForHelper ('portlist', $helper_args);
1293 echo "\",\"findlink\",\"${popup_args}\");'";
1294 // end of onclick=
1295 echo '>';
1296 // end of <a>
5ccd99a0 1297 printImageHREF ('plug', 'Link this port');
cd3775e9
DO
1298 echo "</span>";
1299 echo " <input type=text name=reservation_comment></td>\n";
e673ee24 1300 }
5bbbeaa2
DO
1301 echo "<td>";
1302 printImageHREF ('save', 'Save changes', TRUE);
1303 echo "</td></form></tr>\n";
e673ee24 1304 }
39b4abd0 1305 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
3153a326 1306 printNewItemTR ($prefs);
e673ee24 1307 echo "</table><br>\n";
a1fc539a
RF
1308 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes' && getConfigVar('ENABLE_BULKPORT_FORM') == 'yes'){
1309 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
1310 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>";
1311 echo "<th class=tdleft>Count</th><th>&nbsp;</th></tr>\n";
1312 printOpFormIntro ('addBulkPorts');
1313 echo "<tr><td>";
1314 printImageHREF ('add', 'add ports', TRUE);
1315 echo "</td><td><input type=text size=8 name=port_name tabindex=105></td>\n";
1316 echo "<td><input type=text name=port_label tabindex=106></td><td>";
1317 printNiftySelect (getNewPortTypeOptions(), array ('name' => 'port_type_id', 'tabindex' => 107), $prefs['selected']);
1318 echo "<td><input type=text name=port_numbering_start tabindex=108 size=3 maxlength=3></td>\n";
1319 echo "<td><input type=text name=port_numbering_count tabindex=109 size=3 maxlength=3></td>\n";
1320 echo "<td>&nbsp;</td><td>";
1321 printImageHREF ('add', 'add ports', TRUE, 110);
1322 echo "</td></tr></form>";
1323 echo "</table><br>\n";
1324 }
f44fdef9
DO
1325 if (getConfigVar('ENABLE_MULTIPORT_FORM') == 'yes')
1326 finishPortlet();
1327 if (getConfigVar('ENABLE_MULTIPORT_FORM') != 'yes')
1328 return;
e673ee24
DO
1329
1330 startPortlet ('Add/update multiple ports');
7056988c 1331 printOpFormIntro ('addMultiPorts');
f7a3c94a 1332 echo 'Format: <select name=format tabindex=201>';
e673ee24
DO
1333 echo '<option value=c3600asy>Cisco 3600 async: sh line | inc TTY</option>';
1334 echo '<option value=fiwg selected>Foundry ServerIron/FastIron WorkGroup/Edge: sh int br</option>';
e673ee24 1335 echo '<option value=fisxii>Foundry FastIron SuperX/II4000: sh int br</option>';
351d4dbf 1336 echo '<option value=ssv1>SSV:&lt;interface name&gt; &lt;MAC address&gt;</option>';
e673ee24
DO
1337 echo "</select>";
1338 echo 'Default port type: ';
cd3775e9 1339 printNiftySelect (getNewPortTypeOptions(), array ('name' => 'port_type', 'tabindex' => 202), $prefs['selected']);
f7a3c94a
DO
1340 echo "<input type=submit value='Parse output' tabindex=204><br>\n";
1341 echo "<textarea name=input cols=100 rows=50 tabindex=203></textarea><br>\n";
e673ee24
DO
1342 echo '</form>';
1343 finishPortlet();
1344}
1345
f3505b35 1346function renderIPTabForObject ($object_id, $ip_v)
e673ee24 1347{
f3505b35 1348 function getOpnameByIPFamily ($opname, $ip_v)
e673ee24 1349 {
f3505b35
AA
1350 // do not assemble opnames from the peaces to be able to grep the code by opnames
1351 switch ($opname . '-'. $ip_v)
d7a8186d 1352 {
f3505b35
AA
1353 case 'add-4': return 'addIPv4Allocation';
1354 case 'add-6': return 'addIPv6Allocation';
1355 case 'upd-4': return 'updIPv4Allocation';
1356 case 'upd-6': return 'updIPv6Allocation';
1357 case 'del-4': return 'delIPv4Allocation';
1358 case 'del-6': return 'delIPv6Allocation';
1359 default: throw new InvalidArgException ('$opname or $ip_v', "$opname or $ip_v");
d7a8186d 1360 }
e673ee24 1361 }
710ead7e 1362 function printNewItemTR ($ip_v, $default_type)
21ee3351
AA
1363 {
1364 global $aat;
f3505b35 1365 printOpFormIntro (getOpnameByIPFamily ('add', $ip_v));
21ee3351
AA
1366 echo "<tr><td>";
1367 printImageHREF ('add', 'allocate', TRUE);
1368 echo "</td>";
1369 echo "<td class=tdleft><input type='text' size='10' name='bond_name' tabindex=100></td>\n";
1370 echo "<td class=tdleft><input type=text name='ip' tabindex=101></td>\n";
1371 echo "<td colspan=2>&nbsp;</td><td>";
710ead7e 1372 printSelect ($aat, array ('name' => 'bond_type', 'tabindex' => 102), $default_type);
21ee3351
AA
1373 echo "</td><td>&nbsp;</td><td>";
1374 printImageHREF ('add', 'allocate', TRUE, 103);
1375 echo "</td></tr></form>";
1376 }
1377 $focus = spotEntity ('object', $object_id);
1378 amplifyCell ($focus);
1379 global $aat;
1380 startPortlet ('Allocations');
1381 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
1382 echo '<tr><th>&nbsp;</th><th>OS interface</th><th>IP address</th>';
1383 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
1384 echo '<th>network</th><th>routed by</th>';
1385 echo '<th>type</th><th>misc</th><th>&nbsp</th></tr>';
1386
710ead7e
AA
1387 $alloc_list = ''; // most of the output is stored here
1388 $used_alloc_types = array();
f3505b35 1389 foreach ($focus['ipv' . $ip_v] as $alloc) // ['ipv4'] or ['ipv6']
21ee3351 1390 {
710ead7e
AA
1391 if (! isset ($used_alloc_types[$alloc['type']]))
1392 $used_alloc_types[$alloc['type']] = 0;
1393 $used_alloc_types[$alloc['type']]++;
1394
40c9fc94 1395 $rendered_alloc = callHook ('getRenderedAlloc', $object_id, $alloc);
710ead7e
AA
1396 $alloc_list .= getOutputOf ('printOpFormIntro', getOpnameByIPFamily ('upd', $ip_v), array ('ip' => $alloc['addrinfo']['ip']));
1397 $alloc_list .= "<tr class='${rendered_alloc['tr_class']}' valign=top>";
f3505b35 1398
710ead7e 1399 $alloc_list .= "<td><a href='" .
f3505b35
AA
1400 makeHrefProcess
1401 (
1402 array
1403 (
1404 'op' => getOpnameByIPFamily ('del', $ip_v),
1405 'ip' => $alloc['addrinfo']['ip'],
1406 'object_id' => $object_id
1407 )
1408 ) . "'>" .
1409 getImageHREF ('delete', 'Delete this IP address') .
1410 "</a></td>";
40c9fc94 1411 $alloc_list .= "<td class=tdleft><input type='text' name='bond_name' value='${alloc['osif']}' size=10>" . $rendered_alloc['td_name_suffix'] . "</td>";
710ead7e 1412 $alloc_list .= $rendered_alloc['td_ip'];
21ee3351
AA
1413 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
1414 {
710ead7e
AA
1415 $alloc_list .= $rendered_alloc['td_network'];
1416 $alloc_list .= $rendered_alloc['td_routed_by'];
21ee3351 1417 }
710ead7e
AA
1418 $alloc_list .= '<td>' . getSelect ($aat, array ('name' => 'bond_type'), $alloc['type']) . "</td>";
1419 $alloc_list .= $rendered_alloc['td_peers'];
1420 $alloc_list .= "<td>" .getImageHREF ('save', 'Save changes', TRUE) . "</td>";
f3505b35 1421
710ead7e 1422 $alloc_list .= "</form></tr>\n";
21ee3351 1423 }
710ead7e
AA
1424 asort ($used_alloc_types, SORT_NUMERIC);
1425 $most_popular_type = empty ($used_alloc_types) ? 'regular' : array_pop (array_keys ($used_alloc_types));
1426
1427 if ($list_on_top = (getConfigVar ('ADDNEW_AT_TOP') != 'yes'))
1428 echo $alloc_list;
1429 printNewItemTR ($ip_v, $most_popular_type);
1430 if (! $list_on_top)
1431 echo $alloc_list;
21ee3351
AA
1432
1433 echo "</table><br>\n";
1434 finishPortlet();
f3505b35
AA
1435}
1436
1437function renderIPv4ForObject ($object_id)
1438{
1439 renderIPTabForObject ($object_id, '4');
1440}
21ee3351 1441
f3505b35
AA
1442function renderIPv6ForObject ($object_id)
1443{
1444 renderIPTabForObject ($object_id, '6');
21ee3351
AA
1445}
1446
08408472
AA
1447// This function is deprecated. Do not rely on its internals,
1448// it will probably be removed in the next major relese.
1449// Use new showError, showWarning, showSuccess functions.
a2b16202 1450// Log array is stored in global $log_messages. Its format is simple: plain ordered array
8ab645cf 1451// with values having keys 'c' (both message code and severity) and 'a' (sprintf arguments array)
1cb6adf5 1452function showMessageOrError ()
e673ee24 1453{
a2b16202
AA
1454 global $log_messages;
1455
1456 @session_start();
1457 if (isset ($_SESSION['log']))
1458 {
1459 $log_messages = array_merge ($_SESSION['log'], $log_messages);
1460 unset ($_SESSION['log']);
1461 }
1462 session_commit();
1463
1464 if (empty ($log_messages))
1cb6adf5 1465 return;
8ab645cf
AA
1466 $msginfo = array
1467 (
1468// records 0~99 with success messages
1469 0 => array ('code' => 'success', 'format' => '%s'),
1470 5 => array ('code' => 'success', 'format' => 'added record "%s" successfully'),
1471 6 => array ('code' => 'success', 'format' => 'updated record "%s" successfully'),
1472 7 => array ('code' => 'success', 'format' => 'deleted record "%s" successfully'),
1473 8 => array ('code' => 'success', 'format' => 'Port %s successfully linked with %s'),
1474 10 => array ('code' => 'success', 'format' => 'Added %u ports, updated %u ports, encountered %u errors.'),
1475 21 => array ('code' => 'success', 'format' => 'Generation complete'),
1476 26 => array ('code' => 'success', 'format' => 'updated %u records successfully'),
1477 37 => array ('code' => 'success', 'format' => 'added %u records successfully'),
1478 38 => array ('code' => 'success', 'format' => 'removed %u records successfully'),
8ab645cf
AA
1479 43 => array ('code' => 'success', 'format' => 'Saved successfully.'),
1480 44 => array ('code' => 'success', 'format' => '%s failures and %s successfull changes.'),
1481 48 => array ('code' => 'success', 'format' => 'added a record successfully'),
1482 49 => array ('code' => 'success', 'format' => 'deleted a record successfully'),
1483 51 => array ('code' => 'success', 'format' => 'updated a record successfully'),
1484 57 => array ('code' => 'success', 'format' => 'Reset complete'),
8ab645cf 1485 63 => array ('code' => 'success', 'format' => '%u change request(s) have been processed'),
8ab645cf
AA
1486 67 => array ('code' => 'success', 'format' => "Tag rolling done, %u objects involved"),
1487 71 => array ('code' => 'success', 'format' => 'File "%s" was linked successfully'),
1488 72 => array ('code' => 'success', 'format' => 'File was unlinked successfully'),
8ab645cf
AA
1489 82 => array ('code' => 'success', 'format' => "Bulk port creation was successful. %u ports created, %u failed"),
1490 87 => array ('code' => 'success', 'format' => '802.1Q recalculate: %d ports changed on %d switches'),
8628ae44 1491// records 100~199 with fatal error messages
8ab645cf
AA
1492 100 => array ('code' => 'error', 'format' => '%s'),
1493 109 => array ('code' => 'error', 'format' => 'failed updating a record'),
8ab645cf
AA
1494 131 => array ('code' => 'error', 'format' => 'invalid format requested'),
1495 141 => array ('code' => 'error', 'format' => 'Encountered %u errors, updated %u record(s)'),
1496 149 => array ('code' => 'error', 'format' => 'Turing test failed'),
1497 150 => array ('code' => 'error', 'format' => 'Can only change password under DB authentication.'),
1498 151 => array ('code' => 'error', 'format' => 'Old password doesn\'t match.'),
1499 152 => array ('code' => 'error', 'format' => 'New passwords don\'t match.'),
1500 154 => array ('code' => 'error', 'format' => "Verification error: %s"),
1501 155 => array ('code' => 'error', 'format' => 'Save failed.'),
1502 159 => array ('code' => 'error', 'format' => 'Permission denied moving port %s from VLAN%u to VLAN%u'),
1503 161 => array ('code' => 'error', 'format' => 'Endpoint not found. Please either set FQDN attribute or assign an IP address to the object.'),
1504 162 => array ('code' => 'error', 'format' => 'More than one IP address is assigned to this object, please configure FQDN attribute.'),
8ab645cf
AA
1505 170 => array ('code' => 'error', 'format' => 'There is no network for IP address "%s"'),
1506 172 => array ('code' => 'error', 'format' => 'Malformed request'),
1507 179 => array ('code' => 'error', 'format' => 'Expired form has been declined.'),
1508 188 => array ('code' => 'error', 'format' => "Fatal SNMP failure"),
1509 189 => array ('code' => 'error', 'format' => "Unknown OID '%s'"),
1510 191 => array ('code' => 'error', 'format' => "deploy was blocked due to conflicting configuration versions"),
f0ff4930 1511
8628ae44 1512// records 200~299 with warnings
8ab645cf
AA
1513 200 => array ('code' => 'warning', 'format' => '%s'),
1514 201 => array ('code' => 'warning', 'format' => 'nothing happened...'),
8ab645cf 1515 206 => array ('code' => 'warning', 'format' => 'Rack is not empty'),
7587edca 1516 207 => array ('code' => 'warning', 'format' => 'File upload failed, error: %s'),
57777e4a 1517
24d3182a 1518// records 300~399 with notices
8ab645cf 1519 300 => array ('code' => 'neutral', 'format' => '%s'),
24d3182a 1520
8ab645cf
AA
1521 );
1522 // Handle the arguments. Is there any better way to do it?
a2b16202 1523 foreach ($log_messages as $record)
8ab645cf
AA
1524 {
1525 if (!isset ($record['c']) or !isset ($msginfo[$record['c']]))
1526 {
41152018
AA
1527 $prefix = isset ($record['c']) ? $record['c'] . ': ' : '';
1528 echo "<div class=msg_neutral>(${prefix}this message was lost)</div>";
8ab645cf
AA
1529 continue;
1530 }
1531 if (isset ($record['a']))
1532 switch (count ($record['a']))
baf37d01 1533 {
8ab645cf
AA
1534 case 1:
1535 $msgtext = sprintf
1536 (
1537 $msginfo[$record['c']]['format'],
1538 $record['a'][0]
1539 );
1540 break;
1541 case 2:
1542 $msgtext = sprintf
1543 (
1544 $msginfo[$record['c']]['format'],
1545 $record['a'][0],
1546 $record['a'][1]
1547 );
1548 break;
1549 case 3:
1550 $msgtext = sprintf
1551 (
1552 $msginfo[$record['c']]['format'],
1553 $record['a'][0],
1554 $record['a'][1],
1555 $record['a'][2]
1556 );
1557 break;
1558 case 4:
1559 default:
1560 $msgtext = sprintf
1561 (
1562 $msginfo[$record['c']]['format'],
1563 $record['a'][0],
1564 $record['a'][1],
1565 $record['a'][2],
1566 $record['a'][3]
1567 );
1568 break;
baf37d01 1569 }
8ab645cf
AA
1570 else
1571 $msgtext = $msginfo[$record['c']]['format'];
1572 echo '<div class=msg_' . $msginfo[$record['c']]['code'] . ">${msgtext}</div>";
baf37d01 1573 }
a2b16202 1574 $log_messages = array();
e673ee24
DO
1575}
1576
65e557dd
AA
1577// renders two tables: port link status and learned MAC list
1578function renderPortsInfo($object_id)
1579{
1580 global $nextorder;
1581 echo "<table width='100%'><tr>";
1582
1583 if (permitted (NULL, NULL, 'get_link_status'))
1584 {
1585 try
1586 {
80019a2c 1587 $linkStatus = queryDevice ($object_id, 'getportstatus');
65e557dd
AA
1588 }
1589 catch (RackTablesError $e) {}
1590 if (! empty ($linkStatus))
1591 {
1592 echo "<td valign='top' width='50%'>";
1593 startPortlet('Link status');
1594 echo "<table width='80%' class='widetable' cellspacing=0 cellpadding='5px' align='center'><tr><th>Port<th>Link status<th>Link info</tr>";
1595 $order = 'even';
1596 foreach ($linkStatus as $pn => $link)
1597 {
1598 echo "<tr class='row_$order'>";
1599 $order = $nextorder[$order];
1600 echo '<td>' . $pn;
1601 echo '<td>' . $link['status'];
1602 $info = '';
1603 if (isset ($link['speed']))
1604 $info .= $link['speed'];
1605 if (isset ($link['duplex']))
1606 {
1607 if (! empty ($info))
1608 $info .= ', ';
1609 $info .= $link['duplex'];
1610 }
1611 echo '<td>' . $info;
1612 echo '</tr>';
1613 }
1614 echo "</table></td>";
1615 finishPortlet();
1616 }
1617 }
1618
1619 try
1620 {
80019a2c 1621 $macList = sortPortList (queryDevice ($object_id, 'getmaclist'));
65e557dd
AA
1622 }
1623 catch (RackTablesError $e) {}
1624 if (! empty ($macList))
1625 {
1626 echo "<td valign='top' width='50%'>";
1627 $rendered_macs = '';
1628 $mac_count = 0;
1629 $rendered_macs .= "<table width='80%' class='widetable' cellspacing=0 cellpadding='5px' align='center'><tr><th>MAC<th>Vlan<th>Port</tr>";
1630 $order = 'even';
1631 foreach ($macList as $pn => $list)
1632 {
1633 $order = $nextorder[$order];
1634 foreach ($list as $item)
1635 {
1636 ++$mac_count;
1637 $rendered_macs .= "<tr class='row_$order'>";
1638 $rendered_macs .= '<td style="font-family: monospace">' . $item['mac'];
1639 $rendered_macs .= '<td>' . $item['vid'];
1640 $rendered_macs .= '<td>' . $pn;
1641 $rendered_macs .= '</tr>';
1642 }
1643 }
1644 $rendered_macs .= "</table></td>";
1645
1646 startPortlet("Learned MACs ($mac_count)");
1647 echo $rendered_macs;
1648 finishPortlet();
1649 }
1650
1651 echo "</td></tr></table>";
1652}
1653
e673ee24 1654/*
51c18782 1655The following conditions must be met:
e673ee24
DO
16561. We can mount onto free atoms only. This means: if any record for an atom
1657already exists in RackSpace, it can't be used for mounting.
16582. We can't unmount from 'W' atoms. Operator should review appropriate comments
1659and either delete them before unmounting or refuse to unmount the object.
1660*/
7e1db771 1661function renderRackSpaceForObject ($object_id)
e673ee24 1662{
e673ee24
DO
1663 // Always process occupied racks plus racks chosen by user. First get racks with
1664 // already allocated rackspace...
51c18782 1665 $workingRacksData = getResidentRacksData ($object_id);
e673ee24 1666 // ...and then add those chosen by user (if any).
2135fd83 1667 if (isset($_REQUEST['rackmulti']))
e673ee24 1668 foreach ($_REQUEST['rackmulti'] as $cand_id)
e673ee24
DO
1669 if (!isset ($workingRacksData[$cand_id]))
1670 {
0cc24e9a 1671 $rackData = spotEntity ('rack', $cand_id);
61a1d996 1672 amplifyCell ($rackData);
e673ee24
DO
1673 $workingRacksData[$cand_id] = $rackData;
1674 }
51690ad4 1675
0a7feebb
AD
1676 // Get a list of all of this object's parents,
1677 // then trim the list to only include parents which are racks
1678 $objectParents = getEntityRelatives('parents', 'object', $object_id);
1679 $parentRacks = array();
1680 foreach ($objectParents as $parentData)
1681 if ($parentData['entity_type'] == 'rack')
1682 $parentRacks[] = $parentData['entity_id'];
1683
e673ee24
DO
1684 // Main layout starts.
1685 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0><tr>";
1686
1687 // Left portlet with rack list.
1688 echo "<td class=pcleft height='1%'>";
1689 startPortlet ('Racks');
a8efc03e 1690 $allRacksData = listCells ('rack');
6d42599c
AA
1691
1692 // filter rack list to match only racks having common tags with the object (reducing $allRacksData)
1693 if (! isset ($_REQUEST['show_all_racks']) and getConfigVar ('FILTER_RACKLIST_BY_TAGS') == 'yes')
1694 {
1695 $matching_racks = array();
1696 $object = spotEntity ('object', $object_id);
1697 $matched_tags = array();
1698 foreach ($allRacksData as $rack)
1699 foreach ($object['etags'] as $tag)
1700 if (tagOnChain ($tag, $rack['etags']) or tagOnChain ($tag, $rack['itags']))
1701 {
1702 $matching_racks[$rack['id']] = $rack;
1703 $matched_tags[$tag['id']] = $tag;
1704 break;
1705 }
1706 // add current object's racks even if they dont match filter
1707 foreach ($workingRacksData as $rack_id => $rack)
1708 if (! isset ($matching_racks[$rack_id]))
1709 $matching_racks[$rack_id] = $rack;
1710 // if matching racks found, and rack list is reduced, show 'show all' link
1711 if (count ($matching_racks) and count ($matching_racks) != count ($allRacksData))
1712 {
1713 $filter_text = '';
1714 foreach ($matched_tags as $tag)
1715 $filter_text .= (empty ($filter_text) ? '' : ' or ') . '{' . $tag['tag'] . '}';
1716 $href_show_all = trim($_SERVER['REQUEST_URI'], '&');
1717 $href_show_all .= htmlspecialchars('&show_all_racks=1');
1718 echo "(filtered by <span class='filter-text'>$filter_text</span>, <a href='$href_show_all'>show all</a>)<p>";
1719 $allRacksData = $matching_racks;
1720 }
1721 }
1722
4b8d413e 1723 if (count ($allRacksData) <= getConfigVar ('RACK_PRESELECT_THRESHOLD'))
61a1d996 1724 foreach ($allRacksData as $rack)
51c18782
DO
1725 if (!array_key_exists ($rack['id'], $workingRacksData))
1726 {
1727 amplifyCell ($rack);
1728 $workingRacksData[$rack['id']] = $rack;
1729 }
1730 foreach (array_keys ($workingRacksData) as $rackId)
1731 applyObjectMountMask ($workingRacksData[$rackId], $object_id);
1732 printOpFormIntro ('updateObjectAllocation');
4b8d413e 1733 renderRackMultiSelect ('rackmulti[]', $allRacksData, array_keys ($workingRacksData));
51c18782 1734 echo "<br><br>";
e673ee24
DO
1735 finishPortlet();
1736 echo "</td>";
1737
1738 // Middle portlet with comment and submit.
1739 echo "<td class=pcleft>";
1740 startPortlet ('Comment');
1741 echo "<textarea name=comment rows=10 cols=40></textarea><br>\n";
1742 echo "<input type=submit value='Save' name=got_atoms>\n";
51c18782 1743 echo "<br><br>";
e673ee24
DO
1744 finishPortlet();
1745 echo "</td>";
1746
1747 // Right portlet with rendered racks. If this form submit is not final, we have to
1748 // reflect the former state of the grid in current form.
1749 echo "<td class=pcright rowspan=2 height='1%'>";
1750 startPortlet ('Working copy');
65e557dd 1751 addJS ('js/racktables.js');
e673ee24
DO
1752 echo '<table border=0 cellspacing=10 align=center><tr>';
1753 foreach ($workingRacksData as $rack_id => $rackData)
1754 {
1755 // Order is important here: only original allocation is highlighted.
1756 highlightObject ($rackData, $object_id);
1757 markupAtomGrid ($rackData, 'T');
1758 // If we have a form processed, discard user input and show new database
1759 // contents.
51c18782 1760 if (isset ($_REQUEST['rackmulti'][0])) // is an update
e673ee24
DO
1761 mergeGridFormToRack ($rackData);
1762 echo "<td valign=top>";
1763 echo "<center>\n<h2>${rackData['name']}</h2>\n";
1764 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
57c69e9c 1765 echo "<tr><th width='10%'>&nbsp;</th>";
bd0bfb76
AD
1766 echo "<th width='20%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '0', ${rackData['height']})\">Front</a></th>";
1767 echo "<th width='50%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '1', ${rackData['height']})\">Interior</a></th>";
1768 echo "<th width='20%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '2', ${rackData['height']})\">Back</a></th></tr>\n";
e673ee24 1769 renderAtomGrid ($rackData);
57c69e9c 1770 echo "<tr><th width='10%'>&nbsp;</th>";
bd0bfb76
AD
1771 echo "<th width='20%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '0', ${rackData['height']})\">Front</a></th>";
1772 echo "<th width='50%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '1', ${rackData['height']})\">Interior</a></th>";
1773 echo "<th width='20%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '2', ${rackData['height']})\">Back</a></th></tr>\n";
0a7feebb
AD
1774 echo "</table>\n<br>\n";
1775 // Determine zero-u checkbox status.
1776 // If form has been submitted, use form data, otherwise use DB data.
1777 if (isset($_REQUEST['op']))
1778 $checked = isset($_REQUEST['zerou_'.$rack_id]) ? 'checked' : '';
1779 else
1780 $checked = in_array($rack_id, $parentRacks) ? 'checked' : '';
bd0bfb76
AD
1781 echo "Zero-U: <input type=checkbox ${checked} name=zerou_${rack_id} id=zerou_${rack_id}>\n<br><br>\n";
1782 echo "<input type='button' onclick='uncheckAll();' value='Uncheck all'>\n";
0a7feebb 1783 echo '</center></td>';
e673ee24
DO
1784 }
1785 echo "</tr></table>";
1786 finishPortlet();
1787 echo "</td>\n";
1788
1789 echo "</form>\n";
1790 echo "</tr></table>\n";
1791}
1792
1793function renderMolecule ($mdata, $object_id)
1794{
1795 // sort data out
1796 $rackpack = array();
1797 global $loclist;
64b95774 1798 foreach ($mdata as $rua)
e673ee24
DO
1799 {
1800 $rack_id = $rua['rack_id'];
1801 $unit_no = $rua['unit_no'];
1802 $atom = $rua['atom'];
1803 if (!isset ($rackpack[$rack_id]))
1804 {
61a1d996
DO
1805 $rackData = spotEntity ('rack', $rack_id);
1806 amplifyCell ($rackData);
e673ee24
DO
1807 for ($i = $rackData['height']; $i > 0; $i--)
1808 for ($locidx = 0; $locidx < 3; $locidx++)
1809 $rackData[$i][$locidx]['state'] = 'F';
1810 $rackpack[$rack_id] = $rackData;
1811 }
1812 $rackpack[$rack_id][$unit_no][$loclist[$atom]]['state'] = 'T';
1813 $rackpack[$rack_id][$unit_no][$loclist[$atom]]['object_id'] = $object_id;
1814 }
1815 // now we have some racks to render
64b95774 1816 foreach ($rackpack as $rackData)
e673ee24
DO
1817 {
1818 markAllSpans ($rackData);
1819 echo "<table class=molecule cellspacing=0>\n";
1820 echo "<caption>${rackData['name']}</caption>\n";
1821 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>Front</th><th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
1822 for ($i = $rackData['height']; $i > 0; $i--)
1823 {
1824 echo "<tr><th>$i</th>";
1825 for ($locidx = 0; $locidx < 3; $locidx++)
1826 {
1827 $state = $rackData[$i][$locidx]['state'];
65e557dd 1828 echo "<td class='atom state_${state}'>&nbsp;</td>\n";
e673ee24
DO
1829 }
1830 echo "</tr>\n";
1831 }
1832 echo "</table>\n";
1833 }
1834}
1835
23cdc7e9 1836function renderDepot ()
e673ee24 1837{
23cdc7e9 1838 global $pageno, $nextorder;
23cdc7e9
DO
1839 $cellfilter = getCellFilter();
1840 $objects = filterCellList (listCells ('object'), $cellfilter['expression']);
1841
1842 echo "<table border=0 class=objectview>\n";
1843 echo "<tr><td class=pcleft>";
1844
1ebbf889 1845 if (! renderEmptyResults ($cellfilter, 'objects', count($objects)))
e673ee24 1846 {
4899096d 1847 if (count($objects) > 0)
1ebbf889 1848 {
4899096d
AD
1849 startPortlet ('Objects (' . count ($objects) . ')');
1850 echo '<br><br><table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
81659c05 1851 echo '<tr><th>Common name</th><th>Visible label</th><th>Asset tag</th><th>Row/Rack</th></tr>';
4899096d 1852 $order = 'odd';
3f8a25d6
DO
1853 # gather IDs of all objects and fetch rackspace info in one pass
1854 $idlist = array();
1855 foreach ($objects as $obj)
1856 $idlist[] = $obj['id'];
1857 $mountinfo = getMountInfo ($idlist);
4899096d
AD
1858 foreach ($objects as $obj)
1859 {
1860 if (isset ($_REQUEST['hl_object_id']) and $_REQUEST['hl_object_id'] == $obj['id'])
1861 $secondclass = 'tdleft port_highlight';
1862 else
1863 $secondclass = 'tdleft';
1864 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>";
1865 if (count ($obj['etags']))
1866 echo '<br><small>' . serializeTags ($obj['etags'], makeHref(array('page'=>$pageno, 'tab'=>'default')) . '&') . '</small>';
1867 echo "</td><td class='${secondclass}'>${obj['label']}</td>";
1868 echo "<td class='${secondclass}'>${obj['asset_no']}</td>";
3f8a25d6
DO
1869 $places = array();
1870 if (! array_key_exists ($obj['id'], $mountinfo))
1871 $places[] = 'Unmounted';
4899096d 1872 else
3f8a25d6
DO
1873 foreach ($mountinfo[$obj['id']] as $mi)
1874 $places[] = mkA ($mi['row_name'], 'row', $mi['row_id']) . '/' . mkA ($mi['rack_name'], 'rack', $mi['rack_id']);
1875 echo "<td class='${secondclass}'>" . implode (', ', $places) . '</td>';
4899096d
AD
1876 echo '</tr>';
1877 $order = $nextorder[$order];
1878 }
1879 echo '</table>';
1880 finishPortlet();
1ebbf889 1881 }
4899096d
AD
1882 else
1883 echo '<h2>No objects exist</h2>';
e673ee24 1884 }
23cdc7e9
DO
1885
1886 echo "</td><td class=pcright width='25%'>";
1887
95857b5c 1888 renderCellFilterPortlet ($cellfilter, 'object', $objects);
23cdc7e9 1889 echo "</td></tr></table>\n";
e673ee24
DO
1890}
1891
1ebbf889
AA
1892// This function returns TRUE if the result set is too big to be rendered, and no filter is set.
1893// In this case it renders the describing message instead.
1894function renderEmptyResults($cellfilter, $entities_name, $count = NULL)
1895{
1896 if (!$cellfilter['is_empty'])
1897 return FALSE;
1898 if (isset ($_REQUEST['show_all_objects']))
1899 return FALSE;
1900 $max = intval(getConfigVar('MAX_UNFILTERED_ENTITIES'));
1901 if (0 == $max || $count <= $max)
1902 return FALSE;
1903
1904 $href_show_all = trim($_SERVER['REQUEST_URI'], '&');
1905 $href_show_all .= htmlspecialchars('&show_all_objects=1');
1906 $suffix = isset ($count) ? " ($count)" : '';
1907 echo <<<END
1908<p>Please set a filter to display the corresponging $entities_name.
1909<br><a href="$href_show_all">Show all $entities_name$suffix</a>
1910END;
1911 return TRUE;
1912}
1913
e673ee24 1914// History viewer for history-enabled simple dictionaries.
9b8174d7 1915function renderObjectHistory ($object_id)
e673ee24 1916{
e673ee24
DO
1917 $order = 'odd';
1918 global $nextorder;
9b8174d7
AD
1919 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
1920 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>';
1921 $result = usePreparedSelectBlade
1922 (
1923 'SELECT ctime, user_name, name, label, asset_no, has_problems, comment FROM ObjectHistory WHERE id=? ORDER BY ctime',
1924 array ($object_id)
1925 );
e673ee24
DO
1926 while ($row = $result->fetch (PDO::FETCH_NUM))
1927 {
1928 echo "<tr class=row_${order}><td>${row[0]}</td>";
9b8174d7 1929 for ($i = 1; $i <= 6; $i++)
e673ee24
DO
1930 echo "<td>" . $row[$i] . "</td>";
1931 echo "</tr>\n";
1932 $order = $nextorder[$order];
1933 }
1934 echo "</table><br>\n";
1935}
1936
1937function renderRackspaceHistory ()
1938{
4fbb5a00 1939 global $nextorder, $pageno, $tabno;
e673ee24
DO
1940 $order = 'odd';
1941 $history = getRackspaceHistory();
1942 // Show the last operation by default.
1943 if (isset ($_REQUEST['op_id']))
1944 $op_id = $_REQUEST['op_id'];
1945 elseif (isset ($history[0]['mo_id']))
1946 $op_id = $history[0]['mo_id'];
1947 else $op_id = NULL;
1948
1949 $omid = NULL;
1950 $nmid = NULL;
1951 $object_id = 1;
1952 if ($op_id)
1953 list ($omid, $nmid) = getOperationMolecules ($op_id);
1954
1955 // Main layout starts.
1956 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
1957
1958 // Left top portlet with old allocation.
1959 echo "<tr><td class=pcleft>";
1960 startPortlet ('Old allocation');
1961 if ($omid)
1962 {
1963 $oldMolecule = getMolecule ($omid);
1964 renderMolecule ($oldMolecule, $object_id);
1965 }
1966 else
1967 echo "nothing";
1968 finishPortlet();
1969
1970 echo '</td><td class=pcright>';
1971
1972 // Right top portlet with new allocation
1973 startPortlet ('New allocation');
1974 if ($nmid)
1975 {
1976 $newMolecule = getMolecule ($nmid);
1977 renderMolecule ($newMolecule, $object_id);
1978 }
1979 else
1980 echo "nothing";
1981 finishPortlet();
737a3f72 1982
e673ee24 1983 echo '</td></tr><tr><td colspan=2>';
737a3f72 1984
e673ee24
DO
1985 // Bottom portlet with list
1986
1987 startPortlet ('Rackspace allocation history');
1988 echo "<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>\n";
7fa7047a 1989 echo "<tr><th>timestamp</th><th>author</th><th>object</th><th>comment</th></tr>\n";
e673ee24
DO
1990 foreach ($history as $row)
1991 {
1992 if ($row['mo_id'] == $op_id)
1993 $class = 'hl';
1994 else
1995 $class = "row_${order}";
4fbb5a00 1996 echo "<tr class=${class}><td><a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'op_id'=>$row['mo_id']))."'>${row['ctime']}</a></td>";
7fa7047a
DO
1997 echo "<td>${row['user_name']}</td><td>";
1998 renderCell (spotEntity ('object', $row['ro_id']));
9c6222ef 1999 echo '</td><td>' . niftyString ($row['comment'], 0) . '</td></tr>';
e673ee24
DO
2000 $order = $nextorder[$order];
2001 }
2002 echo "</table>\n";
2003 finishPortlet();
737a3f72 2004
e673ee24 2005 echo '</td></tr></table>';
e673ee24
DO
2006}
2007
1f54e1ba 2008function renderIPv4SpaceRecords ($tree, $baseurl, $target = 0, $knight, $level = 1)
d65353ad
DO
2009{
2010 $self = __FUNCTION__;
ca4eb604
DO
2011 static $vdomlist = NULL;
2012 if ($vdomlist == NULL and getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
e829e76b 2013 $vdomlist = getVLANDomainOptions();
00276508
AA
2014
2015 // scroll page to the highlighted item
2016 if ($target && isset ($_REQUEST['hl_net']))
65e557dd 2017 addAutoScrollScript ("net-$target");
00276508 2018
d65353ad
DO
2019 foreach ($tree as $item)
2020 {
64347dcf 2021 if (getConfigVar ('IPV4_TREE_SHOW_USAGE') == 'yes')
64347dcf 2022 loadIPv4AddrList ($item); // necessary to compute router list and address counter
64347dcf
DO
2023 else
2024 {
2025 $item['addrlist'] = array();
2026 $item['addrc'] = 0;
2027 }
b1e39212
DO
2028 $used = $item['addrc'];
2029 $maxdirect = $item['addrt'];
2030 $maxtotal = binInvMaskFromDec ($item['mask']) + 1;
0137d53c
DO
2031 if (isset ($item['id']))
2032 {
1f54e1ba 2033 $decor = array ('indent' => $level);
fec0c8da 2034 if ($item['symbol'] == 'node-collapsed')
00276508 2035 $decor['symbolurl'] = "${baseurl}&eid=" . $item['id'];
fec0c8da 2036 elseif ($item['symbol'] == 'node-expanded')
00276508 2037 $decor['symbolurl'] = $baseurl . ($item['parent_id'] ? "&eid=${item['parent_id']}" : '');
0137d53c 2038 echo "<tr valign=top>";
21ee3351 2039 if ($target == $item['id'] && isset ($_REQUEST['hl_net']))
ee8688c4 2040 $decor['tdclass'] = 'port_highlight';
21ee3351 2041 printIPNetInfoTDs ($item, $decor);
0137d53c 2042 echo "<td class=tdcenter>";
64347dcf
DO
2043 if (getConfigVar ('IPV4_TREE_SHOW_USAGE') == 'yes')
2044 {
b1e39212
DO
2045 renderProgressBar ($maxdirect ? $used/$maxdirect : 0);
2046 echo "<br><small>${used}/${maxdirect}" . ($maxdirect == $maxtotal ? '' : "/${maxtotal}") . '</small>';
64347dcf
DO
2047 }
2048 else
b1e39212 2049 echo "<small>${maxdirect}</small>";
64347dcf 2050 echo "</td>";
ca4eb604
DO
2051 if (getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2052 {
a5f9d1ca
DO
2053 echo '<td class=tdleft>';
2054 if (count ($item['8021q']))
ca4eb604 2055 {
a5f9d1ca
DO
2056 echo '<ul>';
2057 foreach ($item['8021q'] as $binding)
2058 {
2059 echo '<li><a href="' . makeHref (array ('page' => 'vlan', 'vlan_ck' => $binding['domain_id'] . '-' . $binding['vlan_id'])) . '">';
e829e76b
DO
2060 // FIXME: would formatVLANName() do this?
2061 echo $binding['vlan_id'] . '@' . niftyString ($vdomlist[$binding['domain_id']], 15) . '</a></li>';
a5f9d1ca
DO
2062 }
2063 echo '</ul>';
ca4eb604
DO
2064 }
2065 echo '</td>';
2066 }
0137d53c 2067 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
4a47d34b 2068 printRoutersTD (findRouters ($item['addrlist']), getConfigVar ('IPV4_TREE_RTR_AS_CELL'));
0137d53c 2069 echo "</tr>";
fec0c8da 2070 if ($item['symbol'] == 'node-expanded' or $item['symbol'] == 'node-expanded-static')
1f54e1ba 2071 $self ($item['kids'], $baseurl, $target, $knight, $level + 1);
0137d53c
DO
2072 }
2073 else
2074 {
0137d53c 2075 echo "<tr valign=top>";
21ee3351 2076 printIPNetInfoTDs ($item, array ('indent' => $level, 'knight' => $knight, 'tdclass' => 'sparenetwork'));
0137d53c 2077 echo "<td class=tdcenter>";
64347dcf
DO
2078 if (getConfigVar ('IPV4_TREE_SHOW_USAGE') == 'yes')
2079 {
b1e39212
DO
2080 renderProgressBar ($used/$maxtotal, 'sparenetwork');
2081 echo "<br><small>${used}/${maxtotal}</small>";
64347dcf
DO
2082 }
2083 else
b1e39212 2084 echo "<small>${maxtotal}</small>";
ee3eac34
DO
2085 if (getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2086 echo '</td><td>&nbsp;</td>';
64347dcf 2087 echo "</td><td>&nbsp;</td></tr>";
0137d53c 2088 }
d65353ad
DO
2089 }
2090}
2091
21ee3351
AA
2092function renderIPv6SpaceRecords ($tree, $baseurl, $target = 0, $knight, $level = 1)
2093{
2094 $self = __FUNCTION__;
2095 static $vdomlist = NULL;
2096 if ($vdomlist == NULL and getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2097 $vdomlist = getVLANDomainOptions();
00276508
AA
2098
2099 // scroll page to the highlighted item
2100 if ($target && isset ($_REQUEST['hl_net']))
65e557dd 2101 addAutoScrollScript ("net-$target");
00276508 2102
21ee3351
AA
2103 foreach ($tree as $item)
2104 {
2105 if (getConfigVar ('IPV4_TREE_SHOW_USAGE') == 'yes')
2106 loadIPv6AddrList ($item); // necessary to compute router list and address counter
2107 else
2108 {
2109 $item['addrlist'] = array();
2110 $item['addrc'] = 0;
2111 }
2112 if (isset ($item['id']))
2113 {
2114 $decor = array ('indent' => $level);
2115 if ($item['symbol'] == 'node-collapsed')
00276508 2116 $decor['symbolurl'] = "${baseurl}&eid=" . $item['id'];
21ee3351
AA
2117 elseif ($item['symbol'] == 'node-expanded')
2118 $decor['symbolurl'] = $baseurl . ($item['parent_id'] ? "&eid=${item['parent_id']}#net6id${item['parent_id']}" : '');
2119 echo "<tr valign=top>";
2120 if ($target == $item['id'] && isset ($_REQUEST['hl_net']))
88317562 2121 $decor['tdclass'] = ' port_highlight';
21ee3351
AA
2122 printIPNetInfoTDs ($item, $decor);
2123 echo "<td class=tdcenter>";
21ee3351
AA
2124 // show net usage
2125 echo formatIPv6NetUsage ($item['addrc'], $item['mask']);
2126 echo "</td>";
2127 if (getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2128 {
2129 echo '<td class=tdleft>';
2130 if (count ($item['8021q']))
2131 {
2132 echo '<ul>';
2133 foreach ($item['8021q'] as $binding)
2134 {
2135 echo '<li><a href="' . makeHref (array ('page' => 'vlan', 'vlan_ck' => $binding['domain_id'] . '-' . $binding['vlan_id'])) . '">';
2136 // FIXME: would formatVLANName() do this?
2137 echo $binding['vlan_id'] . '@' . niftyString ($vdomlist[$binding['domain_id']], 15) . '</a></li>';
2138 }
2139 echo '</ul>';
2140 }
2141 echo '</td>';
2142 }
2143 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2144 printRoutersTD (findRouters ($item['addrlist']), getConfigVar ('IPV4_TREE_RTR_AS_CELL'));
2145 echo "</tr>";
2146 if ($item['symbol'] == 'node-expanded' or $item['symbol'] == 'node-expanded-static')
2147 $self ($item['kids'], $baseurl, $target, $knight, $level + 1);
2148 }
2149 /* do not display spare networks
2150 else
2151 { // display spare networks
2152 echo "<tr valign=top>";
2153 printIPNetInfoTDs ($item, array ('indent' => $level, 'knight' => $knight, 'tdclass' => 'sparenetwork'));
2154 echo "<td class=tdcenter>";
2155 echo formatIPv6NetUsage ($item['addrc'], $item['mask']);
2156 if (getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2157 echo '</td><td>&nbsp;</td>';
2158 echo "</td><td>&nbsp;</td></tr>";
2159 }*/
2160 }
2161}
2162
2163// if $used is NULL, returns only human-formatted mask.
2164// Otherwise returns "$used in/of " . human-formatted-mask
2165function formatIPv6NetUsage ($used, $mask)
2166{
2167 $prefixes = array
2168 (
2169 0 => '',
2170 3 => 'k',
2171 6 => 'M',
2172 9 => 'G',
2173 12 => 'T',
2174 15 => 'P',
2175 18 => 'E',
2176 21 => 'Z',
2177 24 => 'Y',
2178 );
2179
2180 if ($mask <= 64)
2181 {
2182 $what = '/64 net';
2183 $preposition = 'in';
2184 $mask += 64;
2185 }
2186 else
2187 {
2188 $what = 'IP';
2189 $preposition = 'of';
2190 }
2191 $what .= (0 == $mask % 64 ? '' : 's');
2192 $addrc = isset ($used) ? "$used $preposition " : '';
2193
2194 $dec_order = intval ((128 - $mask) / 10) * 3;
2195 $mult = isset ($prefixes[$dec_order]) ? $prefixes[$dec_order] : '??';
2196
2197 $cnt = 1 << ((128 - $mask) % 10);
2198 if ($cnt == 1 && $mult == '')
2199 $cnt = 'single';
2200
2201 return "<small>${addrc}${cnt}${mult} ${what}</small>";
2202}
2203
04d619d0 2204function renderIPv4Space ()
e673ee24 2205{
4fbb5a00 2206 global $pageno, $tabno;
31c941ec 2207 $cellfilter = getCellFilter();
1f54e1ba
DO
2208 $netlist = listCells ('ipv4net');
2209 $allcount = count ($netlist);
2210 $netlist = filterCellList ($netlist, $cellfilter['expression']);
4fbb5a00 2211
94a40058 2212 $netcount = count ($netlist);
5388794d
DO
2213 // expand request can take either natural values or "ALL". Zero means no expanding.
2214 $eid = isset ($_REQUEST['eid']) ? $_REQUEST['eid'] : 0;
2215 $tree = prepareIPv4Tree ($netlist, $eid);
3630d1fb
DO
2216
2217 echo "<table border=0 class=objectview>\n";
2218 echo "<tr><td class=pcleft>";
1ebbf889
AA
2219 if (! renderEmptyResults($cellfilter, 'IPv4 nets', count($tree)))
2220 {
2221 startPortlet ("networks (${netcount})");
2222 echo '<h4>';
2223 if ($eid === 0)
2224 echo 'auto-collapsing at threshold ' . getConfigVar ('TREE_THRESHOLD') .
2225 " (<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'eid'=>'ALL')) .
2226 $cellfilter['urlextra'] . "'>expand all</a>)";
2227 elseif ($eid === 'ALL')
2228 echo "expanding all (<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno)) .
2229 $cellfilter['urlextra'] . "'>auto-collapse</a>)";
2230 else
2231 {
2232 $netinfo = spotEntity ('ipv4net', $eid);
2233 echo "expanding ${netinfo['ip']}/${netinfo['mask']} (<a href='" .
2234 makeHref (array ('page' => $pageno, 'tab' => $tabno)) .
2235 $cellfilter['urlextra'] . "'>auto-collapse</a> / <a href='" .
2236 makeHref (array ('page' => $pageno, 'tab' => $tabno, 'eid' => 'ALL')) .
2237 $cellfilter['urlextra'] . "'>expand&nbsp;all</a>)";
2238 }
2239 echo "</h4><table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2240 echo "<tr><th>prefix</th><th>name/tags</th><th>capacity</th>";
2241 if (getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2242 echo '<th>VLAN</th>';
2243 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2244 echo "<th>routed by</th>";
2245 echo "</tr>\n";
2246 $baseurl = makeHref(array('page'=>$pageno, 'tab'=>$tabno)) . $cellfilter['urlextra'];
2247 renderIPv4SpaceRecords ($tree, $baseurl, $eid, $netcount == $allcount and getConfigVar ('IPV4_ENABLE_KNIGHT') == 'yes');
2248 echo "</table>\n";
2249 finishPortlet();
5388794d 2250 }
1ebbf889 2251
74ccacff 2252 echo '</td><td class=pcright>';
95857b5c 2253 renderCellFilterPortlet ($cellfilter, 'ipv4net', $netlist);
74ccacff 2254 echo "</td></tr></table>\n";
f973f491 2255}
a7fe7729 2256
21ee3351
AA
2257function renderIPv6Space ()
2258{
2259 global $pageno, $tabno;
2260 $cellfilter = getCellFilter();
2261 $netlist = listCells ('ipv6net');
2262 $allcount = count ($netlist);
2263 $netlist = filterCellList ($netlist, $cellfilter['expression']);
21ee3351
AA
2264
2265 $netcount = count ($netlist);
2266 // expand request can take either natural values or "ALL". Zero means no expanding.
2267 $eid = isset ($_REQUEST['eid']) ? $_REQUEST['eid'] : 0;
2268 $tree = prepareIPv6Tree ($netlist, $eid);
2269
2270 echo "<table border=0 class=objectview>\n";
2271 echo "<tr><td class=pcleft>";
2272 if (! renderEmptyResults($cellfilter, 'IPv6 nets', count($tree)))
2273 {
2274 startPortlet ("networks (${netcount})");
2275 echo '<h4>';
2276 if ($eid === 0)
2277 echo 'auto-collapsing at threshold ' . getConfigVar ('TREE_THRESHOLD') .
2278 " (<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'eid'=>'ALL')) .
2279 $cellfilter['urlextra'] . "'>expand all</a>)";
2280 elseif ($eid === 'ALL')
2281 echo "expanding all (<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno)) .
2282 $cellfilter['urlextra'] . "'>auto-collapse</a>)";
2283 else
2284 {
2285 $netinfo = spotEntity ('ipv6net', $eid);
2286 echo "expanding ${netinfo['ip']}/${netinfo['mask']} (<a href='" .
2287 makeHref (array ('page' => $pageno, 'tab' => $tabno)) .
2288 $cellfilter['urlextra'] . "'>auto-collapse</a> / <a href='" .
2289 makeHref (array ('page' => $pageno, 'tab' => $tabno, 'eid' => 'ALL')) .
2290 $cellfilter['urlextra'] . "'>expand&nbsp;all</a>)";
2291 }
2292 echo "</h4><table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2293 echo "<tr><th>prefix</th><th>name/tags</th><th>capacity</th>";
2294 if (getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2295 echo '<th>VLAN</th>';
2296 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2297 echo "<th>routed by</th>";
2298 echo "</tr>\n";
2299 $baseurl = makeHref(array('page'=>$pageno, 'tab'=>$tabno)) . $cellfilter['urlextra'];
2300 renderIPv6SpaceRecords ($tree, $baseurl, $eid, $netcount == $allcount and getConfigVar ('IPV4_ENABLE_KNIGHT') == 'yes');
2301 echo "</table>\n";
2302 finishPortlet();
2303 }
2304
2305 echo '</td><td class=pcright>';
2306 renderCellFilterPortlet ($cellfilter, 'ipv6net', $netlist);
2307 echo "</td></tr></table>\n";
2308}
2309
04d619d0 2310function renderIPv4SpaceEditor ()
e673ee24 2311{
93a49e5b
AA
2312 $addrspaceList = listCells ('ipv4net');
2313 startPortlet ('Manage existing (' . count ($addrspaceList) . ')');
2314 if (count ($addrspaceList))
f857f71f 2315 {
04d619d0 2316 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
b1e39212 2317 echo "<tr><th>&nbsp;</th><th>prefix</th><th>name</th><th>capacity</th></tr>";
d3dcdfbb
DO
2318 $tree = prepareIPv4Tree ($addrspaceList, 'ALL');
2319 // this is only called for having "trace" set
2320 treeFromList ($addrspaceList);
0c16ef0c 2321 foreach ($addrspaceList as $netinfo)
e673ee24 2322 {
b1e39212
DO
2323 $netinfo = peekNode ($tree, $netinfo['trace'], $netinfo['id']);
2324 // now we have all subnets listed in netinfo
2325 loadIPv4AddrList ($netinfo);
2326 $used = $netinfo['addrc'];
2327 $maxdirect = $netinfo['addrt'];
2328 $maxtotal = binInvMaskFromDec ($netinfo['mask']) + 1;
e43a2de4 2329 echo "<tr valign=top><td>";
93a49e5b 2330 if (! isIPNetworkEmpty ($netinfo))
21ee3351
AA
2331 printImageHREF ('nodestroy', 'There are ' . count ($netinfo['addrlist']) . ' allocations inside');
2332 else
93a49e5b 2333 echo getOpLink (array ('op' => 'del', 'id' => $netinfo['id']), '', 'destroy', 'Delete this prefix');
21ee3351
AA
2334 echo '</td><td class=tdleft><a href="' . makeHref (array ('page' => 'ipv4net', 'id' => $netinfo['id'])) . '">';
2335 echo "${netinfo['ip']}/${netinfo['mask']}</a></td>";
2336 echo '<td class=tdleft>' . niftyString ($netinfo['name']);
2337 if (count ($netinfo['etags']))
2338 echo '<br><small>' . serializeTags ($netinfo['etags']) . '</small>';
2339 echo '</td><td>';
2340 renderProgressBar ($maxdirect ? $used/$maxdirect : 0);
2341 echo "<br><small>${used}/${maxdirect}" . ($maxdirect == $maxtotal ? '' : "/${maxtotal}") . '</small></td>';
2342 echo '</tr>';
2343 }
2344 echo "</table>";
2345 finishPortlet();
2346 }
21ee3351 2347}
e43a2de4 2348
21ee3351
AA
2349function renderIPv6SpaceEditor ()
2350{
93a49e5b
AA
2351 $addrspaceList = listCells ('ipv6net');
2352 startPortlet ('Manage existing (' . count ($addrspaceList) . ')');
2353 if (count ($addrspaceList))
21ee3351 2354 {
21ee3351
AA
2355 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2356 echo "<tr><th>&nbsp;</th><th>prefix</th><th>name</th><th>capacity</th></tr>";
21ee3351
AA
2357 $tree = prepareIPv6Tree ($addrspaceList, 'ALL');
2358 // this is only called for having "trace" set
2359 treeFromList ($addrspaceList);
2360 foreach ($addrspaceList as $netinfo)
2361 {
2362 $netinfo = peekNode ($tree, $netinfo['trace'], $netinfo['id']);
2363 // now we have all subnets listed in netinfo
2364 loadIPv6AddrList ($netinfo);
2365 echo "<tr valign=top><td>";
93a49e5b 2366 if (! isIPNetworkEmpty ($netinfo))
21ee3351
AA
2367 printImageHREF ('nodestroy', 'There are ' . count ($netinfo['addrlist']) . ' allocations inside');
2368 else
93a49e5b 2369 echo getOpLink (array ('op' => 'del', 'id' => $netinfo['id']), '', 'destroy', 'Delete this prefix');
21ee3351 2370 echo '</td><td class=tdleft><a href="' . makeHref (array ('page' => 'ipv6net', 'id' => $netinfo['id'])) . '">';
ab1283b7 2371 echo "${netinfo['ip']}/${netinfo['mask']}</a></td>";
1f54e1ba
DO
2372 echo '<td class=tdleft>' . niftyString ($netinfo['name']);
2373 if (count ($netinfo['etags']))
2374 echo '<br><small>' . serializeTags ($netinfo['etags']) . '</small>';
2375 echo '</td><td>';
21ee3351 2376 echo formatIPv6NetUsage ($netinfo['addrc'], $netinfo['mask']);
b1e39212 2377 echo '</tr>';
e673ee24 2378 }
04d619d0
DO
2379 echo "</table>";
2380 finishPortlet();
e673ee24 2381 }
93a49e5b
AA
2382}
2383
2384function renderIPNewNetForm ()
2385{
2386 global $pageno;
2387 if ($pageno == 'ipv6space')
2388 {
2389 $realm = 'ipv6net';
3495ec6e 2390 $regexp = '^[a-fA-F0-9:]*:[a-fA-F0-9:\.]*/\d{1,3}$';
93a49e5b
AA
2391 }
2392 else
2393 {
2394 $realm = 'ipv4net';
3495ec6e 2395 $regexp = '^(\d{1,3}\.){3}\d{1,3}/\d{1,2}$';
93a49e5b
AA
2396 }
2397
2398 // IP prefix validator
2399 addJs ('js/live_validation.js');
2400 $regexp = addslashes ($regexp);
2401 addJs (<<<END
2402$(document).ready(function () {
2403 document.add_new_range.range.setAttribute('match', '$regexp');
2404 Validate.init();
2405});
2406END
2407 , TRUE);
2408
2409 startPortlet ('Add new');
2410 echo '<table border=0 cellpadding=10 align=center>';
2411 // This form requires a name, so JavaScript validator can find it.
2412 // No printOpFormIntro() hence
2413 echo "<form method=post name='add_new_range' action='".makeHrefProcess()."'>\n";
2414 echo "<input type=hidden name=op value=add>\n";
2415 // tags column
2416 echo '<tr><td rowspan=5><h3>assign tags</h3>';
2417 renderNewEntityTags ($realm);
2418 echo '</td>';
2419 // inputs column
2420 $prefix_value = empty ($_REQUEST['set-prefix']) ? '' : $_REQUEST['set-prefix'];
2421 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>";
2422 echo '<tr><th class=tdright>VLAN</th><td class=tdleft>';
2423 echo getOptionTree ('vlan_ck', getAllVLANOptions(), array ('select_class' => 'vertical', 'tabindex' => 2)) . '</td></tr>';
2424 echo "<tr><th class=tdright>name</th><td class=tdleft><input type=text name='name' size='20' tabindex=3></td></tr>";
2425 echo '<tr><td class=tdright><input type=checkbox name="is_connected" tabindex=4></td><th class=tdleft>reserve subnet-router anycast address</th></tr>';
2426 echo "<tr><td colspan=2>";
2427 printImageHREF ('CREATE', 'Add a new network', TRUE, 5);
2428 echo '</td></tr>';
2429 echo "</form></table><br><br>\n";
2430 finishPortlet();
e673ee24
DO
2431}
2432
beb9e88a 2433function renderIPv4Network ($id)
e673ee24 2434{
c8824ff4 2435 global $pageno, $tabno, $aac2, $netmaskbylen, $wildcardbylen;
e673ee24 2436
d724d290 2437 $range = spotEntity ('ipv4net', $id);
b6b87070 2438 loadIPv4AddrList ($range);
2034d968 2439 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
99ab184f
DO
2440 echo "<tr><td colspan=2 align=center><h1>${range['ip']}/${range['mask']}</h1><h2>";
2441 echo htmlspecialchars ($range['name'], ENT_QUOTES, 'UTF-8') . "</h2></td></tr>\n";
2034d968
DO
2442
2443 echo "<tr><td class=pcleft width='50%'>";
646272be
AA
2444
2445 // render summary portlet
2446 $summary = array();
2034d968
DO
2447 $total = ($range['ip_bin'] | $range['mask_bin_inv']) - ($range['ip_bin'] & $range['mask_bin']) + 1;
2448 $used = count ($range['addrlist']);
646272be 2449 $summary['%% used'] = getProgressBar ($used/$total) . "&nbsp;${used}/${total}";
001e61fa
DO
2450 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2451 {
3444ecf2
DO
2452 // Build a backtrace from all parent networks.
2453 $clen = $range['mask'];
2454 $backtrace = array();
2455 while (NULL !== ($upperid = getIPv4AddressNetworkId ($range['ip'], $clen)))
2456 {
d724d290 2457 $upperinfo = spotEntity ('ipv4net', $upperid);
3444ecf2 2458 $clen = $upperinfo['mask'];
d724d290 2459 $backtrace[] = $upperinfo;
3444ecf2
DO
2460 }
2461 $arrows = count ($backtrace);
d724d290 2462 foreach (array_reverse ($backtrace) as $ainfo)
001e61fa 2463 {
646272be 2464 $name = '';
3444ecf2 2465 for ($i = 0; $i < $arrows; $i++)
646272be 2466 $name .= '&uarr;';
3444ecf2 2467 $arrows--;
646272be 2468 $summary[] = array ($name, getOutputOf ('renderCell', $ainfo));
001e61fa 2469 }
646272be 2470 $summary[] = array ('&rarr;', getOutputOf ('renderCell', $range));
001e61fa
DO
2471 // FIXME: get and display nested networks
2472 // $theitem = pickLeaf ($ipv4tree, $id);
2473 }
646272be
AA
2474 $summary[] = array ('Netmask:', $netmaskbylen[$range['mask']]);
2475 $summary[] = array ('Netmask:', sprintf ('0x%08X', binMaskFromDec ($range['mask'])));
2476 $summary['Wildcard bits'] = $wildcardbylen[$range['mask']];
2477
a5f9d1ca 2478 foreach ($range['8021q'] as $item)
cbf78395 2479 {
a5f9d1ca 2480 $vlaninfo = getVLANInfo ($item['domain_id'] . '-' . $item['vlan_id']);
646272be 2481 $summary[] = array ('VLAN:', '<a href="' . makeHref (array ('page' => 'vlan', 'vlan_ck' => $vlaninfo['vlan_ck'])) . '">' . formatVLANName ($vlaninfo, 'markup long') . '</a>');
cbf78395 2482 }
3a4f4023 2483 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes' and count ($routers = findRouters ($range['addrlist'])))
04d619d0 2484 {
646272be
AA
2485 $summary['Routed by'] = '';
2486 foreach ($routers as $rtr)
2487 $summary['Routed by'] .= getOutputOf ('renderRouterCell', $rtr['addr'], $rtr['iface'], spotEntity ('object', $rtr['id']));
04d619d0 2488 }
646272be
AA
2489 $summary['tags'] = '';
2490 renderEntitySummary ($range, 'summary', $summary);
e1ae3fb4 2491
99ab184f
DO
2492 if (strlen ($range['comment']))
2493 {
2494 startPortlet ('Comment');
2495 echo '<div class=commentblock>' . string_insert_hrefs (htmlspecialchars ($range['comment'], ENT_QUOTES, 'UTF-8')) . '</div>';
2496 finishPortlet ();
2497 }
2498
e1ae3fb4 2499 renderFilesPortlet ('ipv4net', $id);
2034d968 2500 echo "</td>\n";
e673ee24 2501
2034d968
DO
2502 echo "<td class=pcright>";
2503 startPortlet ('details');
e673ee24
DO
2504 $startip = $range['ip_bin'] & $range['mask_bin'];
2505 $endip = $range['ip_bin'] | $range['mask_bin_inv'];
2506 $realstartip = $startip;
2507 $realendip = $endip;
e673ee24 2508
00276508
AA
2509 if (isset ($_REQUEST['hl_ipv4_addr']))
2510 {
2511 $hl_ip = ip2long ($_REQUEST['hl_ipv4_addr']);
2512 $hl_dottedquad = ip_long2quad ($hl_ip);
65e557dd 2513 addAutoScrollScript ("ip-$hl_dottedquad"); // scroll page to highlighted ip
00276508
AA
2514 }
2515
79b57b18
AA
2516 // pager
2517 $maxperpage = getConfigVar ('IPV4_ADDRS_PER_PAGE');
2518 $address_count = $endip - $startip + 1;
2519 $page = 0;
446c25c3 2520 $rendered_pager = '';
79b57b18
AA
2521 if ($address_count > $maxperpage && $maxperpage > 0)
2522 {
2523 $page = isset ($_REQUEST['pg']) ? $_REQUEST['pg'] : (isset ($hl_ip) ? intval (($hl_ip - $startip) / $maxperpage) : 0);
2524 if ($numpages = ceil ($address_count / $maxperpage))
2525 {
79b57b18
AA
2526 echo '<h3>' . long2ip ($startip) . ' ~ ' . long2ip ($endip) . '</h3>';
2527 for ($i = 0; $i < $numpages; $i++)
2528 if ($i == $page)
446c25c3 2529 $rendered_pager .= "<b>$i</b> ";
79b57b18 2530 else
446c25c3 2531 $rendered_pager .= "<a href='".makeHref (array ('page' => $pageno, 'tab' => $tabno, 'id' => $id, 'pg' => $i)) . "'>$i</a> ";
79b57b18
AA
2532 }
2533 $startip = $startip + $page * $maxperpage;
2534 $endip = min ($startip + $maxperpage - 1, $endip);
2535 }
2536
446c25c3 2537 echo $rendered_pager;
beb9e88a 2538 echo "<table class='widetable' border=0 cellspacing=0 cellpadding=5 align='center' width='100%'>\n";
e673ee24
DO
2539 echo "<tr><th>Address</th><th>Name</th><th>Allocation</th></tr>\n";
2540
b2035dca 2541 for ($ip = $startip; $ip <= $endip; $ip++) :
00276508
AA
2542 $dottedquad = ip_long2quad($ip);
2543 $secondstyle = 'tdleft' . (isset ($hl_ip) && $hl_ip == $ip ? ' port_highlight' : '');
b2035dca 2544 if (!isset ($range['addrlist'][$ip]))
e673ee24 2545 {
a8dc2982
AA
2546 echo "<tr><td class=tdleft><a class='ancor' name='ip-$dottedquad' href='" . makeHref(array('page'=>'ipaddress', 'ip' => $dottedquad)) . "'>$dottedquad</a></td>";
2547 echo "<td class='rsv-port ${secondstyle}'><span class='rsvtext'></span></td><td class='${secondstyle}'>&nbsp;</td></tr>\n";
b2035dca
DO
2548 continue;
2549 }
b2035dca 2550 $addr = $range['addrlist'][$ip];
68c91b9c
AA
2551 // render IP change history
2552 $title = '';
2553 $history_class = '';
2554 if (isset ($addr['last_log']))
2555 {
2556 $title = ' title="' . htmlspecialchars ($addr['last_log']['user'] . ', ' . formatAge ($addr['last_log']['time']) , ENT_QUOTES) . '"';
2557 $history_class = 'hover-history underline';
2558 }
2d318652 2559 echo "<tr class='${addr['class']}'>";
68c91b9c 2560 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
2561 echo "<td class='${secondstyle} " .
2562 (empty ($addr['allocs']) || !empty ($addr['name']) ? 'rsv-port' : '') .
2563 "'><span class='rsvtext'>${addr['name']}</span></td><td class='${secondstyle}'>";
b2035dca 2564 $delim = '';
b2035dca
DO
2565 if ( $addr['reserved'] == 'yes')
2566 {
2d318652 2567 echo "<strong>RESERVED</strong> ";
b2035dca
DO
2568 $delim = '; ';
2569 }
212b565a 2570 foreach ($addr['allocs'] as $ref)
b2035dca 2571 {
beb9e88a 2572 echo $delim . $aac2[$ref['type']];
68c91b9c 2573 echo "<a href='".makeHref(array('page'=>'object', 'object_id'=>$ref['object_id'], 'tab' => 'default', 'hl_ipv4_addr'=>$addr['ip']))."'>";
59a83bd8 2574 echo $ref['name'] . (!strlen ($ref['name']) ? '' : '@');
b2035dca
DO
2575 echo "${ref['object_name']}</a>";
2576 $delim = '; ';
2577 }
2578 if ($delim != '')
e0d6e38e 2579 $delim = '<br>';
212b565a
AA
2580 foreach ($addr['vslist'] as $vs_id)
2581 {
2582 $vs = spotEntity ('ipv4vs', $vs_id);
2583 echo "${delim}<a href='".makeHref(array('page'=>'ipv4vs', 'vs_id'=>$vs['id']))."'>";
2584 echo "${vs['name']}:${vs['vport']}/${vs['proto']}</a>&rarr;";
2585 $delim = '<br>';
2586 }
2587 foreach ($addr['rsplist'] as $rsp_id)
2588 {
2589 $rsp = spotEntity ('ipv4rspool', $rsp_id);
2590 echo "${delim}&rarr;<a href='".makeHref(array('page'=>'ipv4rspool', 'pool_id'=>$rsp['id']))."'>";
2591 echo "${rsp['name']}</a>";
2592 $delim = '<br>';
2593 }
b2035dca
DO
2594 echo "</td></tr>\n";
2595 endfor;
2727c7df 2596 // end of iteration
a8dc2982
AA
2597 if (permitted (NULL, NULL, 'set_reserve_comment'))
2598 addJS ('js/inplace-edit.js');
e673ee24
DO
2599
2600 echo "</table>";
446c25c3
AA
2601 if (! empty ($rendered_pager))
2602 echo '<p>' . $rendered_pager . '</p>';
2603
2034d968
DO
2604 finishPortlet();
2605 echo "</td></tr></table>\n";
e673ee24
DO
2606}
2607
21ee3351
AA
2608// based on renderIPv4Network
2609function renderIPv6Network ($id)
2610{
2611 $range = spotEntity ('ipv6net', $id);
21ee3351
AA
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{
8dc2a6c8 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)