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