function addTable()
{
    global $TABLE_PREFIX, $APP;
    $menuType = @$_REQUEST['menuType'];
    $presetTableName = @$_REQUEST['presetName'];
    $advancedType = @$_REQUEST['advancedType'];
    //
    security_dieUnlessPostForm();
    security_dieUnlessInternalReferer();
    security_dieOnInvalidCsrfToken();
    //
    disableInDemoMode('', 'ajax');
    // error checking
    $errors = '';
    if (!$menuType) {
        $errors .= "No menu type selected!\n";
    }
    if (!@$_REQUEST['menuName']) {
        $errors .= "No menu name specified!\n";
    }
    $errors .= getTablenameErrors(@$_REQUEST['tableName']);
    $newSchema = null;
    if ($menuType == 'copy') {
        if ($errors) {
            die($errors);
        }
        $sourceSchemaName = @$_REQUEST['copy'];
        if (!in_array($sourceSchemaName, getSchemaTables())) {
            die("Couldn't load source schema");
        }
        $newSchema = loadSchema($sourceSchemaName) or die("Couldn't load source schema");
    } else {
        if ($menuType == 'preset') {
            $schemaPresets = getSchemaPresets();
            $presetFound = array_key_exists(@$_REQUEST['preset'], $schemaPresets);
            if (!@$_REQUEST['preset']) {
                $errors .= "You must select a preset from the pulldown!\n";
            } elseif (!$presetFound) {
                $errors .= "No schema preset file found for '" . htmlencode($presetTableName) . "'\n";
            }
        }
        if ($errors) {
            die($errors);
        }
        // create new schema data
        if ($menuType == 'single') {
            $presetTableName = "customSingle";
        } elseif ($menuType == 'multi') {
            $presetTableName = "customMulti";
        } elseif ($menuType == 'preset') {
            $presetTableName = @$_REQUEST['preset'];
        } elseif ($menuType == 'advanced' && $advancedType == 'category') {
            $presetTableName = "customCategory";
        } elseif ($menuType == 'advanced' && $advancedType == 'textlink') {
            $presetTableName = "customTextLink";
        } elseif ($menuType == 'advanced' && $advancedType == 'menugroup') {
            $presetTableName = "customMenuGroup";
        } else {
            die("Unable to determine preset table name to load!");
        }
        $schemaPresetDir = DATA_DIR . "/schemaPresets/";
        $newSchema = loadSchema($presetTableName, $schemaPresetDir) or die("Couldn't load preset schema");
    }
    $newSchema['menuName'] = @$_REQUEST['menuName'];
    // change menu name
    $newSchema['menuOrder'] = time();
    // use time to sort to bottom
    // create mysql table
    // (this isn't required but done here so we catch get mysql errors creating the table)
    // createMissingSchemaTablesAndFields() creates if this doesn't.
    $tableNameWithPrefix = $TABLE_PREFIX . @$_REQUEST['tableName'];
    $result = mysql_query("CREATE TABLE `" . mysql_escape($tableNameWithPrefix) . "` (\n                                          num int(10) unsigned NOT NULL auto_increment,\n                                          PRIMARY KEY (num)\n                                        ) ENGINE=MyISAM DEFAULT CHARSET=utf8;");
    if (!$result) {
        print "Error creating MySQL table.\n\nMySQL error was: " . htmlencode(mysql_error()) . "\n";
        exit;
    }
    // save new schema
    saveSchema(@$_REQUEST['tableName'], $newSchema);
    // Create schema table and fields in MySQL
    createMissingSchemaTablesAndFields();
    clearAlertsAndNotices();
    // don't display alerts about adding new fields
    exit;
    // this is called with ajax so returning nothing means success - see: addTable_functions.js - initSubmitFormWithAjax
}
function saveTableDetails()
{
    global $TABLE_PREFIX, $schema, $APP, $tableName, $tableNameWithPrefix;
    $oldSchemaFilepath = DATA_DIR . '/schema/' . getTableNameWithoutPrefix($_REQUEST['tableName']) . ".ini.php";
    $newSchemaFilepath = DATA_DIR . '/schema/' . getTableNameWithoutPrefix($_REQUEST['newTableName']) . ".ini.php";
    //
    security_dieUnlessPostForm();
    security_dieUnlessInternalReferer();
    security_dieOnInvalidCsrfToken();
    //
    disableInDemoMode('', 'database/listTables.php');
    // error checking
    $errors = '';
    if ($_REQUEST['newTableName'] == '') {
        $errors .= "You must specify a tablename!<br/>\n";
    }
    if (preg_match("/dragSortOrder/", @$_REQUEST['listPageFields']) || preg_match("/dragSortOrder/", $_REQUEST['listPageOrder'])) {
        if (!preg_match("/^dragSortOrder/", @$_REQUEST['listPageFields'])) {
            $errors .= "If used, dragSortOrder must be the first field in 'ListPage Fields'!<br/>\n";
        }
        if (!preg_match("/^dragSortOrder/", $_REQUEST['listPageOrder'])) {
            $errors .= "If used, dragSortOrder must be the first field in 'Order By'!<br/>\n";
        }
    }
    if (@$_REQUEST['tableName'] && !$schema) {
        $errors .= "Error updating schema file.  Please wait a few seconds and try again.<br/>\n";
    }
    if (!is_writable(DATA_DIR . '/schema/')) {
        $errors .= "Schema dir '/data/schema/' isn't writable.  Please update permissions.<br/>\n";
    } elseif (!is_writable($oldSchemaFilepath)) {
        $errors .= "Schema file '/data/schema/" . basename($oldSchemaFilepath) . "' isn't writable.  Please update permissions.<br/>\n";
    }
    // v2.53 - require urls to start with scheme:// or / (to ensure links are valid when moving between sites)
    $fieldNamesToLabels = array();
    $fieldNamesToLabels['_listPage'] = 'List Page Url';
    $fieldNamesToLabels['_detailPage'] = 'Detail Page Url';
    $fieldNamesToLabels['_previewPage'] = 'Preview Page Url';
    foreach ($fieldNamesToLabels as $name => $label) {
        $startsWithHttpOrSlash = preg_match("|^(\\w+:/)?/|", @$_REQUEST[$name]);
        if (@$_REQUEST[$name] && !$startsWithHttpOrSlash) {
            $errors .= t("{$label} must start with /") . "<br/>\n";
        }
    }
    //
    if ($errors) {
        alert($errors);
        return;
    }
    // force add table prefix (if not specified)
    $_REQUEST['newTableName'] = getTableNameWithPrefix($_REQUEST['newTableName']);
    ### rename table
    if ($_REQUEST['tableName'] != $_REQUEST['newTableName']) {
        $error = getTablenameErrors($_REQUEST['newTableName']);
        if ($error) {
            alert($error);
            return;
        }
        // rename mysql table
        $result = mysql_query("RENAME TABLE `" . mysql_escape($_REQUEST['tableName']) . "`\n                                        TO `" . mysql_escape($_REQUEST['newTableName']) . "`") or die("Error renaming MySQL table:\n\n" . htmlencode(mysql_error()) . "\n");
        // rename schema file
        rename_winsafe($oldSchemaFilepath, $newSchemaFilepath) or die("Error renaming schema file!");
        // update uploads table with new table name
        $where = array('tableName' => getTableNameWithoutPrefix($_REQUEST['tableName']));
        // old tableName
        $colsToValues = array('tableName' => getTableNameWithoutPrefix($_REQUEST['newTableName']));
        // new tableName
        $result = mysql_update('uploads', null, $where, $colsToValues);
        // update tableName form field
        $_REQUEST['tableName'] = $_REQUEST['newTableName'];
        // update globals with new tablename
        $tableName = $_REQUEST['tableName'];
        // sic
        $tableNameWithPrefix = $_REQUEST['tableName'];
    }
    ### update schema fields
    $schema['menuName'] = $_REQUEST['menuName'];
    $schema['_indent'] = @$_REQUEST['_indent'];
    $schema['menuType'] = $_REQUEST['menuType'];
    $schema['menuOrder'] = $_REQUEST['menuOrder'];
    if ($_REQUEST['menuType'] != 'link') {
        $schema['menuHidden'] = $_REQUEST['menuHidden'];
        $schema['listPageFields'] = @$_REQUEST['listPageFields'];
        $schema['listPageOrder'] = $_REQUEST['listPageOrder'];
        $schema['listPageSearchFields'] = $_REQUEST['listPageSearchFields'];
        $schema['_perPageDefault'] = @$_REQUEST['_perPageDefault'];
        $schema['_maxRecords'] = $_REQUEST['_maxRecords'];
        $schema['_maxRecordsPerUser'] = $_REQUEST['_maxRecordsPerUser'];
        $schema['_disableAdd'] = $_REQUEST['_disableAdd'];
        $schema['_disableView'] = $_REQUEST['_disableView'];
        $schema['_disableModify'] = $_REQUEST['_disableModify'];
        $schema['_disableErase'] = $_REQUEST['_disableErase'];
        $schema['_disablePreview'] = $_REQUEST['_disablePreview'];
        $schema['_filenameFields'] = @$_REQUEST['_filenameFields'];
        $schema['_listPage'] = @$_REQUEST['_listPage'];
        $schema['_detailPage'] = $_REQUEST['_detailPage'];
        $schema['_previewPage'] = $_REQUEST['_previewPage'];
        $schema['_hideRecordsFromDisabledAccounts'] = $_REQUEST['_hideRecordsFromDisabledAccounts'];
        $schema['_requiredPlugins'] = @$_REQUEST['_requiredPlugins'];
    }
    if ($_REQUEST['menuType'] == 'link') {
        $schema['_url'] = $_REQUEST['_url'];
        $schema['_linkTarget'] = @$_REQUEST['_linkTarget'];
        $schema['_linkMessage'] = @$_REQUEST['_linkMessage'];
        $schema['_iframeHeight'] = @$_REQUEST['_iframeHeight'];
        unset($schema['_targetBlank']);
        // unset old schema value (if it exists)
    }
    if ($_REQUEST['menuType'] == 'category') {
        $schema['_maxDepth'] = $_REQUEST['_maxDepth'];
    }
    saveSchema($_REQUEST['tableName'], $schema);
    //
    notice("Table details for '" . htmlencode($schema['menuName']) . "' have been saved.");
}