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