r4188 update: UI: ability to clear object ports list at one blow
[racktables] / inc / ophandlers.php
index e2934d5..9545734 100644 (file)
@@ -5,9 +5,383 @@
 *
 */
 
+// This array is deprecated. Please do not add new message constants to it.
+// use the new showError, showWarning, showSuccess functions instead
+global $msgcode;
 $msgcode = array();
 
-function buildWideRedirectURL ($log, $nextpage = NULL, $nexttab = NULL, $moreArgs = array())
+global $opspec_list;
+$opspec_list = array();
+
+$opspec_list['rackspace-edit-addRow'] = array
+(
+       'table' => 'RackRow',
+       'action' => 'INSERT',
+       'arglist' => array
+       (
+               array ('url_argname' => 'name', 'assertion' => 'string')
+       ),
+);
+$opspec_list['rackspace-edit-delete'] = array
+(
+       'table' => 'RackRow',
+       'action' => 'DELETE',
+       'arglist' => array
+       (
+               array ('url_argname' => 'row_id', 'table_colname' => 'id', 'assertion' => 'uint')
+       ),
+);
+$opspec_list['rackspace-edit-updateRow'] = array
+(
+       'table' => 'RackRow',
+       'action' => 'UPDATE',
+       'set_arglist' => array
+       (
+               array ('url_argname' => 'name', 'assertion' => 'string')
+       ),
+       'where_arglist' => array
+       (
+               array ('url_argname' => 'row_id', 'table_colname' => 'id', 'assertion' => 'uint')
+       ),
+);
+$opspec_list['object-ports-delPort'] = array
+(
+       'table' => 'Port',
+       'action' => 'DELETE',
+       'arglist' => array
+       (
+               array ('url_argname' => 'port_id', 'table_colname' => 'id', 'assertion' => 'uint'),
+               array ('url_argname' => 'object_id', 'assertion' => 'uint'),
+       ),
+);
+$opspec_list['object-ports-deleteAll'] = array
+(
+       'table' => 'Port',
+       'action' => 'DELETE',
+       'arglist' => array
+       (
+               array ('url_argname' => 'object_id', 'assertion' => 'uint'),
+       ),
+);
+$opspec_list['object-ports-unlinkPort'] = array
+(
+       'table' => 'Link',
+       'action' => 'DELETE',
+       'arglist' => array
+       (
+               array ('url_argname' => 'port_id', 'table_colname' => 'porta', 'assertion' => 'uint'),
+               array ('url_argname' => 'port_id', 'table_colname' => 'portb', 'assertion' => 'uint'),
+       ),
+       'conjunction' => 'OR',
+);
+$opspec_list['object-log-del'] = array
+(
+       'table' => 'ObjectLog',
+       'action' => 'DELETE',
+       'arglist' => array
+       (
+               array ('url_argname' => 'logid', 'table_colname' => 'id', 'assertion' => 'uint'),
+               array ('url_argname' => 'object_id', 'assertion' => 'uint'),
+       ),
+);
+$opspec_list['ipv4vs-editlblist-delLB'] =
+$opspec_list['ipv4rspool-editlblist-delLB'] =
+$opspec_list['object-editrspvs-delLB'] = array
+(
+       'table' => 'IPv4LB',
+       'action' => 'DELETE',
+       'arglist' => array
+       (
+               array ('url_argname' => 'object_id', 'assertion' => 'uint'),
+               array ('url_argname' => 'pool_id', 'table_colname' => 'rspool_id', 'assertion' => 'uint'),
+               array ('url_argname' => 'vs_id', 'assertion' => 'uint'),
+       ),
+);
+$opspec_list['ipv4vs-editlblist-updLB'] =
+$opspec_list['ipv4rspool-editlblist-updLB'] =
+$opspec_list['object-editrspvs-updLB'] = array
+(
+       'table' => 'IPv4LB',
+       'action' => 'UPDATE',
+       'set_arglist' => array
+       (
+               array ('url_argname' => 'vsconfig', 'assertion' => 'string0', 'if_empty' => 'NULL'),
+               array ('url_argname' => 'rsconfig', 'assertion' => 'string0', 'if_empty' => 'NULL'),
+               array ('url_argname' => 'prio', 'assertion' => 'uint0', 'if_empty' => 'NULL'),
+       ),
+       'where_arglist' => array
+       (
+               array ('url_argname' => 'object_id', 'assertion' => 'uint'),
+               array ('url_argname' => 'pool_id', 'table_colname' => 'rspool_id', 'assertion' => 'uint'),
+               array ('url_argname' => 'vs_id', 'assertion' => 'uint'),
+       ),
+);
+$opspec_list['ipv4net-properties-editRange'] = array
+(
+       'table' => 'IPv4Network',
+       'action' => 'UPDATE',
+       'set_arglist' => array
+       (
+               array ('url_argname' => 'name', 'assertion' => 'string0'),
+               array ('url_argname' => 'comment', 'assertion' => 'string0'),
+       ),
+       'where_arglist' => array
+       (
+               array ('url_argname' => 'id', 'assertion' => 'uint')
+       ),
+);
+$opspec_list['ipv6net-properties-editRange'] = array
+(
+       'table' => 'IPv6Network',
+       'action' => 'UPDATE',
+       'set_arglist' => array
+       (
+               array ('url_argname' => 'name', 'assertion' => 'string0'),
+               array ('url_argname' => 'comment', 'assertion' => 'string0'),
+       ),
+       'where_arglist' => array
+       (
+               array ('url_argname' => 'id', 'assertion' => 'uint')
+       ),
+);
+$opspec_list['ipv4rspool-editrslist-delRS'] = array
+(
+       'table' => 'IPv4RS',
+       'action' => 'DELETE',
+       'arglist' => array
+       (
+               array ('url_argname' => 'id', 'assertion' => 'uint'),
+       ),
+);
+$opspec_list['ipv4rspool-edit-updIPv4RSP'] = array
+(
+       'table' => 'IPv4RSPool',
+       'action' => 'UPDATE',
+       'set_arglist' => array
+       (
+               array ('url_argname' => 'name', 'assertion' => 'string0', 'if_empty' => 'NULL'),
+               array ('url_argname' => 'vsconfig', 'assertion' => 'string0', 'if_empty' => 'NULL'),
+               array ('url_argname' => 'rsconfig', 'assertion' => 'string0', 'if_empty' => 'NULL'),
+       ),
+       'where_arglist' => array
+       (
+               array ('url_argname' => 'pool_id', 'table_colname' => 'id', 'assertion' => 'uint')
+       ),
+);
+$opspec_list['file-edit-updateFile'] = array
+(
+       'table' => 'File',
+       'action' => 'UPDATE',
+       'set_arglist' => array
+       (
+               array ('url_argname' => 'file_name', 'table_colname' => 'name', 'assertion' => 'string'),
+               array ('url_argname' => 'file_type', 'table_colname' => 'type', 'assertion' => 'string'),
+               array ('url_argname' => 'file_comment', 'table_colname' => 'comment', 'assertion' => 'string0', 'if_empty' => 'NULL'),
+       ),
+       'where_arglist' => array
+       (
+               array ('url_argname' => 'file_id', 'table_colname' => 'id', 'assertion' => 'uint')
+       ),
+);
+$opspec_list['parentmap-edit-add'] = array
+(
+       'table' => 'ObjectParentCompat',
+       'action' => 'INSERT',
+       'arglist' => array
+       (
+               array ('url_argname' => 'parent_objtype_id', 'assertion' => 'uint'),
+               array ('url_argname' => 'child_objtype_id', 'assertion' => 'uint'),
+       ),
+);
+$opspec_list['parentmap-edit-del'] = array
+(
+       'table' => 'ObjectParentCompat',
+       'action' => 'DELETE',
+       'arglist' => array
+       (
+               array ('url_argname' => 'parent_objtype_id', 'assertion' => 'uint'),
+               array ('url_argname' => 'child_objtype_id', 'assertion' => 'uint'),
+       ),
+);
+$opspec_list['portmap-edit-add'] = array
+(
+       'table' => 'PortCompat',
+       'action' => 'INSERT',
+       'arglist' => array
+       (
+               array ('url_argname' => 'type1', 'assertion' => 'uint'),
+               array ('url_argname' => 'type2', 'assertion' => 'uint'),
+       ),
+);
+$opspec_list['portmap-edit-del'] = array
+(
+       'table' => 'PortCompat',
+       'action' => 'DELETE',
+       'arglist' => array
+       (
+               array ('url_argname' => 'type1', 'assertion' => 'uint'),
+               array ('url_argname' => 'type2', 'assertion' => 'uint'),
+       ),
+);
+$opspec_list['portifcompat-edit-del'] = array
+(
+       'table' => 'PortInterfaceCompat',
+       'action' => 'DELETE',
+       'arglist' => array
+       (
+               array ('url_argname' => 'iif_id', 'assertion' => 'uint'),
+               array ('url_argname' => 'oif_id', 'assertion' => 'uint'),
+       ),
+);
+$opspec_list['attrs-editmap-del'] = array
+(
+       'table' => 'AttributeMap',
+       'action' => 'DELETE',
+       'arglist' => array
+       (
+               array ('url_argname' => 'attr_id', 'assertion' => 'uint'),
+               array ('url_argname' => 'objtype_id', 'assertion' => 'uint'),
+       ),
+);
+$opspec_list['attrs-editattrs-add'] = array
+(
+       'table' => 'Attribute',
+       'action' => 'INSERT',
+       'arglist' => array
+       (
+               array ('url_argname' => 'attr_type', 'table_colname' => 'type', 'assertion' => 'enum/attr_type'),
+               array ('url_argname' => 'attr_name', 'table_colname' => 'name', 'assertion' => 'string'),
+       ),
+);
+$opspec_list['attrs-editattrs-del'] = array
+(
+       'table' => 'Attribute',
+       'action' => 'DELETE',
+       'arglist' => array
+       (
+               array ('url_argname' => 'attr_id', 'table_colname' => 'id', 'assertion' => 'uint'),
+       ),
+);
+$opspec_list['attrs-editattrs-upd'] = array
+(
+       'table' => 'Attribute',
+       'action' => 'UPDATE',
+       'set_arglist' => array
+       (
+               array ('url_argname' => 'attr_name', 'table_colname' => 'name', 'assertion' => 'string'),
+       ),
+       'where_arglist' => array
+       (
+               array ('url_argname' => 'attr_id', 'table_colname' => 'id', 'assertion' => 'uint'),
+       ),
+);
+$opspec_list['dict-chapters-add'] = array
+(
+       'table' => 'Chapter',
+       'action' => 'INSERT',
+       'arglist' => array
+       (
+               array ('url_argname' => 'chapter_name', 'table_colname' => 'name', 'assertion' => 'string')
+       ),
+);
+$opspec_list['chapter-edit-add'] = array
+(
+       'table' => 'Dictionary',
+       'action' => 'INSERT',
+       'arglist' => array
+       (
+               array ('url_argname' => 'chapter_no', 'table_colname' => 'chapter_id', 'assertion' => 'uint'),
+               array ('url_argname' => 'dict_value', 'assertion' => 'string'),
+       ),
+);
+$opspec_list['chapter-edit-del'] = array
+(
+       'table' => 'Dictionary',
+       'action' => 'DELETE',
+       'arglist' => array
+       (
+               // Technically dict_key is enough to delete, but including chapter_id into
+               // WHERE clause makes sure, that the action actually happends for the same
+               // chapter, which authorization was granted for.
+               array ('url_argname' => 'chapter_no', 'table_colname' => 'chapter_id', 'assertion' => 'uint'),
+               array ('url_argname' => 'dict_key', 'assertion' => 'uint'),
+       ),
+);
+$opspec_list['tagtree-edit-createTag'] = array
+(
+       'table' => 'TagTree',
+       'action' => 'INSERT',
+       'arglist' => array
+       (
+               array ('url_argname' => 'tag_name', 'table_colname' => 'tag', 'assertion' => 'tag'),
+               array ('url_argname' => 'parent_id', 'assertion' => 'uint0', 'if_empty' => 'NULL'),
+       ),
+);
+$opspec_list['tagtree-edit-destroyTag'] = array
+(
+       'table' => 'TagTree',
+       'action' => 'DELETE',
+       'arglist' => array
+       (
+               array ('url_argname' => 'tag_id', 'table_colname' => 'id', 'assertion' => 'uint'),
+       ),
+);
+$opspec_list['tagtree-edit-updateTag'] = array
+(
+       'table' => 'TagTree',
+       'action' => 'UPDATE',
+       'set_arglist' => array
+       (
+               array ('url_argname' => 'tag_name', 'table_colname' => 'tag', 'assertion' => 'tag'),
+               array ('url_argname' => 'parent_id', 'assertion' => 'uint0', 'if_empty' => 'NULL'),
+       ),
+       'where_arglist' => array
+       (
+               array ('url_argname' => 'tag_id', 'table_colname' => 'id', 'assertion' => 'uint'),
+       ),
+);
+$opspec_list['8021q-vstlist-upd'] = array
+(
+       'table' => 'VLANSwitchTemplate',
+       'action' => 'UPDATE',
+       'set_arglist' => array
+       (
+               array ('url_argname' => 'vst_descr', 'table_colname' => 'description', 'assertion' => 'string'),
+       ),
+       'where_arglist' => array
+       (
+               array ('url_argname' => 'vst_id', 'table_colname' => 'id', 'assertion' => 'uint'),
+       ),
+);
+$opspec_list['8021q-vdlist-upd'] = array
+(
+       'table' => 'VLANDomain',
+       'action' => 'UPDATE',
+       'set_arglist' => array
+       (
+               array ('url_argname' => 'vdom_descr', 'table_colname' => 'description', 'assertion' => 'string'),
+       ),
+       'where_arglist' => array
+       (
+               array ('url_argname' => 'vdom_id', 'table_colname' => 'id', 'assertion' => 'uint'),
+       ),
+);
+$opspec_list['vlandomain-vlanlist-add'] = array
+(
+       'table' => 'VLANDescription',
+       'action' => 'INSERT',
+       'arglist' => array
+       (
+               array ('url_argname' => 'vdom_id', 'table_colname' => 'domain_id', 'assertion' => 'uint'),
+               array ('url_argname' => 'vlan_id', 'assertion' => 'uint'),
+               array ('url_argname' => 'vlan_type', 'assertion' => 'enum/vlan_type'),
+               array ('url_argname' => 'vlan_descr', 'assertion' => 'string0', 'if_empty' => 'NULL'),
+       ),
+);
+
+// This function is DEPRECATED. Show messages through showError and showSuccess,
+// you dont need to return anything from an ophandler to redirect user back to the page containing submit form
+function buildWideRedirectURL ($log = NULL, $nextpage = NULL, $nexttab = NULL, $moreArgs = array())
 {
        global $page, $pageno, $tabno;
        if ($nextpage === NULL)
@@ -18,26 +392,56 @@ function buildWideRedirectURL ($log, $nextpage = NULL, $nexttab = NULL, $moreArg
        if (isset ($page[$nextpage]['bypass']))
                $url .= '&' . $page[$nextpage]['bypass'] . '=' . $_REQUEST[$page[$nextpage]['bypass']];
 
-       if (count($moreArgs)>0)
+       if (count ($moreArgs) > 0)
+               foreach ($moreArgs as $arg => $value)
+                       if (gettype ($value) != 'array')
+                               $url .= '&' . urlencode ($arg) . '=' . urlencode ($value);
+                       else
+                               foreach ($value as $v)
+                                       $url .= '&' . urlencode ($arg . '[]') . '=' . urlencode ($v);
+
+       if (! empty ($log))
        {
-               foreach($moreArgs as $arg=>$value)
+               if (empty ($_SESSION['log']))
+                       $_SESSION['log'] = $log;
+               elseif ($_SESSION['log']['v'] == $log['v'])
+                       $_SESSION['log'] = array_merge_recursive($log, $_SESSION['log']);
+               elseif ($log['v'] == 1 and $_SESSION['log']['v'] == 2)
+                       foreach ($log['m'] as $msg)
+                               setMessage ($msg['code'], $msg['message'], FALSE);
+               elseif ($log['v'] == 2 and $_SESSION['log']['v'] == 1)
                {
-                       if (gettype($value) == 'array')
+                       foreach ($_SESSION['log'] as $msg)
                        {
-                               foreach ($value as $v)
+                               if (! is_array ($msg))
+                                       continue;
+                               var_dump ($msg);
+                               $new_v2_item = array('c' => '', 'a' => array());
+                               switch ($msg['code'])
                                {
-                                       $url .= '&'.urlencode($arg.'[]').'='.urlencode($v);
+                                       case 'error':
+                                               $new_v2_item['c'] = 100;
+                                               break;
+                                       case 'success':
+                                               $new_v2_item['c'] = 0;
+                                               break;
+                                       case 'warning':
+                                               $new_v2_item['c'] = 200;
+                                               break;
+                                       default:
+                                               $new_v2_item['c'] = 300;
                                }
+                               $new_v2_item['a'][] = $msg['message'];
+                               $log['m'][] = $new_v2_item;
                        }
-                       else
-                               $url .= '&'.urlencode($arg).'='.urlencode($value);
+                       $_SESSION['log'] = $log; // substitute v1 log structure with merged v2
                }
        }
-
-       $_SESSION['log'] = $log;
        return $url;
 }
 
+// This function is DEPRECATED. Show messages through showError and showSuccess,
+// you dont need to return anything from an ophandler to redirect user back to the page containing submit form
 function buildRedirectURL ($callfunc, $status, $log_args = array(), $nextpage = NULL, $nexttab = NULL, $url_args = array())
 {
        global $pageno, $tabno, $msgcode;
@@ -48,7 +452,7 @@ function buildRedirectURL ($callfunc, $status, $log_args = array(), $nextpage =
        return buildWideRedirectURL (oneLiner ($msgcode[$callfunc][$status], $log_args), $nextpage, $nexttab, $url_args);
 }
 
-$msgcode['addPortForwarding']['OK'] = 2;
+$msgcode['addPortForwarding']['OK'] = 48;
 $msgcode['addPortForwarding']['ERR'] = 100;
 function addPortForwarding ()
 {
@@ -79,7 +483,7 @@ function addPortForwarding ()
                return buildRedirectURL (__FUNCTION__, 'ERR', array ($error));
 }
 
-$msgcode['delPortForwarding']['OK'] = 3;
+$msgcode['delPortForwarding']['OK'] = 49;
 $msgcode['delPortForwarding']['ERR'] = 111;
 function delPortForwarding ()
 {
@@ -102,7 +506,7 @@ function delPortForwarding ()
        buildRedirectURL (__FUNCTION__, $result !== FALSE ? 'OK' : 'ERR');
 }
 
-$msgcode['updPortForwarding']['OK'] = 4;
+$msgcode['updPortForwarding']['OK'] = 51;
 $msgcode['updPortForwarding']['ERR'] = 109;
 function updPortForwarding ()
 {
@@ -127,16 +531,13 @@ function updPortForwarding ()
        buildRedirectURL (__FUNCTION__, $result !== FALSE ? 'OK' : 'ERR');
 }
 
-$msgcode['addPortForObject']['OK'] = 5;
-$msgcode['addPortForObject']['ERR1'] = 101;
-$msgcode['addPortForObject']['ERR2'] = 100;
+$msgcode['addPortForObject']['OK'] = 48;
 function addPortForObject ()
 {
-       assertUIntArg ('object_id');
        assertStringArg ('port_name', TRUE);
-       if (!strlen ($_REQUEST['port_name']))
-               return buildRedirectURL (__FUNCTION__, 'ERR1');
-       $error = commitAddPort
+       genericAssertion ('port_l2address', 'l2address0');
+       genericAssertion ('port_name', 'string');
+       commitAddPort
        (
                $_REQUEST['object_id'],
                trim ($_REQUEST['port_name']),
@@ -144,44 +545,20 @@ function addPortForObject ()
                trim ($_REQUEST['port_label']),
                trim ($_REQUEST['port_l2address'])
        );
-       if ($error != '')
-               return buildRedirectURL (__FUNCTION__, 'ERR2', array ($error));
-       else
-               return buildRedirectURL (__FUNCTION__, 'OK', array ($_REQUEST['port_name']));
+       return buildRedirectURL (__FUNCTION__, 'OK', array ($_REQUEST['port_name']));
 }
 
 $msgcode['editPortForObject']['OK'] = 6;
-$msgcode['editPortForObject']['ERR1'] = 101;
-$msgcode['editPortForObject']['ERR2'] = 100;
 function editPortForObject ()
 {
-       assertUIntArg ('object_id');
+       global $sic;
        assertUIntArg ('port_id');
        assertUIntArg ('port_type_id');
        assertStringArg ('reservation_comment', TRUE);
-       // tolerate empty value now to produce custom informative message later
-       assertStringArg ('name', TRUE);
-       if (!strlen ($_REQUEST['name']))
-               return buildRedirectURL (__FUNCTION__, 'ERR1');
-
-       $error = commitUpdatePort ($_REQUEST['object_id'], $_REQUEST['port_id'], $_REQUEST['name'], $_REQUEST['port_type_id'], $_REQUEST['label'], $_REQUEST['l2address'], $_REQUEST['reservation_comment']);
-       if ($error != '')
-               return buildRedirectURL (__FUNCTION__, 'ERR2', array ($error));
-       else
-               return buildRedirectURL (__FUNCTION__, 'OK', array ($_REQUEST['name']));
-}
-
-$msgcode['delPortFromObject']['OK'] = 7;
-$msgcode['delPortFromObject']['ERR'] = 100;
-function delPortFromObject ()
-{
-       assertUIntArg ('port_id');
-       $error = delObjectPort ($_REQUEST['port_id']);
-
-       if ($error != '')
-               return buildRedirectURL (__FUNCTION__, 'ERR', array ($error));
-       else
-               return buildRedirectURL (__FUNCTION__, 'OK', array ($_REQUEST['port_name']));
+       genericAssertion ('l2address', 'l2address0');
+       genericAssertion ('name', 'string');
+       commitUpdatePort ($sic['object_id'], $sic['port_id'], $sic['name'], $sic['port_type_id'], $sic['label'], $sic['l2address'], $sic['reservation_comment']);
+       return buildRedirectURL (__FUNCTION__, 'OK', array ($_REQUEST['name']));
 }
 
 $msgcode['linkPortForObject']['OK'] = 8;
@@ -190,9 +567,10 @@ function linkPortForObject ()
 {
        assertUIntArg ('port_id');
        assertUIntArg ('remote_port_id');
+       assertStringArg ('cable', TRUE);
 
        // FIXME: ensure, that at least one of these ports belongs to the current object
-       $error = linkPorts ($_REQUEST['port_id'], $_REQUEST['remote_port_id']);
+       $error = linkPorts ($_REQUEST['port_id'], $_REQUEST['remote_port_id'], $_REQUEST['cable']);
        if ($error != '')
                return buildRedirectURL (__FUNCTION__, 'ERR', array ($error));
        global $sic;
@@ -212,33 +590,6 @@ function linkPortForObject ()
        );
 }
 
-$msgcode['unlinkPortForObject']['OK'] = 9;
-$msgcode['unlinkPortForObject']['ERR'] = 100;
-function unlinkPortForObject ()
-{
-       assertUIntArg ('port_id');
-       assertUIntArg ('remote_port_id');
-
-       global $sic;
-       $local_port_info = getPortInfo ($sic['port_id']);
-       $remote_port_info = getPortInfo ($sic['remote_port_id']);
-       $remote_object = spotEntity ('object', $remote_port_info['object_id']);
-       $error = unlinkPort ($_REQUEST['port_id']);
-       if ($error != '')
-               return buildRedirectURL (__FUNCTION__, 'ERR', array ($error));
-       return buildRedirectURL
-       (
-               __FUNCTION__,
-               'OK',
-               array
-               (
-                       $local_port_info['name'],
-                       $remote_port_info['name'],
-                       $remote_object['dname'],
-               )
-       );
-}
-
 $msgcode['addMultiPorts']['OK'] = 10;
 $msgcode['addMultiPorts']['ERR'] = 123;
 function addMultiPorts ()
@@ -246,7 +597,6 @@ function addMultiPorts ()
        assertStringArg ('format');
        assertStringArg ('input');
        assertStringArg ('port_type');
-       assertUIntArg ('object_id');
        $format = $_REQUEST['format'];
        $port_type = $_REQUEST['port_type'];
        $object_id = $_REQUEST['object_id'];
@@ -334,19 +684,13 @@ http://www.cisco.com/en/US/products/hw/routers/ps274/products_tech_note09186a008
                $port_ids = getPortIDs ($object_id, $port['name']);
                if (!count ($port_ids))
                {
-                       $result = commitAddPort ($object_id, $port['name'], $port_type, $port['label'], $port['l2address']);
-                       if ($result == '')
-                               $added_count++;
-                       else
-                               $error_count++;
+                       commitAddPort ($object_id, $port['name'], $port_type, $port['label'], $port['l2address']);
+                       $added_count++;
                }
                elseif (count ($port_ids) == 1) // update only single-socket ports
                {
-                       $result = commitUpdatePort ($object_id, $port_ids[0], $port['name'], $port_type, $port['label'], $port['l2address']);
-                       if ($result == '')
-                               $updated_count++;
-                       else
-                               $error_count++;
+                       commitUpdatePort ($object_id, $port_ids[0], $port['name'], $port_type, $port['label'], $port['l2address']);
+                       $updated_count++;
                }
        }
        return buildRedirectURL (__FUNCTION__, 'OK', array ($added_count, $updated_count, $error_count));
