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