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