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