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