Beispiel #1
0
/**
 * The Export Manager installation function. This is automatically called by the installation script if the
 * module is contained in the zipfile. Otherwise it's called when the user manually installs the module.
 */
function export_manager__install($module_id)
{
    global $g_table_prefix, $g_root_dir, $g_root_url, $LANG;
    $queries = array();
    $word_display = ft_sanitize($LANG["word_display"]);
    $queries[] = "\n    CREATE TABLE {$g_table_prefix}module_export_groups (\n      export_group_id smallint(5) unsigned NOT NULL auto_increment,\n      group_name varchar(255) NOT NULL,\n      access_type enum('admin','public','private') NOT NULL default 'public',\n      form_view_mapping enum('all','except','only') NOT NULL default 'all',\n      forms_and_views mediumtext NULL,\n      visibility enum('show','hide') NOT NULL default 'show',\n      icon varchar(100) NOT NULL,\n      action enum('file','popup','new_window') NOT NULL default 'popup',\n      action_button_text varchar(255) NOT NULL default '{$word_display}',\n      popup_height varchar(5) default NULL,\n      popup_width varchar(5) default NULL,\n      headers text,\n      smarty_template mediumtext NOT NULL,\n      list_order tinyint(4) NOT NULL,\n      PRIMARY KEY  (export_group_id)\n    ) DEFAULT CHARSET=utf8\n      ";
    $queries[] = "\n    CREATE TABLE {$g_table_prefix}module_export_group_clients (\n      export_group_id mediumint(8) unsigned NOT NULL,\n      account_id mediumint(8) unsigned NOT NULL,\n      PRIMARY KEY  (export_group_id, account_id)\n    ) DEFAULT CHARSET=utf8\n      ";
    $queries[] = "\n    CREATE TABLE {$g_table_prefix}module_export_types (\n      export_type_id mediumint(8) unsigned NOT NULL auto_increment,\n      export_type_name varchar(255) NOT NULL,\n      export_type_visibility enum('show','hide') NOT NULL default 'show',\n      filename varchar(255) NOT NULL,\n      export_group_id smallint(6) default NULL,\n      smarty_template text NOT NULL,\n      list_order tinyint(3) unsigned NOT NULL,\n      PRIMARY KEY (export_type_id)\n    ) DEFAULT CHARSET=utf8\n      ";
    foreach ($queries as $query) {
        $result = mysql_query($query);
        if (!$result) {
            exp_remove_tables();
            return array(false, $LANG["export_manager"]["notify_installation_problem_c"] . " <b>" . mysql_error() . "</b>");
        }
    }
    // now populate the tables
    list($success, $message) = exp_insert_default_data();
    if (!$success) {
        exp_remove_tables();
        exp_clear_table_data();
        return array(false, $message);
    }
    ft_register_hook("template", "export_manager", "admin_submission_listings_bottom", "", "exp_display_export_options");
    ft_register_hook("template", "export_manager", "client_submission_listings_bottom", "", "exp_display_export_options");
    return array(true, "");
}
/**
 * Inserts a new list group.
 *
 * @param $account_id
 */
function ft_add_list_group($group_type, $group_name, $next_order = "")
{
    global $g_table_prefix;
    $group_name = ft_sanitize($group_name);
    if (empty($next_order)) {
        // get the next list_order for this group
        $query = mysql_query("\n      SELECT list_order\n      FROM   {$g_table_prefix}list_groups\n      WHERE  group_type = '{$group_type}'\n      ORDER BY list_order DESC LIMIT 1\n    ");
        $result = mysql_fetch_assoc($query);
        $next_order = !isset($result["list_order"]) ? 1 : $result["list_order"] + 1;
    }
    $query = mysql_query("\n    INSERT INTO {$g_table_prefix}list_groups (group_type, group_name, custom_data, list_order)\n    VALUES ('{$group_type}', '{$group_name}', '', {$next_order})\n  ");
    $group_id = mysql_insert_id();
    return array("group_id" => $group_id, "group_name" => $group_name);
}
Beispiel #3
0
/**
 * Called by module installation files, and/or whenever needed. This function logs new hooks in the
 * database. This function is called by the module designers WITHIN their own modules.
 *
 * @param string $hook_type "code" or "template"
 * @param string $when when in the functions the hooks should be processed. For code hooks, these are
 *    either "start" or "end"; for template hooks, this is the location attribute of the {template_hook ...}
 *    tag.
 * @param string $function_name the name of the function to which this hook is to be attached
 * @param string $hook_function the name of the hook function, found in the modules library.php file
 * @param integer $priority 1-100 (100 lowest, 1 highest). Optional setting that determines the order
 *    in which this hook gets processed, in relation to OTHER hooks attached to the same event.
 * @param boolean $force_unique if set to true, this will only register hooks that haven't been set
 *    with this module, location, hook and core function.
 */
function ft_register_hook($hook_type, $module_folder, $when, $function_name, $hook_function, $priority = 50, $force_unique = false)
{
    global $g_table_prefix;
    $when = ft_sanitize($when);
    $function_name = ft_sanitize($function_name);
    $hook_function = ft_sanitize($hook_function);
    $may_proceed = true;
    if ($force_unique) {
        $query = mysql_query("\r\n      SELECT count(*) as c\r\n      FROM   {$g_table_prefix}hook_calls\r\n      WHERE  hook_type = '{$hook_type}' AND\r\n             action_location = '{$when}' AND\r\n             module_folder = '{$module_folder}' AND\r\n             function_name = '{$function_name}' AND\r\n             hook_function = '{$hook_function}'\r\n        ");
        $result = mysql_fetch_assoc($query);
        if ($result["c"] > 0) {
            $may_proceed = false;
        }
    }
    $result = mysql_query("\r\n    INSERT INTO {$g_table_prefix}hook_calls (hook_type, action_location, module_folder, function_name, hook_function, priority)\r\n    VALUES ('{$hook_type}', '{$when}', '{$module_folder}', '{$function_name}', '{$hook_function}', {$priority})\r\n      ");
    if ($result) {
        $hook_id = mysql_insert_id();
        return array(true, $hook_id);
    } else {
        return array(false, "");
    }
}
Beispiel #4
0
/**
 * Adds/updates all options for a given field. This is called when the user edits fields from the dialog
 * window on the Fields tab. It updates all information about a field: including the custom settings.
 *
 * @param integer $form_id The unique form ID
 * @param integer $field_id The unique field ID
 * @param integer $info a hash containing tab1 and/or tab2 indexes, containing all the latest values for
 *                the field
 * @param array [0] success/fail (boolean), [1] empty string for success, or error message
 */
function ft_update_field($form_id, $field_id, $tab_info)
{
    global $g_table_prefix, $g_field_sizes, $g_debug, $LANG;
    $tab_info = ft_sanitize($tab_info);
    $existing_form_field_info = ft_get_form_field($field_id);
    // TAB 1: this tab contains the standard settings shared by all fields, regardless of type: display text,
    // form field name, field type, pass on, field size, data type and database col name
    $db_col_name_changes = array();
    if (is_array($tab_info["tab1"])) {
        $info = $tab_info["tab1"];
        $display_name = _ft_extract_array_val($info, "edit_field__display_text");
        // bit weird. this field is a checkbox, so if it's not checked it won't be in the request and
        // _ft_extract_array_val returns an empty string
        $include_on_redirect = _ft_extract_array_val($info, "edit_field__pass_on");
        $include_on_redirect = empty($include_on_redirect) ? "no" : "yes";
        if ($existing_form_field_info["is_system_field"] == "yes") {
            $query = "\n        UPDATE {$g_table_prefix}form_fields\n        SET    field_title = '{$display_name}',\n               include_on_redirect = '{$include_on_redirect}'\n        WHERE  field_id = {$field_id}\n      ";
            $result = mysql_query($query);
            if (!$result) {
                return array(false, $LANG["phrase_query_problem"] . $query);
            }
        } else {
            $field_name = _ft_extract_array_val($info, "edit_field__field_name");
            $field_type_id = _ft_extract_array_val($info, "edit_field__field_type");
            $field_size = _ft_extract_array_val($info, "edit_field__field_size");
            $data_type = _ft_extract_array_val($info, "edit_field__data_type");
            $col_name = _ft_extract_array_val($info, "edit_field__db_column");
            $query = mysql_query("\n        UPDATE {$g_table_prefix}form_fields\n        SET    field_name = '{$field_name}',\n               field_type_id = '{$field_type_id}',\n               field_size = '{$field_size}',\n               field_title = '{$display_name}',\n               data_type = '{$data_type}',\n               include_on_redirect = '{$include_on_redirect}',\n               col_name = '{$col_name}'\n        WHERE  field_id = {$field_id}\n          ");
            // if the column name or field size just changed, we need to "physically" update the form's database table
            // If this fails, we rollback both the field TYPE and the field size.
            // BUG The *one* potential issue here is if the user just deleted a field type, then updated a field which - for
            // whatever reason - fails. But this is very much a fringe case
            $old_field_size = $existing_form_field_info["field_size"];
            $old_col_name = $existing_form_field_info["col_name"];
            $old_field_type_id = $existing_form_field_info["field_type_id"];
            if ($old_field_size != $field_size || $old_col_name != $col_name) {
                $new_field_size_sql = $g_field_sizes[$field_size]["sql"];
                $table_name = "{$g_table_prefix}form_{$form_id}";
                list($is_success, $err_message) = _ft_alter_table_column($table_name, $old_col_name, $col_name, $new_field_size_sql);
                if ($is_success) {
                    if ($old_col_name != $col_name) {
                        $db_col_name_changes[] = $field_id;
                    }
                } else {
                    $query = mysql_query("\n            UPDATE {$g_table_prefix}form_fields\n            SET    field_type_id = '{$old_field_type_id}',\n                   field_size    = '{$old_field_size}',\n                   col_name      = '{$old_col_name}'\n            WHERE  field_id = {$field_id}\n              ");
                    return array(false, $LANG["phrase_query_problem"] . $err_message);
                }
            }
            // if the field type just changed, the field-specific settings are orphaned. Drop them. In this instance, the
            // client-side code ensures that the contents of the second tab are always passed so the code below will add
            // any default values that are needed
            if ($old_field_type_id != $field_type_id) {
                ft_delete_extended_field_settings($field_id);
            }
        }
    }
    // if any of the database column names just changed we need to update any View filters that relied on them
    if (!empty($db_col_name_changes)) {
        foreach ($db_col_name_changes as $field_id) {
            ft_update_field_filters($field_id);
        }
    }
    // TAB 2: update the custom field settings for this field type. tab2 can be any of these values:
    //  1. a string "null": indicating that the user didn't change anything on the tab)
    //  2. the empty string: indicating that things DID change, but nothing is being passed on. This can happen
    //                      when the user checked the "Use Default Value" for all fields on the tab & the tab
    //                      doesn't contain an option list or form field
    //  3. an array of values
    if (isset($tab_info["tab2"]) && $tab_info["tab2"] != "null") {
        $info = is_array($tab_info["tab2"]) ? $tab_info["tab2"] : array();
        // since the second tab is being updated, we can rely on all the latest & greatest values being passed
        // in the request, so clean out all old values
        ft_delete_extended_field_settings($field_id);
        // convert the $info (which is an array of hashes) into a friendlier hash. This makes detecting for Option
        // List fields much easier
        $setting_hash = array();
        for ($i = 0; $i < count($info); $i++) {
            $setting_hash[$info[$i]["name"]] = $info[$i]["value"];
        }
        $new_settings = array();
        while (list($setting_name, $setting_value) = each($setting_hash)) {
            // ignore the additional field ID and field order rows that are custom to Option List / Form Field types. They'll
            // be handled below
            if (preg_match("/edit_field__setting_(\\d)+_field_id/", $setting_name) || preg_match("/edit_field__setting_(\\d)+_field_order/", $setting_name)) {
                continue;
            }
            // TODO BUG. newlines aren't surviving this... why was it added? double quotes? single quotes?
            $setting_value = ft_sanitize(stripslashes($setting_value));
            $setting_id = preg_replace("/edit_field__setting_/", "", $setting_name);
            // if this field is being mapped to a form field, we serialize the form ID, field ID and order into a single var and
            // give it a "form_field:" prefix, so we know exactly what the data contains & we can select the appropriate form ID
            // and not Option List ID on re-editing. This keeps everything pretty simple, rather than spreading the data amongst
            // multiple fields
            if (preg_match("/^ft/", $setting_value)) {
                $setting_value = preg_replace("/^ft/", "", $setting_value);
                $setting_value = "form_field:{$setting_value}|" . $setting_hash["edit_field__setting_{$setting_id}_field_id"] . "|" . $setting_hash["edit_field__setting_{$setting_id}_field_order"];
            }
            $new_settings[] = "({$field_id}, {$setting_id}, '{$setting_value}')";
        }
        if (!empty($new_settings)) {
            $new_settings_str = implode(",", $new_settings);
            $query = "\n        INSERT INTO {$g_table_prefix}field_settings (field_id, setting_id, setting_value)\n        VALUES {$new_settings_str}\n      ";
            $result = @mysql_query($query) or die($query . " - " . mysql_error());
            if (!$result) {
                return array(false, $LANG["phrase_query_problem"] . $query . ", " . mysql_error());
            }
        }
    }
    if (isset($tab_info["tab3"]) && $tab_info["tab3"] != "null") {
        $validation = is_array($tab_info["tab3"]) ? $tab_info["tab3"] : array();
        mysql_query("DELETE FROM {$g_table_prefix}field_validation WHERE field_id = {$field_id}");
        $new_rules = array();
        foreach ($validation as $rule_info) {
            // ignore the checkboxes - we don't need 'em
            if (!preg_match("/^edit_field__v_(.*)_message\$/", $rule_info["name"], $matches)) {
                continue;
            }
            $rule_id = $matches[1];
            $error_message = ft_sanitize($rule_info["value"]);
            mysql_query("\n        INSERT INTO {$g_table_prefix}field_validation (rule_id, field_id, error_message)\n        VALUES ({$rule_id}, {$field_id}, '{$error_message}')\n      ");
        }
    }
    $success = true;
    $message = $LANG["notify_form_field_options_updated"];
    extract(ft_process_hook_calls("end", compact("field_id"), array("success", "message")), EXTR_OVERWRITE);
    return array($success, $message);
}
Beispiel #5
0
/**
 * Updates a client menu.
 *
 * @param array $info
 */
function ft_update_client_menu($info)
{
    global $g_table_prefix, $g_pages, $g_root_url, $LANG;
    $info = ft_sanitize($info);
    $menu_id = $info["menu_id"];
    $menu = trim($info["menu"]);
    $sortable_id = $info["sortable_id"];
    mysql_query("\r\n    UPDATE {$g_table_prefix}menus\r\n    SET    menu    = '{$menu}'\r\n    WHERE  menu_id = {$menu_id}\r\n      ");
    $sortable_rows = explode(",", $info["{$sortable_id}_sortable__rows"]);
    $sortable_new_groups = explode(",", $info["{$sortable_id}_sortable__new_groups"]);
    $menu_items = array();
    foreach ($sortable_rows as $i) {
        // if this row doesn't have a page identifier, just ignore it
        if (!isset($info["page_identifier_{$i}"]) || empty($info["page_identifier_{$i}"])) {
            continue;
        }
        $page_identifier = $info["page_identifier_{$i}"];
        $display_text = ft_sanitize($info["display_text_{$i}"]);
        $custom_options = isset($info["custom_options_{$i}"]) ? ft_sanitize($info["custom_options_{$i}"]) : "";
        $is_submenu = isset($info["submenu_{$i}"]) ? "yes" : "no";
        // construct the URL for this menu item
        $url = ft_construct_page_url($page_identifier, $custom_options);
        $menu_items[] = array("url" => $url, "page_identifier" => $page_identifier, "display_text" => $display_text, "custom_options" => $custom_options, "is_submenu" => $is_submenu, "is_new_sort_group" => in_array($i, $sortable_new_groups) ? "yes" : "no");
    }
    ksort($menu_items);
    mysql_query("DELETE FROM {$g_table_prefix}menu_items WHERE menu_id = {$menu_id}");
    $order = 1;
    foreach ($menu_items as $hash) {
        $url = $hash["url"];
        $page_identifier = $hash["page_identifier"];
        $display_text = $hash["display_text"];
        $custom_options = $hash["custom_options"];
        $is_submenu = $hash["is_submenu"];
        $is_new_sort_group = $hash["is_new_sort_group"];
        mysql_query("\r\n      INSERT INTO {$g_table_prefix}menu_items (menu_id, display_text, page_identifier, custom_options, url, is_submenu,\r\n        list_order, is_new_sort_group)\r\n      VALUES ({$menu_id}, '{$display_text}', '{$page_identifier}', '{$custom_options}', '{$url}', '{$is_submenu}',\r\n        {$order}, '{$is_new_sort_group}')\r\n        ");
        $order++;
    }
    $success = true;
    $message = $LANG["notify_client_menu_updated"];
    extract(ft_process_hook_calls("end", compact("info"), array("success", "message")), EXTR_OVERWRITE);
    return array($success, $message);
}
Beispiel #6
0
<?php

require_once "../../global/library.php";
ft_init_module_page();
if (isset($_GET["repair"])) {
    $module_ids = explode(",", $_GET["repair"]);
    list($g_success, $g_message) = sc_reset_module_hook_calls($module_ids);
}
// example
//sc_generate_module_hook_array("module_hooks_manager_rules", "1.1.4");
//exit;
$word_testing_uc = mb_strtoupper($L["word_untested"]);
$word_passed_uc = mb_strtoupper($L["word_passed"]);
$word_failed_uc = mb_strtoupper($L["word_failed"]);
$notify_hook_verification_complete_problems = ft_sanitize($L["notify_hook_verification_complete_problems"]);
$page_vars = array();
$page_vars["module_list"] = sc_get_compatible_modules("hooks");
//print_r($page_vars["module_list"]);
$page_vars["head_string"] = <<<EOF
<script src="{$g_root_url}/modules/system_check/global/scripts/tests.js"></script>
<link type="text/css" rel="stylesheet" href="{$g_root_url}/modules/system_check/global/css/styles.css">
<script>
g.messages = [];
g.messages["word_testing_c"] = "{$L["word_testing_c"]}";
g.messages["word_untested"] = "{$word_testing_uc}";
g.messages["word_passed"] = "{$word_passed_uc}";
g.messages["word_failed"] = "{$word_failed_uc}";
g.messages["phrase_missing_table_c"] = "{$L["phrase_missing_table_c"]}";
g.messages["phrase_missing_column_c"] = "{$L["phrase_missing_column_c"]}";
g.messages["phrase_table_looks_good_c"] = "{$L["phrase_table_looks_good_c"]}";
g.messages["phrase_invalid_column_c"] = "{$L["phrase_invalid_column_c"]}";
Beispiel #7
0
        $force_delete = $request["force_delete"] == "true" ? true : false;
        // TODO beef up the security here. Check that the person logged in is permitted to see this submission & field...
        list($success, $message) = ft_file_delete_file_submission($form_id, $submission_id, $field_id, $force_delete);
        $success = $success ? 1 : 0;
        $message = ft_sanitize($message);
        $message = preg_replace("/\\\\'/", "'", $message);
        echo "{ \"success\": \"{$success}\", \"message\": \"{$message}\" {$return_str} }";
        break;
        // this is called when the field type is being used in the Form Builder. This is just slightly more restrictive than
        // the logged-in context: it pulls the form ID and submission ID from sessions instead of from the page (which could
        // be hacked)
    // this is called when the field type is being used in the Form Builder. This is just slightly more restrictive than
    // the logged-in context: it pulls the form ID and submission ID from sessions instead of from the page (which could
    // be hacked)
    case "delete_submission_file_standalone":
        $published_form_id = isset($request["published_form_id"]) ? $request["published_form_id"] : "";
        if (empty($published_form_id)) {
            echo "{ \"success\": \"0\", \"message\": \"Your form is missing the form_tools_published_form_id ID field.\" {$return_str} }";
            exit;
        }
        $form_id = $_SESSION["form_builder_{$published_form_id}"]["form_tools_form_id"];
        $submission_id = $_SESSION["form_builder_{$published_form_id}"]["form_tools_submission_id"];
        $field_id = $request["field_id"];
        $force_delete = $request["force_delete"] == "true" ? true : false;
        list($success, $message) = ft_file_delete_file_submission($form_id, $submission_id, $field_id, $force_delete);
        $success = $success ? 1 : 0;
        $message = ft_sanitize($message);
        $message = preg_replace("/\\\\'/", "'", $message);
        echo "{ \"success\": \"{$success}\", \"message\": \"{$message}\" {$return_str} }";
        break;
}
/**
 * Creates an identical copy of an existing Option List, or creates a new blank one. This can be handy if
 * the user was using a single group for multiple fields, but one of the form fields changed. They can just
 * create a new copy, tweak it and re-assign the field.
 *
 * If no Option List ID is passed in the first param, it creates a new blank Option List (sorry for the crappy
 * function name).
 *
 * @param integer $list_id
 * @param integer $field_id if this parameter is set, the new Option List will be assigned to whatever
 *   field IDs are specified. Note: this only works for Field Types that have a single
 * @return mixed the list ID if successful, false if not
 */
function ft_duplicate_option_list($list_id = "", $field_ids = array())
{
    global $g_table_prefix, $LANG;
    // to ensure that all new field option groups have unique names, query the database and find the next free
    // group name of the form "New Option List (X)" (where "New Option List" is in the language of the current user)
    $lists = ft_get_option_lists("all");
    $list_names = array();
    foreach ($lists["results"] as $list_info) {
        $list_names[] = $list_info["option_list_name"];
    }
    $base_new_option_list = $LANG["phrase_new_option_list"];
    $new_option_list_name = $base_new_option_list;
    if (in_array($new_option_list_name, $list_names)) {
        $count = 2;
        $new_option_list_name = "{$base_new_option_list} ({$count})";
        while (in_array($new_option_list_name, $list_names)) {
            $count++;
            $new_option_list_name = "{$base_new_option_list} ({$count})";
        }
    }
    if (empty($list_id)) {
        $query = mysql_query("\n      INSERT INTO {$g_table_prefix}option_lists (option_list_name, is_grouped)\n      VALUES ('{$new_option_list_name}', 'no')\n    ");
        if (!$query) {
            return false;
        }
        $new_list_id = mysql_insert_id();
    } else {
        $option_list_info = ft_get_option_list($list_id);
        $is_grouped = $option_list_info["is_grouped"];
        $query = mysql_query("\n      INSERT INTO {$g_table_prefix}option_lists (option_list_name, is_grouped)\n      VALUES ('{$new_option_list_name}', '{$is_grouped}')\n    ");
        if (!$query) {
            return false;
        }
        $new_list_id = mysql_insert_id();
        // add add the option groups and their field options
        foreach ($option_list_info["options"] as $grouped_option_info) {
            $group_info = $grouped_option_info["group_info"];
            $options = $grouped_option_info["options"];
            $group_type = "option_list_{$new_list_id}";
            $group_name = $group_info["group_name"];
            $list_order = $group_info["list_order"];
            $new_list_group_info = ft_add_list_group($group_type, $group_name, $list_order);
            $new_list_group_id = $new_list_group_info["group_id"];
            foreach ($options as $option_info) {
                $option_info = ft_sanitize($option_info);
                $order = $option_info["option_order"];
                $value = $option_info["option_value"];
                $name = $option_info["option_name"];
                $is_new_sort_group = $option_info["is_new_sort_group"];
                mysql_query("\n          INSERT INTO {$g_table_prefix}field_options (list_id, list_group_id, option_order,\n            option_value, option_name, is_new_sort_group)\n          VALUES ({$new_list_id}, {$new_list_group_id}, '{$order}', '{$value}', '{$name}', '{$is_new_sort_group}')\n            ") or die(mysql_error());
            }
        }
    }
    // if we need to map this new option list to a field - or fields, loop through them and add them
    // one by one. Note: field types may use multiple Option Lists, which makes this extremely difficult. But
    // to make it as generic as possible, this code picks the first Option List field for the field type (as determined
    // by the setting list order)
    if (!empty($field_ids)) {
        foreach ($field_ids as $field_id) {
            $field_type_id = ft_get_field_type_id_by_field_id($field_id);
            $field_settings = ft_get_field_type_settings($field_type_id);
            $option_list_setting_id = "";
            foreach ($field_settings as $field_setting_info) {
                if ($field_setting_info["field_type"] == "option_list_or_form_field") {
                    $option_list_setting_id = $field_setting_info["setting_id"];
                    break;
                }
            }
            // this should ALWAYS have found a setting, but just in case...
            if (!empty($option_list_setting_id)) {
                mysql_query("DELETE FROM {$g_table_prefix}field_settings WHERE field_id = {$field_id} AND setting_id = {$option_list_setting_id}");
                @mysql_query("\n          INSERT INTO {$g_table_prefix}field_settings (field_id, setting_id, setting_value)\n          VALUES ({$field_id}, {$option_list_setting_id}, {$new_list_id})\n           ");
            }
        }
    }
    return $new_list_id;
}
/**
 * Updates an export type.
 *
 * @param integer $export_type_id
 * @param array
 */
function exp_update_export_type($info)
{
    global $g_table_prefix, $L;
    $info = ft_sanitize($info);
    $export_type_id = $info["export_type_id"];
    $export_type_name = $info["export_type_name"];
    $visibility = $info["visibility"];
    $filename = $info["filename"];
    $export_group_id = $info["export_group_id"];
    $smarty_template = $info["smarty_template"];
    mysql_query("\n    UPDATE {$g_table_prefix}module_export_types\n    SET    export_type_name = '{$export_type_name}',\n           export_type_visibility = '{$visibility}',\n           filename = '{$filename}',\n           export_group_id = {$export_group_id},\n           smarty_template = '{$smarty_template}'\n    WHERE  export_type_id = {$export_type_id}\n      ");
    return array(true, $L["notify_export_type_updated"]);
}
Beispiel #10
0
/**
 * Called by the installation script and on the Reset to Defaults page. This cleans out any data already in the
 * tables and inserts the default values.
 */
