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