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