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