@@ -355,11 +699,10 @@ http://www.cisco.com/en/US/products/hw/routers/ps274/products_tech_note09186a008
 $msgcode['addBulkPorts']['OK'] = 82;
 function addBulkPorts ()
 {
-       assertUIntArg ('object_id');
        assertStringArg ('port_type_id');
        assertStringArg ('port_name');
        assertStringArg ('port_label', TRUE);
-       assertUIntArg ('port_numbering_start');
+       assertUIntArg ('port_numbering_start', TRUE);
        assertUIntArg ('port_numbering_count');
        
        $object_id = $_REQUEST['object_id'];
@@ -374,29 +717,39 @@ function addBulkPorts ()
                $port_name .= '%u';
        for ($i=0,$c=$port_numbering_start; $i<$port_numbering_count; $i++,$c++)
        {
-               $result = commitAddPort ($object_id, @sprintf($port_name,$c), $port_type_id, @sprintf($port_label,$c), '');
-               if ($result == '')
-                       $added_count++;
-               else
-                       $error_count++;
+               commitAddPort ($object_id, @sprintf($port_name,$c), $port_type_id, @sprintf($port_label,$c), '');
+               $added_count++;
        }
        return buildRedirectURL (__FUNCTION__, 'OK', array ($added_count, $error_count));
 }
 
-$msgcode['updIPv4Allocation']['OK'] = 12;
+$msgcode['updIPv4Allocation']['OK'] = 51;
 $msgcode['updIPv4Allocation']['ERR'] = 109;
 function updIPv4Allocation ()
 {
        assertIPv4Arg ('ip');
        assertUIntArg ('object_id');
        assertStringArg ('bond_name', TRUE);
-       assertStringArg ('bond_type');
+       genericAssertion ('bond_type', 'enum/inet4alloc');
 
        $result = updateBond ($_REQUEST['ip'], $_REQUEST['object_id'], $_REQUEST['bond_name'], $_REQUEST['bond_type']);
        return buildRedirectURL (__FUNCTION__, $result === FALSE ? 'ERR' : 'OK');
 }
 
-$msgcode['delIPv4Allocation']['OK'] = 14;
+$msgcode['updIPv6Allocation']['OK'] = 51;
+$msgcode['updIv6PAllocation']['ERR'] = 109;
+function updIPv6Allocation ()
+{
+       $ipv6 = assertIPv6Arg ('ip');
+       assertUIntArg ('object_id');
+       assertStringArg ('bond_name', TRUE);
+       genericAssertion ('bond_type', 'enum/inet6alloc');
+
+       $result = updateIPv6Bond ($ipv6, $_REQUEST['object_id'], $_REQUEST['bond_name'], $_REQUEST['bond_type']);
+       return buildRedirectURL (__FUNCTION__, $result === FALSE ? 'ERR' : 'OK');
+}
+
+$msgcode['delIPv4Allocation']['OK'] = 49;
 $msgcode['delIPv4Allocation']['ERR'] = 111;
 function delIPv4Allocation ()
 {
@@ -407,7 +760,17 @@ function delIPv4Allocation ()
        return buildRedirectURL (__FUNCTION__, $result === FALSE ? 'ERR' : 'OK');
 }
 