function exp_insert_default_data()
{
    global $g_table_prefix, $g_root_dir, $g_root_url, $LANG;
    exp_clear_table_data();
    $queries = array();
    // add Export Groups
    $phrase_html_printer = ft_sanitize($LANG["export_manager"]["phrase_html_printer_friendly"]);
    $word_excel = ft_sanitize($LANG["export_manager"]["word_excel"]);
    $word_xml = ft_sanitize($LANG["export_manager"]["word_xml"]);
    $word_csv = ft_sanitize($LANG["export_manager"]["word_csv"]);
    $word_display = ft_sanitize($LANG["word_display"]);
    $word_generate = ft_sanitize($LANG["export_manager"]["word_generate"]);
    $queries[] = "INSERT INTO {$g_table_prefix}module_export_groups VALUES (1, '{$phrase_html_printer}', 'public', 'all', NULL, 'show', 'printer.png', 'popup', '{$word_display}', '600', '800', '', '<html>\r\n<head>\r\n  <title>{\$export_group_name}</title>\r\n\r\n  {* escape the CSS so it doesn''t confuse Smarty *}\r\n  {literal}\r\n  <style type=\"text/css\">\r\n  body { margin: 0px; }\r\n  table, td, tr, div, span { \r\n    font-family: verdana; font-size: 8pt;\r\n  }\r\n  table { empty-cells: show }\r\n  #nav_row { background-color: #efefef; padding: 10px; }\r\n  #export_group_name { color: #336699; font-weight:bold }\r\n  .print_table { border: 1px solid #dddddd; }\r\n  .print_table th { \r\n    border: 1px solid #cccccc; \r\n    background-color: #efefef;\r\n    text-align: left;\r\n  }\r\n  .print_table td { border: 1px solid #cccccc; }\r\n  .one_item { margin-bottom: 15px; }\r\n  .page_break { page-break-after: always; }\r\n  </style>\r\n\r\n  <style type=\"text/css\" media=\"print\">\r\n  .no_print { display: none }\r\n  </style>\r\n  {/literal}\r\n\r\n</head>\r\n<body>\r\n\r\n<div id=\"nav_row\" class=\"no_print\">\r\n\r\n  <span style=\"float:right\">{if \$page_type != \"file\"}\r\n    {* if there''s more than one export type in this group, display the types in a dropdown *}\r\n    {if \$export_types|@count > 1}\r\n      <select name=\"export_type_id\" onchange=\"window.location=''{\$same_page}?export_group_id={\$export_group_id}&export_group_{\$export_group_id}_results={\$export_group_results}&export_type_id='' + this.value\">\r\n      {foreach from=\$export_types item=export_type}\r\n        <option value=\"{\$export_type.export_type_id}\" {if \$export_type.export_type_id == \$export_type_id}selected{/if}>{eval var=\$export_type.export_type_name}</option>\r\n      {/foreach}\r\n      </select>\r\n    {/if}\r\n    {/if}\r\n    <input type=\"button\" onclick=\"window.close()\" value=\"{\$LANG.word_close}\" />\r\n    <input type=\"button\" onclick=\"window.print()\" value=\"{\$LANG.word_print}\" />\r\n  </span>\r\n\r\n  <span id=\"export_group_name\">{eval var=\$export_group_name}</span>\r\n</div>\r\n\r\n<div style=\"padding: 15px\">\r\n  {\$export_type_smarty_template}\r\n</div>\r\n\r\n</body>\r\n</html>', 1)";
    $queries[] = "INSERT INTO {$g_table_prefix}module_export_groups VALUES (2, '{$word_excel}', 'public', 'all', NULL, 'show', 'xls.gif', 'new_window', '{$word_generate}', '', '', 'Pragma: public\nCache-Control: max-age=0\nContent-Type: application/vnd.ms-excel; charset=utf-8\nContent-Disposition: attachment; filename={\$filename}', '<html>\r\n<head>\r\n</head>\r\n<body>\r\n\r\n{\$export_type_smarty_template}\r\n\r\n</body>\r\n</html>', 2)";
    $queries[] = "INSERT INTO {$g_table_prefix}module_export_groups VALUES (3, '{$word_xml}', 'public', 'all', NULL, 'hide', 'xml.jpg', 'new_window', '{$word_generate}', '', '', '', '<?xml version=\"1.0\" encoding=\"utf-8\" ?>\r\n\r\n{\$export_type_smarty_template}', 4)";
    $queries[] = "INSERT INTO {$g_table_prefix}module_export_groups VALUES (4, '{$word_csv}', 'public', 'all', NULL, 'hide', 'csv.gif', 'new_window', '{$word_generate}', '', '', 'Content-type: application/xml; charset=\"octet-stream\"\r\nContent-Disposition: attachment; filename={\$filename}', '{\$export_type_smarty_template}', 3)";
    // add Export Types
    $table_format = ft_sanitize($LANG["export_manager"]["phrase_table_format"]);
    $one_by_one = ft_sanitize($LANG["export_manager"]["phrase_one_by_one"]);
    $one_submission_per_page = ft_sanitize($LANG["export_manager"]["phrase_one_submission_per_page"]);
    $all_submissions = ft_sanitize($LANG["phrase_all_submissions"]);
    $queries[] = "INSERT INTO {$g_table_prefix}module_export_types VALUES (1, '{$table_format}', 'show', 'submissions-{\$M}.{\$j}.html', 1, '<h1>{\$form_name} - {\$view_name}</h1>\r\n\r\n<table cellpadding=\"2\" cellspacing=\"0\" width=\"100%\" class=\"print_table\">\r\n<tr>\r\n  {foreach from=\$display_fields item=column}\r\n    <th>{\$column.field_title}</th>\r\n  {/foreach}\r\n</tr>\r\n{strip}\r\n{foreach from=\$submissions item=submission}\r\n  {assign var=submission_id value=\$submission.submission_id}\r\n  <tr>\r\n    {foreach from=\$display_fields item=field_info}\r\n      {assign var=col_name value=\$field_info.col_name}\r\n      {assign var=value value=\$submission.\$col_name}\r\n      <td>\r\n        {smart_display_field form_id=\$form_id view_id=\$view_id\r\n          submission_id=\$submission_id field_info=\$field_info\r\n          field_types=\$field_types settings=\$settings value=\$value}\r\n      </td>\r\n    {/foreach}\r\n  </tr>\r\n{/foreach}\r\n{/strip}\r\n</table>', 1)";
    $queries[] = "INSERT INTO {$g_table_prefix}module_export_types VALUES (2, '{$one_by_one}', 'show', 'submissions-{\$M}.{\$j}.html', 1, '<h1>{\$form_name} - {\$view_name}</h1>\r\n\r\n{strip}\r\n{foreach from=\$submissions item=submission}\r\n  {assign var=submission_id value=\$submission.submission_id}\r\n  <table cellpadding=\"2\" cellspacing=\"0\" width=\"100%\" \r\n    class=\"print_table one_item\">\r\n    {foreach from=\$display_fields item=field_info}\r\n      {assign var=col_name value=\$field_info.col_name}\r\n      {assign var=value value=\$submission.\$col_name}\r\n      <tr>\r\n        <th width=\"140\">{\$field_info.field_title}</th>\r\n        <td>\r\n          {smart_display_field form_id=\$form_id view_id=\$view_id\r\n            submission_id=\$submission_id field_info=\$field_info\r\n            field_types=\$field_types settings=\$settings value=\$value}\r\n        </td>\r\n      </tr>\r\n    {/foreach}\r\n  </table>\r\n{/foreach}\r\n{/strip}', 2)";
    $queries[] = "INSERT INTO {$g_table_prefix}module_export_types VALUES (3, '{$one_submission_per_page}', 'show', 'submissions-{\$M}.{\$j}.html', 1, '<h1>{\$form_name} - {\$view_name}</h1>\r\n\r\n{foreach from=\$submissions item=submission name=row}\r\n  {assign var=submission_id value=\$submission.submission_id}\r\n  <table cellpadding=\"2\" cellspacing=\"0\" width=\"100%\" \r\n    class=\"print_table one_item\">\r\n    {foreach from=\$display_fields item=field_info}\r\n      {assign var=col_name value=\$field_info.col_name}\r\n      {assign var=value value=\$submission.\$col_name}\r\n      <tr>\r\n        <th width=\"140\">{\$field_info.field_title}</th>\r\n        <td>\r\n          {smart_display_field form_id=\$form_id view_id=\$view_id\r\n            submission_id=\$submission_id field_info=\$field_info\r\n            field_types=\$field_types settings=\$settings value=\$value}\r\n        </td>\r\n      </tr>\r\n    {/foreach}\r\n  </table>\r\n\r\n  {if !\$smarty.foreach.row.last}\r\n    <div class=\"no_print\"><i>- {\$LANG.phrase_new_page} -</i></div>\r\n    <br class=\"page_break\" />\r\n  {/if}\r\n \r\n{/foreach}\r\n', 3)";
    $queries[] = "INSERT INTO {$g_table_prefix}module_export_types VALUES (4, '{$table_format}', 'show', 'submissions-{\$M}.{\$j}.xls', 2, '<h1>{\$form_name} - {\$view_name}</h1>\r\n\r\n<table cellpadding=\"2\" cellspacing=\"0\" width=\"100%\" class=\"print_table\">\r\n<tr>\r\n  {foreach from=\$display_fields item=column}\r\n    <th>{\$column.field_title}</th>\r\n  {/foreach}\r\n</tr>\r\n{strip}\r\n{foreach from=\$submissions item=submission}\r\n  {assign var=submission_id value=\$submission.submission_id}\r\n  <tr>\r\n    {foreach from=\$display_fields item=field_info}\r\n      {assign var=col_name value=\$field_info.col_name}\r\n      {assign var=value value=\$submission.\$col_name}\r\n      <td>\r\n        {smart_display_field form_id=\$form_id view_id=\$view_id\r\n          submission_id=\$submission_id field_info=\$field_info\r\n          field_types=\$field_types settings=\$settings value=\$value\r\n          escape=\"excel\"}\r\n      </td>\r\n    {/foreach}\r\n  </tr>\r\n{/foreach}\r\n{/strip}\r\n</table>', 1)";
    $queries[] = "INSERT INTO {$g_table_prefix}module_export_types VALUES (5, '{$all_submissions}', 'show', 'form{\$form_id}_{\$datetime}.csv', 4, '{strip}\r\n  {foreach from=\$display_fields item=column name=row}\r\n    {* workaround for absurd Microsoft Excel problem, in which the first\r\n       two characters of a file cannot be ID; see:\r\n       http://support.microsoft.com /kb/323626 *}\r\n    {if \$smarty.foreach.row.first && \$column.field_title == \"ID\"}\r\n      .ID\r\n    {else}\r\n      {\$column.field_title|escape:''csv''}\r\n    {/if}\r\n    {if !\$smarty.foreach.row.last},{/if}\r\n  {/foreach}\r\n{/strip}\r\n{foreach from=\$submissions item=submission name=row}{strip}\r\n  {foreach from=\$display_fields item=field_info name=col_row}\r\n    {assign var=col_name value=\$field_info.col_name}\r\n    {assign var=value value=\$submission.\$col_name}\r\n    {smart_display_field form_id=\$form_id view_id=\$view_id\r\n      submission_id=\$submission.submission_id field_info=\$field_info\r\n      field_types=\$field_types settings=\$settings value=\$value\r\n      escape=\"csv\"}\r\n    {* if this wasn''t the last row, output a comma *}\r\n    {if !\$smarty.foreach.col_row.last},{/if}\r\n  {/foreach}\r\n{/strip}\r\n{if !\$smarty.foreach.row.last}\r\n{/if}\r\n{/foreach}', 1)";
    $queries[] = "INSERT INTO {$g_table_prefix}module_export_types VALUES (6, '{$all_submissions}', 'show', 'form{\$form_id}_{\$datetime}.xml', 3, '<export>\r\n  <export_datetime>{\$datetime}</export_datetime>\r\n  <export_unixtime>{\$U}</export_unixtime>\r\n  <form_info>\r\n    <form_id>{\$form_id}</form_id>\r\n    <form_name><![CDATA[{\$form_name}]]></form_name>\r\n    <form_url>{\$form_url}</form_url>\r\n  </form_info>\r\n  <view_info>\r\n    <view_id>{\$view_id}</view_id>\r\n    <view_name><![CDATA[{\$view_name}]]></view_name>\r\n  </view_info>\r\n  <submissions>\r\n    {foreach from=\$submissions item=submission name=row}      \r\n      <submission>\r\n       {foreach from=\$display_fields item=field_info name=col_row}\r\n         {assign var=col_name value=\$field_info.col_name}\r\n         {assign var=value value=\$submission.\$col_name}\r\n       <{\$col_name}><![CDATA[{smart_display_field form_id=\$form_id \r\n      view_id=\$view_id submission_id=\$submission.submission_id\r\n      field_info=\$field_info field_types=\$field_types \r\n      settings=\$settings value=\$value}]]></{\$col_name}>\r\n        {/foreach}\r\n       </submission>\r\n    {/foreach}\r\n  </submissions>\r\n</export>', 1)";
    // add the module settings
    $upload_dir = str_replace("\\", "\\\\", $g_root_dir);
    $separator = "/";
    if (strtoupper(substr(PHP_OS, 0, 3) == 'WIN')) {
        $separator = "\\\\";
    }
    $upload_dir .= "{$separator}upload";
    $queries[] = "INSERT INTO {$g_table_prefix}settings (setting_name, setting_value, module) VALUES ('file_upload_dir', '{$upload_dir}', 'export_manager')";
    $queries[] = "INSERT INTO {$g_table_prefix}settings (setting_name, setting_value, module) VALUES ('file_upload_url', '{$g_root_url}/upload', 'export_manager')";
    foreach ($queries as $query) {
        $result = mysql_query($query);
        if (!$result) {
            return array(false, $LANG["export_manager"]["notify_installation_problem_c"] . " <b>" . mysql_error() . "</b>");
        }
    }
    return array(true, $LANG["export_manager"]["notify_reset_to_default"]);
}
Beispiel #11
0
/**
 * Used in ft_search_forms and ft_get_form_prev_next_links, this function looks at the
 * current search and figures out the WHERE and ORDER BY clauses so that the calling function
 * can retrieve the appropriate form results in the appropriate order.
 *
 * @param array $search_criteria
 * @return array $clauses
 */
function _ft_get_search_form_sql_clauses($search_criteria)
{
    global $g_table_prefix;
    if (!isset($search_criteria["order"])) {
        $search_criteria["order"] = "form_id-DESC";
    }
    // verbose, but at least it prevents any invalid sorting...
    $order_clause = "";
    switch ($search_criteria["order"]) {
        case "form_id-DESC":
            $order_clause = "form_id DESC";
            break;
        case "form_id-ASC":
            $order_clause = "form_id ASC";
            break;
        case "form_name-ASC":
            $order_clause = "form_name ASC";
            break;
        case "form_name-DESC":
            $order_clause = "form_name DESC";
            break;
        case "form_type-ASC":
            $order_clause = "form_type ASC";
            break;
        case "form_type-DESC":
            $order_clause = "form_type DESC";
            break;
        case "status-DESC":
            $order_clause = "(is_initialized = 'no' AND is_complete = 'no'), is_active = 'no', is_active = 'yes'";
            break;
        case "status-ASC":
            $order_clause = "is_active = 'yes', is_active = 'no', (is_initialized = 'no' AND is_complete = 'no')";
            break;
        default:
            $order_clause = "form_id DESC";
            break;
    }
    $order_clause = "ORDER BY {$order_clause}";
    $status_clause = "";
    if (isset($search_criteria["status"])) {
        switch ($search_criteria["status"]) {
            case "online":
                $status_clause = "is_active = 'yes' ";
                break;
            case "offline":
                $status_clause = "(is_active = 'no' AND is_complete = 'yes')";
                break;
            case "incomplete":
                $status_clause = "(is_initialized = 'no' OR is_complete = 'no')";
                break;
            default:
                $status_clause = "";
                break;
        }
    }
    $keyword_clause = "";
    if (isset($search_criteria["keyword"]) && !empty($search_criteria["keyword"])) {
        $search_criteria["keyword"] = trim($search_criteria["keyword"]);
        $string = ft_sanitize($search_criteria["keyword"]);
        $fields = array("form_name", "form_url", "redirect_url", "form_id");
        $clauses = array();
        foreach ($fields as $field) {
            $clauses[] = "{$field} LIKE '%{$string}%'";
        }
        $keyword_clause = join(" OR ", $clauses);
    }
    // if a user ID has been specified, find out which forms have been assigned to this client
    // so we can limit our query
    $form_clause = "";
    // this var is populated ONLY for searches on a particular client account. It stores those public forms on
    // which the client is on the Omit List. This value is used at the end of this function to trim the results
    // returned to NOT include those forms
    $client_omitted_from_public_forms = array();
    if (!empty($search_criteria["account_id"])) {
        $account_id = $search_criteria["account_id"];
        // a bit weird, but necessary. This adds a special clause to the query so that when it searches for a
        // particular account, it also (a) returns all public forms and (b) only returns those forms that are
        // completed. This is because incomplete forms are still set to access_type = "public".
        // Note: this does NOT take into account the public_form_omit_list - that's handled afterwards, to
        // keep the SQL as simple as possible
        $is_public_clause = "(access_type = 'public')";
        $is_setup_clause = "is_complete = 'yes' AND is_initialized = 'yes'";
        // first, grab all those forms that are explicitly associated with this client
        $query = mysql_query("\n      SELECT *\n      FROM   {$g_table_prefix}client_forms\n      WHERE  account_id = {$account_id}\n        ");
        $form_clauses = array();
        while ($result = mysql_fetch_assoc($query)) {
            $form_clauses[] = "form_id = {$result['form_id']}";
        }
        if (count($form_clauses) > 1) {
            $form_clause = "(((" . join(" OR ", $form_clauses) . ") OR {$is_public_clause}) AND ({$is_setup_clause}))";
        } else {
            $form_clause = isset($form_clauses[0]) ? "(({$form_clauses[0]} OR {$is_public_clause}) AND ({$is_setup_clause}))" : "({$is_public_clause} AND ({$is_setup_clause}))";
        }
        // see if this client account has been omitted from any public forms. If it is, this will be used to
        // filter the results
        $query = mysql_query("SELECT form_id FROM {$g_table_prefix}public_form_omit_list WHERE account_id = {$account_id}");
        while ($row = mysql_fetch_assoc($query)) {
            $client_omitted_from_public_forms[] = $row["form_id"];
        }
    }
    $admin_clause = !$search_criteria["is_admin"] ? "is_complete = 'yes' AND is_initialized = 'yes'" : "";
    // add up the where clauses
    $where_clauses = array();
    if (!empty($status_clause)) {
        $where_clauses[] = $status_clause;
    }
    if (!empty($keyword_clause)) {
        $where_clauses[] = "({$keyword_clause})";
    }
    if (!empty($form_clause)) {
        $where_clauses[] = $form_clause;
    }
    if (!empty($admin_clause)) {
        $where_clauses[] = $admin_clause;
    }
    if (!empty($where_clauses)) {
        $where_clause = "WHERE " . join(" AND ", $where_clauses);
    } else {
        $where_clause = "";
    }
    return array("order_clause" => $order_clause, "where_clause" => $where_clause, "client_omitted_from_public_forms" => $client_omitted_from_public_forms);
}
/**
 * Updates the administrator account. With the addition of the "UI Language" option, this action
 * gets a little more complicated. The problem is that we can't just update the UI language in
 * sessions *within* this function, because by the time this function is called, the appropriate
 * language file is already in memory and being used. So, to get around this problem, the login
 * information form now passes along both the new and old UI languages. If it's different, AFTER
 * this function is called, you need to reset sessions and refresh the page. So be aware that
 * this problem is NOT handled by this function, see:
 *     /admin/accounts/index.php to see how it's solved.
 *
 * @param array $infohash This parameter should be a hash (e.g. $_POST or $_GET) containing the
 *               following keys: first_name, last_name, user_name, password.
 * @param integer $user_id the administrator's user ID
 * @return array [0]: true/false (success / failure)
 *               [1]: message string
 */
function ft_update_admin_account($infohash, $account_id)
{
    global $g_table_prefix, $g_root_url, $LANG;
    $success = true;
    $message = $LANG["notify_account_updated"];
    $infohash = ft_sanitize($infohash);
    extract(ft_process_hook_calls("start", compact("infohash", "account_id"), array("infohash")), EXTR_OVERWRITE);
    $rules = array();
    $rules[] = "required,first_name,{$LANG["validation_no_first_name"]}";
    $rules[] = "required,last_name,{$LANG["validation_no_last_name"]}";
    $rules[] = "required,email,{$LANG["validation_no_email"]}";
    $rules[] = "required,theme,{$LANG["validation_no_theme"]}";
    $rules[] = "required,login_page,{$LANG["validation_no_login_page"]}";
    $rules[] = "required,logout_url,{$LANG["validation_no_account_logout_url"]}";
    $rules[] = "required,ui_language,{$LANG["validation_no_ui_language"]}";
    $rules[] = "required,sessions_timeout,{$LANG["validation_no_sessions_timeout"]}";
    $rules[] = "required,date_format,{$LANG["validation_no_date_format"]}";
    $rules[] = "required,username,{$LANG["validation_no_username"]}";
    $rules[] = "if:password!=,required,password_2,{$LANG["validation_no_account_password_confirmed"]}";
    $rules[] = "if:password!=,same_as,password,password_2,{$LANG["validation_passwords_different"]}";
    $errors = validate_fields($infohash, $rules);
    if (!empty($errors)) {
        $success = false;
        array_walk($errors, create_function('&$el', '$el = "&bull;&nbsp; " . $el;'));
        $message = implode("<br />", $errors);
        return array($success, $message);
    }
    $first_name = $infohash["first_name"];
    $last_name = $infohash["last_name"];
    $email = $infohash["email"];
    $theme = $infohash["theme"];
    $login_page = $infohash["login_page"];
    $logout_url = $infohash["logout_url"];
    $ui_language = $infohash["ui_language"];
    $timezone_offset = $infohash["timezone_offset"];
    $sessions_timeout = $infohash["sessions_timeout"];
    $date_format = $infohash["date_format"];
    $username = $infohash["username"];
    $password = $infohash["password"];
    $swatch = "";
    if (isset($infohash["{$theme}_theme_swatches"])) {
        $swatch = $infohash["{$theme}_theme_swatches"];
    }
    // if the password is defined, md5 it
    $password_sql = !empty($password) ? "password = '******', " : "";
    // check to see if username is already taken
    list($valid_username, $problem) = _ft_is_valid_username($username, $account_id);
    if (!$valid_username) {
        return array(false, $problem);
    }
    $query = "\n      UPDATE  {$g_table_prefix}accounts\n      SET     {$password_sql}\n              first_name = '{$first_name}',\n              last_name = '{$last_name}',\n              email = '{$email}',\n              theme = '{$theme}',\n              swatch = '{$swatch}',\n              login_page = '{$login_page}',\n              logout_url = '{$logout_url}',\n              ui_language = '{$ui_language}',\n              timezone_offset = '{$timezone_offset}',\n              sessions_timeout = '{$sessions_timeout}',\n              date_format = '{$date_format}',\n              username = '******'\n      WHERE   account_id = {$account_id}\n           ";
    mysql_query($query) or ft_handle_error("Failed query in <b>" . __FUNCTION__ . "</b>: <i>{$query}</i>", mysql_error());
    // update the settings
    $_SESSION["ft"]["settings"] = ft_get_settings();
    $_SESSION["ft"]["account"] = ft_get_account_info($account_id);
    $_SESSION["ft"]["account"]["is_logged_in"] = true;
    // if the password just changed, update sessions and empty any temporary password that happens to have been
    // stored
    if (!empty($password)) {
        $_SESSION["ft"]["account"] = ft_get_account_info($account_id);
        $_SESSION["ft"]["account"]["is_logged_in"] = true;
        $_SESSION["ft"]["account"]["password"] = md5(md5($password));
        mysql_query("UPDATE {$g_table_prefix}accounts SET temp_reset_password = NULL where account_id = {$account_id}");
    }
    extract(ft_process_hook_calls("end", compact("infohash", "account_id"), array("success", "message")), EXTR_OVERWRITE);
    return array($success, $message);
}
Beispiel #13
0
/**
 * Updates a page.
 *
 * @param integer $page_id
 * @param array
 */
function pg_update_page($page_id, $info)
{
    global $g_table_prefix, $LANG;
    $info = ft_sanitize($info);
    $page_name = $info["page_name"];
    $heading = $info["heading"];
    $access_type = $info["access_type"];
    $content_type = $info["content_type"];
    $use_wysiwyg = $info["use_wysiwyg_hidden"];
    $content = $info["codemirror_content"];
    if ($content_type == "html" && $use_wysiwyg == "yes") {
        $content = $info["wysiwyg_content"];
    }
    mysql_query("\n    UPDATE {$g_table_prefix}module_pages\n    SET    page_name = '{$page_name}',\n           content_type = '{$content_type}',\n           access_type = '{$access_type}',\n           use_wysiwyg = '{$use_wysiwyg}',\n           heading = '{$heading}',\n           content = '{$content}'\n    WHERE  page_id = {$page_id}\n      ");
    @mysql_query("DELETE FROM {$g_table_prefix}module_pages_clients WHERE page_id = {$page_id}");
    if ($access_type == "private") {
        foreach ($info["selected_client_ids"] as $client_id) {
            mysql_query("INSERT INTO {$g_table_prefix}module_pages_clients (page_id, client_id) VALUES ({$page_id}, {$client_id})");
        }
    }
    return array(true, $LANG["notify_page_updated"]);
}
Beispiel #14
0
/**
 * Helper function which should be used on all submitted data to properly escape user-inputted
 * values for inserting into a database. This replaces the former ft_clean_hash function and
 * can be used on any variable.
 *
 * @param mixed
 * @return array The "clean" (escaped) hash.
 */
function ft_sanitize($input)
{
    if (is_array($input)) {
        $output = array();
        foreach ($input as $k => $i) {
            $output[$k] = ft_sanitize($i);
        }
    } else {
        if (get_magic_quotes_gpc()) {
            $input = stripslashes($input);
        }
        $output = mysql_real_escape_string($input);
    }
    return $output;
}
Beispiel #15
0
/**
 * This returns the IDs of the previous and next client accounts, as determined by the administrators current
 * search and sort.
 *
 * Not happy with this function! Getting this info is surprisingly tricky, once you throw in the sort clause.
 * Still, the number of client accounts are liable to be quite small, so it's not such a sin.
 *
 * @param integer $account_id
 * @param array $search_criteria
 * @return hash prev_account_id => the previous account ID (or empty string)
 *              next_account_id => the next account ID (or empty string)
 */
function ft_get_client_prev_next_links($account_id, $search_criteria = array())
{
    global $g_table_prefix;
    $keyword_clause = "";
    if (isset($search_criteria["keyword"]) && !empty($search_criteria["keyword"])) {
        $string = ft_sanitize($search_criteria["keyword"]);
        $fields = array("last_name", "first_name", "email", "account_id");
        $clauses = array();
        foreach ($fields as $field) {
            $clauses[] = "{$field} LIKE '%{$string}%'";
        }
        $keyword_clause = implode(" OR ", $clauses);
    }
    // add up the where clauses
    $where_clauses = array("account_type = 'client'");
    if (!empty($status_clause)) {
        $where_clauses[] = "({$status_clause})";
    }
    if (!empty($keyword_clause)) {
        $where_clauses[] = "({$keyword_clause})";
    }
    $where_clause = "WHERE " . implode(" AND ", $where_clauses);
    $order_clause = _ft_get_client_order_clause($search_criteria["order"]);
    // get the clients
    $client_query_result = mysql_query("\n    SELECT account_id\n    FROM   {$g_table_prefix}accounts\n    {$where_clause}\n    {$order_clause}\n           ");
    $sorted_account_ids = array();
    while ($row = mysql_fetch_assoc($client_query_result)) {
        $sorted_account_ids[] = $row["account_id"];
    }
    $current_index = array_search($account_id, $sorted_account_ids);
    $return_info = array("prev_account_id" => "", "next_account_id" => "");
    if ($current_index === 0) {
        if (count($sorted_account_ids) > 1) {
            $return_info["next_account_id"] = $sorted_account_ids[$current_index + 1];
        }
    } else {
        if ($current_index === count($sorted_account_ids) - 1) {
            if (count($sorted_account_ids) > 1) {
                $return_info["prev_account_id"] = $sorted_account_ids[$current_index - 1];
            }
        } else {
            $return_info["prev_account_id"] = $sorted_account_ids[$current_index - 1];
            $return_info["next_account_id"] = $sorted_account_ids[$current_index + 1];
        }
    }
    return $return_info;
}
Beispiel #16
0
/**
 * This function checks to see if a submission is unique - based on whatever criteria you require
 * for your test case.
 *
 * @param integer $form_id
 * @param array $criteria a hash of whatever criteria is need to denote uniqueness, where the key is the
 *   database column name and the value is the current value being tested. For instance, if you wanted to check
 *   that no-one has submitted a form with a particular email address, you could pass
 *   array("email" => "myemail@whatever.com) as the second parameter (where "email" is the database column name).
 * @param integer $current_submission_id if this value is set, the function ignores that submission when doing
 *   a comparison.
 */
function ft_api_check_submission_is_unique($form_id, $criteria, $current_submission_id = "")
{
    global $g_api_debug, $g_table_prefix;
    // confirm the form is valid
    if (!ft_check_form_exists($form_id)) {
        if ($g_api_debug) {
            $page_vars = array("message_type" => "error", "error_code" => 550, "error_type" => "user");
            ft_display_page("error.tpl", $page_vars);
            exit;
        } else {
            return array(false, 550);
        }
    }
    if (!is_array($criteria)) {
        if ($g_api_debug) {
            $page_vars = array("message_type" => "error", "error_code" => 551, "error_type" => "user");
            ft_display_page("error.tpl", $page_vars);
            exit;
        } else {
            return array(false, 551);
        }
    }
    $where_clauses = array();
    while (list($col_name, $value) = each($criteria)) {
        if (empty($col_name)) {
            if ($g_api_debug) {
                $page_vars = array("message_type" => "error", "error_code" => 552, "error_type" => "user");
                ft_display_page("error.tpl", $page_vars);
                exit;
            } else {
                return array(false, 552);
            }
        }
        $where_clauses[] = "{$col_name} = '" . ft_sanitize($value) . "'";
    }
    if (empty($where_clauses)) {
        if ($g_api_debug) {
            $page_vars = array("message_type" => "error", "error_code" => 553, "error_type" => "user");
            ft_display_page("error.tpl", $page_vars);
            exit;
        } else {
            return array(false, 553);
        }
    }
    if (!empty($current_submission_id)) {
        $where_clauses[] = "submission_id != {$current_submission_id}";
    }
    $where_clause = "WHERE " . join(" AND ", $where_clauses);
    $query = @mysql_query("\n    SELECT count(*) as c\n    FROM {$g_table_prefix}form_{$form_id}\n    {$where_clause}\n    ");
    if ($query) {
        $result = mysql_fetch_assoc($query);
    } else {
        $page_vars = array("message_type" => "error", "error_code" => 554, "error_type" => "user");
        ft_display_page("error.tpl", $page_vars);
        exit;
    }
    return $result["c"] == 0;
}
Beispiel #17
0
/**
 * This makes a copy of all field groups for a View and returns a hash of old group IDs to new group IDs.
 * It's used in the create View functionality when the user wants to base the new View on an existing
 * one.
 *
 * @param integer $source_view_id
 * @param integer $target_view_id
 * @return array
 */
function ft_duplicate_view_field_groups($source_view_id, $target_view_id)
{
    global $g_table_prefix;
    $query = mysql_query("\r\n    SELECT *\r\n    FROM   {$g_table_prefix}list_groups\r\n    WHERE group_type = 'view_fields_{$source_view_id}'\r\n    ORDER BY list_order\r\n  ");
    $map = array();
    while ($row = mysql_fetch_assoc($query)) {
        $row = ft_sanitize($row);
        $group_id = $row["group_id"];
        $group_type = "view_fields_{$target_view_id}";
        $group_name = $row["group_name"];
        $custom_data = $row["custom_data"];
        $list_order = $row["list_order"];
        mysql_query("\r\n      INSERT INTO {$g_table_prefix}list_groups (group_type, group_name, custom_data, list_order)\r\n      VALUES ('{$group_type}', '{$group_name}', '{$custom_data}', {$list_order})\r\n    ") or die(mysql_error());
        $map[$group_id] = mysql_insert_id();
    }
    return $map;
}
Beispiel #18
0
/**
 * This function processes the form submissions, after the form has been set up in the database.
 */
