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