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