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