-$msgcode['addIPv4Allocation']['OK'] = 13;
+$msgcode['delIPv6Allocation']['OK'] = 49;
+$msgcode['delIPv6Allocation']['ERR'] = 111;
+function delIPv6Allocation ()
+{
+       assertUIntArg ('object_id');
+       $ipv6 = assertIPv6Arg ('ip');
+       $result = unbindIPv6FromObject ($ipv6, $_REQUEST['object_id']);
+       return buildRedirectURL (__FUNCTION__, $result === FALSE ? 'ERR' : 'OK');
+}
+
+$msgcode['addIPv4Allocation']['OK'] = 48;
 $msgcode['addIPv4Allocation']['ERR1'] = 170;
 $msgcode['addIPv4Allocation']['ERR2'] = 100;
 function addIPv4Allocation ()
@@ -415,7 +778,7 @@ function addIPv4Allocation ()
        assertIPv4Arg ('ip');
        assertUIntArg ('object_id');
        assertStringArg ('bond_name', TRUE);
-       assertStringArg ('bond_type');
+       genericAssertion ('bond_type', 'enum/inet4alloc');
 
        // Strip masklen.
        $ip = preg_replace ('@/[[:digit:]]+$@', '', $_REQUEST['ip']);
@@ -437,12 +800,39 @@ function addIPv4Allocation ()
        return buildRedirectURL (__FUNCTION__, 'OK');
 }
 
-$msgcode['addIPv4Prefix']['OK'] = 23;
-$msgcode['addIPv4Prefix']['ERR'] = 100;
-$msgcode['addIPv4Prefix']['ERR1'] = 173;
-$msgcode['addIPv4Prefix']['ERR2'] = 174;
-$msgcode['addIPv4Prefix']['ERR3'] = 175;
-$msgcode['addIPv4Prefix']['ERR4'] = 176;
+$msgcode['addIPv6Allocation']['OK'] = 48;
+$msgcode['addIPv6Allocation']['ERR1'] = 170;
+$msgcode['addIPv6Allocation']['ERR2'] = 100;
+function addIPv6Allocation ()
+{
+       assertUIntArg ('object_id');
+       assertStringArg ('bond_name', TRUE);
+       genericAssertion ('bond_type', 'enum/inet6alloc');
+
+       // Strip masklen.
+       $ipv6 = new IPv6Address;
+       if (! $ipv6->parse (preg_replace ('@/\d+$@', '', $_REQUEST['ip'])))
+               throw new InvalidRequestArgException('ip', $_REQUEST['ip'], 'parameter is not a valid ipv6 address');
+
+       if  (getConfigVar ('IPV4_JAYWALK') != 'yes' and NULL === getIPv6AddressNetworkId ($ipv6))
+               return buildRedirectURL (__FUNCTION__, 'ERR1', array ($ip));
+
+       if (FALSE === bindIPv6ToObject ($ipv6, $_REQUEST['object_id'], $_REQUEST['bond_name'], $_REQUEST['bond_type']))
+               return buildRedirectURL (__FUNCTION__, 'ERR2', array ($error));
+       $address = getIPv6Address ($ipv6);
+       if ($address['reserved'] == 'yes' or strlen ($address['name']))
+       {
+               $release = getConfigVar ('IPV4_AUTO_RELEASE');
+               if ($release >= 1)
+                       $address['reserved'] = 'no';
+               if ($release >= 2)
+                       $address['name'] = '';
+               updateAddress ($ipv6, $address['name'], $address['reserved']);
+       }
+       return buildRedirectURL (__FUNCTION__, 'OK');
+}
+
+$msgcode['addIPv4Prefix']['OK'] = 48;
 function addIPv4Prefix ()
 {
        assertStringArg ('range');
@@ -451,42 +841,42 @@ function addIPv4Prefix ()
        $is_bcast = isset ($_REQUEST['is_bcast']) ? $_REQUEST['is_bcast'] : 'off';
        $taglist = isset ($_REQUEST['taglist']) ? $_REQUEST['taglist'] : array();
        global $sic;
-       $error = createIPv4Prefix ($_REQUEST['range'], $sic['name'], $is_bcast == 'on', $taglist);
-       if ($error != '')
-               return buildRedirectURL (__FUNCTION__, 'ERR', array ($error));
-       else
-               return buildRedirectURL (__FUNCTION__, 'OK');
+       createIPv4Prefix ($_REQUEST['range'], $sic['name'], $is_bcast == 'on', $taglist);
+       return buildRedirectURL (__FUNCTION__, 'OK');
+}
+
+$msgcode['addIPv6Prefix']['OK'] = 48;
+function addIPv6Prefix ()
+{
+       assertStringArg ('range');
+       assertStringArg ('name', TRUE);
+
+       $taglist = isset ($_REQUEST['taglist']) ? $_REQUEST['taglist'] : array();
+       global $sic;
+       createIPv6Prefix ($_REQUEST['range'], $sic['name'], $taglist);
+       return buildRedirectURL (__FUNCTION__, 'OK');
 }
 
-$msgcode['delIPv4Prefix']['OK'] = 24;
-$msgcode['delIPv4Prefix']['ERR'] = 100;
+$msgcode['delIPv4Prefix']['OK'] = 49;
 function delIPv4Prefix ()
 {
        assertUIntArg ('id');
-       $error = destroyIPv4Prefix ($_REQUEST['id']);
-       if ($error != '')
-               return buildRedirectURL (__FUNCTION__, 'ERR', array ($error));
-       else
-               return buildRedirectURL (__FUNCTION__, 'OK');
+       destroyIPv4Prefix ($_REQUEST['id']);
+       return buildRedirectURL (__FUNCTION__, 'OK');
 }
 
-$msgcode['updIPv4Prefix']['OK'] = 25;
-$msgcode['updIPv4Prefix']['ERR'] = 109;
-function updIPv4Prefix ()
+$msgcode['delIPv6Prefix']['OK'] = 49;
+function delIPv6Prefix ()
 {
        assertUIntArg ('id');
-       assertStringArg ('name', TRUE);
-       assertStringArg ('comment', TRUE);
-       global $sic;
-       $result = updateIPv4Network_real ($sic['id'], $sic['name'], $sic['comment']);
-       return buildRedirectURL (__FUNCTION__, $result !== FALSE ? 'OK' : 'ERR');
+       destroyIPv6Prefix ($_REQUEST['id']);
+       return buildRedirectURL (__FUNCTION__, 'OK');
 }
 
-$msgcode['editAddress']['OK'] = 27;
+$msgcode['editAddress']['OK'] = 51;
 $msgcode['editAddress']['ERR'] = 100;
 function editAddress ()
 {
-       assertIPv4Arg ('ip');
        assertStringArg ('name', TRUE);
 
        if (isset ($_REQUEST['reserved']))
@@ -500,7 +890,25 @@ function editAddress ()
                return buildRedirectURL (__FUNCTION__, 'OK');
 }
 
-$msgcode['createUser']['OK'] = 40;
+$msgcode['editv6Address']['OK'] = 51;
+$msgcode['editv6Address']['ERR'] = 100;
+function editv6Address ()
+{
+       $ipv6 = assertIPArg ('ip');
+       assertStringArg ('name', TRUE);
+
+       if (isset ($_REQUEST['reserved']))
+               $reserved = $_REQUEST['reserved'];
+       else
+               $reserved = 'off';
+       $error = updateAddress ($ipv6, $_REQUEST['name'], $reserved == 'on' ? 'yes' : 'no');
+       if ($error != '')
+               return buildRedirectURL (__FUNCTION__, 'ERR', array ($error));
+       else
+               return buildRedirectURL (__FUNCTION__, 'OK');
+}
+
+$msgcode['createUser']['OK'] = 5;
 $msgcode['createUser']['ERR'] = 102;
 function createUser ()
 {
@@ -517,19 +925,16 @@ function createUser ()
        return buildRedirectURL (__FUNCTION__, 'OK', array ($username));
 }
 
-$msgcode['updateUser']['OK'] = 39;
-$msgcode['updateUser']['ERR1'] = 103;
-$msgcode['updateUser']['ERR1'] = 104;
+$msgcode['updateUser']['OK'] = 6;
+$msgcode['updateUser']['ERR2'] = 104;
 function updateUser ()
 {
-       assertUIntArg ('user_id');
        assertStringArg ('username');
        assertStringArg ('realname', TRUE);
        assertStringArg ('password');
        $username = $_REQUEST['username'];
        $new_password = $_REQUEST['password'];
-       if (NULL == ($userinfo = spotEntity ('user', $_REQUEST['user_id'])))
-               return buildRedirectURL (__FUNCTION__, 'ERR1');
+       $userinfo = spotEntity ('user', $_REQUEST['user_id']);
        // Update user password only if provided password is not the same as current password hash.
        if ($new_password != $userinfo['user_password_hash'])
                $new_password = sha1 ($new_password);
@@ -541,67 +946,47 @@ function updateUser ()
 }
 
 $msgcode['updateDictionary']['OK'] = 51;
-$msgcode['updateDictionary']['ERR'] = 109;
 function updateDictionary ()
 {
-       assertUIntArg ('chapter_no');
        assertUIntArg ('dict_key');
        assertStringArg ('dict_value');
-       if (FALSE !== commitUpdateDictionary ($_REQUEST['chapter_no'], $_REQUEST['dict_key'], $_REQUEST['dict_value']))
-               return buildRedirectURL (__FUNCTION__, 'OK');
-       else
-               return buildRedirectURL (__FUNCTION__, 'ERR');
-}
-
-$msgcode['supplementDictionary']['OK'] = 52;
-$msgcode['supplementDictionary']['ERR'] = 110;
-function supplementDictionary ()
-{
-       assertUIntArg ('chapter_no');
-       assertStringArg ('dict_value');
-       if (commitSupplementDictionary ($_REQUEST['chapter_no'], $_REQUEST['dict_value']) === TRUE)
-               return buildRedirectURL (__FUNCTION__, 'OK');
-       else
-               return buildRedirectURL (__FUNCTION__, 'ERR');
-}
-
-$msgcode['reduceDictionary']['OK'] = 50;
-$msgcode['reduceDictionary']['ERR'] = 111;
-function reduceDictionary ()
-{
-       assertUIntArg ('chapter_no');
-       assertUIntArg ('dict_key');
-       if (commitReduceDictionary ($_REQUEST['chapter_no'], $_REQUEST['dict_key']) === TRUE)
-               return buildRedirectURL (__FUNCTION__, 'OK');
-       else
-               return buildRedirectURL (__FUNCTION__, 'ERR');
-}
-
-$msgcode['addChapter']['OK'] = 55;
-$msgcode['addChapter']['ERR'] = 112;
-function addChapter ()
-{
-       assertStringArg ('chapter_name');
-       if (commitAddChapter ($_REQUEST['chapter_name']) === TRUE)
-               return buildRedirectURL (__FUNCTION__, 'OK');
-       else
-               return buildRedirectURL (__FUNCTION__, 'ERR');
+       // this request must be built with chapter_no
+       usePreparedUpdateBlade
+       (
+               'Dictionary',
+               array ('dict_value' => $sic['dict_value']),
+               array
+               (
+                       'chapter_id' => $sic['chapter_no'],
+                       'dict_key' => $sic['dict_key'],
+               )
+       );
+       return buildRedirectURL (__FUNCTION__, 'OK');
 }
 
-$msgcode['updateChapter']['OK'] = 54;
-$msgcode['updateChapter']['ERR'] = 113;
+$msgcode['updateChapter']['OK'] = 51;
 function updateChapter ()
 {
        assertUIntArg ('chapter_no');
        assertStringArg ('chapter_name');
-       if (FALSE !== commitUpdateChapter ($_REQUEST['chapter_no'], $_REQUEST['chapter_name']))
-               return buildRedirectURL (__FUNCTION__, 'OK');
-       else
-               return buildRedirectURL (__FUNCTION__, 'ERR');
+       usePreparedUpdateBlade
+       (
+               'Chapter',
+               array
+               (
+                       'name' => $chapter_name,
+               ),
+               array
+               (
+                       'id' => $chapter_no,
+                       'sticky' => 'no', // note this constant, it protects system chapters
+               )
+       );
+       return buildRedirectURL (__FUNCTION__, 'OK');
 }
 
-$msgcode['delChapter']['OK'] = 53;
-$msgcode['delChapter']['ERR'] = 114;
+$msgcode['delChapter']['OK'] = 49;
+$msgcode['delChapter']['ERR'] = 111;
 function delChapter ()
 {
        assertUIntArg ('chapter_no');
@@ -611,44 +996,9 @@ function delChapter ()
                return buildRedirectURL (__FUNCTION__, 'ERR');
 }
 
-$msgcode['changeAttribute']['OK'] = 46;
-$msgcode['changeAttribute']['ERR'] = 115;
-function changeAttribute ()
-{
-       assertUIntArg ('attr_id');
-       assertStringArg ('attr_name');
-       if (FALSE !== commitUpdateAttribute ($_REQUEST['attr_id'], $_REQUEST['attr_name']))
-               return buildRedirectURL (__FUNCTION__, 'OK');
-       else
-               return buildRedirectURL (__FUNCTION__, 'ERR');
-}
-
-$msgcode['createAttribute']['OK'] = 45;
-$msgcode['createAttribute']['ERR'] = 116;
-function createAttribute ()
-{
-       assertStringArg ('attr_name');
-       assertStringArg ('attr_type');
-       if (commitAddAttribute ($_REQUEST['attr_name'], $_REQUEST['attr_type']))
-               return buildRedirectURL (__FUNCTION__, 'OK', array ($_REQUEST['attr_name']));
-       else
-               return buildRedirectURL (__FUNCTION__, 'ERR');
-}
-
-$msgcode['deleteAttribute']['OK'] = 47;
-$msgcode['deleteAttribute']['ERR'] = 117;
-function deleteAttribute ()
-{
-       assertUIntArg ('attr_id');
-       if (commitDeleteAttribute ($_REQUEST['attr_id']))
-               return buildRedirectURL (__FUNCTION__, 'OK');
-       else
-               return buildRedirectURL (__FUNCTION__, 'ERR');
-}
-
 $msgcode['supplementAttrMap']['OK'] = 48;
 $msgcode['supplementAttrMap']['ERR1'] = 154;
-$msgcode['supplementAttrMap']['ERR2'] = 118;
+$msgcode['supplementAttrMap']['ERR2'] = 110;
 function supplementAttrMap ()
 {
        assertUIntArg ('attr_id');
@@ -674,24 +1024,11 @@ function supplementAttrMap ()
                return buildRedirectURL (__FUNCTION__, 'ERR2');
 }
 
