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