4 * This file contains frontend functions for RackTables.
8 // Interface function's special.
9 $nextorder['odd'] = 'even';
10 $nextorder['even'] = 'odd';
13 function renderIndex ()
17 <table border
=0 cellpadding
=0 cellspacing
=0 width
='100%'>
20 <div style
='text-align: center; margin: 10px; '>
21 <table width
='100%' cellspacing
=0 cellpadding
=30 class=mainmenu border
=0>
24 <h1
><a href
='<?php echo $root; ?>?page=rackspace'>Rackspace
<br
>
25 <?php
printImageHREF ('rackspace'); ?
></a
></h1
>
28 <h1
><a href
='<?php echo $root; ?>?page=objects'>Objects
<br
>
29 <?php
printImageHREF ('objects'); ?
></a
></h1
>
32 <h1
><a href
='<?php echo $root; ?>?page=ipv4space'>IPv4 space
<br
>
33 <?php
printImageHREF ('ipv4space'); ?
></a
></h1
>
37 <table width
='100%' cellspacing
=0 cellpadding
=30 class=mainmenu border
=0>
40 <h1
><a href
='<?php echo $root; ?>?page=config'>Configuration
<br
>
41 <?php
printImageHREF ('config'); ?
></a
></h1
>
44 <h1
><a href
='<?php echo $root; ?>?page=reports'>Reports
<br
>
45 <?php
printImageHREF ('reports'); ?
></a
></h1
>
48 <h1
><a href
='<?php echo $root; ?>?page=ipv4slb'>IPv4 SLB
<br
>
49 <?php
printImageHREF ('ipv4slb'); ?
></a
></h1
>
60 function renderRackspace ()
62 $tagfilter = getTagFilter();
63 $tagfilter_str = getTagFilterStr ($tagfilter);
64 echo "<table class=objview border=0 width='100%'><tr><td class=pcleft>";
65 renderTagFilterPortlet ($tagfilter, 'rack');
66 echo '</td><td class=pcright>';
67 echo '<table border=0 cellpadding=10 cellpadding=1>';
68 // generate thumb gallery
69 $rackrowList = getRackspace ($tagfilter);
70 global $root, $nextorder;
71 $rackwidth = getRackImageWidth();
73 foreach ($rackrowList as $rackrow)
75 echo "<tr class=row_${order}><th class=tdleft>";
76 echo "<a href='${root}?page=row&row_id=${rackrow['row_id']}${tagfilter_str}'>";
77 echo "${rackrow['row_name']}</a></th>";
78 $rackList = getRacksForRow ($rackrow['row_id'], $tagfilter);
79 echo "<td><table border=0 cellspacing=5><tr>";
80 foreach ($rackList as $rack)
82 echo "<td align=center><a href='${root}?page=rack&rack_id=${rack['id']}'>";
83 echo "<img border=0 width=${rackwidth} height=";
84 echo getRackImageHeight ($rack['height']);
85 echo " title='${rack['height']} units'";
86 echo "src='render_image.php?img=minirack&rack_id=${rack['id']}'>";
87 echo "<br>${rack['name']}</a></td>";
89 echo "</tr></table></tr>\n";
90 $order = $nextorder[$order];
93 echo "</td></tr></table>\n";
96 function renderRow ($row_id = 0)
100 showError ('Invalid row_id', __FUNCTION__
);
103 if (($rowInfo = getRackRowInfo ($row_id)) == NULL)
105 showError ('getRackRowInfo() failed', __FUNCTION__
);
108 $tagfilter = getTagFilter();
109 $rackList = getRacksForRow ($row_id, $tagfilter);
110 // Main layout starts.
111 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
113 // Left portlet with row information.
114 echo "<tr><td class=pcleft>";
115 startPortlet ($rowInfo['name']);
116 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
117 echo "<tr><th width='50%' class=tdright>Racks:</th><td class=tdleft>${rowInfo['count']}</td></tr>\n";
118 echo "<tr><th width='50%' class=tdright>Units:</th><td class=tdleft>${rowInfo['sum']}</td></tr>\n";
119 echo "<tr><th width='50%' class=tdright>Utilization:</th><td class=tdleft>";
120 renderProgressBar (getRSUforRackRow ($rackList));
122 echo "</table><br>\n";
125 echo "</td><td class=pcright rowspan=2>";
127 global $root, $nextorder;
128 $rackwidth = getRackImageWidth() * getConfigVar ('ROW_SCALE');
130 startPortlet ('Racks');
131 echo "<table border=0 cellspacing=5 align='center'><tr>";
132 foreach ($rackList as $rack)
134 echo "<td align=center class=row_${order}><a href='${root}?page=rack&rack_id=${rack['id']}'>";
135 echo "<img border=0 width=${rackwidth} height=" . (getRackImageHeight ($rack['height']) * getConfigVar ('ROW_SCALE'));
136 echo " title='${rack['height']} units'";
137 echo "src='render_image.php?img=minirack&rack_id=${rack['id']}'>";
138 echo "<br>${rack['name']}</a></td>";
139 $order = $nextorder[$order];
141 echo "</tr></table>\n";
145 echo "<tr><td class=pcleft>";
146 renderTagFilterPortlet ($tagfilter, 'rack', 'row_id', $row_id);
147 echo "</td></tr></table>";
150 function showError ($info = '', $funcname = 'N/A')
153 echo "<div class=msg_error>An error has occured in function [${funcname}]. ";
155 echo 'No additional information is available.';
157 echo "Additional information:<br><p>\n<pre>\n${info}\n</pre></p>";
158 echo "Go back or try starting from <a href='${root}'>index page</a>.<br></div>\n";
161 // This function renders rack as HTML table.
162 function renderRack ($rack_id = 0, $hl_obj_id = 0)
166 showError ('Invalid rack_id', __FUNCTION__
);
169 if (($rackData = getRackData ($rack_id)) == NULL)
171 showError ('getRackData() failed', __FUNCTION__
);
174 global $root, $pageno, $tabno;
175 markAllSpans ($rackData);
177 highlightObject ($rackData, $hl_obj_id);
178 markupObjectProblems ($rackData);
179 $prev_id = getPrevIDforRack ($rackData['row_id'], $rack_id);
180 $next_id = getNextIDforRack ($rackData['row_id'], $rack_id);
181 echo "<center><table border=0><tr valign=middle>";
182 echo "<td><h2><a href='${root}?page=row&row_id=${rackData['row_id']}'>${rackData['row_name']}</a> :</h2></td>";
183 // FIXME: use 'bypass'?
184 if ($prev_id != NULL)
186 echo "<td><a href='${root}?page=rack&rack_id=${prev_id}'>";
187 printImageHREF ('prev', 'previous rack');
190 echo "<td><h2><a href='${root}?page=rack&rack_id=${rackData['id']}'>${rackData['name']}</a></h2></td>";
191 if ($next_id != NULL)
193 echo "<td><a href='${root}?page=rack&rack_id=${next_id}'>";
194 printImageHREF ('next', 'next rack');
197 echo "</h2></td></tr></table>\n";
198 if ($rackData['left_is_front'] == 'yes')
199 $markup = array ('left' => 'Front', 'right' => 'Back');
201 $markup = array ('left' => 'Back', 'right' => 'Front');
202 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
203 echo "<tr><th width='10%'> </th><th width='20%'>${markup['left']}</th>";
204 echo "<th width='50%'>Interior</th><th width='20%'>${markup['right']}</th></tr>\n";
205 for ($i = $rackData['height']; $i > 0; $i--)
207 echo '<tr><th>' . ($rackData['bottom_is_unit1'] == 'yes' ?
$i : $rackData['height'] - $i +
1) . '</th>';
208 for ($locidx = 0; $locidx < 3; $locidx++
)
210 if (isset ($rackData[$i][$locidx]['skipped']))
212 $state = $rackData[$i][$locidx]['state'];
213 echo "<td class=state_${state}";
214 if (isset ($rackData[$i][$locidx]['hl']))
215 echo $rackData[$i][$locidx]['hl'];
216 if (isset ($rackData[$i][$locidx]['colspan']))
217 echo ' colspan=' . $rackData[$i][$locidx]['colspan'];
218 if (isset ($rackData[$i][$locidx]['rowspan']))
219 echo ' rowspan=' . $rackData[$i][$locidx]['rowspan'];
224 $objectData = getObjectInfo ($rackData[$i][$locidx]['object_id']);
225 if (!empty ($objectData['asset_no']))
226 $prefix = "<div title='${objectData['asset_no']}";
228 $prefix = "<div title='no asset tag";
229 // Don't tell about label, if it matches common name.
230 if ($objectData['name'] != $objectData['label'] and !empty ($objectData['label']))
231 $suffix = ", visible label is \"${objectData['label']}\"'>";
234 echo $prefix . $suffix;
235 echo "<a href='${root}?page=object&object_id=${objectData['id']}'>${objectData['dname']}</a></div>";
238 echo '<div title="This rackspace does not exist"> </div>';
241 echo '<div title="Free rackspace"> </div>';
244 echo '<div title="Problematic rackspace, you CAN\'T mount here"> </div>';
247 echo '<div title="No data"> </div>';
254 echo "</table></center>\n";
257 function renderNewRackForm ($row_id)
259 global $pageno, $tabno;
261 $taglist = isset ($_REQUEST['taglist']) ?
$_REQUEST['taglist'] : array();
263 // Look for current submit.
264 if (isset ($_REQUEST['got_data']))
266 assertStringArg ('rack_name', __FUNCTION__
);
267 assertUIntArg ('rack_height1', __FUNCTION__
);
268 assertStringArg ('rack_comment', __FUNCTION__
, TRUE);
269 $name = $_REQUEST['rack_name'];
271 if (commitAddRack ($name, $_REQUEST['rack_height1'], $row_id, $_REQUEST['rack_comment'], $taglist) === TRUE)
272 $log[] = array ('code' => 'success', 'message' => "Added new rack '${name}'");
274 $log[] = array ('code' => 'error', 'message' => __FUNCTION__
. ': commitAddRack() failed');
276 elseif (isset ($_REQUEST['got_mdata']))
278 assertUIntArg ('rack_height2', __FUNCTION__
);
279 assertStringArg ('rack_names', __FUNCTION__
, TRUE);
280 // copy-and-paste from renderAddMultipleObjectsForm()
281 $names1 = explode ('\n', $_REQUEST['rack_names']);
283 foreach ($names1 as $line)
285 $parts = explode ('\r', $line);
287 if (empty ($parts[0]))
290 $names2[] = rtrim ($parts[0]);
292 foreach ($names2 as $cname)
293 if (commitAddRack ($cname, $_REQUEST['rack_height2'], $row_id, '', $taglist) === TRUE)
294 $log[] = array ('code' => 'success', 'message' => "Added new rack '${cname}'");
296 $log[] = array ('code' => 'error', 'message' => __FUNCTION__
. ': commitAddRack() failed');
300 echo "<table border=0 width='100%'><tr><td valign=top>";
301 // Render a form for the next.
302 startPortlet ('Add one');
304 echo "<input type=hidden name=page value=${pageno}>";
305 echo "<input type=hidden name=tab value=${tabno}>";
306 echo "<input type=hidden name=row_id value=${row_id}>";
307 echo '<table border=0 align=center>';
308 $defh = getConfigVar ('DEFAULT_RACK_HEIGHT');
311 echo "<tr><th class=tdright>Rack name (*):</th><td class=tdleft><input type=text name=rack_name tabindex=1></td></tr>\n";
312 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";
313 echo "<tr><th class=tdright>Comment:</th><td class=tdleft><input type=text name=rack_comment tabindex=3></td></tr>\n";
314 echo "<tr><td class=submit colspan=2><input type=submit name=got_data value='Add'></td></tr>\n";
319 echo '<td rowspan=2 valign=top>';
320 startPortlet ('Pre-assigned tags');
325 echo '<tr><td valign=top>';
326 startPortlet ('Add many');
327 echo '<table border=0 align=center>';
328 $defh = getConfigVar ('DEFAULT_RACK_HEIGHT');
331 echo "<tr><th class=tdright>Height in units (*):</th><td class=tdleft><input type=text name=rack_height2 value='${defh}'></td></tr>\n";
332 echo "<tr><th class=tdright>Rack names (*):</th><td class=tdleft><textarea name=rack_names cols=40 rows=25></textarea></td></tr>\n";
333 echo "<tr><td class=submit colspan=2><input type=submit name=got_mdata value='Add'></td></tr>\n";
334 echo '</form></table>';
340 function renderEditObjectForm ($object_id)
342 showMessageOrError();
344 global $pageno, $tabno, $root;
345 $object = getObjectInfo ($object_id);
348 showError ('getObjectInfo() failed', __FUNCTION__
);
351 echo '<table border=0 width=100%><tr>';
353 echo '<td class=pcleft>';
354 startPortlet ('Static attributes');
355 echo "<form method=post action='${root}process.php?page=${pageno}&tab=${tabno}&op=update'>";
356 echo "<input type=hidden name=object_id value=${object_id}>";
357 echo '<table border=0 align=center>';
358 echo "<tr><th class=tdright>Type:</th><td class=tdleft>";
359 printSelect (getObjectTypeList(), 'object_type_id', $object['objtype_id']);
362 echo "<tr><th class=tdright>Common name:</th><td class=tdleft><input type=text name=object_name value='${object['name']}'></td></tr>\n";
363 echo "<tr><th class=tdright>Visible label:</th><td class=tdleft><input type=text name=object_label value='${object['label']}'></td></tr>\n";
364 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";
365 echo "<tr><th class=tdright>Barcode:</th><td class=tdleft><input type=text name=object_barcode value='${object['barcode']}'></td></tr>\n";
366 echo "<tr><th class=tdright>Has problems:</th><td class=tdleft><input type=checkbox name=object_has_problems";
367 if ($object['has_problems'] == 'yes')
369 echo "></td></tr>\n";
370 echo "<tr><td colspan=2><b>Comment:</b><br><textarea name=object_comment rows=10 cols=80>${object['comment']}</textarea></td></tr>";
371 echo "<tr><th class=submit colspan=2>";
372 printImageHREF ('SAVE', 'Save changes', TRUE);
374 echo '</form></table><br>';
379 echo '<td class=pcright>';
380 startPortlet ('Optional attributes');
381 $values = getAttrValues ($object_id);
382 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable>\n";
383 echo "<tr><th> </th><th>Attribute</th><th>Value</th><th> </th></tr>\n";
384 echo "<form method=post action='${root}process.php?page=${pageno}&tab=${tabno}&op=updateStickers'>\n";
385 echo "<input type=hidden name=object_id value=${object_id}>\n";
386 echo '<input type=hidden name=num_attrs value=' . count($values) . ">\n";
389 foreach ($values as $record)
391 echo "<input type=hidden name=${i}_attr_id value=${record['id']}>";
393 if (!empty ($record['value']))
395 echo "<a href='${root}process.php?page=${pageno}&tab=${tabno}&op=clearSticker&object_id=${object_id}&attr_id=${record['id']}'>";
396 printImageHREF ('clear', 'Clear value');
402 echo "<td class=tdright>${record['name']}:</td><td class=tdleft>";
403 switch ($record['type'])
408 echo "<input type=text name=${i}_value value='${record['value']}'>";
411 $chapter = readChapter ($record['chapter_name']);
412 $chapter[0] = '-- NOT SET --';
413 printSelect ($chapter, "${i}_value", $record['key']);
419 echo "<tr><td colspan=3>";
420 printImageHREF ('SAVE', 'Save changes', TRUE);
429 echo '<td colspan=2>';
430 startPortlet ('history');
431 renderHistory ($pageno, $object_id);
435 echo '</tr></table>';
438 // This is a clone of renderEditObjectForm().
439 function renderEditRackForm ($rack_id)
442 if (isset ($_REQUEST['got_data']))
445 assertUIntArg ('rack_row_id', __FUNCTION__
);
446 assertUIntArg ('rack_height', __FUNCTION__
);
447 assertStringArg ('rack_name', __FUNCTION__
);
448 assertStringArg ('rack_comment', __FUNCTION__
, TRUE);
449 $row_id = $_REQUEST['rack_row_id'];
450 $height = $_REQUEST['rack_height'];
451 $name = $_REQUEST['rack_name'];
452 $comment = $_REQUEST['rack_comment'];
454 if (commitUpdateRack ($rack_id, $name, $height, $row_id, $comment) === TRUE)
455 $log[] = array ('code' => 'success', 'message' => "Updated rack '${name}'");
457 $log[] = array ('code' => 'error', 'message' => __FUNCTION__
. ': commitUpdateRack() failed');
458 resetThumbCache ($rack_id);
462 global $pageno, $tabno;
463 $rack = getRackData ($rack_id);
466 showError ('getRackData() failed', __FUNCTION__
);
470 // Render a form for the next.
471 startPortlet ('Rack attributes');
473 echo "<input type=hidden name=page value=${pageno}>";
474 echo "<input type=hidden name=tab value=${tabno}>";
475 echo "<input type=hidden name=rack_id value=${rack_id}>";
476 echo '<table border=0 align=center>';
477 echo "<tr><th class=tdright>Rack row:</th><td class=tdleft>";
478 printSelect (readChapter ('RackRow'), 'rack_row_id', $rack['row_id']);
480 echo "<tr><th class=tdright>Name (required):</th><td class=tdleft><input type=text name=rack_name value='${rack['name']}'></td></tr>\n";
481 echo "<tr><th class=tdright>Height (required):</th><td class=tdleft><input type=text name=rack_height value='${rack['height']}'></td></tr>\n";
482 echo "<tr><th class=tdright>Comment:</th><td class=tdleft><input type=text name=rack_comment value='${rack['comment']}'></td></tr>\n";
483 echo "<tr><td class=submit colspan=2><input type=submit name=got_data value='Update'></td></tr>\n";
484 echo '</form></table><br>';
487 startPortlet ('History');
488 renderHistory ($pageno, $rack_id);
492 // This is a helper for creators and editors.
493 function printSelect ($rowList, $select_name, $selected_id = 1)
495 // First collect all data for OPTGROUPs, then ouput it and dump
496 // the rest of records as is.
499 foreach ($rowList as $dict_key => $dict_value)
501 if (strpos ($dict_value, '%GSKIP%') !== FALSE)
503 $tmp = explode ('%GSKIP%', $dict_value, 2);
504 $optgroup[$tmp[0]][$dict_key] = $tmp[1];
506 elseif (strpos ($dict_value, '%GPASS%') !== FALSE)
508 $tmp = explode ('%GPASS%', $dict_value, 2);
509 $optgroup[$tmp[0]][$dict_key] = $tmp[1];
512 $other[$dict_key] = $dict_value;
514 echo "<select name=${select_name}>";
515 if (!count ($optgroup))
517 foreach ($other as $dict_key => $dict_value)
519 echo "<option value=${dict_key}";
520 if ($dict_key == $selected_id)
522 echo ">${dict_value}</option>";
527 foreach ($optgroup as $groupname => $groupdata)
529 echo "<optgroup label='${groupname}'>";
530 foreach ($groupdata as $dict_key => $dict_value)
532 echo "<option value=${dict_key}";
533 if ($dict_key == $selected_id)
535 echo ">${dict_value}</option>";
537 echo "</optgroup>\n";
541 echo "<optgroup label='other'>\n";
542 foreach ($other as $dict_key => $dict_value)
544 echo "<option value=${dict_key}";
545 if ($dict_key == $selected_id)
547 echo ">${dict_value}</option>";
549 echo "</optgroup>\n";
555 // used by renderGridForm() and renderRackPage()
556 function renderRackInfoPortlet ($rackData)
559 startPortlet ('summary');
560 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
561 echo "<tr><th width='50%' class=tdright>Rack row:</th><td class=tdleft>${rackData['row_name']}</td></tr>\n";
562 echo "<tr><th width='50%' class=tdright>Name:</th><td class=tdleft>${rackData['name']}</td></tr>\n";
563 echo "<tr><th width='50%' class=tdright>Height:</th><td class=tdleft>${rackData['height']}</td></tr>\n";
564 echo "<tr><th width='50%' class=tdright>Utilization:</th><td class=tdleft>";
565 renderProgressBar (getRSUforRack ($rackData));
567 echo "<tr><th width='50%' class=tdright>Objects:</th><td class=tdleft>";
568 echo getObjectCount ($rackData);
570 printTagTRs ("${root}?page=rackspace&");
571 if (!empty ($rackData['comment']))
572 echo "<tr><th width='50%' class=tdright>Comment:</th><td class=tdleft>${rackData['comment']}</td></tr>\n";
577 // This is a universal editor of rack design/waste.
578 function renderGridForm ($rack_id = 0, $filter, $header, $submit, $state1, $state2)
582 showError ('Invalid rack_id', __FUNCTION__
);
585 if (($rackData = getRackData ($rack_id)) == NULL)
587 showError ('getRackData() failed', __FUNCTION__
);
591 global $root, $pageno, $tabno;
593 markupObjectProblems ($rackData);
595 // Process form submit.
596 if (isset ($_REQUEST['do_update']))
598 $log[] = processGridForm ($rackData, $state1, $state2);
600 $rackData = getRackData ($rack_id);
602 markupObjectProblems ($rackData);
605 // Render the result whatever it is.
607 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
608 echo "<tr><td colspan=2 align=center><h1>${rackData['name']}</h1></td></tr>\n";
610 // Left column with information portlet.
611 echo "<tr><td class=pcleft height='1%' width='50%'>";
612 renderRackInfoPortlet ($rackData);
614 echo "<td class=pcright>";
617 startPortlet ($header);
619 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
620 echo "<tr><th width='10%'> </th><th width='20%'>Front</th>";
621 echo "<th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
622 echo "<form method=post action='${root}?'>\n";
623 echo "<input type=hidden name=page value=${pageno}>\n";
624 echo "<input type=hidden name=tab value=${tabno}>\n";
625 echo "<input type=hidden name=rack_id value=${rack_id}>\n";
626 markupAtomGrid ($rackData, $state2);
627 renderAtomGrid ($rackData);
628 echo "</table></center>\n";
629 echo "<br><input type=submit name=do_update value='${submit}'></form><br><br>\n";
631 echo "</td></tr></table>\n";
634 function renderRackDesign ($rack_id)
636 renderGridForm ($rack_id, 'applyRackDesignMask', 'Rack design', 'Set rack design', 'A', 'F');
639 function renderRackProblems ($rack_id = 0)
641 renderGridForm ($rack_id, 'applyRackProblemMask', 'Rack problems', 'Mark unusable atoms', 'F', 'U');
644 function startPortlet ($title = '')
646 echo "<div class=portlet><h2>${title}</h2>";
649 function finishPortlet ()
654 function printRefsOfType ($refs, $type, $eq)
658 foreach ($refs as $ref)
660 if ($eq($ref['type'], $type))
662 if ($gotone) echo ', ';
663 echo "<a href='${root}?page=object&object_id=${ref['object_id']}'>";
664 if (!empty ($ref['name']))
665 echo $ref['name'] . '@';
666 echo "${ref['object_name']}</a>";
672 function renderRackObject ($object_id = 0)
674 global $root, $nextorder;
677 showError ('Invalid object_id', __FUNCTION__
);
680 $info = getObjectInfo ($object_id);
683 showError ('getObjectInfo() failed', __FUNCTION__
);
686 // Main layout starts.
687 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
688 echo "<tr><td colspan=2 align=center><h1>${info['dname']}</h1></td></tr>\n";
689 // left column with uknown number of portlets
690 echo "<tr><td class=pcleft>";
691 startPortlet ('Object information');
692 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
693 if (!empty ($info['name']))
694 echo "<tr><th width='50%' class=tdright>Common name:</th><td class=tdleft>${info['name']}</td></tr>\n";
695 elseif (in_array ($info['objtype_id'], explode (',', getConfigVar ('NAMEFUL_OBJTYPES'))))
696 echo "<tr><td colspan=2 class=msg_error>Common name is missing.</td></tr>\n";
697 echo "<tr><th width='50%' class=tdright>Object type:</th>";
698 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";
699 if (!empty ($info['asset_no']))
700 echo "<tr><th width='50%' class=tdright>Asset tag:</th><td class=tdleft>${info['asset_no']}</td></tr>\n";
701 elseif (in_array ($info['objtype_id'], explode (',', getConfigVar ('REQUIRE_ASSET_TAG_FOR'))))
702 echo "<tr><td colspan=2 class=msg_error>Asset tag is missing.</td></tr>\n";
703 if (!empty ($info['label']))
704 echo "<tr><th width='50%' class=tdright>Visible label:</th><td class=tdleft>${info['label']}</td></tr>\n";
705 if (!empty ($info['barcode']))
706 echo "<tr><th width='50%' class=tdright>Barcode:</th><td class=tdleft>${info['barcode']}</td></tr>\n";
707 if ($info['has_problems'] == 'yes')
708 echo "<tr><td colspan=2 class=msg_error>Has problems</td></tr>\n";
709 foreach (getAttrValues ($object_id, TRUE) as $record)
710 if (!empty ($record['value']))
711 echo "<tr><th width='50%' class=opt_attr_th>${record['name']}:</th><td class=tdleft>${record['a_value']}</td></tr>\n";
712 printTagTRs ("${root}?page=objgroup&group_id=${info['objtype_id']}&");
713 echo "</table><br>\n";
716 if (!empty ($info['comment']))
718 startPortlet ('Comment');
719 echo '<div class=commentblock>' . string_insert_hrefs ($info['comment']) . '</div>';
723 $ports = getObjectPortsAndLinks ($object_id);
726 startPortlet ('Ports and links');
727 usort($ports, 'sortByName');
731 if (isset ($_REQUEST['hl_port_id']))
733 assertUIntArg ('hl_port_id', __FUNCTION__
);
734 $hl_port_id = $_REQUEST['hl_port_id'];
736 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
737 echo "<tr><th>Local name</th><th>Visible label</th><th>Port type</th><th>L2 address</th>";
738 echo "<th>Rem. Object</th><th>Rem. port</th></tr>\n";
739 foreach ($ports as $port)
742 if ($hl_port_id == $port['id'])
743 echo ' class=port_highlight';
744 echo "><td>${port['name']}</td><td>${port['label']}</td><td>${port['type']}</td>";
745 echo "<td>${port['l2address']}</td>";
746 if ($port['remote_object_id'])
748 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>";
749 echo "<td>${port['remote_name']}</td>";
751 elseif (!empty ($port['reservation_comment']))
753 echo "<td><b>Reserved;</b></td>";
754 echo "<td>${port['reservation_comment']}</td>";
757 echo '<td> </td><td> </td>';
760 echo "</table><br>\n";
764 $addresses = getObjectAddresses ($object_id);
765 usort($addresses, 'sortAddresses');
766 if (count ($addresses))
768 startPortlet ('IPv4 addresses');
769 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
770 echo "<tr><th>OS interface</th><th>IP address</th><th>description</th><th>misc</th></tr>\n";
772 if (isset ($_REQUEST['hl_ipv4_addr']))
774 assertIPv4Arg ('hl_ipv4_addr', __FUNCTION__
);
775 $hl_ipv4_addr = $_REQUEST['hl_ipv4_addr'];
777 foreach ($addresses as $addr)
779 if (strlen($addr['address_name'])>40)
780 $address_name = substr($addr['address_name'],0,38).'...';
782 $address_name = $addr['address_name'];
784 $virtnum = countRefsOfType($addr['references'], 'virtual', 'eq');
785 $sharednum = countRefsOfType($addr['references'], 'shared', 'eq');
786 $regnum = countRefsOfType($addr['references'], 'regular', 'eq');
787 $notvirtnum = countRefsOfType($addr['references'], 'virtual', 'neq');
790 if ($addr['address_reserved']=='yes')
791 echo ' class=trerror';
792 elseif ($addr['type']!='virtual' && $regnum>0)
793 echo ' class=trerror';
794 elseif ($addr['type']=='regular' && $sharednum>0)
795 echo ' class=trerror';
797 if ($hl_ipv4_addr == $addr['ip'])
798 echo ' class=port_highlight';
799 echo "><td class=tdleft>${addr['name']}</td><td class=tdleft>";
800 echo "<a href='${root}?page=ipaddress&ip=${addr['ip']}&hl_object_id=${object_id}'>";
801 echo "${addr['ip']}</a></td><td class='description'>$address_name</td><td class=tdleft>\n";
803 if ($addr['address_reserved']=='yes')
804 echo "<b>Reserved;</b> ";
806 if ($addr['type'] == 'virtual')
812 printRefsOfType($addr['references'], 'virtual', 'neq');
815 elseif ($addr['type'] == 'shared')
821 printRefsOfType($addr['references'], 'shared', 'eq');
827 printRefsOfType($addr['references'], 'virtual', 'eq');
832 echo " Collisions: ";
833 printRefsOfType($addr['references'], 'regular', 'eq');
842 printRefsOfType($addr['references'], 'virtual', 'eq');
847 echo " Collisions: ";
848 printRefsOfType($addr['references'], 'virtual', 'neq');
854 echo "</table><br>\n";
858 $forwards = getNATv4ForObject ($object_id);
859 if (count($forwards['in']) or count($forwards['out']))
861 startPortlet('NATv4');
863 if (count($forwards['out']))
866 echo "<h3>locally performed NAT</h3>";
868 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
869 echo "<tr><th>Proto</th><th>Match endpoint</th><th>Translate to</th><th>Target object</th><th>Rule comment</th></tr>\n";
871 foreach ($forwards['out'] as $pf)
875 foreach ($addresses as $addr)
876 if ($addr['ip'] == $pf['localip'])
883 echo "<tr class='$class'>";
885 echo "<td>${pf['proto']}</td><td class=tdleft>${name}: <a href='${root}?page=ipaddress&tab=default&ip=${pf['localip']}'>${pf['localip']}</a>:${pf['localport']}</td>";
887 echo "<td class=tdleft><a href='${root}?page=ipaddress&tab=default&ip=${pf['remoteip']}'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
889 $address=getIPAddress($pf['remoteip']);
891 echo "<td class='description'>";
892 if (count ($address['bonds']))
893 foreach($address['bonds'] as $bond)
894 echo "<a href='${root}?page=object&tab=default&object_id=${bond['object_id']}'>${bond['object_name']}(${bond['name']})</a> ";
895 elseif (!empty ($pf['remote_addr_name']))
896 echo '(' . $pf['remote_addr_name'] . ')';
898 echo "</td><td class='description'>${pf['description']}</td>";
902 echo "</table><br><br>";
904 if (count($forwards['in']))
906 echo "<h3>arriving NAT connections</h3>";
908 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
909 echo "<tr><th>Matched endpoint</th><th>Source object</th><th>Translated to</th><th>Rule comment</th></tr>\n";
911 foreach ($forwards['in'] as $pf)
914 echo "<td>${pf['proto']}/<a href='${root}?page=ipaddress&tab=default&ip=${pf['localip']}'>${pf['localip']}</a>:${pf['localport']}</td>";
916 echo "<td class='description'><a href='${root}?page=object&tab=default&object_id=${pf['object_id']}'>${pf['object_name']}</a>";
918 echo "</td><td><a href='${root}?page=ipaddress&tab=default&ip=${pf['remoteip']}'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
919 echo "<td class='description'>${pf['description']}</td></tr>";
922 echo "</table><br><br>";
927 $pools = getRSPoolsForObject ($object_id);
931 startPortlet ('Real server pools');
932 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable>\n";
933 echo "<tr><th>VS</th><th>RS pool</th><th>RS</th><th>VS config</th><th>RS config</th></tr>\n";
934 foreach ($pools as $vs_id => $info)
936 echo "<tr valign=top class=row_${order}><td class=tdleft><a href='${root}?page=ipv4vs&vs_id=${vs_id}'>";
937 echo buildVServiceName ($info);
939 if (!empty ($info['name']))
940 echo "<br>${info['name']}";
941 echo "</td><td class=tdleft><a href='${root}?page=ipv4rsp&pool_id=${info['pool_id']}'>";
942 echo (empty ($info['pool_name']) ?
'ANONYMOUS' : $info['pool_name']);
943 echo '</a></td><td class=tdleft>' . $info['rscount'] . '</td>';
944 echo "<td class=tdleft><pre>${info['vsconfig']}</pre></td>";
945 echo "<td class=tdleft><pre>${info['rsconfig']}</pre></td>";
947 $order = $nextorder[$order];
954 // After left column we have (surprise!) right column with rackspace portled only.
955 echo "<td class=pcright>";
957 startPortlet ('Rackspace allocation');
958 // FIXME: now we call getRackData() twice
959 $racks = getResidentRacksData ($object_id);
960 foreach ($racks as $rackData)
961 renderRack ($rackData['id'], $object_id);
968 function renderRackMultiSelect ($sname, $racks, $selected)
970 // Transform the given flat list into a list of groups, each representing a rack row.
972 foreach ($racks as $rack)
973 if (!isset ($rdata[$rack['row_name']]))
974 $rdata[$rack['row_name']] = array ($rack['id'] => $rack['name']);
976 $rdata[$rack['row_name']][$rack['id']] = $rack['name'];
977 echo "<select name=${sname} multiple size=" . getConfigVar ('MAXSELSIZE') . " onchange='getElementById(\"racks\").submit()'>\n";
978 foreach ($rdata as $optgroup => $racklist)
980 echo "<optgroup label='${optgroup}'>";
981 foreach ($racklist as $rack_id => $rack_name)
983 echo "<option value=${rack_id}";
984 if (!(array_search ($rack_id, $selected) === FALSE))
986 echo">${rack_name}</option>\n";
992 function showMessageOrError ()
994 if (isset ($_REQUEST['message']))
995 echo "<div class=msg_success>${_REQUEST['message']}</div>";
996 elseif (isset ($_REQUEST['error']))
997 echo "<div class=msg_error>${_REQUEST['error']}</div>";
998 elseif (isset ($_REQUEST['log']))
999 printLog (unserialize (base64_decode ($_REQUEST['log'])));
1002 // This function renders a form for port edition.
1003 function renderPortsForObject ($object_id = 0)
1005 global $root, $pageno, $tabno;
1006 if ($object_id <= 0)
1008 showError ('Invalid object_id', __FUNCTION__
);
1011 showMessageOrError();
1012 startPortlet ('Ports and interfaces');
1013 $ports = getObjectPortsAndLinks ($object_id);
1014 usort($ports, 'sortByName');
1015 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
1016 echo "<tr><th> </th><th>Local name</th><th>Visible label</th><th>Port type</th><th>L2 address</th>";
1017 echo "<th>Rem. object</th><th>Rem. port</th><th>(Un)link or (un)reserve</th><th> </th></tr>\n";
1018 foreach ($ports as $port)
1020 echo "<form action='${root}process.php'>";
1021 echo "<input type=hidden name=op value=editPort>";
1022 echo "<input type=hidden name=page value='${pageno}'>\n";
1023 echo "<input type=hidden name=tab value='${tabno}'>\n";
1024 echo "<input type=hidden name=port_id value='${port['id']}'>";
1025 echo "<input type=hidden name=object_id value='$object_id'>\n";
1026 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']}'>";
1027 printImageHREF ('delete', 'Unlink and Delete this port');
1029 echo "<td><input type=text name=name value='${port['name']}' size=8></td>";
1030 echo "<td><input type=text name=label value='${port['label']}' size=24></td>";
1031 echo "<td>${port['type']}</td>\n";
1032 echo "<td><input type=text name=l2address value='${port['l2address']}'></td>\n";
1033 if ($port['remote_object_id'])
1035 echo "<td><a href='${root}?page=object&object_id=${port['remote_object_id']}'>${port['remote_object_name']}</a></td>";
1036 echo "<td>${port['remote_name']}</td>";
1037 echo "<td><a href='${root}process.php?op=unlinkPort&page=${pageno}&tab=${tabno}&port_id=${port['id']}&object_id=$object_id&port_name=";
1038 echo urlencode ($port['name']);
1039 echo "&remote_port_name=${port['remote_name']}&remote_object_name=${port['remote_object_name']}'>";
1040 printImageHREF ('unlink', 'Unlink this port');
1043 elseif (!empty ($port['reservation_comment']))
1045 echo "<td><b>Reserved;</b></td>";
1046 echo "<td><input type=text name=reservation_comment value='${port['reservation_comment']}'></td>";
1047 echo "<td><a href='${root}process.php?op=useup&page=${pageno}&tab=${tabno}&port_id=${port['id']}&object_id=${object_id}'>";
1048 printImageHREF ('useup', 'Use up this port');
1053 echo "<td> </td><td> </td>";
1055 echo "<a href='javascript:;' onclick='window.open(\"${root}link_helper.php?port=${port['id']}&type=${port['type_id']}&object_id=$object_id&port_name=";
1056 echo urlencode ($port['name']);
1057 echo "\",\"findlink\",\"height=700, width=400, location=no, menubar=no, resizable=yes, scrollbars=no, status=no, titlebar=no, toolbar=no\");'>";
1058 printImageHREF ('link', 'Link this port');
1059 echo "</a> <input type=text name=reservation_comment>";
1063 printImageHREF ('save', 'Save changes', TRUE);
1064 echo "</td></form></tr>\n";
1066 echo "<form action='${root}process.php'><tr><td>";
1067 printImageHREF ('add', '', TRUE, 104);
1068 echo "</td><td><input type=text size=8 name=port_name tabindex=100></td>\n";
1069 echo "<td><input type=text size=24 name=port_label tabindex=101></td>";
1070 echo "<input type=hidden name=op value=addPort>\n";
1071 echo "<input type=hidden name=object_id value='${object_id}'>\n";
1072 echo "<input type=hidden name=page value='${pageno}'>\n";
1073 echo "<input type=hidden name=tab value='${tabno}'>\n";
1074 echo "<td><select name='port_type_id' tabindex=102>\n";
1075 $types = getPortTypes();
1076 $default_port_type = getConfigVar ('default_port_type');
1077 foreach ($types as $typeid => $typename)
1079 echo "<option value='${typeid}'";
1080 if ($typeid == $default_port_type)
1082 echo ">${typename}</option>\n";
1084 echo "</select></td>";
1085 echo "<td><input type=text name=port_l2address tabindex=103></td>\n";
1086 echo "<td colspan=4> </td></tr></form>";
1087 echo "</table><br>\n";
1090 startPortlet ('Add/update multiple ports');
1091 echo "<form action=${root}process.php method=post>";
1092 echo "<input type=hidden name=page value='${pageno}'>\n";
1093 echo "<input type=hidden name=tab value='${tabno}'>\n";
1094 echo "<input type=hidden name=object_id value='${object_id}'>\n";
1095 echo "<input type=hidden name=op value=addMultiPorts>";
1096 echo 'Format: <select name=format>';
1097 echo '<option value=c3600asy>Cisco 3600 async: sh line | inc TTY</option>';
1098 echo '<option value=fiwg selected>Foundry ServerIron/FastIron WorkGroup/Edge: sh int br</option>';
1099 echo '<option value=fisxii>Foundry FastIron SuperX/II4000: sh int br</option>';
1100 echo '<option value=ssv1>SSV:<interface name> <MAC address></option>';
1102 echo 'Default port type: ';
1103 echo "<select name=port_type>\n";
1104 foreach ($types as $typeid => $typename)
1106 echo "<option value='${typeid}'";
1107 if ($typeid == $default_port_type)
1109 echo ">${typename}</option>\n";
1112 echo "<input type=submit value='Parse output'><br>\n";
1113 echo "<textarea name=input cols=100 rows=50></textarea><br>\n";
1118 function renderIPv4ForObject ($object_id = 0)
1120 global $root, $pageno, $tabno;
1121 if ($object_id <= 0)
1123 showError ('Invalid object_id', __FUNCTION__
);
1126 showMessageOrError();
1127 startPortlet ('Allocations');
1128 $addresses = getObjectAddresses ($object_id);
1129 usort($addresses, 'sortAddresses');
1130 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
1131 echo "<tr><th> </th><th>OS interface</th><th>IP address</th><th>description</th><th>type</th><th>misc</th><th> </th></tr>\n";
1132 foreach ($addresses as $addr)
1134 if (strlen($addr['address_name'])>40)
1135 $address_name = substr($addr['address_name'],0,38).'...';
1137 $address_name = $addr['address_name'];
1139 $virtnum = countRefsOfType($addr['references'], 'virtual', 'eq');
1140 $sharednum = countRefsOfType($addr['references'], 'shared', 'eq');
1141 $regnum = countRefsOfType($addr['references'], 'regular', 'eq');
1142 $notvirtnum = countRefsOfType($addr['references'], 'virtual', 'neq');
1144 if ($addr['address_reserved']=='yes')
1146 elseif ($addr['type']!='virtual' && $regnum>0)
1148 elseif ($addr['type']=='regular' && $sharednum>0)
1153 echo "<form action='${root}process.php'>";
1154 echo "<input type=hidden name=page value='${pageno}'>\n";
1155 echo "<input type=hidden name=tab value='${tabno}'>\n";
1156 echo "<input type=hidden name=op value=updIPv4Allocation>";
1157 echo "<input type=hidden name=object_id value='$object_id'>";
1158 echo "<input type=hidden name=ip value='${addr['ip']}'>";
1159 echo "<tr class='$class'><td><a href='${root}process.php?op=delIPv4Allocation&page=${pageno}&tab=${tabno}&ip=${addr['ip']}&object_id=$object_id'>";
1160 printImageHREF ('delete', 'Delete this IPv4 address');
1162 echo "<td class=tdleft><input type='text' name='bond_name' value='${addr['name']}' size=10></td>";
1163 echo "<td class=tdleft><a href='${root}?page=ipaddress&ip=${addr['ip']}'>${addr['ip']}</a></td>";
1164 echo "<td class='description'>$address_name</td>\n";
1165 echo "<td><select name='bond_type'>";
1166 foreach (array('regular'=>'Regular', 'virtual'=>'Virtual', 'shared'=>'Shared') as $n => $v)
1168 echo "<option value='$n'";
1169 if ($addr['type'] == $n)
1171 echo ">$v</option>";
1174 if ($addr['address_reserved']=='yes')
1175 echo "<b>Reserved</b>; ";
1177 if ($addr['type'] == 'virtual')
1179 if ($notvirtnum > 0)
1182 printRefsOfType($addr['references'], 'virtual', 'neq');
1185 elseif ($addr['type'] == 'shared')
1190 printRefsOfType($addr['references'], 'shared', 'eq');
1196 printRefsOfType($addr['references'], 'virtual', 'eq');
1201 echo " Collisions: ";
1202 printRefsOfType($addr['references'], 'regular', 'eq');
1211 printRefsOfType($addr['references'], 'virtual', 'eq');
1214 if ($notvirtnum > 0)
1216 echo " Collisions: ";
1217 printRefsOfType($addr['references'], 'virtual', 'neq');
1222 printImageHREF ('save', 'Save changes', TRUE);
1223 echo "</td></form></tr>\n";
1227 echo "<form action='${root}process.php'><tr><td>";
1228 printImageHREF ('add', 'Allocate new address', TRUE, 99);
1229 echo "</td><td class=tdleft>";
1230 echo "<input type='text' size='10' name='bond_name' tabindex=100></td>\n";
1231 echo "<input type=hidden name=page value='${pageno}'>\n";
1232 echo "<input type=hidden name=tab value='${tabno}'>\n";
1233 echo "<input type=hidden name=op value=addIPv4Allocation>\n";
1234 echo "<input type=hidden name=object_id value='$object_id'>\n";
1235 echo "<td class=tdleft><input type=text name='ip' tabindex=101>\n";
1236 echo "</td><td> </td><td><select name='bond_type' tabindex=102>";
1237 echo "<option value='regular'>Regular</option>";
1238 echo "<option value='virtual'>Virtual</option>";
1239 echo "<option value='shared'>Shared</option>";
1241 echo "</td><td colspan=2> </td></tr></form>";
1242 echo "</table><br>\n";
1247 function printLog ($log)
1249 foreach ($log as $record)
1250 echo "<div class=msg_${record['code']}>${record['message']}</div>";
1254 The following conditions must be followed:
1255 1. We can mount onto free atoms only. This means: if any record for an atom
1256 already exists in RackSpace, it can't be used for mounting.
1257 2. We can't unmount from 'W' atoms. Operator should review appropriate comments
1258 and either delete them before unmounting or refuse to unmount the object.
1261 // We extensively use $_REQUEST in the function.
1262 function renderRackSpaceForObject ($object_id = 0)
1264 if ($object_id <= 0)
1266 showError ('Invalid object_id', __FUNCTION__
);
1269 $is_submit = isset ($_REQUEST['got_atoms']);
1270 $is_update = isset ($_REQUEST['rackmulti'][0]);
1271 $info = getObjectInfo ($object_id);
1274 showError ('getObjectInfo() failed', __FUNCTION__
);
1277 // Always process occupied racks plus racks chosen by user. First get racks with
1278 // already allocated rackspace...
1279 $workingRacksData = getResidentRacksData ($object_id);
1280 if ($workingRacksData === NULL)
1282 print_r ($workingRacksData);
1283 showError ('getResidentRacksData() failed', __FUNCTION__
);
1287 // ...and then add those chosen by user (if any).
1289 foreach ($_REQUEST['rackmulti'] as $cand_id)
1291 if (!isset ($workingRacksData[$cand_id]))
1293 $rackData = getRackData ($cand_id);
1294 if ($rackData == NULL)
1296 showError ('getRackData() failed', __FUNCTION__
);
1299 $workingRacksData[$cand_id] = $rackData;
1303 // Do it only once...
1304 foreach ($workingRacksData as &$rackData)
1305 applyObjectMountMask ($rackData, $object_id);
1306 // Now we workaround an old caveat: http://bugs.php.net/bug.php?id=37410
1309 // Here we process form submit by trying to save all submitted info to database.
1312 $oldMolecule = getMoleculeForObject ($object_id);
1313 $worldchanged = FALSE;
1315 foreach ($workingRacksData as $rack_id => $rackData)
1317 $logrecord = processGridForm ($rackData, 'F', 'T', $object_id);
1318 $log[] = $logrecord;
1319 if ($logrecord['code'] != 300)
1321 $worldchanged = TRUE;
1322 // Reload our working copy after form processing.
1323 $rackData = getRackData ($rack_id);
1324 if ($rackData == NULL)
1325 $log[] = array ('code' => 500, 'message' => 'Working copy update failed in ', __FUNCTION__
);
1326 applyObjectMountMask ($rackData, $object_id);
1327 $workingRacksData[$rack_id] = $rackData;
1333 $newMolecule = getMoleculeForObject ($object_id);
1334 $oc = count ($oldMolecule);
1335 $nc = count ($newMolecule);
1336 $omid = $oc ?
createMolecule ($oldMolecule) : 'NULL';
1337 $nmid = $nc ?
createMolecule ($newMolecule) : 'NULL';
1338 global $remote_username;
1339 $comment = empty ($_REQUEST['comment']) ?
'NULL' : "'${_REQUEST['comment']}'";
1341 "insert into MountOperation(object_id, old_molecule_id, new_molecule_id, user_name, comment) " .
1342 "values (${object_id}, ${omid}, ${nmid}, '${remote_username}', ${comment})";
1344 $result = $dbxlink->query ($query);
1345 if ($result == NULL)
1346 $log[] = array ('code' => 'error', 'message' => 'SQL query failed during history logging.');
1348 $log[] = array ('code' => 'success', 'message' => 'History logged.');
1353 // This is the time for rendering.
1354 global $root, $pageno, $tabno;
1355 echo "<form id='racks' action='${root}'>";
1356 echo "<input type=hidden name=page value='${pageno}'>\n";
1357 echo "<input type=hidden name=tab value='${tabno}'>\n";
1358 echo "<input type=hidden name=object_id value='${object_id}'>\n";
1359 // Main layout starts.
1360 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0><tr>";
1362 // Left portlet with rack list.
1363 echo "<td class=pcleft height='1%'>";
1364 startPortlet ('Racks');
1365 $allRacksData = getRacksForRow();
1366 if (count ($allRacksData) <= getConfigVar ('RACK_PRESELECT_THRESHOLD'))
1368 foreach (array_keys ($allRacksData) as $rack_id)
1370 $rackData = getRackData ($rack_id);
1371 if ($rackData == NULL)
1373 showError ('getRackData() failed', __FUNCTION__
);
1376 $workingRacksData[$rack_id] = $rackData;
1378 foreach ($workingRacksData as &$rackData)
1379 applyObjectMountMask ($rackData, $object_id);
1382 renderRackMultiSelect ('rackmulti[]', $allRacksData, array_keys ($workingRacksData));
1388 // Middle portlet with comment and submit.
1389 echo "<td class=pcleft>";
1390 startPortlet ('Comment');
1391 echo "<textarea name=comment rows=10 cols=40></textarea><br>\n";
1392 echo "<input type=submit value='Save' name=got_atoms>\n";
1398 // Right portlet with rendered racks. If this form submit is not final, we have to
1399 // reflect the former state of the grid in current form.
1400 echo "<td class=pcright rowspan=2 height='1%'>";
1401 startPortlet ('Working copy');
1402 echo '<table border=0 cellspacing=10 align=center><tr>';
1403 foreach ($workingRacksData as $rack_id => $rackData)
1405 // Order is important here: only original allocation is highlighted.
1406 highlightObject ($rackData, $object_id);
1407 markupAtomGrid ($rackData, 'T');
1408 // If we have a form processed, discard user input and show new database
1410 if (!$is_submit and $is_update)
1411 mergeGridFormToRack ($rackData);
1412 echo "<td valign=top>";
1413 echo "<center>\n<h2>${rackData['name']}</h2>\n";
1414 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
1415 echo "<tr><th width='10%'> </th><th width='20%'>Front</th>";
1416 echo "<th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
1417 renderAtomGrid ($rackData);
1418 echo "<tr><th width='10%'> </th><th width='20%'>Front</th>";
1419 echo "<th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
1420 echo "</table></center>\n";
1423 echo "</tr></table>";
1428 echo "</tr></table>\n";
1431 function renderMolecule ($mdata, $object_id)
1434 $rackpack = array();
1436 foreach ($mdata as $rua)
1438 $rack_id = $rua['rack_id'];
1439 $unit_no = $rua['unit_no'];
1440 $atom = $rua['atom'];
1441 if (!isset ($rackpack[$rack_id]))
1443 $rackData = getRackData ($rack_id);
1444 for ($i = $rackData['height']; $i > 0; $i--)
1445 for ($locidx = 0; $locidx < 3; $locidx++
)
1446 $rackData[$i][$locidx]['state'] = 'F';
1447 $rackpack[$rack_id] = $rackData;
1449 $rackpack[$rack_id][$unit_no][$loclist[$atom]]['state'] = 'T';
1450 $rackpack[$rack_id][$unit_no][$loclist[$atom]]['object_id'] = $object_id;
1452 // now we have some racks to render
1453 foreach ($rackpack as $rackData)
1455 markAllSpans ($rackData);
1456 echo "<table class=molecule cellspacing=0>\n";
1457 echo "<caption>${rackData['name']}</caption>\n";
1458 echo "<tr><th width='10%'> </th><th width='20%'>Front</th><th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
1459 for ($i = $rackData['height']; $i > 0; $i--)
1461 echo "<tr><th>$i</th>";
1462 for ($locidx = 0; $locidx < 3; $locidx++
)
1464 $state = $rackData[$i][$locidx]['state'];
1465 echo "<td class=state_${state}> </td>\n";
1473 function renderUnmountedObjectsPortlet ()
1475 startPortlet ('Unmounted objects');
1476 $objs = getUnmountedObjects();
1479 showError ('getUnmountedObjects() failed', __FUNCTION__
);
1482 global $root, $nextorder;
1484 echo '<br><br><table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
1485 echo '<tr><th>Common name</th><th>Visible label</th><th>Asset number</th><th>Barcode</th></tr>';
1486 foreach ($objs as $obj)
1488 echo "<tr class=row_${order}><td><a href='${root}?page=object&object_id=${obj['id']}'>${obj['dname']}</a></td>";
1489 echo "<td>${obj['label']}</td>";
1490 echo "<td>${obj['asset_no']}</td>";
1491 echo "<td>${obj['barcode']}</td></tr>";
1492 $order = $nextorder[$order];
1494 echo "</table><br>\n";
1498 function renderProblematicObjectsPortlet ()
1500 startPortlet ('Problematic objects');
1501 $objs = getProblematicObjects();
1504 showError ('getProblematicObjects() failed', __FUNCTION__
);
1507 global $root, $nextorder;
1509 echo '<br><br><table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
1510 echo '<tr><th>Type</th><th>Common name</th></tr>';
1511 foreach ($objs as $obj)
1513 echo "<tr class=row_${order}><td>${obj['objtype_name']}</td>";
1514 echo "<td><a href='${root}?page=object&object_id=${obj['id']}'>${obj['dname']}</a></tr>";
1515 $order = $nextorder[$order];
1517 echo "</table><br>\n";
1521 function renderObjectSpace ()
1523 global $root, $taglist, $tagtree;
1524 echo "<table border=0 class=objectview>\n";
1525 echo "<tr><td class=pcleft width='50%'>";
1526 startPortlet ('View all by type');
1527 $groupInfo = getObjectGroupInfo();
1528 if ($groupInfo === NULL)
1530 showError ('getObjectGroupInfo() failed', __FUNCTION__
);
1533 if (count ($groupInfo) == 0)
1534 echo "No objects exist in DB";
1537 echo '<div align=left><ul>';
1538 foreach ($groupInfo as $gi)
1539 echo "<li><a href='${root}?page=objgroup&group_id=${gi['id']}'>${gi['name']}</a> (${gi['count']})</li>";
1544 echo '</td><td class=pcright>';
1546 startPortlet ('View all by tag');
1547 if (count ($taglist) == 0)
1548 echo "No tags exist in DB";
1550 renderTagCloud ('object');
1552 echo "</td></tr></table>\n";
1555 function renderObjectGroup ()
1557 global $root, $pageno, $tabno, $nextorder, $taglist, $tagtree;
1558 assertUIntArg ('group_id', __FUNCTION__
, TRUE);
1559 $group_id = $_REQUEST['group_id'];
1560 $tagfilter = getTagFilter();
1561 $tagfilter_str = getTagFilterStr ($tagfilter);
1562 echo "<table border=0 class=objectview>\n";
1563 echo "<tr><td class=pcleft width='25%'>";
1564 startPortlet ('change type');
1565 $groupInfo = getObjectGroupInfo();
1566 if ($groupInfo === NULL)
1568 showError ('getObjectGroupInfo() failed', __FUNCTION__
);
1571 if (count ($groupInfo) == 0)
1572 echo "No objects exist in DB";
1575 echo '<div align=left><ul>';
1576 foreach ($groupInfo as $gi)
1578 echo "<li><a href='${root}?page=${pageno}&group_id=${gi['id']}${tagfilter_str}'>";
1579 if ($gi['id'] == $group_id)
1581 echo "${gi['name']}</a>";
1582 if ($gi['id'] == $group_id)
1584 echo " (${gi['count']})";
1585 if ($gi['id'] == $group_id)
1593 echo '</td><td class=pcleft>';
1595 startPortlet ('Objects');
1596 $objects = getObjectList ($group_id, $tagfilter, getTFMode());
1597 if ($objects === NULL)
1599 showError ('getObjectList() failed', __FUNCTION__
);
1602 echo '<br><br><table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
1603 echo '<tr><th>Common name</th><th>Visible label</th><th>Asset tag</th><th>Barcode</th><th>Rack</th></tr>';
1605 foreach ($objects as $obj)
1607 if (isset ($_REQUEST['hl_object_id']) and $_REQUEST['hl_object_id'] == $obj['id'])
1608 $secondclass = 'tdleft port_highlight';
1610 $secondclass = 'tdleft';
1611 echo "<tr class=row_${order}><td class='${secondclass}'><a href='${root}?page=object&object_id=${obj['id']}'>${obj['dname']}</a></td>";
1612 echo "<td class='${secondclass}'>${obj['label']}</td>";
1613 echo "<td class='${secondclass}'>${obj['asset_no']}</td>";
1614 echo "<td class='${secondclass}'>${obj['barcode']}</td>";
1615 if ($obj['rack_id'])
1616 echo "<td class='${secondclass}'><a href='${root}?page=rack&rack_id=${obj['rack_id']}'>${obj['Rack_name']}</a></td>";
1618 echo "<td class='${secondclass}'>Unmounted</td>";
1620 $order = $nextorder[$order];
1625 echo "</td><td class=pcright width='25%'>";
1627 renderTagFilterPortlet ($tagfilter, 'object', 'group_id', $group_id);
1628 echo "</td></tr></table>\n";
1631 function renderEmptyPortsSelect ($port_id, $type_id)
1633 $ports = getEmptyPortsOfType($type_id);
1634 usort($ports, 'sortEmptyPorts');
1635 foreach ($ports as $port)
1637 if ($port_id == $port['Port_id'])
1639 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";
1643 function renderObjectAddressesAndNames ()
1645 $addresses = getObjectAddressesAndNames();
1646 usort($addresses, 'sortObjectAddressesAndNames');
1647 foreach ($addresses as $address)
1649 echo "<option value='${address['ip']}' onclick='getElementById(\"ip\").value=\"${address['ip']}\";'>${address['object_name']} ${address['name']} ${address['ip']}</option>\n";
1653 // History viewer for history-enabled simple dictionaries.
1654 function renderHistory ($object_type, $object_id)
1656 switch ($object_type)
1659 $query = "select ctime, user_name, name, deleted, comment from RackRowHistory where id = ${object_id} order by ctime";
1660 $header = '<tr><th>change time</th><th>author</th><th>rack row name</th><th>is deleted?</th><th>rack row comment</th></tr>';
1665 "select ctime, user_name, rh.name, rh.deleted, d.dict_value as name, rh.height, rh.comment " .
1666 "from RackHistory as rh left join Dictionary as d on rh.row_id = d.dict_key " .
1667 "natural join Chapter " .
1668 "where chapter_name = 'RackRow' and rh.id = ${object_id} order by ctime";
1669 $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>';
1674 "select ctime, user_name, name, label, barcode, asset_no, deleted, has_problems, dict_value, comment " .
1675 "from RackObjectHistory inner join Dictionary on objtype_id = dict_key natural join Chapter " .
1676 "where chapter_name = 'RackObjectType' and id=${object_id} order by ctime";
1677 $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>';
1681 showError ("Uknown object type '${object_type}'", __FUNCTION__
);
1685 $result = $dbxlink->query ($query);
1686 if ($result == NULL)
1688 showError ('SQL query failed', __FUNCTION__
);
1691 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
1695 while ($row = $result->fetch (PDO
::FETCH_NUM
))
1697 echo "<tr class=row_${order}><td>${row[0]}</td>";
1698 for ($i = 1; $i <= $extra; $i++
)
1699 echo "<td>" . $row[$i] . "</td>";
1701 $order = $nextorder[$order];
1703 echo "</table><br>\n";
1706 function renderRackspaceHistory ()
1708 global $root, $nextorder, $pageno, $tabno;
1710 $history = getRackspaceHistory();
1711 // Show the last operation by default.
1712 if (isset ($_REQUEST['op_id']))
1713 $op_id = $_REQUEST['op_id'];
1714 elseif (isset ($history[0]['mo_id']))
1715 $op_id = $history[0]['mo_id'];
1722 list ($omid, $nmid) = getOperationMolecules ($op_id);
1724 // Main layout starts.
1725 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
1727 // Left top portlet with old allocation.
1728 echo "<tr><td class=pcleft>";
1729 startPortlet ('Old allocation');
1732 $oldMolecule = getMolecule ($omid);
1733 renderMolecule ($oldMolecule, $object_id);
1739 echo '</td><td class=pcright>';
1741 // Right top portlet with new allocation
1742 startPortlet ('New allocation');
1745 $newMolecule = getMolecule ($nmid);
1746 renderMolecule ($newMolecule, $object_id);
1752 echo '</td></tr><tr><td colspan=2>';
1754 // Bottom portlet with list
1756 startPortlet ('Rackspace allocation history');
1757 echo "<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>\n";
1758 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";
1759 foreach ($history as $row)
1761 if ($row['mo_id'] == $op_id)
1764 $class = "row_${order}";
1765 echo "<tr class=${class}><td><a href='${root}?page=${pageno}&tab=${tabno}&op_id=${row['mo_id']}'>${row['ctime']}</a></td>";
1766 echo "<td>${row['user_name']}</td>";
1767 echo "<td>${row['ro_id']}</td><td>${row['objtype_name']}</td><td>${row['name']}</td><td>${row['comment']}</td>\n";
1769 $order = $nextorder[$order];
1774 echo '</td></tr></table>';
1778 function renderAddressspace ()
1780 global $root, $page;
1782 echo "<table border=0 class=objectview>\n";
1783 echo "<tr><td class=pcleft>";
1785 startPortlet ('Subnets');
1786 echo "<table class='widetable' border=0 cellpadding=10 cellspacing=0 align='center'>\n";
1787 $tagfilter = getTagFilter();
1788 $addrspaceList = getAddressspaceList ($tagfilter, getTFMode());
1789 echo "<tr><th>Subnet</th><th>Name</th><th>Utilization</th></tr>";
1790 foreach ($addrspaceList as $iprange)
1792 $range = getIPRange ($iprange['id']);
1793 $total = ($iprange['ip_bin'] |
$iprange['mask_bin_inv']) - ($iprange['ip_bin'] & $iprange['mask_bin']) +
1;
1794 $used = count ($range['addrlist']);
1795 echo "<tr><td class=tdleft><a href='${root}?page=iprange&id=${iprange['id']}'>${iprange['ip']}/${iprange['mask']}</a></td>";
1796 echo "<td class=tdleft>${iprange['name']}</td><td class=tdleft>";
1797 renderProgressBar ($used/$total);
1798 echo " ${used}/${total}</td></tr>";
1802 echo '</td><td class=pcright>';
1803 renderTagFilterPortlet ($tagfilter, 'ipv4net');
1804 echo "</td></tr></table>\n";
1807 function renderIPv4SLB ()
1809 global $root, $page, $nextorder;
1811 startPortlet ('SLB configuration');
1812 echo "<table border=0 width='100%'><tr>";
1813 foreach (array ('ipv4vslist', 'ipv4rsplist', 'rservers', 'lbs') as $pno)
1814 echo "<td><h3><a href='${root}?page=${pno}'>" . $page[$pno]['title'] . "</a></h3></td>";
1815 echo '</tr></table>';
1818 $summary = getSLBSummary();
1819 startPortlet ('SLB tactical overview');
1820 // A single id-keyed array isn't used here to preserve existing
1821 // order of LBs returned by getSLBSummary()
1824 foreach ($summary as $vipdata)
1825 foreach (array_keys ($vipdata['lblist']) as $lb_object_id)
1826 if (!in_array ($lb_object_id, $lblist))
1828 $oi = getObjectInfo ($lb_object_id);
1829 $lbdname[$lb_object_id] = $oi['dname'];
1830 $lblist[] = $lb_object_id;
1832 if (!count ($summary))
1833 echo 'none configured';
1837 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
1838 echo "<tr><th>VS ↓ LB →</th>";
1839 foreach ($lblist as $lb_object_id)
1840 echo "<th><a href='${root}?page=object&tab=default&object_id=${lb_object_id}'>" . $lbdname[$lb_object_id] . "</a></th>";
1842 foreach ($summary as $vsid => $vsdata)
1844 echo "<tr class=row_${order}><td class=tdleft><a href='$root?page=ipv4vs&tab=default&vs_id=${vsid}'>";
1845 echo buildVServiceName ($vsdata);
1847 if (!empty ($vsdata['name']))
1848 echo "<br>${vsdata['name']}";
1850 foreach ($lblist as $lb_object_id)
1852 echo '<td class=tdleft>';
1853 if (!isset ($vsdata['lblist'][$lb_object_id]))
1857 echo $vsdata['lblist'][$lb_object_id]['size'];
1858 echo " (<a href='${root}?page=ipv4rsp&pool_id=";
1859 echo $vsdata['lblist'][$lb_object_id]['id'] . "'>";
1860 echo $vsdata['lblist'][$lb_object_id]['name'] . '</a>)';
1865 $order = $nextorder[$order];
1872 function renderAddNewRange ()
1874 global $root, $pageno, $tabno;
1875 showMessageOrError();
1877 startPortlet ("Add New");
1878 echo "<table class='widetable' border=0 cellpadding=10 align='center'>\n";
1879 echo "<tr><th>Address range</th><th>Name</th><th>connected network</th><th>assign tags</th><th> </th></tr>\n";
1880 echo "<form name='add_new_range' action='${root}process.php'>\n";
1881 echo "<input type=hidden name=op value=addIPv4Prefix>\n";
1882 echo "<input type=hidden name=page value='${pageno}'>\n";
1883 echo "<input type=hidden name=tab value='${tabno}'>\n";
1884 echo "<tr valign=top><td class='tdcenter'><input type=text name='range' size=18 class='live-validate' tabindex=1></td>\n";
1885 echo "<td class='tdcenter'><input type=text name='name' size='20' tabindex=2></td>\n";
1886 echo "<td class='tdcenter'><input type=checkbox name='is_bcast' tabindex=3 checked></td>\n";
1890 echo "<td class='tdcenter'><input type=submit value='Add a new range' tabindex=4></td>\n";
1891 echo "</td></tr>\n";
1892 echo "</form></table><br><br>\n";
1895 startPortlet ("Manage Existing");
1896 echo "<table class='widetable' border=0 cellpadding=10 align='center'>\n";
1897 $addrspaceList = getAddressspaceList();
1898 echo "<tr><th> </th><th>Address range</th><th>Name</th><th>Utilization</th></tr>";
1899 foreach ($addrspaceList as $iprange)
1901 $range = getIPRange($iprange['id']);
1902 $usedips = count ($range['addrlist']);
1903 $totalips = ($iprange['ip_bin'] |
$iprange['mask_bin_inv']) - ($iprange['ip_bin'] & $iprange['mask_bin']) +
1;
1907 echo "<a href='${root}process.php?op=delIPv4Prefix&page=${pageno}&tab=${tabno}&id=${iprange['id']}'>";
1908 printImageHREF ('delete', 'Delete this IP range');
1912 printImageHREF ('nodelete', 'There are IP addresses allocated or reserved');
1913 echo "</td>\n<td class=tdleft><a href='${root}?page=iprange&id=${iprange['id']}'>";
1914 echo "${iprange['ip']}/${iprange['mask']}</a></td><td class=tdleft>${iprange['name']}";
1915 echo "</td><td class=tdleft>";
1916 renderProgressBar ($usedips / $totalips);
1917 echo " ${usedips}/${totalips}";
1924 function renderIPRange ($id)
1926 global $root, $pageno, $tabno;
1927 $netmaskbylen = array
1929 32 => '255.255.255.255',
1930 31 => '255.255.255.254',
1931 30 => '255.255.255.252',
1932 29 => '255.255.255.248',
1933 28 => '255.255.255.240',
1934 27 => '255.255.255.224',
1935 26 => '255.255.255.192',
1936 25 => '255.255.255.128',
1937 24 => '255.255.255.0',
1938 23 => '255.255.254.0',
1939 22 => '255.255.252.0',
1940 21 => '255.255.248.0',
1941 20 => '255.255.240.0',
1942 19 => '255.255.224.0',
1943 18 => '255.255.192.0',
1944 17 => '255.255.128.0',
1945 16 => '255.255.0.0',
1946 15 => '255.254.0.0',
1947 14 => '255.252.0.0',
1948 13 => '255.248.0.0',
1949 12 => '255.240.0.0',
1950 11 => '255.224.0.0',
1951 10 => '255.192.0.0',
1962 $wildcardbylen = array
1979 17 => '0.0.127.255',
1981 15 => '0.1.255.255',
1982 14 => '0.3.255.255',
1983 13 => '0.7.255.255',
1984 12 => '0.15.255.255',
1985 11 => '0.31.255.255',
1986 10 => '0.63.255.255',
1987 9 => '0.127.255.255',
1988 8 => '0.255.255.255',
1989 7 => '1.255.255.255',
1990 6 => '3.255.255.255',
1991 5 => '7.255.255.255',
1992 4 => '15.255.255.255',
1993 3 => '31.255.255.255',
1994 2 => '63.255.255.255',
1995 1 => '127.255.255.255'
1997 $maxperpage = getConfigVar ('IPV4_ADDRS_PER_PAGE');
1998 if (isset($_REQUEST['pg']))
1999 $page = $_REQUEST['pg'];
2003 $range = getIPRange($id);
2004 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
2005 echo "<tr><td colspan=2 align=center><h1>${range['ip']}/${range['mask']}</h1><h2>${range['name']}</h2></td></tr>\n";
2007 echo "<tr><td class=pcleft width='50%'>";
2008 startPortlet ('summary');
2009 $total = ($range['ip_bin'] |
$range['mask_bin_inv']) - ($range['ip_bin'] & $range['mask_bin']) +
1;
2010 $used = count ($range['addrlist']);
2011 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
2012 echo "<tr><th width='50%' class=tdright>Utilization:</th><td class=tdleft>";
2013 renderProgressBar ($used/$total);
2014 echo " ${used}/${total}</td></tr>\n";
2015 echo "<tr><th width='50%' class=tdright>Netmask:</th><td class=tdleft>";
2016 echo $netmaskbylen[$range['mask']];
2017 echo "</td></tr>\n";
2018 echo "<tr><th width='50%' class=tdright>Wildcard bits:</th><td class=tdleft>";
2019 echo $wildcardbylen[$range['mask']];
2020 echo "</td></tr>\n";
2021 printTagTRs ("${root}?page=ipv4space&");
2022 echo "</table><br>\n";
2026 echo "<td class=pcright>";
2027 startPortlet ('details');
2028 $startip = $range['ip_bin'] & $range['mask_bin'];
2029 $endip = $range['ip_bin'] |
$range['mask_bin_inv'];
2030 $realstartip = $startip;
2031 $realendip = $endip;
2033 if($endip - $startip > $maxperpage)
2035 $numpages = ($endip - $startip)/$maxperpage;
2036 $startip = $startip +
$page * $maxperpage;
2037 $endip = $startip +
$maxperpage-1;
2041 echo '<h3>' . long2ip ($startip) . ' ~ ' . long2ip ($endip) . '</h3>';
2042 for ($i=0; $i<$numpages; $i++
)
2047 echo "<a href='${root}?page=${pageno}&tab=${tabno}&id=$id&pg=$i'>$i</a> ";
2051 echo "<table class='widetable' border=0 cellspacing=0 cellpadding=5 align='center'>\n";
2052 echo "<tr><th>Address</th><th>Name</th><th>Allocation</th></tr>\n";
2055 for ($ip = $startip; $ip<=$endip; $ip++
)
2056 if (!isset ($range['addrlist'][$ip]))
2057 echo "<tr><td class=tdleft><a href='${root}?page=ipaddress&ip=".long2ip($ip)."'>".long2ip($ip)."</a></td><td> </td><td> </td></tr>\n";
2060 $numshared = countRefsOfType($range['addrlist'][$ip]['references'], 'shared', 'eq');
2061 $numreg = countRefsOfType($range['addrlist'][$ip]['references'], 'regular', 'eq');
2062 $numvirt = countRefsOfType($range['addrlist'][$ip]['references'], 'virtual', 'eq');
2063 $numlb = count ($range['addrlist'][$ip]['lbrefs']);
2064 $numrs = count ($range['addrlist'][$ip]['rsrefs']);
2066 $addr = $range['addrlist'][$ip];
2067 if ( ($numshared > 0 && $numreg > 0) ||
$numreg > 1 )
2068 echo "<tr class='trerror'>";
2069 elseif ( $addr['reserved'] == 'yes' and $numshared+
$numreg+
$numvirt+
$numlb+
$numrs > 0)
2070 echo "<tr class='trerror'>";
2071 elseif ( $addr['reserved'] == 'yes')
2072 echo "<tr class='trbusy'>";
2073 elseif ($numshared +
$numreg +
$numvirt +
$numlb +
$numrs > 0)
2074 echo "<tr class='trbusy'>";
2078 echo "<td class=tdleft><a href='${root}?page=ipaddress&ip=${addr['ip']}'>${addr['ip']}</a></td>";
2079 if (isset ($_REQUEST['hl_ipv4_addr']) and $_REQUEST['hl_ipv4_addr'] == $addr['ip'])
2080 $secondstyle = 'tdleft port_highlight';
2082 $secondstyle = 'tdleft';
2083 echo "<td class='${secondstyle}'>${addr['name']}</td><td class='${secondstyle}'>";
2086 if ( $addr['reserved'] == 'yes')
2088 echo "<b>Reserved</b> ";
2091 foreach ($range['addrlist'][$ip]['references'] as $ref)
2093 echo "${delim}<a href='${root}?page=object&object_id=${ref['object_id']}";
2094 echo "&hl_ipv4_addr=${addr['ip']}'>";
2095 echo $ref['name'] . (empty ($ref['name']) ?
'' : '@');
2096 echo "${ref['object_name']}</a>";
2104 foreach ($range['addrlist'][$ip]['lbrefs'] as $ref)
2108 echo "${delim}<a href='${root}?page=object&object_id=${ref['object_id']}'>";
2109 echo "${ref['object_name']}</a>:<a href='${root}?page=ipv4vs&vs_id=${ref['vs_id']}'>";
2110 echo "${ref['vport']}/${ref['proto']}</a>→";
2118 foreach ($range['addrlist'][$ip]['rsrefs'] as $ref)
2122 echo "${delim}→${ref['rsport']}@<a href='${root}?page=ipv4rsp&pool_id=${ref['rspool_id']}'>";
2123 echo "${ref['rspool_name']}</a>";
2126 echo "</td></tr>\n";
2132 echo "</td></tr></table>\n";
2135 function renderIPRangeProperties ($id)
2137 global $root, $pageno, $tabno;
2138 showMessageOrError();
2139 $range = getIPRange($id);
2140 echo "<center><h1>${range['ip']}/${range['mask']}</h1></center>\n";
2141 echo "<table border=0 cellpadding=10 cellpadding=1 align='center'>\n";
2142 echo "<form action='${root}process.php'><input type=hidden name=op value=editRange>";
2143 echo "<input type=hidden name=page value='${pageno}'>\n";
2144 echo "<input type=hidden name=tab value='${tabno}'>\n";
2145 echo "<input type=hidden name=id value='${id}'>";
2146 echo "<tr><td class='tdright'>Name:</td><td class='tdleft'><input type=text name=name size=20 value='${range['name']}'></tr><tr><td colspan=2 class='tdcenter'><input type=submit value='Update range'></td></form></tr>";
2151 function renderIPAddress ($ip)
2154 $address = getIPAddress ($ip);
2155 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
2156 echo "<tr><td colspan=2 align=center><h1>${ip}</h1></td></tr>\n";
2157 if ($address['exists'] == 1)
2158 echo "<tr><td colspan=2 align=center><h2>${address['name']}</h2></td></tr>\n";
2160 echo "<tr><td class=pcleft>";
2161 startPortlet ('summary');
2162 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
2163 echo "<tr><th width='50%' class=tdright>Allocations:</th><td class=tdleft>" . count ($address['bonds']) . "</td></tr>\n";
2164 echo "<tr><th width='50%' class=tdright>Originated NAT connections:</th><td class=tdleft>" . count ($address['outpf']) . "</td></tr>\n";
2165 echo "<tr><th width='50%' class=tdright>Arriving NAT connections:</th><td class=tdleft>" . count ($address['inpf']) . "</td></tr>\n";
2166 echo "<tr><th width='50%' class=tdright>SLB virtual services:</th><td class=tdleft>" . count ($address['vslist']) . "</td></tr>\n";
2167 echo "<tr><th width='50%' class=tdright>SLB real servers:</th><td class=tdleft>" . count ($address['rslist']) . "</td></tr>\n";
2169 echo "</table><br>\n";
2173 echo "<td class=pcright>";
2174 $numshared = countRefsOfType($address['bonds'], 'shared', 'eq');
2175 $numreg = countRefsOfType($address['bonds'], 'regular', 'eq');
2176 $numvirt = countRefsOfType($address['bonds'], 'virtual', 'eq');
2178 if ($address['reserved'] == 'yes' or ($numshared +
$numreg +
$numvirt) > 0)
2180 startPortlet ('allocations');
2181 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
2182 echo "<tr><th>Object name</th><th>Interface name</th><th>Interface type</th></tr>\n";
2183 if ( ($numshared > 0 && $numreg > 0) ||
$numreg > 1 )
2185 elseif ( $address['reserved'] == 'yes' and $numshared+
$numreg+
$numvirt > 0)
2190 if ($address['reserved'] == 'yes')
2191 echo "<tr class='$class'><td colspan='3'><b>RESERVED</b></td></tr>";
2192 foreach ($address['bonds'] as $bond)
2194 if (isset ($_REQUEST['hl_object_id']) and $_REQUEST['hl_object_id'] == $bond['object_id'])
2195 $secondclass = 'tdleft port_highlight';
2197 $secondclass = 'tdleft';
2198 echo "<tr class='$class'><td class=tdleft><a href='${root}?page=object&object_id=${bond['object_id']}";
2199 echo "&hl_ipv4_addr=${ip}'>${bond['object_name']}</td><td class='${secondclass}'>${bond['name']}</td><td class='${secondclass}'><b>";
2200 switch ($bond['type'])
2212 echo "</b></td></tr>\n";
2214 echo "</table><br><br>";
2218 if (count ($address['vslist']))
2220 startPortlet ('Virtual services (' . count ($address['vslist']) . ')');
2221 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
2222 echo "<tr><th>VS</th><th>name</th></tr>\n";
2223 foreach ($address['vslist'] as $vsinfo)
2225 echo "<tr><td class=tdleft><a href='${root}?page=ipv4vs&vs_id=${vsinfo['id']}'>";
2226 echo buildVServiceName ($vsinfo) . "</a></td><td class=tdleft>";
2227 echo $vsinfo['name'] . "</td></tr>\n";
2229 echo "</table><br><br>";
2233 if (count ($address['rslist']))
2235 startPortlet ('Real servers (' . count ($address['rslist']) . ')');
2236 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
2237 echo "<tr><th> </th><th>port</th><th>RS pool</th></tr>\n";
2238 foreach ($address['rslist'] as $rsinfo)
2241 if ($rsinfo['inservice'] == 'yes')
2242 printImageHREF ('inservice', 'in service');
2244 printImageHREF ('notinservice', 'NOT in service');
2245 echo "</td><td class=tdleft>${rsinfo['rsport']}</td><td class=tdleft><a href='${root}?page=ipv4rsp&pool_id=${rsinfo['pool_id']}'>";
2246 echo $rsinfo['poolname'] . "</a></td></tr>\n";
2248 echo "</table><br><br>";
2252 if (count ($address['outpf']))
2254 startPortlet ('departing NAT rules');
2255 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
2256 echo "<tr><th>proto</th><th>from</th><th>to</th><th>comment</th></tr>\n";
2257 foreach ($address['outpf'] as $rule)
2258 echo "<tr><td>${rule['proto']}</td><td>${rule['localip']}:${rule['localport']}</td><td>${rule['remoteip']}:${rule['localport']}</td><td>${rule['description']}</td></tr>";
2263 if (count ($address['inpf']))
2265 startPortlet ('arriving NAT rules');
2266 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
2267 echo "<tr><th>proto</th><th>from</th><th>to</th><th>comment</th></tr>\n";
2268 foreach ($address['inpf'] as $rule)
2269 echo "<tr><td>${rule['proto']}</td><td>${rule['localip']}:${rule['localport']}</td><td>${rule['remoteip']}:${rule['localport']}</td><td>${rule['description']}</td></tr>";
2278 function renderIPAddressProperties ($ip)
2280 global $pageno, $tabno, $root;
2281 showMessageOrError();
2282 $address = getIPAddress($ip);
2283 echo "<center><h1>$ip</h1></center>\n";
2284 startPortlet ('update');
2285 echo "<table border=0 cellpadding=10 cellpadding=1 align='center'>\n";
2286 echo "<form action='${root}process.php'><input type=hidden name=op value=editAddress>";
2287 echo "<input type=hidden name=page value='${pageno}'>\n";
2288 echo "<input type=hidden name=tab value='${tabno}'>\n";
2289 echo "<input type=hidden name=ip value='${ip}'>";
2290 echo "<tr><td class='tdright'>Name:</td><td class='tdleft'><input type=text name=name size=20 value='".($address['exists']==1?
$address['name']:'')."'></tr>";
2291 echo "<td class='tdright'>Reserved:</td><td class='tdleft'><input type=checkbox name=reserved size=20 ".($address['exists']==1?
(($address['reserved']=='yes')?
'checked':''):'')."></tr>";
2292 echo "<tr><td colspan=2 class='tdcenter'><input type=submit value='Update address'></td></form></tr>";
2295 if (empty ($address['name']) and $address['reserved'] == 'no')
2297 startPortlet ('release');
2298 echo "<form action='${root}process.php?page=${pageno}&tab=${tabno}&op=editAddress' method=post>";
2299 echo "<input type=hidden name=ip value='${ip}'>";
2300 echo "<input type=hidden name=name value=''>";
2301 echo "<input type=hidden name=reserved value=''>";
2302 echo "<input type=submit value='release'></form>";
2306 function renderIPAddressAssignment ($ip)
2308 global $pageno, $tabno, $root;
2309 $address = getIPAddress($ip);
2311 showMessageOrError();
2312 echo "<center><h1>$ip</h1></center>\n";
2315 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
2316 echo "<tr><th> </th><th>object name</th><th>object interface</th><th>allocation type</th><th> </th></tr>\n";
2318 $numshared = countRefsOfType($address['bonds'], 'shared', 'eq');
2319 $numreg = countRefsOfType($address['bonds'], 'regular', 'eq');
2320 $numvirt = countRefsOfType($address['bonds'], 'virtual', 'eq');
2323 if ( ($numshared > 0 && $numreg > 0) ||
$numreg > 1 )
2325 elseif ( $address['reserved'] == 'yes' and $numshared+
$numreg+
$numvirt > 0)
2332 if ($address['reserved'] == 'yes')
2333 echo "<tr class='$class'><td colspan='5'><b>RESERVED</b></td></tr>";
2334 foreach ($address['bonds'] as $bond)
2336 echo "<tr class='$class'><form action='${root}process.php'>";
2337 echo "<input type=hidden name=op value='updIPv4Allocation'>";
2338 echo "<input type=hidden name=page value='${pageno}'>";
2339 echo "<input type=hidden name=tab value='${tabno}'>";
2340 echo "<input type=hidden name=ip value='$ip'>";
2341 echo "<input type=hidden name=object_id value='${bond['object_id']}'>";
2342 echo "<td><a href='${root}process.php?op=delIPv4Allocation&page=${pageno}&tab=${tabno}&ip=$ip&object_id=${bond['object_id']}'>";
2343 printImageHREF ('delete', 'Unallocate address');
2345 echo "<td><a href='${root}?page=object&object_id=${bond['object_id']}&hl_ipv4_addr=${ip}'>${bond['object_name']}</td>";
2346 echo "<td><input type='text' name='bond_name' value='${bond['name']}' size=10></td>";
2347 echo "<td><select name='bond_type'>";
2348 switch ($bond['type'])
2351 echo "<option value='regular'>Regular</option>";
2352 echo "<option value='virtual' selected>Virtual</option>";
2353 echo "<option value='shared'>Shared</option>";
2356 echo "<option value='regular'>Regular</option>";
2357 echo "<option value='virtual'>Virtual</option>";
2358 echo "<option value='shared' selected>Shared</option>";
2361 echo "<option value='regular' selected>Regular</option>";
2362 echo "<option value='virtual'>Virtual</option>";
2363 echo "<option value='shared'>Shared</option>";
2366 echo "</select></td><td>";
2367 printImageHREF ('save', 'Save changes', TRUE);
2368 echo "</td></form></tr>\n";
2370 echo "<form action='${root}process.php'><input type='hidden' name='op' value='addIPv4Allocation'>";
2371 echo "<input type=hidden name=page value='${pageno}'>\n";
2372 echo "<input type=hidden name=tab value='${tabno}'>\n";
2373 echo "<input type='hidden' name='ip' value='$ip'>";
2375 printImageHREF ('add', 'new allocation', TRUE);
2376 echo "</td><td><select name='object_id'>";
2378 foreach (explode (',', getConfigVar ('IPV4_PERFORMERS')) as $type)
2379 foreach (getNarrowObjectList ($type) as $object)
2380 echo "<option value='${object['id']}'>${object['dname']}</option>";
2382 echo "</select></td><td><input type='text' name='bond_name' value='' size=10></td>";
2383 echo "<td><select name='bond_type'><option value='regular'>Regular</option><option value='virtual'>Virtual</option><option value='shared'>Shared</option></select></td>";
2384 echo "<td> </td></form></tr>";
2385 echo "</table><br><br>";
2389 function renderNATv4ForObject ($object_id = 0)
2391 global $pageno, $tabno, $root;
2393 $info = getObjectInfo ($object_id);
2394 $forwards = getNATv4ForObject ($object_id);
2395 $addresses = getObjectAddresses ($object_id);
2396 showMessageOrError();
2397 echo "<center><h2>locally performed NAT</h2></center>";
2399 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
2400 echo "<tr><th></th><th>Match endpoint</th><th>Translate to</th><th>Target object</th><th>Comment</th><th> </th></tr>\n";
2402 foreach ($forwards['out'] as $pf)
2406 foreach ($addresses as $addr)
2407 if ($addr['ip'] == $pf['localip'])
2410 $name = $addr['name'];
2414 echo "<tr class='$class'>";
2415 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}'>";
2416 printImageHREF ('delete', 'Delete NAT rule');
2418 echo "<td>${pf['proto']}/${name}: <a href='${root}?page=ipaddress&tab=default&ip=${pf['localip']}'>${pf['localip']}</a>:${pf['localport']}";
2419 if (!empty ($pf['local_addr_name']))
2420 echo ' (' . $pf['local_addr_name'] . ')';
2422 echo "<td><a href='${root}?page=ipaddress&tab=default&ip=${pf['remoteip']}'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
2424 $address=getIPAddress($pf['remoteip']);
2426 echo "<td class='description'>";
2427 if (count ($address['bonds']))
2428 foreach($address['bonds'] as $bond)
2429 echo "<a href='${root}?page=object&tab=default&object_id=${bond['object_id']}'>${bond['object_name']}(${bond['name']})</a> ";
2430 elseif (!empty ($pf['remote_addr_name']))
2431 echo '(' . $pf['remote_addr_name'] . ')';
2432 echo "</td><form action='${root}process.php'><input type=hidden name=op value=updNATv4Rule><input type=hidden name=page value='${pageno}'>";
2433 echo "<input type=hidden name=tab value='${tabno}'><input type='hidden' name='object_id' value='$object_id'>";
2434 echo "<input type='hidden' name='localip' value='${pf['localip']}'><input type='hidden' name='localport' value='${pf['localport']}'>";
2435 echo "<input type='hidden' name='remoteip' value='${pf['remoteip']}'><input type='hidden' name='remoteport' value='${pf['remoteport']}'>";
2436 echo "<input type='hidden' name='proto' value='${pf['proto']}'><td class='description'>";
2437 echo "<input type='text' name='description' value='${pf['description']}'></td><td>";
2438 printImageHREF ('save', 'Save changes', TRUE);
2439 echo "</td></form></tr>";
2441 echo "<form action='${root}process.php'><input type='hidden' name=op value=addNATv4Rule>";
2442 echo "<input type='hidden' name='object_id' value='$object_id'>";
2443 echo "<input type=hidden name=page value='${pageno}'>\n";
2444 echo "<input type=hidden name=tab value='${tabno}'>\n";
2445 echo "<tr align='center'><td>";
2446 printImageHREF ('add', 'Add new NAT rule', TRUE);
2448 printSelect (array ('TCP' => 'TCP', 'UDP' => 'UDP'), 'proto');
2449 echo "<select name='localip' tabindex=1>";
2451 foreach ($addresses as $addr)
2452 echo "<option value='${addr['ip']}'>" . (empty ($addr['name']) ?
'' : "${addr['name']}: ") .
2453 "${addr['ip']}" . (empty ($addr['address_name']) ?
'' : " (${addr['address_name']})") . "</option>";
2455 echo "</select>:<input type='text' name='localport' size='4' tabindex=2></td>";
2456 echo "<td><input type='text' name='remoteip' id='remoteip' size='10' tabindex=3>";
2457 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\");'>";
2458 printImageHREF ('find', 'Find object');
2460 echo ":<input type='text' name='remoteport' size='4' tabindex=4></td><td></td>";
2461 echo "<td colspan=1><input type='text' name='description' size='20' tabindex=5></td><td> </td></tr>";
2464 echo "</table><br><br>";
2466 echo "<center><h2>arriving NAT connections</h2></center>";
2467 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
2468 echo "<tr><th></th><th>Source</th><th>Source objects</th><th>Target</th><th>Description</th></tr>\n";
2470 foreach ($forwards['in'] as $pf)
2472 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}'>";
2473 printImageHREF ('delete', 'Delete NAT rule');
2475 echo "<td>${pf['proto']}/<a href='${root}?page=ipaddress&tab=default&ip=${pf['localip']}'>${pf['localip']}</a>:${pf['localport']}</td>";
2476 echo "<td class='description'><a href='${root}?page=object&tab=default&object_id=${pf['object_id']}'>${pf['object_name']}</a>";
2477 echo "</td><td><a href='${root}?page=ipaddress&tab=default&ip=${pf['remoteip']}'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
2478 echo "<td class='description'>${pf['description']}</td></tr>";
2481 echo "</table><br><br>";
2484 function renderAddMultipleObjectsForm ()
2486 global $root, $pageno, $tabno, $nextorder;
2489 $global_type_id = 0;
2491 $asset_no = array();
2492 $keepvalues1 = $keepvalues2 = FALSE;
2494 // Look for current submit.
2495 if (isset ($_REQUEST['got_fast_data']))
2497 $taglist = isset ($_REQUEST['taglist']) ?
$_REQUEST['taglist'] : array();
2498 $keepvalues1 = TRUE;
2499 $max = getConfigVar ('MASSCOUNT');
2500 for ($i = 0; $i < $max; $i++
)
2502 if (!isset ($_REQUEST["${i}_object_type_id"]))
2504 $log[] = array ('code' => 'error', 'message' => "Submitted form is invalid at line " . $i +
1);
2507 assertUIntArg ("${i}_object_type_id", __FUNCTION__
, TRUE);
2508 assertStringArg ("${i}_object_name", __FUNCTION__
, TRUE);
2509 assertStringArg ("${i}_object_label", __FUNCTION__
, TRUE);
2510 assertStringArg ("${i}_object_asset_no", __FUNCTION__
, TRUE);
2511 assertStringArg ("${i}_object_barcode", __FUNCTION__
, TRUE);
2512 $type_id[$i] = $_REQUEST["${i}_object_type_id"];
2513 // Save user input for possible rendering.
2514 $name[$i] = $_REQUEST["${i}_object_name"];
2515 $label[$i] = $_REQUEST["${i}_object_label"];
2516 $asset_no[$i] = $_REQUEST["${i}_object_asset_no"];
2517 $barcode[$i] = $_REQUEST["${i}_object_barcode"];
2519 // It's better to skip silently, than to print a notice.
2520 if ($type_id[$i] == 0)
2522 if (commitAddObject ($name[$i], $label[$i], $barcode[$i], $type_id[$i], $asset_no[$i], $taglist) === TRUE)
2523 $log[] = array ('code' => 'success', 'message' => "Added new object '${name[$i]}'");
2525 $log[] = array ('code' => 'error', 'message' => __FUNCTION__
. ': commitAddObject() failed');
2528 elseif (isset ($_REQUEST['got_very_fast_data']))
2530 $taglist = isset ($_REQUEST['taglist']) ?
$_REQUEST['taglist'] : array();
2531 $keepvalues2 = TRUE;
2532 assertUIntArg ('global_type_id', __FUNCTION__
, TRUE);
2533 assertStringArg ('namelist', __FUNCTION__
, TRUE);
2534 $global_type_id = $_REQUEST['global_type_id'];
2535 if ($global_type_id == 0)
2537 if (!empty ($_REQUEST['namelist']))
2538 $log[] = array ('code' => 'error', 'message' => 'Object type is not selected, check the form below');
2540 $log[] = array ('code' => 'error', 'message' => 'Empty form has been ignored. Cheers.');
2544 // The name extractor below was stolen from ophandlers.php:addMultiPorts()
2545 $names1 = explode ('\n', $_REQUEST['namelist']);
2547 foreach ($names1 as $line)
2549 $parts = explode ('\r', $line);
2551 if (empty ($parts[0]))
2554 $names2[] = rtrim ($parts[0]);
2556 foreach ($names2 as $cname)
2557 if (commitAddObject ($cname, '', '', $global_type_id, '', $taglist) === TRUE)
2558 $log[] = array ('code' => 'success', 'message' => "Added new object '${cname}'");
2560 $log[] = array ('code' => 'error', 'message' => "Could not add '${cname}'");
2565 // Render a form for the next.
2566 $typelist = getObjectTypeList();
2567 $typelist[0] = 'select type...';
2569 startPortlet ('Distinct types, same tags');
2570 $max = getConfigVar ('MASSCOUNT');
2571 echo "<form name=fastform method=post action='${root}?page=${pageno}&tab=${tabno}'>";
2572 echo '<table border=0 align=center>';
2573 echo "<tr><th>Object type</th><th>Common name</th><th>Visible label</th>";
2574 echo "<th>Asset tag</th><th>Barcode</th><th>Tags</th></tr>\n";
2575 // If a user forgot to select object type on input, we keep his
2576 // previous input in the form.
2577 for ($i = 0; $i < $max; $i++
)
2580 // Don't employ DEFAULT_OBJECT_TYPE to avoid creating ghost records for pre-selected empty rows.
2581 printSelect ($typelist, "${i}_object_type_id", 0);
2583 echo "<td><input type=text size=30 name=${i}_object_name";
2584 if ($keepvalues1 and isset ($name[$i]) and (!isset ($type_id[$i]) or $type_id[$i] == 0))
2585 echo " value='${name[$i]}'";
2587 echo "<td><input type=text size=30 name=${i}_object_label";
2588 if ($keepvalues1 and isset ($label[$i]) and (!isset ($type_id[$i]) or $type_id[$i] == 0))
2589 echo " value='${label[$i]}'";
2591 echo "<td><input type=text size=20 name=${i}_object_asset_no";
2592 if ($keepvalues1 and isset ($asset_no[$i]) and (!isset ($type_id[$i]) or $type_id[$i] == 0))
2593 echo " value='${asset_no[$i]}'";
2595 echo "<td><input type=text size=10 name=${i}_object_barcode";
2596 if ($keepvalues1 and isset ($barcode[$i]) and (!isset ($type_id[$i]) or $type_id[$i] == 0))
2597 echo " value='${barcode[$i]}'";
2601 echo "<td valign=top rowspan=${max}>";
2607 echo "<tr><td class=submit colspan=5><input type=submit name=got_fast_data value='Go!'></td></tr>\n";
2608 echo "</form></table>\n";
2611 startPortlet ('Same type, same tags');
2612 echo "<form name=veryfastform method=post action='${root}?page=${pageno}&tab=${tabno}'>";
2613 echo "<table border=0 align=center><tr><th>names</th><th>type</th></tr>";
2614 echo "<tr><td rowspan=3><textarea name=namelist cols=40 rows=25>\n";
2615 if ($keepvalues2 and $global_type_id == 0)
2616 echo $_REQUEST['namelist'];
2617 echo "</textarea></td><td valign=top>";
2618 printSelect ($typelist, "global_type_id", getConfigVar ('DEFAULT_OBJECT_TYPE'));
2620 echo "<tr><th>Tags</th></tr>";
2621 echo "<tr><td valign=top>";
2624 echo "<tr><td colspan=2><input type=submit name=got_very_fast_data value='Go!'></td></tr></table>\n";
2629 function printGreeting ()
2631 global $remote_username, $accounts, $root;
2632 $account = $accounts[$remote_username];
2633 echo "Hello, ${account['user_realname']}. This is RackTables " . CODE_VERSION
. ". Click <a href='${root}?logout'>here</a> to logout.";
2636 function renderSearchResults ()
2638 global $remote_username, $root;
2639 $terms = trim ($_REQUEST['q']);
2642 showError ('Search string cannot be empty.', __FUNCTION__
);
2645 if (!permitted ('objects', 'default'))
2647 showError ('You are not authorized for viewing information about objects.', __FUNCTION__
);
2651 // If we search for L2 address, we can either find one or find none.
2654 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
2655 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
2656 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
2657 // STP bridge ID: bridge priotity + port MAC address. Cut off first 4 chars and look for MAC address.
2658 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)
2660 // Search for L2 address.
2662 $terms = str_replace ('.', '', $terms);
2663 $terms = str_replace (':', '', $terms);
2664 $terms = substr ($terms, -12);
2665 $result = searchByl2address ($terms);
2666 if ($result !== NULL)
2670 $summary['port'][] = $result;
2673 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))
2674 // Search for IP address.
2676 $result = getRangeByIp ($terms);
2677 if ($result !== NULL)
2680 $lasthit = 'ipv4address1';
2681 $summary['ipv4address1'][] = $terms;
2685 // Search for objects, addresses, networks, virtual services and RS pools by their description.
2687 $tmp = getObjectSearchResults ($terms);
2690 $nhits +
= count ($tmp);
2691 $lasthit = 'object';
2692 $summary['object'] = $tmp;
2694 $tmp = getIPv4AddressSearchResult ($terms);
2697 $nhits +
= count ($tmp);
2698 $lasthit = 'ipv4address2';
2699 $summary['ipv4address2'] = $tmp;
2701 $tmp = getIPv4PrefixSearchResult ($terms);
2704 $nhits +
= count ($tmp);
2705 $lasthit = 'ipv4network';
2706 $summary['ipv4network'] = $tmp;
2708 $tmp = getIPv4RSPoolSearchResult ($terms);
2711 $nhits +
= count ($tmp);
2712 $lasthit = 'ipv4rspool';
2713 $summary['ipv4rspool'] = $tmp;
2715 $tmp = getIPv4VServiceSearchResult ($terms);
2718 $nhits +
= count ($tmp);
2719 $lasthit = 'ipv4vs';
2720 $summary['ipv4vs'] = $tmp;
2722 $tmp = getAccountSearchResult ($terms);
2725 $nhits +
= count ($tmp);
2727 $summary['user'] = $tmp;
2731 echo "<center><h2>Nothing found for '${terms}'</h2></center>";
2732 elseif ($nhits == 1)
2734 $record = current ($summary[$lasthit]);
2738 echo "<script language='Javascript'>document.location='${root}?page=object";
2739 echo "&hl_port_id=" . $record['port_id'];
2740 echo "&object_id=" . $record['object_id'] . "';//</script>";
2742 case 'ipv4address1':
2743 echo "<script language='Javascript'>document.location='${root}?page=ipaddress";
2744 echo "&ip=${record}";
2745 echo "';//</script>";
2747 case 'ipv4address2':
2748 echo "<script language='Javascript'>document.location='${root}?page=ipaddress";
2749 echo "&ip=${record['ip']}";
2750 echo "';//</script>";
2753 echo "<script language='Javascript'>document.location='${root}?page=iprange";
2754 echo "&id=${record['id']}";
2755 echo "';//</script>";
2758 echo "<script language='Javascript'>document.location='${root}?page=object&object_id=${record['id']}';//</script>";
2761 echo "<script language='Javascript'>document.location='${root}?page=ipv4rsp&pool_id=${record['pool_id']}';//</script>";
2764 echo "<script language='Javascript'>document.location='${root}?page=ipv4vs&vs_id=${record['id']}';//</script>";
2767 echo "<script language='Javascript'>document.location='${root}?page=user&user_id=${record['user_id']}';//</script>";
2776 echo "<center><h2>${nhits} result(s) found for '${terms}'</h2></center>";
2777 foreach ($summary as $where => $what)
2781 startPortlet ("<a href='${root}?page=objects'>Objects</a>");
2782 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
2783 echo '<tr><th>Common name</th><th>Visible label</th><th>Asset tag</th><th>barcode</th></tr>';
2784 foreach ($what as $obj)
2786 echo "<tr class=row_${order}><td><a href=\"${root}?page=object&object_id=${obj['id']}\">${obj['dname']}</a></td>";
2787 echo "<td>${obj['label']}</td>";
2788 echo "<td>${obj['asset_no']}</td>";
2789 echo "<td>${obj['barcode']}</td></tr>";
2790 $order = $nextorder[$order];
2796 startPortlet ("<a href='${root}?page=ipv4space'>IPv4 networks</a>");
2797 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
2798 echo '<tr><th>Network</th><th>Descritpion</th></tr>';
2799 foreach ($what as $net)
2801 echo "<tr class=row_${order}><td class=tdleft><a href='${root}?page=iprange&id=${net['id']}'>${net['ip']}";
2802 echo '/' . $net['mask'] . '</a></td>';
2803 echo "<td class=tdleft>${net['name']}</td></tr>";
2804 $order = $nextorder[$order];
2809 case 'ipv4address2':
2810 startPortlet ('IPv4 addresses');
2811 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
2812 echo '<tr><th>Address</th><th>Descritpion</th></tr>';
2813 foreach ($what as $addr)
2815 echo "<tr class=row_${order}><td class=tdleft><a href='${root}?page=ipaddress&ip=${addr['ip']}'>";
2816 echo "${addr['ip']}</a></td>";
2817 echo "<td class=tdleft>${addr['name']}</td></tr>";
2818 $order = $nextorder[$order];
2824 startPortlet ("<a href='${root}?page=ipv4rsplist'>RS pools</a>");
2825 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
2826 foreach ($what as $rspool)
2828 echo "<tr class=row_${order}><td class=tdleft><a href='${root}?page=ipv4rsp&pool_id=${rspool['pool_id']}'>";
2829 echo buildRSPoolName ($rspool);
2830 echo "</a></td></tr>";
2831 $order = $nextorder[$order];
2837 startPortlet ("<a href='${root}?page=ipv4vslist'>Virtual services</a>");
2838 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
2839 echo '<tr><th>VS</th><th>Descritpion</th></tr>';
2840 foreach ($what as $vs)
2842 echo "<tr class=row_${order}><td class=tdleft><a href='${root}?page=ipv4vs&vs_id=${vs['id']}'>";
2843 echo buildVServiceName ($vs);
2844 echo "</a></td><td class=tdleft>${vs['name']}</td></tr>";
2845 $order = $nextorder[$order];
2851 startPortlet ("<a href='${root}?page=userlist'>Users</a>");
2852 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
2853 echo '<tr><th>username</th><th>realname</th></tr>';
2854 foreach ($what as $item)
2856 echo "<tr class=row_${order}><td class=tdleft><a href='${root}?page=user&user_id=${item['user_id']}'>";
2857 echo $item['user_name'];
2858 echo "</a></td><td class=tdleft>${item['user_realname']}</td></tr>";
2859 $order = $nextorder[$order];
2868 // This function prints a table of checkboxes to aid the user in toggling mount atoms
2869 // from one state to another. The first argument is rack data as
2870 // produced by getRackData(), the second is the value used for the 'unckecked' state
2871 // and the third is the value used for 'checked' state.
2873 // for mounting an object: printAtomGrid ($data, 'F', 'T')
2874 // for changing rack design: printAtomGrid ($data, 'A', 'F')
2875 // for adding rack problem: printAtomGrid ($data, 'F', 'U')
2876 // for adding object problem: printAtomGrid ($data, 'T', 'W')
2878 function renderAtomGrid ($data)
2880 $rack_id = $data['id'];
2881 for ($unit_no = $data['height']; $unit_no > 0; $unit_no--)
2883 echo "<tr><th>${unit_no}</th>";
2884 for ($locidx = 0; $locidx < 3; $locidx++
)
2886 $state = $data[$unit_no][$locidx]['state'];
2887 echo "<td class=state_${state}";
2888 if (isset ($data[$unit_no][$locidx]['hl']))
2889 echo $data[$unit_no][$locidx]['hl'];
2891 if (!($data[$unit_no][$locidx]['enabled'] === TRUE))
2892 echo '<input type=checkbox disabled>';
2894 echo "<input type=checkbox" . $data[$unit_no][$locidx]['checked'] . " name=atom_${rack_id}_${unit_no}_${locidx}>";
2901 function renderUserList ()
2903 global $nextorder, $accounts, $root;
2904 echo "<table border=0 class=objectview>\n";
2905 echo "<tr><td class=pcleft>";
2906 startPortlet ('User accounts');
2907 echo "<table class=cooltable border=0 cellpadding=5 cellspacing=0 align=center>\n";
2908 echo "<tr><th class=tdleft>Username</th><th class=tdleft>Real name</th></tr>";
2910 $tagfilter = getTagFilter();
2911 foreach (getUserAccounts ($tagfilter, getTFMode()) as $user)
2913 echo "<tr class=row_${order}><td class=tdleft><a href='${root}?page=user&user_id=${user['user_id']}'>";
2914 echo "${user['user_name']}</a></td>";
2915 echo "<td class=tdleft>${user['user_realname']}</td></li>";
2916 $order = $nextorder[$order];
2920 echo '</td><td class=pcright>';
2921 renderTagFilterPortlet ($tagfilter, 'user');
2922 echo "</td></tr></table>\n";
2925 function renderUserListEditor ()
2927 global $root, $pageno, $tabno, $accounts;
2928 startPortlet ('User accounts');
2929 showMessageOrError();
2930 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable>\n";
2931 echo "<tr><th>status (click to change)</th><th>Username</th><th>Real name</th><th>Password</th><th> </th></tr>\n";
2932 foreach ($accounts as $account)
2934 echo "<form action='${root}process.php'>";
2935 echo "<input type=hidden name=op value=updateUser>";
2936 echo "<input type=hidden name=page value='${pageno}'>\n";
2937 echo "<input type=hidden name=tab value='${tabno}'>\n";
2938 echo "<input type=hidden name=user_id value='${account['user_id']}'><tr>";
2940 if ($account['user_enabled'] == 'yes' && $account['user_id'] != 1)
2942 echo "<a href='${root}process.php?op=disableUser&page=${pageno}&tab=${tabno}&user_id=${account['user_id']}'>";
2943 printImageHREF ('blockuser', 'disable account');
2946 if ($account['user_enabled'] == 'no' && $account['user_id'] != 1)
2948 echo "<a href='${root}process.php?op=enableUser&page=${pageno}&tab=${tabno}&user_id=${account['user_id']}'>";
2949 printImageHREF ('unblockuser', 'enable account');
2952 // Otherwise skip icon.
2954 echo "<td><input type=text name=username value='${account['user_name']}' size=16></td>";
2955 echo "<td><input type=text name=realname value='${account['user_realname']}' size=24></td>";
2956 echo "<td><input type=password name=password value='${account['user_password_hash']}' size=64></td><td>";
2957 printImageHREF ('save', 'Save changes', TRUE);
2958 echo "</td></form></tr>\n";
2960 echo "<form action='${root}process.php' method=post><tr>";
2961 echo "<input type=hidden name=op value=createUser>\n";
2962 echo "<input type=hidden name=page value='${pageno}'>\n";
2963 echo "<input type=hidden name=tab value='${tabno}'>\n";
2964 echo "<td> </td><td><input type=text size=16 name=username tabindex=100></td>\n";
2965 echo "<td><input type=text size=24 name=realname tabindex=101></td>";
2966 echo "<td><input type=password size=64 name=password tabindex=102></td><td>";
2967 printImageHREF ('create', 'Add new account', TRUE, 103);
2968 echo "</td></tr></form>";
2969 echo "</table><br>\n";
2973 function printChildrenAsOptions ($root, $depth = 0)
2975 echo "<option value=${root['title']}>";
2978 for ($i = 0; $i < $depth; $i++
)
2980 echo $root['title'];
2982 foreach ($root['kids'] as $kid)
2983 printChildrenAsOptions ($kid, $depth +
1);
2986 // 1. Find all parentless pages.
2987 // 2. For each of them recursively find all children.
2988 // 3. Output the tree with recursion tree display.
2989 function printPagesTree ()
2993 foreach ($page as $ctitle => $cpage)
2994 if (!isset ($cpage['parent']))
2996 $croot['title'] = $ctitle;
2997 $croot['kids'] = getAllChildPages ($ctitle);
2998 printChildrenAsOptions ($croot);
3003 function renderPortMapViewer ()
3005 renderPortMap (FALSE);
3008 function renderPortMapEditor ()
3010 renderPortMap (TRUE);
3013 function renderPortMap ($editable = FALSE)
3015 global $nextorder, $root, $pageno, $tabno;
3016 showMessageOrError();
3017 startPortlet ("Port compatibility map");
3018 $ptlist = getPortTypes();
3019 $pclist = getPortCompat();
3020 $pctable = buildPortCompatMatrixFromList ($ptlist, $pclist);
3023 echo "<form method=post action='${root}process.php'>";
3024 echo "<input type=hidden name=page value='${pageno}'>";
3025 echo "<input type=hidden name=tab value='${tabno}'>";
3026 echo "<input type=hidden name=op value=save>";
3028 echo "<table class=cooltable border=0 cellpadding=5 cellspacing=0 align=center>\n";
3029 echo "<tr><th class=vert_th> </th>";
3030 foreach ($ptlist as $name2)
3031 echo "<th>to ${name2}</th>";
3033 // Make a copy to have an independent array pointer.
3036 foreach ($ptlistY as $type1 => $name1)
3038 echo "<tr class=row_${order}><th class=vert_th style='border-bottom: 0px;'>from $name1</th>";
3039 foreach ($ptlist as $type2 => $name2)
3041 echo '<td' . ($pctable[$type1][$type2] ?
" class=portmap_highlight_$order" : '') . '>';
3042 echo '<input type=checkbox' . ($editable ?
" name=atom_${type1}_${type2}" : ' disabled');
3043 echo ($pctable[$type1][$type2] ?
' checked' : '') . '></td>';
3046 $order = $nextorder[$order];
3048 echo '</table><br>';
3051 echo "<input type=submit value='Save changes'>";
3057 function renderConfigMainpage ()
3059 global $pageno, $root;
3060 $children = getDirectChildPages ($pageno);
3062 // FIXME: assume all config kids to have static titles at the moment,
3063 // but use some proper abstract function later.
3064 foreach ($children as $cpageno => $child)
3065 echo "<li><a href='${root}?page=${cpageno}'>" . $child['title'] . "</li>\n";
3070 function renderRackPage ($rack_id)
3074 showError ('Invalid rack_id', __FUNCTION__
);
3077 if (($rackData = getRackData ($rack_id)) == NULL)
3079 showError ('getRackData() failed', __FUNCTION__
);
3082 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0><tr>";
3084 // Left column with information.
3085 echo "<td class=pcleft>";
3086 renderRackInfoPortlet ($rackData);
3089 // Right column with rendered rack.
3091 startPortlet ('Rack diagram');
3092 renderRack ($rack_id);
3096 echo '</tr></table>';
3099 function renderDictionary ()
3102 $dict = getDict (TRUE);
3103 echo "<br><table class=cooltable border=0 cellpadding=5 cellspacing=0 align=center>\n";
3104 foreach ($dict as $chapter_no => $chapter)
3107 echo "<tr><th>Chapter</th><th>refs</th><th>Word</th></tr>\n";
3108 $wc = count ($chapter['word']);
3109 echo "<tr class=row_${order}><td class=tdleft" . ($wc ?
" rowspan = ${wc}" : '');
3110 echo "><div title='number=${chapter_no}'>${chapter['name']} (${wc} records)</div></td>";
3112 echo "<td colspan=2>none</td>";
3116 foreach ($chapter['word'] as $key => $value)
3119 echo "<tr class=row_${order}>";
3121 $chap_start = FALSE;
3122 echo '<td>' . ($chapter['refcnt'][$key] ?
$chapter['refcnt'][$key] : ' ') . '</td>';
3123 echo "<td><div title='key=${key}'>${value}</div></td></tr>\n";
3124 $order = $nextorder[$order];
3128 echo "</table>\n<br>";
3131 function renderDictionaryEditor ()
3133 global $root, $pageno, $tabno, $nextorder;
3135 showMessageOrError();
3136 echo "<br><table class=cooltable border=0 cellpadding=5 cellspacing=0 align=center>\n";
3137 foreach ($dict as $chapter_no => $chapter)
3140 echo "<tr><th>Chapter</th><th> </th><th>Word</th><th> </th></tr>\n";
3141 $wc = count ($chapter['word']);
3142 // One extra span for the new record per each chapter block.
3143 echo "<tr class=row_${order}><td class=tdleft" . ($wc ?
' rowspan = ' . ($wc +
1) : '');
3144 echo "><div title='number=${chapter_no}'>${chapter['name']} (${wc} records)</div></td>";
3145 echo "<form action='${root}process.php' method=post>";
3146 echo "<input type=hidden name=page value='${pageno}'>";
3147 echo "<input type=hidden name=tab value='${tabno}'>";
3148 echo "<input type=hidden name=op value=add>";
3149 echo "<input type=hidden name=chapter_no value='${chapter['no']}'>";
3150 echo "<td> </td>";
3151 echo "<td class=tdright><input type=text name=dict_value size=32></td>";
3152 echo "<td><input type=submit value='Add new'></td>";
3153 echo '</tr></form>';
3154 $order = $nextorder[$order];
3155 foreach ($chapter['word'] as $key => $value)
3157 echo "<form action='${root}process.php' method=post>";
3158 echo "<input type=hidden name=page value='${pageno}'>";
3159 echo "<input type=hidden name=tab value='${tabno}'>";
3160 echo "<input type=hidden name=op value='upd'>";
3161 echo "<input type=hidden name=chapter_no value='${chapter['no']}'>";
3162 echo "<input type=hidden name=dict_key value='${key}'>";
3163 echo "<tr class=row_${order}><td>";
3164 // Prevent deleting words currently used somewhere.
3165 if ($chapter['refcnt'][$key])
3166 printImageHREF ('nodelete', 'referenced ' . $chapter['refcnt'][$key] . ' time(s)');
3169 echo "<a href='${root}process.php?page=${pageno}&tab=${tabno}&op=del&chapter_no=${chapter['no']}&dict_key=${key}'>";
3170 printImageHREF ('delete', 'Delete word');
3174 echo "<td class=tdright><input type=text name=dict_value size=32 value='${value}'></td>";
3175 echo "<td><input type=submit value=OK></td>";
3176 echo "</tr></form>\n";
3177 $order = $nextorder[$order];
3178 } // foreach ($chapter['word']
3183 // We don't allow to rename/delete a sticky chapter and we don't allow
3184 // to delete a non-empty chapter.
3185 function renderChaptersEditor ()
3187 global $root, $pageno, $tabno;
3188 showMessageOrError();
3190 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable>\n";
3191 echo '<tr><th> </th><th>Chapter name</th><th>Words</th><th> </th></tr>';
3192 foreach ($dict as $chapter)
3194 $wordcount = count ($chapter['word']);
3195 $sticky = $chapter['sticky'];
3196 echo "<form action='${root}process.php' method=post>";
3197 echo "<input type=hidden name=page value='${pageno}'>";
3198 echo "<input type=hidden name=tab value='${tabno}'>";
3199 echo "<input type=hidden name=op value=upd>";
3200 echo "<input type=hidden name=chapter_no value='${chapter['no']}'>";
3204 printImageHREF ('nodelete', 'system chapter');
3205 elseif ($wordcount > 0)
3206 printImageHREF ('nodelete', 'contains ' . $wordcount . ' word(s)');
3209 echo "<a href='${root}process.php?page=${pageno}&tab=${tabno}&op=del&chapter_no=${chapter['no']}'>";
3210 printImageHREF ('delete', 'Remove chapter');
3214 echo "<td><input type=text name=chapter_name value='${chapter['name']}'" . ($sticky ?
' disabled' : '') . "></td>";
3215 echo "<td class=tdleft>${wordcount}</td><td>";
3219 echo "<input type=submit value='OK'>";