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