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