function ft_process_form($form_data)
{
    global $g_table_prefix, $g_multi_val_delimiter, $g_query_str_multi_val_separator, $g_root_dir, $LANG, $g_api_version, $g_api_recaptcha_private_key;
    // ensure the incoming values are escaped
    $form_data = ft_sanitize($form_data);
    $form_id = $form_data["form_tools_form_id"];
    $form_info = ft_get_form($form_id);
    // do we have a form for this id?
    if (!ft_check_form_exists($form_id)) {
        $page_vars = array("message_type" => "error", "message" => $LANG["processing_invalid_form_id"]);
        ft_display_page("error.tpl", $page_vars);
        exit;
    }
    extract(ft_process_hook_calls("start", compact("form_info", "form_id", "form_data"), array("form_data")), EXTR_OVERWRITE);
    // check to see if this form has been completely set up
    if ($form_info["is_complete"] == "no") {
        $page_vars = array("message_type" => "error", "message" => $LANG["processing_form_incomplete"]);
        ft_display_page("error.tpl", $page_vars);
        exit;
    }
    // check to see if this form has been disabled
    if ($form_info["is_active"] == "no") {
        if (isset($form_data["form_tools_inactive_form_redirect_url"])) {
            header("location: {$form_data["form_tools_inactive_form_redirect_url"]}");
            exit;
        }
        $page_vars = array("message_type" => "error", "message" => $LANG["processing_form_disabled"]);
        ft_display_page("error.tpl", $page_vars);
        exit;
    }
    // do we have a form for this id?
    if (!ft_check_form_exists($form_id)) {
        $page_vars = array("message_type" => "error", "message" => $LANG["processing_invalid_form_id"]);
        ft_display_page("error.tpl", $page_vars);
        exit;
    }
    // was there a reCAPTCHA response? If so, a recaptcha was just submitted. This generally implies the
    // form page included the API, so check it was entered correctly. If not, return the user to the webpage
    if (isset($g_api_version) && isset($form_data["recaptcha_response_field"])) {
        $passes_captcha = false;
        $recaptcha_challenge_field = $form_data["recaptcha_challenge_field"];
        $recaptcha_response_field = $form_data["recaptcha_response_field"];
        $folder = dirname(__FILE__);
        require_once "{$folder}/global/api/recaptchalib.php";
        $resp = recaptcha_check_answer($g_api_recaptcha_private_key, $_SERVER["REMOTE_ADDR"], $recaptcha_challenge_field, $recaptcha_response_field);
        if ($resp->is_valid) {
            $passes_captcha = true;
        } else {
            // since we need to pass all the info back to the form page we do it by storing the data in sessions. Enable 'em.
            @ft_api_start_sessions();
            $_SESSION["form_tools_form_data"] = $form_data;
            $_SESSION["form_tools_form_data"]["api_recaptcha_error"] = $resp->error;
            // if there's a form_tools_form_url specified, redirect to that
            if (isset($form_data["form_tools_form_url"])) {
                header("location: {$form_data["form_tools_form_url"]}");
                exit;
            } else {
                if (isset($_SERVER["HTTP_REFERER"])) {
                    header("location: {$_SERVER["HTTP_REFERER"]}");
                    exit;
                } else {
                    $page_vars = array("message_type" => "error", "message" => $LANG["processing_no_form_url_for_recaptcha"]);
                    ft_display_page("error.tpl", $page_vars);
                    exit;
                }
            }
        }
    }
    // get a list of the custom form fields (i.e. non-system) for this form
    $form_fields = ft_get_form_fields($form_id, array("include_field_type_info" => true));
    $custom_form_fields = array();
    $file_fields = array();
    foreach ($form_fields as $field_info) {
        $field_id = $field_info["field_id"];
        $is_system_field = $field_info["is_system_field"];
        $field_name = $field_info["field_name"];
        // ignore system fields
        if ($is_system_field == "yes") {
            continue;
        }
        if ($field_info["is_file_field"] == "no") {
            $custom_form_fields[$field_name] = array("field_id" => $field_id, "col_name" => $field_info["col_name"], "field_title" => $field_info["field_title"], "include_on_redirect" => $field_info["include_on_redirect"], "field_type_id" => $field_info["field_type_id"], "is_date_field" => $field_info["is_date_field"]);
        } else {
            $file_fields[] = array("field_id" => $field_id, "field_info" => $field_info);
        }
    }
    // now examine the contents of the POST/GET submission and get a list of those fields
    // which we're going to update
    $valid_form_fields = array();
    while (list($form_field, $value) = each($form_data)) {
        // if this field is included, store the value for adding to DB
        if (array_key_exists($form_field, $custom_form_fields)) {
            $curr_form_field = $custom_form_fields[$form_field];
            $cleaned_value = $value;
            if (is_array($value)) {
                if ($form_info["submission_strip_tags"] == "yes") {
                    for ($i = 0; $i < count($value); $i++) {
                        $value[$i] = strip_tags($value[$i]);
                    }
                }
                $cleaned_value = implode("{$g_multi_val_delimiter}", $value);
            } else {
                if ($form_info["submission_strip_tags"] == "yes") {
                    $cleaned_value = strip_tags($value);
                }
            }
            $valid_form_fields[$curr_form_field["col_name"]] = "'{$cleaned_value}'";
        }
    }
    $now = ft_get_current_datetime();
    $ip_address = $_SERVER["REMOTE_ADDR"];
    $col_names = array_keys($valid_form_fields);
    $col_names_str = join(", ", $col_names);
    if (!empty($col_names_str)) {
        $col_names_str .= ", ";
    }
    $col_values = array_values($valid_form_fields);
    $col_values_str = join(", ", $col_values);
    if (!empty($col_values_str)) {
        $col_values_str .= ", ";
    }
    // build our query
    $query = "\r\n    INSERT INTO {$g_table_prefix}form_{$form_id} ({$col_names_str} submission_date, last_modified_date, ip_address, is_finalized)\r\n    VALUES ({$col_values_str} '{$now}', '{$now}', '{$ip_address}', 'yes')\r\n           ";
    // add the submission to the database (if form_tools_ignore_submission key isn't set by either the form or a module)
    $submission_id = "";
    if (!isset($form_data["form_tools_ignore_submission"])) {
        $result = mysql_query($query);
        if (!$result) {
            $page_vars = array("message_type" => "error", "error_code" => 304, "error_type" => "system", "debugging" => "Failed query in <b>" . __FUNCTION__ . ", " . __FILE__ . "</b>, line " . __LINE__ . ": <i>" . nl2br($query) . "</i>", mysql_error());
            ft_display_page("error.tpl", $page_vars);
            exit;
        }
        $submission_id = mysql_insert_id();
        extract(ft_process_hook_calls("end", compact("form_id", "submission_id"), array()), EXTR_OVERWRITE);
    }
    $redirect_query_params = array();
    // build the redirect query parameter array
    foreach ($form_fields as $field_info) {
        if ($field_info["include_on_redirect"] == "no" || $field_info["is_file_field"] == "yes") {
            continue;
        }
        switch ($field_info["col_name"]) {
            case "submission_id":
                $redirect_query_params[] = "submission_id={$submission_id}";
                break;
            case "submission_date":
                $settings = ft_get_settings();
                $submission_date_formatted = ft_get_date($settings["default_timezone_offset"], $now, $settings["default_date_format"]);
                $redirect_query_params[] = "submission_date=" . rawurlencode($submission_date_formatted);
                break;
            case "last_modified_date":
                $settings = ft_get_settings();
                $submission_date_formatted = ft_get_date($settings["default_timezone_offset"], $now, $settings["default_date_format"]);
                $redirect_query_params[] = "last_modified_date=" . rawurlencode($submission_date_formatted);
                break;
            case "ip_address":
                $redirect_query_params[] = "ip_address={$ip_address}";
                break;
            default:
                $field_name = $field_info["field_name"];
                // if $value is an array, convert it to a string, separated by $g_query_str_multi_val_separator
                if (isset($form_data[$field_name])) {
                    if (is_array($form_data[$field_name])) {
                        $value_str = join($g_query_str_multi_val_separator, $form_data[$field_name]);
                        $redirect_query_params[] = "{$field_name}=" . rawurlencode($value_str);
                    } else {
                        $redirect_query_params[] = "{$field_name}=" . rawurlencode($form_data[$field_name]);
                    }
                }
                break;
        }
    }
    // only upload files & send emails if we're not ignoring the submission
    if (!isset($form_data["form_tools_ignore_submission"])) {
        // now process any file fields. This is placed after the redirect query param code block above to allow whatever file upload
        // module to append the filename to the query string, if needed
        extract(ft_process_hook_calls("manage_files", compact("form_id", "submission_id", "file_fields", "redirect_query_params"), array("success", "message", "redirect_query_params")), EXTR_OVERWRITE);
        // send any emails
        ft_send_emails("on_submission", $form_id, $submission_id);
    }
    // if the redirect URL has been specified either in the database or as part of the form
    // submission, redirect the user [form submission form_tools_redirect_url value overrides
    // database value]
    if (!empty($form_info["redirect_url"]) || !empty($form_data["form_tools_redirect_url"])) {
        // build redirect query string
        $redirect_url = isset($form_data["form_tools_redirect_url"]) && !empty($form_data["form_tools_redirect_url"]) ? $form_data["form_tools_redirect_url"] : $form_info["redirect_url"];
        $query_str = "";
        if (!empty($redirect_query_params)) {
            $query_str = join("&", $redirect_query_params);
        }
        if (!empty($query_str)) {
            // only include the ? if it's not already there
            if (strpos($redirect_url, "?")) {
                $redirect_url .= "&" . $query_str;
            } else {
                $redirect_url .= "?" . $query_str;
            }
        }
        header("Location: " . $redirect_url);
        exit;
    }
    // the user should never get here! This means that the no redirect URL has been specified
    $page_vars = array("message_type" => "error", "message" => $LANG["processing_no_redirect_url"]);
    ft_display_page("error.tpl", $page_vars);
    exit;
}
Beispiel #19
0
/**
 * This function is provided for theme developers who find themselves in a position where a theme they
 * create is wonky, and prevents them seeing anything in the UI. It can only be called after having
 * logged in as an administrator (which will not be affected by a dud theme - even through they may
 * see nothing after logging in). To call it, they'll need to construct this URL:
 *
 *     http://www.yourdomain.com/formtools/admin/settings/index.php?page=themes&theme_override=deepblue
 *
 * @param string $theme the name of the theme folder to reset to (e.g. deepblue)
 */
function ft_reset_admin_theme($theme)
{
    global $g_table_prefix, $LANG;
    $theme = ft_sanitize($theme);
    $admin_id = $_SESSION["ft"]["account"]["account_id"];
    mysql_query("\n    UPDATE {$g_table_prefix}accounts\n    SET    theme = '{$theme}'\n    WHERE  account_id = {$admin_id}\n      ");
    $_SESSION["ft"]["account"]["theme"] = $theme;
    return array(true, $LANG["notify_admin_theme_overridden"]);
}
Beispiel #20
0
/**
 * Updates the last logged in date for an account.
 *
 * @param $account_id
 */
function ft_update_last_logged_in($account_id)
{
    global $g_table_prefix;
    $account_id = ft_sanitize($account_id);
    if (!is_numeric($account_id)) {
        return;
    }
    $now = ft_get_current_datetime();
    @mysql_query("\r\n    UPDATE {$g_table_prefix}accounts\r\n    SET    last_logged_in = '{$now}'\r\n    WHERE  account_id = {$account_id}\r\n  ");
}
/**
 * This is the main server-side validation function, called whenever updating a submission. The current version (Core 2.1.9)
 * only performs a subset of the total validation rules; namely, those non-custom ones that
 *
 * @param array $editable_field_ids - this contains ALL editable field IDs in the form
 * @param array $request
 * @return array an array of errors, or an empty array if no errors
 */
function ft_validate_submission($form_id, $editable_field_ids, $request)
{
    if (empty($editable_field_ids)) {
        return array();
    }
    // get the validation rules for the current page. The use of $request["field_ids"] is a fix for bug #339; this should be handled
    // a lot better. The calling page (edit_submission.php amongst other) should be figuring out what fields are editable on that particular
    // page and passing THAT info as $editable_field_ids
    $editable_field_ids_on_tab = explode(",", $request["field_ids"]);
    // return all validation rules for items on tab, including those marked as editable == "no"
    $rules = ft_get_php_field_validation_rules($editable_field_ids_on_tab);
    // gets all form fields in this View
    $form_fields = ft_get_view_fields($request["view_id"]);
    // reorganize $form_fields to be a hash of field_id => array(form_name => "", field_tield => "")
    $field_info = array();
    foreach ($form_fields as $curr_field_info) {
        $field_info[$curr_field_info["field_id"]] = array("field_name" => $curr_field_info["field_name"], "field_title" => $curr_field_info["field_title"], "is_editable" => $curr_field_info["is_editable"]);
    }
    // construct the RSV-friendly validation
    $validation = array();
    foreach ($rules as $rule_info) {
        $rule = $rule_info["rsv_rule"];
        $field_id = $rule_info["field_id"];
        $field_name = $field_info[$field_id]["field_name"];
        $field_title = $field_info[$field_id]["field_title"];
        $error_message = $rule_info["error_message"];
        // if this field is marked as non-editable, ignore it. We don't need to validate it
        if ($field_info[$field_id]["is_editable"] == "no") {
            continue;
        }
        $placeholders = array("field" => $field_title, "field_name" => $field_name);
        $error_message = ft_eval_smarty_string($error_message, $placeholders);
        $validation[] = "{$rule},{$field_name},{$error_message}";
    }
    $errors = array();
    if (!empty($validation)) {
        $form_vals = ft_sanitize($request);
        $errors = validate_fields($form_vals, $validation);
    }
    return $errors;
}
Beispiel #22
0
/**
 * Called by administrators; updates the default user account settings.
 *
 * @param array $infohash this parameter should be a hash (e.g. $_POST or $_GET) containing the
 *             various fields from the main settings admin page.
 * @return array Returns array with indexes:<br/>
 *               [0]: true/false (success / failure)<br/>
 *               [1]: message string<br/>
 */
function ft_update_account_settings($infohash)
{
    global $g_table_prefix, $g_root_url, $LANG;
    $success = true;
    $message = $LANG["notify_setup_options_updated"];
    $infohash = ft_sanitize($infohash);
    $rules = array();
    $rules[] = "required,default_page_titles,{$LANG["validation_no_page_titles"]}";
    $rules[] = "required,default_client_menu_id,{$LANG["validation_no_menu_id"]}";
    $rules[] = "required,default_theme,{$LANG["validation_no_theme"]}";
    $rules[] = "required,default_login_page,{$LANG["validation_no_login_page"]}";
    $rules[] = "required,default_logout_url,{$LANG["validation_no_logout_url"]}";
    $rules[] = "required,default_language,{$LANG["validation_no_default_language"]}";
    $rules[] = "required,default_sessions_timeout,{$LANG["validation_no_default_sessions_timeout"]}";
    $rules[] = "digits_only,default_sessions_timeout,{$LANG["validation_invalid_default_sessions_timeout"]}";
    $rules[] = "required,default_date_format,{$LANG["validation_no_date_format"]}";
    $errors = validate_fields($infohash, $rules);
    if (!empty($errors)) {
        $success = false;
        array_walk($errors, create_function('&$el', '$el = "&bull;&nbsp; " . $el;'));
        $message = join("<br />", $errors);
        return array($success, $message, "");
    }
    $clients_may_edit_page_titles = isset($infohash["clients_may_edit_page_titles"]) ? "yes" : "no";
    $clients_may_edit_footer_text = isset($infohash["clients_may_edit_footer_text"]) ? "yes" : "no";
    $clients_may_edit_theme = isset($infohash["clients_may_edit_theme"]) ? "yes" : "no";
    $clients_may_edit_logout_url = isset($infohash["clients_may_edit_logout_url"]) ? "yes" : "no";
    $clients_may_edit_ui_language = isset($infohash["clients_may_edit_ui_language"]) ? "yes" : "no";
    $clients_may_edit_timezone_offset = isset($infohash["clients_may_edit_timezone_offset"]) ? "yes" : "no";
    $clients_may_edit_sessions_timeout = isset($infohash["clients_may_edit_sessions_timeout"]) ? "yes" : "no";
    $clients_may_edit_date_format = isset($infohash["clients_may_edit_date_format"]) ? "yes" : "no";
    $clients_may_edit_max_failed_login_attempts = isset($infohash["clients_may_edit_max_failed_login_attempts"]) ? "yes" : "no";
    $required_password_chars = "";
    if (isset($infohash["required_password_chars"]) && is_array($infohash["required_password_chars"])) {
        $required_password_chars = implode(",", $infohash["required_password_chars"]);
    }
    $default_theme = $infohash["default_theme"];
    $default_client_swatch = "";
    if (isset($infohash["{$default_theme}_default_theme_swatches"])) {
        $default_client_swatch = $infohash["{$default_theme}_default_theme_swatches"];
    }
    $settings = array("default_page_titles" => $infohash["default_page_titles"], "default_footer_text" => $infohash["default_footer_text"], "default_client_menu_id" => $infohash["default_client_menu_id"], "default_theme" => $default_theme, "default_client_swatch" => $default_client_swatch, "default_login_page" => $infohash["default_login_page"], "default_logout_url" => $infohash["default_logout_url"], "default_language" => $infohash["default_language"], "default_timezone_offset" => $infohash["default_timezone_offset"], "default_sessions_timeout" => $infohash["default_sessions_timeout"], "default_date_format" => $infohash["default_date_format"], "forms_page_default_message" => $infohash["forms_page_default_message"], "clients_may_edit_page_titles" => $clients_may_edit_page_titles, "clients_may_edit_footer_text" => $clients_may_edit_footer_text, "clients_may_edit_theme" => $clients_may_edit_theme, "clients_may_edit_logout_url" => $clients_may_edit_logout_url, "clients_may_edit_ui_language" => $clients_may_edit_ui_language, "clients_may_edit_timezone_offset" => $clients_may_edit_timezone_offset, "clients_may_edit_sessions_timeout" => $clients_may_edit_sessions_timeout, "clients_may_edit_date_format" => $clients_may_edit_date_format, "default_max_failed_login_attempts" => $infohash["default_max_failed_login_attempts"], "min_password_length" => $infohash["min_password_length"], "required_password_chars" => $required_password_chars, "num_password_history" => $infohash["num_password_history"], "clients_may_edit_max_failed_login_attempts" => $clients_may_edit_max_failed_login_attempts);
    ft_set_settings($settings);
    extract(ft_process_hook_calls("end", compact("settings"), array("success", "message")), EXTR_OVERWRITE);
    return array($success, $message);
}
Beispiel #23
0
/**
 * Updates all aspects of an email template.
 *
 * @param integer $email_id
 * @param array $info
 */
function ft_update_email_template($email_id, $info)
{
    global $g_table_prefix, $LANG;
    // neat bug. We need to trim out any trailing whitespace from the templates, otherwise they're
    // escaped for DB insertion & can't be trimmed out then
    $info["text_template"] = trim($info["text_template"]);
    $info["html_template"] = trim($info["html_template"]);
    $info = ft_sanitize($info);
    extract(ft_process_hook_calls("start", compact("email_id", "info"), array("info")), EXTR_OVERWRITE);
    // "Main" tab
    $email_template_name = $info["email_template_name"];
    $email_status = $info["email_status"];
    $view_mapping_type = isset($info["view_mapping_type"]) ? $info["view_mapping_type"] : "all";
    $email_event_trigger = isset($info["email_event_trigger"]) && !empty($info["email_event_trigger"]) ? join(",", $info["email_event_trigger"]) : "";
    $include_on_edit_submission_page = isset($info["include_on_edit_submission_page"]) ? $info["include_on_edit_submission_page"] : "no";
    $limit_email_content_to_fields_in_view = isset($info["limit_email_content_to_fields_in_view"]) && !empty($info["limit_email_content_to_fields_in_view"]) ? $info["limit_email_content_to_fields_in_view"] : "NULL";
    $subject = $info["subject"];
    $email_from = $info["email_from"];
    $custom_from_name = isset($info["custom_from_name"]) ? $info["custom_from_name"] : "";
    $custom_from_email = isset($info["custom_from_email"]) ? $info["custom_from_email"] : "";
    $email_reply_to = $info["email_reply_to"];
    $custom_reply_to_name = isset($info["custom_reply_to_name"]) ? $info["custom_reply_to_name"] : "";
    $custom_reply_to_email = isset($info["custom_reply_to_email"]) ? $info["custom_reply_to_email"] : "";
    // figure out the email_from field details
    $email_from_account_id = "";
    $email_from_form_email_id = "";
    if (preg_match("/^client_account_id_(\\d+)/", $email_from, $matches)) {
        $email_from_account_id = $matches[1];
        $email_from = "client";
    } else {
        if (preg_match("/^form_email_id_(\\d+)/", $email_from, $matches)) {
            $email_from_form_email_id = $matches[1];
            $email_from = "form_email_field";
        }
    }
    // figure out the email_from field details
    $email_reply_to_account_id = "";
    $email_reply_to_form_email_id = "";
    if (preg_match("/^client_account_id_(\\d+)/", $email_reply_to, $matches)) {
        $email_reply_to_account_id = $matches[1];
        $email_reply_to = "client";
    } else {
        if (preg_match("/^form_email_id_(\\d+)/", $email_reply_to, $matches)) {
            $email_reply_to_form_email_id = $matches[1];
            $email_reply_to = "form_email_field";
        }
    }
    $email_from_account_id = empty($email_from_account_id) ? "NULL" : "'{$email_from_account_id}'";
    $email_from_form_email_id = empty($email_from_form_email_id) ? "NULL" : "'{$email_from_form_email_id}'";
    $email_reply_to_account_id = empty($email_reply_to_account_id) ? "NULL" : "'{$email_reply_to_account_id}'";
    $email_reply_to_form_email_id = empty($email_reply_to_form_email_id) ? "NULL" : "'{$email_reply_to_form_email_id}'";
    $email_from = empty($email_from) ? "NULL" : "'{$email_from}'";
    $email_reply_to = empty($email_reply_to) ? "NULL" : "'{$email_reply_to}'";
    // "Email Content" tab
    $html_template = $info["html_template"];
    $text_template = $info["text_template"];
    mysql_query("\r\n    UPDATE {$g_table_prefix}email_templates\r\n    SET    email_template_name = '{$email_template_name}',\r\n           email_status = '{$email_status}',\r\n           view_mapping_type = '{$view_mapping_type}',\r\n           limit_email_content_to_fields_in_view = {$limit_email_content_to_fields_in_view},\r\n           email_event_trigger = '{$email_event_trigger}',\r\n           include_on_edit_submission_page = '{$include_on_edit_submission_page}',\r\n           subject = '{$subject}',\r\n           email_from = {$email_from},\r\n           email_from_account_id = {$email_from_account_id},\r\n           email_from_form_email_id = {$email_from_form_email_id},\r\n           custom_from_name = '{$custom_from_name}',\r\n           custom_from_email = '{$custom_from_email}',\r\n           email_reply_to = {$email_reply_to},\r\n           email_reply_to_account_id = {$email_reply_to_account_id},\r\n           email_reply_to_form_email_id = {$email_reply_to_form_email_id},\r\n           custom_reply_to_name = '{$custom_reply_to_name}',\r\n           custom_reply_to_email = '{$custom_reply_to_email}',\r\n           html_template = '{$html_template}',\r\n           text_template = '{$text_template}'\r\n    WHERE  email_id = {$email_id}\r\n      ") or die(mysql_error());
    // update the email template edit submission page Views
    mysql_query("DELETE FROM {$g_table_prefix}email_template_edit_submission_views WHERE email_id = {$email_id}");
    $selected_edit_submission_views = isset($info["selected_edit_submission_views"]) ? $info["selected_edit_submission_views"] : array();
    foreach ($selected_edit_submission_views as $view_id) {
        mysql_query("\r\n      INSERT INTO {$g_table_prefix}email_template_edit_submission_views (email_id, view_id)\r\n      VALUES ({$email_id}, {$view_id})\r\n        ");
    }
    // update the email template when sent Views
    mysql_query("DELETE FROM {$g_table_prefix}email_template_when_sent_views WHERE email_id = {$email_id}");
    $selected_when_sent_views = isset($info["selected_when_sent_views"]) ? $info["selected_when_sent_views"] : array();
    foreach ($selected_when_sent_views as $view_id) {
        mysql_query("\r\n      INSERT INTO {$g_table_prefix}email_template_when_sent_views (email_id, view_id)\r\n      VALUES ({$email_id}, {$view_id})\r\n        ");
    }
    // update the recipient list
    mysql_query("DELETE FROM {$g_table_prefix}email_template_recipients WHERE email_template_id = {$email_id}");
    $recipient_ids = $info["recipients"];
    foreach ($recipient_ids as $recipient_id) {
        $row = $recipient_id;
        // if there's no recipient user type (admin/form_email_field/client/custom), just ignore the row
        if (!isset($info["recipient_{$row}_user_type"])) {
            continue;
        }
        // "" (main), "cc" or "bcc"
        $recipient_type = empty($info["recipient_{$row}_type"]) ? "main" : $info["recipient_{$row}_type"];
        switch ($info["recipient_{$row}_user_type"]) {
            case "admin":
                mysql_query("\r\n          INSERT INTO {$g_table_prefix}email_template_recipients (email_template_id, recipient_user_type, recipient_type)\r\n          VALUES ({$email_id}, 'admin', '{$recipient_type}')\r\n            ");
                break;
            case "form_email_field":
                $form_email_id = $info["recipient_{$row}_form_email_id"];
                mysql_query("\r\n          INSERT INTO {$g_table_prefix}email_template_recipients\r\n            (email_template_id, recipient_user_type, recipient_type, form_email_id)\r\n          VALUES ({$email_id}, 'form_email_field', '{$recipient_type}', {$form_email_id})\r\n            ");
                break;
            case "client":
                $account_id = $info["recipient_{$row}_account_id"];
                mysql_query("\r\n          INSERT INTO {$g_table_prefix}email_template_recipients\r\n            (email_template_id, recipient_user_type, recipient_type, account_id)\r\n          VALUES ({$email_id}, 'client', '{$recipient_type}', '{$account_id}')\r\n            ");
                break;
            case "custom":
                $name = isset($info["recipient_{$row}_name"]) ? $info["recipient_{$row}_name"] : "";
                $email = isset($info["recipient_{$row}_email"]) ? $info["recipient_{$row}_email"] : "";
                mysql_query("\r\n          INSERT INTO {$g_table_prefix}email_template_recipients\r\n            (email_template_id, recipient_user_type, recipient_type, custom_recipient_name, custom_recipient_email)\r\n          VALUES ({$email_id}, 'custom', '{$recipient_type}', '{$name}', '{$email}')\r\n            ");
                break;
        }
    }
    $success = true;
    $message = $LANG["notify_email_template_updated"];
    extract(ft_process_hook_calls("end", compact("email_id", "info"), array("success", "message")), EXTR_OVERWRITE);
    return array($success, $message);
}
Beispiel #24
0
/**
 * This function upgrades the Form Tools Core. As of 2.0.3, it works very simply: this gets called
 * every time a person goes to the login page, the function is called. It contains all the
 * updates made to the script since the original release and based on the release date of the users
 * current build, only upgrades the more recent changes. Since $g_release_date was only added in 2.0.3,
 * there's a helper function that contains the dates of the main releases, to ensure those are updated
 * properly.
 *
 * The changes here are listed in the changelog: http://docs.formtools.org/changelog.php
 *
 * @return array a hash with the following keys:
 *            "upgraded" => (boolean) true if the script did just attempt to upgrade, false otherwise
 *            "success"  => (boolean) if an upgrade attempt was made, this determines whether it was
 *                          successful or not
 *            "message"  => the error message, if unsuccessful
 */
