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