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