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