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