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