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