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