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