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