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