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