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