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