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