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