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