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