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