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