function ft_upgrade_form_tools()
{
    global $g_table_prefix, $g_current_version, $g_release_type, $g_release_date, $LANG, $g_default_datetime_format;
    $upgrade_attempted = false;
    $success = "";
    $message = "";
    $old_version_info = ft_get_core_version_info();
    // upgrading to 2.1.0 can take a while (not THIS long, but this should be safe)
    set_time_limit(600);
    // ----------------------------------------------------------------------------------------------
    // 2.0.0 beta updates
    if ($old_version_info["release_date"] < 20090113) {
        // add the Hooks table
        @mysql_query("\r\n      CREATE TABLE {$g_table_prefix}hooks (\r\n        hook_id mediumint(8) unsigned NOT NULL auto_increment,\r\n        action_location enum('start','end') NOT NULL,\r\n        module_folder varchar(255) NOT NULL,\r\n        core_function varchar(255) NOT NULL,\r\n        hook_function varchar(255) NOT NULL,\r\n        priority tinyint(4) NOT NULL default '50',\r\n        PRIMARY KEY (hook_id)\r\n      ) DEFAULT CHARSET=utf8\r\n      ");
    }
    if ($old_version_info["release_date"] < 20090301) {
        @mysql_query("\r\n      ALTER TABLE {$g_table_prefix}email_templates\r\n      CHANGE email_reply_to email_reply_to\r\n      ENUM('none', 'admin', 'client', 'user', 'custom')\r\n      CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL\r\n        ");
    }
    if ($old_version_info["release_date"] < 20090317) {
        @mysql_query("\r\n      ALTER TABLE {$g_table_prefix}views\r\n      ADD may_add_submissions ENUM('yes', 'no') NOT NULL DEFAULT 'no'\r\n        ");
    }
    if ($old_version_info["release_date"] < 20090402) {
        @mysql_query("\r\n      ALTER TABLE {$g_table_prefix}hooks\r\n      ADD hook_type ENUM('code', 'template') NOT NULL DEFAULT 'code' AFTER hook_id\r\n        ");
        @mysql_query("\r\n      ALTER TABLE {$g_table_prefix}hooks\r\n      CHANGE action_location action_location VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL\r\n        ");
        @mysql_query("\r\n      ALTER TABLE {$g_table_prefix}account_settings\r\n      CHANGE setting_value setting_value MEDIUMTEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL\r\n        ");
    }
    if ($old_version_info["release_date"] < 20090510) {
        @mysql_query("\r\n      ALTER TABLE {$g_table_prefix}view_fields\r\n      ADD is_searchable ENUM('yes','no') NOT NULL DEFAULT 'yes' AFTER is_editable\r\n        ");
    }
    // bug #117
    if ($old_version_info["release_date"] < 20090627) {
        @mysql_query("\r\n      ALTER TABLE {$g_table_prefix}view_filters\r\n      CHANGE operator operator ENUM('equals', 'not_equals', 'like', 'not_like', 'before', 'after')\r\n      CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'equals'\r\n        ");
    }
    if ($old_version_info["release_date"] < 20090815) {
        @mysql_query("\r\n      ALTER TABLE {$g_table_prefix}forms\r\n      ADD edit_submission_page_label TEXT NULL\r\n        ");
        // for upgrades, for maximum language compatibility set all the form Edit Submission Labels to
        // $LANG.phrase_edit_submission. They can always change it to English or whatever language they
        // want. New installations will have that value set to the administrator's language
        $forms = ft_get_forms();
        foreach ($forms as $form_info) {
            $form_id = $form_info["form_id"];
            @mysql_query("\r\n        UPDATE {$g_table_prefix}forms\r\n        SET    edit_submission_page_label = '{\$LANG.phrase_edit_submission|upper}'\r\n        WHERE  form_id = {$form_id}\r\n          ");
        }
    }
    if ($old_version_info["release_date"] < 20090826) {
        // bug fix for previous version which had a syntax error
        $query = mysql_query("SHOW COLUMNS FROM {$g_table_prefix}forms");
        $has_edit_submission_page_label_field = false;
        while ($row = mysql_fetch_assoc($query)) {
            if ($row["Field"] == "edit_submission_page_label") {
                $has_edit_submission_page_label_field = true;
            }
        }
        if (!$has_edit_submission_page_label_field) {
            @mysql_query("ALTER TABLE {$g_table_prefix}forms ADD edit_submission_page_label TEXT NULL");
            $forms = ft_get_forms();
            foreach ($forms as $form_info) {
                $form_id = $form_info["form_id"];
                @mysql_query("\r\n          UPDATE {$g_table_prefix}forms\r\n          SET    edit_submission_page_label = '{\$LANG.phrase_edit_submission|upper}'\r\n          WHERE  form_id = {$form_id}\r\n            ");
            }
        }
    }
    if ($old_version_info["release_date"] < 20091113) {
        @mysql_query("ALTER TABLE {$g_table_prefix}view_filters ADD filter_type ENUM('standard', 'client_map') NOT NULL DEFAULT 'standard' AFTER view_id");
        @mysql_query("ALTER TABLE {$g_table_prefix}views ADD has_standard_filter ENUM('yes', 'no') NOT NULL DEFAULT 'no'");
        @mysql_query("ALTER TABLE {$g_table_prefix}views ADD has_client_map_filter ENUM('yes', 'no') NOT NULL DEFAULT 'no'");
        // set the has_standard_filter value to "yes" for any Views that have a filter defined
        $query = @mysql_query("SELECT view_id FROM {$g_table_prefix}view_filters GROUP BY view_id");
        while ($row = mysql_fetch_assoc($query)) {
            $view_id = $row["view_id"];
            @mysql_query("UPDATE {$g_table_prefix}views SET has_standard_filter = 'yes' WHERE view_id = {$view_id}");
        }
    }
    // this version introduced an improved "form email fields" feature that lets you mark multiple email
    // fields as having significance for the email mechanism. All DB changes relate to this new feature.
    if ($old_version_info["release_date"] < 20100118) {
        // [1] misc DB column updates
        @mysql_query("\r\n      ALTER TABLE {$g_table_prefix}email_templates\r\n      ADD email_from_form_email_id MEDIUMINT UNSIGNED NULL AFTER email_from_account_id\r\n        ");
        @mysql_query("\r\n      ALTER TABLE {$g_table_prefix}email_templates\r\n      ADD email_reply_to_form_email_id MEDIUMINT UNSIGNED NULL AFTER email_reply_to_account_id\r\n        ");
        // [2] email_from DB field update
        $email_from_query = mysql_query("\r\n      SELECT email_id\r\n      FROM   {$g_table_prefix}email_templates\r\n      WHERE  email_from = 'user'\r\n        ");
        @mysql_query("\r\n      ALTER TABLE {$g_table_prefix}email_templates\r\n      CHANGE email_from email_from ENUM('admin', 'client', 'form_email_field', 'custom', 'none')\r\n      CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL\r\n        ");
        while ($row = mysql_fetch_assoc($email_from_query)) {
            $email_id = $row["email_id"];
            mysql_query("\r\n        UPDATE {$g_table_prefix}email_templates\r\n        SET    email_from = 'form_email_field'\r\n        WHERE  email_id = {$email_id}\r\n          ");
        }
        // [3] email_reply_to DB field update
        $email_reply_to_query = mysql_query("\r\n      SELECT email_id\r\n      FROM   {$g_table_prefix}email_templates\r\n      WHERE  email_reply_to = 'user'\r\n        ");
        @mysql_query("\r\n      ALTER TABLE {$g_table_prefix}email_templates\r\n      CHANGE email_reply_to email_reply_to ENUM('admin', 'client', 'form_email_field', 'custom', 'none')\r\n      CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL\r\n        ");
        while ($row = mysql_fetch_assoc($email_reply_to_query)) {
            $email_id = $row["email_id"];
            mysql_query("\r\n        UPDATE {$g_table_prefix}email_templates\r\n        SET    email_reply_to = 'form_email_field'\r\n        WHERE  email_id = {$email_id}\r\n          ");
        }
        // [4] create our new form_email_fields table
        @mysql_query("\r\n      CREATE TABLE {$g_table_prefix}form_email_fields (\r\n        form_email_id MEDIUMINT unsigned NOT NULL auto_increment,\r\n        form_id MEDIUMINT UNSIGNED NOT NULL,\r\n        email_field VARCHAR( 255 ) NOT NULL,\r\n        first_name_field VARCHAR( 255 ) NULL,\r\n        last_name_field VARCHAR( 255 ) NULL,\r\n        PRIMARY KEY (form_email_id)\r\n      ) DEFAULT CHARSET=utf8\r\n        ");
        // [5] rename the "recipient_user_type" enum options to call the "user" option "form_email_field" instead,
        // but first, store all the recipient_ids so we can update them after the DB change
        $recipients_id_query = @mysql_query("\r\n      SELECT recipient_id\r\n      FROM   {$g_table_prefix}email_template_recipients\r\n      WHERE  recipient_user_type = 'user'\r\n        ");
        @mysql_query("\r\n      ALTER TABLE {$g_table_prefix}email_template_recipients\r\n      CHANGE recipient_user_type recipient_user_type ENUM('admin', 'client', 'form_email_field', 'custom')\r\n      CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL\r\n        ");
        @mysql_query("\r\n      ALTER TABLE {$g_table_prefix}email_template_recipients\r\n      ADD form_email_id MEDIUMINT UNSIGNED NULL AFTER account_id\r\n        ");
        while ($row = mysql_fetch_assoc($recipients_id_query)) {
            // we can safely set the form_email_id to 1 for these because after upgrading they will
            // have one and only one form email ID
            $recipient_id = $row["recipient_id"];
            mysql_query("\r\n        UPDATE {$g_table_prefix}email_template_recipients\r\n        SET    recipient_user_type = 'form_email_field',\r\n               form_email_id = 1\r\n        WHERE  recipient_id = {$recipient_id}\r\n          ");
        }
        // [6] now update the old "user" email field data to the new "form email field" table
        // and update the corresponding DB tables
        $forms_query = @mysql_query("SELECT form_id, user_email_field, user_first_name_field, user_last_name_field FROM {$g_table_prefix}forms");
        while ($form_info = mysql_fetch_assoc($forms_query)) {
            $form_id = $form_info["form_id"];
            $user_email_field = $form_info["user_email_field"];
            $user_first_name_field = $form_info["user_first_name_field"];
            $user_last_name_field = $form_info["user_last_name_field"];
            if (!empty($user_email_field)) {
                // create the new email field
                @mysql_query("\r\n          INSERT INTO {$g_table_prefix}form_email_fields (form_id, email_field, first_name_field, last_name_field)\r\n          VALUES ({$form_id}, '{$user_email_field}', '{$user_first_name_field}', '{$user_last_name_field}')\r\n            ");
                $form_email_id = mysql_insert_id();
                // "from"
                @mysql_query("\r\n          UPDATE {$g_table_prefix}email_templates\r\n          SET    email_from_form_email_id = {$form_email_id}\r\n          WHERE  form_id = {$form_id} AND\r\n                 email_from = 'form_email_field'\r\n            ");
                // "reply-to"
                @mysql_query("\r\n          UPDATE {$g_table_prefix}email_templates\r\n          SET    email_reply_to_form_email_id = {$form_email_id}\r\n          WHERE  form_id = {$form_id} AND\r\n                 email_reply_to = 'form_email_field'\r\n              ");
                // "to"
                @mysql_query("\r\n          UPDATE {$g_table_prefix}email_template_recipients\r\n          SET    form_email_id = {$form_email_id}\r\n          WHERE  form_id = {$form_id} AND\r\n                 recipient_user_type = 'form_email_field'\r\n              ");
            }
        }
        // delete the old fields in the forms table. They're not needed any more
        @mysql_query("ALTER TABLE {$g_table_prefix}forms DROP COLUMN user_email_field");
        @mysql_query("ALTER TABLE {$g_table_prefix}forms DROP COLUMN user_first_name_field");
        @mysql_query("ALTER TABLE {$g_table_prefix}forms DROP COLUMN user_last_name_field");
    }
    // ----------------------------------------------------------------------------------------------
    // 2.0.3 beta updates
    if ($old_version_info["release_date"] < 20100731) {
        // add the default security setting fields
        $settings = array("default_max_failed_login_attempts" => "", "min_password_length" => "", "required_password_chars" => "", "num_password_history" => "", "clients_may_edit_max_failed_login_attempts" => "");
        ft_set_settings($settings);
        // now set the default values for all clients. This sucks, obviously - but eventually the
        // whole inheritance model for client account settings will be overhauled and replaced with a
        // "Client Group" system
        $client_settings = array("min_password_length" => "", "num_failed_login_attempts" => 0, "num_password_history" => "", "required_password_chars" => "", "may_edit_max_failed_login_attempts" => "");
        $clients = ft_get_client_list();
        foreach ($clients as $client_info) {
            // add the current password to the password history queue
            $client_settings["password_history"] = $client_info["password"];
            ft_set_account_settings($client_info["account_id"], $client_settings);
        }
    }
    if ($old_version_info["release_date"] < 20100908) {
        // convert all core tables to MyISAM
        $core_tables = array("accounts", "account_settings", "client_forms", "client_views", "email_templates", "email_template_edit_submission_views", "email_template_recipients", "field_options", "field_option_groups", "field_settings", "forms", "form_email_fields", "form_fields", "hooks", "menus", "menu_items", "modules", "module_menu_items", "multi_page_form_urls", "public_form_omit_list", "public_view_omit_list", "settings", "sessions", "themes", "views", "view_fields", "view_filters", "view_tabs");
        foreach ($core_tables as $table) {
            @mysql_query("ALTER TABLE {$g_table_prefix}{$table} TYPE=MyISAM");
            @mysql_query("ALTER TABLE {$g_table_prefix}{$table} ENGINE=MyISAM");
        }
        // convert all the custom tables to MyISAM as well
        $forms = ft_get_forms();
        foreach ($forms as $form_info) {
            $form_id = $form_info["form_id"];
            @mysql_query("ALTER TABLE {$g_table_prefix}form_{$form_id} TYPE=MyISAM");
            @mysql_query("ALTER TABLE {$g_table_prefix}form_{$form_id} ENGINE=MyISAM");
        }
    }
    // ----------------------------------------------------------------------------------------------
    // 2.1.0
    if ($old_version_info["release_date"] < 20110509) {
        // create the new 2.1.0 tables (this is only ever done once!)
        $check_tables_query = mysql_query("SHOW TABLES");
        $existing_tables = array();
        while ($row = mysql_fetch_array($check_tables_query)) {
            $existing_tables[] = $row[0];
        }
        if (!in_array("{$g_table_prefix}field_type_setting_options", $existing_tables)) {
            $query = mysql_query("\r\n        CREATE TABLE {$g_table_prefix}field_type_setting_options (\r\n          setting_id mediumint(9) NOT NULL,\r\n          option_text varchar(255) default NULL,\r\n          option_value varchar(255) default NULL,\r\n          option_order smallint(6) NOT NULL,\r\n          is_new_sort_group enum('yes','no') NOT NULL,\r\n          PRIMARY KEY  (setting_id,option_order)\r\n        ) DEFAULT CHARSET=utf8\r\n      ");
            // textbox - size
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (1, 'Tiny', 'cf_size_tiny', 1, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (1, 'Small', 'cf_size_small', 2, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (1, 'Medium', 'cf_size_medium', 3, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (1, 'Large', 'cf_size_large', 4, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (1, 'Full Width', 'cf_size_full_width', 5, 'yes')");
            // textbox - highlight
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (3, 'Orange', 'cf_colour_orange', 3, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (3, 'Yellow', 'cf_colour_yellow', 4, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (3, 'Red', 'cf_colour_red', 2, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (3, 'None', '', 1, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (3, 'Green', 'cf_colour_green', 5, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (3, 'Blue', 'cf_colour_blue', 6, 'yes')");
            // textarea - height
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (5, 'Tiny (30px)', 'cf_size_tiny', 1, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (5, 'Small (80px)', 'cf_size_small', 2, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (5, 'Medium (150px)', 'cf_size_medium', 3, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (5, 'Large (300px)', 'cf_size_large', 4, 'yes')");
            // textarea - highlight
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (6, 'None', '', 1, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (6, 'Red', 'cf_colour_red', 2, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (6, 'Orange', 'cf_colour_orange', 3, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (6, 'Yellow', 'cf_colour_yellow', 4, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (6, 'Green', 'cf_colour_green', 5, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (6, 'Blue', 'cf_colour_blue', 6, 'yes')");
            // textarea - input length
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (7, 'No Limit', '', 1, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (7, 'Words', 'words', 2, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (7, 'Characters', 'chars', 3, 'yes')");
            // radios
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (17, 'Horizontal', 'horizontal', 1, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (17, 'Vertical', 'vertical', 2, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (17, '2 Columns', 'cf_option_list_2cols', 3, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (17, '3 Columns', 'cf_option_list_3cols', 4, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (17, '4 Columns', 'cf_option_list_4cols', 5, 'yes')");
            // checkboxes
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (20, 'Horizontal', 'horizontal', 1, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (20, 'Vertical', 'vertical', 2, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (20, '2 Columns', 'cf_option_list_2cols', 3, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (20, '3 Columns', 'cf_option_list_3cols', 4, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (20, '4 Columns', 'cf_option_list_4cols', 5, 'yes')");
            // date
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (22, '2011-11-30', 'yy-mm-dd', 1, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (22, '30/11/2011 (dd/mm/yyyy)', 'dd/mm/yy', 2, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (22, '11/30/2011 (mm/dd/yyyy)', 'mm/dd/yy', 3, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (22, 'Nov 30, 2011', 'M d, yy', 4, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (22, 'November 30, 2011', 'MM d, yy', 5, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (22, 'Wed Nov 30, 2011 ', 'D M d, yy', 6, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (22, 'Wednesday, November 30, 2011', 'DD, MM d, yy', 7, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (22, '30. 08. 2011.', 'dd. mm. yy.', 8, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (22, '30/11/2011 8:00 PM', 'datetime:dd/mm/yy|h:mm TT|ampm`true', 9, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (22, '11/30/2011 8:00 PM', 'datetime:mm/dd/yy|h:mm TT|ampm`true', 10, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (22, '2011-11-30 8:00 PM', 'datetime:yy-mm-dd|h:mm TT|ampm`true', 11, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (22, '2011-11-30 20:00', 'datetime:yy-mm-dd|hh:mm', 12, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (22, '2011-11-30 20:00:00', 'datetime:yy-mm-dd|hh:mm:ss|showSecond`true', 13, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (22, '30. 08. 2011. 20:00', 'datetime:dd. mm. yy.|hh:mm', 14, 'yes')");
            // time
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (24, '8:00 AM', 'h:mm TT|ampm`true', 1, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (24, '16:00', 'hh:mm|ampm`false', 2, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (24, '16:00:00', 'hh:mm:ss|showSecond`true|ampm`false', 3, 'yes')");
            // code / markup
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (28, 'CSS', 'CSS', 1, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (28, 'HTML', 'HTML', 2, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (28, 'JavaScript', 'JavaScript', 3, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (28, 'XML', 'XML', 4, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (29, 'Tiny (50px)', '50', 1, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (29, 'Small (100px)', '100', 2, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (29, 'Medium (200px)', '200', 3, 'yes')");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES (29, 'Large (400px)', '400', 4, 'yes')");
        }
        if (!in_array("{$g_table_prefix}field_type_settings", $existing_tables)) {
            $query = mysql_query("\r\n        CREATE TABLE {$g_table_prefix}field_type_settings (\r\n          setting_id mediumint(8) unsigned NOT NULL auto_increment,\r\n          field_type_id mediumint(8) unsigned NOT NULL,\r\n          field_label varchar(255) NOT NULL,\r\n          field_setting_identifier varchar(50) NOT NULL,\r\n          field_type enum('textbox','textarea','radios','checkboxes','select','multi-select','option_list_or_form_field') NOT NULL,\r\n          field_orientation enum('horizontal','vertical','na') NOT NULL default 'na',\r\n          default_value_type enum('static','dynamic') NOT NULL default 'static',\r\n          default_value varchar(255) default NULL,\r\n          list_order smallint(6) NOT NULL,\r\n          PRIMARY KEY  (setting_id)\r\n        ) DEFAULT CHARSET=utf8\r\n      ");
            // textbox
            mysql_query("INSERT INTO {$g_table_prefix}field_type_settings VALUES (1, 1, 'Size', 'size', 'select', 'na', 'static', 'cf_size_medium', 1)");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_settings VALUES (2, 1, 'Max Length', 'maxlength', 'textbox', 'na', 'static', '', 2)");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_settings VALUES (3, 1, 'Highlight', 'highlight', 'select', 'na', 'static', '', 4)");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_settings VALUES (4, 1, 'Field Comments', 'comments', 'textarea', 'na', 'static', '', 3)");
            // textarea
            mysql_query("INSERT INTO {$g_table_prefix}field_type_settings VALUES (5, 2, 'Height', 'height', 'select', 'na', 'static', 'cf_size_small', 1)");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_settings VALUES (6, 2, 'Highlight Colour', 'highlight_colour', 'select', 'na', 'static', '', 3)");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_settings VALUES (7, 2, 'Input length limit', 'input_length', 'radios', 'horizontal', 'static', '', 4)");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_settings VALUES (8, 2, '- Max length (words/chars)', 'maxlength', 'textbox', 'na', 'static', '', 5)");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_settings VALUES (9, 2, 'Field Comments', 'comments', 'textarea', 'na', 'static', '', 2)");
            // password
            mysql_query("INSERT INTO {$g_table_prefix}field_type_settings VALUES (10, 3, 'Field Comments', 'comments', 'textarea', 'na', 'static', '', 1)");
            // dropdown
            mysql_query("INSERT INTO {$g_table_prefix}field_type_settings VALUES (11, 4, 'Option List / Contents', 'contents', 'option_list_or_form_field', 'na', 'static', '', 1)");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_settings VALUES (12, 4, 'Field Comments', 'comments', 'textarea', 'na', 'static', '', 2)");
            // multi-select dropdown
            mysql_query("INSERT INTO {$g_table_prefix}field_type_settings VALUES (13, 5, 'Option List / Contents', 'contents', 'option_list_or_form_field', 'na', 'static', '', 1)");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_settings VALUES (14, 5, 'Num Rows', 'num_rows', 'textbox', 'na', 'static', '5', 2)");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_settings VALUES (15, 5, 'Field Comments', 'comments', 'textarea', 'na', 'static', '', 3)");
            // radios
            mysql_query("INSERT INTO {$g_table_prefix}field_type_settings VALUES (16, 6, 'Option List / Contents', 'contents', 'option_list_or_form_field', 'na', 'static', '', 1)");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_settings VALUES (17, 6, 'Formatting', 'formatting', 'select', 'na', 'static', 'horizontal', 2)");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_settings VALUES (18, 6, 'Field Comments', 'comments', 'textarea', 'na', 'static', '', 3)");
            // checkboxes
            mysql_query("INSERT INTO {$g_table_prefix}field_type_settings VALUES (19, 7, 'Option List / Contents', 'contents', 'option_list_or_form_field', 'na', 'static', '', 1)");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_settings VALUES (20, 7, 'Formatting', 'formatting', 'select', 'na', 'static', 'horizontal', 2)");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_settings VALUES (21, 7, 'Field Comments', 'comments', 'textarea', 'na', 'static', '', 3)");
            // date
            mysql_query("INSERT INTO {$g_table_prefix}field_type_settings VALUES (22, 8, 'Custom Display Format', 'display_format', 'select', 'na', 'static', 'yy-mm-dd', 1)");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_settings VALUES (23, 8, 'Field Comments', 'comments', 'textarea', 'na', 'static', '', 2)");
            // time
            mysql_query("INSERT INTO {$g_table_prefix}field_type_settings VALUES (24, 9, 'Custom Display Format', 'display_format', 'select', 'na', 'static', 'h:mm TT|ampm`true', 1)");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_settings VALUES (25, 9, 'Field Comments', 'comments', 'textarea', 'na', 'static', '', 2)");
            // phone number
            mysql_query("INSERT INTO {$g_table_prefix}field_type_settings VALUES (26, 10, 'Phone Number Format', 'phone_number_format', 'textbox', 'na', 'static', '(xxx) xxx-xxxx', 1)");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_settings VALUES (27, 10, 'Field Comments', 'comments', 'textarea', 'na', 'static', '', 2)");
            // code / markup
            mysql_query("INSERT INTO {$g_table_prefix}field_type_settings VALUES (28, 11, 'Code / Markup Type', 'code_markup', 'select', 'na', 'static', 'HTML', 1)");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_settings VALUES (29, 11, 'Height', 'height', 'select', 'na', 'static', '200', 2)");
            mysql_query("INSERT INTO {$g_table_prefix}field_type_settings VALUES (30, 11, 'Field Comments', 'comments', 'textarea', 'na', 'static', '', 3)");
        }
        if (!in_array("{$g_table_prefix}field_types", $existing_tables)) {
            $query = mysql_query("\r\n        CREATE TABLE {$g_table_prefix}field_types (\r\n          field_type_id mediumint(8) unsigned NOT NULL auto_increment,\r\n          is_editable enum('yes','no') NOT NULL,\r\n          non_editable_info mediumtext,\r\n          managed_by_module_id mediumint(9) default NULL,\r\n          field_type_name varchar(255) NOT NULL,\r\n          field_type_identifier varchar(50) NOT NULL,\r\n          group_id smallint(6) NOT NULL,\r\n          is_file_field enum('yes','no') NOT NULL default 'no',\r\n          is_date_field enum('yes','no') NOT NULL default 'no',\r\n          raw_field_type_map varchar(50) default NULL,\r\n          raw_field_type_map_multi_select_id mediumint(9) default NULL,\r\n          list_order smallint(6) NOT NULL,\r\n          compatible_field_sizes varchar(255) NOT NULL,\r\n          view_field_smarty_markup mediumtext NOT NULL,\r\n          edit_field_smarty_markup mediumtext NOT NULL,\r\n          php_processing mediumtext NOT NULL,\r\n          resources_css mediumtext,\r\n          resources_js mediumtext,\r\n          PRIMARY KEY (field_type_id)\r\n        ) DEFAULT CHARSET=utf8\r\n      ");
            mysql_query("INSERT INTO {$g_table_prefix}field_types VALUES (1, 'no', '{\$LANG.text_non_deletable_fields}', NULL, '{\$LANG.word_textbox}', 'textbox', 1, 'no', 'no', 'textbox', NULL, 1, '1char,2chars,tiny,small,medium,large,very_large', '\r\n', '<input type=\"text\" name=\"{\$NAME}\" value=\"{\$VALUE|escape}\" \r\n  class=\"{\$size}{if \$highlight} {\$highlight}{/if}\" \r\n  {if \$maxlength}maxlength=\"{\$maxlength}\"{/if} />\r\n \r\n{if \$comments}\r\n  <div class=\"cf_field_comments\">{\$comments}</div>\r\n{/if}\r\n', '\r\n', 'input.cf_size_tiny {\r\n  width: 30px; \r\n}\r\ninput.cf_size_small {\r\n  width: 80px; \r\n}\r\ninput.cf_size_medium {\r\n  width: 150px; \r\n}\r\ninput.cf_size_large {\r\n  width: 250px;\r\n}\r\ninput.cf_size_full_width {\r\n  width: 99%; \r\n}\r\n\r\n', '')");
            mysql_query("INSERT INTO {$g_table_prefix}field_types VALUES (2, 'yes', NULL, NULL, '{\$LANG.word_textarea}', 'textarea', 1, 'no', 'no', 'textarea', NULL, 2, 'medium,large,very_large', '{\$VALUE|nl2br}', '{* figure out all the classes *}\r\n{assign var=classes value=\$height}\r\n{if \$highlight_colour}\r\n  {assign var=classes value=\"`\$classes` `\$highlight_colour`\"}\r\n{/if}\r\n{if \$input_length == \"words\" && \$maxlength != \"\"}\r\n  {assign var=classes value=\"`\$classes` cf_wordcounter max`\$maxlength`\"}\r\n{else if \$input_length == \"chars\" && \$maxlength != \"\"}\r\n  {assign var=classes value=\"`\$classes` cf_textcounter max`\$maxlength`\"}\r\n{/if}\r\n\r\n<textarea name=\"{\$NAME}\" id=\"{\$NAME}_id\" class=\"{\$classes}\">{\$VALUE}</textarea>\r\n\r\n{if \$input_length == \"words\" && \$maxlength != \"\"}\r\n  <div class=\"cf_counter\" id=\"{\$NAME}_counter\">\r\n    {\$maxlength} word limit. <span></span> remaining words\r\n  </div>\r\n{elseif \$input_length == \"chars\" && \$max_length != \"\"}\r\n  <div class=\"cf_counter\" id=\"{\$NAME}_counter\">\r\n    {\$maxlength} characters limit. <span></span> remaining characters\r\n  </div>\r\n{/if}\r\n\r\n{if \$comments}\r\n  <div class=\"cf_field_comments\">{\$comments|nl2br}</div>\r\n{/if}\r\n', '', '.cf_counter span {\r\n  font-weight: bold; \r\n}\r\ntextarea {\r\n  width: 99%;\r\n}\r\ntextarea.cf_size_tiny {\r\n  height: 30px;\r\n}\r\ntextarea.cf_size_small {\r\n  height: 80px;  \r\n}\r\ntextarea.cf_size_medium {\r\n  height: 150px;  \r\n}\r\ntextarea.cf_size_large {\r\n  height: 300px;\r\n}\r\n', '/**\r\n * The following code provides a simple text/word counter option for any  \r\n * textarea. It either just keeps counting up, or limits the results to a\r\n * certain number - all depending on what the user has selected via the\r\n * field type settings.\r\n */\r\nvar cf_counter = {};\r\ncf_counter.get_max_count = function(el) {\r\n  var classes = \$(el).attr(''class'').split(\" \").slice(-1);\r\n  var max = null;\r\n  for (var i=0; i<classes.length; i++) {\r\n    var result = classes[i].match(/max(\\\\d+)/);\r\n    if (result != null) {\r\n      max = result[1];\r\n      break;\r\n    }\r\n  }\r\n  return max;\r\n}\r\n\r\n\$(function() {\r\n  \$(\"textarea[class~=''cf_wordcounter'']\").each(function() {\r\n    var max = cf_counter.get_max_count(this);\r\n    if (max == null) {\r\n      return;\r\n    }\r\n    \$(this).bind(\"keydown\", function() {\r\n      var val = \$(this).val();\r\n      var len        = val.split(/[\\\\s]+/);\r\n      var field_name = \$(this).attr(\"name\");\r\n      var num_words  = len.length - 1;\r\n      if (num_words > max) {\r\n        var allowed_words = val.split(/[\\\\s]+/, max);\r\n        truncated_str = allowed_words.join(\" \");\r\n        \$(this).val(truncated_str);\r\n      } else {\r\n        \$(\"#\" + field_name + \"_counter\").find(\"span\").html(parseInt(max) - parseInt(num_words));\r\n      }\r\n    });     \r\n    \$(this).trigger(\"keydown\");\r\n  });\r\n\r\n  \$(\"textarea[class~=''cf_textcounter'']\").each(function() {\r\n    var max = cf_counter.get_max_count(this);\r\n    if (max == null) {\r\n      return;\r\n    }\r\n    \$(this).bind(\"keydown\", function() {    \r\n      var field_name = \$(this).attr(\"name\");      \r\n      if (this.value.length > max) {\r\n        this.value = this.value.substring(0, max);\r\n      } else {\r\n        \$(\"#\" + field_name + \"_counter\").find(\"span\").html(max - this.value.length);\r\n      }\r\n    });\r\n    \$(this).trigger(\"keydown\");\r\n  }); \r\n});\r\n\r\n')");
            mysql_query("INSERT INTO {$g_table_prefix}field_types VALUES (3, 'yes', NULL, NULL, '{\$LANG.word_password}', 'password', 1, 'no', 'no', 'password', NULL, 3, '1char,2chars,tiny,small,medium', '\r\n', '<input type=\"password\" name=\"{\$NAME}\" value=\"{\$VALUE|escape}\" \r\n  class=\"cf_password\" />\r\n \r\n{if \$comments}\r\n  <div class=\"cf_field_comments\">{\$comments}</div>\r\n{/if}\r\n', '', 'input.cf_password {\r\n  width: 120px;\r\n}\r\n', '')");
            mysql_query("INSERT INTO {$g_table_prefix}field_types VALUES (4, 'yes', NULL, NULL, '{\$LANG.word_dropdown}', 'dropdown', 1, 'no', 'no', 'select', 11, 6, '1char,2chars,tiny,small,medium,large', '{if \$contents != \"\"}\r\n  {assign var=counter value=\"1\"}\r\n  {foreach from=\$.options item=curr_group_info name=group}\r\n    {assign var=group_info value=\$curr_group_info.group_info}\r\n    {assign var=options value=\$curr_group_info.options}\r\n    {foreach from=\$options item=option name=row}\r\n      {if \$VALUE == \$option.option_value}{\$option.option_name}{/if}\r\n    {/foreach}\r\n  {/foreach}\r\n{/if}', '{if \$contents == \"\"}\r\n  <div class=\"cf_field_comments\">\r\n    This field isn''t assigned to an Option List. \r\n  </div>\r\n{else}\r\n  <select name=\"{\$NAME}\">\r\n  {foreach from=\$contents.options item=curr_group_info name=group}\r\n    {assign var=group_info value=\$curr_group_info.group_info}\r\n    {assign var=options value=\$curr_group_info.options}\r\n    {if \$group_info.group_name}\r\n      <optgroup label=\"{\$group_info.group_name|escape}\">\r\n    {/if}\r\n    {foreach from=\$options item=option name=row}\r\n      <option value=\"{\$option.option_value}\"\r\n        {if \$VALUE == \$option.option_value}selected{/if}>{\$option.option_name}</option>\r\n    {/foreach}\r\n    {if \$group_info.group_name}\r\n      </optgroup>\r\n    {/if}\r\n  {/foreach}\r\n  </select>\r\n{/if}\r\n\r\n{if \$comments}\r\n  <div class=\"cf_field_comments\">{\$comments}</div>\r\n{/if}\r\n\r\n', '', '', '')");
            mysql_query("INSERT INTO {$g_table_prefix}field_types VALUES (5, 'yes', NULL, NULL, '{\$LANG.phrase_multi_select_dropdown}', 'multi_select_dropdown', 1, 'no', 'no', 'multi-select', 13, 7, '1char,2chars,tiny,small,medium,large', '{if \$contents != \"\"}\r\n  {assign var=vals value=\"`\$g_multi_val_delimiter`\"|explode:\$VALUE}\r\n  {assign var=is_first value=true}\r\n  {strip}\r\n  {foreach from=\$contents.options item=curr_group_info name=group}\r\n    {assign var=options value=\$curr_group_info.options}\r\n    {foreach from=\$options item=option name=row}\r\n      {if \$option.option_value|in_array:\$vals}\r\n        {if \$is_first == false}, {/if}\r\n        {\$option.option_name}\r\n        {assign var=is_first value=false}\r\n      {/if}\r\n    {/foreach}\r\n  {/foreach}\r\n  {/strip}\r\n{/if}', '{if \$contents == \"\"}\r\n  <div class=\"cf_field_comments\">\r\n    This field isn''t assigned to an Option List. \r\n  </div>\r\n{else}\r\n  {assign var=vals value=\"`\$g_multi_val_delimiter`\"|explode:\$VALUE}\r\n  <select name=\"{\$NAME}[]\" multiple size=\"{if \$num_rows}{\$num_rows}{else}5{/if}\">\r\n  {foreach from=\$contents.options item=curr_group_info name=group}\r\n    {assign var=group_info value=\$curr_group_info.group_info}\r\n    {assign var=options value=\$curr_group_info.options}\r\n    {if \$group_info.group_name}\r\n      <optgroup label=\"{\$group_info.group_name|escape}\">\r\n    {/if}\r\n    {foreach from=\$options item=option name=row}\r\n      <option value=\"{\$option.option_value}\"\r\n        {if \$option.option_value|in_array:\$vals}selected{/if}>{\$option.option_name}</option>\r\n    {/foreach}\r\n    {if \$group_info.group_name}\r\n      </optgroup>\r\n    {/if}\r\n  {/foreach}\r\n  </select>\r\n{/if}\r\n\r\n{if \$comments}\r\n  <div class=\"cf_field_comments\">{\$comments}</div>\r\n{/if}\r\n', '', '', '')");
            mysql_query("INSERT INTO {$g_table_prefix}field_types VALUES (6, 'yes', NULL, NULL, '{\$LANG.phrase_radio_buttons}', 'radio_buttons', 1, 'no', 'no', 'radio-buttons', 16, 4, '1char,2chars,tiny,small,medium,large', '{if \$contents != \"\"}\r\n  {assign var=counter value=\"1\"}\r\n  {foreach from=\$contents.options item=curr_group_info name=group}\r\n    {assign var=group_info value=\$curr_group_info.group_info}\r\n    {assign var=options value=\$curr_group_info.options}\r\n    {foreach from=\$options item=option name=row}\r\n      {if \$VALUE == \$option.option_value}{\$option.option_name}{/if}\r\n    {/foreach}\r\n  {/foreach}\r\n{/if}\r\n', '{if \$contents == \"\"}\r\n  <div class=\"cf_field_comments\">\r\n    This field isn''t assigned to an Option List. \r\n  </div>\r\n{else}\r\n  {assign var=is_in_columns value=false}\r\n  {if \$formatting == \"cf_option_list_2cols\" || \r\n      \$formatting == \"cf_option_list_3cols\" || \r\n      \$formatting == \"cf_option_list_4cols\"}\r\n    {assign var=is_in_columns value=true}\r\n  {/if}\r\n\r\n  {assign var=counter value=\"1\"}\r\n  {foreach from=\$contents.options item=curr_group_info name=group}\r\n    {assign var=group_info value=\$curr_group_info.group_info}\r\n    {assign var=options value=\$curr_group_info.options}\r\n\r\n    {if \$group_info.group_name}\r\n      <div class=\"cf_option_list_group_label\">{\$group_info.group_name}</div>\r\n    {/if}\r\n\r\n    {if \$is_in_columns}<div class=\"{\$formatting}\">{/if}\r\n\r\n    {foreach from=\$options item=option name=row}\r\n      {if \$is_in_columns}<div class=\"column\">{/if}\r\n        <input type=\"radio\" name=\"{\$NAME}\" id=\"{\$NAME}_{\$counter}\" \r\n          value=\"{\$option.option_value}\"\r\n          {if \$VALUE == \$option.option_value}checked{/if} />\r\n          <label for=\"{\$NAME}_{\$counter}\">{\$option.option_name}</label>\r\n      {if \$is_in_columns}</div>{/if}\r\n      {if \$formatting == \"vertical\"}<br />{/if}\r\n      {assign var=counter value=\$counter+1}\r\n    {/foreach}\r\n\r\n    {if \$is_in_columns}</div>{/if}\r\n  {/foreach}\r\n\r\n  {if \$comments}<div class=\"cf_field_comments\">{\$comments}</div>{/if}\r\n{/if}\r\n', '', '/* All CSS styles for this field type are found in Shared Resources */\r\n', '')");
            mysql_query("INSERT INTO {$g_table_prefix}field_types VALUES (7, 'yes', NULL, NULL, '{\$LANG.word_checkboxes}', 'checkboxes', 1, 'no', 'no', 'checkboxes', 19, 5, '1char,2chars,tiny,small,medium,large', '{if \$contents != \"\"}\r\n  {assign var=vals value=\"`\$g_multi_val_delimiter`\"|explode:\$VALUE}\r\n  {assign var=is_first value=true}\r\n  {strip}\r\n  {foreach from=\$contents.options item=curr_group_info name=group}\r\n    {assign var=options value=\$curr_group_info.options}\r\n    {foreach from=\$options item=option name=row}\r\n      {if \$option.option_value|in_array:\$vals}\r\n        {if \$is_first == false}, {/if}\r\n        {\$option.option_name}\r\n        {assign var=is_first value=false}\r\n      {/if}\r\n    {/foreach}\r\n  {/foreach}\r\n  {/strip}\r\n{/if}', '{if \$contents == \"\"}\r\n  <div class=\"cf_field_comments\">\r\n    This field isn''t assigned to an Option List. \r\n  </div>\r\n{else}\r\n  {assign var=vals value=\"`\$g_multi_val_delimiter`\"|explode:\$VALUE}\r\n  {assign var=is_in_columns value=false}\r\n  {if \$formatting == \"cf_option_list_2cols\" || \r\n      \$formatting == \"cf_option_list_3cols\" || \r\n      \$formatting == \"cf_option_list_4cols\"}\r\n    {assign var=is_in_columns value=true}\r\n  {/if}\r\n\r\n  {assign var=counter value=\"1\"}\r\n  {foreach from=\$contents.options item=curr_group_info name=group}\r\n    {assign var=group_info value=\$curr_group_info.group_info}\r\n    {assign var=options value=\$curr_group_info.options}\r\n\r\n    {if \$group_info.group_name}\r\n      <div class=\"cf_option_list_group_label\">{\$group_info.group_name}</div>\r\n    {/if}\r\n\r\n    {if \$is_in_columns}<div class=\"{\$formatting}\">{/if}\r\n\r\n    {foreach from=\$options item=option name=row}\r\n      {if \$is_in_columns}<div class=\"column\">{/if}\r\n        <input type=\"checkbox\" name=\"{\$NAME}[]\" id=\"{\$NAME}_{\$counter}\" \r\n          value=\"{\$option.option_value|escape}\" \r\n          {if \$option.option_value|in_array:\$vals}checked{/if} />\r\n          <label for=\"{\$NAME}_{\$counter}\">{\$option.option_name}</label>\r\n      {if \$is_in_columns}</div>{/if}\r\n      {if \$formatting == \"vertical\"}<br />{/if}\r\n      {assign var=counter value=\$counter+1}\r\n    {/foreach}\r\n\r\n    {if \$is_in_columns}</div>{/if}\r\n  {/foreach}\r\n\r\n  {if {\$comments}\r\n    <div class=\"cf_field_comments\">{\$comments}</div> \r\n  {/if}\r\n{/if}\r\n', '', '/* all CSS is found in Shared Resources */\r\n', '')");
            mysql_query("\r\n        INSERT INTO {$g_table_prefix}field_types (field_type_id, is_editable, non_editable_info, managed_by_module_id, field_type_name,\r\n          field_type_identifier, group_id, is_file_field, is_date_field, raw_field_type_map, raw_field_type_map_multi_select_id,\r\n          list_order, compatible_field_sizes, view_field_smarty_markup, edit_field_smarty_markup, php_processing,\r\n          resources_css, resources_js)\r\n        VALUES (8, 'no', '{\$LANG.text_non_deletable_fields}', NULL, 'Date', 'date', 2, 'no', 'yes', '', NULL, 1, 'small', '', '', '',\r\n            '.cf_datepicker {\r\n  width: 160px; \r\n}\r\n.cf_datetimepicker {\r\n  width: 160px; \r\n}\r\n.ui-datepicker-trigger {\r\n  cursor: pointer; \r\n}\r\n',\r\n            '\$(function() {\r\n  // the datetimepicker has a bug that prevents the icon from appearing. So\r\n  // instead, we add the image manually into the page and assign the open event\r\n  // handler to the image\r\n  var default_settings = {\r\n    changeYear: true,\r\n    changeMonth: true   \r\n  }\r\n\r\n  \$(\".cf_datepicker\").each(function() {\r\n    var field_name = \$(this).attr(\"name\");\r\n    var settings = default_settings;\r\n    if (\$(\"#\" + field_name + \"_id\").length) {\r\n      settings.dateFormat = \$(\"#\" + field_name + \"_format\").val();\r\n    }\r\n    \$(this).datepicker(settings);\r\n    \$(\"#\" + field_name + \"_icon_id\").bind(\"click\",\r\n      { field_id: \"#\" + field_name + \"_id\" }, function(e) {      \r\n      \$.datepicker._showDatepicker(\$(e.data.field_id)[0]);\r\n    });\r\n  });\r\n    \r\n  \$(\".cf_datetimepicker\").each(function() {\r\n    var field_name = \$(this).attr(\"name\");\r\n    var settings = default_settings;\r\n    if (\$(\"#\" + field_name + \"_id\").length) {\r\n      var settings_str = \$(\"#\" + field_name + \"_format\").val();\r\n      settings_str = settings_str.replace(/datetime:/, \"\");\r\n      var settings_list = settings_str.split(\"|\");\r\n      var settings = {};\r\n      settings.dateFormat = settings_list[0];\r\n      settings.timeFormat = settings_list[1];      \r\n      for (var i=2; i<settings_list.length; i++) {\r\n        var parts = settings_list[i].split(\"`\");\r\n        if (parts[1] === \"true\") {\r\n          parts[1] = true;\r\n        }\r\n        settings[parts[0]] = parts[1];\r\n      }\r\n    }\r\n    \$(this).datetimepicker(settings);\r\n    \$(\"#\" + field_name + \"_icon_id\").bind(\"click\",\r\n      { field_id: \"#\" + field_name + \"_id\" }, function(e) {      \r\n      \$.datepicker._showDatepicker(\$(e.data.field_id)[0]);\r\n    });\r\n  });  \r\n});')");
            mysql_query("INSERT INTO {$g_table_prefix}field_types VALUES (9, 'yes', NULL, NULL, '{\$LANG.word_time}', 'time', 2, 'no', 'no', '', NULL, 2, 'small', '', '<div class=\"cf_date_group\">\r\n  <input type=\"input\" name=\"{\$NAME}\" value=\"{\$VALUE}\" class=\"cf_datefield cf_timepicker\" />\r\n  <input type=\"hidden\" id=\"{\$NAME}_id\" value=\"{\$display_format}\" />\r\n  \r\n  {if \$comments}\r\n    <div class=\"cf_field_comments\">{\$comments}</div>\r\n  {/if}\r\n</div>\r\n', '\r\n', '.cf_timepicker {\r\n  width: 60px; \r\n}\r\n.ui-timepicker-div .ui-widget-header{ margin-bottom: 8px; }\r\n.ui-timepicker-div dl{ text-align: left; }\r\n.ui-timepicker-div dl dt{ height: 25px; }\r\n.ui-timepicker-div dl dd{ margin: -25px 0 10px 65px; }\r\n.ui-timepicker-div td { font-size: 90%; }\r\n\r\n', '\$(function() {  \r\n  var default_settings = {\r\n    buttonImage:     g.root_url + \"/global/images/clock.png\",      \r\n    showOn:          \"both\",\r\n    buttonImageOnly: true\r\n  }\r\n  \$(\".cf_timepicker\").each(function() {\r\n    var field_name = \$(this).attr(\"name\");\r\n    var settings = default_settings;\r\n    if (\$(\"#\" + field_name + \"_id\").length) {\r\n      var settings_list = \$(\"#\" + field_name + \"_id\").val().split(\"|\");      \r\n      if (settings_list.length > 0) {\r\n        settings.timeFormat = settings_list[0];\r\n        for (var i=1; i<settings_list.length; i++) {\r\n          var parts = settings_list[i].split(\"`\");\r\n          if (parts[1] === \"true\") {\r\n            parts[1] = true;\r\n          } else if (parts[1] === \"false\") {\r\n            parts[1] = false;\r\n          }\r\n          settings[parts[0]] = parts[1];\r\n        }\r\n      }\r\n    }\r\n    \$(this).timepicker(settings);\r\n  });\r\n});\r\n\r\n')");
            mysql_query("INSERT INTO {$g_table_prefix}field_types VALUES (10, 'yes', NULL, NULL, '{\$LANG.phrase_phone_number}', 'phone', 2, 'no', 'no', '', NULL, 3, 'small,medium', '{php}\r\n\$format = \$this->get_template_vars(\"phone_number_format\");\r\n\$values = explode(\"|\", \$this->get_template_vars(\"VALUE\"));\r\n\$pieces = preg_split(\"/(x+)/\", \$format, 0, PREG_SPLIT_DELIM_CAPTURE);\r\n\$counter = 1;\r\n\$output = \"\";\r\n\$has_content = false;\r\nforeach (\$pieces as \$piece)\r\n{\r\n  if (empty(\$piece))\r\n    continue;\r\n\r\n  if (\$piece[0] == \"x\") {    \r\n    \$value = (isset(\$values[\$counter-1])) ? \$values[\$counter-1] : \"\";\r\n    \$output .= \$value;\r\n    if (!empty(\$value))\r\n    {\r\n      \$has_content = true;\r\n    }\r\n    \$counter++;\r\n  } else {\r\n    \$output .= \$piece;\r\n  }\r\n}\r\n\r\nif (!empty(\$output) && \$has_content)\r\n  echo \$output;\r\n{/php}', '{php}\r\n\$format = \$this->get_template_vars(\"phone_number_format\");\r\n\$values = explode(\"|\", \$this->get_template_vars(\"VALUE\"));\r\n\$name   = \$this->get_template_vars(\"NAME\");\r\n\r\n\$pieces = preg_split(\"/(x+)/\", \$format, 0, PREG_SPLIT_DELIM_CAPTURE);\r\n\$counter = 1;\r\nforeach (\$pieces as \$piece)\r\n{\r\n  if (strlen(\$piece) == 0)\r\n    continue;\r\n\r\n  if (\$piece[0] == \"x\") {\r\n    \$size = strlen(\$piece); \r\n    \$value = (isset(\$values[\$counter-1])) ? \$values[\$counter-1] : \"\";\r\n    \$value = htmlspecialchars(\$value);\r\n    echo \"<input type=\\\\\"text\\\\\" name=\\\\\"{\$name}_\$counter\\\\\" value=\\\\\"\$value\\\\\"\r\n            size=\\\\\"\$size\\\\\" maxlength=\\\\\"\$size\\\\\" />\";\r\n    \$counter++;\r\n  } else {\r\n    echo \$piece;\r\n  }\r\n}\r\n{/php}\r\n{if \$comments}\r\n  <div class=\"cf_field_comments\">{\$comments}</div>\r\n{/if}\r\n', '\$field_name = \$vars[\"field_info\"][\"field_name\"];\r\n\$joiner = \"|\";\r\n\r\n\$count = 1;\r\n\$parts = array();\r\nwhile (isset(\$vars[\"data\"][\"{\$field_name}_\$count\"]))\r\n{\r\n  \$parts[] = \$vars[\"data\"][\"{\$field_name}_\$count\"];\r\n  \$count++;\r\n}\r\n\$value = implode(\"|\", \$parts);\r\n\r\n\r\n', '', '')");
            mysql_query("INSERT INTO {$g_table_prefix}field_types VALUES (11, 'yes', NULL, NULL, '{\$LANG.phrase_code_markup_field}', 'code_markup', 2, 'no', 'no', 'textarea', NULL, 4, 'large,very_large', '{if \$CONTEXTPAGE == \"edit_submission\"}\r\n  <textarea id=\"{\$NAME}_id\" name=\"{\$NAME}\">{\$VALUE}</textarea>\r\n  <script>\r\n  var code_mirror_{\$NAME} = new CodeMirror.fromTextArea(\"{\$NAME}_id\", \r\n  {literal}{{/literal}\r\n    height: \"{\$SIZE_PX}px\",\r\n    path:   \"{\$g_root_url}/global/codemirror/js/\",\r\n    readOnly: true,\r\n    {if \$code_markup == \"HTML\" || \$code_markup == \"XML\"}\r\n      parserfile: [\"parsexml.js\"],\r\n      stylesheet: \"{\$g_root_url}/global/codemirror/css/xmlcolors.css\"\r\n    {elseif \$code_markup == \"CSS\"}\r\n      parserfile: [\"parsecss.js\"],\r\n      stylesheet: \"{\$g_root_url}/global/codemirror/css/csscolors.css\"\r\n    {elseif \$code_markup == \"JavaScript\"}  \r\n      parserfile: [\"tokenizejavascript.js\", \"parsejavascript.js\"],\r\n      stylesheet: \"{\$g_root_url}/global/codemirror/css/jscolors.css\"\r\n    {/if}\r\n  {literal}});{/literal}\r\n  </script>\r\n{else}\r\n  {\$VALUE|strip_tags}\r\n{/if}\r\n', '<div class=\"editor\">\r\n  <textarea id=\"{\$NAME}_id\" name=\"{\$NAME}\">{\$VALUE}</textarea>\r\n</div>\r\n<script>\r\n  var code_mirror_{\$NAME} = new CodeMirror.fromTextArea(\"{\$NAME}_id\", \r\n  {literal}{{/literal}\r\n    height: \"{\$SIZE_PX}px\",\r\n    path:   \"{\$g_root_url}/global/codemirror/js/\",\r\n    {if \$code_markup == \"HTML\" || \$code_markup == \"XML\"}\r\n      parserfile: [\"parsexml.js\"],\r\n      stylesheet: \"{\$g_root_url}/global/codemirror/css/xmlcolors.css\"\r\n    {elseif \$code_markup == \"CSS\"}\r\n      parserfile: [\"parsecss.js\"],\r\n      stylesheet: \"{\$g_root_url}/global/codemirror/css/csscolors.css\"\r\n    {elseif \$code_markup == \"JavaScript\"}  \r\n      parserfile: [\"tokenizejavascript.js\", \"parsejavascript.js\"],\r\n      stylesheet: \"{\$g_root_url}/global/codemirror/css/jscolors.css\"\r\n    {/if}\r\n  {literal}});{/literal}\r\n</script>\r\n\r\n{if \$comments}\r\n  <div class=\"cf_field_comments\">{\$comments}</div>\r\n{/if}\r\n', '', '.cf_view_markup_field {\r\n  margin: 0px; \r\n}\r\n', '')");
        }
        if (!in_array("{$g_table_prefix}field_types", $existing_tables)) {
            $query = mysql_query("\r\n        CREATE TABLE {$g_table_prefix}list_groups (\r\n          group_id mediumint(8) unsigned NOT NULL auto_increment,\r\n          group_type varchar(50) NOT NULL,\r\n          group_name varchar(255) NOT NULL,\r\n          custom_data text NOT NULL,\r\n          list_order smallint(6) NOT NULL,\r\n          PRIMARY KEY  (group_id)\r\n        ) DEFAULT CHARSET=utf8\r\n      ");
            $standard_fields = ft_sanitize($LANG["phrase_standard_fields"]);
            $special_fields = ft_sanitize($LANG["phrase_special_fields"]);
            mysql_query("INSERT INTO {$g_table_prefix}list_groups (group_type, group_name, list_order) VALUES ('field_types', '{$standard_fields}', 1)");
            mysql_query("INSERT INTO {$g_table_prefix}list_groups (group_type, group_name, list_order) VALUES ('field_types', '{$special_fields}', 2)");
        }
        // this will automatically fail if the fields already exist
        @mysql_query("\r\n      ALTER TABLE {$g_table_prefix}modules\r\n      ADD is_premium ENUM('yes', 'no') NOT NULL DEFAULT 'no' AFTER is_enabled,\r\n      ADD module_key VARCHAR(15) NULL AFTER is_premium\r\n    ");
        @mysql_query("ALTER TABLE {$g_table_prefix}field_types ADD view_field_rendering_type ENUM('none', 'php', 'smarty') NOT NULL DEFAULT 'none' AFTER compatible_field_sizes");
        @mysql_query("ALTER TABLE {$g_table_prefix}field_types ADD view_field_php_function VARCHAR(255) NULL AFTER view_field_rendering_type");
        @mysql_query("ALTER TABLE {$g_table_prefix}field_types ADD view_field_php_function_source VARCHAR(255) NULL AFTER view_field_rendering_type");
        mysql_query("ALTER TABLE {$g_table_prefix}hooks RENAME {$g_table_prefix}hook_calls");
        mysql_query("ALTER TABLE {$g_table_prefix}hook_calls CHANGE core_function function_name VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL");
        // okay! At this point, we've created the new tables for the field types & can safely add the new file and tinyMCE field
        // types. In order to upgrade to 2.1.0, the user MUST have installed the WYSIWYG and file upload modules
        ft_update_module_list();
        // not installed? Return an error. Note: the above code will NOT be re-inser
        if (!ft_check_module_available("field_type_file")) {
            return array("upgraded" => true, "success" => false, "message" => "Sorry, the <b>File Upload module</b> isn't installed. In order to upgrade to 2.1.0 or later, you must upload that module to your /modules folder, then refresh this page.");
        }
        if (!ft_check_module_available("field_type_tinymce")) {
            return array("upgraded" => true, "success" => false, "message" => "Sorry, the <b>TinyMCE Field</b> module isn't installed. In order to upgrade to 2.1.0 or later, you must upload that module to your /modules folder, then refresh this page.");
        }
        // okay, now this is a balancing act. At this point in the upgrade, SOME of the database has been updated, but not
        // all. The thing is, in order to upgrade the DB to use the file and WYSIWYG fields (and port over their old values
        // to the new DB structure) we need to ensure those two modules are installed. The code at the top of this section
        // ensured that those two modules are in fact found in the folder, but now we need to install them as well
        $modules = ft_get_modules();
        foreach ($modules as $module_info) {
            $module_id = $module_info["module_id"];
            $is_installed = $module_info["is_installed"];
            if ($is_installed == "yes") {
                continue;
            }
            ft_install_module(array("install" => $module_id));
        }
        $query = @mysql_query("\r\n      CREATE TABLE {$g_table_prefix}new_view_submission_defaults (\r\n        view_id mediumint(9) NOT NULL,\r\n        field_id mediumint(9) NOT NULL,\r\n        default_value text NOT NULL,\r\n        list_order smallint(6) NOT NULL,\r\n        PRIMARY KEY  (view_id,field_id)\r\n      ) DEFAULT CHARSET=utf8\r\n    ");
        $query = @mysql_query("\r\n      CREATE TABLE {$g_table_prefix}view_columns (\r\n        view_id mediumint(9) NOT NULL,\r\n        field_id mediumint(9) NOT NULL,\r\n        list_order smallint(6) NOT NULL,\r\n        is_sortable enum('yes','no') NOT NULL,\r\n        auto_size enum('yes','no') NOT NULL default 'yes',\r\n        custom_width varchar(10) default NULL,\r\n        truncate enum('truncate','no_truncate') NOT NULL default 'truncate',\r\n        PRIMARY KEY  (view_id,field_id,list_order)\r\n      ) DEFAULT CHARSET=utf8\r\n    ");
        // changed Tables: simple changes that don't require any data manipulation
        mysql_query("ALTER TABLE {$g_table_prefix}accounts ADD last_logged_in DATETIME NULL AFTER account_status");
        mysql_query("ALTER TABLE {$g_table_prefix}accounts CHANGE username username VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL");
        mysql_query("ALTER TABLE {$g_table_prefix}accounts CHANGE password password VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL");
        mysql_query("ALTER TABLE {$g_table_prefix}menu_items ADD is_new_sort_group ENUM('yes','no') NOT NULL DEFAULT 'yes' AFTER is_submenu");
        mysql_query("ALTER TABLE {$g_table_prefix}field_options ADD is_new_sort_group ENUM('yes','no') NOT NULL DEFAULT 'yes'");
        mysql_query("ALTER TABLE {$g_table_prefix}field_options CHANGE field_group_id list_id MEDIUMINT(8) UNSIGNED NOT NULL");
        mysql_query("ALTER TABLE {$g_table_prefix}form_fields ADD is_new_sort_group ENUM('yes','no') NOT NULL DEFAULT 'yes' AFTER list_order");
        mysql_query("ALTER TABLE {$g_table_prefix}form_fields CHANGE field_size field_size VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT 'medium'");
        mysql_query("ALTER TABLE {$g_table_prefix}field_settings CHANGE setting_value setting_value MEDIUMTEXT CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT ''");
        mysql_query("ALTER TABLE {$g_table_prefix}view_fields ADD is_new_sort_group ENUM('yes','no') NOT NULL DEFAULT 'yes'");
        mysql_query("ALTER TABLE {$g_table_prefix}views ADD is_new_sort_group ENUM('yes','no') NOT NULL DEFAULT 'yes' AFTER view_order");
        mysql_query("ALTER TABLE {$g_table_prefix}views ADD group_id SMALLINT NULL AFTER is_new_sort_group");
        mysql_query("ALTER TABLE {$g_table_prefix}forms DROP default_view_id");
        mysql_query("ALTER TABLE {$g_table_prefix}forms ADD form_type ENUM('internal','external') NOT NULL DEFAULT 'external' AFTER form_id");
        mysql_query("ALTER TABLE {$g_table_prefix}forms ADD add_submission_button_label VARCHAR(255) NULL DEFAULT '{$LANG["word_add_rightarrow"]}'");
        mysql_query("ALTER TABLE {$g_table_prefix}forms CHANGE form_url form_url VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL");
        mysql_query("INSERT INTO {$g_table_prefix}settings (setting_name, setting_value, module) VALUES ('edit_submission_shared_resources_js', '\$(function() {\r\n  \$(\".fancybox\").fancybox();\r\n});\r\n', 'core')");
        mysql_query("INSERT INTO {$g_table_prefix}settings (setting_name, setting_value, module) VALUES ('edit_submission_shared_resources_css', '/* used in the \"Highlight\" setting for most field types */\r\n.cf_colour_red { \r\n  background-color: #990000;\r\n  color: white;\r\n}\r\n.cf_colour_orange {\r\n  background-color: orange; \r\n}\r\n.cf_colour_yellow {\r\n  background-color: yellow; \r\n}\r\n.cf_colour_green {\r\n  background-color: green;\r\n  color: white; \r\n}\r\n.cf_colour_blue {\r\n  background-color: #336699; \r\n  color: white; \r\n}\r\n\r\n/* field comments */\r\n.cf_field_comments {\r\n  font-style: italic;\r\n  color: #999999;\r\n  clear: both;\r\n}\r\n\r\n/* column layouts for radios & checkboxes */\r\n.cf_option_list_group_label {\r\n  font-weight: bold;  \r\n  clear: both;\r\n  margin-left: 4px;\r\n}\r\n.cf_option_list_2cols, .cf_option_list_3cols, .cf_option_list_4cols {\r\n  clear: both; \r\n}\r\n.cf_option_list_2cols .column { \r\n  width: 50%;\r\n  float: left; \r\n}\r\n.cf_option_list_3cols .column { \r\n  width: 33%;\r\n  float: left;\r\n}\r\n.cf_option_list_4cols .column { \r\n  width: 25%;\r\n  float: left;\r\n}\r\n\r\n/* Used for the date and time pickers */\r\n.cf_date_group img {\r\n  margin-bottom: -4px;\r\n  padding: 1px;\r\n}\r\n\r\n', 'core')");
        mysql_query("INSERT INTO {$g_table_prefix}settings (setting_name, setting_value, module) VALUES ('edit_submission_onload_resources', '<script src=\"{\$g_root_url}/global/codemirror/js/codemirror.js\"></script>|<script src=\"{\$g_root_url}/global/scripts/jquery-ui-timepicker-addon.js\"></script>|<script src=\"{\$g_root_url}/global/fancybox/jquery.fancybox-1.3.4.pack.js\"></script> |<link rel=\"stylesheet\" href=\"{\$g_root_url}/global/fancybox/jquery.fancybox-1.3.4.css\" type=\"text/css\" media=\"screen\" />', 'core')");
        $forms_page_default_message = ft_sanitize($LANG["text_client_welcome"]);
        mysql_query("INSERT INTO {$g_table_prefix}settings (setting_name, setting_value, module) VALUES ('forms_page_default_message', '{$forms_page_default_message}', 'core')");
        mysql_query("UPDATE {$g_table_prefix}settings SET setting_name = 'num_option_lists_per_page' WHERE setting_name = 'num_field_option_groups_per_page'");
        // Field Option Groups are now called Option Lists
        mysql_query("ALTER TABLE {$g_table_prefix}field_option_groups RENAME {$g_table_prefix}option_lists");
        mysql_query("ALTER TABLE {$g_table_prefix}option_lists CHANGE group_id list_id MEDIUMINT(8) UNSIGNED NOT NULL AUTO_INCREMENT");
        mysql_query("ALTER TABLE {$g_table_prefix}option_lists CHANGE group_name option_list_name VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL");
        mysql_query("ALTER TABLE {$g_table_prefix}option_lists ADD is_grouped ENUM('yes', 'no') NOT NULL DEFAULT 'no' AFTER option_list_name");
        // may not be necessary, but just to make sure
        mysql_query("\r\n      ALTER TABLE {$g_table_prefix}view_filters\r\n      CHANGE operator operator ENUM('equals', 'not_equals', 'like', 'not_like', 'before', 'after')\r\n      CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'equals'\r\n    ");
        // not used anymore! Dependency tracking is entirely handled by formtools.org
        mysql_query("ALTER TABLE {$g_table_prefix}themes DROP supports_ft_versions");
        mysql_query("ALTER TABLE {$g_table_prefix}modules DROP supports_ft_versions");
        // next, we need up update menus to change field_option_groups to option_lists. Since the user may have tweaked the
        // menu label to say whatever they want, only update the actual label if it was the original English "Field Option Groups"
        $menu_items_query = mysql_query("\r\n      SELECT *\r\n      FROM   {$g_table_prefix}menu_items\r\n      WHERE  page_identifier = 'field_option_groups'\r\n        ");
        while ($row = mysql_fetch_assoc($menu_items_query)) {
            $menu_item_id = $row["menu_item_id"];
            $display_text_clause = "";
            if ($row["display_text"] == "Field Option Groups") {
                $display_text = ft_sanitize($LANG["phrase_option_lists"]);
                $display_text_clause = ", display_text = '{$display_text}'";
            }
            mysql_query("\r\n        UPDATE {$g_table_prefix}menu_items\r\n        SET    page_identifier = 'option_lists',\r\n               url = '/admin/forms/option_lists/'\r\n               {$display_text_clause}\r\n        WHERE  menu_item_id = {$menu_item_id}\r\n      ");
        }
        mysql_query("DELETE FROM {$g_table_prefix}menu_items WHERE page_identifier = 'settings_wysiwyg'");
        mysql_query("\r\n      UPDATE {$g_table_prefix}menu_items\r\n      SET    page_identifier = 'add_form_choose_type',\r\n             url = '/admin/forms/add/'\r\n      WHERE  page_identifier = 'add_form1'\r\n    ");
        // all Views are now grouped. Add in a default group for each
        $forms_query = mysql_query("SELECT form_id FROM {$g_table_prefix}forms WHERE is_complete = 'yes'");
        $views_label = ft_sanitize($LANG["word_views"]);
        while ($row = mysql_fetch_assoc($forms_query)) {
            $form_id = $row["form_id"];
            mysql_query("\r\n        INSERT INTO {$g_table_prefix}list_groups (group_type, group_name, custom_data, list_order)\r\n        VALUES ('form_{$form_id}_view_group', '{$views_label}', '', 1)\r\n      ");
            $new_group_id = mysql_insert_id();
            mysql_query("\r\n        UPDATE {$g_table_prefix}views\r\n        SET    group_id = {$new_group_id}\r\n        WHERE  form_id = {$form_id}\r\n      ");
        }
        // the field options table now groups the options. What we need to do here is create a group for all items in each
        // Option List
        mysql_query("ALTER TABLE {$g_table_prefix}field_options ADD list_group_id MEDIUMINT NOT NULL AFTER list_id");
        $field_options = mysql_query("SELECT DISTINCT list_id FROM {$g_table_prefix}field_options");
        while ($row = mysql_fetch_assoc($field_options)) {
            $list_id = $row["list_id"];
            mysql_query("\r\n        INSERT INTO {$g_table_prefix}list_groups (group_type, group_name, custom_data, list_order)\r\n        VALUES ('option_list_{$list_id}', '', '', 1)\r\n      ");
            $new_group_id = mysql_insert_id();
            mysql_query("UPDATE {$g_table_prefix}field_options SET list_group_id = {$new_group_id} WHERE list_id = {$list_id}");
        }
        // field types are now field type IDs. This has significant impact.
        $forms = ft_get_forms();
        $form_changes = array();
        $date_system_field_ids = array();
        $fields_with_option_lists = array();
        foreach ($forms as $form_info) {
            $form_id = $form_info["form_id"];
            $fields = ft_get_form_fields($form_id);
            $field_types = array();
            // stores field IDs grouped by field type (key == old field type name string)
            $field_col_to_id_map = array();
            $field_id_to_option_list_id = array();
            foreach ($fields as $field_info) {
                $field_id = $field_info["field_id"];
                if (!array_key_exists($field_info["field_type"], $field_types)) {
                    $field_types[$field_info["field_type"]] = array();
                }
                if ($field_info["field_type"] == "system" && ($field_info["col_name"] == "last_modified_date" || $field_info["col_name"] == "submission_date")) {
                    $date_system_field_ids[] = $field_id;
                }
                $field_types[$field_info["field_type"]][] = $field_id;
                $field_col_to_id_map[$field_info["col_name"]] = $field_id;
                if (!empty($field_info["field_group_id"])) {
                    $field_id_to_option_list_id[$field_info["field_id"]] = $field_info["field_group_id"];
                }
            }
            $form_changes[$form_id] = array("field_types" => $field_types, "field_col_to_id_map" => $field_col_to_id_map, "fields_with_option_lists" => $field_id_to_option_list_id);
        }
        // update the core field names for all forms
        foreach ($forms as $form_info) {
            $form_id = $form_info["form_id"];
            if ($form_info["is_complete"] == "no") {
                continue;
            }
            mysql_query("\r\n        UPDATE {$g_table_prefix}form_fields\r\n        SET    field_name = 'core__submission_id'\r\n        WHERE  col_name = 'submission_id' AND\r\n               field_type = 'system'\r\n      ");
            mysql_query("\r\n        UPDATE {$g_table_prefix}form_fields\r\n        SET    field_name = 'core__last_modified'\r\n        WHERE  col_name = 'last_modified_date' AND\r\n               field_type = 'system'\r\n      ");
            mysql_query("\r\n        UPDATE {$g_table_prefix}form_fields\r\n        SET    field_name = 'core__submission_date'\r\n        WHERE  col_name = 'submission_date' AND\r\n               field_type = 'system'\r\n      ");
            mysql_query("\r\n        UPDATE {$g_table_prefix}form_fields\r\n        SET    field_name = 'core__ip_address'\r\n        WHERE  col_name = 'ip_address' AND\r\n               field_type = 'system'\r\n       ");
        }
        mysql_query("ALTER TABLE {$g_table_prefix}form_fields CHANGE field_type field_type_id SMALLINT NOT NULL DEFAULT '1'");
        mysql_query("ALTER TABLE {$g_table_prefix}form_fields ADD is_system_field ENUM('yes','no') NOT NULL DEFAULT 'no' AFTER field_type_id");
        $field_types = ft_get_field_types();
        $field_type_map = array();
        foreach ($field_types as $row) {
            $field_type_map[$row["field_type_identifier"]] = $row["field_type_id"];
        }
        // existing ENUM key => new field type identifier
        $textbox_field_type_id = ft_get_field_type_id_by_identifier("textbox");
        $date_field_type_id = ft_get_field_type_id_by_identifier("date");
        $map = array("textbox" => $field_type_map["textbox"], "textarea" => $field_type_map["textarea"], "password" => $field_type_map["password"], "select" => $field_type_map["dropdown"], "multi-select" => $field_type_map["multi_select_dropdown"], "radio-buttons" => $field_type_map["radio_buttons"], "checkboxes" => $field_type_map["checkboxes"], "date" => $field_type_map["date"], "file" => $field_type_map["file"], "wysiwyg" => $field_type_map["tinymce"], "system" => $textbox_field_type_id);
        while (list($form_id, $changes) = each($form_changes)) {
            while (list($field_label, $field_ids) = each($changes["field_types"])) {
                foreach ($field_ids as $field_id) {
                    $field_type_id = $map[$field_label];
                    if (in_array($field_id, $date_system_field_ids)) {
                        $field_type_id = $date_field_type_id;
                    }
                    $is_system_field = $field_label == "system" ? "yes" : "no";
                    mysql_query("\r\n            UPDATE {$g_table_prefix}form_fields\r\n            SET    field_type_id = {$field_type_id},\r\n                   is_system_field = '{$is_system_field}'\r\n            WHERE  field_id = {$field_id}\r\n          ");
                }
            }
        }
        reset($form_changes);
        // next, the form_email_fields table now uses IDs instead of col names. Update it!
        $email_updates = array();
        foreach ($forms as $form_info) {
            $form_id = $form_info["form_id"];
            $email_field_query = mysql_query("\r\n        SELECT *\r\n        FROM   {$g_table_prefix}form_email_fields\r\n        WHERE  form_id = {$form_id}\r\n      ");
            $email_fields = array();
            while ($field_info = mysql_fetch_assoc($email_field_query)) {
                $email_fields[] = array("form_email_id" => $field_info["form_email_id"], "email_field_id" => array_key_exists($field_info["email_field"], $form_changes[$form_id]["field_col_to_id_map"]) ? $form_changes[$form_id]["field_col_to_id_map"][$field_info["email_field"]] : "", "first_name_field_id" => array_key_exists($field_info["first_name_field"], $form_changes[$form_id]["field_col_to_id_map"]) ? $form_changes[$form_id]["field_col_to_id_map"][$field_info["first_name_field"]] : "NULL", "last_name_field_id" => array_key_exists($field_info["last_name_field"], $form_changes[$form_id]["field_col_to_id_map"]) ? $form_changes[$form_id]["field_col_to_id_map"][$field_info["last_name_field"]] : "NULL");
            }
            $email_updates[$form_id] = $email_fields;
        }
        mysql_query("ALTER TABLE {$g_table_prefix}form_email_fields CHANGE email_field email_field_id MEDIUMINT(9) NOT NULL");
        mysql_query("ALTER TABLE {$g_table_prefix}form_email_fields CHANGE first_name_field first_name_field_id MEDIUMINT(9) NULL DEFAULT NULL");
        mysql_query("ALTER TABLE {$g_table_prefix}form_email_fields CHANGE last_name_field last_name_field_id MEDIUMINT(9) NULL DEFAULT NULL");
        while (list($form_id, $changes) = each($email_updates)) {
            foreach ($changes as $email_change_info) {
                $form_email_id = $email_change_info["form_email_id"];
                $email_field_id = $email_change_info["email_field_id"];
                if (empty($email_field_id) || !is_numeric($email_field_id)) {
                    continue;
                }
                $first_name_field_id = !empty($email_change_info["first_name_field_id"]) ? "'{$email_change_info["first_name_field_id"]}'" : "NULL";
                $last_name_field_id = !empty($email_change_info["last_name_field_id"]) ? "'{$email_change_info["last_name_field_id"]}'" : "NULL";
                mysql_query("\r\n          UPDATE {$g_table_prefix}form_email_fields\r\n          SET    email_field_id      = {$email_field_id},\r\n                 first_name_field_id = {$first_name_field_id},\r\n                 last_name_field_id  = {$last_name_field_id}\r\n          WHERE  form_email_id = {$form_email_id}\r\n        ");
            }
        }
        // now update the View fields table. The is_column and is_sortable info is now stored in the view_columns table
        $view_cols = array();
        foreach ($forms as $form_info) {
            $form_id = $form_info["form_id"];
            $view_query = mysql_query("SELECT view_id FROM {$g_table_prefix}views WHERE form_id = {$form_id}");
            $view_ids = array();
            while ($view_info = mysql_fetch_assoc($view_query)) {
                $view_ids[] = $view_info["view_id"];
            }
            foreach ($view_ids as $view_id) {
                // we can't use ft_get_view_fields here because the Core code references DB changes
                // that can't be made yet
                $view_fields_query = mysql_query("\r\n          SELECT field_id, tab_number, is_column, is_sortable\r\n          FROM   {$g_table_prefix}view_fields\r\n          WHERE  view_id = {$view_id}\r\n        ");
                while ($view_field_info = mysql_fetch_assoc($view_fields_query)) {
                    $field_id = $view_field_info["field_id"];
                    $tab_number = $view_field_info["tab_number"];
                    $is_column = $view_field_info["is_column"];
                    $is_sortable = $view_field_info["is_sortable"];
                    if ($is_column != "yes") {
                        continue;
                    }
                    $view_cols[$view_id][] = array("field_id" => $field_id, "is_sortable" => $is_sortable);
                }
            }
        }
        // now insert the view_columns records
        while (list($view_id, $info) = each($view_cols)) {
            $order = 1;
            foreach ($info as $col_info) {
                $field_id = $col_info["field_id"];
                $is_sortable = $col_info["is_sortable"];
                mysql_query("\r\n          INSERT INTO {$g_table_prefix}view_columns (view_id, field_id, list_order, is_sortable, auto_size, custom_width, truncate)\r\n          VALUES ({$view_id}, {$field_id}, {$order}, 'yes', 'yes', '', 'truncate')\r\n        ");
                $order++;
            }
        }
        mysql_query("ALTER TABLE {$g_table_prefix}view_fields DROP is_column, DROP is_sortable");
        mysql_query("ALTER TABLE {$g_table_prefix}view_fields ADD group_id MEDIUMINT(9) NOT NULL AFTER field_id");
        // all View fields are now grouped. Formerly, view fields could be mapped to tabs individually, now they're mapped
        // to the View field group. So what we do here is: look at each View, and those fields within it.
        $forms_query = mysql_query("SELECT form_id FROM {$g_table_prefix}forms WHERE is_complete = 'yes'");
        while ($row = mysql_fetch_assoc($forms_query)) {
            $form_id = $row["form_id"];
            $views_query = mysql_query("SELECT view_id FROM {$g_table_prefix}views WHERE form_id = {$form_id}");
            while ($view_info = mysql_fetch_assoc($views_query)) {
                $view_id = $view_info["view_id"];
                $tab_num_query = mysql_query("\r\n          SELECT DISTINCT tab_number\r\n          FROM   {$g_table_prefix}view_fields\r\n          WHERE  view_id = {$view_id} AND\r\n                 tab_number IS NOT NULL\r\n        ");
                $tab_numbers = array();
                while ($tab_row = mysql_fetch_assoc($tab_num_query)) {
                    $tab_numbers[] = $tab_row["tab_number"];
                }
                // if none of the fields were mapped to a tab, cool! Just map all View fields to a single list group
                if (empty($tab_numbers)) {
                    mysql_query("\r\n            INSERT INTO {$g_table_prefix}list_groups (group_type, group_name, custom_data, list_order)\r\n            VALUES ('view_fields_{$view_id}', '', '', 1)\r\n          ");
                    $new_group_id = mysql_insert_id();
                    mysql_query("\r\n            UPDATE {$g_table_prefix}view_fields\r\n            SET    group_id = {$new_group_id}\r\n            WHERE  view_id = {$view_id}\r\n          ");
                } else {
                    $order = 1;
                    foreach ($tab_numbers as $tab_number) {
                        mysql_query("\r\n              INSERT INTO {$g_table_prefix}list_groups (group_type, group_name, custom_data, list_order)\r\n              VALUES ('view_fields_{$view_id}', '', '{$tab_number}', {$order})\r\n            ");
                        $new_group_id = mysql_insert_id();
                        $order++;
                        mysql_query("\r\n              UPDATE {$g_table_prefix}view_fields\r\n              SET    group_id = {$new_group_id}\r\n              WHERE  view_id = {$view_id} AND\r\n                     tab_number = {$tab_number}\r\n            ");
                    }
                }
            }
        }
        mysql_query("ALTER TABLE {$g_table_prefix}view_fields DROP tab_number");
        // FIELD_SETTINGS table  -----------------
        $old_field_settings = array();
        $field_settings_query = mysql_query("SELECT * FROM {$g_table_prefix}field_settings");
        while ($row = mysql_fetch_assoc($field_settings_query)) {
            $old_field_settings[] = $row;
        }
        mysql_query("TRUNCATE {$g_table_prefix}field_settings");
        mysql_query("ALTER TABLE {$g_table_prefix}field_settings DROP module");
        // this field wasn't ever used
        mysql_query("ALTER TABLE {$g_table_prefix}field_settings CHANGE setting_name setting_id MEDIUMINT NOT NULL");
        $file_field_type_id = ft_get_field_type_id_by_identifier("file");
        $field_setting_name_to_id_map = array("file_upload_dir" => ft_get_field_type_setting_by_identifier($file_field_type_id, "folder_path"), "file_upload_url" => ft_get_field_type_setting_by_identifier($file_field_type_id, "folder_url"), "file_upload_filetypes" => ft_get_field_type_setting_by_identifier($file_field_type_id, "permitted_file_types"), "file_upload_max_size" => ft_get_field_type_setting_by_identifier($file_field_type_id, "max_file_size"));
        foreach ($old_field_settings as $info) {
            $field_id = $info["field_id"];
            $setting_id = array_key_exists($info["setting_name"], $field_setting_name_to_id_map) ? $field_setting_name_to_id_map[$info["setting_name"]] : "";
            $setting_value = $info["setting_value"];
            // this shouldn't happen. The field_settings table was exceedingly underutilized & only ever contained settings with
            // those 4 names specified above
            if (empty($setting_id)) {
                continue;
            }
            mysql_query("INSERT INTO {$g_table_prefix}field_settings (field_id, setting_id, setting_value) VALUES ({$field_id}, {$setting_id}, '{$setting_value}')");
        }
        // now the field_settings table is up to date, a few Core fields need new entries in the table
        $query = mysql_query("\r\n      SELECT field_id\r\n      FROM   {$g_table_prefix}form_fields\r\n      WHERE  is_system_field = 'yes' AND\r\n             (field_name = 'core__submission_date' OR field_name = 'core__last_modified')\r\n    ");
        $date_field_type_datetime_setting_id = ft_get_field_type_setting_id_by_identifier($date_field_type_id, "display_format");
        while ($row = mysql_fetch_assoc($query)) {
            $field_id = $row["field_id"];
            mysql_query("\r\n        INSERT INTO {$g_table_prefix}field_settings (field_id, setting_id, setting_value)\r\n        VALUES ({$field_id}, {$date_field_type_datetime_setting_id}, '{$g_default_datetime_format}')\r\n      ");
        }
        // next we need to update the mappings for any fields that use an Option List. Before, that info was stored in the
        // field_group_id field in the form_fields table; now it's associated with a setting for the field type. First, create
        // a map of field_type_id => field_setting_id, where the setting ID is the one that contains the Option List
        $field_type_option_list_setting_id_map = array();
        foreach ($field_types as $row) {
            $field_type_id = $row["field_type_id"];
            $field_setting_info = ft_get_field_type_setting_by_identifier($field_type_id, "contents");
            if (!empty($field_setting_info)) {
                $field_type_option_list_setting_id_map[$field_type_id] = $field_setting_info["setting_id"];
            }
        }
        // next, loop through each field that has an old field_option_group field and add the new field_setting
        $query = mysql_query("\r\n      SELECT field_id, field_type_id, field_group_id\r\n      FROM   {$g_table_prefix}form_fields\r\n      WHERE  field_group_id IS NOT NULL AND field_group_id != ''\r\n    ");
        // this stores those field IDs that are mapped to each option list ID
        $option_list_id_to_field_ids = array();
        while ($row = mysql_fetch_assoc($query)) {
            $field_id = $row["field_id"];
            $field_type_id = $row["field_type_id"];
            $field_group_id = $row["field_group_id"];
            $setting_id = array_key_exists($field_type_id, $field_type_option_list_setting_id_map) ? $field_type_option_list_setting_id_map[$field_type_id] : "";
            mysql_query("\r\n        INSERT INTO {$g_table_prefix}field_settings (field_id, setting_id, setting_value)\r\n        VALUES ({$field_id}, {$setting_id}, {$field_group_id})\r\n      ");
            if (!array_key_exists($field_group_id, $option_list_id_to_field_ids)) {
                $option_list_id_to_field_ids[$field_group_id] = array();
            }
            $option_list_id_to_field_ids[$field_group_id][] = $field_id;
        }
        mysql_query("ALTER TABLE {$g_table_prefix}form_fields DROP field_group_id");
        // for this one, we need to locate every field that uses the Option List and add a custom setting to ensure the
        // orientation isn't lost. At this juncture, we have the luxury of knowing that the default field type settings &
        // options haven't been modified by the user
        $orientation_query = mysql_query("\r\n      SELECT list_id, field_orientation\r\n      FROM   {$g_table_prefix}option_lists\r\n      WHERE  field_orientation = 'vertical' OR field_orientation = 'horizontal'\r\n    ");
        while ($row = mysql_fetch_assoc($orientation_query)) {
            $curr_option_list_id = $row["list_id"];
            $orientation = $row["field_orientation"];
            if (!array_key_exists($curr_option_list_id, $option_list_id_to_field_ids)) {
                continue;
            }
            // the assumption here is that the multi-select field types have an orientation setting with
            // values "horizontal" and "vertical". It's safe.
            foreach ($option_list_id_to_field_ids[$curr_option_list_id] as $field_id) {
                // slow and crappy!
                $field_type_id = ft_get_field_type_id_by_field_id($field_id);
                $setting_id = ft_get_field_type_setting_id_by_identifier($field_type_id, "formatting");
                // for checkbox & radios fields that were assigned to an option list with a "n/a" orientation, don't
                // worry about it: they'll inherit the default value
                if (empty($setting_id)) {
                    continue;
                }
                mysql_query("\r\n          INSERT INTO {$g_table_prefix}field_settings (field_id, setting_id, setting_value)\r\n          VALUES ({$field_id}, {$setting_id}, '{$orientation}')\r\n        ");
            }
        }
        mysql_query("ALTER TABLE {$g_table_prefix}option_lists DROP field_orientation");
    }
    if ($old_version_info["release_date"] < 20110521) {
        mysql_query("\r\n      UPDATE {$g_table_prefix}field_types\r\n      SET    view_field_smarty_markup = '{\$VALUE|htmlspecialchars}'\r\n      WHERE  field_type_identifier = 'textbox'\r\n    ");
        mysql_query("\r\n      UPDATE {$g_table_prefix}field_types\r\n      SET    view_field_smarty_markup = '{if \$CONTEXTPAGE == \"edit_submission\"}\t\n  {\$VALUE|nl2br}\r\n{else}\r\n  {\$VALUE}\r\n{/if}'\r\n      WHERE  field_type_identifier = 'textarea'\r\n    ");
    }
    if ($old_version_info["release_date"] < 20110527) {
        mysql_query("\r\n      UPDATE {$g_table_prefix}field_types\r\n      SET    raw_field_type_map_multi_select_id = 16\r\n      WHERE  field_type_identifier = 'radio_buttons'\r\n    ");
        mysql_query("\r\n      CREATE TABLE {$g_table_prefix}hooks (\r\n        id mediumint(8) unsigned NOT NULL auto_increment,\r\n        hook_type enum('code','template') NOT NULL,\r\n        component enum('core','api','module') NOT NULL,\r\n        filepath varchar(255) NOT NULL,\r\n        action_location varchar(255) NOT NULL,\r\n        function_name varchar(255) NOT NULL,\r\n        params mediumtext,\r\n        overridable mediumtext,\r\n        PRIMARY KEY (id)\r\n      )");
    }
    if ($old_version_info["release_date"] < 20110528) {
        // assorted updates to the Date field type
        mysql_query("\r\n      INSERT INTO {$g_table_prefix}field_type_settings (field_type_id, field_label, field_setting_identifier, field_type,\r\n        field_orientation, default_value_type, default_value, list_order)\r\n      VALUES (8, 'Apply Timezone Offset', 'apply_timezone_offset', 'radios', 'horizontal', 'static', 'no', 2)\r\n    ");
        $new_setting_id = mysql_insert_id();
        mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES ({$new_setting_id}, 'Yes', 'yes', 1, 'yes')");
        mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES ({$new_setting_id}, 'No', 'no', 2, 'yes')");
        mysql_query("\r\n     UPDATE {$g_table_prefix}field_type_settings\r\n     SET    list_order = 3\r\n     WHERE  field_type_id = 8 AND\r\n            field_setting_identifier = 'comments'\r\n    ");
        mysql_query("\r\n      UPDATE {$g_table_prefix}field_types\r\n      SET    view_field_smarty_markup = '{strip}\r\n  {if \$VALUE}\r\n    {assign var=tzo value=\"\"}\r\n    {if \$apply_timezone_offset == \"yes\"}\r\n      {assign var=tzo value=\$ACCOUNT_INFO.timezone_offset}\r\n    {/if}\r\n    {if \$display_format == \"yy-mm-dd\" || !\$display_format}\r\n      {\$VALUE|custom_format_date:\$tzo:\"Y-m-d\"}\r\n    {elseif \$display_format == \"dd/mm/yy\"}\r\n      {\$VALUE|custom_format_date:\$tzo:\"d/m/Y\"}\r\n    {elseif \$display_format == \"mm/dd/yy\"}\r\n      {\$VALUE|custom_format_date:\$tzo:\"m/d/Y\"}\r\n    {elseif \$display_format == \"M d, yy\"}\r\n      {\$VALUE|custom_format_date:\$tzo:\"M j, Y\"}\r\n    {elseif \$display_format == \"MM d, yy\"}\r\n      {\$VALUE|custom_format_date:\$tzo:\"F j, Y\"}\r\n    {elseif \$display_format == \"D M d, yy\"}\r\n      {\$VALUE|custom_format_date:\$tzo:\"D M j, Y\"}\r\n    {elseif \$display_format == \"DD, MM d, yy\"}\r\n      {\$VALUE|custom_format_date:\$tzo:\"l M j, Y\"}\r\n    {elseif \$display_format == \"datetime:dd/mm/yy|h:mm TT|ampm`true\"}\r\n      {\$VALUE|custom_format_date:\$tzo:\"d/m/Y g:i A\"}\r\n    {elseif \$display_format == \"datetime:mm/dd/yy|h:mm TT|ampm`true\"}\r\n      {\$VALUE|custom_format_date:\$tzo:\"m/d/Y g:i A\"}\r\n    {elseif \$display_format == \"datetime:yy-mm-dd|h:mm TT|ampm`true\"}\r\n      {\$VALUE|custom_format_date:\$tzo:\"Y-m-d g:i A\"}\r\n    {elseif \$display_format == \"datetime:yy-mm-dd|hh:mm\"}\r\n      {\$VALUE|custom_format_date:\$tzo:\"Y-m-d H:i\"}\r\n    {elseif \$display_format == \"datetime:yy-mm-dd|hh:mm:ss|showSecond`true\"}\r\n      {\$VALUE|custom_format_date:\$tzo:\"Y-m-d H:i:s\"}\r\n    {/if}\r\n{/if}{/strip}\r\n',\r\n             edit_field_smarty_markup = '{assign var=class value=\"cf_datepicker\"}\r\n{if \$display_format|strpos:\"datetime\" === 0}\r\n  {assign var=class value=\"cf_datetimepicker\"}\r\n{/if}\r\n\r\n{assign var=\"val\" value=\"\"}\r\n{if \$VALUE}\r\n  {assign var=tzo value=\"\"}\r\n  {if \$apply_timezone_offset == \"yes\"}\r\n    {assign var=tzo value=\$ACCOUNT_INFO.timezone_offset}\r\n  {/if}\r\n  {if \$display_format == \"yy-mm-dd\"}\r\n    {assign var=val value=\$VALUE|custom_format_date:\$tzo:\"Y-m-d\"}\r\n  {elseif \$display_format == \"dd/mm/yy\"}\r\n    {assign var=val value=\$VALUE|custom_format_date:\$tzo:\"d/m/Y\"}\r\n  {elseif \$display_format == \"mm/dd/yy\"}\r\n    {assign var=val value=\$VALUE|custom_format_date:\$tzo:\"m/d/Y\"}\r\n  {elseif \$display_format == \"M d, yy\"}\r\n    {assign var=val value=\$VALUE|custom_format_date:\$tzo:\"M j, Y\"}\r\n  {elseif \$display_format == \"MM d, yy\"}\r\n    {assign var=val value=\$VALUE|custom_format_date:\$tzo:\"F j, Y\"}\r\n  {elseif \$display_format == \"D M d, yy\"}\r\n    {assign var=val value=\$VALUE|custom_format_date:\$tzo:\"D M j, Y\"}\r\n  {elseif \$display_format == \"DD, MM d, yy\"}\r\n    {assign var=val value=\$VALUE|custom_format_date:\$tzo:\"l M j, Y\"}\r\n  {elseif \$display_format == \"datetime:dd/mm/yy|h:mm TT|ampm`true\"}\r\n    {assign var=val value=\$VALUE|custom_format_date:\$tzo:\"d/m/Y g:i A\"}\r\n  {elseif \$display_format == \"datetime:mm/dd/yy|h:mm TT|ampm`true\"}\r\n    {assign var=val value=\$VALUE|custom_format_date:\$tzo:\"m/d/Y g:i A\"}\r\n  {elseif \$display_format == \"datetime:yy-mm-dd|h:mm TT|ampm`true\"}\r\n    {assign var=val value=\$VALUE|custom_format_date:\$tzo:\"Y-m-d g:i A\"}\r\n  {elseif \$display_format == \"datetime:yy-mm-dd|hh:mm\"}\r\n    {assign var=val value=\$VALUE|custom_format_date:\$tzo:\"Y-m-d H:i\"}\r\n  {elseif \$display_format == \"datetime:yy-mm-dd|hh:mm:ss|showSecond`true\"}\r\n    {assign var=val value=\$VALUE|custom_format_date:\$tzo:\"Y-m-d H:i:s\"}\r\n  {/if}\r\n{/if}\r\n\r\n<div class=\"cf_date_group\">\r\n  <input type=\"input\" name=\"{\$NAME}\" id=\"{\$NAME}_id\" \r\n    class=\"cf_datefield {\$class}\" value=\"{\$val}\" /><img class=\"ui-datepicker-trigger\" src=\"{\$g_root_url}/global/images/calendar.png\" id=\"{\$NAME}_icon_id\" />\r\n  <input type=\"hidden\" id=\"{\$NAME}_format\" value=\"{\$display_format}\" />\r\n  {if \$comments}\r\n    <div class=\"cf_field_comments\">{\$comments}</div>\r\n  {/if}\r\n</div>\r\n',\r\n             php_processing = '\$field_name     = \$vars[\"field_info\"][\"field_name\"];\r\n\$date           = \$vars[\"data\"][\$field_name];\r\n\$display_format = \$vars[\"settings\"][\"display_format\"];\r\n\$atzo           = \$vars[\"settings\"][\"apply_timezone_offset\"];\r\n\$account_info   = isset(\$vars[\"account_info\"]) ? \$vars[\"account_info\"] : array();\r\n\r\nif (empty(\$date))\r\n{\r\n  \$value = \"\";\r\n}\r\nelse\r\n{\r\n  if (strpos(\$display_format, \"datetime:\") === 0)\r\n  {\r\n    \$parts = explode(\" \", \$date);\r\n    switch (\$display_format)\r\n    {\r\n      case \"datetime:dd/mm/yy|h:mm TT|ampm`true\":\r\n        \$date = substr(\$date, 3, 2) . \"/\" . substr(\$date, 0, 2) . \"/\" . \r\n          substr(\$date, 6);        \r\n        break;\r\n    }\r\n  }\r\n  else\r\n  {\r\n    if (\$display_format == \"dd/mm/yy\")\r\n    {\r\n      \$date = substr(\$date, 3, 2) . \"/\" . substr(\$date, 0, 2) . \"/\" . \r\n        substr(\$date, 6);\r\n    }\r\n  }\r\n  \$time = strtotime(\$date);\r\n  \r\n  // lastly, if this field has a timezone offset being applied to it, do the\r\n  // appropriate math on the date\r\n  if (\$atzo == \"yes\" && !isset(\$account_info[\"timezone_offset\"]))\r\n  {\r\n    \$seconds_offset = \$account_info[\"timezone_offset\"] * 60 * 60;\r\n    \$time += \$seconds_offset;\r\n  }\r\n\r\n  \$value = date(\"Y-m-d H:i:s\", \$time);\r\n}\r\n\r\n\r\n'\r\n      WHERE  field_type_id = 8\r\n    ");
    }
    if ($old_version_info["release_date"] < 20110530) {
        mysql_query("INSERT INTO {$g_table_prefix}settings (setting_name, setting_value) VALUES ('default_date_field_search_value', 'none')");
    }
    if ($old_version_info["release_date"] < 20110612) {
        @mysql_query("ALTER TABLE {$g_table_prefix}accounts ADD temp_reset_password VARCHAR(50) NULL");
    }
    if ($old_version_info["release_date"] < 20110622) {
        @mysql_query("UPDATE {$g_table_prefix}field_types SET view_field_php_function_source = 'core'");
        // for compatibility with existing field type modules
        mysql_query("\r\n      UPDATE {$g_table_prefix}field_types\r\n      SET     view_field_rendering_type = 'smarty'\r\n    ");
        // textbox
        mysql_query("\r\n      UPDATE {$g_table_prefix}field_types\r\n      SET    view_field_rendering_type = 'smarty',\r\n             view_field_php_function_source = 'core',\r\n             view_field_php_function = ''\r\n      WHERE  field_type_identifier = 'textbox'\r\n    ");
        // textarea
        mysql_query("\r\n      UPDATE {$g_table_prefix}field_types\r\n      SET    view_field_rendering_type = 'smarty',\r\n             view_field_php_function_source = 'core',\r\n             view_field_php_function = '',\r\n             view_field_smarty_markup = '{if \$CONTEXTPAGE == \"edit_submission\"}  \r\n  {\$VALUE|nl2br}\r\n{else}\r\n  {\$VALUE}\r\n{/if}',\r\n             edit_field_smarty_markup = '{* figure out all the classes *}\r\n{assign var=classes value=\$height}\r\n{if \$highlight_colour}\r\n  {assign var=classes value=\"`\$classes` `\$highlight_colour`\"}\r\n{/if}\r\n{if \$input_length == \"words\" && \$maxlength != \"\"}\r\n  {assign var=classes value=\"`\$classes` cf_wordcounter max`\$maxlength`\"}\r\n{else if \$input_length == \"chars\" && \$maxlength != \"\"}\r\n  {assign var=classes value=\"`\$classes` cf_textcounter max`\$maxlength`\"}\r\n{/if}\r\n\r\n<textarea name=\"{\$NAME}\" id=\"{\$NAME}_id\" class=\"{\$classes}\">{\$VALUE}</textarea>\r\n\r\n{if \$input_length == \"words\" && \$maxlength != \"\"}\r\n  <div class=\"cf_counter\" id=\"{\$NAME}_counter\">\r\n    {\$maxlength} {\$LANG.phrase_word_limit_p} <span></span> {\$LANG.phrase_remaining_words}\r\n  </div>\r\n{elseif \$input_length == \"chars\" && \$max_length != \"\"}\r\n  <div class=\"cf_counter\" id=\"{\$NAME}_counter\">\r\n    {\$maxlength} {\$LANG.phrase_characters_limit_p} <span></span> {\$LANG.phrase_remaining_characters}\r\n  </div>\r\n{/if}\r\n\r\n{if \$comments}\r\n  <div class=\"cf_field_comments\">{\$comments|nl2br}</div>\r\n{/if}'\r\n      WHERE  field_type_identifier = 'textarea'\r\n    ");
        // password
        mysql_query("\r\n      UPDATE {$g_table_prefix}field_types\r\n      SET     view_field_rendering_type = 'none'\r\n      WHERE   field_type_identifier = 'password'\r\n    ");
        // dropdown
        mysql_query("\r\n      UPDATE {$g_table_prefix}field_types\r\n      SET    view_field_rendering_type = 'php',\r\n             view_field_php_function_source = 'core',\r\n             view_field_php_function = 'ft_display_field_type_dropdown',\r\n             view_field_smarty_markup = '{strip}{if \$contents != \"\"}\r\n  {foreach from=\$contents.options item=curr_group_info name=group}\r\n    {assign var=options value=\$curr_group_info.options}\r\n    {foreach from=\$options item=option name=row}\r\n      {if \$VALUE == \$option.option_value}{\$option.option_name}{/if}\r\n    {/foreach}\r\n  {/foreach}\r\n{/if}{/strip}',\r\n             edit_field_smarty_markup = '{if \$contents == \"\"}\r\n  <div class=\"cf_field_comments\">{\$LANG.phrase_not_assigned_to_option_list}</div>\r\n{else}\r\n  <select name=\"{\$NAME}\">\r\n  {foreach from=\$contents.options item=curr_group_info name=group}\r\n    {assign var=group_info value=\$curr_group_info.group_info}\r\n    {assign var=options value=\$curr_group_info.options}\r\n    {if \$group_info.group_name}\r\n      <optgroup label=\"{\$group_info.group_name|escape}\">\r\n    {/if}\r\n    {foreach from=\$options item=option name=row}\r\n      <option value=\"{\$option.option_value}\"\r\n        {if \$VALUE == \$option.option_value}selected{/if}>{\$option.option_name}</option>\r\n    {/foreach}\r\n    {if \$group_info.group_name}\r\n      </optgroup>\r\n    {/if}\r\n  {/foreach}\r\n  </select>\r\n{/if}\r\n\r\n{if \$comments}\r\n  <div class=\"cf_field_comments\">{\$comments}</div>\r\n{/if}'\r\n      WHERE  field_type_identifier = 'dropdown'\r\n    ");
        // multi-select dropdown
        mysql_query("\r\n      UPDATE {$g_table_prefix}field_types\r\n      SET    view_field_rendering_type = 'php',\r\n             view_field_php_function_source = 'core',\r\n             view_field_php_function = 'ft_display_field_type_multi_select_dropdown',\r\n             view_field_smarty_markup = '{if \$contents != \"\"}\r\n  {assign var=vals value=\"`\$g_multi_val_delimiter`\"|explode:\$VALUE}\r\n  {assign var=is_first value=true}\r\n  {strip}\r\n  {foreach from=\$contents.options item=curr_group_info name=group}\r\n    {assign var=options value=\$curr_group_info.options}\r\n    {foreach from=\$options item=option name=row}\r\n      {if \$option.option_value|in_array:\$vals}\r\n        {if \$is_first == false}, {/if}\r\n        {\$option.option_name}\r\n        {assign var=is_first value=false}\r\n      {/if}\r\n    {/foreach}\r\n  {/foreach}\r\n  {/strip}\r\n{/if}',\r\n             edit_field_smarty_markup = '{if \$contents == \"\"}\r\n  <div class=\"cf_field_comments\">{\$LANG.phrase_not_assigned_to_option_list}</div>\r\n{else}\r\n  {assign var=vals value=\"`\$g_multi_val_delimiter`\"|explode:\$VALUE}\r\n  <select name=\"{\$NAME}[]\" multiple size=\"{if \$num_rows}{\$num_rows}{else}5{/if}\">\r\n  {foreach from=\$contents.options item=curr_group_info name=group}\r\n    {assign var=group_info value=\$curr_group_info.group_info}\r\n    {assign var=options value=\$curr_group_info.options}\r\n    {if \$group_info.group_name}\r\n      <optgroup label=\"{\$group_info.group_name|escape}\">\r\n    {/if}\r\n    {foreach from=\$options item=option name=row}\r\n      <option value=\"{\$option.option_value}\"\r\n        {if \$option.option_value|in_array:\$vals}selected{/if}>{\$option.option_name}</option>\r\n    {/foreach}\r\n    {if \$group_info.group_name}\r\n      </optgroup>\r\n    {/if}\r\n  {/foreach}\r\n  </select>\r\n{/if}\r\n\r\n{if \$comments}\r\n  <div class=\"cf_field_comments\">{\$comments}</div>\r\n{/if}',\r\n      WHERE  field_type_identifier = 'multi_select_dropdown'\r\n    ");
        // radio buttons
        mysql_query("\r\n      UPDATE {$g_table_prefix}field_types\r\n      SET    view_field_rendering_type = 'php',\r\n             view_field_php_function_source = 'core',\r\n             view_field_php_function = 'ft_display_field_type_radios',\r\n             view_field_smarty_markup = '{strip}{if \$contents != \"\"}\r\n  {foreach from=\$contents.options item=curr_group_info name=group}\r\n    {assign var=options value=\$curr_group_info.options}\r\n    {foreach from=\$options item=option name=row}\r\n      {if \$VALUE == \$option.option_value}{\$option.option_name}{/if}\r\n    {/foreach}\r\n  {/foreach}\r\n{/if}{/strip}',\r\n             edit_field_smarty_markup = '{if \$contents == \"\"}\r\n  <div class=\"cf_field_comments\">{\$LANG.phrase_not_assigned_to_option_list}</div>\r\n{else}\r\n  {assign var=is_in_columns value=false}\r\n  {if \$formatting == \"cf_option_list_2cols\" || \r\n      \$formatting == \"cf_option_list_3cols\" || \r\n      \$formatting == \"cf_option_list_4cols\"}\r\n    {assign var=is_in_columns value=true}\r\n  {/if}\r\n\r\n  {assign var=counter value=\"1\"}\r\n  {foreach from=\$contents.options item=curr_group_info name=group}\r\n    {assign var=group_info value=\$curr_group_info.group_info}\r\n    {assign var=options value=\$curr_group_info.options}\r\n\r\n    {if \$group_info.group_name}\r\n      <div class=\"cf_option_list_group_label\">{\$group_info.group_name}</div>\r\n    {/if}\r\n\r\n    {if \$is_in_columns}<div class=\"{\$formatting}\">{/if}\r\n\r\n    {foreach from=\$options item=option name=row}\r\n      {if \$is_in_columns}<div class=\"column\">{/if}\r\n        <input type=\"radio\" name=\"{\$NAME}\" id=\"{\$NAME}_{\$counter}\" \r\n          value=\"{\$option.option_value}\"\r\n          {if \$VALUE == \$option.option_value}checked{/if} />\r\n          <label for=\"{\$NAME}_{\$counter}\">{\$option.option_name}</label>\r\n      {if \$is_in_columns}</div>{/if}\r\n      {if \$formatting == \"vertical\"}<br />{/if}\r\n      {assign var=counter value=\$counter+1}\r\n    {/foreach}\r\n\r\n    {if \$is_in_columns}</div>{/if}\r\n  {/foreach}\r\n\r\n  {if \$comments}<div class=\"cf_field_comments\">{\$comments}</div>{/if}\r\n{/if}'\r\n      WHERE  field_type_identifier = 'radio_buttons'\r\n    ");
        // checkboxes
        mysql_query("\r\n      UPDATE {$g_table_prefix}field_types\r\n      SET    view_field_rendering_type = 'php',\r\n             view_field_php_function_source = 'core',\r\n             view_field_php_function = 'ft_display_field_type_checkboxes',\r\n             view_field_smarty_markup = '{strip}{if \$contents != \"\"}\r\n  {assign var=vals value=\"`\$g_multi_val_delimiter`\"|explode:\$VALUE}\r\n  {assign var=is_first value=true}\r\n  {strip}\r\n  {foreach from=\$contents.options item=curr_group_info name=group}\r\n    {assign var=options value=\$curr_group_info.options}\r\n    {foreach from=\$options item=option name=row}\r\n      {if \$option.option_value|in_array:\$vals}\r\n        {if \$is_first == false}, {/if}\r\n        {\$option.option_name}\r\n        {assign var=is_first value=false}\r\n      {/if}\r\n    {/foreach}\r\n  {/foreach}\r\n  {/strip}\r\n{/if}{/strip}',\r\n             edit_field_smarty_markup = '{if \$contents == \"\"}\r\n  <div class=\"cf_field_comments\">{\$LANG.phrase_not_assigned_to_option_list}</div>\r\n{else}\r\n  {assign var=vals value=\"`\$g_multi_val_delimiter`\"|explode:\$VALUE}\r\n  {assign var=is_in_columns value=false}\r\n  {if \$formatting == \"cf_option_list_2cols\" || \r\n      \$formatting == \"cf_option_list_3cols\" || \r\n      \$formatting == \"cf_option_list_4cols\"}\r\n    {assign var=is_in_columns value=true}\r\n  {/if}\r\n\r\n  {assign var=counter value=\"1\"}\r\n  {foreach from=\$contents.options item=curr_group_info name=group}\r\n    {assign var=group_info value=\$curr_group_info.group_info}\r\n    {assign var=options value=\$curr_group_info.options}\r\n\r\n    {if \$group_info.group_name}\r\n      <div class=\"cf_option_list_group_label\">{\$group_info.group_name}</div>\r\n    {/if}\r\n\r\n    {if \$is_in_columns}<div class=\"{\$formatting}\">{/if}\r\n\r\n    {foreach from=\$options item=option name=row}\r\n      {if \$is_in_columns}<div class=\"column\">{/if}\r\n        <input type=\"checkbox\" name=\"{\$NAME}[]\" id=\"{\$NAME}_{\$counter}\" \r\n          value=\"{\$option.option_value|escape}\" \r\n          {if \$option.option_value|in_array:\$vals}checked{/if} />\r\n          <label for=\"{\$NAME}_{\$counter}\">{\$option.option_name}</label>\r\n      {if \$is_in_columns}</div>{/if}\r\n      {if \$formatting == \"vertical\"}<br />{/if}\r\n      {assign var=counter value=\$counter+1}\r\n    {/foreach}\r\n\r\n    {if \$is_in_columns}</div>{/if}\r\n  {/foreach}\r\n\r\n  {if {\$comments}\r\n    <div class=\"cf_field_comments\">{\$comments}</div> \r\n  {/if}\r\n{/if}'\r\n      WHERE  field_type_identifier = 'checkboxes'\r\n    ");
        // date
        mysql_query("\r\n      UPDATE {$g_table_prefix}field_types\r\n      SET    view_field_rendering_type = 'php',\r\n             view_field_php_function_source = 'core',\r\n             view_field_php_function = 'ft_display_field_type_date'\r\n      WHERE  field_type_identifier = 'date'\r\n    ");
        // time
        mysql_query("\r\n      UPDATE {$g_table_prefix}field_types\r\n      SET    view_field_rendering_type = 'none'\r\n      WHERE  field_type_identifier = 'time'\r\n    ");
        // phone
        mysql_query("\r\n      UPDATE {$g_table_prefix}field_types\r\n      SET    view_field_rendering_type = 'php',\r\n             view_field_php_function_source = 'core',\r\n             view_field_php_function = 'ft_display_field_type_phone_number'\r\n      WHERE  field_type_identifier = 'phone'\r\n    ");
        // code / markup
        mysql_query("\r\n      UPDATE {$g_table_prefix}field_types\r\n      SET    view_field_rendering_type = 'php',\r\n             view_field_php_function_source = 'core',\r\n             view_field_php_function = 'ft_display_field_type_code_markup'\r\n      WHERE  field_type_identifier = 'code_markup'\r\n    ");
    }
    if ($old_version_info["release_date"] < 20110630) {
        mysql_query("INSERT INTO {$g_table_prefix}settings (setting_name, setting_value, module) VALUES ('field_type_settings_shared_characteristics', 'field_comments:textbox,comments`textarea,comments`password,comments`dropdown,comments`multi_select_dropdown,comments`radio_buttons,comments`checkboxes,comments`date,comments`time,comments`phone,comments`code_markup,comments`file,comments`google_maps_field,comments`tinymce,comments|data_source:dropdown,contents`multi_select_dropdown,contents`radio_buttons,contents`checkboxes,contents|column_formatting:checkboxes,formatting`radio_buttons,formatting|maxlength_attr:textbox,maxlength|colour_highlight:textbox,highlight|folder_path:file,folder_path|folder_url:file,folder_url|permitted_file_types:file,folder_url|max_file_size:file,max_file_size|date_display_format:date,display_format|apply_timezone_offset:date,apply_timezone_offset', 'core')");
    }
    // yet more field type updates
    if ($old_version_info["release_date"] < 20110702) {
        mysql_query("UPDATE {$g_table_prefix}field_types SET field_type_name = '{\$LANG.word_time}' WHERE field_type_identifier = 'time'");
        mysql_query("UPDATE {$g_table_prefix}field_types SET field_type_name = '{\$LANG.word_date}' WHERE field_type_identifier = 'date'");
        mysql_query("UPDATE {$g_table_prefix}field_types SET field_type_name = '{\$LANG.phrase_phone_number}' WHERE field_type_identifier = 'phone'");
        mysql_query("UPDATE {$g_table_prefix}field_types SET field_type_name = '{\$LANG.phrase_code_markup_field}' WHERE field_type_identifier = 'code_markup'");
        mysql_query("\r\n      UPDATE {$g_table_prefix}field_types\r\n      SET    edit_field_smarty_markup = '{* figure out all the classes *}\r\n{assign var=classes value=\$height}\r\n{if \$highlight_colour}\r\n  {assign var=classes value=\"`\$classes` `\$highlight_colour`\"}\r\n{/if}\r\n{if \$input_length == \"words\" && \$maxlength != \"\"}\r\n  {assign var=classes value=\"`\$classes` cf_wordcounter max`\$maxlength`\"}\r\n{elseif \$input_length == \"chars\" && \$maxlength != \"\"}\r\n  {assign var=classes value=\"`\$classes` cf_textcounter max`\$maxlength`\"}\r\n{/if}\r\n\r\n<textarea name=\"{\$NAME}\" id=\"{\$NAME}_id\" class=\"{\$classes}\">{\$VALUE}</textarea>\r\n\r\n{if \$input_length == \"words\" && \$maxlength != \"\"}\r\n  <div class=\"cf_counter\" id=\"{\$NAME}_counter\">\r\n    {\$maxlength} {\$LANG.phrase_word_limit_p} <span></span> {\$LANG.phrase_remaining_words}\r\n  </div>\r\n{elseif \$input_length == \"chars\" && \$maxlength != \"\"}\r\n  <div class=\"cf_counter\" id=\"{\$NAME}_counter\">\r\n    {\$maxlength} {\$LANG.phrase_characters_limit_p} <span></span> {\$LANG.phrase_remaining_characters}\r\n  </div>\r\n{/if}\r\n\r\n{if \$comments}\r\n  <div class=\"cf_field_comments\">{\$comments|nl2br}</div>\r\n{/if}',\r\n             resources_js = '/**\r\n * The following code provides a simple text/word counter option for any  \r\n * textarea. It either just keeps counting up, or limits the results to a\r\n * certain number - all depending on what the user has selected via the\r\n * field type settings.\r\n */\r\nvar cf_counter = {};\r\ncf_counter.get_max_count = function(el) {\r\n  var classes = \$(el).attr(''class'').split(\" \").slice(-1);\r\n  var max = null;\r\n  for (var i=0; i<classes.length; i++) {\r\n    var result = classes[i].match(/max(\\\\d+)/);\r\n    if (result != null) {\r\n      max = result[1];\r\n      break;\r\n    }\r\n  }\r\n  return max;\r\n}\r\n\r\n\$(function() {\r\n  \$(\"textarea[class~=''cf_wordcounter'']\").each(function() {\r\n    var max = cf_counter.get_max_count(this);\r\n    if (max == null) {\r\n      return;\r\n    }\r\n    \$(this).bind(\"keydown\", function() {\r\n      var val = \$(this).val();\r\n      var len        = val.split(/[\\\\s]+/);\r\n      var field_name = \$(this).attr(\"name\");\r\n      var num_words  = len.length - 1;\r\n      if (num_words > max) {\r\n        var allowed_words = val.split(/[\\\\s]+/, max);\r\n        truncated_str = allowed_words.join(\" \");\r\n        \$(this).val(truncated_str);\r\n      } else {\r\n        \$(\"#\" + field_name + \"_counter\").find(\"span\").html(parseInt(max) - parseInt(num_words));\r\n      }\r\n    });     \r\n    \$(this).trigger(\"keydown\");\r\n  });\r\n\r\n  \$(\"textarea[class~=''cf_textcounter'']\").each(function() {\r\n    var max = cf_counter.get_max_count(this);\r\n    if (max == null) {\r\n      return;\r\n    }\r\n    \$(this).bind(\"keydown\", function() {    \r\n      var field_name = \$(this).attr(\"name\");      \r\n      if (this.value.length > max) {\r\n        this.value = this.value.substring(0, max);\r\n      } else {\r\n        \$(\"#\" + field_name + \"_counter\").find(\"span\").html(max - this.value.length);\r\n      }\r\n    });\r\n    \$(this).trigger(\"keydown\");\r\n  }); \r\n});'\r\n      WHERE  field_type_identifier = 'textarea'\r\n    ");
        mysql_query("\r\n      UPDATE {$g_table_prefix}field_types\r\n      SET    view_field_smarty_markup = '{php}\r\n\$format = \$this->get_template_vars(\"phone_number_format\");\r\n\$values = explode(\"|\", \$this->get_template_vars(\"VALUE\"));\r\n\$pieces = preg_split(\"/(x+)/\", \$format, 0, PREG_SPLIT_DELIM_CAPTURE);\r\n\$counter = 1;\r\n\$output = \"\";\r\n\$has_content = false;\r\nforeach (\$pieces as \$piece)\r\n{\r\n  if (empty(\$piece))\r\n    continue;\r\n\r\n  if (\$piece[0] == \"x\") {    \r\n    \$value = (isset(\$values[\$counter-1])) ? \$values[\$counter-1] : \"\";\r\n    \$output .= \$value;\r\n    if (!empty(\$value))\r\n    {\r\n      \$has_content = true;\r\n    }\r\n    \$counter++;\r\n  } else {\r\n    \$output .= \$piece;\r\n  }\r\n}\r\n\r\nif (!empty(\$output) && \$has_content)\r\n  echo \$output;\r\n{/php}',\r\n             edit_field_smarty_markup = '{php}\r\n\$format = \$this->get_template_vars(\"phone_number_format\");\r\n\$values = explode(\"|\", \$this->get_template_vars(\"VALUE\"));\r\n\$name   = \$this->get_template_vars(\"NAME\");\r\n\r\n\$pieces = preg_split(\"/(x+)/\", \$format, 0, PREG_SPLIT_DELIM_CAPTURE);\r\n\$counter = 1;\r\nforeach (\$pieces as \$piece)\r\n{\r\n  if (strlen(\$piece) == 0)\r\n    continue;\r\n\r\n  if (\$piece[0] == \"x\") {\r\n    \$size = strlen(\$piece); \r\n    \$value = (isset(\$values[\$counter-1])) ? \$values[\$counter-1] : \"\";\r\n    \$value = htmlspecialchars(\$value);\r\n    echo \"<input type=\\\\\"text\\\\\" name=\\\\\"{\$name}_\$counter\\\\\" value=\\\\\"\$value\\\\\"\r\n            size=\\\\\"\$size\\\\\" maxlength=\\\\\"\$size\\\\\" />\";\r\n    \$counter++;\r\n  } else {\r\n    echo \$piece;\r\n  }\r\n}\r\n{/php}\r\n{if \$comments}\r\n  <div class=\"cf_field_comments\">{\$comments}</div>\r\n{/if}'\r\n      WHERE  field_type_identifier = 'phone'\r\n    ");
        mysql_query("\r\n      UPDATE {$g_table_prefix}field_types\r\n      SET    edit_field_smarty_markup = '<div class=\"editor\">\r\n  <textarea id=\"{\$NAME}_id\" name=\"{\$NAME}\">{\$VALUE}</textarea>\r\n</div>\r\n<script>\r\n  var code_mirror_{\$NAME} = new CodeMirror.fromTextArea(\"{\$NAME}_id\", \r\n  {literal}{{/literal}\r\n    height: \"{\$height}px\",\r\n    path:   \"{\$g_root_url}/global/codemirror/js/\",\r\n    {if \$code_markup == \"HTML\" || \$code_markup == \"XML\"}\r\n      parserfile: [\"parsexml.js\"],\r\n      stylesheet: \"{\$g_root_url}/global/codemirror/css/xmlcolors.css\"\r\n    {elseif \$code_markup == \"CSS\"}\r\n      parserfile: [\"parsecss.js\"],\r\n      stylesheet: \"{\$g_root_url}/global/codemirror/css/csscolors.css\"\r\n    {elseif \$code_markup == \"JavaScript\"}  \r\n      parserfile: [\"tokenizejavascript.js\", \"parsejavascript.js\"],\r\n      stylesheet: \"{\$g_root_url}/global/codemirror/css/jscolors.css\"\r\n    {/if}\r\n  {literal}});{/literal}\r\n</script>\r\n\r\n{if \$comments}\r\n  <div class=\"cf_field_comments\">{\$comments}</div>\r\n{/if}'\r\n      WHERE  field_type_identifier = 'code_markup'\r\n    ");
    }
    if ($old_version_info["release_date"] < 20110716) {
        $field_type_info = ft_get_field_type_by_identifier("code_markup");
        foreach ($field_type_info["settings"] as $curr_field_type_info) {
            if ($curr_field_type_info["field_setting_identifier"] != "height") {
                continue;
            }
            $setting_id = $curr_field_type_info["setting_id"];
            mysql_query("UPDATE {$g_table_prefix}field_type_settings SET default_value = '200' WHERE setting_id = {$setting_id}") or die(mysql_error());
        }
    }
    // update the Date field type for additional custom date formats
    if ($old_version_info["release_date"] < 20110811) {
        $field_type_info = ft_get_field_type_by_identifier("date");
        $field_type_id = $field_type_info["field_type_id"];
        $custom_date_format_info = ft_get_field_type_setting_by_identifier($field_type_id, "display_format");
        $setting_id = $custom_date_format_info["setting_id"];
        mysql_query("DELETE FROM {$g_table_prefix}field_type_setting_options WHERE setting_id = {$setting_id}");
        mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES ({$setting_id}, '2011-11-30', 'yy-mm-dd', 1, 'yes')");
        mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES ({$setting_id}, '30/11/2011 (dd/mm/yyyy)', 'dd/mm/yy', 2, 'yes')");
        mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES ({$setting_id}, '11/30/2011 (mm/dd/yyyy)', 'mm/dd/yy', 3, 'yes')");
        mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES ({$setting_id}, 'Nov 30, 2011', 'M d, yy', 4, 'yes')");
        mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES ({$setting_id}, 'November 30, 2011', 'MM d, yy', 5, 'yes')");
        mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES ({$setting_id}, 'Wed Nov 30, 2011 ', 'D M d, yy', 6, 'yes')");
        mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES ({$setting_id}, 'Wednesday, November 30, 2011', 'DD, MM d, yy', 7, 'yes')");
        mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES ({$setting_id}, '30. 08. 2011.', 'dd. mm. yy.', 8, 'yes')");
        mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES ({$setting_id}, '30/11/2011 8:00 PM', 'datetime:dd/mm/yy|h:mm TT|ampm`true', 9, 'yes')");
        mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES ({$setting_id}, '11/30/2011 8:00 PM', 'datetime:mm/dd/yy|h:mm TT|ampm`true', 10, 'yes')");
        mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES ({$setting_id}, '2011-11-30 8:00 PM', 'datetime:yy-mm-dd|h:mm TT|ampm`true', 11, 'yes')");
        mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES ({$setting_id}, '2011-11-30 20:00', 'datetime:yy-mm-dd|hh:mm', 12, 'yes')");
        mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES ({$setting_id}, '2011-11-30 20:00:00', 'datetime:yy-mm-dd|hh:mm:ss|showSecond`true', 13, 'yes')");
        mysql_query("INSERT INTO {$g_table_prefix}field_type_setting_options VALUES ({$setting_id}, '30. 08. 2011. 20:00', 'datetime:dd. mm. yy.|hh:mm', 14, 'yes')");
        mysql_query("\r\n      UPDATE {$g_table_prefix}field_types\r\n      SET    view_field_smarty_markup = '{strip}\r\n  {if \$VALUE}\r\n    {assign var=tzo value=\"\"}\r\n    {if \$apply_timezone_offset == \"yes\"}\r\n      {assign var=tzo value=\$ACCOUNT_INFO.timezone_offset}\r\n    {/if}\r\n    {if \$display_format == \"yy-mm-dd\" || !\$display_format}\r\n      {\$VALUE|custom_format_date:\$tzo:\"Y-m-d\"}\r\n    {elseif \$display_format == \"dd/mm/yy\"}\r\n      {\$VALUE|custom_format_date:\$tzo:\"d/m/Y\"}\r\n    {elseif \$display_format == \"mm/dd/yy\"}\r\n      {\$VALUE|custom_format_date:\$tzo:\"m/d/Y\"}\r\n    {elseif \$display_format == \"M d, yy\"}\r\n      {\$VALUE|custom_format_date:\$tzo:\"M j, Y\"}\r\n    {elseif \$display_format == \"MM d, yy\"}\r\n      {\$VALUE|custom_format_date:\$tzo:\"F j, Y\"}\r\n    {elseif \$display_format == \"D M d, yy\"}\r\n      {\$VALUE|custom_format_date:\$tzo:\"D M j, Y\"}\r\n    {elseif \$display_format == \"DD, MM d, yy\"}\r\n      {\$VALUE|custom_format_date:\$tzo:\"l M j, Y\"}\r\n    {elseif \$display_format == \"dd. mm. yy.\"}\r\n      {\$VALUE|custom_format_date:\$tzo:\"d. m. Y.\"}\r\n    {elseif \$display_format == \"datetime:dd/mm/yy|h:mm TT|ampm`true\"}\r\n      {\$VALUE|custom_format_date:\$tzo:\"d/m/Y g:i A\"}\r\n    {elseif \$display_format == \"datetime:mm/dd/yy|h:mm TT|ampm`true\"}\r\n      {\$VALUE|custom_format_date:\$tzo:\"m/d/Y g:i A\"}\r\n    {elseif \$display_format == \"datetime:yy-mm-dd|h:mm TT|ampm`true\"}\r\n      {\$VALUE|custom_format_date:\$tzo:\"Y-m-d g:i A\"}\r\n    {elseif \$display_format == \"datetime:yy-mm-dd|hh:mm\"}\r\n      {\$VALUE|custom_format_date:\$tzo:\"Y-m-d H:i\"}\r\n    {elseif \$display_format == \"datetime:yy-mm-dd|hh:mm:ss|showSecond`true\"}\r\n      {\$VALUE|custom_format_date:\$tzo:\"Y-m-d H:i:s\"}\r\n    {elseif \$display_format == \"datetime:dd. mm. yy.|hh:mm\"}\r\n      {\$VALUE|custom_format_date:\$tzo:\"d. m. Y. H:i\"}\r\n    {/if}\r\n{/if}{/strip}',\r\n             edit_field_smarty_markup = '{assign var=class value=\"cf_datepicker\"}\r\n{if \$display_format|strpos:\"datetime\" === 0}\r\n  {assign var=class value=\"cf_datetimepicker\"}\r\n{/if}\r\n\r\n{assign var=\"val\" value=\"\"}\r\n{if \$VALUE}\r\n  {assign var=tzo value=\"\"}\r\n  {if \$apply_timezone_offset == \"yes\"}\r\n    {assign var=tzo value=\$ACCOUNT_INFO.timezone_offset}\r\n  {/if}\r\n  {if \$display_format == \"yy-mm-dd\"}\r\n    {assign var=val value=\$VALUE|custom_format_date:\$tzo:\"Y-m-d\"}\r\n  {elseif \$display_format == \"dd/mm/yy\"}\r\n    {assign var=val value=\$VALUE|custom_format_date:\$tzo:\"d/m/Y\"}\r\n  {elseif \$display_format == \"mm/dd/yy\"}\r\n    {assign var=val value=\$VALUE|custom_format_date:\$tzo:\"m/d/Y\"}\r\n  {elseif \$display_format == \"M d, yy\"}\r\n    {assign var=val value=\$VALUE|custom_format_date:\$tzo:\"M j, Y\"}\r\n  {elseif \$display_format == \"MM d, yy\"}\r\n    {assign var=val value=\$VALUE|custom_format_date:\$tzo:\"F j, Y\"}\r\n  {elseif \$display_format == \"D M d, yy\"}\r\n    {assign var=val value=\$VALUE|custom_format_date:\$tzo:\"D M j, Y\"}\r\n  {elseif \$display_format == \"DD, MM d, yy\"}\r\n    {assign var=val value=\$VALUE|custom_format_date:\$tzo:\"l M j, Y\"}\r\n  {elseif \$display_format == \"dd. mm. yy.\"}\r\n    {assign var=val value=\$VALUE|custom_format_date:\$tzo:\"d. m. Y.\"}\r\n  {elseif \$display_format == \"datetime:dd/mm/yy|h:mm TT|ampm`true\"}\r\n    {assign var=val value=\$VALUE|custom_format_date:\$tzo:\"d/m/Y g:i A\"}\r\n  {elseif \$display_format == \"datetime:mm/dd/yy|h:mm TT|ampm`true\"}\r\n    {assign var=val value=\$VALUE|custom_format_date:\$tzo:\"m/d/Y g:i A\"}\r\n  {elseif \$display_format == \"datetime:yy-mm-dd|h:mm TT|ampm`true\"}\r\n    {assign var=val value=\$VALUE|custom_format_date:\$tzo:\"Y-m-d g:i A\"}\r\n  {elseif \$display_format == \"datetime:yy-mm-dd|hh:mm\"}\r\n    {assign var=val value=\$VALUE|custom_format_date:\$tzo:\"Y-m-d H:i\"}\r\n  {elseif \$display_format == \"datetime:yy-mm-dd|hh:mm:ss|showSecond`true\"}\r\n    {assign var=val value=\$VALUE|custom_format_date:\$tzo:\"Y-m-d H:i:s\"}\r\n  {elseif \$display_format == \"datetime:dd. mm. yy.|hh:mm\"}\r\n    {assign var=val value=\$VALUE|custom_format_date:\$tzo:\"d. m. Y. H:i\"}\r\n  {/if}\r\n{/if}\r\n\r\n<div class=\"cf_date_group\">\r\n  <input type=\"input\" name=\"{\$NAME}\" id=\"{\$NAME}_id\" \r\n    class=\"cf_datefield {\$class}\" value=\"{\$val}\" /><img class=\"ui-datepicker-trigger\" src=\"{\$g_root_url}/global/images/calendar.png\" id=\"{\$NAME}_icon_id\" />\r\n  <input type=\"hidden\" id=\"{\$NAME}_format\" value=\"{\$display_format}\" />\r\n  {if \$comments}\r\n    <div class=\"cf_field_comments\">{\$comments}</div>\r\n  {/if}\r\n</div>',\r\n             php_processing = '\$field_name     = \$vars[\"field_info\"][\"field_name\"];\r\n\$date           = \$vars[\"data\"][\$field_name];\r\n\$display_format = \$vars[\"settings\"][\"display_format\"];\r\n\$atzo           = \$vars[\"settings\"][\"apply_timezone_offset\"];\r\n\$account_info   = isset(\$vars[\"account_info\"]) ? \$vars[\"account_info\"] : array();\r\n\r\nif (empty(\$date))\r\n{\r\n  \$value = \"\";\r\n}\r\nelse\r\n{\r\n  if (strpos(\$display_format, \"datetime:\") === 0)\r\n  {\r\n    \$parts = explode(\" \", \$date);\r\n    switch (\$display_format)\r\n    {\r\n      case \"datetime:dd/mm/yy|h:mm TT|ampm`true\":\r\n        \$date = substr(\$date, 3, 2) . \"/\" . substr(\$date, 0, 2) . \"/\" . \r\n          substr(\$date, 6);\r\n        break;\r\n      case \"datetime:dd. mm. yy.|hh:mm\":\r\n        \$date = substr(\$date, 4, 2) . \"/\" . substr(\$date, 0, 2) . \"/\" . \r\n          substr(\$date, 8, 4) . \" \" . substr(\$date, 14);\r\n        break;\r\n    }\r\n  }\r\n  else\r\n  {\r\n    if (\$display_format == \"dd/mm/yy\")\r\n    {\r\n      \$date = substr(\$date, 3, 2) . \"/\" . substr(\$date, 0, 2) . \"/\" . \r\n        substr(\$date, 6);\r\n    } \r\n    else if (\$display_format == \"dd. mm. yy.\")\r\n    {\r\n      \$parts = explode(\" \", \$date);\r\n      \$date = trim(\$parts[1], \".\") . \"/\" . trim(\$parts[0], \".\") . \"/\" . trim(\$parts[2], \".\");\r\n    }\r\n  }\r\n\r\n  \$time = strtotime(\$date);\r\n  \r\n  // lastly, if this field has a timezone offset being applied to it, do the\r\n  // appropriate math on the date\r\n  if (\$atzo == \"yes\" && !isset(\$account_info[\"timezone_offset\"]))\r\n  {\r\n    \$seconds_offset = \$account_info[\"timezone_offset\"] * 60 * 60;\r\n    \$time += \$seconds_offset;\r\n  }\r\n\r\n  \$value = date(\"Y-m-d H:i:s\", \$time);\r\n}\r\n\r\n'\r\n      WHERE  field_type_id = {$field_type_id}\r\n        ");
    }
    // 2.1.3: swatches + new "email_template_when_sent_views" table to log multiple "when sent" email-View mapping
    $has_problems = false;
    if ($old_version_info["release_date"] < 20110927) {
        $upgrade_attempted = true;
        $queries = array();
        $queries[] = "\r\n  \t  ALTER TABLE {$g_table_prefix}themes\r\n  \t    ADD uses_swatches ENUM('yes', 'no') NOT NULL DEFAULT 'no' AFTER theme_name,\r\n        ADD swatches MEDIUMTEXT NULL AFTER uses_swatches\r\n  \t";
        $queries[] = "ALTER TABLE {$g_table_prefix}accounts ADD swatch VARCHAR(255) NOT NULL AFTER theme";
        $queries[] = "UPDATE {$g_table_prefix}accounts SET swatch = 'green' WHERE theme = 'default'";
        $queries[] = "\r\n      CREATE TABLE {$g_table_prefix}email_template_when_sent_views (\r\n        email_id MEDIUMINT NOT NULL,\r\n        view_id MEDIUMINT NOT NULL\r\n      ) DEFAULT CHARSET=utf8\r\n    ";
        $find_query = mysql_query("\r\n      SELECT email_id, view_mapping_view_id\r\n      FROM   {$g_table_prefix}email_templates\r\n      WHERE  view_mapping_view_id != '' AND view_mapping_view_id IS NOT NULL\r\n    ");
        while ($row = mysql_fetch_assoc($find_query)) {
            $email_id = $row["email_id"];
            $view_id = $row["view_mapping_view_id"];
            $queries[] = "INSERT INTO {$g_table_prefix}email_template_when_sent_views (email_id, view_id) VALUES ({$email_id}, {$view_id})";
        }
        ft_set_settings(array("default_client_swatch" => "green"));
        foreach ($queries as $query) {
            $result = @mysql_query($query);
            if (!$result) {
                $has_problems = true;
                $success = false;
                $mysql_error = "<i>{$query}></i> [" . mysql_error() . "]";
                $error_message = ft_eval_smarty_string($LANG["notify_problem_upgrading"], array("version" => $g_current_version));
                $link_text = ft_eval_smarty_string($LANG["phrase_upgrade_problem_link"], array("link" => "http://docs.formtools.org/upgrading/?page=problems_upgrading"));
                $message = $error_message . " " . $mysql_error . "<br />" . $_LANG["phrase_upgrade_problem_link"] . " " . $link_text;
                break;
            }
        }
        // if there were ANY problems, undo all the changes we just did
        if ($has_problems) {
            @mysql_query("ALTER TABLE {$g_table_prefix}themes DROP uses_swatches");
            @mysql_query("ALTER TABLE {$g_table_prefix}themes DROP swatches");
            @mysql_query("ALTER TABLE {$g_table_prefix}accounts DROP swatch");
            @mysql_query("DROP TABLE {$g_table_prefix}email_template_when_sent_views");
            @mysql_query("DELETE FROM {$g_table_prefix}settings WHERE setting_name='default_client_swatch' AND module='core'");
        } else {
            // delete the old view_mapping_view_id column from the email_templates table
            @mysql_query("ALTER TABLE {$g_table_prefix}email_templates DROP view_mapping_view_id");
            // refresh the theme list. This updates Form Tools to recognize the new swatches for the default theme, saving
            // the administrator from having to click the "Refresh Theme List" button
            ft_update_theme_list();
        }
    }
    // 2.1.4: field validation
    $has_problems = false;
    if ($old_version_info["release_date"] < 20111007) {
        $upgrade_attempted = true;
        @mysql_query("ALTER TABLE {$g_table_prefix}form_fields DROP option_list_id");
        @mysql_query("ALTER TABLE {$g_table_prefix}modules CHANGE module_key module_key VARCHAR(15)");
        $queries = array();
        $queries[] = "\r\n      CREATE TABLE {$g_table_prefix}field_type_validation_rules (\r\n        rule_id mediumint(8) unsigned NOT NULL AUTO_INCREMENT,\r\n        field_type_id mediumint(9) NOT NULL,\r\n        rsv_rule varchar(50) NOT NULL,\r\n        rule_label varchar(100) NOT NULL,\r\n        rsv_field_name varchar(255) NOT NULL,\r\n        custom_function varchar(100) NOT NULL,\r\n        custom_function_required enum('yes','no','na') NOT NULL DEFAULT 'na',\r\n        default_error_message mediumtext NOT NULL,\r\n        list_order smallint(6) NOT NULL,\r\n        PRIMARY KEY (rule_id)\r\n      ) DEFAULT CHARSET=utf8\r\n    ";
        $queries[] = "INSERT INTO {$g_table_prefix}field_type_validation_rules VALUES(1, 1, 'required', '{\$LANG.word_required}', '{\$field_name}', '', 'no', '{\$LANG.validation_default_rule_required}', 1)";
        $queries[] = "INSERT INTO {$g_table_prefix}field_type_validation_rules VALUES(2, 1, 'valid_email', '{\$LANG.phrase_valid_email}', '{\$field_name}', '', 'no', '{\$LANG.validation_default_rule_valid_email}', 2)";
        $queries[] = "INSERT INTO {$g_table_prefix}field_type_validation_rules VALUES(3, 1, 'digits_only', '{\$LANG.phrase_numbers_only}', '{\$field_name}', '', 'no', '{\$LANG.validation_default_rule_numbers_only}', 3)";
        $queries[] = "INSERT INTO {$g_table_prefix}field_type_validation_rules VALUES(4, 1, 'letters_only', '{\$LANG.phrase_letters_only}', '{\$field_name}', '', 'no', '{\$LANG.validation_default_rule_letters_only}', 4)";
        $queries[] = "INSERT INTO {$g_table_prefix}field_type_validation_rules VALUES(5, 1, 'is_alpha', '{\$LANG.phrase_alphanumeric}', '{\$field_name}', '', 'no', '{\$LANG.validation_default_rule_alpha}', 5)";
        $queries[] = "INSERT INTO {$g_table_prefix}field_type_validation_rules VALUES(6, 2, 'required', '{\$LANG.word_required}', '{\$field_name}', '', '', '{\$LANG.validation_default_rule_required}', 1)";
        $queries[] = "INSERT INTO {$g_table_prefix}field_type_validation_rules VALUES(7, 3, 'required', '{\$LANG.word_required}', '{\$field_name}', '', '', '{\$LANG.validation_default_rule_required}', 1)";
        $queries[] = "INSERT INTO {$g_table_prefix}field_type_validation_rules VALUES(8, 4, 'required', '{\$LANG.word_required}', '{\$field_name}', '', '', '{\$LANG.validation_default_rule_required}', 1)";
        $queries[] = "INSERT INTO {$g_table_prefix}field_type_validation_rules VALUES(9, 5, 'required', '{\$LANG.word_required}', '{\$field_name}[]', '', 'no', '{\$LANG.validation_default_rule_required}', 1)";
        $queries[] = "INSERT INTO {$g_table_prefix}field_type_validation_rules VALUES(10, 6, 'required', '{\$LANG.word_required}', '{\$field_name}', '', '', '{\$LANG.validation_default_rule_required}', 1)";
        $queries[] = "INSERT INTO {$g_table_prefix}field_type_validation_rules VALUES(11, 7, 'required', '{\$LANG.word_required}', '{\$field_name}[]', '', '', '{\$LANG.validation_default_rule_required}', 1)";
        $queries[] = "INSERT INTO {$g_table_prefix}field_type_validation_rules VALUES(12, 8, 'required', '{\$LANG.word_required}', '{\$field_name}', '', 'no', '{\$LANG.validation_default_rule_required}', 1)";
        $queries[] = "INSERT INTO {$g_table_prefix}field_type_validation_rules VALUES(13, 9, 'required', '{\$LANG.word_required}', '{\$field_name}', '', 'no', '{\$LANG.validation_default_rule_required}', 1)";
        $queries[] = "INSERT INTO {$g_table_prefix}field_type_validation_rules VALUES(14, 10, 'function', '{\$LANG.word_required}', '', 'cf_phone.check_required', 'yes', '{\$LANG.validation_default_phone_num_required}', 1)";
        $queries[] = "INSERT INTO {$g_table_prefix}field_type_validation_rules VALUES(15, 11, 'function', '{\$LANG.word_required}', '', 'cf_code.check_required', 'yes', '{\$LANG.validation_default_rule_required}', 1)";
        $queries[] = "\r\n      CREATE TABLE {$g_table_prefix}field_validation (\r\n        rule_id mediumint(8) unsigned NOT NULL,\r\n        field_id mediumint(9) NOT NULL,\r\n        error_message mediumtext NOT NULL,\r\n        UNIQUE KEY rule_id (rule_id,field_id)\r\n      ) DEFAULT CHARSET=utf8\r\n    ";
        // now update the field types that have changed: phone & code/markup
        $queries[] = "UPDATE {$g_table_prefix}field_types SET resources_js = 'var cf_phone = {};\r\ncf_phone.check_required = function() {\r\n  var errors = [];\r\n  for (var i=0; i<rsv_custom_func_errors.length; i++) {\r\n    if (rsv_custom_func_errors[i].func != \"cf_phone.check_required\") {\r\n      continue;\r\n    }\r\n    var field_name = rsv_custom_func_errors[i].field;\r\n    var fields = \$(\"input[name^=\\\\\"\" + field_name + \"_\\\\\"]\");\r\n    fields.each(function() {\r\n      if (!this.name.match(/_(\\\\d+)\$/)) {\r\n        return;\r\n      }\r\n      var req_len = \$(this).attr(\"maxlength\");\r\n      var actual_len = this.value.length;\r\n      if (req_len != actual_len || this.value.match(/\\\\D/)) {\r\n        var el = document.edit_submission_form[field_name];\r\n        errors.push([el, rsv_custom_func_errors[i].err]);\r\n        return false;\r\n      }\r\n    });\r\n  }\r\n\r\n  if (errors.length) {\r\n    return errors;\r\n  }\r\n\r\n  return true;\r\n  \r\n}' WHERE field_type_identifier = 'phone'";
        $queries[] = "UPDATE {$g_table_prefix}field_types SET resources_js = 'var cf_code = {};\r\ncf_code.check_required = function() {\r\n  var errors = [];\r\n  for (var i=0; i<rsv_custom_func_errors.length; i++) {\r\n    if (rsv_custom_func_errors[i].func != \"cf_code.check_required\") {\r\n      continue;\r\n    }\r\n    var field_name = rsv_custom_func_errors[i].field;\r\n    var val = \$.trim(window[\"code_mirror_\" + field_name].getCode());\r\n    if (!val) {\r\n      var el = document.edit_submission_form[field_name];\r\n      errors.push([el, rsv_custom_func_errors[i].err]);\r\n    }\r\n  }\r\n  if (errors.length) {\r\n    return errors;\r\n  }\r\n  return true;  \r\n}\r\n' WHERE field_type_identifier = 'code_markup'";
        foreach ($queries as $query) {
            $result = @mysql_query($query);
            if (!$result) {
                $has_problems = true;
                $success = false;
                $mysql_error = "<i>{$query}></i> [" . mysql_error() . "]";
                $error_message = ft_eval_smarty_string($LANG["notify_problem_upgrading"], array("version" => $g_current_version));
                $link_text = ft_eval_smarty_string($LANG["phrase_upgrade_problem_link"], array("link" => "http://docs.formtools.org/upgrading/?page=problems_upgrading"));
                $message = $error_message . " " . $mysql_error . "<br />" . $_LANG["phrase_upgrade_problem_link"] . " " . $link_text;
                break;
            }
        }
        // if there were ANY problems, undo all the changes we just did
        if ($has_problems) {
            @mysql_query("DROP TABLE {$g_table_prefix}field_type_validation_rules");
            @mysql_query("DROP TABLE {$g_table_prefix}field_validation");
            // the changes to the field types don't need to be undone; they just added functions
        }
    }
    // 2.1.5
    $has_problems = false;
    if ($old_version_info["release_date"] < 20111022) {
        $upgrade_attempted = true;
        $setting = array("core_version_upgrade_track" => "unknown");
        ft_set_settings($setting);
        $queries = array();
        $queries[] = "\r\n      ALTER TABLE {$g_table_prefix}forms\r\n      CHANGE form_type form_type ENUM('internal', 'external', 'form_builder')\r\n      CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'external'\r\n    ";
        foreach ($queries as $query) {
            $result = @mysql_query($query);
            if (!$result) {
                $has_problems = true;
                $success = false;
                $mysql_error = "<i>{$query}></i> [" . mysql_error() . "]";
                $error_message = ft_eval_smarty_string($LANG["notify_problem_upgrading"], array("version" => $g_current_version));
                $link_text = ft_eval_smarty_string($LANG["phrase_upgrade_problem_link"], array("link" => "http://docs.formtools.org/upgrading/?page=problems_upgrading"));
                $message = $error_message . " " . $mysql_error . "<br />" . $_LANG["phrase_upgrade_problem_link"] . " " . $link_text;
                break;
            }
        }
    }
    // ----------------------------------------------------------------------------------------------
    // if no problems were encountered, and the the full version string (version-type-date) has changed,
    // update the database
    if ($old_version_info["full"] != "{$g_current_version}-{$g_release_type}-{$g_release_date}" && !$has_problems) {
        $upgrade_attempted = true;
        $upgrade_track = ft_get_settings("core_version_upgrade_track");
        $upgrade_track .= ",{$g_current_version}-{$g_release_type}-{$g_release_date}";
        $new_settings = array("program_version" => $g_current_version, "release_date" => $g_release_date, "release_type" => $g_release_type, "core_version_upgrade_track" => $upgrade_track);
        ft_set_settings($new_settings);
        // any time the Core version changes, we need to update the list of hooks found in the source files
        ft_update_available_hooks();
        $success = true;
    }
    return array("upgraded" => $upgrade_attempted, "success" => $success, "message" => $message);
}
/**
 * This generic function processes any form field with a field type that requires additional
 * processing, e.g. phone number fields, date fields etc. - anything that needs a little extra PHP
 * in order to convert the form data into
 *
 * This function must
 *
 * @param array $info
 */
function ft_process_form_field($vars)
{
    eval($vars["code"]);
    $value = isset($value) ? $value : "";
    return ft_sanitize($value);
}
Beispiel #26
0
/**
 * This function is called from the main Modules page. It upgrades an individual
 * module.
 */
function ft_upgrade_module($module_id)
{
    global $LANG, $g_root_url, $g_root_dir, $g_table_prefix;
    $module_info = ft_get_module($module_id);
    $module_folder = $module_info["module_folder"];
    $module_name = $module_info["module_name"];
    $old_module_version_date = $module_info["module_date"];
    $current_db_version = $module_info["version"];
    $info = ft_get_module_info_file_contents($module_folder);
    $new_version = $info["version"];
    if ($current_db_version == $new_version) {
        return array(false, "");
    }
    // if the module has its own upgrade function, call it. In Oct 2011, a BIG problem was identified
    // in the way modules were being updated. For backward compatibility, the new upgrade function
    // must be named [module folder]__update (not ...__upgrade). if the __update function is defined,
    // it will be called instead of the older __upgrade one.
    @(include_once "{$g_root_dir}/modules/{$module_folder}/library.php");
    // NEW "update" function
    $update_function_name = "{$module_folder}__update";
    if (function_exists($update_function_name)) {
        list($success, $message) = $update_function_name($module_info, $info);
        if (!$success) {
            return array($success, $message);
        }
    } else {
        // OLD "upgrade" function
        $upgrade_function_name = "{$module_folder}__upgrade";
        if (function_exists($upgrade_function_name)) {
            $upgrade_function_name($current_db_version, $new_version);
        }
    }
    // now, update the main module record
    $info = ft_sanitize($info);
    // we're assuming the module developer hasn't removed any of the required fields...
    // now check the language file contains the two required fields: module_name and module_description
    $lang_file = "{$g_root_dir}/modules/{$module_folder}/lang/{$info["origin_language"]}.php";
    $lang_info = _ft_get_module_lang_file_contents($lang_file);
    $lang_info = ft_sanitize($lang_info);
    // check the required language file fields
    if (!isset($lang_info["module_name"]) || empty($lang_info["module_name"]) || (!isset($lang_info["module_description"]) || empty($lang_info["module_description"]))) {
        return;
    }
    $author = $info["author"];
    $author_email = $info["author_email"];
    $author_link = $info["author_link"];
    $module_version = $info["version"];
    $module_date = $info["date"];
    $origin_language = $info["origin_language"];
    $nav = $info["nav"];
    $module_name = $lang_info["module_name"];
    $module_description = $lang_info["module_description"];
    // convert the date into a MySQL datetime
    list($year, $month, $day) = explode("-", $module_date);
    $timestamp = mktime(null, null, null, $month, $day, $year);
    $module_datetime = ft_get_current_datetime($timestamp);
    @mysql_query("\n    UPDATE {$g_table_prefix}modules\n    SET    origin_language = '{$origin_language}',\n           module_name = '{$module_name}',\n           version = '{$module_version}',\n           author = '{$author}',\n           author_email = '{$author_email}',\n           author_link = '{$author_link}',\n           description = '{$module_description}',\n           module_date = '{$module_datetime}'\n    WHERE  module_id = {$module_id}\n      ") or die(mysql_error());
    // remove and update the navigation links for this module
    @mysql_query("DELETE FROM {$g_table_prefix}module_menu_items WHERE module_id = {$module_id}");
    $order = 1;
    while (list($lang_file_key, $info) = each($nav)) {
        $url = $info[0];
        $is_submenu = $info[1] ? "yes" : "no";
        if (empty($lang_file_key) || empty($url)) {
            continue;
        }
        $display_text = isset($lang_info[$lang_file_key]) ? $lang_info[$lang_file_key] : $LANG[$lang_file_key];
        mysql_query("\n      INSERT INTO {$g_table_prefix}module_menu_items (module_id, display_text, url, is_submenu, list_order)\n      VALUES ({$module_id}, '{$display_text}', '{$url}', '{$is_submenu}', {$order})\n        ") or die(mysql_error());
        $order++;
    }
    // And we're done! inform the user that it's been upgraded
    $placeholders = array("module" => $module_name, "version" => $new_version, "link" => "{$g_root_url}/modules/{$module_folder}");
    $message = ft_eval_smarty_string($LANG["notify_module_updated"], $placeholders);
    return array(true, $message);
}