-$msgcode['reduceAttrMap']['OK'] = 49;
-$msgcode['reduceAttrMap']['ERR'] = 119;
-function reduceAttrMap ()
-{
-       assertUIntArg ('attr_id');
-       assertUIntArg ('objtype_id');
-       if (commitReduceAttrMap ($_REQUEST['attr_id'], $_REQUEST['objtype_id']) !== FALSE)
-               return buildRedirectURL (__FUNCTION__, 'OK');
-       else
-               return buildRedirectURL (__FUNCTION__, 'ERR');
-}
-
-$msgcode['clearSticker']['OK'] = 15;
+$msgcode['clearSticker']['OK'] = 49;
 $msgcode['clearSticker']['ERR'] = 120;
 function clearSticker ()
 {
        assertUIntArg ('attr_id');
-       assertUIntArg ('object_id');
        if (commitResetAttrValue ($_REQUEST['object_id'], $_REQUEST['attr_id']) !== FALSE)
                return buildRedirectURL (__FUNCTION__, 'OK');
        else
@@ -701,8 +1038,7 @@ function clearSticker ()
 $msgcode['updateObjectAllocation']['OK'] = 63;
 function updateObjectAllocation ()
 {
-       assertUIntArg ('object_id');
-
+       global $remote_username, $sic;
        if (!isset ($_REQUEST['got_atoms']))
        {
                unset($_GET['page']);
@@ -748,31 +1084,27 @@ function updateObjectAllocation ()
                return buildRedirectURL (__FUNCTION__, 'OK', $changecnt);
        // Log a record.
        $newMolecule = getMoleculeForObject ($object_id);
-       $oc = count ($oldMolecule);
-       $nc = count ($newMolecule);
-       $omid = $oc ? createMolecule ($oldMolecule) : 'NULL';
-       $nmid = $nc ? createMolecule ($newMolecule) : 'NULL';
-       global $remote_username;
-       $comment = empty ($_REQUEST['comment']) ? 'NULL' : "'${_REQUEST['comment']}'";
-       $query =
-               "insert into MountOperation(object_id, old_molecule_id, new_molecule_id, user_name, comment) " .
-               "values (${object_id}, ${omid}, ${nmid}, '${remote_username}', ${comment})";
-       global $dbxlink;
-       $result = $dbxlink->query ($query);
-       if ($result == NULL)
-               $log[] = array ('code' => 500, 'message' => 'SQL query failed during history logging.');
-       else
-               $log[] = array ('code' => 200, 'message' => 'History logged.');
+       usePreparedInsertBlade
+       (
+               'MountOperation', 
+               array
+               (
+                       'object_id' => $object_id,
+                       'old_molecule_id' => count ($oldMolecule) ? createMolecule ($oldMolecule) : NULL,
+                       'new_molecule_id' => count ($newMolecule) ? createMolecule ($newMolecule) : NULL,
+                       'user_name' => $remote_username,
+                       'comment' => empty ($sic['comment']) ? NULL : $sic['comment'],
+               )
+       );
+       $log[] = array ('code' => 200, 'message' => 'history logged');
        return buildWideRedirectURL ($log);
 }
 
-$msgcode['updateObject']['OK'] = 16;
-$msgcode['updateObject']['ERR'] = 121;
+$msgcode['updateObject']['OK'] = 51;
+$msgcode['updateObject']['ERR'] = 109;
 function updateObject ()
 {
        assertUIntArg ('num_attrs', TRUE);
-       assertUIntArg ('object_id');
-       assertUIntArg ('object_type_id');
        assertStringArg ('object_name', TRUE);
        assertStringArg ('object_label', TRUE);
        assertStringArg ('object_barcode', TRUE);
@@ -787,7 +1119,6 @@ function updateObject ()
                $_REQUEST['object_name'],
                $_REQUEST['object_label'],
                $_REQUEST['object_barcode'],
-               $_REQUEST['object_type_id'],
                $has_problems,
                $_REQUEST['object_asset_no'],
                $_REQUEST['object_comment']
@@ -837,12 +1168,11 @@ function updateObject ()
 
        // Invalidate thumb cache of all racks objects could occupy.
        foreach (getResidentRacksData ($_REQUEST['object_id'], FALSE) as $rack_id)
-               resetThumbCache ($rack_id);
+               usePreparedUpdateBlade ('Rack', array ('thumb_data' => NULL), array ('id' => $rack_id));
 
        return buildRedirectURL (__FUNCTION__, 'OK');
 }
 
-
 function addMultipleObjects()
 {
        $log = emptyLog();
@@ -855,6 +1185,15 @@ function addMultipleObjects()
                        $log = mergeLogs ($log, oneLiner (184, array ($i + 1)));
                        break;
                }
+
+               // set to empty values for virtual objects
+               if (isset ($_REQUEST['virtual_objects']))
+               {
+                       $_REQUEST["${i}_object_label"] = '';
+                       $_REQUEST["${i}_object_barcode"] = '';
+                       $_REQUEST["${i}_object_asset_no"] = '';
+               }
+
                assertUIntArg ("${i}_object_type_id", TRUE);
                assertStringArg ("${i}_object_name", TRUE);
                assertStringArg ("${i}_object_label", TRUE);
@@ -877,9 +1216,9 @@ function addMultipleObjects()
                        $info = spotEntity ('object', $object_id);
                        // FIXME: employ amplifyCell() instead of calling loader functions directly
                        amplifyCell ($info);
-                       $log = mergeLogs ($log, oneLiner (80, array ('<a href="' . makeHref (array ('page' => 'object', 'tab' => 'default', 'object_id' => $object_id)) . '">' . $info['dname'] . '</a>')));
+                       $log = mergeLogs ($log, oneLiner (5, array ('<a href="' . makeHref (array ('page' => 'object', 'tab' => 'default', 'object_id' => $object_id)) . '">' . $info['dname'] . '</a>')));
                }else{
-                       $log = mergeLogs ($log, oneLiner (185, array ($name)));
+                       $log = mergeLogs ($log, oneLiner (147, array ($name)));
                }
        }
        return buildWideRedirectURL ($log);
@@ -913,15 +1252,15 @@ function addLotOfObjects()
                        {
                                $info = spotEntity ('object', $object_id);
                                amplifyCell ($info);
-                               $log = mergeLogs ($log, oneLiner (80, array ('<a href="' . makeHref (array ('page' => 'object', 'tab' => 'default', 'object_id' => $object_id)) . '">' . $info['dname'] . '</a>')));
+                               $log = mergeLogs ($log, oneLiner (5, array ('<a href="' . makeHref (array ('page' => 'object', 'tab' => 'default', 'object_id' => $object_id)) . '">' . $info['dname'] . '</a>')));
                        }
                        else
-                               $log = mergeLogs ($log, oneLiner (185, array ($name)));
+                               $log = mergeLogs ($log, oneLiner (147, array ($name)));
        }
        return buildWideRedirectURL ($log);
 }
 
-$msgcode['deleteObject']['OK'] = 76;
+$msgcode['deleteObject']['OK'] = 6;
 function deleteObject ()
 {
        assertUIntArg ('object_id');
@@ -930,36 +1269,44 @@ function deleteObject ()
        $racklist = getResidentRacksData ($_REQUEST['object_id'], FALSE);
        commitDeleteObject ($_REQUEST['object_id']);
        foreach ($racklist as $rack_id)
-               resetThumbCache ($rack_id);
+               usePreparedUpdateBlade ('Rack', array ('thumb_data' => NULL), array ('id' => $rack_id));
        return buildRedirectURL (__FUNCTION__, 'OK', array ($oinfo['dname']));
 }
 
-$msgcode['resetObject']['OK'] = 83;
-$msgcode['resetObject']['ERR'] = 100;
+$msgcode['resetObject']['OK'] = 57;
 function resetObject ()
 {
-       assertUIntArg ('object_id');
        $oinfo = spotEntity ('object', $_REQUEST['object_id']);
 
        $racklist = getResidentRacksData ($_REQUEST['object_id'], FALSE);
        commitResetObject ($_REQUEST['object_id']);
        foreach ($racklist as $rack_id)
-               resetThumbCache ($rack_id);
-       return buildRedirectURL (__FUNCTION__, 'OK', array ($oinfo['dname']));
+               usePreparedUpdateBlade ('Rack', array ('thumb_data' => NULL), array ('id' => $rack_id));
+       return buildRedirectURL (__FUNCTION__, 'OK');
 }
 
-$msgcode['useupPort']['OK'] = 11;
-$msgcode['useupPort']['ERR'] = 124;
+$msgcode['useupPort']['OK'] = 49;
 function useupPort ()
 {
+       global $sic;
        assertUIntArg ('port_id');
-       if (FALSE !== commitUseupPort ($_REQUEST['port_id']))
-               return buildRedirectURL (__FUNCTION__, 'OK');
-       else
-               return buildRedirectURL (__FUNCTION__, 'ERR');
+       usePreparedUpdateBlade
+       (
+               'Port',
+               array
+               (
+                       'reservation_comment' => NULL,
+               ),
+               array
+               (
+                       'object_id' => $sic['object_id'],
+                       'id' => $sic['port_id'],
+               )
+       );
+       return buildRedirectURL (__FUNCTION__, 'OK');
 }
 
-$msgcode['updateUI']['OK'] = 56;
+$msgcode['updateUI']['OK'] = 51;
 function updateUI ()
 {
        assertUIntArg ('num_vars');
@@ -980,7 +1327,7 @@ function updateUI ()
        return buildRedirectURL (__FUNCTION__, 'OK');
 }
 
-$msgcode['saveMyPreferences']['OK'] = 56;
+$msgcode['saveMyPreferences']['OK'] = 51;
 function saveMyPreferences ()
 {
        assertUIntArg ('num_vars');
@@ -1000,7 +1347,7 @@ function saveMyPreferences ()
        return buildRedirectURL (__FUNCTION__, 'OK');
 }
 
