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