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