r2204 - try two more arts for tree view
[racktables] / inc / interface.php
CommitLineData
b325120a 1<?php
e673ee24
DO
2/*
3*
4* This file contains frontend functions for RackTables.
5*
6*/
7
9c0b0016
DO
8// Interface function's special.
9$nextorder['odd'] = 'even';
10$nextorder['even'] = 'odd';
11
52c836b1
DO
12// address allocation type
13$aat = array
14(
15 'regular' => 'Connected',
16 'virtual' => 'Loopback',
17 'shared' => 'Shared',
18 'router' => 'Router',
19);
beb9e88a 20// address allocation code, IPv4 addresses and objects view
52c836b1
DO
21$aac = array
22(
23 'regular' => '',
24 'virtual' => '<strong>L</strong>',
25 'shared' => '<strong>S</strong>',
26 'router' => '<strong>R</strong>',
27);
beb9e88a
DO
28// address allocation code, IPv4 networks view
29$aac2 = array
30(
31 'regular' => '',
32 'virtual' => '<strong>L:</strong>',
33 'router' => '<strong>R:</strong>',
34);
52c836b1 35
7056988c
DO
36// Let's have it here, so extensions can add their own images.
37$image = array();
38$image['error']['path'] = 'pix/error.png';
39$image['error']['width'] = 76;
40$image['error']['height'] = 17;
41$image['logo']['path'] = 'pix/defaultlogo.png';
42$image['logo']['width'] = 210;
43$image['logo']['height'] = 40;
44$image['rackspace']['path'] = 'pix/racks.png';
45$image['rackspace']['width'] = 218;
46$image['rackspace']['height'] = 200;
47$image['objects']['path'] = 'pix/server.png';
48$image['objects']['width'] = 218;
49$image['objects']['height'] = 200;
50$image['ipv4space']['path'] = 'pix/addressspace.png';
51$image['ipv4space']['width'] = 218;
52$image['ipv4space']['height'] = 200;
53$image['ipv4slb']['path'] = 'pix/slb.png';
54$image['ipv4slb']['width'] = 218;
55$image['ipv4slb']['height'] = 200;
56$image['config']['path'] = 'pix/configuration.png';
57$image['config']['width'] = 218;
58$image['config']['height'] = 200;
59$image['reports']['path'] = 'pix/report.png';
60$image['reports']['width'] = 218;
61$image['reports']['height'] = 200;
62$image['useup']['path'] = 'pix/tango-edit-clear.png';
63$image['useup']['width'] = 16;
64$image['useup']['height'] = 16;
65$image['link']['path'] = 'pix/tango-network-wired.png';
66$image['link']['width'] = 16;
67$image['link']['height'] = 16;
68$image['unlink']['path'] = 'pix/tango-edit-clear.png';
69$image['unlink']['width'] = 16;
70$image['unlink']['height'] = 16;
71$image['add']['path'] = 'pix/tango-list-add.png';
72$image['add']['width'] = 16;
73$image['add']['height'] = 16;
74$image['delete']['path'] = 'pix/tango-list-remove.png';
75$image['delete']['width'] = 16;
76$image['delete']['height'] = 16;
77$image['nodelete']['path'] = 'pix/tango-list-remove-shadow.png';
78$image['nodelete']['width'] = 16;
79$image['nodelete']['height'] = 16;
80$image['grant'] = $image['add'];
81$image['revoke'] = $image['delete'];
82$image['inservice']['path'] = 'pix/tango-emblem-system.png';
83$image['inservice']['width'] = 16;
84$image['inservice']['height'] = 16;
85$image['notinservice']['path'] = 'pix/tango-dialog-error.png';
86$image['notinservice']['width'] = 16;
87$image['notinservice']['height'] = 16;
88$image['blockuser'] = $image['inservice'];
89$image['unblockuser'] = $image['notinservice'];
90$image['find']['path'] = 'pix/tango-system-search.png';
91$image['find']['width'] = 16;
92$image['find']['height'] = 16;
93$image['spacer']['path'] = 'pix/pixel.png';
94$image['spacer']['width'] = 16;
95$image['spacer']['height'] = 16;
51b6651a
DO
96$image['MP']['path'] = 'pix/midst-plus.png';
97$image['MP']['width'] = 16;
98$image['MP']['height'] = 16;
99$image['MM']['path'] = 'pix/midst-minus.png';
100$image['MM']['width'] = 16;
101$image['MM']['height'] = 16;
102$image['LP']['path'] = 'pix/last-plus.png';
103$image['LP']['width'] = 16;
104$image['LP']['height'] = 16;
105$image['LM']['path'] = 'pix/last-minus.png';
106$image['LM']['width'] = 16;
107$image['LM']['height'] = 16;
108$image['MT']['path'] = 'pix/midst-terminal.png';
109$image['MT']['width'] = 16;
110$image['MT']['height'] = 16;
111$image['LT']['path'] = 'pix/last-terminal.png';
112$image['LT']['width'] = 16;
113$image['LT']['height'] = 16;
7056988c
DO
114$image['next']['path'] = 'pix/tango-go-next.png';
115$image['next']['width'] = 32;
116$image['next']['height'] = 32;
117$image['prev']['path'] = 'pix/tango-go-previous.png';
118$image['prev']['width'] = 32;
119$image['prev']['height'] = 32;
120$image['clear']['path'] = 'pix/tango-edit-clear.png';
121$image['clear']['width'] = 16;
122$image['clear']['height'] = 16;
61a61189
DO
123$image['CLEAR']['path'] = 'pix/tango-edit-clear-big.png';
124$image['CLEAR']['width'] = 32;
125$image['CLEAR']['height'] = 32;
7056988c
DO
126$image['save']['path'] = 'pix/tango-document-save.png';
127$image['save']['width'] = 16;
128$image['save']['height'] = 16;
129$image['SAVE']['path'] = 'pix/tango-document-save-big.png';
130$image['SAVE']['width'] = 32;
131$image['SAVE']['height'] = 32;
132$image['create']['path'] = 'pix/tango-document-new.png';
133$image['create']['width'] = 16;
134$image['create']['height'] = 16;
135$image['CREATE']['path'] = 'pix/tango-document-new-big.png';
136$image['CREATE']['width'] = 32;
137$image['CREATE']['height'] = 32;
138$image['DENIED']['path'] = 'pix/tango-dialog-error-big.png';
139$image['DENIED']['width'] = 32;
140$image['DENIED']['height'] = 32;
d28d7f4d
DO
141$image['apply']['path'] = 'pix/tango-emblem-system.png';
142$image['apply']['width'] = 16;
143$image['apply']['height'] = 16;
7056988c 144
e5c4506d
DO
145// This may be populated later onsite, report rendering function will use it.
146// See the $systemreport for structure.
147$localreports = array();
148
e673ee24
DO
149// Main menu.
150function renderIndex ()
151{
152 global $root;
153?>
154<table border=0 cellpadding=0 cellspacing=0 width='100%'>
155 <tr>
156 <td>
157 <div style='text-align: center; margin: 10px; '>
158 <table width='100%' cellspacing=0 cellpadding=30 class=mainmenu border=0>
159 <tr>
160 <td>
b325120a
DO
161 <h1><a href='<?php echo $root; ?>?page=rackspace'>Rackspace<br>
162 <?php printImageHREF ('rackspace'); ?></a></h1>
e673ee24
DO
163 </td>
164 <td>
b325120a
DO
165 <h1><a href='<?php echo $root; ?>?page=objects'>Objects<br>
166 <?php printImageHREF ('objects'); ?></a></h1>
e673ee24
DO
167 </td>
168 <td>
b325120a
DO
169 <h1><a href='<?php echo $root; ?>?page=ipv4space'>IPv4 space<br>
170 <?php printImageHREF ('ipv4space'); ?></a></h1>
e673ee24
DO
171 </td>
172 </tr>
173 </table>
174 <table width='100%' cellspacing=0 cellpadding=30 class=mainmenu border=0>
175 <tr>
176 <td>
b325120a
DO
177 <h1><a href='<?php echo $root; ?>?page=config'>Configuration<br>
178 <?php printImageHREF ('config'); ?></a></h1>
e673ee24
DO
179 </td>
180 <td>
da95280e 181 <h1><a href='<?php echo $root; ?>?page=reports'>Reports<br>
b325120a 182 <?php printImageHREF ('reports'); ?></a></h1>
e673ee24 183 </td>
ae545907 184 <td>
f973f491
DO
185 <h1><a href='<?php echo $root; ?>?page=ipv4slb'>IPv4 SLB<br>
186 <?php printImageHREF ('ipv4slb'); ?></a></h1>
ae545907 187 </td>
e673ee24
DO
188 </tr>
189 </table>
190 </div>
191 </td>
192 </tr>
193</table>
b325120a 194<?php
e673ee24
DO
195}
196
197function renderRackspace ()
198{
932cf41f 199 $tagfilter = getTagFilter();
094a8e6e 200 $tagfilter_str = getTagFilterStr ($tagfilter);
489a7502
DO
201 echo "<table class=objview border=0 width='100%'><tr><td class=pcleft>";
202 renderTagFilterPortlet ($tagfilter, 'rack');
203 echo '</td><td class=pcright>';
204 echo '<table border=0 cellpadding=10 cellpadding=1>';
e673ee24 205 // generate thumb gallery
489a7502 206 $rackrowList = getRackspace ($tagfilter);
9c0b0016 207 global $root, $nextorder;
d5157018 208 $rackwidth = getRackImageWidth();
e673ee24
DO
209 $order = 'odd';
210 foreach ($rackrowList as $rackrow)
211 {
84466afa 212 echo "<tr class=row_${order}><th class=tdleft>";
a0d54e7e
DO
213 echo "<a href='${root}?page=row&row_id=${rackrow['row_id']}${tagfilter_str}'>";
214 echo "${rackrow['row_name']}</a></th>";
215 $rackList = getRacksForRow ($rackrow['row_id'], $tagfilter);
e673ee24 216 echo "<td><table border=0 cellspacing=5><tr>";
64b95774 217 foreach ($rackList as $rack)
e673ee24
DO
218 {
219 echo "<td align=center><a href='${root}?page=rack&rack_id=${rack['id']}'>";
220 echo "<img border=0 width=${rackwidth} height=";
d5157018 221 echo getRackImageHeight ($rack['height']);
e673ee24 222 echo " title='${rack['height']} units'";
d2ec5490 223 echo "src='render_image.php?img=minirack&rack_id=${rack['id']}'>";
e673ee24
DO
224 echo "<br>${rack['name']}</a></td>";
225 }
226 echo "</tr></table></tr>\n";
227 $order = $nextorder[$order];
228 }
229 echo "</table>\n";
489a7502 230 echo "</td></tr></table>\n";
e673ee24
DO
231}
232
d5157018 233function renderRow ($row_id = 0)
e673ee24
DO
234{
235 if ($row_id == 0)
236 {
39a6338a 237 showError ('Invalid row_id', __FUNCTION__);
e673ee24
DO
238 return;
239 }
240 if (($rowInfo = getRackRowInfo ($row_id)) == NULL)
241 {
39a6338a 242 showError ('getRackRowInfo() failed', __FUNCTION__);
e673ee24
DO
243 return;
244 }
a0d54e7e
DO
245 $tagfilter = getTagFilter();
246 $rackList = getRacksForRow ($row_id, $tagfilter);
e673ee24
DO
247 // Main layout starts.
248 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
249
250 // Left portlet with row information.
251 echo "<tr><td class=pcleft>";
a8ce7234 252 startPortlet ($rowInfo['name']);
e673ee24 253 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
e673ee24
DO
254 echo "<tr><th width='50%' class=tdright>Racks:</th><td class=tdleft>${rowInfo['count']}</td></tr>\n";
255 echo "<tr><th width='50%' class=tdright>Units:</th><td class=tdleft>${rowInfo['sum']}</td></tr>\n";
04d619d0 256 echo "<tr><th width='50%' class=tdright>%% used:</th><td class=tdleft>";
114e50af
DO
257 renderProgressBar (getRSUforRackRow ($rackList));
258 echo "</td></tr>\n";
e673ee24
DO
259 echo "</table><br>\n";
260 finishPortlet();
261
a0d54e7e 262 echo "</td><td class=pcright rowspan=2>";
e673ee24 263
9c0b0016 264 global $root, $nextorder;
d5157018 265 $rackwidth = getRackImageWidth() * getConfigVar ('ROW_SCALE');
e673ee24
DO
266 $order = 'odd';
267 startPortlet ('Racks');
268 echo "<table border=0 cellspacing=5 align='center'><tr>";
64b95774 269 foreach ($rackList as $rack)
e673ee24
DO
270 {
271 echo "<td align=center class=row_${order}><a href='${root}?page=rack&rack_id=${rack['id']}'>";
d5157018 272 echo "<img border=0 width=${rackwidth} height=" . (getRackImageHeight ($rack['height']) * getConfigVar ('ROW_SCALE'));
e673ee24 273 echo " title='${rack['height']} units'";
d2ec5490 274 echo "src='render_image.php?img=minirack&rack_id=${rack['id']}'>";
e673ee24
DO
275 echo "<br>${rack['name']}</a></td>";
276 $order = $nextorder[$order];
277 }
278 echo "</tr></table>\n";
279 finishPortlet();
a0d54e7e 280 echo "</td></tr>";
e673ee24 281
a0d54e7e
DO
282 echo "<tr><td class=pcleft>";
283 renderTagFilterPortlet ($tagfilter, 'rack', 'row_id', $row_id);
e673ee24
DO
284 echo "</td></tr></table>";
285}
286
04f110a0 287function showError ($info = '', $location = 'N/A')
e673ee24
DO
288{
289 global $root;
04f110a0
DO
290 if (preg_match ('/\.php$/', $location))
291 $location = basename ($location);
292 elseif ($location != 'N/A')
293 $location = $location . '()';
294 echo "<div class=msg_error>An error has occured in [${location}]. ";
e673ee24
DO
295 if (empty ($info))
296 echo 'No additional information is available.';
297 else
298 echo "Additional information:<br><p>\n<pre>\n${info}\n</pre></p>";
299 echo "Go back or try starting from <a href='${root}'>index page</a>.<br></div>\n";
300}
301
302// This function renders rack as HTML table.
303function renderRack ($rack_id = 0, $hl_obj_id = 0)
304{
305 if ($rack_id == 0)
306 {
39a6338a 307 showError ('Invalid rack_id', __FUNCTION__);
e673ee24
DO
308 return;
309 }
310 if (($rackData = getRackData ($rack_id)) == NULL)
311 {
39a6338a 312 showError ('getRackData() failed', __FUNCTION__);
e673ee24
DO
313 return;
314 }
315 global $root, $pageno, $tabno;
316 markAllSpans ($rackData);
317 if ($hl_obj_id > 0)
318 highlightObject ($rackData, $hl_obj_id);
319 markupObjectProblems ($rackData);
320 $prev_id = getPrevIDforRack ($rackData['row_id'], $rack_id);
321 $next_id = getNextIDforRack ($rackData['row_id'], $rack_id);
d48d8820
DO
322 echo "<center><table border=0><tr valign=middle>";
323 echo "<td><h2><a href='${root}?page=row&row_id=${rackData['row_id']}'>${rackData['row_name']}</a> :</h2></td>";
e673ee24
DO
324 // FIXME: use 'bypass'?
325 if ($prev_id != NULL)
9803c56c 326 {
d48d8820 327 echo "<td><a href='${root}?page=rack&rack_id=${prev_id}'>";
9803c56c 328 printImageHREF ('prev', 'previous rack');
d48d8820 329 echo "</a></td>";
9803c56c 330 }
d48d8820 331 echo "<td><h2><a href='${root}?page=rack&rack_id=${rackData['id']}'>${rackData['name']}</a></h2></td>";
e673ee24 332 if ($next_id != NULL)
9803c56c 333 {
d48d8820 334 echo "<td><a href='${root}?page=rack&rack_id=${next_id}'>";
f444c095 335 printImageHREF ('next', 'next rack');
d48d8820 336 echo "</a></td>";
9803c56c 337 }
d48d8820 338 echo "</h2></td></tr></table>\n";
1c81a02c
DO
339 if ($rackData['left_is_front'] == 'yes')
340 $markup = array ('left' => 'Front', 'right' => 'Back');
341 else
342 $markup = array ('left' => 'Back', 'right' => 'Front');
e673ee24 343 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
9ddfe309
DO
344 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>${markup['left']}</th>";
345 echo "<th width='50%'>Interior</th><th width='20%'>${markup['right']}</th></tr>\n";
e673ee24
DO
346 for ($i = $rackData['height']; $i > 0; $i--)
347 {
9ddfe309 348 echo '<tr><th>' . ($rackData['bottom_is_unit1'] == 'yes' ? $i : $rackData['height'] - $i + 1) . '</th>';
e673ee24
DO
349 for ($locidx = 0; $locidx < 3; $locidx++)
350 {
351 if (isset ($rackData[$i][$locidx]['skipped']))
352 continue;
353 $state = $rackData[$i][$locidx]['state'];
354 echo "<td class=state_${state}";
355 if (isset ($rackData[$i][$locidx]['hl']))
356 echo $rackData[$i][$locidx]['hl'];
357 if (isset ($rackData[$i][$locidx]['colspan']))
358 echo ' colspan=' . $rackData[$i][$locidx]['colspan'];
359 if (isset ($rackData[$i][$locidx]['rowspan']))
360 echo ' rowspan=' . $rackData[$i][$locidx]['rowspan'];
361 echo ">";
362 switch ($state)
363 {
364 case 'T':
365 $objectData = getObjectInfo ($rackData[$i][$locidx]['object_id']);
366 if (!empty ($objectData['asset_no']))
367 $prefix = "<div title='${objectData['asset_no']}";
368 else
369 $prefix = "<div title='no asset tag";
370 // Don't tell about label, if it matches common name.
371 if ($objectData['name'] != $objectData['label'] and !empty ($objectData['label']))
372 $suffix = ", visible label is \"${objectData['label']}\"'>";
373 else
374 $suffix = "'>";
375 echo $prefix . $suffix;
376 echo "<a href='${root}?page=object&object_id=${objectData['id']}'>${objectData['dname']}</a></div>";
377 break;
378 case 'A':
379 echo '<div title="This rackspace does not exist">&nbsp;</div>';
380 break;
381 case 'F':
382 echo '<div title="Free rackspace">&nbsp;</div>';
383 break;
384 case 'U':
385 echo '<div title="Problematic rackspace, you CAN\'T mount here">&nbsp;</div>';
386 break;
387 default:
388 echo '<div title="No data">&nbsp;</div>';
389 break;
390 }
391 echo '</td>';
392 }
393 echo "</tr>\n";
394 }
395 echo "</table></center>\n";
396}
397
e673ee24
DO
398function renderNewRackForm ($row_id)
399{
f19c75d6 400 showMessageOrError();
f19c75d6 401
50b4ba85 402 startPortlet ('Add one');
f19c75d6 403 printOpFormIntro ('addRack', array ('got_data' => 'TRUE'));
e673ee24 404 echo '<table border=0 align=center>';
b901bf1f
DO
405 $defh = getConfigVar ('DEFAULT_RACK_HEIGHT');
406 if ($defh == 0)
407 $defh = '';
72d52730
DO
408 echo "<tr><th class=tdright>Rack name (*):</th><td class=tdleft><input type=text name=rack_name tabindex=1></td>";
409 echo "<td rowspan=4>Assign tags:<br>";
410 renderTagSelect();
411 echo "</td></tr>\n";
b8094ae4 412 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 413 echo "<tr><th class=tdright>Comment:</th><td class=tdleft><input type=text name=rack_comment tabindex=3></td></tr>\n";
f19c75d6
DO
414 echo "<tr><td class=submit colspan=2>";
415 printImageHREF ('CREATE', 'Add', TRUE);
416 echo "</td></tr></table></form>";
406b54bd 417 finishPortlet();
406b54bd 418
50b4ba85 419 startPortlet ('Add many');
f19c75d6 420 printOpFormIntro ('addRack', array ('got_mdata' => 'TRUE'));
50b4ba85
DO
421 echo '<table border=0 align=center>';
422 $defh = getConfigVar ('DEFAULT_RACK_HEIGHT');
423 if ($defh == 0)
424 $defh = '';
72d52730
DO
425 echo "<tr><th class=tdright>Height in units (*):</th><td class=tdleft><input type=text name=rack_height2 value='${defh}'></td>";
426 echo "<td rowspan=3 valign=top>Assign tags:<br>";
427 renderTagSelect();
428 echo "</td></tr>\n";
50b4ba85 429 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
430 echo "<tr><td class=submit colspan=2>";
431 printImageHREF ('CREATE', 'Add', TRUE);
e673ee24
DO
432 echo '</form></table>';
433 finishPortlet();
434}
435
436function renderEditObjectForm ($object_id)
437{
438 showMessageOrError();
e673ee24 439
22bb04da 440 global $pageno, $tabno, $root;
e673ee24
DO
441 $object = getObjectInfo ($object_id);
442 if ($object == NULL)
443 {
39a6338a 444 showError ('getObjectInfo() failed', __FUNCTION__);
e673ee24
DO
445 return;
446 }
e673ee24
DO
447 echo '<table border=0 width=100%><tr>';
448
449 echo '<td class=pcleft>';
450 startPortlet ('Static attributes');
43fb6eaf 451 printOpFormIntro ('update');
e673ee24
DO
452 echo '<table border=0 align=center>';
453 echo "<tr><th class=tdright>Type:</th><td class=tdleft>";
454 printSelect (getObjectTypeList(), 'object_type_id', $object['objtype_id']);
455 echo "</td></tr>\n";
22bb04da 456 // baseline info
e673ee24
DO
457 echo "<tr><th class=tdright>Common name:</th><td class=tdleft><input type=text name=object_name value='${object['name']}'></td></tr>\n";
458 echo "<tr><th class=tdright>Visible label:</th><td class=tdleft><input type=text name=object_label value='${object['label']}'></td></tr>\n";
459 echo "<tr><th class=tdright>Asset tag:</th><td class=tdleft><input type=text name=object_asset_no value='${object['asset_no']}'></td></tr>\n";
460 echo "<tr><th class=tdright>Barcode:</th><td class=tdleft><input type=text name=object_barcode value='${object['barcode']}'></td></tr>\n";
461 echo "<tr><th class=tdright>Has problems:</th><td class=tdleft><input type=checkbox name=object_has_problems";
462 if ($object['has_problems'] == 'yes')
463 echo ' checked';
464 echo "></td></tr>\n";
465 echo "<tr><td colspan=2><b>Comment:</b><br><textarea name=object_comment rows=10 cols=80>${object['comment']}</textarea></td></tr>";
5bbbeaa2
DO
466 echo "<tr><th class=submit colspan=2>";
467 printImageHREF ('SAVE', 'Save changes', TRUE);
468 echo "</td></tr>\n";
e673ee24
DO
469 echo '</form></table><br>';
470 finishPortlet();
471 echo '</td>';
472
22bb04da 473 // stickers
e673ee24
DO
474 echo '<td class=pcright>';
475 startPortlet ('Optional attributes');
476 $values = getAttrValues ($object_id);
e673ee24
DO
477 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable>\n";
478 echo "<tr><th>&nbsp;</th><th>Attribute</th><th>Value</th><th>&nbsp;</th></tr>\n";
43fb6eaf 479 printOpFormIntro ('updateStickers');
0dfb8a2a
DO
480 echo '<input type=hidden name=num_attrs value=' . count($values) . ">\n";
481
482 $i = 0;
e673ee24
DO
483 foreach ($values as $record)
484 {
0dfb8a2a 485 echo "<input type=hidden name=${i}_attr_id value=${record['id']}>";
0c4605ab 486 echo '<tr><td>';
ca1fec24 487 if (!empty ($record['value']))
0c4605ab 488 {
22bb04da 489 echo "<a href='${root}process.php?page=${pageno}&tab=${tabno}&op=clearSticker&object_id=${object_id}&attr_id=${record['id']}'>";
d48d8820 490 printImageHREF ('clear', 'Clear value');
0c4605ab
DO
491 echo '</a>';
492 }
493 else
d48d8820 494 echo '&nbsp;';
0c4605ab 495 echo '</td>';
e673ee24
DO
496 echo "<td class=tdright>${record['name']}:</td><td class=tdleft>";
497 switch ($record['type'])
498 {
499 case 'uint':
500 case 'float':
501 case 'string':
0dfb8a2a 502 echo "<input type=text name=${i}_value value='${record['value']}'>";
e673ee24
DO
503 break;
504 case 'dict':
505 $chapter = readChapter ($record['chapter_name']);
4c330a14 506 $chapter[0] = '-- NOT SET --';
0dfb8a2a 507 printSelect ($chapter, "${i}_value", $record['key']);
e673ee24
DO
508 break;
509 }
0dfb8a2a
DO
510 echo "</td></tr>\n";
511 $i++;
e673ee24 512 }
5bbbeaa2
DO
513 echo "<tr><td colspan=3>";
514 printImageHREF ('SAVE', 'Save changes', TRUE);
515 echo "</td></tr>\n";
0dfb8a2a 516 echo "</form>";
e673ee24
DO
517 echo "</table>\n";
518 finishPortlet();
519 echo '</td>';
520
521 echo '</tr><tr>';
522
523 echo '<td colspan=2>';
524 startPortlet ('history');
525 renderHistory ($pageno, $object_id);
526 finishPortlet();
527 echo '</td>';
528
529 echo '</tr></table>';
530}
531
532// This is a clone of renderEditObjectForm().
533function renderEditRackForm ($rack_id)
534{
0c2b7c4a
DO
535 showMessageOrError();
536 global $pageno;
e673ee24
DO
537 $rack = getRackData ($rack_id);
538 if ($rack == NULL)
539 {
39a6338a 540 showError ('getRackData() failed', __FUNCTION__);
e673ee24
DO
541 return;
542 }
543
e673ee24 544 startPortlet ('Rack attributes');
7056988c 545 printOpFormIntro ('updateRack');
e673ee24
DO
546 echo '<table border=0 align=center>';
547 echo "<tr><th class=tdright>Rack row:</th><td class=tdleft>";
4c330a14 548 printSelect (readChapter ('RackRow'), 'rack_row_id', $rack['row_id']);
e673ee24
DO
549 echo "</td></tr>\n";
550 echo "<tr><th class=tdright>Name (required):</th><td class=tdleft><input type=text name=rack_name value='${rack['name']}'></td></tr>\n";
551 echo "<tr><th class=tdright>Height (required):</th><td class=tdleft><input type=text name=rack_height value='${rack['height']}'></td></tr>\n";
552 echo "<tr><th class=tdright>Comment:</th><td class=tdleft><input type=text name=rack_comment value='${rack['comment']}'></td></tr>\n";
7056988c
DO
553 echo "<tr><td class=submit colspan=2>";
554 printImageHREF ('SAVE', 'Save changes', TRUE);
555 echo "</td></tr>\n";
e673ee24
DO
556 echo '</form></table><br>';
557 finishPortlet();
558
559 startPortlet ('History');
560 renderHistory ($pageno, $rack_id);
561 finishPortlet();
562}
563
564// This is a helper for creators and editors.
565function printSelect ($rowList, $select_name, $selected_id = 1)
566{
9e7f32a7
DO
567 // First collect all data for OPTGROUPs, then ouput it and dump
568 // the rest of records as is.
569 $optgroup = array();
570 $other = array();
4c330a14 571 foreach ($rowList as $dict_key => $dict_value)
e673ee24 572 {
f0b540a3 573 if (strpos ($dict_value, '%GSKIP%') !== FALSE)
9e7f32a7 574 {
f0b540a3 575 $tmp = explode ('%GSKIP%', $dict_value, 2);
9e7f32a7
DO
576 $optgroup[$tmp[0]][$dict_key] = $tmp[1];
577 }
f0b540a3 578 elseif (strpos ($dict_value, '%GPASS%') !== FALSE)
2613bc1c 579 {
f0b540a3 580 $tmp = explode ('%GPASS%', $dict_value, 2);
2613bc1c
DO
581 $optgroup[$tmp[0]][$dict_key] = $tmp[1];
582 }
9e7f32a7
DO
583 else
584 $other[$dict_key] = $dict_value;
585 }
586 echo "<select name=${select_name}>";
587 if (!count ($optgroup))
588 {
589 foreach ($other as $dict_key => $dict_value)
590 {
591 echo "<option value=${dict_key}";
592 if ($dict_key == $selected_id)
593 echo ' selected';
594 echo ">${dict_value}</option>";
595 }
596 }
597 else
598 {
599 foreach ($optgroup as $groupname => $groupdata)
600 {
601 echo "<optgroup label='${groupname}'>";
602 foreach ($groupdata as $dict_key => $dict_value)
603 {
604 echo "<option value=${dict_key}";
605 if ($dict_key == $selected_id)
606 echo ' selected';
607 echo ">${dict_value}</option>";
608 }
609 echo "</optgroup>\n";
610 }
611 if (count ($other))
612 {
613 echo "<optgroup label='other'>\n";
614 foreach ($other as $dict_key => $dict_value)
615 {
616 echo "<option value=${dict_key}";
617 if ($dict_key == $selected_id)
618 echo ' selected';
619 echo ">${dict_value}</option>";
620 }
621 echo "</optgroup>\n";
622 }
e673ee24
DO
623 }
624 echo "</select>";
625}
626
254673dd
DO
627// used by renderGridForm() and renderRackPage()
628function renderRackInfoPortlet ($rackData)
629{
d9c609c4 630 global $root;
254673dd
DO
631 startPortlet ('summary');
632 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
633 echo "<tr><th width='50%' class=tdright>Rack row:</th><td class=tdleft>${rackData['row_name']}</td></tr>\n";
634 echo "<tr><th width='50%' class=tdright>Name:</th><td class=tdleft>${rackData['name']}</td></tr>\n";
635 echo "<tr><th width='50%' class=tdright>Height:</th><td class=tdleft>${rackData['height']}</td></tr>\n";
04d619d0 636 echo "<tr><th width='50%' class=tdright>%% used:</th><td class=tdleft>";
254673dd
DO
637 renderProgressBar (getRSUforRack ($rackData));
638 echo "</td></tr>\n";
639 echo "<tr><th width='50%' class=tdright>Objects:</th><td class=tdleft>";
abef7149 640 echo count (stuffInRackspace ($rackData));
254673dd 641 echo "</td></tr>\n";
e2ac59cf 642 printTagTRs ("${root}?page=rackspace&");
254673dd
DO
643 if (!empty ($rackData['comment']))
644 echo "<tr><th width='50%' class=tdright>Comment:</th><td class=tdleft>${rackData['comment']}</td></tr>\n";
645 echo '</table>';
646 finishPortlet();
647}
648
e673ee24 649// This is a universal editor of rack design/waste.
7056988c 650// FIXME: switch to using printOpFormIntro()
bb09cca0 651function renderGridForm ($rack_id = 0, $filter, $header, $submit, $state1, $state2)
e673ee24
DO
652{
653 if ($rack_id == 0)
654 {
591ff2c4 655 showError ('Invalid rack_id', __FUNCTION__);
e673ee24
DO
656 return;
657 }
658 if (($rackData = getRackData ($rack_id)) == NULL)
659 {
591ff2c4 660 showError ('getRackData() failed', __FUNCTION__);
e673ee24
DO
661 return;
662 }
663
664 global $root, $pageno, $tabno;
254673dd 665 $filter ($rackData);
e673ee24
DO
666 markupObjectProblems ($rackData);
667
668 // Process form submit.
669 if (isset ($_REQUEST['do_update']))
670 {
671 $log[] = processGridForm ($rackData, $state1, $state2);
254673dd
DO
672 printLog ($log);
673 $rackData = getRackData ($rack_id);
674 $filter ($rackData);
675 markupObjectProblems ($rackData);
e673ee24
DO
676 }
677
678 // Render the result whatever it is.
679 // Main layout.
680 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
681 echo "<tr><td colspan=2 align=center><h1>${rackData['name']}</h1></td></tr>\n";
682
683 // Left column with information portlet.
684 echo "<tr><td class=pcleft height='1%' width='50%'>";
254673dd 685 renderRackInfoPortlet ($rackData);
e673ee24 686 echo "</td>\n";
bb09cca0 687 echo "<td class=pcright>";
e673ee24
DO
688
689 // Grid form.
690 startPortlet ($header);
691 echo "<center>\n";
692 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
693 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>Front</th>";
694 echo "<th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
9d479d56 695 echo "<form method=post action='${root}?'>\n";
e673ee24
DO
696 echo "<input type=hidden name=page value=${pageno}>\n";
697 echo "<input type=hidden name=tab value=${tabno}>\n";
698 echo "<input type=hidden name=rack_id value=${rack_id}>\n";
699 markupAtomGrid ($rackData, $state2);
700 renderAtomGrid ($rackData);
701 echo "</table></center>\n";
702 echo "<br><input type=submit name=do_update value='${submit}'></form><br><br>\n";
703 finishPortlet();
bb09cca0 704 echo "</td></tr></table>\n";
e673ee24
DO
705}
706
707function renderRackDesign ($rack_id)
708{
bb09cca0 709 renderGridForm ($rack_id, 'applyRackDesignMask', 'Rack design', 'Set rack design', 'A', 'F');
e673ee24
DO
710}
711
712function renderRackProblems ($rack_id = 0)
713{
bb09cca0 714 renderGridForm ($rack_id, 'applyRackProblemMask', 'Rack problems', 'Mark unusable atoms', 'F', 'U');
e673ee24
DO
715}
716
717function startPortlet ($title = '')
718{
719 echo "<div class=portlet><h2>${title}</h2>";
720}
721
722function finishPortlet ()
723{
724 echo "</div>\n";
725}
726
727function printRefsOfType ($refs, $type, $eq)
728{
729 global $root;
730 $gotone=0;
731 foreach ($refs as $ref)
732 {
733 if ($eq($ref['type'], $type))
734 {
735 if ($gotone) echo ', ';
4b2bf583
DO
736 echo "<a href='${root}?page=object&object_id=${ref['object_id']}'>";
737 if (!empty ($ref['name']))
738 echo $ref['name'] . '@';
739 echo "${ref['object_name']}</a>";
e673ee24
DO
740 $gotone=1;
741 }
742 }
743}
744
745function renderRackObject ($object_id = 0)
746{
52c836b1 747 global $root, $nextorder, $aac;
e673ee24
DO
748 if ($object_id <= 0)
749 {
591ff2c4 750 showError ('Invalid object_id', __FUNCTION__);
e673ee24
DO
751 return;
752 }
753 $info = getObjectInfo ($object_id);
754 if ($info == NULL)
755 {
591ff2c4 756 showError ('getObjectInfo() failed', __FUNCTION__);
e673ee24
DO
757 return;
758 }
759 // Main layout starts.
760 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
761 echo "<tr><td colspan=2 align=center><h1>${info['dname']}</h1></td></tr>\n";
762 // left column with uknown number of portlets
763 echo "<tr><td class=pcleft>";
0ab782bc 764 startPortlet ('summary');
e673ee24
DO
765 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
766 if (!empty ($info['name']))
767 echo "<tr><th width='50%' class=tdright>Common name:</th><td class=tdleft>${info['name']}</td></tr>\n";
9c0b0016 768 elseif (in_array ($info['objtype_id'], explode (',', getConfigVar ('NAMEFUL_OBJTYPES'))))
a0ec6295 769 echo "<tr><td colspan=2 class=msg_error>Common name is missing.</td></tr>\n";
e2ac59cf 770 echo "<tr><th width='50%' class=tdright>Object type:</th>";
8e700dd1 771 echo "<td class=tdleft><a href='${root}?page=objgroup&group_id=${info['objtype_id']}&hl_object_id=${object_id}'>${info['objtype_name']}</a></td></tr>\n";
e673ee24
DO
772 if (!empty ($info['asset_no']))
773 echo "<tr><th width='50%' class=tdright>Asset tag:</th><td class=tdleft>${info['asset_no']}</td></tr>\n";
a6305acc 774 elseif (in_array ($info['objtype_id'], explode (',', getConfigVar ('REQUIRE_ASSET_TAG_FOR'))))
a0ec6295 775 echo "<tr><td colspan=2 class=msg_error>Asset tag is missing.</td></tr>\n";
e673ee24
DO
776 if (!empty ($info['label']))
777 echo "<tr><th width='50%' class=tdright>Visible label:</th><td class=tdleft>${info['label']}</td></tr>\n";
778 if (!empty ($info['barcode']))
779 echo "<tr><th width='50%' class=tdright>Barcode:</th><td class=tdleft>${info['barcode']}</td></tr>\n";
780 if ($info['has_problems'] == 'yes')
781 echo "<tr><td colspan=2 class=msg_error>Has problems</td></tr>\n";
24cbe8af 782 foreach (getAttrValues ($object_id, TRUE) as $record)
e673ee24 783 if (!empty ($record['value']))
50a954f6 784 echo "<tr><th width='50%' class=opt_attr_th>${record['name']}:</th><td class=tdleft>${record['a_value']}</td></tr>\n";
e2ac59cf 785 printTagTRs ("${root}?page=objgroup&group_id=${info['objtype_id']}&");
e673ee24
DO
786 echo "</table><br>\n";
787 finishPortlet();
788
789 if (!empty ($info['comment']))
790 {
791 startPortlet ('Comment');
6cc5d6cd 792 echo '<div class=commentblock>' . string_insert_hrefs ($info['comment']) . '</div>';
e673ee24
DO
793 finishPortlet ();
794 }
795
796 $ports = getObjectPortsAndLinks ($object_id);
797 if (count ($ports))
798 {
0ab782bc 799 startPortlet ('ports and links');
e673ee24
DO
800 usort($ports, 'sortByName');
801 if ($ports)
802 {
803 $hl_port_id = 0;
804 if (isset ($_REQUEST['hl_port_id']))
805 {
2c6c7645 806 assertUIntArg ('hl_port_id', __FUNCTION__);
e673ee24
DO
807 $hl_port_id = $_REQUEST['hl_port_id'];
808 }
809 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
810 echo "<tr><th>Local name</th><th>Visible label</th><th>Port type</th><th>L2 address</th>";
811 echo "<th>Rem. Object</th><th>Rem. port</th></tr>\n";
812 foreach ($ports as $port)
813 {
814 echo '<tr';
815 if ($hl_port_id == $port['id'])
816 echo ' class=port_highlight';
817 echo "><td>${port['name']}</td><td>${port['label']}</td><td>${port['type']}</td>";
818 echo "<td>${port['l2address']}</td>";
819 if ($port['remote_object_id'])
820 {
8e700dd1 821 echo "<td><a href='${root}?page=object&object_id=${port['remote_object_id']}&hl_port_id=${port['remote_id']}'>${port['remote_object_name']}</a></td>";
e673ee24
DO
822 echo "<td>${port['remote_name']}</td>";
823 }
824 elseif (!empty ($port['reservation_comment']))
825 {
826 echo "<td><b>Reserved;</b></td>";
827 echo "<td>${port['reservation_comment']}</td>";
828 }
829 else
830 echo '<td>&nbsp;</td><td>&nbsp;</td>';
831 echo "</tr>\n";
832 }
833 echo "</table><br>\n";
834 }
835 finishPortlet();
836 }
85970da2 837
0ab782bc
DO
838 $alloclist = getObjectIPv4Allocations ($object_id);
839 if (count ($alloclist))
e673ee24 840 {
f28fbe8b 841 startPortlet ('IPv4 addresses');
e673ee24 842 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
f0ed1181 843 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
71287f1c 844 echo "<tr><th>OS interface</th><th>IP address</th><th colspan=2>network</th><th>routed by</th><th>peers</th></tr>\n";
83fdf85f
DO
845 else
846 echo "<tr><th>OS interface</th><th>IP address</th><th>peers</th></tr>\n";
fc0e3978
DO
847 $hl_ipv4_addr = '';
848 if (isset ($_REQUEST['hl_ipv4_addr']))
849 {
850 assertIPv4Arg ('hl_ipv4_addr', __FUNCTION__);
851 $hl_ipv4_addr = $_REQUEST['hl_ipv4_addr'];
852 }
85970da2 853 foreach ($alloclist as $dottedquad => $alloc)
e673ee24 854 {
0ab782bc
DO
855 $address_name = niftyString ($alloc['addrinfo']['name']);
856 $class = $alloc['addrinfo']['class'];
85970da2 857 $secondclass = ($hl_ipv4_addr == $dottedquad) ? 'tdleft port_highlight' : 'tdleft';
83fdf85f 858 $netid = getIPv4AddressNetworkId ($dottedquad);
71287f1c 859 $netinfo = getIPv4NetworkInfo ($netid);
b6b87070 860 loadIPv4AddrList ($netinfo);
83fdf85f
DO
861 echo "<tr class='${class}' valign=top><td class=tdleft>${alloc['osif']}</td><td class='${secondclass}'>";
862 echo "<a href='${root}?page=ipaddress&ip=" . $dottedquad . "&hl_object_id=${object_id}'>${dottedquad}</a>";
f0ed1181 863 if (getConfigVar ('EXT_IPV4_VIEW') != 'yes')
83fdf85f
DO
864 {
865 if (NULL === $netid)
866 $suffix = '/??';
867 else
83fdf85f 868 echo '<small>/' . $netinfo['mask'] . '</small>';
83fdf85f 869 }
351b1f45 870 echo '&nbsp;' . $aac[$alloc['type']];
83fdf85f
DO
871 if (!empty ($alloc['addrinfo']['name']))
872 echo '(' . niftyString ($alloc['addrinfo']['name']) . ')';
873 echo '</td>';
f0ed1181 874 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
b90c3907 875 {
83fdf85f 876 if (NULL === $netid)
71287f1c 877 echo '<td colspan=2>?</td>';
83fdf85f 878 else
fd30f6e4 879 printIPv4NetInfoTDs ($netinfo, $secondclass);
71287f1c 880 echo "<td class='${secondclass}'>";
83fdf85f 881 // FIXME: These cals are really heavy, replace them with a more appropriate dedicated function.
83fdf85f 882 $newline = '';
b6b87070 883 foreach (findRouters ($netinfo['addrlist']) as $router)
83fdf85f
DO
884 {
885 if ($router['id'] == $object_id)
886 continue;
887 echo $newline . $router['addr'] . ", <a href='${root}?page=object&object_id=${router['id']}&hl_ipv4_addr=${router['addr']}'>";
888 echo (empty ($router['iface']) ? '' : $router['iface'] . '@') . $router['dname'] . '</a>';
889 $routertags = loadRackObjectTags ($router['id']);
890 if (count ($routertags))
351b1f45 891 echo '<br><small>' . serializeTags ($routertags, "${root}?page=objects&tab=default&") . '</small>';
83fdf85f
DO
892 $newline = '<br>';
893 }
894 echo '</td>';
b90c3907 895 }
83fdf85f 896 // peers
0ab782bc 897 echo "<td class='${secondclass}'>\n";
0ab782bc 898 $prefix = '';
2c817354 899 if ($alloc['addrinfo']['reserved'] == 'yes')
e673ee24 900 {
85970da2 901 echo $prefix . '<strong>RESERVED</strong>';
0ab782bc
DO
902 $prefix = '; ';
903 }
904 foreach ($alloc['addrinfo']['allocs'] as $allocpeer)
905 {
906 if ($allocpeer['object_id'] == $object_id)
907 continue;
908 echo $prefix . "<a href='${root}?page=object&object_id=${allocpeer['object_id']}'>";
909 if (!empty ($allocpeer['osif']))
910 echo $allocpeer['osif'] . '@';
911 echo $allocpeer['object_name'] . '</a>';
0ab782bc 912 $prefix = '; ';
e673ee24 913 }
e673ee24
DO
914 echo "</td></tr>\n";
915 }
916 echo "</table><br>\n";
917 finishPortlet();
918 }
919
eeb4a5d8 920 $forwards = getNATv4ForObject ($object_id);
e673ee24
DO
921 if (count($forwards['in']) or count($forwards['out']))
922 {
f28fbe8b 923 startPortlet('NATv4');
e673ee24
DO
924
925 if (count($forwards['out']))
926 {
927
f28fbe8b 928 echo "<h3>locally performed NAT</h3>";
e673ee24 929
105a3bc8 930 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
f28fbe8b 931 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
932
933 foreach ($forwards['out'] as $pf)
934 {
2c817354
DO
935 $class = 'trerror';
936 $osif = '';
937 if (isset ($alloclist [$pf['localip']]))
938 {
939 $class = $alloclist [$pf['localip']]['addrinfo']['class'];
940 $osif = $alloclist [$pf['localip']]['osif'] . ': ';
941 }
e673ee24 942 echo "<tr class='$class'>";
2c817354 943 echo "<td>${pf['proto']}</td><td class=tdleft>${osif}<a href='${root}?page=ipaddress&tab=default&ip=${pf['localip']}'>${pf['localip']}</a>:${pf['localport']}</td>";
f28fbe8b 944 echo "<td class=tdleft><a href='${root}?page=ipaddress&tab=default&ip=${pf['remoteip']}'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
53ef3908 945 $address = getIPv4Address ($pf['remoteip']);
e673ee24 946 echo "<td class='description'>";
53ef3908
DO
947 if (count ($address['allocs']))
948 foreach($address['allocs'] as $bond)
f28fbe8b
DO
949 echo "<a href='${root}?page=object&tab=default&object_id=${bond['object_id']}'>${bond['object_name']}(${bond['name']})</a> ";
950 elseif (!empty ($pf['remote_addr_name']))
951 echo '(' . $pf['remote_addr_name'] . ')';
53ef3908 952 echo "</td><td class='description'>${pf['description']}</td></tr>";
e673ee24
DO
953 }
954 echo "</table><br><br>";
955 }
956 if (count($forwards['in']))
957 {
f28fbe8b 958 echo "<h3>arriving NAT connections</h3>";
105a3bc8 959 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
f28fbe8b 960 echo "<tr><th>Matched endpoint</th><th>Source object</th><th>Translated to</th><th>Rule comment</th></tr>\n";
e673ee24
DO
961 foreach ($forwards['in'] as $pf)
962 {
963 echo "<tr>";
964 echo "<td>${pf['proto']}/<a href='${root}?page=ipaddress&tab=default&ip=${pf['localip']}'>${pf['localip']}</a>:${pf['localport']}</td>";
e673ee24 965 echo "<td class='description'><a href='${root}?page=object&tab=default&object_id=${pf['object_id']}'>${pf['object_name']}</a>";
e673ee24
DO
966 echo "</td><td><a href='${root}?page=ipaddress&tab=default&ip=${pf['remoteip']}'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
967 echo "<td class='description'>${pf['description']}</td></tr>";
968 }
e673ee24
DO
969 echo "</table><br><br>";
970 }
971 finishPortlet();
972 }
973
78e7b769
DO
974 $pools = getRSPoolsForObject ($object_id);
975 if (count ($pools))
976 {
300826cb 977 $order = 'odd';
78e7b769
DO
978 startPortlet ('Real server pools');
979 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable>\n";
732e4578 980 echo "<tr><th>VS</th><th>RS pool</th><th>RS</th><th>VS config</th><th>RS config</th></tr>\n";
748805bf 981 foreach ($pools as $vs_id => $info)
78e7b769 982 {
300826cb 983 echo "<tr valign=top class=row_${order}><td class=tdleft><a href='${root}?page=ipv4vs&vs_id=${vs_id}'>";
748805bf
DO
984 echo buildVServiceName ($info);
985 echo '</a>';
986 if (!empty ($info['name']))
300826cb 987 echo "<br>${info['name']}";
0e692350 988 echo "</td><td class=tdleft><a href='${root}?page=ipv4rsp&pool_id=${info['pool_id']}'>";
748805bf 989 echo (empty ($info['pool_name']) ? 'ANONYMOUS' : $info['pool_name']);
732e4578
DO
990 echo '</a></td><td class=tdleft>' . $info['rscount'] . '</td>';
991 echo "<td class=tdleft><pre>${info['vsconfig']}</pre></td>";
992 echo "<td class=tdleft><pre>${info['rsconfig']}</pre></td>";
78e7b769 993 echo "</tr>\n";
300826cb 994 $order = $nextorder[$order];
78e7b769
DO
995 }
996 echo "</table>\n";
997 finishPortlet();
998 }
e673ee24
DO
999 echo "</td>\n";
1000
7056988c 1001 // After left column we have (surprise!) right column with rackspace portlet only.
e673ee24
DO
1002 echo "<td class=pcright>";
1003 // rackspace portlet
0ab782bc 1004 startPortlet ('rackspace allocation');
e673ee24
DO
1005 // FIXME: now we call getRackData() twice
1006 $racks = getResidentRacksData ($object_id);
1007 foreach ($racks as $rackData)
1008 renderRack ($rackData['id'], $object_id);
1009 echo '<br>';
1010 finishPortlet();
1011 echo "</td></tr>";
1012 echo "</table>\n";
1013}
1014
1015function renderRackMultiSelect ($sname, $racks, $selected)
1016{
04571888
DO
1017 // Transform the given flat list into a list of groups, each representing a rack row.
1018 $rdata = array();
e673ee24 1019 foreach ($racks as $rack)
04571888
DO
1020 if (!isset ($rdata[$rack['row_name']]))
1021 $rdata[$rack['row_name']] = array ($rack['id'] => $rack['name']);
1022 else
1023 $rdata[$rack['row_name']][$rack['id']] = $rack['name'];
1024 echo "<select name=${sname} multiple size=" . getConfigVar ('MAXSELSIZE') . " onchange='getElementById(\"racks\").submit()'>\n";
1025 foreach ($rdata as $optgroup => $racklist)
e673ee24 1026 {
04571888
DO
1027 echo "<optgroup label='${optgroup}'>";
1028 foreach ($racklist as $rack_id => $rack_name)
1029 {
1030 echo "<option value=${rack_id}";
1031 if (!(array_search ($rack_id, $selected) === FALSE))
1032 echo ' selected';
1033 echo">${rack_name}</option>\n";
1034 }
e673ee24
DO
1035 }
1036 echo "</select>\n";
1037}
1038
1039function showMessageOrError ()
1040{
46f92ff7 1041 if (isset ($_REQUEST['message']))
e673ee24 1042 echo "<div class=msg_success>${_REQUEST['message']}</div>";
46f92ff7 1043 elseif (isset ($_REQUEST['error']))
e673ee24 1044 echo "<div class=msg_error>${_REQUEST['error']}</div>";
46f92ff7
DO
1045 elseif (isset ($_REQUEST['log']))
1046 printLog (unserialize (base64_decode ($_REQUEST['log'])));
e673ee24
DO
1047}
1048
1049// This function renders a form for port edition.
1050function renderPortsForObject ($object_id = 0)
1051{
1052 global $root, $pageno, $tabno;
1053 if ($object_id <= 0)
1054 {
591ff2c4 1055 showError ('Invalid object_id', __FUNCTION__);
e673ee24
DO
1056 return;
1057 }
1058 showMessageOrError();
1059 startPortlet ('Ports and interfaces');
1060 $ports = getObjectPortsAndLinks ($object_id);
1061 usort($ports, 'sortByName');
1062 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
1063 echo "<tr><th>&nbsp;</th><th>Local name</th><th>Visible label</th><th>Port type</th><th>L2 address</th>";
1064 echo "<th>Rem. object</th><th>Rem. port</th><th>(Un)link or (un)reserve</th><th>&nbsp;</th></tr>\n";
1065 foreach ($ports as $port)
1066 {
7056988c 1067 printOpFormIntro ('editPort', array ('port_id' => $port['id']));
e673ee24
DO
1068 echo "<tr><td><a href='${root}process.php?op=delPort&page=${pageno}&tab=${tabno}&port_id=${port['id']}&object_id=$object_id&port_name=${port['name']}'>";
1069 printImageHREF ('delete', 'Unlink and Delete this port');
1070 echo "</a></td>\n";
1071 echo "<td><input type=text name=name value='${port['name']}' size=8></td>";
1072 echo "<td><input type=text name=label value='${port['label']}' size=24></td>";
1073 echo "<td>${port['type']}</td>\n";
1074 echo "<td><input type=text name=l2address value='${port['l2address']}'></td>\n";
1075 if ($port['remote_object_id'])
1076 {
1077 echo "<td><a href='${root}?page=object&object_id=${port['remote_object_id']}'>${port['remote_object_name']}</a></td>";
1078 echo "<td>${port['remote_name']}</td>";
1079 echo "<td><a href='${root}process.php?op=unlinkPort&page=${pageno}&tab=${tabno}&port_id=${port['id']}&object_id=$object_id&port_name=";
1080 echo urlencode ($port['name']);
1081 echo "&remote_port_name=${port['remote_name']}&remote_object_name=${port['remote_object_name']}'>";
1082 printImageHREF ('unlink', 'Unlink this port');
1083 echo "</a></td>";
1084 }
1085 elseif (!empty ($port['reservation_comment']))
1086 {
1087 echo "<td><b>Reserved;</b></td>";
1088 echo "<td><input type=text name=reservation_comment value='${port['reservation_comment']}'></td>";
1089 echo "<td><a href='${root}process.php?op=useup&page=${pageno}&tab=${tabno}&port_id=${port['id']}&object_id=${object_id}'>";
1090 printImageHREF ('useup', 'Use up this port');
1091 echo "</a></td>";
1092 }
1093 else
1094 {
1095 echo "<td>&nbsp;</td><td>&nbsp;</td>";
1096 echo "<td>";
1097 echo "<a href='javascript:;' onclick='window.open(\"${root}link_helper.php?port=${port['id']}&type=${port['type_id']}&object_id=$object_id&port_name=";
1098 echo urlencode ($port['name']);
1099 echo "\",\"findlink\",\"height=700, width=400, location=no, menubar=no, resizable=yes, scrollbars=no, status=no, titlebar=no, toolbar=no\");'>";
1100 printImageHREF ('link', 'Link this port');
1101 echo "</a> <input type=text name=reservation_comment>";
1102 echo "</td>\n";
1103 }
5bbbeaa2
DO
1104 echo "<td>";
1105 printImageHREF ('save', 'Save changes', TRUE);
1106 echo "</td></form></tr>\n";
e673ee24 1107 }
7056988c
DO
1108 printOpFormIntro ('addPort');
1109 echo "<tr><td>";
d48d8820
DO
1110 printImageHREF ('add', '', TRUE, 104);
1111 echo "</td><td><input type=text size=8 name=port_name tabindex=100></td>\n";
e673ee24 1112 echo "<td><input type=text size=24 name=port_label tabindex=101></td>";
e673ee24
DO
1113 echo "<td><select name='port_type_id' tabindex=102>\n";
1114 $types = getPortTypes();
9c0b0016 1115 $default_port_type = getConfigVar ('default_port_type');
e673ee24
DO
1116 foreach ($types as $typeid => $typename)
1117 {
1118 echo "<option value='${typeid}'";
1119 if ($typeid == $default_port_type)
1120 echo " selected";
1121 echo ">${typename}</option>\n";
1122 }
1123 echo "</select></td>";
1124 echo "<td><input type=text name=port_l2address tabindex=103></td>\n";
d48d8820 1125 echo "<td colspan=4>&nbsp;</td></tr></form>";
e673ee24
DO
1126 echo "</table><br>\n";
1127 finishPortlet();
1128
1129 startPortlet ('Add/update multiple ports');
7056988c 1130 printOpFormIntro ('addMultiPorts');
e673ee24 1131 echo 'Format: <select name=format>';
e673ee24
DO
1132 echo '<option value=c3600asy>Cisco 3600 async: sh line | inc TTY</option>';
1133 echo '<option value=fiwg selected>Foundry ServerIron/FastIron WorkGroup/Edge: sh int br</option>';
e673ee24 1134 echo '<option value=fisxii>Foundry FastIron SuperX/II4000: sh int br</option>';
351d4dbf 1135 echo '<option value=ssv1>SSV:&lt;interface name&gt; &lt;MAC address&gt;</option>';
e673ee24
DO
1136 echo "</select>";
1137 echo 'Default port type: ';
1138 echo "<select name=port_type>\n";
1139 foreach ($types as $typeid => $typename)
1140 {
1141 echo "<option value='${typeid}'";
1142 if ($typeid == $default_port_type)
1143 echo " selected";
1144 echo ">${typename}</option>\n";
1145 }
1146 echo "</select>";
1147 echo "<input type=submit value='Parse output'><br>\n";
1148 echo "<textarea name=input cols=100 rows=50></textarea><br>\n";
1149 echo '</form>';
1150 finishPortlet();
1151}
1152
72d8ced3 1153function renderIPv4ForObject ($object_id = 0)
e673ee24 1154{
52c836b1 1155 global $root, $pageno, $tabno, $aat;
e673ee24
DO
1156 if ($object_id <= 0)
1157 {
591ff2c4 1158 showError ('Invalid object_id', __FUNCTION__);
e673ee24
DO
1159 return;
1160 }
1161 showMessageOrError();
72d8ced3 1162 startPortlet ('Allocations');
85970da2 1163 $alloclist = getObjectIPv4Allocations ($object_id);
e673ee24 1164 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
79e45b4c
DO
1165 echo '<tr><th>&nbsp;</th><th>OS interface</th><th>IP address</th>';
1166 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
1167 echo '<th colspan=2>network</th><th>routed by</th>';
1168 echo '<th>type</th><th>misc</th><th>&nbsp</th></tr>';
85970da2 1169 foreach ($alloclist as $dottedquad => $alloc)
e673ee24 1170 {
85970da2 1171 $class = $alloc['addrinfo']['class'];
79e45b4c
DO
1172 $netid = getIPv4AddressNetworkId ($dottedquad);
1173 $netinfo = getIPv4NetworkInfo ($netid);
b6b87070 1174 loadIPv4AddrList ($netinfo);
85970da2 1175 printOpFormIntro ('updIPv4Allocation', array ('ip' => $dottedquad));
79e45b4c 1176 echo "<tr class='$class' valign=top><td><a href='${root}process.php?op=delIPv4Allocation&page=${pageno}&tab=${tabno}&ip=${dottedquad}&object_id=$object_id'>";
e673ee24
DO
1177 printImageHREF ('delete', 'Delete this IPv4 address');
1178 echo "</a></td>";
85970da2 1179 echo "<td class=tdleft><input type='text' name='bond_name' value='${alloc['osif']}' size=10></td>";
79e45b4c
DO
1180 echo "<td class=tdleft><a href='${root}?page=ipaddress&ip=${dottedquad}'>${dottedquad}</a>";
1181 if (getConfigVar ('EXT_IPV4_VIEW') != 'yes')
1182 {
1183 if (NULL === $netid)
1184 $suffix = '/??';
1185 else
1186 echo '<small>/' . $netinfo['mask'] . '</small>';
1187 }
1188 echo '&nbsp;' . $aac[$alloc['type']];
1189 if (!empty ($alloc['addrinfo']['name']))
1190 echo '(' . niftyString ($alloc['addrinfo']['name']) . ')';
1191 echo '</td>';
1192 // FIXME: this a copy-and-paste from renderRackObject()
1193 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
1194 {
1195 if (NULL === $netid)
1196 echo '<td colspan=2>?</td>';
1197 else
1198 printIPv4NetInfoTDs ($netinfo);
1199 echo "<td class='${secondclass}'>";
1200 // FIXME: These cals are really heavy, replace them with a more appropriate dedicated function.
79e45b4c 1201 $newline = '';
b6b87070 1202 foreach (findRouters ($netinfo['addrlist']) as $router)
79e45b4c
DO
1203 {
1204 if ($router['id'] == $object_id)
1205 continue;
1206 echo $newline . $router['addr'] . ", <a href='${root}?page=object&object_id=${router['id']}&hl_ipv4_addr=${router['addr']}'>";
1207 echo (empty ($router['iface']) ? '' : $router['iface'] . '@') . $router['dname'] . '</a>';
1208 $routertags = loadRackObjectTags ($router['id']);
1209 if (count ($routertags))
1210 echo '<br><small>' . serializeTags ($routertags, "${root}?page=objects&tab=default&") . '</small>';
1211 $newline = '<br>';
1212 }
1213 echo '</td>';
1214 }
1215 echo '<td>';
85970da2 1216 printSelect ($aat, 'bond_type', $alloc['type']);
e673ee24 1217 echo "</td><td>";
85970da2 1218 $prefix = '';
4940e4d5 1219 if ($alloc['addrinfo']['reserved'] == 'yes')
e673ee24 1220 {
85970da2
DO
1221 echo $prefix . '<strong>RESERVED</strong>';
1222 $prefix = '; ';
e673ee24 1223 }
85970da2 1224 foreach ($alloc['addrinfo']['allocs'] as $allocpeer)
e673ee24 1225 {
85970da2
DO
1226 if ($allocpeer['object_id'] == $object_id)
1227 continue;
1228 echo $prefix . "<a href='${root}?page=object&object_id=${allocpeer['object_id']}'>";
1229 if (!empty ($allocpeer['osif']))
1230 echo $allocpeer['osif'] . '@';
1231 echo $allocpeer['object_name'] . '</a>';
1232 $prefix = '; ';
e673ee24 1233 }
d54b9495
DO
1234 echo "</td><td>";
1235 printImageHREF ('save', 'Save changes', TRUE);
1236 echo "</td></form></tr>\n";
e673ee24
DO
1237 }
1238
7056988c
DO
1239 printOpFormIntro ('addIPv4Allocation');
1240 echo "<tr><td>";
d54b9495 1241 printImageHREF ('add', 'Allocate new address', TRUE, 99);
7056988c
DO
1242 echo "</td>";
1243 echo "<td class=tdleft><input type='text' size='10' name='bond_name' tabindex=100></td>\n";
1244 echo "<td class=tdleft><input type=text name='ip' tabindex=101></td>\n";
79e45b4c 1245 echo "<td colspan=3>&nbsp;</td><td>";
52c836b1 1246 printSelect ($aat, 'bond_type');
7056988c 1247 echo "</td><td colspan=2>&nbsp;</td></tr></form></table><br>\n";
e673ee24
DO
1248 finishPortlet();
1249
1250}
1251
baf37d01
DO
1252// Log structure versions:
1253// 1: the whole structure is a list of code-message pairs
1254// 2 and later: there's a "v" field set, which indicates the version
1255// 2: there's a "m" list set to hold message code and optional arguments
e673ee24
DO
1256function printLog ($log)
1257{
baf37d01
DO
1258 switch (TRUE)
1259 {
1260 case !isset ($log['v']):
ebb5441d 1261 case $log['v'] == 1:
baf37d01 1262 foreach ($log as $key => $record)
ebb5441d 1263 if ($key !== 'v')
baf37d01
DO
1264 echo "<div class=msg_${record['code']}>${record['message']}</div>";
1265 break;
1266 case $log['v'] == 2:
1267 $msginfo = array
1268 (
ebb5441d 1269 0 => array ('code' => 'success', 'format' => 'Success: %s'),
baf37d01
DO
1270 1 => array ('code' => 'success', 'format' => '%u new records done, %u already existed'),
1271 2 => array ('code' => 'success', 'format' => 'NATv4 rule was successfully added.'),
1272 3 => array ('code' => 'success', 'format' => 'NATv4 rule was successfully deleted.'),
1273 4 => array ('code' => 'success', 'format' => 'NATv4 rule was successfully updated'),
1274 5 => array ('code' => 'success', 'format' => 'Port %s was added successfully'),
1275 6 => array ('code' => 'success', 'format' => 'Port %s was updated successfully'),
1276 7 => array ('code' => 'success', 'format' => 'Port %s was deleted successfully'),
1277 8 => array ('code' => 'success', 'format' => 'Port %s successfully linked with port %s at object %s'),
1278 9 => array ('code' => 'success', 'format' => 'Port %s was successfully unlinked from %s@%s'),
1279 10 => array ('code' => 'success', 'format' => 'Added %u ports, updated %u ports, encountered %u errors.'),
1280 11 => array ('code' => 'success', 'format' => 'Reservation removed.'),
1281 12 => array ('code' => 'success', 'format' => 'allocation updated'),
1282 13 => array ('code' => 'success', 'format' => 'allocated'),
1283 14 => array ('code' => 'success', 'format' => 'deallocated'),
1284 15 => array ('code' => 'success', 'format' => 'Reset succeeded.'),
1285 16 => array ('code' => 'success', 'format' => 'Update done'),
1286 17 => array ('code' => 'success', 'format' => 'Update(s) succeeded.'),
1287 18 => array ('code' => 'success', 'format' => 'Load balancer was successfully added'),
1288 19 => array ('code' => 'success', 'format' => 'Load balancer was successfully deleted'),
1289 20 => array ('code' => 'success', 'format' => 'Load balancer info was successfully updated'),
1290 21 => array ('code' => 'success', 'format' => 'Generation complete'),
1291 22 => array ('code' => 'success', 'format' => 'Chained %u tags'),
1292 23 => array ('code' => 'success', 'format' => 'IPv4 prefix successfully added'),
1293 24 => array ('code' => 'success', 'format' => 'IPv4 prefix deleted'),
1294 25 => array ('code' => 'success', 'format' => 'IPv4 prefix updated'),
1295 26 => array ('code' => 'success', 'format' => '%u IP address(es) were successfully updated'),
1296 27 => array ('code' => 'success', 'format' => 'IPv4 address updated'),
1297 28 => array ('code' => 'success', 'format' => 'Virtual service was successfully created'),
1298 29 => array ('code' => 'success', 'format' => 'Virtual service was successfully deleted'),
1299 30 => array ('code' => 'success', 'format' => 'Virtual service was successfully updated'),
1300 31 => array ('code' => 'success', 'format' => 'RS pool was successfully created'),
1301 32 => array ('code' => 'success', 'format' => 'RS pool was successfully deleted'),
1302 33 => array ('code' => 'success', 'format' => 'RS pool was successfully updated'),
1303 34 => array ('code' => 'success', 'format' => 'Real server was successfully added'),
1304 35 => array ('code' => 'success', 'format' => 'Real server was successfully deleted'),
1305 36 => array ('code' => 'success', 'format' => 'Real server was successfully updated'),
1306 37 => array ('code' => 'success', 'format' => 'Successfully added %u real servers'),
1307 38 => array ('code' => 'success', 'format' => '%u real server(s) were successfully (de)activated'),
1308 39 => array ('code' => 'success', 'format' => 'User account %s updated.'),
1309 40 => array ('code' => 'success', 'format' => 'User account %s created.'),
1310 41 => array ('code' => 'success', 'format' => 'User account disabled.'),
1311 42 => array ('code' => 'success', 'format' => 'User account enabled.'),
1312 43 => array ('code' => 'success', 'format' => 'Saved successfully.'),
1313 44 => array ('code' => 'success', 'format' => '%s failures and %s successfull changes.'),
1314 45 => array ('code' => 'success', 'format' => "Attribute '%s' created."),
1315 46 => array ('code' => 'success', 'format' => 'Rename successful.'),
1316 47 => array ('code' => 'success', 'format' => 'Attribute was deleted.'),
1317 48 => array ('code' => 'success', 'format' => 'Supplement succeeded.'),
1318 49 => array ('code' => 'success', 'format' => 'Reduction succeeded.'),
1319 50 => array ('code' => 'success', 'format' => 'Reduction succeeded.'),
1320 51 => array ('code' => 'success', 'format' => 'Update succeeded.'),
1321 52 => array ('code' => 'success', 'format' => 'Supplement succeeded.'),
1322 53 => array ('code' => 'success', 'format' => 'Chapter was deleted.'),
1323 54 => array ('code' => 'success', 'format' => 'Chapter was updated.'),
1324 55 => array ('code' => 'success', 'format' => 'Chapter was added.'),
1325 56 => array ('code' => 'success', 'format' => 'Update succeeded.'),
1326 57 => array ('code' => 'success', 'format' => 'Reset complete'),
1327 58 => array ('code' => 'success', 'format' => "Successfully deleted tag ."),
1328 59 => array ('code' => 'success', 'format' => "Created tag '%s'."),
1329 60 => array ('code' => 'success', 'format' => "Updated tag '%s'."),
ebb5441d 1330 61 => array ('code' => 'success', 'format' => 'Password changed successfully.'),
24dcb9d8 1331 62 => array ('code' => 'success', 'format' => 'gw: %s'),
f0ff4930
DO
1332 63 => array ('code' => 'success', 'format' => '%u change request(s) have been processed'),
1333 64 => array ('code' => 'success', 'format' => 'Port %s@%s has been assigned to VLAN %u'),
f19c75d6 1334 65 => array ('code' => 'success', 'format' => "Added new rack '%s'"),
03e6ef01 1335 66 => array ('code' => 'success', 'format' => "File sent Ok via handler '%s'"),
abef7149 1336 67 => array ('code' => 'success', 'format' => "Tag rolling done, %u objects involved"),
0c2b7c4a 1337 68 => array ('code' => 'success', 'format' => "Updated rack '%s'"),
f0ff4930 1338
ebb5441d
DO
1339 100 => array ('code' => 'error', 'format' => 'Generic error: %s'),
1340 101 => array ('code' => 'error', 'format' => 'Port name cannot be empty'),
1341 102 => array ('code' => 'error', 'format' => "Error creating user account '%s'"),
1342 103 => array ('code' => 'error', 'format' => 'getHashByID() failed'),
1343 104 => array ('code' => 'error', 'format' => "Error updating user account '%s'"),
1344 105 => array ('code' => 'error', 'format' => 'Error enabling user account.'),
1345 106 => array ('code' => 'error', 'format' => 'Error disabling user account.'),
1346 107 => array ('code' => 'error', 'format' => 'Admin account cannot be disabled'),
1347 108 => array ('code' => 'error', 'format' => '%u failures and %u successfull changes.'),
1348 109 => array ('code' => 'error', 'format' => 'Update failed!'),
1349 110 => array ('code' => 'error', 'format' => 'Supplement failed!'),
1350 111 => array ('code' => 'error', 'format' => 'Reduction failed!'),
1351 112 => array ('code' => 'error', 'format' => 'Error adding chapter.'),
1352 113 => array ('code' => 'error', 'format' => 'Error updating chapter.'),
1353 114 => array ('code' => 'error', 'format' => 'Error deleting chapter.'),
1354 115 => array ('code' => 'error', 'format' => 'Error renaming attribute.'),
1355 116 => array ('code' => 'error', 'format' => 'Error creating attribute.'),
1356 117 => array ('code' => 'error', 'format' => 'Error deleting attribute.'),
1357 118 => array ('code' => 'error', 'format' => 'Supplement failed!'),
1358 119 => array ('code' => 'error', 'format' => 'Reduction failed!'),
1359 120 => array ('code' => 'error', 'format' => 'Reset failed!'),
1360 121 => array ('code' => 'error', 'format' => 'commitUpdateObject() failed'),
1361 122 => array ('code' => 'error', 'format' => 'One or more update(s) failed!'),
1362 123 => array ('code' => 'error', 'format' => 'Cannot process submitted data: unknown format code.'),
1363 124 => array ('code' => 'error', 'format' => 'Error removing reservation!'),
1364 125 => array ('code' => 'error', 'format' => "Update failed with error: '%s'"),
1365 126 => array ('code' => 'error', 'format' => 'addRStoRSPool() failed'),
1366 127 => array ('code' => 'error', 'format' => 'Added %u real servers and encountered %u errors'),
1367 128 => array ('code' => 'error', 'format' => 'commitDeleteRS() failed'),
1368 129 => array ('code' => 'error', 'format' => 'commitDeleteLB() failed'),
1369 130 => array ('code' => 'error', 'format' => 'commitDeleteVS() failed'),
1370 131 => array ('code' => 'error', 'format' => 'invalid format requested'),
1371 132 => array ('code' => 'error', 'format' => 'invalid protocol'),
1372 133 => array ('code' => 'error', 'format' => 'commitUpdateRS() failed'),
1373 134 => array ('code' => 'error', 'format' => 'commitUpdateLB() failed'),
1374 135 => array ('code' => 'error', 'format' => 'commitUpdateVS() failed'),
1375 136 => array ('code' => 'error', 'format' => 'addLBtoRSPool() failed'),
1376 137 => array ('code' => 'error', 'format' => 'addLBtoRSPool() failed'),
1377 138 => array ('code' => 'error', 'format' => 'commitDeleteRSPool() failed'),
1378 139 => array ('code' => 'error', 'format' => 'commitUpdateRSPool() failed'),
1379 140 => array ('code' => 'error', 'format' => 'Encountered %u errors, (de)activated %u real servers'),
1380 141 => array ('code' => 'error', 'format' => 'Encountered %u errors, updated %u IP address(es)'),
1381 142 => array ('code' => 'error', 'format' => 'executeAutoPorts() failed'),
1382 143 => array ('code' => 'error', 'format' => 'Tried chaining %u tags, but experienced %u errors.'),
1383 144 => array ('code' => 'error', 'format' => "Error deleting tag: '%s'"),
1384 145 => array ('code' => 'error', 'format' => "Invalid tag name '%s'"),
1385 146 => array ('code' => 'error', 'format' => "Tag '%s' (or similar name) already exists"),
1386 147 => array ('code' => 'error', 'format' => "Could not create tag '%s' because of error '%s'"),
1387 148 => array ('code' => 'error', 'format' => "Could not update tag '%s' because of error '%s'"),
1388 149 => array ('code' => 'error', 'format' => 'Turing test failed'),
1389 150 => array ('code' => 'error', 'format' => 'Can only change password under DB authentication.'),
1390 151 => array ('code' => 'error', 'format' => 'Old password doesn\'t match.'),
1391 152 => array ('code' => 'error', 'format' => 'New passwords don\'t match.'),
1392 153 => array ('code' => 'error', 'format' => 'Password change failed.'),
1393 154 => array ('code' => 'error', 'format' => "Verification error: %s"),
1394 155 => array ('code' => 'error', 'format' => 'Save failed.'),
1395 156 => array ('code' => 'error', 'format' => 'getSwitchVLANs() failed'),
e81fb764 1396 157 => array ('code' => 'error', 'format' => 'operation not permitted'),
24dcb9d8
DO
1397 158 => array ('code' => 'error', 'format' => 'Ignoring malformed record #%u in form submit'),
1398 159 => array ('code' => 'error', 'format' => 'Permission denied moving port %s from VLAN%u to VLAN%u'),
1399 160 => array ('code' => 'error', 'format' => 'Invalid arguments'),
1400 161 => array ('code' => 'error', 'format' => 'Endpoint not found. Please either set FQDN attribute or assign an IP address to the object.'),
1401 162 => array ('code' => 'error', 'format' => 'More than one IP address is assigned to this object, please configure FQDN attribute.'),
1402 163 => array ('code' => 'error', 'format' => 'Failed to get any response from queryGateway() or the gateway died'),
c030232f 1403 164 => array ('code' => 'error', 'format' => 'Gateway failure: %s.'),
24dcb9d8
DO
1404 165 => array ('code' => 'error', 'format' => 'Gateway failure: malformed reply.'),
1405 166 => array ('code' => 'error', 'format' => 'gw: %s'),
f0ff4930
DO
1406 167 => array ('code' => 'error', 'format' => 'Could not find port %s'),
1407 168 => array ('code' => 'error', 'format' => 'Port %s is a trunk'),
1408 169 => array ('code' => 'error', 'format' => 'Failed to configure %s, connector returned code %u'),
5222f192 1409 170 => array ('code' => 'error', 'format' => 'There is no network for IP address "%s"'),
f19c75d6
DO
1410 171 => array ('code' => 'error', 'format' => "Failed creating rack '%s'. Already exists in this row?"),
1411 172 => array ('code' => 'error', 'format' => 'Malformed request'),
e5c4506d
DO
1412 173 => array ('code' => 'error', 'format' => "Invalid IPv4 prefix '%s'"),
1413 174 => array ('code' => 'error', 'format' => 'Bad IPv4 address'),
1414 175 => array ('code' => 'error', 'format' => 'Invalid netmask'),
1415 176 => array ('code' => 'error', 'format' => 'This network already exists'),
0c2b7c4a 1416 177 => array ('code' => 'error', 'format' => 'commitUpdateRack() failed'),
f0ff4930 1417
24dcb9d8
DO
1418 200 => array ('code' => 'warning', 'format' => 'generic warning: %s'),
1419 201 => array ('code' => 'warning', 'format' => 'nothing happened...'),
1420 202 => array ('code' => 'warning', 'format' => 'gw: %s'),
f0ff4930
DO
1421 203 => array ('code' => 'warning', 'format' => 'Port %s seems to be the first in VLAN %u at this switch.'),
1422 204 => array ('code' => 'warning', 'format' => 'Check uplink/downlink configuration for proper operation.'),
1423 205 => array ('code' => 'warning', 'format' => '%u change request(s) have been ignored'),
baf37d01
DO
1424 );
1425 // Handle the arguments. Is there any better way to do it?
1426 foreach ($log['m'] as $record)
1427 {
5222f192
DO
1428 if (!isset ($record['c']) or !isset ($msginfo[$record['c']]))
1429 {
1430 echo '<div class=msg_neutral>(this message was lost)</div>';
1431 continue;
1432 }
baf37d01
DO
1433 if (isset ($record['a']))
1434 switch (count ($record['a']))
1435 {
1436 case 1:
1437 $msgtext = sprintf
1438 (
1439 $msginfo[$record['c']]['format'],
1440 $record['a'][0]
1441 );
1442 break;
1443 case 2:
1444 $msgtext = sprintf
1445 (
1446 $msginfo[$record['c']]['format'],
1447 $record['a'][0],
1448 $record['a'][1]
1449 );
1450 break;
1451 case 3:
1452 $msgtext = sprintf
1453 (
1454 $msginfo[$record['c']]['format'],
1455 $record['a'][0],
1456 $record['a'][1],
1457 $record['a'][2]
1458 );
1459 break;
1460 case 4:
1461 default:
1462 $msgtext = sprintf
1463 (
1464 $msginfo[$record['c']]['format'],
1465 $record['a'][0],
1466 $record['a'][1],
1467 $record['a'][2],
1468 $record['a'][3]
1469 );
1470 break;
1471 }
1472 else
1473 $msgtext = $msginfo[$record['c']]['format'];
1474 echo '<div class=msg_' . $msginfo[$record['c']]['code'] . ">${msgtext}</div>";
1475 }
1476 break;
1477 default:
1478 echo '<div class=msg_error>' . __FUNCTION__ . ': internal error</div>';
1479 break;
1480 }
e673ee24
DO
1481}
1482
1483/*
1484The following conditions must be followed:
14851. We can mount onto free atoms only. This means: if any record for an atom
1486already exists in RackSpace, it can't be used for mounting.
14872. We can't unmount from 'W' atoms. Operator should review appropriate comments
1488and either delete them before unmounting or refuse to unmount the object.
1489*/
1490
1491// We extensively use $_REQUEST in the function.
7056988c 1492// FIXME: move related code into ophandler
e673ee24
DO
1493function renderRackSpaceForObject ($object_id = 0)
1494{
1495 if ($object_id <= 0)
1496 {
591ff2c4 1497 showError ('Invalid object_id', __FUNCTION__);
e673ee24
DO
1498 return;
1499 }
1500 $is_submit = isset ($_REQUEST['got_atoms']);
1501 $is_update = isset ($_REQUEST['rackmulti'][0]);
1502 $info = getObjectInfo ($object_id);
1503 if ($info == NULL)
1504 {
591ff2c4 1505 showError ('getObjectInfo() failed', __FUNCTION__);
e673ee24
DO
1506 return;
1507 }
1508 // Always process occupied racks plus racks chosen by user. First get racks with
1509 // already allocated rackspace...
1510 $workingRacksData = getResidentRacksData ($object_id);
1511 if ($workingRacksData === NULL)
1512 {
1513 print_r ($workingRacksData);
591ff2c4 1514 showError ('getResidentRacksData() failed', __FUNCTION__);
e673ee24
DO
1515 return;
1516 }
1517
1518 // ...and then add those chosen by user (if any).
1519 if ($is_update)
1520 foreach ($_REQUEST['rackmulti'] as $cand_id)
1521 {
1522 if (!isset ($workingRacksData[$cand_id]))
1523 {
1524 $rackData = getRackData ($cand_id);
1525 if ($rackData == NULL)
1526 {
591ff2c4 1527 showError ('getRackData() failed', __FUNCTION__);
e673ee24
DO
1528 return NULL;
1529 }
1530 $workingRacksData[$cand_id] = $rackData;
1531 }
1532 }
1533
1534 // Do it only once...
1535 foreach ($workingRacksData as &$rackData)
1536 applyObjectMountMask ($rackData, $object_id);
1537 // Now we workaround an old caveat: http://bugs.php.net/bug.php?id=37410
1538 unset ($rackData);
1539
1540 // Here we process form submit by trying to save all submitted info to database.
1541 if ($is_submit)
1542 {
1543 $oldMolecule = getMoleculeForObject ($object_id);
1544 $worldchanged = FALSE;
1545 $log = array();
1546 foreach ($workingRacksData as $rack_id => $rackData)
1547 {
1548 $logrecord = processGridForm ($rackData, 'F', 'T', $object_id);
1549 $log[] = $logrecord;
1550 if ($logrecord['code'] != 300)
1551 {
1552 $worldchanged = TRUE;
1553 // Reload our working copy after form processing.
1554 $rackData = getRackData ($rack_id);
1555 if ($rackData == NULL)
4d2e93f2 1556 $log[] = array ('code' => 500, 'message' => 'Working copy update failed in ', __FUNCTION__);
e673ee24
DO
1557 applyObjectMountMask ($rackData, $object_id);
1558 $workingRacksData[$rack_id] = $rackData;
1559 }
1560 }
1561 if ($worldchanged)
1562 {
1563 // Log a record.
1564 $newMolecule = getMoleculeForObject ($object_id);
1565 $oc = count ($oldMolecule);
1566 $nc = count ($newMolecule);
1567 $omid = $oc ? createMolecule ($oldMolecule) : 'NULL';
1568 $nmid = $nc ? createMolecule ($newMolecule) : 'NULL';
1569 global $remote_username;
1570 $comment = empty ($_REQUEST['comment']) ? 'NULL' : "'${_REQUEST['comment']}'";
1571 $query =
1572 "insert into MountOperation(object_id, old_molecule_id, new_molecule_id, user_name, comment) " .
1573 "values (${object_id}, ${omid}, ${nmid}, '${remote_username}', ${comment})";
1574 global $dbxlink;
1575 $result = $dbxlink->query ($query);
1576 if ($result == NULL)
1577 $log[] = array ('code' => 'error', 'message' => 'SQL query failed during history logging.');
1578 else
1579 $log[] = array ('code' => 'success', 'message' => 'History logged.');
1580 }
1581 printLog ($log);
1582 }
1583
1584 // This is the time for rendering.
1585 global $root, $pageno, $tabno;
1586 echo "<form id='racks' action='${root}'>";
1587 echo "<input type=hidden name=page value='${pageno}'>\n";
1588 echo "<input type=hidden name=tab value='${tabno}'>\n";
1589 echo "<input type=hidden name=object_id value='${object_id}'>\n";
1590 // Main layout starts.
1591 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0><tr>";
1592
1593 // Left portlet with rack list.
1594 echo "<td class=pcleft height='1%'>";
1595 startPortlet ('Racks');
1596 $allRacksData = getRacksForRow();
4b8d413e
DO
1597 if (count ($allRacksData) <= getConfigVar ('RACK_PRESELECT_THRESHOLD'))
1598 {
1599 foreach (array_keys ($allRacksData) as $rack_id)
1600 {
1601 $rackData = getRackData ($rack_id);
1602 if ($rackData == NULL)
1603 {
1604 showError ('getRackData() failed', __FUNCTION__);
1605 return NULL;
1606 }
1607 $workingRacksData[$rack_id] = $rackData;
1608 }
1609 foreach ($workingRacksData as &$rackData)
1610 applyObjectMountMask ($rackData, $object_id);
1611 unset ($rackData);
1612 }
1613 renderRackMultiSelect ('rackmulti[]', $allRacksData, array_keys ($workingRacksData));
e673ee24
DO
1614 echo "<br>";
1615 echo "<br>";
1616 finishPortlet();
1617 echo "</td>";
1618
1619 // Middle portlet with comment and submit.
1620 echo "<td class=pcleft>";
1621 startPortlet ('Comment');
1622 echo "<textarea name=comment rows=10 cols=40></textarea><br>\n";
1623 echo "<input type=submit value='Save' name=got_atoms>\n";
1624 echo "<br>";
1625 echo "<br>";
1626 finishPortlet();
1627 echo "</td>";
1628
1629 // Right portlet with rendered racks. If this form submit is not final, we have to
1630 // reflect the former state of the grid in current form.
1631 echo "<td class=pcright rowspan=2 height='1%'>";
1632 startPortlet ('Working copy');
1633 echo '<table border=0 cellspacing=10 align=center><tr>';
1634 foreach ($workingRacksData as $rack_id => $rackData)
1635 {
1636 // Order is important here: only original allocation is highlighted.
1637 highlightObject ($rackData, $object_id);
1638 markupAtomGrid ($rackData, 'T');
1639 // If we have a form processed, discard user input and show new database
1640 // contents.
1641 if (!$is_submit and $is_update)
1642 mergeGridFormToRack ($rackData);
1643 echo "<td valign=top>";
1644 echo "<center>\n<h2>${rackData['name']}</h2>\n";
1645 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
1646 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>Front</th>";
1647 echo "<th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
1648 renderAtomGrid ($rackData);
9b7468b7
DO
1649 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>Front</th>";
1650 echo "<th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
e673ee24
DO
1651 echo "</table></center>\n";
1652 echo '</td>';
1653 }
1654 echo "</tr></table>";
1655 finishPortlet();
1656 echo "</td>\n";
1657
1658 echo "</form>\n";
1659 echo "</tr></table>\n";
1660}
1661
1662function renderMolecule ($mdata, $object_id)
1663{
1664 // sort data out
1665 $rackpack = array();
1666 global $loclist;
64b95774 1667 foreach ($mdata as $rua)
e673ee24
DO
1668 {
1669 $rack_id = $rua['rack_id'];
1670 $unit_no = $rua['unit_no'];
1671 $atom = $rua['atom'];
1672 if (!isset ($rackpack[$rack_id]))
1673 {
1674 $rackData = getRackData ($rack_id);
1675 for ($i = $rackData['height']; $i > 0; $i--)
1676 for ($locidx = 0; $locidx < 3; $locidx++)
1677 $rackData[$i][$locidx]['state'] = 'F';
1678 $rackpack[$rack_id] = $rackData;
1679 }
1680 $rackpack[$rack_id][$unit_no][$loclist[$atom]]['state'] = 'T';
1681 $rackpack[$rack_id][$unit_no][$loclist[$atom]]['object_id'] = $object_id;
1682 }
1683 // now we have some racks to render
64b95774 1684 foreach ($rackpack as $rackData)
e673ee24
DO
1685 {
1686 markAllSpans ($rackData);
1687 echo "<table class=molecule cellspacing=0>\n";
1688 echo "<caption>${rackData['name']}</caption>\n";
1689 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>Front</th><th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
1690 for ($i = $rackData['height']; $i > 0; $i--)
1691 {
1692 echo "<tr><th>$i</th>";
1693 for ($locidx = 0; $locidx < 3; $locidx++)
1694 {
1695 $state = $rackData[$i][$locidx]['state'];
1696 echo "<td class=state_${state}>&nbsp;</td>\n";
1697 }
1698 echo "</tr>\n";
1699 }
1700 echo "</table>\n";
1701 }
1702}
1703
1704function renderUnmountedObjectsPortlet ()
1705{
1706 startPortlet ('Unmounted objects');
1707 $objs = getUnmountedObjects();
1708 if ($objs === NULL)
1709 {
591ff2c4 1710 showError ('getUnmountedObjects() failed', __FUNCTION__);
e673ee24
DO
1711 return;
1712 }
1713 global $root, $nextorder;
1714 $order = 'odd';
1715 echo '<br><br><table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
18d94c29 1716 echo '<tr><th>Common name</th><th>Visible label</th><th>Asset number</th><th>Barcode</th></tr>';
e673ee24
DO
1717 foreach ($objs as $obj)
1718 {
1719 echo "<tr class=row_${order}><td><a href='${root}?page=object&object_id=${obj['id']}'>${obj['dname']}</a></td>";
1720 echo "<td>${obj['label']}</td>";
18d94c29
DO
1721 echo "<td>${obj['asset_no']}</td>";
1722 echo "<td>${obj['barcode']}</td></tr>";
e673ee24
DO
1723 $order = $nextorder[$order];
1724 }
1725 echo "</table><br>\n";
1726 finishPortlet();
1727}
1728
1729function renderProblematicObjectsPortlet ()
1730{
1731 startPortlet ('Problematic objects');
1732 $objs = getProblematicObjects();
1733 if ($objs === NULL)
1734 {
591ff2c4 1735 showError ('getProblematicObjects() failed', __FUNCTION__);
e673ee24
DO
1736 return;
1737 }
1738 global $root, $nextorder;
1739 $order = 'odd';
1740 echo '<br><br><table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
1741 echo '<tr><th>Type</th><th>Common name</th></tr>';
1742 foreach ($objs as $obj)
1743 {
1744 echo "<tr class=row_${order}><td>${obj['objtype_name']}</td>";
1745 echo "<td><a href='${root}?page=object&object_id=${obj['id']}'>${obj['dname']}</a></tr>";
1746 $order = $nextorder[$order];
1747 }
1748 echo "</table><br>\n";
1749 finishPortlet();
1750}
1751
7cc02fc1
DO
1752function renderObjectSpace ()
1753{
105cea6e 1754 global $root, $taglist, $tagtree;
7cc02fc1
DO
1755 echo "<table border=0 class=objectview>\n";
1756 echo "<tr><td class=pcleft width='50%'>";
1757 startPortlet ('View all by type');
1758 $groupInfo = getObjectGroupInfo();
1759 if ($groupInfo === NULL)
1760 {
1761 showError ('getObjectGroupInfo() failed', __FUNCTION__);
1762 return;
1763 }
1764 if (count ($groupInfo) == 0)
1765 echo "No objects exist in DB";
1766 else
1767 {
1768 echo '<div align=left><ul>';
1769 foreach ($groupInfo as $gi)
1770 echo "<li><a href='${root}?page=objgroup&group_id=${gi['id']}'>${gi['name']}</a> (${gi['count']})</li>";
1771 echo '</ul></div>';
1772 }
1773 finishPortlet();
1774
1775 echo '</td><td class=pcright>';
1776
1777 startPortlet ('View all by tag');
1778 if (count ($taglist) == 0)
1779 echo "No tags exist in DB";
1780 else
1781 renderTagCloud ('object');
1782 finishPortlet();
e673ee24
DO
1783 echo "</td></tr></table>\n";
1784}
1785
466dcbe6 1786function renderObjectGroup ()
7cc02fc1
DO
1787{
1788 global $root, $pageno, $tabno, $nextorder, $taglist, $tagtree;
2c6c7645 1789 assertUIntArg ('group_id', __FUNCTION__, TRUE);
7cc02fc1 1790 $group_id = $_REQUEST['group_id'];
a0d54e7e
DO
1791 $tagfilter = getTagFilter();
1792 $tagfilter_str = getTagFilterStr ($tagfilter);
7cc02fc1
DO
1793 echo "<table border=0 class=objectview>\n";
1794 echo "<tr><td class=pcleft width='25%'>";
1795 startPortlet ('change type');
1796 $groupInfo = getObjectGroupInfo();
1797 if ($groupInfo === NULL)
1798 {
1799 showError ('getObjectGroupInfo() failed', __FUNCTION__);
1800 return;
1801 }
1802 if (count ($groupInfo) == 0)
1803 echo "No objects exist in DB";
1804 else
1805 {
1806 echo '<div align=left><ul>';
1807 foreach ($groupInfo as $gi)
1808 {
a0d54e7e 1809 echo "<li><a href='${root}?page=${pageno}&group_id=${gi['id']}${tagfilter_str}'>";
105cea6e
DO
1810 if ($gi['id'] == $group_id)
1811 echo '<strong>';
1812 echo "${gi['name']}</a>";
1813 if ($gi['id'] == $group_id)
1814 echo '</strong>';
1815 echo " (${gi['count']})";
1816 if ($gi['id'] == $group_id)
1817 echo ' &larr;';
1818 echo "</li>";
7cc02fc1
DO
1819 }
1820 echo '</ul></div>';
1821 }
1822 finishPortlet();
1823
1824 echo '</td><td class=pcleft>';
1825
1826 startPortlet ('Objects');
11c8e4be 1827 $objects = getObjectList ($group_id, $tagfilter, getTFMode());
7cc02fc1
DO
1828 if ($objects === NULL)
1829 {
1830 showError ('getObjectList() failed', __FUNCTION__);
1831 return;
1832 }
1833 echo '<br><br><table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
1834 echo '<tr><th>Common name</th><th>Visible label</th><th>Asset tag</th><th>Barcode</th><th>Rack</th></tr>';
1835 $order = 'odd';
1836 foreach ($objects as $obj)
1837 {
8e700dd1
DO
1838 if (isset ($_REQUEST['hl_object_id']) and $_REQUEST['hl_object_id'] == $obj['id'])
1839 $secondclass = 'tdleft port_highlight';
1840 else
1841 $secondclass = 'tdleft';
1842 echo "<tr class=row_${order}><td class='${secondclass}'><a href='${root}?page=object&object_id=${obj['id']}'>${obj['dname']}</a></td>";
1843 echo "<td class='${secondclass}'>${obj['label']}</td>";
1844 echo "<td class='${secondclass}'>${obj['asset_no']}</td>";
1845 echo "<td class='${secondclass}'>${obj['barcode']}</td>";
7cc02fc1 1846 if ($obj['rack_id'])
8e700dd1 1847 echo "<td class='${secondclass}'><a href='${root}?page=rack&rack_id=${obj['rack_id']}'>${obj['Rack_name']}</a></td>";
7cc02fc1 1848 else
8e700dd1 1849 echo "<td class='${secondclass}'>Unmounted</td>";
7cc02fc1
DO
1850 echo '</tr>';
1851 $order = $nextorder[$order];
1852 }
1853 echo '</table>';
1854 finishPortlet();
1855
1856 echo "</td><td class=pcright width='25%'>";
1857
a0d54e7e 1858 renderTagFilterPortlet ($tagfilter, 'object', 'group_id', $group_id);
7cc02fc1 1859 echo "</td></tr></table>\n";
e673ee24
DO
1860}
1861
1862function renderEmptyPortsSelect ($port_id, $type_id)
1863{
1864 $ports = getEmptyPortsOfType($type_id);
1865 usort($ports, 'sortEmptyPorts');
1866 foreach ($ports as $port)
1867 {
1868 if ($port_id == $port['Port_id'])
1869 continue;
1870 echo "<option value='${port['Port_id']}' onclick='getElementById(\"remote_port_name\").value=\"${port['Port_name']}\"; getElementById(\"remote_object_name\").value=\"${port['Object_name']}\";'>${port['Object_name']} ${port['Port_name']}</option>\n";
1871 }
1872}
1873
6ef9683b 1874function renderAllIPv4Allocations ()
e673ee24 1875{
6ef9683b 1876 $addresses = getAllIPv4Allocations();
e673ee24
DO
1877 usort($addresses, 'sortObjectAddressesAndNames');
1878 foreach ($addresses as $address)
1879 {
1880 echo "<option value='${address['ip']}' onclick='getElementById(\"ip\").value=\"${address['ip']}\";'>${address['object_name']} ${address['name']} ${address['ip']}</option>\n";
1881 }
1882}
1883
1884// History viewer for history-enabled simple dictionaries.
1885function renderHistory ($object_type, $object_id)
1886{
1887 switch ($object_type)
1888 {
1889 case 'row':
1890 $query = "select ctime, user_name, name, deleted, comment from RackRowHistory where id = ${object_id} order by ctime";
1891 $header = '<tr><th>change time</th><th>author</th><th>rack row name</th><th>is deleted?</th><th>rack row comment</th></tr>';
1892 $extra = 4;
1893 break;
1894 case 'rack':
1895 $query =
1896 "select ctime, user_name, rh.name, rh.deleted, d.dict_value as name, rh.height, rh.comment " .
1897 "from RackHistory as rh left join Dictionary as d on rh.row_id = d.dict_key " .
1898 "natural join Chapter " .
1899 "where chapter_name = 'RackRow' and rh.id = ${object_id} order by ctime";
1900 $header = '<tr><th>change time</th><th>author</th><th>rack name</th><th>is deleted?</th><th>rack row name</th><th>rack height</th><th>rack comment</th></tr>';
1901 $extra = 6;
1902 break;
1903 case 'object':
1904 $query =
1905 "select ctime, user_name, name, label, barcode, asset_no, deleted, has_problems, dict_value, comment " .
1906 "from RackObjectHistory inner join Dictionary on objtype_id = dict_key natural join Chapter " .
1907 "where chapter_name = 'RackObjectType' and id=${object_id} order by ctime";
1908 $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>is deleted?</th><th>has problems?</th><th>object type</th><th>comment</th></tr>';
1909 $extra = 9;
1910 break;
1911 default:
591ff2c4 1912 showError ("Uknown object type '${object_type}'", __FUNCTION__);
e673ee24
DO
1913 return;
1914 }
1915 global $dbxlink;
1916 $result = $dbxlink->query ($query);
1917 if ($result == NULL)
1918 {
591ff2c4 1919 showError ('SQL query failed', __FUNCTION__);
e673ee24
DO
1920 return;
1921 }
1922 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
1923 $order = 'odd';
1924 global $nextorder;
1925 echo $header;
1926 while ($row = $result->fetch (PDO::FETCH_NUM))
1927 {
1928 echo "<tr class=row_${order}><td>${row[0]}</td>";
1929 for ($i = 1; $i <= $extra; $i++)
1930 echo "<td>" . $row[$i] . "</td>";
1931 echo "</tr>\n";
1932 $order = $nextorder[$order];
1933 }
1934 echo "</table><br>\n";
1935}
1936
1937function renderRackspaceHistory ()
1938{
1939 global $root, $nextorder, $pageno, $tabno;
1940 $order = 'odd';
1941 $history = getRackspaceHistory();
1942 // Show the last operation by default.
1943 if (isset ($_REQUEST['op_id']))
1944 $op_id = $_REQUEST['op_id'];
1945 elseif (isset ($history[0]['mo_id']))
1946 $op_id = $history[0]['mo_id'];
1947 else $op_id = NULL;
1948
1949 $omid = NULL;
1950 $nmid = NULL;
1951 $object_id = 1;
1952 if ($op_id)
1953 list ($omid, $nmid) = getOperationMolecules ($op_id);
1954
1955 // Main layout starts.
1956 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
1957
1958 // Left top portlet with old allocation.
1959 echo "<tr><td class=pcleft>";
1960 startPortlet ('Old allocation');
1961 if ($omid)
1962 {
1963 $oldMolecule = getMolecule ($omid);
1964 renderMolecule ($oldMolecule, $object_id);
1965 }
1966 else
1967 echo "nothing";
1968 finishPortlet();
1969
1970 echo '</td><td class=pcright>';
1971
1972 // Right top portlet with new allocation
1973 startPortlet ('New allocation');
1974 if ($nmid)
1975 {
1976 $newMolecule = getMolecule ($nmid);
1977 renderMolecule ($newMolecule, $object_id);
1978 }
1979 else
1980 echo "nothing";
1981 finishPortlet();
1982
1983 echo '</td></tr><tr><td colspan=2>';
1984
1985 // Bottom portlet with list
1986
1987 startPortlet ('Rackspace allocation history');
1988 echo "<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>\n";
1989 echo "<tr><th>timestamp</th><th>author</th><th>rack object ID</th><th>rack object type</th><th>rack object name</th><th>comment</th></tr>\n";
1990 foreach ($history as $row)
1991 {
1992 if ($row['mo_id'] == $op_id)
1993 $class = 'hl';
1994 else
1995 $class = "row_${order}";
1996 echo "<tr class=${class}><td><a href='${root}?page=${pageno}&tab=${tabno}&op_id=${row['mo_id']}'>${row['ctime']}</a></td>";
1997 echo "<td>${row['user_name']}</td>";
1998 echo "<td>${row['ro_id']}</td><td>${row['objtype_name']}</td><td>${row['name']}</td><td>${row['comment']}</td>\n";
1999 echo "</tr>\n";
2000 $order = $nextorder[$order];
2001 }
2002 echo "</table>\n";
2003 finishPortlet();
2004
2005 echo '</td></tr></table>';
2006
2007}
2008
0137d53c 2009function renderIPv4SpaceRecords ($tree, $todo, $level = 0, &$tagcache = array())
d65353ad
DO
2010{
2011 $self = __FUNCTION__;
0137d53c 2012 $doing = 1;
d65353ad
DO
2013 foreach ($tree as $item)
2014 {
b6b87070 2015 $total = binInvMaskFromDec ($item['mask']) + 1;
0137d53c
DO
2016 if (isset ($item['id']))
2017 {
b6b87070
DO
2018 loadIPv4AddrList ($item);
2019 $used = $item['addrc'];
0137d53c
DO
2020 echo "<tr valign=top>";
2021 $verge = ($doing == $todo ? 'L' : 'M') . ($item['kidc'] ? 'M' : 'T');
b6b87070 2022 printIPv4NetInfoTDs ($item, 'tdleft', $level, $verge);
0137d53c
DO
2023 echo "<td class=tdcenter>";
2024 renderProgressBar ($used/$total);
2025 echo "<br><small>${used}/${total}</small></td>";
2026 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
b6b87070 2027 printRoutersTD (findRouters ($item['addrlist']), $tagcache);
0137d53c
DO
2028 echo "</tr>";
2029 $self ($item['kids'], $item['kidc'], $level + 1, $tagcache);
2030 }
2031 else
2032 {
2033 $used = 0;
0137d53c
DO
2034 echo "<tr valign=top>";
2035 $verge = ($doing == $todo ? 'L' : 'M') . 'T';
2036 printIPv4NetInfoTDs ($item, 'tdleft', $level, $verge);
2037 echo "<td class=tdcenter>";
2038 renderProgressBar ($used/$total);
2039 echo "<br><small>${used}/${total}</small></td>";
2040 echo "<td>&nbsp;</td></tr>";
2041 }
2042 $doing++;
d65353ad
DO
2043 }
2044}
2045
04d619d0 2046function renderIPv4Space ()
e673ee24 2047{
932cf41f 2048 $tagfilter = getTagFilter();
94a40058
DO
2049 $netlist = getIPv4NetworkList ($tagfilter, getTFMode());
2050 $netcount = count ($netlist);
2051 $tree = treeFromList ($netlist, getConfigVar ('TREE_THRESHOLD'));
2052 unset ($netlist);
1327d9dd 2053 sortTree ($tree, 'IPv4NetworkCmp');
0137d53c 2054 treeApplyFunc ($tree, 'iptree_fill');
3630d1fb
DO
2055
2056 echo "<table border=0 class=objectview>\n";
2057 echo "<tr><td class=pcleft>";
1327d9dd 2058 // FIXME: the counter is wrong
94a40058 2059 startPortlet ("networks (${netcount})");
04d619d0 2060 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
57dece2f 2061 echo "<tr><th>prefix</th><th>name/tags</th><th>%% used</th>";
f0ed1181 2062 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
57dece2f
DO
2063 echo "<th>routed by</th>";
2064 echo "</tr>\n";
51b6651a 2065 renderIPv4SpaceRecords ($tree, count ($tree));
e673ee24 2066 echo "</table>\n";
a7fe7729 2067 finishPortlet();
74ccacff 2068 echo '</td><td class=pcright>';
5b7bd02e 2069 renderTagFilterPortlet ($tagfilter, 'ipv4net');
74ccacff 2070 echo "</td></tr></table>\n";
f973f491 2071}
a7fe7729 2072
f973f491
DO
2073function renderIPv4SLB ()
2074{
80e85ea1 2075 global $root, $page, $nextorder;
a7fe7729 2076
6fec9f39 2077 startPortlet ('SLB configuration');
b3c50e6c 2078 echo "<table border=0 width='100%'><tr>";
ee437dab 2079 foreach (array ('ipv4vslist', 'ipv4rsplist', 'rservers', 'lbs') as $pno)
e57dca7f 2080 echo "<td><h3><a href='${root}?page=${pno}'>" . $page[$pno]['title'] . "</a></h3></td>";
b3c50e6c
DO
2081 echo '</tr></table>';
2082 finishPortlet();
2083
c3bdc503 2084 $summary = getSLBSummary();
6fec9f39 2085 startPortlet ('SLB tactical overview');
4cadac8f
DO
2086 // A single id-keyed array isn't used here to preserve existing
2087 // order of LBs returned by getSLBSummary()
c3bdc503
DO
2088 $lblist = array();
2089 $lbdname = array();
4cadac8f 2090 foreach ($summary as $vipdata)
da04825a 2091 foreach (array_keys ($vipdata['lblist']) as $lb_object_id)
c3bdc503
DO
2092 if (!in_array ($lb_object_id, $lblist))
2093 {
2094 $oi = getObjectInfo ($lb_object_id);
2095 $lbdname[$lb_object_id] = $oi['dname'];
2096 $lblist[] = $lb_object_id;
2097 }
2098 if (!count ($summary))
2099 echo 'none configured';
2100 else
2101 {
80e85ea1 2102 $order = 'odd';
c3bdc503 2103 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
a7bc13c8 2104 echo "<tr><th>VS&nbsp;&darr; LB&nbsp;&rarr;</th>";
c3bdc503 2105 foreach ($lblist as $lb_object_id)
71b8bda1 2106 echo "<th><a href='${root}?page=object&tab=default&object_id=${lb_object_id}'>" . $lbdname[$lb_object_id] . "</a></th>";
c3bdc503 2107 echo "</tr>\n";
4cadac8f
DO
2108 foreach ($summary as $vsid => $vsdata)
2109 {
49fb2686 2110 echo "<tr class=row_${order}><td class=tdleft><a href='$root?page=ipv4vs&tab=default&vs_id=${vsid}'>";
8d790216 2111 echo buildVServiceName ($vsdata);
6fec9f39
DO
2112 echo '</a>';
2113 if (!empty ($vsdata['name']))
300826cb 2114 echo "<br>${vsdata['name']}";
6fec9f39 2115 echo "</td>";
4cadac8f 2116 foreach ($lblist as $lb_object_id)
da04825a 2117 {
60fbcece 2118 echo '<td class=tdleft>';
2b4eee17 2119 if (!isset ($vsdata['lblist'][$lb_object_id]))
da04825a
DO
2120 echo '&nbsp;';
2121 else
6fec9f39
DO
2122 {
2123 echo $vsdata['lblist'][$lb_object_id]['size'];
79a9edb4
DO
2124// echo " (<a href='${root}?page=ipv4rsp&pool_id=";
2125// echo $vsdata['lblist'][$lb_object_id]['id'] . "'>";
2126// echo $vsdata['lblist'][$lb_object_id]['name'] . '</a>)';
6fec9f39 2127 }
da04825a
DO
2128 echo '</td>';
2129 }
2130 echo "</tr>\n";
80e85ea1 2131 $order = $nextorder[$order];
4cadac8f 2132 }
c3bdc503
DO
2133 echo "</table>\n";
2134 }
a7fe7729 2135 finishPortlet ();
e673ee24
DO
2136}
2137
04d619d0 2138function renderIPv4SpaceEditor ()
e673ee24
DO
2139{
2140 global $root, $pageno, $tabno;
2141 showMessageOrError();
2a201216 2142
a262e150
DO
2143 // IPv4 validator
2144?>
2145 <script type="text/javascript">
2146 function init() {
2147 document.add_new_range.range.setAttribute('match', "^\\d\\d?\\d?\\.\\d\\d?\\d?\\.\\d\\d?\\d?\\.\\d\\d?\\d?\\/\\d\\d?$");
2148
2149 Validate.init();
2150 }
2151 window.onload=init;
2152 </script>
2153<?php
2154
4c0653e2 2155 startPortlet ("Add new");
04d619d0 2156 echo '<table border=0 cellpadding=10 align=center>';
7056988c
DO
2157 // This form requires a name, so JavaScript validator can find it.
2158 // No printOpFormIntro() hence
04d619d0 2159 echo "<form method=post name='add_new_range' action='${root}process.php'>\n";
42023f03 2160 echo "<input type=hidden name=op value=addIPv4Prefix>\n";
2a201216
DY
2161 echo "<input type=hidden name=page value='${pageno}'>\n";
2162 echo "<input type=hidden name=tab value='${tabno}'>\n";
04d619d0
DO
2163 // tags column
2164 echo '<tr><td rowspan=4><h3>assign tags</h3>';
5c0bb421 2165 renderTagSelect();
04d619d0
DO
2166 echo '</td>';
2167 // inputs column
2168 echo "<th class=tdright>prefix</th><td class=tdleft><input type=text name='range' size=18 class='live-validate' tabindex=1></td>";
2169 echo "<tr><th class=tdright>name</th><td class=tdleft><input type=text name='name' size='20' tabindex=2></td></tr>";
2170 echo "<tr><th class=tdright>connected network</th><td class=tdleft><input type=checkbox name='is_bcast' tabindex=3 checked></td></tr>";
2171 echo "<tr><td colspan=2>";
4c0653e2 2172 printImageHREF ('CREATE', 'Add a new network', TRUE, 4);
04d619d0 2173 echo '</td></tr>';
2a201216 2174 echo "</form></table><br><br>\n";
5c0bb421 2175 finishPortlet();
2a201216 2176
b18d26dc 2177 $addrspaceList = getIPv4NetworkList();
04d619d0 2178 if (count ($addrspaceList))
e673ee24 2179 {
04d619d0
DO
2180 startPortlet ('Manage existing (' . count ($addrspaceList) . ')');
2181 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2182 echo "<tr><th>&nbsp;</th><th>prefix</th><th>name</th><th>&nbsp;</th></tr>";
2183 foreach ($addrspaceList as $iprange)
e673ee24 2184 {
b6b87070
DO
2185 $netdata = getIPv4NetworkInfo ($iprange['id']);
2186 loadIPv4AddrList ($netdata);
04d619d0 2187 $usedips = count ($netdata['addrlist']);
b6b87070 2188 $totalips = binInvMaskFromDec ($netdata['mask']) + 1;
04d619d0
DO
2189 echo "<form method=post action='${root}process.php?page=${pageno}&tab=${tabno}&op=updIPv4Prefix&id=${iprange['id']}'>";
2190 echo '<tr valign=top><td>';
2191 if ($usedips == 0)
2192 {
2193 echo "<a href='${root}process.php?op=delIPv4Prefix&page=${pageno}&tab=${tabno}&id=${iprange['id']}'>";
2194 printImageHREF ('delete', 'Delete this IP range');
2195 echo "</a>";
2196 }
2197 else
2198 printImageHREF ('nodelete', 'There are IP addresses allocated or reserved');
2199 echo "</td>\n<td class=tdleft>${netdata['ip']}/${netdata['mask']}</td>";
2200 echo "<td><input type=text name=name size=40 value='${netdata['name']}'>";
2201 echo "</td><td>";
2202 printImageHREF ('save', 'Save changes', TRUE);
2203 echo "</td></tr></form>\n";
e673ee24 2204 }
04d619d0
DO
2205 echo "</table>";
2206 finishPortlet();
e673ee24 2207 }
e673ee24
DO
2208}
2209
beb9e88a 2210function renderIPv4Network ($id)
e673ee24 2211{
beb9e88a 2212 global $root, $pageno, $tabno, $aac2;
545478d0
DO
2213 $netmaskbylen = array
2214 (
2215 32 => '255.255.255.255',
2216 31 => '255.255.255.254',
2217 30 => '255.255.255.252',
2218 29 => '255.255.255.248',
2219 28 => '255.255.255.240',
2220 27 => '255.255.255.224',
2221 26 => '255.255.255.192',
2222 25 => '255.255.255.128',
2223 24 => '255.255.255.0',
2224 23 => '255.255.254.0',
2225 22 => '255.255.252.0',
2226 21 => '255.255.248.0',
2227 20 => '255.255.240.0',
2228 19 => '255.255.224.0',
2229 18 => '255.255.192.0',
2230 17 => '255.255.128.0',
2231 16 => '255.255.0.0',
2232 15 => '255.254.0.0',
2233 14 => '255.252.0.0',
2234 13 => '255.248.0.0',
2235 12 => '255.240.0.0',
2236 11 => '255.224.0.0',
2237 10 => '255.192.0.0',
2238 9 => '255.128.0.0',
2239 8 => '255.0.0.0',
2240 7 => '254.0.0.0',
2241 6 => '252.0.0.0',
2242 5 => '248.0.0.0',
2243 4 => '240.0.0.0',
2244 3 => '224.0.0.0',
2245 2 => '192.0.0.0',
2246 1 => '128.0.0.0'
2247 );
2248 $wildcardbylen = array
2249 (
2250 32 => '0.0.0.0',
2251 31 => '0.0.0.1',
2252 30 => '0.0.0.3',
2253 29 => '0.0.0.7',
2254 28 => '0.0.0.15',
2255 27 => '0.0.0.31',
2256 26 => '0.0.0.63',
2257 25 => '0.0.0.127',
2258 24 => '0.0.0.255',
2259 23 => '0.0.1.255',
2260 22 => '0.0.3.255',
2261 21 => '0.0.7.255',
2262 20 => '0.0.15.255',
2263 19 => '0.0.31.255',
2264 18 => '0.0.63.255',
2265 17 => '0.0.127.255',
2266 16 => '0.0.255.25',
2267 15 => '0.1.255.255',
2268 14 => '0.3.255.255',
2269 13 => '0.7.255.255',
2270 12 => '0.15.255.255',
2271 11 => '0.31.255.255',
2272 10 => '0.63.255.255',
2273 9 => '0.127.255.255',
2274 8 => '0.255.255.255',
2275 7 => '1.255.255.255',
2276 6 => '3.255.255.255',
2277 5 => '7.255.255.255',
2278 4 => '15.255.255.255',
2279 3 => '31.255.255.255',
2280 2 => '63.255.255.255',
2281 1 => '127.255.255.255'
2282 );
b901bf1f 2283 $maxperpage = getConfigVar ('IPV4_ADDRS_PER_PAGE');
e673ee24
DO
2284 if (isset($_REQUEST['pg']))
2285 $page = $_REQUEST['pg'];
2286 else
2287 $page=0;
2288
b6b87070
DO
2289 $range = getIPv4NetworkInfo ($id);
2290 loadIPv4AddrList ($range);
2034d968
DO
2291 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
2292 echo "<tr><td colspan=2 align=center><h1>${range['ip']}/${range['mask']}</h1><h2>${range['name']}</h2></td></tr>\n";
2293
2294 echo "<tr><td class=pcleft width='50%'>";
2295 startPortlet ('summary');
2296 $total = ($range['ip_bin'] | $range['mask_bin_inv']) - ($range['ip_bin'] & $range['mask_bin']) + 1;
2297 $used = count ($range['addrlist']);
2298 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
04d619d0
DO
2299
2300 echo "<tr><th width='50%' class=tdright>%% used:</th><td class=tdleft>";
2034d968
DO
2301 renderProgressBar ($used/$total);
2302 echo "&nbsp;${used}/${total}</td></tr>\n";
04d619d0 2303
545478d0
DO
2304 echo "<tr><th width='50%' class=tdright>Netmask:</th><td class=tdleft>";
2305 echo $netmaskbylen[$range['mask']];
2306 echo "</td></tr>\n";
04d619d0 2307
545478d0
DO
2308 echo "<tr><th width='50%' class=tdright>Wildcard bits:</th><td class=tdleft>";
2309 echo $wildcardbylen[$range['mask']];
2310 echo "</td></tr>\n";
04d619d0 2311
f3d0cb20 2312 $routers = findRouters ($range['addrlist']);
f0ed1181 2313 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes' and count ($routers))
04d619d0 2314 {
57dece2f 2315 echo "<tr><th width='50%' class=tdright>Routed by:</th>";
f3d0cb20 2316 printRoutersTD ($routers);
57dece2f 2317 echo "</tr>\n";
04d619d0
DO
2318 }
2319
e2ac59cf 2320 printTagTRs ("${root}?page=ipv4space&");
2034d968
DO
2321 echo "</table><br>\n";
2322 finishPortlet();
2323 echo "</td>\n";
e673ee24 2324
2034d968
DO
2325 echo "<td class=pcright>";
2326 startPortlet ('details');
e673ee24
DO
2327 $startip = $range['ip_bin'] & $range['mask_bin'];
2328 $endip = $range['ip_bin'] | $range['mask_bin_inv'];
2329 $realstartip = $startip;
2330 $realendip = $endip;
2331 $numpages = 0;
2332 if($endip - $startip > $maxperpage)
2333 {
e673ee24
DO
2334 $numpages = ($endip - $startip)/$maxperpage;
2335 $startip = $startip + $page * $maxperpage;
2336 $endip = $startip + $maxperpage-1;
2337 }
2338 echo "<center>";
b901bf1f
DO
2339 if ($numpages)
2340 echo '<h3>' . long2ip ($startip) . ' ~ ' . long2ip ($endip) . '</h3>';
e673ee24
DO
2341 for ($i=0; $i<$numpages; $i++)
2342 {
2343 if ($i == $page)
2344 echo "<b>$i</b> ";
2345 else
a60e0851 2346 echo "<a href='${root}?page=${pageno}&tab=${tabno}&id=$id&pg=$i'>$i</a> ";
e673ee24
DO
2347 }
2348 echo "</center>";
2349
beb9e88a 2350 echo "<table class='widetable' border=0 cellspacing=0 cellpadding=5 align='center' width='100%'>\n";
e673ee24
DO
2351 echo "<tr><th>Address</th><th>Name</th><th>Allocation</th></tr>\n";
2352
2353
b2035dca
DO
2354 for ($ip = $startip; $ip <= $endip; $ip++) :
2355 if (isset ($_REQUEST['hl_ipv4_addr']) and ip2long ($_REQUEST['hl_ipv4_addr']) == $ip)
2356 $secondstyle = 'tdleft port_highlight';
2727c7df 2357 else
b2035dca
DO
2358 $secondstyle = 'tdleft';
2359 if (!isset ($range['addrlist'][$ip]))
e673ee24 2360 {
b2035dca
DO
2361 echo "<tr><td class=tdleft><a href='${root}?page=ipaddress&ip=" . long2ip ($ip) . "'>" . long2ip ($ip);
2362 echo "</a></td><td class='${secondstyle}'>&nbsp;</td><td class='${secondstyle}'>&nbsp;</td></tr>\n";
2363 continue;
2364 }
b2035dca 2365 $addr = $range['addrlist'][$ip];
2d318652 2366 echo "<tr class='${addr['class']}'>";
e673ee24 2367
b2035dca
DO
2368 echo "<td class=tdleft><a href='${root}?page=ipaddress&ip=${addr['ip']}'>${addr['ip']}</a></td>";
2369 echo "<td class='${secondstyle}'>${addr['name']}</td><td class='${secondstyle}'>";
2370 $delim = '';
2371 $prologue = '';
2372 if ( $addr['reserved'] == 'yes')
2373 {
2d318652 2374 echo "<strong>RESERVED</strong> ";
b2035dca
DO
2375 $delim = '; ';
2376 }
2d318652 2377 foreach ($range['addrlist'][$ip]['allocs'] as $ref)
b2035dca 2378 {
beb9e88a
DO
2379 echo $delim . $aac2[$ref['type']];
2380 echo "<a href='${root}?page=object&object_id=${ref['object_id']}";
b2035dca
DO
2381 echo "&hl_ipv4_addr=${addr['ip']}'>";
2382 echo $ref['name'] . (empty ($ref['name']) ? '' : '@');
2383 echo "${ref['object_name']}</a>";
2384 $delim = '; ';
2385 }
2386 if ($delim != '')
2387 {
6131056c 2388 $delim = '';
b2035dca
DO
2389 $prologue = '<br>';
2390 }
2d318652 2391 foreach ($range['addrlist'][$ip]['lblist'] as $ref)
b2035dca
DO
2392 {
2393 echo $prologue;
602663f4 2394 $prologue = '';
b2035dca
DO
2395 echo "${delim}<a href='${root}?page=object&object_id=${ref['object_id']}'>";
2396 echo "${ref['object_name']}</a>:<a href='${root}?page=ipv4vs&vs_id=${ref['vs_id']}'>";
2397 echo "${ref['vport']}/${ref['proto']}</a>&rarr;";
2398 $delim = '; ';
2399 }
2400 if ($delim != '')
2401 {
2402 $delim = '';
2403 $prologue = '<br>';
e673ee24 2404 }
2d318652 2405 foreach ($range['addrlist'][$ip]['rslist'] as $ref)
b2035dca
DO
2406 {
2407 echo $prologue;
2408 $prologue = '';
2409 echo "${delim}&rarr;${ref['rsport']}@<a href='${root}?page=ipv4rsp&pool_id=${ref['rspool_id']}'>";
2410 echo "${ref['rspool_name']}</a>";
2411 $delim = '; ';
2412 }
2413 echo "</td></tr>\n";
2414 endfor;
2727c7df 2415 // end of iteration
e673ee24
DO
2416
2417 echo "</table>";
2034d968
DO
2418 finishPortlet();
2419 echo "</td></tr></table>\n";
e673ee24
DO
2420}
2421
53ef3908 2422function renderIPv4NetworkProperties ($id)
e673ee24 2423{
e673ee24 2424 showMessageOrError();
53ef3908
DO
2425 $netdata = getIPv4NetworkInfo ($id);
2426 echo "<center><h1>${netdata['ip']}/${netdata['mask']}</h1></center>\n";
e673ee24 2427 echo "<table border=0 cellpadding=10 cellpadding=1 align='center'>\n";
7056988c 2428 printOpFormIntro ('editRange');
53ef3908
DO
2429 echo "<tr><td class='tdright'>Name:</td><td class='tdleft'><input type=text name=name size=20 value='${netdata['name']}'></tr>";
2430 echo "<tr><td colspan=2 class=tdcenter>";
2431 printImageHREF ('SAVE', 'Save changes', TRUE);
2432 echo "</td></form></tr></table>\n";
e673ee24
DO
2433}
2434
2d318652 2435function renderIPv4Address ($dottedquad)
e673ee24 2436{
52c836b1 2437 global $root, $aat;
2d318652 2438 $address = getIPv4Address ($dottedquad);
68225375 2439 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
2d318652
DO
2440 echo "<tr><td colspan=2 align=center><h1>${dottedquad}</h1></td></tr>\n";
2441 if (!empty ($address['name']))
68225375 2442 echo "<tr><td colspan=2 align=center><h2>${address['name']}</h2></td></tr>\n";
e673ee24 2443
68225375
DO
2444 echo "<tr><td class=pcleft>";
2445 startPortlet ('summary');
2446 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
04d619d0 2447 echo "<tr><th width='50%' class=tdright>Allocations:</th><td class=tdleft>" . count ($address['allocs']) . "</td></tr>\n";
68225375
DO
2448 echo "<tr><th width='50%' class=tdright>Originated NAT connections:</th><td class=tdleft>" . count ($address['outpf']) . "</td></tr>\n";
2449 echo "<tr><th width='50%' class=tdright>Arriving NAT connections:</th><td class=tdleft>" . count ($address['inpf']) . "</td></tr>\n";
04d619d0 2450 echo "<tr><th width='50%' class=tdright>SLB virtual services:</th><td class=tdleft>" . count ($address['lblist']) . "</td></tr>\n";
68225375
DO
2451 echo "<tr><th width='50%' class=tdright>SLB real servers:</th><td class=tdleft>" . count ($address['rslist']) . "</td></tr>\n";
2452 printTagTRs();
2453 echo "</table><br>\n";
2454 finishPortlet();
2455 echo "</td>\n";
e673ee24 2456
68225375 2457 echo "<td class=pcright>";
e673ee24 2458
2d318652 2459 if (!empty ($address['class']))
59bebe2b 2460 {
8e700dd1 2461 startPortlet ('allocations');
2d318652
DO
2462 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2463 echo "<tr><th>object</th><th>OS interface</th><th>allocation type</th></tr>\n";
2464 $class = $address['class'];
2465 // render all allocation records for this address the same way
59bebe2b 2466 if ($address['reserved'] == 'yes')
2d318652
DO
2467 echo "<tr class='${class}'><td colspan=2>&nbsp;</td><td class=tdleft><strong>RESERVED</strong></td></tr>";
2468 foreach ($address['allocs'] as $bond)
59bebe2b 2469 {
8e700dd1
DO
2470 if (isset ($_REQUEST['hl_object_id']) and $_REQUEST['hl_object_id'] == $bond['object_id'])
2471 $secondclass = 'tdleft port_highlight';
2472 else
2473 $secondclass = 'tdleft';
2474 echo "<tr class='$class'><td class=tdleft><a href='${root}?page=object&object_id=${bond['object_id']}";
2d318652 2475 echo "&hl_ipv4_addr=${dottedquad}'>${bond['object_name']}</td><td class='${secondclass}'>${bond['name']}</td><td class='${secondclass}'><strong>";
52c836b1
DO
2476 echo $aat[$bond['type']];
2477 echo "</strong></td></tr>\n";
59bebe2b
DO
2478 }
2479 echo "</table><br><br>";
2480 finishPortlet();
2481 }
e673ee24 2482
f3d0cb20
DO
2483 // FIXME: The returned list is structured differently, than we expect it to be. One of the sides
2484 // must be fixed.
2d318652 2485 if (count ($address['lblist']))
e673ee24 2486 {
2d318652
DO
2487 startPortlet ('Virtual services (' . count ($address['lblist']) . ')');
2488 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
59bebe2b 2489 echo "<tr><th>VS</th><th>name</th></tr>\n";
2d318652 2490 foreach ($address['lblist'] as $vsinfo)
e673ee24 2491 {
2d318652 2492 echo "<tr><td class=tdleft><a href='${root}?page=ipv4vs&vs_id=${vsinfo['vs_id']}'>";
59bebe2b 2493 echo buildVServiceName ($vsinfo) . "</a></td><td class=tdleft>";
5fe1ed76 2494 echo $vsinfo['name'] . "</td></tr>\n";
e673ee24 2495 }
59bebe2b
DO
2496 echo "</table><br><br>";
2497 finishPortlet();
e673ee24 2498 }
5fe1ed76
DO
2499
2500 if (count ($address['rslist']))
2501 {
2502 startPortlet ('Real servers (' . count ($address['rslist']) . ')');
2d318652 2503 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
53f4b619 2504 echo "<tr><th>&nbsp;</th><th>port</th><th>RS pool</th></tr>\n";
5fe1ed76
DO
2505 foreach ($address['rslist'] as $rsinfo)
2506 {
2507 echo "<tr><td>";
2508 if ($rsinfo['inservice'] == 'yes')
2509 printImageHREF ('inservice', 'in service');
2510 else
2511 printImageHREF ('notinservice', 'NOT in service');
2d318652
DO
2512 echo "</td><td class=tdleft>${rsinfo['rsport']}</td><td class=tdleft><a href='${root}?page=ipv4rsp&pool_id=${rsinfo['rspool_id']}'>";
2513 echo $rsinfo['rspool_name'] . "</a></td></tr>\n";
5fe1ed76
DO
2514 }
2515 echo "</table><br><br>";
2516 finishPortlet();
2517 }
2518
68225375
DO
2519 if (count ($address['outpf']))
2520 {
105a3bc8 2521 startPortlet ('departing NAT rules');
2d318652 2522 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
105a3bc8
DO
2523 echo "<tr><th>proto</th><th>from</th><th>to</th><th>comment</th></tr>\n";
2524 foreach ($address['outpf'] as $rule)
b62ff880 2525 echo "<tr><td>${rule['proto']}</td><td>${rule['localip']}:${rule['localport']}</td><td>${rule['remoteip']}:${rule['remoteport']}</td><td>${rule['description']}</td></tr>";
105a3bc8 2526 echo "</table>";
68225375
DO
2527 finishPortlet();
2528 }
105a3bc8
DO
2529
2530 if (count ($address['inpf']))
2531 {
2532 startPortlet ('arriving NAT rules');
2d318652 2533 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
105a3bc8
DO
2534 echo "<tr><th>proto</th><th>from</th><th>to</th><th>comment</th></tr>\n";
2535 foreach ($address['inpf'] as $rule)
b62ff880 2536 echo "<tr><td>${rule['proto']}</td><td>${rule['localip']}:${rule['localport']}</td><td>${rule['remoteip']}:${rule['remoteport']}</td><td>${rule['description']}</td></tr>";
105a3bc8
DO
2537 echo "</table>";
2538 finishPortlet();
2539 }
2540
68225375
DO
2541 echo "</td></tr>";
2542 echo "</table>\n";
e673ee24
DO
2543}
2544
2d318652 2545function renderIPv4AddressProperties ($dottedquad)
e673ee24 2546{
e673ee24 2547 showMessageOrError();
2d318652
DO
2548 $address = getIPv4Address ($dottedquad);
2549 echo "<center><h1>$dottedquad</h1></center>\n";
7056988c 2550
1fbc9fd6 2551 startPortlet ('update');
e673ee24 2552 echo "<table border=0 cellpadding=10 cellpadding=1 align='center'>\n";
7056988c 2553 printOpFormIntro ('editAddress');
2d318652
DO
2554 echo "<tr><td class='tdright'>Name:</td><td class='tdleft'><input type=text name=name size=20 value='${address['name']}'></tr>";
2555 echo "<td class='tdright'>Reserved:</td><td class='tdleft'><input type=checkbox name=reserved size=20 ";
2556 echo ($address['reserved']=='yes') ? 'checked' : '';
53ef3908
DO
2557 echo "></tr><tr><td colspan=2 class='tdcenter'>";
2558 printImageHREF ('SAVE', 'Save changes', TRUE);
2559 echo "</td></form></tr></table>\n";
1fbc9fd6
DO
2560 finishPortlet();
2561 if (empty ($address['name']) and $address['reserved'] == 'no')
2562 return;
7056988c 2563
1fbc9fd6 2564 startPortlet ('release');
7056988c 2565 printOpFormIntro ('editAddress', array ('name' => '', 'reserved' => ''));
1fbc9fd6
DO
2566 echo "<input type=submit value='release'></form>";
2567 finishPortlet();
e673ee24
DO
2568}
2569
2d318652 2570function renderIPv4AddressAllocations ($dottedquad)
e673ee24 2571{
e673ee24 2572 showMessageOrError();
2d318652 2573 global $pageno, $tabno, $root, $aat;
e673ee24 2574
2d318652
DO
2575 $address = getIPv4Address ($dottedquad);
2576 $class = $address['class'];
2577 echo "<center><h1>${dottedquad}</h1></center>\n";
105a3bc8 2578 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
2d318652 2579 echo "<tr><th>&nbsp;</th><th>object</th><th>OS interface</th><th>allocation type</th><th>&nbsp;</th></tr>\n";
e673ee24
DO
2580
2581 if ($address['reserved'] == 'yes')
2d318652
DO
2582 echo "<tr class='${class}'><td colspan=3>&nbsp;</td><td class=tdleft><strong>RESERVED</strong></td><td>&nbsp;</td></tr>";
2583 foreach ($address['allocs'] as $bond)
e673ee24 2584 {
7056988c
DO
2585 echo "<tr class='$class'>";
2586 printOpFormIntro ('updIPv4Allocation', array ('object_id' => $bond['object_id']));
2d318652 2587 echo "<td><a href='${root}process.php?op=delIPv4Allocation&page=${pageno}&tab=${tabno}&ip=${dottedquad}&object_id=${bond['object_id']}'>";
e673ee24
DO
2588 printImageHREF ('delete', 'Unallocate address');
2589 echo "</a></td>";
2d318652 2590 echo "<td><a href='${root}?page=object&object_id=${bond['object_id']}&hl_ipv4_addr=${dottedquad}'>${bond['object_name']}</td>";
52c836b1
DO
2591 echo "<td><input type='text' name='bond_name' value='${bond['name']}' size=10></td><td>";
2592 printSelect ($aat, 'bond_type', $bond['type']);
2593 echo "</td><td>";
b4c1ef87
DO
2594 printImageHREF ('save', 'Save changes', TRUE);
2595 echo "</td></form></tr>\n";
e673ee24 2596 }
7056988c 2597 printOpFormIntro ('addIPv4Allocation');
b4c1ef87
DO
2598 echo "<td>";
2599 printImageHREF ('add', 'new allocation', TRUE);
2600 echo "</td><td><select name='object_id'>";
e673ee24 2601
6dbdc7c7 2602 foreach (explode (',', getConfigVar ('IPV4_PERFORMERS')) as $type)
e9132485 2603 foreach (getNarrowObjectList ($type) as $object)
e673ee24 2604 echo "<option value='${object['id']}'>${object['dname']}</option>";
e673ee24 2605
52c836b1
DO
2606 echo "</select></td><td><input type='text' name='bond_name' value='' size=10></td><td>";
2607 printSelect ($aat, 'bond_type');
2608 echo "</td><td>&nbsp;</td></form></tr>";
e673ee24
DO
2609 echo "</table><br><br>";
2610
2611}
2612
eeb4a5d8 2613function renderNATv4ForObject ($object_id = 0)
e673ee24
DO
2614{
2615 global $pageno, $tabno, $root;
2616
2617 $info = getObjectInfo ($object_id);
eeb4a5d8 2618 $forwards = getNATv4ForObject ($object_id);
2c817354 2619 $alloclist = getObjectIPv4Allocations ($object_id);
e673ee24 2620 showMessageOrError();
f28fbe8b 2621 echo "<center><h2>locally performed NAT</h2></center>";
e673ee24 2622
105a3bc8 2623 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
d54b9495 2624 echo "<tr><th></th><th>Match endpoint</th><th>Translate to</th><th>Target object</th><th>Comment</th><th>&nbsp;</th></tr>\n";
e673ee24
DO
2625
2626 foreach ($forwards['out'] as $pf)
2627 {
2c817354
DO
2628 $class = 'trerror';
2629 $osif = '';
2630 if (isset ($alloclist [$pf['localip']]))
2631 {
2632 $class = $alloclist [$pf['localip']]['addrinfo']['class'];
2633 $osif = $alloclist [$pf['localip']]['osif'] . ': ';
2634 }
e673ee24
DO
2635
2636 echo "<tr class='$class'>";
72d8ced3 2637 echo "<td><a href='${root}process.php?op=delNATv4Rule&localip=${pf['localip']}&localport=${pf['localport']}&remoteip=${pf['remoteip']}&remoteport=${pf['remoteport']}&proto=${pf['proto']}&object_id=$object_id&page=${pageno}&tab=${tabno}'>";
4de22e7e
DO
2638 printImageHREF ('delete', 'Delete NAT rule');
2639 echo "</a></td>";
2c817354 2640 echo "<td>${pf['proto']}/${osif}<a href='${root}?page=ipaddress&tab=default&ip=${pf['localip']}'>${pf['localip']}</a>:${pf['localport']}";
f28fbe8b
DO
2641 if (!empty ($pf['local_addr_name']))
2642 echo ' (' . $pf['local_addr_name'] . ')';
2643 echo "</td>";
e673ee24
DO
2644 echo "<td><a href='${root}?page=ipaddress&tab=default&ip=${pf['remoteip']}'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
2645
53ef3908 2646 $address = getIPv4Address ($pf['remoteip']);
e673ee24
DO
2647
2648 echo "<td class='description'>";
53ef3908
DO
2649 if (count ($address['allocs']))
2650 foreach ($address['allocs'] as $bond)
f28fbe8b
DO
2651 echo "<a href='${root}?page=object&tab=default&object_id=${bond['object_id']}'>${bond['object_name']}(${bond['name']})</a> ";
2652 elseif (!empty ($pf['remote_addr_name']))
2653 echo '(' . $pf['remote_addr_name'] . ')';
7056988c
DO
2654 printOpFormIntro
2655 (
2656 'updNATv4Rule',
2657 array
2658 (
2659 'localip' => $pf['localip'],
2660 'localport' => $pf['localport'],
2661 'remoteip' => $pf['remoteip'],
2662 'remoteport' => $pf['remoteport'],
2663 'proto' => $pf['proto']
2664 )
2665 );
2666 echo "</td><td class='description'>";
d54b9495
DO
2667 echo "<input type='text' name='description' value='${pf['description']}'></td><td>";
2668 printImageHREF ('save', 'Save changes', TRUE);
2669 echo "</td></form></tr>";
e673ee24 2670 }
7056988c 2671 printOpFormIntro ('addNATv4Rule');
d54b9495
DO
2672 echo "<tr align='center'><td>";
2673 printImageHREF ('add', 'Add new NAT rule', TRUE);
2674 echo '</td><td>';
eeb4a5d8 2675 printSelect (array ('TCP' => 'TCP', 'UDP' => 'UDP'), 'proto');
52c3543f 2676 echo "<select name='localip' tabindex=1>";
e673ee24 2677
2c817354
DO
2678 foreach ($alloclist as $dottedquad => $alloc)
2679 {
2680 $name = empty ($alloc['addrinfo']['name']) ? '' : (' (' . niftyString ($alloc['addrinfo']['name']) . ')');
2681 $osif = empty ($alloc['osif']) ? '' : ($alloc['osif'] . ': ');
2682 echo "<option value='${dottedquad}'>${osif}${dottedquad}${name}</option>";
2683 }
e673ee24 2684
52c3543f
DO
2685 echo "</select>:<input type='text' name='localport' size='4' tabindex=2></td>";
2686 echo "<td><input type='text' name='remoteip' id='remoteip' size='10' tabindex=3>";
4de22e7e
DO
2687 echo "<a href='javascript:;' onclick='window.open(\"${root}/find_object_ip_helper.php\", \"findobjectip\", \"height=700, width=400, location=no, menubar=no, resizable=yes, scrollbars=no, status=no, titlebar=no, toolbar=no\");'>";
2688 printImageHREF ('find', 'Find object');
2689 echo "</a>";
52c3543f 2690 echo ":<input type='text' name='remoteport' size='4' tabindex=4></td><td></td>";
d54b9495 2691 echo "<td colspan=1><input type='text' name='description' size='20' tabindex=5></td><td>&nbsp;</td></tr>";
e673ee24
DO
2692 echo "</form>";
2693
2694 echo "</table><br><br>";
2695
f28fbe8b 2696 echo "<center><h2>arriving NAT connections</h2></center>";
105a3bc8 2697 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
e673ee24
DO
2698 echo "<tr><th></th><th>Source</th><th>Source objects</th><th>Target</th><th>Description</th></tr>\n";
2699
2700 foreach ($forwards['in'] as $pf)
2701 {
72d8ced3 2702 echo "<tr><td><a href='${root}process.php?op=delNATv4Rule&localip=${pf['localip']}&localport=${pf['localport']}&remoteip=${pf['remoteip']}&remoteport=${pf['remoteport']}&proto=${pf['proto']}&object_id=${pf['object_id']}&page=${pageno}&tab=${tabno}'>";
4de22e7e
DO
2703 printImageHREF ('delete', 'Delete NAT rule');
2704 echo "</a></td>";
e673ee24
DO
2705 echo "<td>${pf['proto']}/<a href='${root}?page=ipaddress&tab=default&ip=${pf['localip']}'>${pf['localip']}</a>:${pf['localport']}</td>";
2706 echo "<td class='description'><a href='${root}?page=object&tab=default&object_id=${pf['object_id']}'>${pf['object_name']}</a>";
2707 echo "</td><td><a href='${root}?page=ipaddress&tab=default&ip=${pf['remoteip']}'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
2708 echo "<td class='description'>${pf['description']}</td></tr>";
2709 }
2710
e673ee24 2711 echo "</table><br><br>";
e673ee24
DO
2712}
2713
7056988c 2714// FIXME: move related code away into ophandler(s)
e673ee24
DO
2715function renderAddMultipleObjectsForm ()
2716{
20c901a7 2717 global $root, $pageno, $tabno, $nextorder;
e673ee24
DO
2718
2719 $type_id = array();
7f791d1d 2720 $global_type_id = 0;
e673ee24
DO
2721 $name = array();
2722 $asset_no = array();
ce4d1a79 2723 $keepvalues1 = $keepvalues2 = FALSE;
7f791d1d 2724 $log = array();
e673ee24 2725 // Look for current submit.
7f791d1d 2726 if (isset ($_REQUEST['got_fast_data']))
e673ee24 2727 {
f60bb422 2728 $taglist = isset ($_REQUEST['taglist']) ? $_REQUEST['taglist'] : array();
ce4d1a79 2729 $keepvalues1 = TRUE;
9c0b0016
DO
2730 $max = getConfigVar ('MASSCOUNT');
2731 for ($i = 0; $i < $max; $i++)
e673ee24
DO
2732 {
2733 if (!isset ($_REQUEST["${i}_object_type_id"]))
2734 {
2735 $log[] = array ('code' => 'error', 'message' => "Submitted form is invalid at line " . $i + 1);
2736 break;
2737 }
2c6c7645
DO
2738 assertUIntArg ("${i}_object_type_id", __FUNCTION__, TRUE);
2739 assertStringArg ("${i}_object_name", __FUNCTION__, TRUE);
2740 assertStringArg ("${i}_object_label", __FUNCTION__, TRUE);
2741 assertStringArg ("${i}_object_asset_no", __FUNCTION__, TRUE);
2742 assertStringArg ("${i}_object_barcode", __FUNCTION__, TRUE);
e673ee24
DO
2743 $type_id[$i] = $_REQUEST["${i}_object_type_id"];
2744 // Save user input for possible rendering.
2745 $name[$i] = $_REQUEST["${i}_object_name"];
2746 $label[$i] = $_REQUEST["${i}_object_label"];
2747 $asset_no[$i] = $_REQUEST["${i}_object_asset_no"];
2748 $barcode[$i] = $_REQUEST["${i}_object_barcode"];
2749
f60bb422 2750 // It's better to skip silently, than to print a notice.
e673ee24
DO
2751 if ($type_id[$i] == 0)
2752 continue;
f60bb422 2753 if (commitAddObject ($name[$i], $label[$i], $barcode[$i], $type_id[$i], $asset_no[$i], $taglist) === TRUE)
e673ee24
DO
2754 $log[] = array ('code' => 'success', 'message' => "Added new object '${name[$i]}'");
2755 else
4d2e93f2 2756 $log[] = array ('code' => 'error', 'message' => __FUNCTION__ . ': commitAddObject() failed');
e673ee24 2757 }
e673ee24 2758 }
7f791d1d
DO
2759 elseif (isset ($_REQUEST['got_very_fast_data']))
2760 {
f60bb422 2761 $taglist = isset ($_REQUEST['taglist']) ? $_REQUEST['taglist'] : array();
ce4d1a79 2762 $keepvalues2 = TRUE;
2c6c7645
DO
2763 assertUIntArg ('global_type_id', __FUNCTION__, TRUE);
2764 assertStringArg ('namelist', __FUNCTION__, TRUE);
7f791d1d
DO
2765 $global_type_id = $_REQUEST['global_type_id'];
2766 if ($global_type_id == 0)
2767 {
2768 if (!empty ($_REQUEST['namelist']))
2769 $log[] = array ('code' => 'error', 'message' => 'Object type is not selected, check the form below');
2770 else
2771 $log[] = array ('code' => 'error', 'message' => 'Empty form has been ignored. Cheers.');
2772 }
2773 else
2774 {
2775 // The name extractor below was stolen from ophandlers.php:addMultiPorts()
2776 $names1 = explode ('\n', $_REQUEST['namelist']);
2777 $names2 = array();
2778 foreach ($names1 as $line)
2779 {
2780 $parts = explode ('\r', $line);
2781 reset ($parts);
2782 if (empty ($parts[0]))
2783 continue;
2784 else
2785 $names2[] = rtrim ($parts[0]);
2786 }
2787 foreach ($names2 as $cname)
f60bb422 2788 if (commitAddObject ($cname, '', '', $global_type_id, '', $taglist) === TRUE)
7f791d1d
DO
2789 $log[] = array ('code' => 'success', 'message' => "Added new object '${cname}'");
2790 else
2791 $log[] = array ('code' => 'error', 'message' => "Could not add '${cname}'");
2792 }
2793 }
2794 printLog ($log);
e673ee24
DO
2795
2796 // Render a form for the next.
2797 $typelist = getObjectTypeList();
4c330a14 2798 $typelist[0] = 'select type...';
7f791d1d 2799
f60bb422
DO
2800 startPortlet ('Distinct types, same tags');
2801 $max = getConfigVar ('MASSCOUNT');
20c901a7 2802 echo "<form name=fastform method=post action='${root}?page=${pageno}&tab=${tabno}'>";
e673ee24 2803 echo '<table border=0 align=center>';
f60bb422
DO
2804 echo "<tr><th>Object type</th><th>Common name</th><th>Visible label</th>";
2805 echo "<th>Asset tag</th><th>Barcode</th><th>Tags</th></tr>\n";
7f791d1d 2806 // If a user forgot to select object type on input, we keep his
e673ee24 2807 // previous input in the form.
9c0b0016 2808 for ($i = 0; $i < $max; $i++)
e673ee24 2809 {
7f791d1d 2810 echo '<tr><td>';
e7ade6bf
DO
2811 // Don't employ DEFAULT_OBJECT_TYPE to avoid creating ghost records for pre-selected empty rows.
2812 printSelect ($typelist, "${i}_object_type_id", 0);
e673ee24
DO
2813 echo '</td>';
2814 echo "<td><input type=text size=30 name=${i}_object_name";
ce4d1a79 2815 if ($keepvalues1 and isset ($name[$i]) and (!isset ($type_id[$i]) or $type_id[$i] == 0))
e673ee24
DO
2816 echo " value='${name[$i]}'";
2817 echo "></td>";
2818 echo "<td><input type=text size=30 name=${i}_object_label";
ce4d1a79 2819 if ($keepvalues1 and isset ($label[$i]) and (!isset ($type_id[$i]) or $type_id[$i] == 0))
e673ee24
DO
2820 echo " value='${label[$i]}'";
2821 echo "></td>";
2822 echo "<td><input type=text size=20 name=${i}_object_asset_no";
ce4d1a79 2823 if ($keepvalues1 and isset ($asset_no[$i]) and (!isset ($type_id[$i]) or $type_id[$i] == 0))
e673ee24
DO
2824 echo " value='${asset_no[$i]}'";
2825 echo "></td>";
2826 echo "<td><input type=text size=10 name=${i}_object_barcode";
ce4d1a79 2827 if ($keepvalues1 and isset ($barcode[$i]) and (!isset ($type_id[$i]) or $type_id[$i] == 0))
e673ee24
DO
2828 echo " value='${barcode[$i]}'";
2829 echo "></td>";
f60bb422
DO
2830 if ($i == 0)
2831 {
2832 echo "<td valign=top rowspan=${max}>";
2833 renderTagSelect();
2834 echo "</td>\n";
2835 }
e673ee24 2836 echo "</tr>\n";
e673ee24 2837 }
216c84bb 2838 echo "<tr><td class=submit colspan=5><input type=submit name=got_fast_data value='Go!'></td></tr>\n";
e673ee24
DO
2839 echo "</form></table>\n";
2840 finishPortlet();
7f791d1d 2841
f60bb422 2842 startPortlet ('Same type, same tags');
20c901a7 2843 echo "<form name=veryfastform method=post action='${root}?page=${pageno}&tab=${tabno}'>";
f60bb422
DO
2844 echo "<table border=0 align=center><tr><th>names</th><th>type</th></tr>";
2845 echo "<tr><td rowspan=3><textarea name=namelist cols=40 rows=25>\n";
ce4d1a79 2846 if ($keepvalues2 and $global_type_id == 0)
7f791d1d 2847 echo $_REQUEST['namelist'];
f60bb422
DO
2848 echo "</textarea></td><td valign=top>";
2849 printSelect ($typelist, "global_type_id", getConfigVar ('DEFAULT_OBJECT_TYPE'));
2850 echo "</td></tr>";
2851 echo "<tr><th>Tags</th></tr>";
2852 echo "<tr><td valign=top>";
2853 renderTagSelect();
2854 echo "</td></tr>";
2855 echo "<tr><td colspan=2><input type=submit name=got_very_fast_data value='Go!'></td></tr></table>\n";
2856 echo "</form>\n";
7f791d1d 2857 finishPortlet();
e673ee24
DO
2858}
2859
2860function printGreeting ()
2861{
59cd003e 2862 global $remote_username, $accounts, $root;
e673ee24 2863 $account = $accounts[$remote_username];
7056988c
DO
2864 $person = empty ($account['user_realname']) ? $account['user_name'] : $account['user_realname'];
2865 echo "Hello, ${person}. This is RackTables " . CODE_VERSION . ". Click <a href='${root}?logout'>here</a> to logout.";
e673ee24
DO
2866}
2867
2868function renderSearchResults ()
2869{
2870 global $remote_username, $root;
2871 $terms = trim ($_REQUEST['q']);
2872 if (empty ($terms))
2873 {
591ff2c4 2874 showError ('Search string cannot be empty.', __FUNCTION__);
e673ee24
DO
2875 return;
2876 }
54522168 2877 if (!permitted ('objects', 'default'))
e673ee24 2878 {
591ff2c4 2879 showError ('You are not authorized for viewing information about objects.', __FUNCTION__);
e673ee24
DO
2880 return;
2881 }
ea5fc465 2882 $nhits = 0;
e673ee24
DO
2883 // If we search for L2 address, we can either find one or find none.
2884 if
2885 (
2886 preg_match ('/^[0-9a-f][0-9a-f]?:[0-9a-f][0-9a-f]?:[0-9a-f][0-9a-f]?:[0-9a-f][0-9a-f]?:[0-9a-f][0-9a-f]?:[0-9a-f][0-9a-f]?$/i', $terms) or
2887 preg_match ('/^[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]$/i', $terms) or
ea5fc465
DO
2888 preg_match ('/^[0-9a-f][0-9a-f][0-9a-f][0-9a-f].[0-9a-f][0-9a-f][0-9a-f][0-9a-f].[0-9a-f][0-9a-f][0-9a-f][0-9a-f]$/i', $terms) or
2889 // STP bridge ID: bridge priotity + port MAC address. Cut off first 4 chars and look for MAC address.
2890 preg_match ('/^[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]$/i', $terms)
e673ee24
DO
2891 )
2892 // Search for L2 address.
2893 {
3ec29bf4
DO
2894 $terms = str_replace ('.', '', $terms);
2895 $terms = str_replace (':', '', $terms);
ea5fc465 2896 $terms = substr ($terms, -12);
e673ee24
DO
2897 $result = searchByl2address ($terms);
2898 if ($result !== NULL)
2899 {
ea5fc465
DO
2900 $nhits++;
2901 $lasthit = 'port';
2902 $summary['port'][] = $result;
e673ee24 2903 }
e673ee24
DO
2904 }
2905 elseif (preg_match ('/^[0-9][0-9]?[0-9]?\.[0-9]?[0-9]?[0-9]?\.[0-9][0-9]?[0-9]?\.[0-9]?[0-9]?[0-9]?$/i', $terms))
2906 // Search for IP address.
2907 {
bb0a44e9 2908 if (NULL !== getIPv4AddressNetworkId ($terms))
e673ee24 2909 {
ea5fc465 2910 $nhits++;
f3d0cb20
DO
2911 $lasthit = 'ipv4addressbydq';
2912 $summary['ipv4addressbydq'][] = $terms;
e673ee24 2913 }
e673ee24
DO
2914 }
2915 else
ea5fc465 2916 // Search for objects, addresses, networks, virtual services and RS pools by their description.
e673ee24 2917 {
ea5fc465
DO
2918 $tmp = getObjectSearchResults ($terms);
2919 if (count ($tmp))
e673ee24 2920 {
ea5fc465
DO
2921 $nhits += count ($tmp);
2922 $lasthit = 'object';
2923 $summary['object'] = $tmp;
e673ee24 2924 }
ea5fc465
DO
2925 $tmp = getIPv4AddressSearchResult ($terms);
2926 if (count ($tmp))
e673ee24 2927 {
ea5fc465 2928 $nhits += count ($tmp);
f3d0cb20
DO
2929 $lasthit = 'ipv4addressbydescr';
2930 $summary['ipv4addressbydescr'] = $tmp;
ea5fc465
DO
2931 }
2932 $tmp = getIPv4PrefixSearchResult ($terms);
2933 if (count ($tmp))
2934 {
2935 $nhits += count ($tmp);
2936 $lasthit = 'ipv4network';
2937 $summary['ipv4network'] = $tmp;
2938 }
05411ccd
DO
2939 $tmp = getIPv4RSPoolSearchResult ($terms);
2940 if (count ($tmp))
2941 {
2942 $nhits += count ($tmp);
2943 $lasthit = 'ipv4rspool';
2944 $summary['ipv4rspool'] = $tmp;
2945 }
2946 $tmp = getIPv4VServiceSearchResult ($terms);
2947 if (count ($tmp))
2948 {
2949 $nhits += count ($tmp);
2950 $lasthit = 'ipv4vs';
2951 $summary['ipv4vs'] = $tmp;
2952 }
6a88e734
DO
2953 $tmp = getAccountSearchResult ($terms);
2954 if (count ($tmp))
2955 {
2956 $nhits += count ($tmp);
2957 $lasthit = 'user';
2958 $summary['user'] = $tmp;
2959 }
ea5fc465
DO
2960 }
2961 if ($nhits == 0)
2962 echo "<center><h2>Nothing found for '${terms}'</h2></center>";
2963 elseif ($nhits == 1)
2964 {
2965 $record = current ($summary[$lasthit]);
2966 switch ($lasthit)
2967 {
2968 case 'port':
2969 echo "<script language='Javascript'>document.location='${root}?page=object";
2970 echo "&hl_port_id=" . $record['port_id'];
2971 echo "&object_id=" . $record['object_id'] . "';//</script>";
2972 break;
f3d0cb20
DO
2973 case 'ipv4addressbydq':
2974 $parentnet = getIPv4AddressNetworkId ($record);
2975 if ($parentnet !== NULL)
79a9edb4 2976 echo "<script language='Javascript'>document.location='${root}?page=iprange&tab=default&id=${parentnet}&hl_ipv4_addr=${record}';//</script>";
f3d0cb20
DO
2977 else
2978 echo "<script language='Javascript'>document.location='${root}?page=ipaddress&ip=${record}';//</script>";
ea5fc465 2979 break;
f3d0cb20
DO
2980 case 'ipv4addressbydescr':
2981 $parentnet = getIPv4AddressNetworkId ($record['ip']);
2982 if ($parentnet !== NULL)
79a9edb4 2983 echo "<script language='Javascript'>document.location='${root}?page=iprange&tab=default&id=${parentnet}&hl_ipv4_addr=${record['ip']}';//</script>";
f3d0cb20
DO
2984 else
2985 echo "<script language='Javascript'>document.location='${root}?page=ipaddress&ip=${record['ip']}';//</script>";
ea5fc465
DO
2986 break;
2987 case 'ipv4network':
2988 echo "<script language='Javascript'>document.location='${root}?page=iprange";
2989 echo "&id=${record['id']}";
2990 echo "';//</script>";
2991 break;
2992 case 'object':
2993 echo "<script language='Javascript'>document.location='${root}?page=object&object_id=${record['id']}';//</script>";
2994 break;
05411ccd 2995 case 'ipv4rspool':
0e692350 2996 echo "<script language='Javascript'>document.location='${root}?page=ipv4rsp&pool_id=${record['pool_id']}';//</script>";
05411ccd
DO
2997 break;
2998 case 'ipv4vs':
49fb2686 2999 echo "<script language='Javascript'>document.location='${root}?page=ipv4vs&vs_id=${record['id']}';//</script>";
05411ccd 3000 break;
6a88e734
DO
3001 case 'user':
3002 echo "<script language='Javascript'>document.location='${root}?page=user&user_id=${record['user_id']}';//</script>";
3003 break;
ea5fc465
DO
3004 }
3005 return;
3006 }
3007 else
3008 {
3009 global $nextorder;
3010 $order = 'odd';
3011 echo "<center><h2>${nhits} result(s) found for '${terms}'</h2></center>";
3012 foreach ($summary as $where => $what)
3013 switch ($where)
e673ee24 3014 {
ea5fc465 3015 case 'object':
06adfe89 3016 startPortlet ("<a href='${root}?page=objects'>Objects</a>");
ea5fc465
DO
3017 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
3018 echo '<tr><th>Common name</th><th>Visible label</th><th>Asset tag</th><th>barcode</th></tr>';
3019 foreach ($what as $obj)
3020 {
3021 echo "<tr class=row_${order}><td><a href=\"${root}?page=object&object_id=${obj['id']}\">${obj['dname']}</a></td>";
3022 echo "<td>${obj['label']}</td>";
3023 echo "<td>${obj['asset_no']}</td>";
3024 echo "<td>${obj['barcode']}</td></tr>";
3025 $order = $nextorder[$order];
3026 }
3027 echo '</table>';
3028 finishPortlet();
3029 break;
3030 case 'ipv4network':
06adfe89 3031 startPortlet ("<a href='${root}?page=ipv4space'>IPv4 networks</a>");
ea5fc465 3032 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
3c41194e 3033 echo '<tr><th>network</th><th>name/tags</th></tr>';
71287f1c 3034 foreach ($what as $netinfo)
ea5fc465 3035 {
71287f1c
DO
3036 echo "<tr class=row_${order} valign=top>";
3037 printIPv4NetInfoTDs ($netinfo);
3038 echo "</tr>\n";
ea5fc465
DO
3039 $order = $nextorder[$order];
3040 }
3041 echo '</table>';
3042 finishPortlet();
3043 break;
f3d0cb20 3044 case 'ipv4addressbydescr':
ea5fc465
DO
3045 startPortlet ('IPv4 addresses');
3046 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
f3d0cb20 3047 // FIXME: address, parent network, routers (if extended view is enabled)
ea5fc465
DO
3048 echo '<tr><th>Address</th><th>Descritpion</th></tr>';
3049 foreach ($what as $addr)
3050 {
f3d0cb20
DO
3051 echo "<tr class=row_${order}><td class=tdleft>";
3052 $parentnet = getIPv4AddressNetworkId ($addr['ip']);
3053 if ($parentnet !== NULL)
3054 echo "<a href='${root}?page=iprange&id=${parentnet}&hl_ipv4_addr=${addr['ip']}'>${addr['ip']}</a></td>";
3055 else
3056 echo "<a href='${root}?page=ipaddress&ip=${addr['ip']}'>${addr['ip']}</a></td>";
ea5fc465
DO
3057 echo "<td class=tdleft>${addr['name']}</td></tr>";
3058 $order = $nextorder[$order];
3059 }
3060 echo '</table>';
3061 finishPortlet();
3062 break;
05411ccd 3063 case 'ipv4rspool':
ee437dab 3064 startPortlet ("<a href='${root}?page=ipv4rsplist'>RS pools</a>");
05411ccd
DO
3065 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
3066 foreach ($what as $rspool)
3067 {
0e692350 3068 echo "<tr class=row_${order}><td class=tdleft><a href='${root}?page=ipv4rsp&pool_id=${rspool['pool_id']}'>";
05411ccd
DO
3069 echo buildRSPoolName ($rspool);
3070 echo "</a></td></tr>";
3071 $order = $nextorder[$order];
3072 }
3073 echo '</table>';
3074 finishPortlet();
3075 break;
3076 case 'ipv4vs':
a239e016 3077 startPortlet ("<a href='${root}?page=ipv4vslist'>Virtual services</a>");
05411ccd
DO
3078 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
3079 echo '<tr><th>VS</th><th>Descritpion</th></tr>';
3080 foreach ($what as $vs)
3081 {
49fb2686 3082 echo "<tr class=row_${order}><td class=tdleft><a href='${root}?page=ipv4vs&vs_id=${vs['id']}'>";
05411ccd 3083 echo buildVServiceName ($vs);
6a88e734
DO
3084 echo "</a></td><td class=tdleft>${vs['name']}</td></tr>";
3085 $order = $nextorder[$order];
3086 }
3087 echo '</table>';
3088 finishPortlet();
3089 break;
3090 case 'user':
3091 startPortlet ("<a href='${root}?page=userlist'>Users</a>");
3092 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
3093 echo '<tr><th>username</th><th>realname</th></tr>';
3094 foreach ($what as $item)
3095 {
3096 echo "<tr class=row_${order}><td class=tdleft><a href='${root}?page=user&user_id=${item['user_id']}'>";
3097 echo $item['user_name'];
3098 echo "</a></td><td class=tdleft>${item['user_realname']}</td></tr>";
05411ccd
DO
3099 $order = $nextorder[$order];
3100 }
3101 echo '</table>';
3102 finishPortlet();
3103 break;
e673ee24 3104 }
e673ee24
DO
3105 }
3106}
3107
3108// This function prints a table of checkboxes to aid the user in toggling mount atoms
3109// from one state to another. The first argument is rack data as
3110// produced by getRackData(), the second is the value used for the 'unckecked' state
3111// and the third is the value used for 'checked' state.
3112// Usage contexts:
3113// for mounting an object: printAtomGrid ($data, 'F', 'T')
3114// for changing rack design: printAtomGrid ($data, 'A', 'F')
3115// for adding rack problem: printAtomGrid ($data, 'F', 'U')
3116// for adding object problem: printAtomGrid ($data, 'T', 'W')
3117
3118function renderAtomGrid ($data)
3119{
3120 $rack_id = $data['id'];
3121 for ($unit_no = $data['height']; $unit_no > 0; $unit_no--)
3122 {
3123 echo "<tr><th>${unit_no}</th>";
3124 for ($locidx = 0; $locidx < 3; $locidx++)
3125 {
3126 $state = $data[$unit_no][$locidx]['state'];
3127 echo "<td class=state_${state}";
3128 if (isset ($data[$unit_no][$locidx]['hl']))
3129 echo $data[$unit_no][$locidx]['hl'];
3130 echo ">";
3131 if (!($data[$unit_no][$locidx]['enabled'] === TRUE))
3132 echo '<input type=checkbox disabled>';
3133 else
3134 echo "<input type=checkbox" . $data[$unit_no][$locidx]['checked'] . " name=atom_${rack_id}_${unit_no}_${locidx}>";
3135 echo '</td>';
3136 }
3137 echo "</tr>\n";
3138 }
3139}
3140
59427701 3141function renderUserList ()
e673ee24 3142{
9048d42b 3143 global $nextorder, $accounts, $root, $pageno;
59427701
DO
3144 echo "<table border=0 class=objectview>\n";
3145 echo "<tr><td class=pcleft>";
e673ee24
DO
3146 startPortlet ('User accounts');
3147 echo "<table class=cooltable border=0 cellpadding=5 cellspacing=0 align=center>\n";
3148 echo "<tr><th class=tdleft>Username</th><th class=tdleft>Real name</th></tr>";
3149 $order = 'odd';
59427701 3150 $tagfilter = getTagFilter();
11c8e4be 3151 foreach (getUserAccounts ($tagfilter, getTFMode()) as $user)
e673ee24 3152 {
9048d42b
DO
3153 echo "<tr class=row_${order} valign=top><td class=tdleft><a href='${root}?page=user&user_id=${user['user_id']}'>";
3154 echo "${user['user_name']}</a>";
3155 $usertags = loadUserTags ($user['user_id']);
3156 if (count ($usertags))
3157 echo '<br><small>' . serializeTags ($usertags, "${root}?page=${pageno}&tab=default&") . '</small>';
3158 echo "</td><td class=tdleft>${user['user_realname']}</td></li>";
e673ee24
DO
3159 $order = $nextorder[$order];
3160 }
3161 echo '</table>';
3162 finishPortlet();
59427701
DO
3163 echo '</td><td class=pcright>';
3164 renderTagFilterPortlet ($tagfilter, 'user');
3165 echo "</td></tr></table>\n";
e673ee24
DO
3166}
3167
59427701 3168function renderUserListEditor ()
e673ee24
DO
3169{
3170 global $root, $pageno, $tabno, $accounts;
3171 startPortlet ('User accounts');
3172 showMessageOrError();
3173 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable>\n";
623457f8 3174 echo "<tr><th>status (click to change)</th><th>Username</th><th>Real name</th><th>Password</th><th>&nbsp;</th></tr>\n";
e673ee24
DO
3175 foreach ($accounts as $account)
3176 {
7056988c
DO
3177 printOpFormIntro ('updateUser', array ('user_id' => $account['user_id']));
3178 echo "<tr><td>";
e673ee24
DO
3179 if ($account['user_enabled'] == 'yes' && $account['user_id'] != 1)
3180 {
59427701 3181 echo "<a href='${root}process.php?op=disableUser&page=${pageno}&tab=${tabno}&user_id=${account['user_id']}'>";
e673ee24
DO
3182 printImageHREF ('blockuser', 'disable account');
3183 echo "</a>\n";
3184 }
3185 if ($account['user_enabled'] == 'no' && $account['user_id'] != 1)
3186 {
59427701 3187 echo "<a href='${root}process.php?op=enableUser&page=${pageno}&tab=${tabno}&user_id=${account['user_id']}'>";
e673ee24
DO
3188 printImageHREF ('unblockuser', 'enable account');
3189 echo "</a>\n";
3190 }
3191 // Otherwise skip icon.
3192 echo "</td>";
3193 echo "<td><input type=text name=username value='${account['user_name']}' size=16></td>";
3194 echo "<td><input type=text name=realname value='${account['user_realname']}' size=24></td>";
8e5763a7
DO
3195 echo "<td><input type=password name=password value='${account['user_password_hash']}' size=64></td><td>";
3196 printImageHREF ('save', 'Save changes', TRUE);
3197 echo "</td></form></tr>\n";
e673ee24 3198 }
7056988c 3199 printOpFormIntro ('createUser');
8e5763a7 3200 echo "<td>&nbsp;</td><td><input type=text size=16 name=username tabindex=100></td>\n";
e673ee24 3201 echo "<td><input type=text size=24 name=realname tabindex=101></td>";
8e5763a7
DO
3202 echo "<td><input type=password size=64 name=password tabindex=102></td><td>";
3203 printImageHREF ('create', 'Add new account', TRUE, 103);
3204 echo "</td></tr></form>";
e673ee24
DO
3205 echo "</table><br>\n";
3206 finishPortlet();
3207}
3208
17c32f4c
DO
3209function renderPortMapViewer ()
3210{
3211 renderPortMap (FALSE);
3212}
3213
3214function renderPortMapEditor ()
3215{
3216 renderPortMap (TRUE);
3217}
3218
e673ee24
DO
3219function renderPortMap ($editable = FALSE)
3220{
3221 global $nextorder, $root, $pageno, $tabno;
3222 showMessageOrError();
3223 startPortlet ("Port compatibility map");
3224 $ptlist = getPortTypes();
3225 $pclist = getPortCompat();
3226 $pctable = buildPortCompatMatrixFromList ($ptlist, $pclist);
3227 if ($editable)
7056988c 3228 printOpFormIntro ('save');
e673ee24
DO
3229 echo "<table class=cooltable border=0 cellpadding=5 cellspacing=0 align=center>\n";
3230 echo "<tr><th class=vert_th>&nbsp;</th>";
3231 foreach ($ptlist as $name2)
3232 echo "<th>to ${name2}</th>";
3233 echo "</tr>";
3234 // Make a copy to have an independent array pointer.
3235 $ptlistY = $ptlist;
3236 $order = 'odd';
3237 foreach ($ptlistY as $type1 => $name1)
3238 {
3239 echo "<tr class=row_${order}><th class=vert_th style='border-bottom: 0px;'>from $name1</th>";
3240 foreach ($ptlist as $type2 => $name2)
3241 {
92b38217 3242 echo '<td' . ($pctable[$type1][$type2] ? " class=portmap_highlight_$order" : '') . '>';
19acd465 3243 echo '<input type=checkbox' . ($editable ? " name=atom_${type1}_${type2}" : ' disabled');
e673ee24
DO
3244 echo ($pctable[$type1][$type2] ? ' checked' : '') . '></td>';
3245 }
3246 echo "</tr>\n";
3247 $order = $nextorder[$order];
3248 }
3249 echo '</table><br>';
3250 if ($editable)
3251 {
7056988c 3252 printImageHREF ('SAVE', 'Save changes', TRUE);
e673ee24
DO
3253 echo "</form>";
3254 }
3255 finishPortlet();
3256}
3257
3258function renderConfigMainpage ()
3259{
3260 global $pageno, $root;
3261 $children = getDirectChildPages ($pageno);
3262 echo '<ul>';
27ef67da
DO
3263 // FIXME: assume all config kids to have static titles at the moment,
3264 // but use some proper abstract function later.
e673ee24 3265 foreach ($children as $cpageno => $child)
27ef67da 3266 echo "<li><a href='${root}?page=${cpageno}'>" . $child['title'] . "</li>\n";
e673ee24
DO
3267 echo '';
3268 echo '</ul>';
3269}
3270
3271function renderRackPage ($rack_id)
3272{
3273 if ($rack_id == 0)
3274 {
7056988c 3275 showError ('Invalid argument', __FUNCTION__);
e673ee24
DO
3276 return;
3277 }
3278 if (($rackData = getRackData ($rack_id)) == NULL)
3279 {
591ff2c4 3280 showError ('getRackData() failed', __FUNCTION__);
e673ee24
DO
3281 return;
3282 }
3283 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0><tr>";
3284
3285 // Left column with information.
3286 echo "<td class=pcleft>";
254673dd 3287 renderRackInfoPortlet ($rackData);
e673ee24
DO
3288 echo '</td>';
3289
3290 // Right column with rendered rack.
3291 echo '<td>';
3292 startPortlet ('Rack diagram');
3293 renderRack ($rack_id);
3294 finishPortlet();
3295 echo '</td>';
3296
3297 echo '</tr></table>';
3298}
3299
3300function renderDictionary ()
3301{
3302 global $nextorder;
2dd59b15 3303 $dict = getDict (TRUE);
aa28ebdf 3304 echo "<br><table class=cooltable border=0 cellpadding=5 cellspacing=0 align=center>\n";
aa28ebdf
DO
3305 foreach ($dict as $chapter_no => $chapter)
3306 {
a22ec5b4 3307 $order = 'odd';
83d2fcca 3308 echo "<tr><th>Chapter</th><th>refs</th><th>Word</th></tr>\n";
aa28ebdf
DO
3309 $wc = count ($chapter['word']);
3310 echo "<tr class=row_${order}><td class=tdleft" . ($wc ? " rowspan = ${wc}" : '');
3311 echo "><div title='number=${chapter_no}'>${chapter['name']} (${wc} records)</div></td>";
3312 if (!$wc)
3313 echo "<td colspan=2>none</td>";
3314 else
e673ee24 3315 {
aa28ebdf
DO
3316 $chap_start = TRUE;
3317 foreach ($chapter['word'] as $key => $value)
3318 {
3319 if (!$chap_start)
3320 echo "<tr class=row_${order}>";
3321 else
3322 $chap_start = FALSE;
6bb8e41d
DO
3323 echo '<td>' . ($chapter['refcnt'][$key] ? $chapter['refcnt'][$key] : '&nbsp;') . '</td>';
3324 echo "<td><div title='key=${key}'>${value}</div></td></tr>\n";
aa28ebdf
DO
3325 $order = $nextorder[$order];
3326 }
e673ee24 3327 }
e673ee24 3328 }
2dd59b15 3329 echo "</table>\n<br>";
e673ee24
DO
3330}
3331
3332function renderDictionaryEditor ()
3333{
f632bd28 3334 global $root, $pageno, $tabno, $nextorder;
e673ee24 3335 $dict = getDict();
95d80773 3336 showMessageOrError();
f632bd28
DO
3337 echo "<br><table class=cooltable border=0 cellpadding=5 cellspacing=0 align=center>\n";
3338 foreach ($dict as $chapter_no => $chapter)
e673ee24 3339 {
f632bd28 3340 $order = 'odd';
b2f9fa84 3341 echo "<tr><th>Chapter</th><th>&nbsp;</th><th>Word</th><th>&nbsp;</th></tr>\n";
f632bd28
DO
3342 $wc = count ($chapter['word']);
3343 // One extra span for the new record per each chapter block.
3344 echo "<tr class=row_${order}><td class=tdleft" . ($wc ? ' rowspan = ' . ($wc + 1) : '');
3345 echo "><div title='number=${chapter_no}'>${chapter['name']} (${wc} records)</div></td>";
7056988c
DO
3346 printOpFormIntro ('add', array ('chapter_no' => $chapter['no']));
3347 echo "<td>";
3348 printImageHREF ('add', 'Add new', TRUE);
3349 echo "</td>";
f632bd28 3350 echo "<td class=tdright><input type=text name=dict_value size=32></td>";
7056988c 3351 echo "<td>&nbsp;</td>";
f632bd28 3352 echo '</tr></form>';
b2f9fa84 3353 $order = $nextorder[$order];
e673ee24
DO
3354 foreach ($chapter['word'] as $key => $value)
3355 {
7056988c 3356 printOpFormIntro ('upd', array ('chapter_no' => $chapter['no'], 'dict_key' => $key));
95d80773 3357 echo "<tr class=row_${order}><td>";
f632bd28
DO
3358 // Prevent deleting words currently used somewhere.
3359 if ($chapter['refcnt'][$key])
b2f9fa84 3360 printImageHREF ('nodelete', 'referenced ' . $chapter['refcnt'][$key] . ' time(s)');
f632bd28
DO
3361 else
3362</