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