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