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