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