-$msgcode['resetMyPreference']['OK'] = 56;
+$msgcode['resetMyPreference']['OK'] = 51;
 function resetMyPreference ()
 {
        assertStringArg ("varname");
@@ -1011,7 +1358,7 @@ function resetMyPreference ()
 $msgcode['resetUIConfig']['OK'] = 57;
 function resetUIConfig()
 {
-       setConfigVar ('MASSCOUNT','15');
+       setConfigVar ('MASSCOUNT','8');
        setConfigVar ('MAXSELSIZE','30');
        setConfigVar ('ROW_SCALE','2');
        setConfigVar ('PORTS_PER_ROW','12');
@@ -1040,7 +1387,7 @@ function resetUIConfig()
        setConfigVar ('PREVIEW_IMAGE_MAXPXS', '320');
        setConfigVar ('VENDOR_SIEVE', '');
        setConfigVar ('IPV4LB_LISTSRC', '{$typeid_4}');
-       setConfigVar ('IPV4OBJ_LISTSRC','{$typeid_4} or {$typeid_7} or {$typeid_8} or {$typeid_12} or {$typeid_445} or {$typeid_447} or {$typeid_798}');
+       setConfigVar ('IPV4OBJ_LISTSRC','{$typeid_4} or {$typeid_7} or {$typeid_8} or {$typeid_12} or {$typeid_445} or {$typeid_447} or {$typeid_798} or {$typeid_1504}');
        setConfigVar ('IPV4NAT_LISTSRC','{$typeid_4} or {$typeid_7} or {$typeid_8} or {$typeid_798}');
        setConfigVar ('ASSETWARN_LISTSRC','{$typeid_4} or {$typeid_7} or {$typeid_8}');
        setConfigVar ('NAMEWARN_LISTSRC','{$typeid_4} or {$typeid_7} or {$typeid_8}');
@@ -1077,11 +1424,14 @@ function resetUIConfig()
        setConfigVar ('HNDP_RUNNERS_LISTSRC', '');
        setConfigVar ('SHRINK_TAG_TREE_ON_CLICK', 'yes');
        setConfigVar ('MAX_UNFILTERED_ENTITIES', '0');
+       setConfigVar ('SYNCDOMAIN_MAX_PROCESSES', '0');
+    setConfigVar ('VIRTUAL_OBJ_LISTSRC', '{$typeid_1504} or {$typeid_1505} or {$typeid_1506} or {$typeid_1507}');
+    setConfigVar ('PORT_EXCLUSION_LISTSRC', '{$typeid_3} or {$typeid_10} or {$typeid_11} or {$typeid_1505} or {$typeid_1506}');
        return buildRedirectURL (__FUNCTION__, 'OK');
 }
 
-$msgcode['addRealServer']['OK'] = 34;
-$msgcode['addRealServer']['ERR'] = 126;
+$msgcode['addRealServer']['OK'] = 48;
+$msgcode['addRealServer']['ERR'] = 110;
 // Add single record.
 function addRealServer ()
 {
@@ -1107,7 +1457,6 @@ $msgcode['addRealServers']['ERR2'] = 127;
 // Parse textarea submitted and try adding a real server for each line.
 function addRealServers ()
 {
-       assertUIntArg ('pool_id');
        assertStringArg ('format');
        assertStringArg ('rawtext');
        $ngood = $nbad = 0;
@@ -1163,65 +1512,34 @@ function addRealServers ()
                return buildRedirectURL (__FUNCTION__, 'ERR2', array ($ngood, $nbad));
 }
 
-$msgcode['addVService']['OK'] = 28;
-$msgcode['addVService']['ERR1'] = 132;
-$msgcode['addVService']['ERR2'] = 100;
+$msgcode['addVService']['OK'] = 48;
 function addVService ()
 {
        assertIPv4Arg ('vip');
        assertUIntArg ('vport');
-       assertStringArg ('proto');
-       if ($_REQUEST['proto'] != 'TCP' and $_REQUEST['proto'] != 'UDP')
-               return buildRedirectURL (__FUNCTION__, 'ERR1');
+       genericAssertion ('proto', 'enum/ipproto');
        assertStringArg ('name', TRUE);
        assertStringArg ('vsconfig', TRUE);
        assertStringArg ('rsconfig', TRUE);
-       $error = commitCreateVS
+       usePreparedExecuteBlade
        (
-               $_REQUEST['vip'],
-               $_REQUEST['vport'],
-               $_REQUEST['proto'],
-               $_REQUEST['name'],
-               $_REQUEST['vsconfig'],
-               $_REQUEST['rsconfig'],
-               isset ($_REQUEST['taglist']) ? $_REQUEST['taglist'] : array()
+               'INSERT INTO IPv4VS (vip, vport, proto, name, vsconfig, rsconfig) VALUES (INET_ATON(?), ?, ?, ?, ?, ?)',
+               array
+               (
+                       $_REQUEST['vip'],
+                       $_REQUEST['vport'],
+                       $_REQUEST['proto'],
+                       !mb_strlen ($_REQUEST['name']) ? NULL : $_REQUEST['name'],
+                       !strlen ($_REQUEST['vsconfig']) ? NULL : $_REQUEST['vsconfig'],
+                       !strlen ($_REQUEST['rsconfig']) ? NULL : $_REQUEST['rsconfig'],
+               )
        );
-       if ($error != '')
-               return buildRedirectURL (__FUNCTION__, 'ERR2', array ($error));
-       else
-               return buildRedirectURL (__FUNCTION__, 'OK');
-}
-
-$msgcode['deleteRealServer']['OK'] = 35;
-$msgcode['deleteRealServer']['ERR'] = 128;
-function deleteRealServer ()
-{
-       assertUIntArg ('id');
-       if (!commitDeleteRS ($_REQUEST['id']))
-               return buildRedirectURL (__FUNCTION__, 'ERR');
-       else
-               return buildRedirectURL (__FUNCTION__, 'OK');
-}
-
-$msgcode['deleteLoadBalancer']['OK'] = 19;
-$msgcode['deleteLoadBalancer']['ERR'] = 129;
-function deleteLoadBalancer ()
-{
-       assertUIntArg ('object_id');
-       assertUIntArg ('pool_id');
-       assertUIntArg ('vs_id');
-       if (!commitDeleteLB (
-               $_REQUEST['object_id'],
-               $_REQUEST['pool_id'],
-               $_REQUEST['vs_id']
-       ))
-               return buildRedirectURL (__FUNCTION__, 'ERR');
-       else
-               return buildRedirectURL (__FUNCTION__, 'OK');
+       produceTagsForLastRecord ('ipv4vs', isset ($_REQUEST['taglist']) ? $_REQUEST['taglist'] : array());
+       return buildRedirectURL (__FUNCTION__, 'OK');
 }
 
-$msgcode['deleteVService']['OK'] = 29;
-$msgcode['deleteVService']['ERR'] = 130;
+$msgcode['deleteVService']['OK'] = 49;
+$msgcode['deleteVService']['ERR'] = 111;
 function deleteVService ()
 {
        assertUIntArg ('vs_id');
@@ -1245,8 +1563,8 @@ function updateSLBDefConfig ()
                return buildRedirectURL (__FUNCTION__, 'OK');
 }
 
-$msgcode['updateRealServer']['OK'] = 36;
-$msgcode['updateRealServer']['ERR'] = 133;
+$msgcode['updateRealServer']['OK'] = 51;
+$msgcode['updateRealServer']['ERR'] = 109;
 function updateRealServer ()
 {
        assertUIntArg ('rs_id');
@@ -1264,39 +1582,14 @@ function updateRealServer ()
                return buildRedirectURL (__FUNCTION__, 'OK');
 }
 
-$msgcode['updateLoadBalancer']['OK'] = 20;
-$msgcode['updateLoadBalancer']['ERR'] = 134;
-function updateLoadBalancer ()
-{
-       assertUIntArg ('object_id');
-       assertUIntArg ('pool_id');
-       assertUIntArg ('vs_id');
-       assertStringArg ('vsconfig', TRUE);
-       assertStringArg ('rsconfig', TRUE);
-       if (! empty($_REQUEST['prio']))
-               assertUIntArg('prio', TRUE);
-
-       if (FALSE === commitUpdateLB (
-               $_REQUEST['object_id'],
-               $_REQUEST['pool_id'],
-               $_REQUEST['vs_id'],
-               $_REQUEST['vsconfig'],
-               $_REQUEST['rsconfig'],
-               $_REQUEST['prio']
-       ))
-               return buildRedirectURL (__FUNCTION__, 'ERR');
-       else
-               return buildRedirectURL (__FUNCTION__, 'OK');
-}
-
-$msgcode['updateVService']['OK'] = 30;
-$msgcode['updateVService']['ERR'] = 135;
+$msgcode['updateVService']['OK'] = 51;
+$msgcode['updateVService']['ERR'] = 109;
 function updateVService ()
 {
        assertUIntArg ('vs_id');
        assertIPv4Arg ('vip');
        assertUIntArg ('vport');
-       assertStringArg ('proto');
+       genericAssertion ('proto', 'enum/ipproto');
        assertStringArg ('name', TRUE);
        assertStringArg ('vsconfig', TRUE);
        assertStringArg ('rsconfig', TRUE);
@@ -1314,8 +1607,8 @@ function updateVService ()
                return buildRedirectURL (__FUNCTION__, 'OK');
 }
 
-$msgcode['addLoadBalancer']['OK'] = 18;
-$msgcode['addLoadBalancer']['ERR'] = 137;
+$msgcode['addLoadBalancer']['OK'] = 48;
+$msgcode['addLoadBalancer']['ERR'] = 110;
 function addLoadBalancer ()
 {
        assertUIntArg ('pool_id');
@@ -1339,28 +1632,24 @@ function addLoadBalancer ()
                return buildRedirectURL (__FUNCTION__, 'OK');
 }
 
-$msgcode['addRSPool']['OK'] = 31;
-$msgcode['addRSPool']['ERR'] = 100;
+$msgcode['addRSPool']['OK'] = 48;
 function addRSPool ()
 {
-       assertStringArg ('name', TRUE);
+       assertStringArg ('name');
        assertStringArg ('vsconfig', TRUE);
        assertStringArg ('rsconfig', TRUE);
-       $error = commitCreateRSPool
+       commitCreateRSPool
        (
                $_REQUEST['name'],
                $_REQUEST['vsconfig'],
                $_REQUEST['rsconfig'],
                isset ($_REQUEST['taglist']) ? $_REQUEST['taglist'] : array()
        );
-       if ($error != '')
-               return buildRedirectURL (__FUNCTION__, 'ERR', array ($error));
-       else
-               return buildRedirectURL (__FUNCTION__, 'OK');
+       return buildRedirectURL (__FUNCTION__, 'OK');
 }
 
-$msgcode['deleteRSPool']['OK'] = 32;
-$msgcode['deleteRSPool']['ERR'] = 138;
+$msgcode['deleteRSPool']['OK'] = 49;
+$msgcode['deleteRSPool']['ERR'] = 111;
 function deleteRSPool ()
 {
        assertUIntArg ('pool_id');
@@ -1370,29 +1659,8 @@ function deleteRSPool ()
                return buildRedirectURL (__FUNCTION__, 'OK');
 }
 
-$msgcode['updateRSPool']['OK'] = 33;
-$msgcode['updateRSPool']['ERR'] = 139;
-function updateRSPool ()
-{
-       assertUIntArg ('pool_id');
-       assertStringArg ('name', TRUE);
-       assertStringArg ('vsconfig', TRUE);
-       assertStringArg ('rsconfig', TRUE);
-       if (FALSE === commitUpdateRSPool
-               (
-                       $_REQUEST['pool_id'],
-                       $_REQUEST['name'],
-                       $_REQUEST['vsconfig'],
-                       $_REQUEST['rsconfig']
-               )
-       )
-               return buildRedirectURL (__FUNCTION__, 'ERR');
-       else
-               return buildRedirectURL (__FUNCTION__, 'OK');
-}
-
-$msgcode['updateRSInService']['OK'] = 38;
-$msgcode['updateRSInService']['ERR'] = 140;
+$msgcode['updateRSInService']['OK'] = 26;
+$msgcode['updateRSInService']['ERR'] = 141;
 function updateRSInService ()
 {
        assertUIntArg ('rscount');
@@ -1457,7 +1725,6 @@ $msgcode['generateAutoPorts']['ERR'] = 142;
 function generateAutoPorts ()
 {
        global $pageno;
-       assertUIntArg ('object_id');
        $info = spotEntity ('object', $_REQUEST['object_id']);
        // Navigate away in case of success, stay at the place otherwise.
        if (executeAutoPorts ($_REQUEST['object_id'], $info['objtype_id']))
@@ -1466,19 +1733,16 @@ function generateAutoPorts ()
                return buildRedirectURL (__FUNCTION__, 'ERR');
 }
 
-$msgcode['saveEntityTags']['OK'] = 22;
+$msgcode['saveEntityTags']['OK'] = 26;
 $msgcode['saveEntityTags']['ERR1'] = 143;
-$msgcode['saveEntityTags']['ERR2'] = 187;
 // Filter out implicit tags before storing the new tag set.
 function saveEntityTags ()
 {
-       global $page, $pageno, $etype_by_pageno;
-       if (!isset ($etype_by_pageno[$pageno]) or !isset ($page[$pageno]['bypass']))
-               return buildRedirectURL (__FUNCTION__, 'ERR2', array (__FUNCTION__));
+       global $pageno, $etype_by_pageno;
+       if (!isset ($etype_by_pageno[$pageno]))
+               throw new RackTablesError ('key not found in etype_by_pageno', RackTablesError::INTERNAL);
        $realm = $etype_by_pageno[$pageno];
-       $bypass = $page[$pageno]['bypass'];
-       assertUIntArg ($bypass);
-       $entity_id = $_REQUEST[$bypass];
+       $entity_id = getBypassValue();
        $taglist = isset ($_REQUEST['taglist']) ? $_REQUEST['taglist'] : array();
        // Build a chain from the submitted data, minimize it,
        // then wipe existing records and store the new set instead.
@@ -1498,63 +1762,10 @@ function saveEntityTags ()
                return buildRedirectURL (__FUNCTION__, 'OK', array ($n_succeeds));
 }
 
-$msgcode['destroyTag']['OK'] = 58;
-$msgcode['destroyTag']['ERR1'] = 183;
-$msgcode['destroyTag']['ERR2'] = 144;
-function destroyTag ()
-{
-       assertUIntArg ('tag_id');
-       global $taglist;
-       if (!isset ($taglist[$_REQUEST['tag_id']]))
-               return buildRedirectURL (__FUNCTION__, 'ERR1', array ($_REQUEST['tag_id']));
-       if (($ret = commitDestroyTag ($_REQUEST['tag_id'])) == '')
-               return buildRedirectURL (__FUNCTION__, 'OK', array ($taglist[$_REQUEST['tag_id']]['tag']));
-       else
-               return buildRedirectURL (__FUNCTION__, 'ERR2');
-}
-
-$msgcode['createTag']['OK'] = 59;
-$msgcode['createTag']['ERR1'] = 145;
-$msgcode['createTag']['ERR3'] = 147;
-function createTag ()
-{
-       assertStringArg ('tag_name');
-       assertUIntArg ('parent_id', TRUE);
-       $tagname = trim ($_REQUEST['tag_name']);
-       if (!validTagName ($tagname))
-               return buildRedirectURL (__FUNCTION__, 'ERR1', array ($tagname));
-       if (($parent_id = $_REQUEST['parent_id']) <= 0)
-               $parent_id = NULL;
-       if (FALSE === commitCreateTag ($tagname, $parent_id))
-               return buildRedirectURL (__FUNCTION__, 'ERR3', array (niftyString ($tagname)));
-       return buildRedirectURL (__FUNCTION__, 'OK', array (niftyString ($tagname)));
-}
-
-$msgcode['updateTag']['OK'] = 60;
-$msgcode['updateTag']['ERR1'] = 145;
-$msgcode['updateTag']['ERR2'] = 109;
-function updateTag ()
-{
-       assertUIntArg ('tag_id');
-       assertUIntArg ('parent_id', TRUE);
-       assertStringArg ('tag_name');
-       $tagname = trim ($_REQUEST['tag_name']);
-       if (!validTagName ($tagname))
-               return buildRedirectURL (__FUNCTION__, 'ERR1', array ($tagname));
-       if (($parent_id = $_REQUEST['parent_id']) <= 0)
-               $parent_id = 'NULL';
-       if (FALSE !== commitUpdateTag ($_REQUEST['tag_id'], $tagname, $parent_id))
-               return buildRedirectURL (__FUNCTION__, 'OK', array ($tagname));
-       // Use old name in the message, cause update failed.
-       global $taglist;
-       return buildRedirectURL (__FUNCTION__, 'ERR2', array ($taglist[$_REQUEST['tag_id']]['tag']));
-}
-
 $msgcode['rollTags']['OK'] = 67;
 $msgcode['rollTags']['ERR'] = 149;
 function rollTags ()
 {
-       assertUIntArg ('row_id');
        assertStringArg ('sum', TRUE);
        assertUIntArg ('realsum');
        if ($_REQUEST['sum'] != $_REQUEST['realsum'])
@@ -1579,7 +1790,7 @@ function rollTags ()
        return buildRedirectURL (__FUNCTION__, 'OK', array ($n_ok));
 }
 
-$msgcode['changeMyPassword']['OK'] = 61;
+$msgcode['changeMyPassword']['OK'] = 51;
 $msgcode['changeMyPassword']['ERR1'] = 150;
 $msgcode['changeMyPassword']['ERR2'] = 151;
 $msgcode['changeMyPassword']['ERR3'] = 152;
@@ -1623,16 +1834,21 @@ function saveRackCode ()
        return buildRedirectURL (__FUNCTION__, 'ERR2');
 }
 
-$msgcode['setPortVLAN']['ERR1'] = 156;
+$msgcode['setPortVLAN']['ERR'] = 164;
 // This handler's context is pre-built, but not authorized. It is assumed, that the
 // handler will take existing context and before each commit check authorization
 // on the base chain plus necessary context added.
 function setPortVLAN ()
 {
        assertUIntArg ('portcount');
-       $data = getSwitchVLANs ($_REQUEST['object_id']);
-       if ($data === NULL)
-               return buildRedirectURL (__FUNCTION__, 'ERR1');
+       try
+       {
+               $data = getSwitchVLANs ($_REQUEST['object_id']);
+       }
+       catch (RTGatewayError $re)
+       {
+               return buildRedirectURL (__FUNCTION__, 'ERR', array ($re->getMessage()));
+       }
        list ($vlanlist, $portlist) = $data;
        // Here we just build up 1 set command for the gateway with all of the ports
        // included. The gateway is expected to filter unnecessary changes silently
@@ -1643,41 +1859,46 @@ function setPortVLAN ()
        $log = emptyLog();
        $setcmd = '';
        for ($i = 0; $i < $nports; $i++)
+       {
+               genericAssertion ('portname_' . $i, 'string');
+               genericAssertion ('vlanid_' . $i, 'string');
+               if ($_REQUEST['portname_' . $i] != $portlist[$i]['portname'])
+                       throw new InvalidRequestArgException ('portname_' . $i, $_REQUEST['portname_' . $i], 'expected to be ' . $portlist[$i]['portname']);
                if
-               (
-                       !isset ($_REQUEST['portname_' . $i]) ||
-                       !isset ($_REQUEST['vlanid_' . $i]) ||
-                       $_REQUEST['portname_' . $i] != $portlist[$i]['portname']
-               )
-                       $log['m'][] = array ('c' => 158, 'a' => array ($i));
-               elseif
                (
                        $_REQUEST['vlanid_' . $i] == $portlist[$i]['vlanid'] ||
                        $portlist[$i]['vlaind'] == 'TRUNK'
                )
                        continue;
-               else
+               $portname = $_REQUEST['portname_' . $i];
+               $oldvlanid = $portlist[$i]['vlanid'];
+               $newvlanid = $_REQUEST['vlanid_' . $i];
+               if
+               (
+                       !permitted (NULL, NULL, NULL, array (array ('tag' => '$fromvlan_' . $oldvlanid))) or
+                       !permitted (NULL, NULL, NULL, array (array ('tag' => '$tovlan_' . $newvlanid)))
+               )
                {
-                       $portname = $_REQUEST['portname_' . $i];
-                       $oldvlanid = $portlist[$i]['vlanid'];
-                       $newvlanid = $_REQUEST['vlanid_' . $i];
-                       if
-                       (
-                               !permitted (NULL, NULL, NULL, array (array ('tag' => '$fromvlan_' . $oldvlanid))) or
-                               !permitted (NULL, NULL, NULL, array (array ('tag' => '$tovlan_' . $newvlanid)))
-                       )
-                       {
-                               $log['m'][] = array ('c' => 159, 'a' => array ($portname, $oldvlanid, $newvlanid));
-                               continue;
-                       }
-                       $setcmd .= $prefix . $portname . '=' . $newvlanid;
-                       $prefix = ';';
+                       $log = mergeLogs ($log, oneLiner (159, array ($portname, $oldvlanid, $newvlanid)));
+                       continue;
                }
+               $setcmd .= $prefix . $portname . '=' . $newvlanid;
+               $prefix = ';';
+       }
        // Feed the gateway and interpret its (non)response.
-       if ($setcmd != '')
-               $log['m'] = array_merge ($log['m'], setSwitchVLANs ($_REQUEST['object_id'], $setcmd));
+       if ($setcmd == '')
+               $log = mergeLogs ($log, oneLiner (201));
        else
-               $log['m'][] = array ('c' => 201);
+       {
+               try
+               {
+                       $log = mergeLogs ($log, setSwitchVLANs ($_REQUEST['object_id'], $setcmd));
+               }
+               catch (RTGatewayError $e)
+               {
+                       $log = mergeLogs ($log, oneLiner (164, $e->getMessage()));
+               }
+       }
        return buildWideRedirectURL ($log);
 }
 
@@ -1685,7 +1906,6 @@ $msgcode['submitSLBConfig']['OK'] = 66;
 $msgcode['submitSLBConfig']['ERR'] = 164;
 function submitSLBConfig ()
 {
-       assertUIntArg ('object_id');
        $newconfig = buildLVSConfig ($_REQUEST['object_id']);
        try
        {
@@ -1698,57 +1918,18 @@ function submitSLBConfig ()
        return buildRedirectURL (__FUNCTION__, 'OK', array ('slbconfig'));
 }
 
-$msgcode['addRow']['OK'] = 74;
-$msgcode['addRow']['ERR'] = 100;
-function addRow ()
-{
-       assertStringArg ('name');
-
-       if (commitAddRow ($_REQUEST['name']) === TRUE)
-               return buildRedirectURL (__FUNCTION__, 'OK', array ($_REQUEST['name']));
-       else
-               return buildRedirectURL (__FUNCTION__, 'ERR', array ($_REQUEST['name']));
-}
-
-$msgcode['updateRow']['OK'] = 75;
-$msgcode['updateRow']['ERR'] = 100;
-function updateRow ()
-{
-       assertUIntArg ('row_id');
-       assertStringArg ('name');
-
-       if (FALSE !== commitUpdateRow ($_REQUEST['row_id'], $_REQUEST['name']))
-               return buildRedirectURL (__FUNCTION__, 'OK', array ($_REQUEST['name']));
-       else
-               return buildRedirectURL (__FUNCTION__, 'ERR', array ($_REQUEST['name']));
-}
-
-$msgcode['deleteRow']['OK'] = 77;
-$msgcode['deleteRow']['ERR'] = 146;
-function deleteRow ()
-{
-       assertUIntArg ('row_id');
-       $rowinfo = getRackRowInfo ($_REQUEST['row_id']);
-       return buildRedirectURL (__FUNCTION__, FALSE === commitDeleteRow ($_REQUEST['row_id']) ? 'ERR' : 'OK', array ($rowinfo['name']));
-}
-
-$msgcode['addRack']['OK'] = 65;
-$msgcode['addRack']['ERR1'] = 171;
+$msgcode['addRack']['OK'] = 51;
 $msgcode['addRack']['ERR2'] = 172;
 function addRack ()
 {
-       assertUIntArg ('row_id');
        $taglist = isset ($_REQUEST['taglist']) ? $_REQUEST['taglist'] : array();
        if (isset ($_REQUEST['got_data']))
        {
                assertStringArg ('rack_name');
                assertUIntArg ('rack_height1');
                assertStringArg ('rack_comment', TRUE);
-
-               if (commitAddRack ($_REQUEST['rack_name'], $_REQUEST['rack_height1'], $_REQUEST['row_id'], $_REQUEST['rack_comment'], $taglist) === TRUE)
-                       return buildRedirectURL (__FUNCTION__, 'OK', array ($_REQUEST['rack_name']));
-               else
-                       return buildRedirectURL (__FUNCTION__, 'ERR1', array ($_REQUEST['rack_name']));
+               commitAddRack ($_REQUEST['rack_name'], $_REQUEST['rack_height1'], $_REQUEST['row_id'], $_REQUEST['rack_comment'], $taglist);
+               return buildRedirectURL (__FUNCTION__, 'OK', array ($_REQUEST['rack_name']));
        }
        elseif (isset ($_REQUEST['got_mdata']))
        {
@@ -1769,24 +1950,23 @@ function addRack ()
                }
                global $msgcode;
                foreach ($names2 as $cname)
-                       if (commitAddRack ($cname, $_REQUEST['rack_height2'], $_REQUEST['row_id'], '', $taglist) === TRUE)
-                               $log['m'][] = array ('c' => $msgcode[__FUNCTION__]['OK'], 'a' => array ($cname));
-                       else
-                               $log['m'][] = array ('c' => $msgcode[__FUNCTION__]['ERR1'], 'a' => array ($cname));
+               {
+                       commitAddRack ($cname, $_REQUEST['rack_height2'], $_REQUEST['row_id'], '', $taglist);
+                       $log['m'][] = array ('c' => $msgcode[__FUNCTION__]['OK'], 'a' => array ($cname));
+               }
                return buildWideRedirectURL ($log);
        }
        else
                return buildRedirectURL (__FUNCTION__, 'ERR2');
 }
 
-$msgcode['deleteRack']['OK'] = 79;
+$msgcode['deleteRack']['OK'] = 6;
 $msgcode['deleteRack']['ERR'] = 100;
 $msgcode['deleteRack']['ERR1'] = 206;
 function deleteRack ()
 {
        assertUIntArg ('rack_id');
-       if (NULL == ($rackData = spotEntity ('rack', $_REQUEST['rack_id'])))
-               return buildRedirectURL (__FUNCTION__, 'ERR', array ('Rack not found'), 'rackspace', 'default');
+       $rackData = spotEntity ('rack', $_REQUEST['rack_id']);
        amplifyCell ($rackData);
        if (count ($rackData['mountedObjects']))
                return buildRedirectURL (__FUNCTION__, 'ERR1');
@@ -1795,17 +1975,17 @@ function deleteRack ()
        return buildRedirectURL (__FUNCTION__, 'OK', array ($rackData['name']), 'rackspace', 'default');
 }
 
-$msgcode['updateRack']['OK'] = 68;
-$msgcode['updateRack']['ERR'] = 177;
+$msgcode['updateRack']['OK'] = 7;
+$msgcode['updateRack']['ERR'] = 109;
 function updateRack ()
 {
-       assertUIntArg ('rack_id');
        assertUIntArg ('rack_row_id');
        assertUIntArg ('rack_height');
        assertStringArg ('rack_name');
        assertStringArg ('rack_comment', TRUE);
 
-       resetThumbCache ($_REQUEST['rack_id']);
+       global $sic;
+       usePreparedUpdateBlade ('Rack', array ('thumb_data' => NULL), array ('id' => $sic['rack_id']));
        if (TRUE === commitUpdateRack ($_REQUEST['rack_id'], $_REQUEST['rack_name'], $_REQUEST['rack_height'], $_REQUEST['rack_row_id'], $_REQUEST['rack_comment']))
                return buildRedirectURL (__FUNCTION__, 'OK', array ($_REQUEST['rack_name']));
        else
@@ -1814,7 +1994,6 @@ function updateRack ()
 
 function updateRackDesign ()
 {
-       assertUIntArg ('rack_id');
        $rackData = spotEntity ('rack', $_REQUEST['rack_id']);
        amplifyCell ($rackData);
        applyRackDesignMask($rackData);
@@ -1825,7 +2004,6 @@ function updateRackDesign ()
 
 function updateRackProblems ()
 {
-       assertUIntArg ('rack_id');
        $rackData = spotEntity ('rack', $_REQUEST['rack_id']);
        amplifyCell ($rackData);
        applyRackProblemMask($rackData);
@@ -1836,14 +2014,63 @@ function updateRackProblems ()
 
 function querySNMPData ()
 {
-       assertUIntArg ('object_id');
-       assertStringArg ('community');
-       return doSNMPmining ($_REQUEST['object_id'], $_REQUEST['community']);
+       assertStringArg ('community', TRUE);
+
+       $snmpsetup = array ();
+       if ($_REQUEST['community'] != '')
+               $snmpsetup['community'] = $_REQUEST['community'];
+       else
+       {
+               assertStringArg ('sec_name');
+               assertStringArg ('sec_level');
+               assertStringArg ('auth_protocol');
+               assertStringArg ('auth_passphrase', TRUE);
+               assertStringArg ('priv_protocol');
+               assertStringArg ('priv_passphrase', TRUE);
+
+               $snmpsetup['sec_name'] = $_REQUEST['sec_name'];
+               $snmpsetup['sec_level'] = $_REQUEST['sec_level'];
+               $snmpsetup['auth_protocol'] = $_REQUEST['auth_protocol'];
+               $snmpsetup['auth_passphrase'] = $_REQUEST['auth_passphrase'];
+               $snmpsetup['priv_protocol'] = $_REQUEST['priv_protocol'];
+               $snmpsetup['priv_passphrase'] = $_REQUEST['priv_passphrase'];
+       }
+       return doSNMPmining ($_REQUEST['object_id'], $snmpsetup);
+}
+
+$msgcode['linkEntities']['OK'] = 51;
+$msgcode['linkEntities']['ERR2'] = 109;
+function linkEntities ()
+{
+       assertStringArg ('parent_entity_type');
+       assertUIntArg ('parent_entity_id');
+       assertStringArg ('child_entity_type');
+       assertUIntArg ('child_entity_id');
+       $result = usePreparedInsertBlade
+       (
+               'EntityLink',
+               array
+               (
+                       'parent_entity_type' => $_REQUEST['parent_entity_type'],
+                       'parent_entity_id' => $_REQUEST['parent_entity_id'],
+                       'child_entity_type' => $_REQUEST['child_entity_type'],
+                       'child_entity_id' => $_REQUEST['child_entity_id'],
+               )
+       );
+       if ($result === FALSE)
+               return buildRedirectURL (__FUNCTION__, 'ERR2');
+       return buildRedirectURL (__FUNCTION__, 'OK');
 }
 
-$msgcode['addFileWithoutLink']['OK'] = 69;
-$msgcode['addFileWithoutLink']['ERR1'] = 181;
-$msgcode['addFileWithoutLink']['ERR2'] = 110;
+$msgcode['unlinkEntities']['OK'] = 49;
+$msgcode['unlinkEntities']['ERR'] = 111;
+function unlinkEntities ()
+{
+       assertUIntArg ('link_id');
+       return buildRedirectURL (__FUNCTION__, commitUnlinkEntities ($_REQUEST['link_id']) === FALSE ? 'ERR' : 'OK');
+}
+
+$msgcode['addFileWithoutLink']['OK'] = 5;
 // File-related functions
 function addFileWithoutLink ()
 {
@@ -1851,77 +2078,77 @@ function addFileWithoutLink ()
 
        // Make sure the file can be uploaded
        if (get_cfg_var('file_uploads') != 1)
-               return buildRedirectURL (__FUNCTION__, 'ERR1');
+               throw new RackTablesError ('file uploads not allowed, change "file_uploads" parameter in php.ini', RackTablesError::MISCONFIGURED);
 
        $fp = fopen($_FILES['file']['tmp_name'], 'rb');
        global $sic;
-       if (FALSE === commitAddFile ($_FILES['file']['name'], $_FILES['file']['type'], $_FILES['file']['size'], $fp, $sic['comment']))
-               return buildRedirectURL (__FUNCTION__, 'ERR2');
+       commitAddFile ($_FILES['file']['name'], $_FILES['file']['type'], $fp, $sic['comment']);
        if (isset ($_REQUEST['taglist']))
                produceTagsForLastRecord ('file', $_REQUEST['taglist']);
        return buildRedirectURL (__FUNCTION__, 'OK', array (htmlspecialchars ($_FILES['file']['name'])));
 }
 
-$msgcode['addFileToEntity']['OK'] = 69;
-$msgcode['addFileToEntity']['ERR2'] = 181;
-$msgcode['addFileToEntity']['ERR3'] = 110;
+$msgcode['addFileToEntity']['OK'] = 5;
 function addFileToEntity ()
 {
-       global $page, $pageno, $etype_by_pageno;
-       if (!isset ($etype_by_pageno[$pageno]) or !isset ($page[$pageno]['bypass']))
-               throw new RackTablesError ('dispatching failure', RackTablesError::INTERNAL);
+       global $pageno, $etype_by_pageno;
+       if (!isset ($etype_by_pageno[$pageno]))
+               throw new RackTablesError ('key not found in etype_by_pageno', RackTablesError::INTERNAL);
        $realm = $etype_by_pageno[$pageno];
-       $bypass = $page[$pageno]['bypass'];
-       assertUIntArg ($bypass);
-       $entity_id = $_REQUEST[$bypass];
        assertStringArg ('comment', TRUE);
 
        // Make sure the file can be uploaded
        if (get_cfg_var('file_uploads') != 1)
-               return buildRedirectURL (__FUNCTION__, 'ERR2');
+               throw new RackTablesError ('file uploads not allowed, change "file_uploads" parameter in php.ini', RackTablesError::MISCONFIGURED);
 
        $fp = fopen($_FILES['file']['tmp_name'], 'rb');
        global $sic;
-       if (FALSE === commitAddFile ($_FILES['file']['name'], $_FILES['file']['type'], $_FILES['file']['size'], $fp, $sic['comment']))
-               return buildRedirectURL (__FUNCTION__, 'ERR3');
-       if (FALSE === commitLinkFile (lastInsertID(), $realm, $entity_id))
-               return buildRedirectURL (__FUNCTION__, 'ERR3');
-
+       commitAddFile ($_FILES['file']['name'], $_FILES['file']['type'], $fp, $sic['comment']);
+       usePreparedInsertBlade
+       (
+               'FileLink',
+               array
+               (
+                       'file_id' => lastInsertID(),
+                       'entity_type' => $realm,
+                       'entity_id' => getBypassValue(),
+               )
+       );
        return buildRedirectURL (__FUNCTION__, 'OK', array (htmlspecialchars ($_FILES['file']['name'])));
 }
 
 $msgcode['linkFileToEntity']['OK'] = 71;
-$msgcode['linkFileToEntity']['ERR1'] = 178;
-$msgcode['linkFileToEntity']['ERR2'] = 110;
 function linkFileToEntity ()
 {
        assertUIntArg ('file_id');
-       global $page, $pageno, $etype_by_pageno;
-       if (!isset ($etype_by_pageno[$pageno]) or !isset ($page[$pageno]['bypass']))
-               throw new RackTablesError ('dispatching failure', RackTablesError::INTERNAL);
-       $entity_type = $etype_by_pageno[$pageno];
-       $bypass_name = $page[$pageno]['bypass'];
-       assertUIntArg ($bypass_name);
-
-       $fi = spotEntity ('file', $_REQUEST['file_id']);
-       if (FALSE === commitLinkFile ($_REQUEST['file_id'], $entity_type, $_REQUEST[$bypass_name]))
-               return buildRedirectURL (__FUNCTION__, 'ERR2');
+       global $pageno, $etype_by_pageno, $sic;
+       if (!isset ($etype_by_pageno[$pageno]))
+               throw new RackTablesError ('key not found in etype_by_pageno', RackTablesError::INTERNAL);
 
+       $fi = spotEntity ('file', $sic['file_id']);
+       usePreparedInsertBlade
+       (
+               'FileLink',
+               array
+               (
+                       'file_id' => $sic['file_id'],
+                       'entity_type' => $etype_by_pageno[$pageno],
+                       'entity_id' => getBypassValue(),
+               )
+       );
        return buildRedirectURL (__FUNCTION__, 'OK', array (htmlspecialchars ($fi['name'])));
 }
 
-$msgcode['replaceFile']['OK'] = 70;
-$msgcode['replaceFile']['ERR1'] = 181;
+$msgcode['replaceFile']['OK'] = 7;
 $msgcode['replaceFile']['ERR2'] = 207;
 $msgcode['replaceFile']['ERR3'] = 109;
 function replaceFile ()
 {
        global $sic;
-       assertUIntArg ('file_id');
 
        // Make sure the file can be uploaded
        if (get_cfg_var('file_uploads') != 1)
-               return buildRedirectURL (__FUNCTION__, 'ERR1');
+               throw new RackTablesError ('file uploads not allowed, change "file_uploads" parameter in php.ini', RackTablesError::MISCONFIGURED);
        $shortInfo = spotEntity ('file', $sic['file_id']);
 
        $fp = fopen($_FILES['file']['tmp_name'], 'rb');
@@ -1939,53 +2166,28 @@ function replaceFile ()
        return buildRedirectURL (__FUNCTION__, 'OK', array (htmlspecialchars ($shortInfo['name'])));
 }
 
-$msgcode['updateFile']['OK'] = 70;
-$msgcode['updateFile']['ERR'] = 109;
-function updateFile ()
-{
-       assertUIntArg ('file_id');
-       assertStringArg ('file_name');
-       assertStringArg ('file_type');
-       assertStringArg ('file_comment', TRUE);
-       global $sic;
-       if (FALSE === commitUpdateFile ($sic['file_id'], $sic['file_name'], $sic['file_type'], $sic['file_comment']))
-               return buildRedirectURL (__FUNCTION__, 'ERR');
-       return buildRedirectURL (__FUNCTION__, 'OK', array ($_REQUEST['file_name']));
-}
-
 $msgcode['unlinkFile']['OK'] = 72;
-$msgcode['unlinkFile']['ERR'] = 182;
+$msgcode['unlinkFile']['ERR'] = 111;
 function unlinkFile ()
 {
        assertUIntArg ('link_id');
-       $error = commitUnlinkFile ($_REQUEST['link_id']);
-
-       if ($error != '')
-               return buildRedirectURL (__FUNCTION__, 'ERR', array ($error));
-
-       return buildRedirectURL (__FUNCTION__, 'OK');
+       return buildRedirectURL (__FUNCTION__, commitUnlinkFile ($_REQUEST['link_id']) === FALSE ? 'ERR' : 'OK');
 }
 
-$msgcode['deleteFile']['OK'] = 73;
-$msgcode['deleteFile']['ERR'] = 100;
+$msgcode['deleteFile']['OK'] = 6;
 function deleteFile ()
 {
        assertUIntArg ('file_id');
        $shortInfo = spotEntity ('file', $_REQUEST['file_id']);
-       $error = commitDeleteFile ($_REQUEST['file_id']);
-
-       if ($error != '')
-               return buildRedirectURL (__FUNCTION__, 'ERR', array ($error));
-
+       commitDeleteFile ($_REQUEST['file_id']);
        return buildRedirectURL (__FUNCTION__, 'OK', array (htmlspecialchars ($shortInfo['name'])));
 }
 
-$msgcode['updateFileText']['OK'] = 78;
+$msgcode['updateFileText']['OK'] = 7;
 $msgcode['updateFileText']['ERR1'] = 179;
-$msgcode['updateFileText']['ERR2'] = 180;
+$msgcode['updateFileText']['ERR2'] = 155;
 function updateFileText ()
 {
-       assertUIntArg ('file_id');
        assertStringArg ('mtime_copy');
        assertStringArg ('file_text', TRUE); // it's Ok to save empty
        $shortInfo = spotEntity ('file', $_REQUEST['file_id']);
@@ -2008,17 +2210,6 @@ function addPortInterfaceCompat ()
        return buildRedirectURL (__FUNCTION__, 'ERR');
 }
 
-$msgcode['delPortInterfaceCompat']['OK'] = 49;
-$msgcode['delPortInterfaceCompat']['ERR'] = 111;
-function delPortInterfaceCompat ()
-{
-       assertUIntArg ('iif_id');
-       assertUIntArg ('oif_id');
-       if (commitReducePIC ($_REQUEST['iif_id'], $_REQUEST['oif_id']))
-               return buildRedirectURL (__FUNCTION__, 'OK');
-       return buildRedirectURL (__FUNCTION__, 'ERR');
-}
-
 $ifcompatpack = array
 (
        '1000cwdm80' => array (1209, 1210, 1211, 1212, 1213, 1214, 1215, 1216),
@@ -2041,14 +2232,11 @@ $ifcompatpack = array
 );
 
 $msgcode['addPortInterfaceCompatPack']['OK'] = 44;
-$msgcode['addPortInterfaceCompatPack']['ERR'] = 123;
 function addPortInterfaceCompatPack ()
 {
-       assertStringArg ('standard');
-       assertUIntArg ('iif_id');
+       genericAssertion ('standard', 'enum/wdmstd');
+       genericAssertion ('iif_id', 'iif');
        global $ifcompatpack;
-       if (!array_key_exists ($_REQUEST['standard'], $ifcompatpack) or !array_key_exists ($_REQUEST['iif_id'], getPortIIFOptions()))
-               return buildRedirectURL (__FUNCTION__, 'ERR');
        $ngood = $nbad = 0;
        foreach ($ifcompatpack[$_REQUEST['standard']] as $oif_id)
                if (commitSupplementPIC ($_REQUEST['iif_id'], $oif_id))
@@ -2064,43 +2252,20 @@ function delPortInterfaceCompatPack ()
 {
        assertStringArg ('standard');
        assertUIntArg ('iif_id');
-       global $ifcompatpack;
-       if (!array_key_exists ($_REQUEST['standard'], $ifcompatpack) or !array_key_exists ($_REQUEST['iif_id'], getPortIIFOptions()))
+       global $ifcompatpack, $sic;
+       if (!array_key_exists ($sic['standard'], $ifcompatpack) or !array_key_exists ($sic['iif_id'], getPortIIFOptions()))
                return buildRedirectURL (__FUNCTION__, 'ERR');
        $ngood = $nbad = 0;
-       foreach ($ifcompatpack[$_REQUEST['standard']] as $oif_id)
-               if (commitReducePIC ($_REQUEST['iif_id'], $oif_id))
+       foreach ($ifcompatpack[$sic['standard']] as $oif_id)
+               if (usePreparedDeleteBlade ('PortInterfaceCompat', array ('iif_id' => $sic['iif_id'], 'oif_id' => $oif_id)))
                        $ngood++;
                else
                        $nbad++;
        return buildRedirectURL (__FUNCTION__, 'OK', array ($nbad, $ngood));
 }
 
-$msgcode['addPortOIFCompat']['OK'] = 48;
-$msgcode['addPortOIFCompat']['ERR'] = 110;
-function addPortOIFCompat()
-{
-       assertUIntArg('type1');
-       assertUIntArg('type2');
-       if (commitSupplementPOIFC($_REQUEST['type1'], $_REQUEST['type2']))
-               return buildRedirectURL(__FUNCTION__, 'OK');
-       return buildRedirectURL(__FUNCTION__, 'ERR');
-}
-
-$msgcode['delPortOIFCompat']['OK'] = 49;
-$msgcode['delPortOIFCompat']['ERR'] = 111;
-function delPortOIFCompat ()
-{
-       assertUIntArg('type1');
-       assertUIntArg('type2');
-       if (commitReducePOIFC ($_REQUEST['type1'], $_REQUEST['type2']) !== FALSE)
-               return buildRedirectURL (__FUNCTION__, 'OK');
-       return buildRedirectURL (__FUNCTION__, 'ERR');
-
-}
-
 $msgcode['add8021QOrder']['OK'] = 48;
-$msgcode['add8021QOrder']['ERR'] = 118;
+$msgcode['add8021QOrder']['ERR'] = 110;
 function add8021QOrder ()
 {
        assertUIntArg ('vdom_id');
@@ -2117,38 +2282,21 @@ function add8021QOrder ()
 }
 
 $msgcode['del8021QOrder']['OK'] = 49;
-$msgcode['del8021QOrder']['ERR'] = 119;
+$msgcode['del8021QOrder']['ERR'] = 111;
 function del8021QOrder ()
 {
        assertUIntArg ('object_id');
+       assertUIntArg ('vdom_id');
+       assertUIntArg ('vst_id');
        global $sic;
        $result = usePreparedDeleteBlade ('VLANSwitch', array ('object_id' => $sic['object_id']));
-       return buildRedirectURL (__FUNCTION__, $result ? 'OK' : 'ERR');
-}
-
-$msgcode['addVLANDescription']['OK'] = 48;
-$msgcode['addVLANDescription']['ERR1'] = 190;
-$msgcode['addVLANDescription']['ERR2'] = 110;
-function addVLANDescription ()
-{
-       assertUIntArg ('vlan_id');
-       assertStringArg ('vlan_type', TRUE);
-       assertStringArg ('vlan_descr', TRUE);
-       global $sic;
-       if (!($sic['vlan_id'] >= VLAN_MIN_ID + 1 and $sic['vlan_id'] <= VLAN_MAX_ID))
-               return buildRedirectURL (__FUNCTION__, 'ERR1', array ($sic['vlan_id']));
-       $result = usePreparedInsertBlade
+       $focus_hints = array
        (
-               'VLANDescription',
-               array
-               (
-                       'domain_id' => $sic['vdom_id'],
-                       'vlan_id' => $sic['vlan_id'],
-                       'vlan_type' => $sic['vlan_type'],
-                       'vlan_descr' => mb_strlen ($sic['vlan_descr']) ? $sic['vlan_descr'] : NULL
-               )
+               'prev_objid' => $_REQUEST['object_id'],
+               'prev_vstid' => $_REQUEST['vst_id'],
+               'prev_vdid' => $_REQUEST['vdom_id'],
        );
-       return buildRedirectURL (__FUNCTION__, $result ? 'OK' : 'ERR2');
+       return buildRedirectURL (__FUNCTION__, $result ? 'OK' : 'ERR', array(), NULL, NULL, $focus_hints);
 }
 
 $msgcode['delVLANDescription']['OK'] = 49;
@@ -2166,7 +2314,6 @@ function delVLANDescription ()
 
 $msgcode['updVLANDescription']['OK'] = 51;
 $msgcode['updVLANDescription']['ERR1'] = 105;
-$msgcode['updVLANDescription']['ERR2'] = 109;
 function updVLANDescription ()
 {
        assertUIntArg ('vlan_id');
@@ -2175,14 +2322,21 @@ function updVLANDescription ()
        global $sic;
        if ($sic['vlan_id'] == VLAN_DFL_ID)
                return buildRedirectURL (__FUNCTION__, 'ERR1');
-       $result = commitUpdateVLANDescription
+       usePreparedUpdateBlade
        (
-               $sic['vdom_id'],
-               $sic['vlan_id'],
-               $sic['vlan_type'],
-               $sic['vlan_descr']
+               'VLANDescription',
+               array
+               (
+                       'vlan_descr' => !mb_strlen ($sic['vlan_descr']) ? NULL : $sic['vlan_descr'],
+                       'vlan_type' => $sic['vlan_type'],
+               ),
+               array
+               (
+                       'domain_id' => $sic['vdom_id'],
+                       'vlan_id' => $sic['vlan_id'],
+               )
        );
-       return buildRedirectURL (__FUNCTION__, $result !== FALSE ? 'OK' : 'ERR2');
+       return buildRedirectURL (__FUNCTION__, 'OK');
 }
 
 $msgcode['createVLANDomain']['OK'] = 48;
@@ -2223,20 +2377,8 @@ function destroyVLANDomain ()
        return buildRedirectURL (__FUNCTION__, $result ? 'OK' : 'ERR');
 }
 
-$msgcode['updateVLANDomain']['OK'] = 51;
-$msgcode['updateVLANDomain']['ERR'] = 109;
-function updateVLANDomain ()
-{
-       assertUIntArg ('vdom_id');
-       assertStringArg ('vdom_descr');
-       global $sic;
-       $result = FALSE !== commitUpdateVLANDomain ($sic['vdom_id'], $sic['vdom_descr']);
-       return buildRedirectURL (__FUNCTION__, $result ? 'OK' : 'ERR');
-}
-
 $msgcode['save8021QPorts']['OK1'] = 63;
 $msgcode['save8021QPorts']['OK2'] = 41;
-$msgcode['save8021QPorts']['ERR1'] = 160;
 $msgcode['save8021QPorts']['ERR2'] = 109;
 function save8021QPorts ()
 {
@@ -2365,6 +2507,16 @@ function bindVLANtoIPv4 ()
        return buildRedirectURL (__FUNCTION__, $result ? 'OK' : 'ERR');
 }
 
+$msgcode['bindVLANtoIPv6']['OK'] = 48;
+$msgcode['bindVLANtoIPv6']['ERR'] = 110;
+function bindVLANtoIPv6 ()
+{
+       assertUIntArg ('id'); // network id
+       global $sic;
+       $result = commitSupplementVLANIPv6 ($sic['vlan_ck'], $_REQUEST['id']);
+       return buildRedirectURL (__FUNCTION__, $result ? 'OK' : 'ERR');
+}
+
 $msgcode['unbindVLANfromIPv4']['OK'] = 49;
 $msgcode['unbindVLANfromIPv4']['ERR'] = 111;
 function unbindVLANfromIPv4 ()
@@ -2375,6 +2527,16 @@ function unbindVLANfromIPv4 ()
        return buildRedirectURL (__FUNCTION__, $result ? 'OK' : 'ERR');
 }
 
+$msgcode['unbindVLANfromIPv6']['OK'] = 49;
+$msgcode['unbindVLANfromIPv6']['ERR'] = 111;
+function unbindVLANfromIPv6 ()
+{
+       assertUIntArg ('id'); // network id
+       global $sic;
+       $result = commitReduceVLANIPv6 ($sic['vlan_ck'], $sic['id']);
+       return buildRedirectURL (__FUNCTION__, $result ? 'OK' : 'ERR');
+}
+
 $msgcode['process8021QSyncRequest']['OK'] = 63;
 $msgcode['process8021QSyncRequest']['ERR'] = 191;
 function process8021QSyncRequest ()
@@ -2386,6 +2548,21 @@ function process8021QSyncRequest ()
        return buildRedirectURL (__FUNCTION__, 'OK', array ($done));
 }
 
+$msgcode['process8021QRecalcRequest']['CHANGED'] = 87;
+$msgcode['process8021QRecalcRequest']['NO_CHANGES'] = 300;
+$msgcode['process8021QRecalcRequest']['ERR'] = 157;
+function process8021QRecalcRequest ()
+{
+       global $sic;
+       if (! permitted (NULL, NULL, NULL, array (array ('tag' => '$op_recalc8021Q'))))
+               return buildRedirectURL (__FUNCTION__, 'ERR');
+       $counters = recalc8021QPorts ($sic['object_id']);
+       if ($counters['ports'])
+               return buildRedirectURL (__FUNCTION__, 'CHANGED', array ($counters['ports'], $counters['switches']));
+       else
+               return buildRedirectURL (__FUNCTION__, 'NO_CHANGES', array ('No changes were made'));
+}
+
 $msgcode['resolve8021QConflicts']['OK'] = 63;
 $msgcode['resolve8021QConflicts']['ERR1'] = 179;
 $msgcode['resolve8021QConflicts']['ERR2'] = 109;
@@ -2479,18 +2656,11 @@ function addVLANSwitchTemplate()
 {
        assertStringArg ('vst_descr');
        global $sic;
-       $max_local_vlans = NULL;
-       if (array_key_exists ('vst_maxvlans', $sic) && mb_strlen ($sic['vst_maxvlans']))
-       {
-               assertUIntArg ('vst_maxvlans');
-               $max_local_vlans = $sic['vst_maxvlans'];
-       }
        $result = usePreparedInsertBlade
        (
                'VLANSwitchTemplate',
                array
                (
-                       'max_local_vlans' => $max_local_vlans,
                        'description' => $sic['vst_descr'],
                )
        );
@@ -2507,92 +2677,60 @@ function delVLANSwitchTemplate()
        return buildRedirectURL (__FUNCTION__, $result ? 'OK' : 'ERR');
 }
 
-$msgcode['updVLANSwitchTemplate']['OK'] = 51;
-$msgcode['updVLANSwitchTemplate']['ERR'] = 109;
-function updVLANSwitchTemplate()
-{
-       assertUIntArg ('vst_id');
-       assertStringArg ('vst_descr');
-       global $sic;
-       $max_local_vlans = NULL;
-       if (array_key_exists ('vst_maxvlans', $sic) && mb_strlen ($sic['vst_maxvlans']))
-       {
-               assertUIntArg ('vst_maxvlans');
-               $max_local_vlans = $sic['vst_maxvlans'];
-       }
-       $result = commitUpdateVST ($sic['vst_id'], $max_local_vlans, $sic['vst_descr']);
-       return buildRedirectURL (__FUNCTION__, $result !== FALSE ? 'OK' : 'ERR');
-}
-
-$msgcode['addVSTRule']['OK'] = 48;
-$msgcode['addVSTRule']['ERR'] = 110;
-function addVSTRule()
-{
-       assertUIntArg ('vst_id');
-       assertUIntArg ('rule_no');
-       assertPCREArg ('port_pcre');
-       assertStringArg ('port_role');
-       assertStringArg ('wrt_vlans', TRUE);
-       assertStringArg ('description', TRUE);
-       global $sic;
-       $result = usePreparedInsertBlade
-       (
-               'VLANSTRule',
-               array
-               (
-                       'vst_id' => $sic['vst_id'],
-                       'rule_no' => $sic['rule_no'],
-                       'port_pcre' => $sic['port_pcre'],
-                       'port_role' => $sic['port_role'],
-                       'wrt_vlans' => $sic['wrt_vlans'],
-                       'description' => $sic['description'],
-               )
-       );
-       return buildRedirectURL (__FUNCTION__, $result ? 'OK' : 'ERR');
-}
-
-$msgcode['delVSTRule']['OK'] = 49;
-$msgcode['delVSTRule']['ERR'] = 111;
-function delVSTRule()
+$msgcode['cloneVST']['OK'] = 48;
+$msgcode['cloneVST']['ERR'] = 179;
+function cloneVST()
 {
-       assertUIntArg ('vst_id');
-       assertUIntArg ('rule_no');
-       global $sic;
-       $result = FALSE !== usePreparedDeleteBlade
-       (
-               'VLANSTRule',
-               array
-               (
-                       'vst_id' => $sic['vst_id'],
-                       'rule_no' => $sic['rule_no']
-               )
-       );
-       return buildRedirectURL (__FUNCTION__, $result ? 'OK' : 'ERR');
+       assertUIntArg ('mutex_rev', TRUE);
+       assertUIntArg ('from_id');
+       $src_vst = getVLANSwitchTemplate ($_REQUEST['from_id']);
+       commitUpdateVSTRules (getBypassValue(), $_REQUEST['mutex_rev'], $src_vst['rules']);
+       return buildRedirectURL (__FUNCTION__, 'OK');
 }
 
-$msgcode['updVSTRule']['OK'] = 51;
-$msgcode['updVSTRule']['ERR'] = 109;
+$msgcode['updVSTRule']['OK'] = 43;
 function updVSTRule()
 {
-       assertUIntArg ('vst_id');
-       assertUIntArg ('rule_no');
-       assertUIntArg ('new_rule_no');
-       assertPCREArg ('port_pcre');
-       assertStringArg ('port_role');
-       assertStringArg ('wrt_vlans', TRUE);
-       assertStringArg ('description', TRUE);
-       global $sic;
-       $result = commitUpdateVSTRule
-       (
-               $sic['vst_id'],
-               $sic['rule_no'],
-               $sic['new_rule_no'],
-               $sic['port_pcre'],
-               $sic['port_role'],
-               $sic['wrt_vlans'],
-               $sic['description']
-       );
-       return buildRedirectURL (__FUNCTION__, $result !== FALSE ? 'OK' : 'ERR');
+       // this is used for making throwing an invalid argument exception easier.
+       function updVSTRule_get_named_param ($name, $haystack, &$last_used_name)
+       {
+               $last_used_name = $name;
+               return isset ($haystack[$name]) ? $haystack[$name] : NULL;
+       }
+
+       global $port_role_options, $sic;
+       assertUIntArg ('mutex_rev', TRUE);
+       genericAssertion ('template_json', 'json');
+       $data = json_decode ($sic['template_json'], TRUE);
+       $rule_no = 0;
+       try
+       {
+               $last_field = '';
+               foreach ($data as $rule)
+               {
+                       $rule_no++;
+                       if
+                       (
+                               ! isInteger (updVSTRule_get_named_param ('rule_no', $rule, $last_field))
+                               or ! isPCRE (updVSTRule_get_named_param ('port_pcre', $rule, $last_field))
+                               or NULL === updVSTRule_get_named_param ('port_role', $rule, $last_field)
+                               or ! array_key_exists (updVSTRule_get_named_param ('port_role', $rule, $last_field), $port_role_options)
+                               or NULL ===  updVSTRule_get_named_param ('wrt_vlans', $rule, $last_field)
+                               or ! preg_match ('/^[ 0-9\-,]*$/',  updVSTRule_get_named_param ('wrt_vlans', $rule, $last_field))
+                               or NULL ===  updVSTRule_get_named_param ('description', $rule, $last_field)
+                       )
+                               throw new InvalidRequestArgException ($last_field, $rule[$last_field], "rule #$rule_no");
+               }
+               commitUpdateVSTRules ($_REQUEST['vst_id'], $_REQUEST['mutex_rev'], $data);
+       }
+       catch (Exception $e)
+       {
+               // Every case, which is soft-processed in process.php, will have the working copy available for a retry.
+               if ($e instanceof InvalidRequestArgException or $e instanceof RTDatabaseError)
+                       $_SESSION['vst_edited'] = $data;
+               throw $e;
+       }
+       return buildRedirectURL (__FUNCTION__, 'OK');
 }
 
 $msgcode['importDPData']['OK'] = 44;
@@ -2631,4 +2769,87 @@ function importDPData()
        return buildRedirectURL (__FUNCTION__, 'OK', array ($nignored, $ndone));
 }
 
+$msgcode['addObjectlog']['OK'] = 0;
+function addObjectlog ()
+{
+       assertStringArg ('logentry');
+       global $remote_username, $sic;
+       $oi = spotEntity ('object', $sic['object_id']);
+       usePreparedExecuteBlade ('INSERT INTO ObjectLog SET object_id=?, user=?, date=NOW(), content=?', array ($sic['object_id'], $remote_username, $sic['logentry']));
+       return buildRedirectURL (__FUNCTION__, 'OK', array ('Log entry for ' . mkA ($oi['dname'], 'object', $sic['object_id'], 'log') . " added by ${remote_username}"));
+}
+
+function getOpspec()
+{
+       global $pageno, $tabno, $op, $opspec_list;
+       if (!array_key_exists ($pageno . '-' . $tabno . '-' . $op, $opspec_list))
+               throw new RackTablesError ('key not found in opspec_list', RackTablesError::INTERNAL);
+       $ret = $opspec_list[$pageno . '-' . $tabno . '-' . $op];
+       if
+       (
+               !array_key_exists ('table', $ret)
+               or !array_key_exists ('action', $ret)
+               // add further checks here
+       )
+               throw new RackTablesError ('malformed array structure in opspec_list', RackTablesError::INTERNAL);
+       return $ret;
+}
+
+function tableHandler()
+{
+       $opspec = getOpspec();
+       global $sic;
+       $columns = array();
+       foreach (array ('arglist', 'set_arglist', 'where_arglist') as $listname)
+               foreach ($opspec[$listname] as $argspec)
+               {
+                       genericAssertion ($argspec['url_argname'], $argspec['assertion']);
+                       // "table_colname" is normally used for an override, if it is not
+                       // set, use the URL argument name
+                       $table_colname = array_key_exists ('table_colname', $argspec) ?
+                               $argspec['table_colname'] :
+                               $argspec['url_argname'];
+                       $arg_value = $sic[$argspec['url_argname']];
+                       if
+                       (
+                               ($argspec['assertion'] == 'uint0' and $arg_value == 0)
+                               or ($argspec['assertion'] == 'string0' and $arg_value == '')
+                       )
+                               switch (TRUE)
+                               {
+                               case !array_key_exists ('if_empty', $argspec): // no action requested
+                                       break;
+                               case $argspec['if_empty'] == 'NULL':
+                                       $arg_value = NULL;
+                                       break;
+                               default:
+                                       throw new InvalidArgException ('opspec', '(malformed array structure)', '"if_empty" not recognized');
+                               }
+                       $columns[$listname][$table_colname] = $arg_value;
+               }
+       switch ($opspec['action'])
+       {
+       case 'INSERT':
+               $retcode = TRUE === usePreparedInsertBlade ($opspec['table'], $columns['arglist']) ? 48 : 110;
+               break;
+       case 'DELETE':
+               $conjunction = array_key_exists ('conjunction', $opspec) ? $opspec['conjunction'] : 'AND';
+               $retcode = FALSE !== usePreparedDeleteBlade ($opspec['table'], $columns['arglist'], $conjunction) ? 49 : 111;
+               break;
+       case 'UPDATE':
+               usePreparedUpdateBlade
+               (
+                       $opspec['table'],
+                       $columns['set_arglist'],
+                       $columns['where_arglist'],
+                       array_key_exists ('conjunction', $opspec) ? $opspec['conjunction'] : 'AND'
+               );
+               $retcode = 51;
+               break;
+       default:
+               throw new InvalidArgException ('opspec/action', $opspec['action']);
+       }
+       return buildWideRedirectURL (oneLiner ($retcode));
+}
+
 ?>