Пример #1
0
/**
 * This constructs and sends the email from an individual email template for a single form
 * submission.
 *
 * @param integer $form_id
 * @param integer $submission_id
 * @param integer $email_id
 */
function ft_process_email_template($form_id, $submission_id, $email_id)
{
    list($success, $email_components) = ft_get_email_components($form_id, $submission_id, $email_id);
    if (!$success) {
        return array(false, "Email components not returned properly (ft_get_email_components).");
    }
    extract(ft_process_hook_calls("start", compact("form_id", "submission_id", "email_id", "email_components"), array("email_components")), EXTR_OVERWRITE);
    // if Swift Mailer is enabled, send the emails with that
    $continue = true;
    if (ft_check_module_enabled("swift_mailer")) {
        $sm_settings = ft_get_module_settings("", "swift_mailer");
        if (isset($sm_settings["swiftmailer_enabled"]) && $sm_settings["swiftmailer_enabled"] == "yes") {
            ft_include_module("swift_mailer");
            list($success, $message) = swift_send_email($email_components);
            $continue = false;
        }
    }
    // if it was sent (or was attempted to have been sent) by the Swift Mailer module, stop here
    if (!$continue) {
        return array($success, $message);
    }
    $eol = _ft_get_email_eol_char();
    $recipient_list = array();
    foreach ($email_components["to"] as $to_info) {
        $recipient_list[] = $to_info["recipient_line"];
    }
    $to = join(", ", $recipient_list);
    $to = htmlspecialchars_decode($to);
    if (empty($to)) {
        return array(false, "No main recipient specified.");
    }
    $headers = "MIME-Version: 1.0{$eol}";
    if (!empty($email_components["from"])) {
        $from = htmlspecialchars_decode($email_components["from"]["recipient_line"]);
        $headers .= "From: {$from}{$eol}";
    }
    if (!empty($email_components["reply_to"])) {
        $reply_to = htmlspecialchars_decode($email_components["reply_to"]["recipient_line"]);
        $headers .= "Reply-to: {$reply_to}{$eol}";
    }
    if (!empty($email_components["cc"])) {
        $cc_list = array();
        foreach ($email_components["cc"] as $cc_info) {
            $cc_list[] = $cc_info["recipient_line"];
        }
        $cc = join(", ", $cc_list);
        $cc = htmlspecialchars_decode($cc);
        $headers .= "Cc: {$cc}{$eol}";
    }
    if (!empty($email_components["bcc"])) {
        $bcc_list = array();
        foreach ($email_components["bcc"] as $bcc_info) {
            $bcc_list[] = $bcc_info["recipient_line"];
        }
        $bcc = join(", ", $bcc_list);
        $bcc = htmlspecialchars_decode($bcc);
        $headers .= "Bcc: {$bcc}{$eol}";
    }
    $message = "";
    $html_content = isset($email_components["html_content"]) ? $email_components["html_content"] : "";
    $text_content = isset($email_components["text_content"]) ? $email_components["text_content"] : "";
    $html_content = trim($html_content);
    $text_content = trim($text_content);
    // if there's no TO line or there's no email content for either types, we can't send the email
    if (empty($html_content) && empty($text_content)) {
        return array(false, "No text or HTML email content specified");
    }
    if (!empty($html_content) && !empty($text_content)) {
        $headers .= _ft_get_multipart_message($html_content, $text_content, $eol);
    } else {
        if (!empty($html_content)) {
            $message = $html_content;
            $headers .= "Content-type: text/html; charset=UTF-8";
        } else {
            if (!empty($text_content)) {
                $message = $text_content;
                $headers .= "Content-type: text/plain; charset=UTF-8";
            }
        }
    }
    $subject = $email_components["subject"];
    // send the email
    $email_sent = @mail("{$to}", $subject, $message, $headers);
    if ($email_sent) {
        return array(true, "");
    } else {
        return array(false, "The mail() function failed to send the email.");
    }
}
Пример #2
0
/**
 * Loads a theme opening page for a module. This should be used loaded for every page in a
 * module. It serves the same function as ft_display_page, except that it sets the appropriate root
 * folder for the module and loads the
 *
 * @param array $page_vars a hash of information to display / provide to the template.
 * @param string $theme
 */
function ft_display_module_page($template, $page_vars = array(), $theme = "", $swatch = "")
{
    global $g_root_dir, $g_root_url, $g_success, $g_message, $g_link, $g_smarty_debug, $g_language, $LANG, $g_smarty, $L, $g_smarty_use_sub_dirs, $g_js_debug, $g_benchmark_start, $g_enable_benchmarking, $g_hide_upgrade_link;
    $module_folder = _ft_get_current_module_folder();
    // $module_id = ft_get_module_id_from_module_folder($module_folder);
    $default_module_language = "en_us";
    if (empty($theme) && isset($_SESSION["ft"]["account"]["theme"])) {
        $theme = $_SESSION["ft"]["account"]["theme"];
        $swatch = isset($_SESSION["ft"]["account"]["swatch"]) ? $_SESSION["ft"]["account"]["swatch"] : "";
    } elseif (empty($theme)) {
        $settings = ft_get_settings(array("default_theme", "default_client_swatch"));
        $theme = $settings["default_theme"];
        $swatch = $settings["default_client_swatch"];
    }
    if (!isset($_SESSION["ft"]["account"]["is_logged_in"])) {
        $_SESSION["ft"]["account"]["is_logged_in"] = false;
    }
    if (!isset($_SESSION["ft"]["account"]["account_type"])) {
        $_SESSION["ft"]["account"]["account_type"] = "";
    }
    // common variables. These are sent to EVERY template
    $g_smarty->template_dir = "{$g_root_dir}/themes/{$theme}";
    $g_smarty->compile_dir = "{$g_root_dir}/themes/{$theme}/cache/";
    $g_smarty->use_sub_dirs = $g_smarty_use_sub_dirs;
    $g_smarty->assign("LANG", $LANG);
    // this contains the custom language content of the module, in the language required. It's populated by
    // ft_init_module_page(), called on every module page
    $g_smarty->assign("L", $L);
    $g_smarty->assign("SESSION", $_SESSION["ft"]);
    $settings = isset($_SESSION["ft"]["settings"]) ? $_SESSION["ft"]["settings"] : array();
    $g_smarty->assign("settings", $settings);
    $g_smarty->assign("account", $_SESSION["ft"]["account"]);
    $g_smarty->assign("g_root_dir", $g_root_dir);
    $g_smarty->assign("g_root_url", $g_root_url);
    $g_smarty->assign("g_js_debug", $g_js_debug ? "true" : "false");
    $g_smarty->assign("g_hide_upgrade_link", $g_hide_upgrade_link);
    $g_smarty->assign("same_page", ft_get_clean_php_self());
    $g_smarty->assign("query_string", $_SERVER["QUERY_STRING"]);
    // TODO FIX
    $g_smarty->assign("dir", $LANG["special_text_direction"]);
    $g_smarty->assign("g_enable_benchmarking", $g_enable_benchmarking);
    $g_smarty->assign("swatch", $swatch);
    // if this page has been told to dislay a custom message, override g_success and g_message
    if (isset($_GET["message"])) {
        list($g_success, $g_message) = ft_display_custom_page_message($_GET["message"]);
    }
    $g_smarty->assign("g_success", $g_success);
    $g_smarty->assign("g_message", $g_message);
    $module_id = ft_get_module_id_from_module_folder($module_folder);
    $module_nav = ft_get_module_menu_items($module_id, $module_folder);
    $g_smarty->assign("module_nav", $module_nav);
    // if there's no module title, display the module name. TODO not compatible with languages...
    if (!isset($page_vars["head_title"])) {
        $module_id = ft_get_module_id_from_module_folder($module_folder);
        $module_info = ft_get_module($module_id);
        $page_vars["head_title"] = $module_info["module_name"];
    }
    // check the "required" vars are at least set so they don't produce warnings when smarty debug is enabled
    if (!isset($page_vars["head_css"])) {
        $page_vars["head_css"] = "";
    }
    if (!isset($page_vars["head_js"])) {
        $page_vars["head_js"] = "";
    }
    if (!isset($page_vars["page"])) {
        $page_vars["page"] = "";
    }
    // if we need to include custom JS messages in the page, add it to the generated JS. Note: even if the js_messages
    // key is defined but still empty, the ft_generate_js_messages function is called, returning the "base" JS - like
    // the JS version of g_root_url. Only if it is not defined will that info not be included. This feature was hacked
    // in 2.1 to support js_messages from a single module file
    $js_messages = "";
    if (isset($page_vars["js_messages"]) || isset($page_vars["module_js_messages"])) {
        $core_js_messages = isset($page_vars["js_messages"]) ? $page_vars["js_messages"] : "";
        $module_js_messages = isset($page_vars["module_js_messages"]) ? $page_vars["module_js_messages"] : "";
        $js_messages = ft_generate_js_messages($core_js_messages, $module_js_messages);
    }
    if (!empty($page_vars["head_js"]) || !empty($js_messages)) {
        $page_vars["head_js"] = "<script type=\"text/javascript\">\n//<![CDATA[\n{$page_vars["head_js"]}\n{$js_messages}\n//]]>\n</script>";
    }
    if (!isset($page_vars["head_css"])) {
        $page_vars["head_css"] = "";
    } else {
        if (!empty($page_vars["head_css"])) {
            $page_vars["head_css"] = "<style type=\"text/css\">\n{$page_vars["head_css"]}\n</style>";
        }
    }
    // theme-specific vars
    $g_smarty->assign("images_url", "{$g_root_url}/themes/{$theme}/images");
    $g_smarty->assign("theme_url", "{$g_root_url}/themes/{$theme}");
    $g_smarty->assign("theme_dir", "{$g_root_dir}/themes/{$theme}");
    // if there's a Smarty folder, import any of its resources
    if (is_dir("{$g_root_dir}/modules/{$module_folder}/smarty")) {
        $g_smarty->plugins_dir[] = "{$g_root_dir}/modules/{$module_folder}/smarty";
    }
    // now add the custom variables for this template, as defined in $page_vars
    foreach ($page_vars as $key => $value) {
        $g_smarty->assign($key, $value);
    }
    // if smarty debug is on, enable Smarty debugging
    if ($g_smarty_debug) {
        $g_smarty->debugging = true;
    }
    extract(ft_process_hook_calls("main", compact("g_smarty", "template", "page_vars"), array("g_smarty")), EXTR_OVERWRITE);
    $g_smarty->display("{$g_root_dir}/modules/{$module_folder}/{$template}");
    ft_db_disconnect($g_link);
}
Пример #3
0
/**
 * Returns an array of account IDs of those clients in the omit list for this public form.
 *
 * @param integer $form_id
 * @return array
 */
function ft_get_public_form_omit_list($form_id)
{
    global $g_table_prefix;
    $query = mysql_query("\n    SELECT account_id\n    FROM   {$g_table_prefix}public_form_omit_list\n    WHERE form_id = {$form_id}\n      ");
    $client_ids = array();
    while ($row = mysql_fetch_assoc($query)) {
        $client_ids[] = $row["account_id"];
    }
    extract(ft_process_hook_calls("end", compact("clients_id", "form_id"), array("client_ids")), EXTR_OVERWRITE);
    return $client_ids;
}
Пример #4
0
/**
 * Returns all files associated with a particular form field or fields. Different field types may store the
 * files differently, so EVERY file upload module needs to add a hook to this function to return the
 * appropriate information.
 *
 * The module functions should return an array of hashes with the following structure:
 *    array(
 *      "submission_id" =>
 *      "field_id"      =>
 *      "field_type_id" =>
 *      "folder_path"   =>
 *      "folder_url"    =>
 *      "filename"      =>
 *    ),
 *    ...
 *
 * @param integer $form_id the unique form ID
 * @param array $field_ids an array of field IDs
 */
function ft_get_uploaded_files($form_id, $field_ids)
{
    $uploaded_files = array();
    extract(ft_process_hook_calls("start", compact("form_id", "field_ids"), array("uploaded_files")), EXTR_OVERWRITE);
    return $uploaded_files;
}
Пример #5
0
/**
 * Deletes a client menu. Since it's possible for one or more clients to already be associated with the
 * menu, those clients will be orphaned by this action. In this situation, it refuses to delete the
 * menu, and lists all clients that will be affected (each a link to their account). It also provides
 * an option to bulk assign them to another menu.
 *
 * In all likelihood, however, the administrator will already be aware of this, having seen their names
 * listed in the table where they chose to delete the menu.
 *
 * @param integer $menu_id
 * @return array [0] T/F, [1] message
 */
function ft_delete_client_menu($menu_id)
{
    global $g_table_prefix, $g_root_url, $LANG;
    extract(ft_process_hook_calls("start", compact("menu_id"), array()), EXTR_OVERWRITE);
    // confirm that there are no client accounts that currently use this menu
    $query = mysql_query("\r\n    SELECT account_id, first_name, last_name\r\n    FROM   {$g_table_prefix}accounts\r\n    WHERE  menu_id = {$menu_id}\r\n  ");
    $client_info = array();
    while ($row = mysql_fetch_assoc($query)) {
        $client_info[] = $row;
    }
    if (!empty($client_info)) {
        $message = $LANG["notify_deleted_menu_already_assigned"];
        $placeholder_str = $LANG["phrase_assign_all_listed_client_accounts_to_menu"];
        $menus = ft_get_menu_list();
        $dd = "<select id=\"mass_update_client_menu\">";
        foreach ($menus as $menu_info) {
            if ($menu_info["menu_type"] == "admin") {
                continue;
            }
            $dd .= "<option value=\"{$menu_info["menu_id"]}\">{$menu_info["menu"]}</option>";
        }
        $dd .= "</select>";
        // a bit bad (hardcoded HTML!), but organize the account list in 3 columns
        $client_links_table = "<table cellspacing=\"0\" cellpadding=\"0\" width=\"100%\">\n<tr>";
        $num_affected_clients = count($client_info);
        for ($i = 0; $i < $num_affected_clients; $i++) {
            $account_info = $client_info[$i];
            $client_id = $account_info["account_id"];
            $first_name = $account_info["first_name"];
            $last_name = $account_info["last_name"];
            $client_ids[] = $client_id;
            if ($i != 0 && $i % 3 == 0) {
                $client_links_table .= "</tr>\n<tr>";
            }
            $client_links_table .= "<td width=\"33%\">&bull;&nbsp;<a href=\"{$g_root_url}/admin/clients/edit.php?page=settings&client_id={$client_id}\" target=\"_blank\">{$first_name} {$last_name}</a></td>\n";
        }
        $client_id_str = join(",", $client_ids);
        // close the table
        if ($num_affected_clients % 3 == 1) {
            $client_links_table .= "<td colspan=\"2\" width=\"66%\"> </td>";
        } else {
            if ($num_affected_clients % 3 == 2) {
                $client_links_table .= "<td width=\"33%\"> </td>";
            }
        }
        $client_links_table .= "</tr></table>";
        $submit_button = "<input type=\"button\" value=\"{$LANG["phrase_update_accounts"]}\" onclick=\"window.location='index.php?page=menus&mass_assign=1&accounts={$client_id_str}&menu_id=' + \$('#mass_update_client_menu').val()\" />";
        $placeholders = array("menu_dropdown" => $dd, "submit_button" => $submit_button);
        $mass_assign_html = "<div class=\"margin_top_large margin_bottom_large\">" . ft_eval_smarty_string($placeholder_str, $placeholders) . "</div>";
        $html = $message . $mass_assign_html . $client_links_table;
        return array(false, $html);
    }
    // ------------------------------------------------------------
    $client_account_query = mysql_query("\r\n    SELECT account_id, first_name, last_name\r\n    FROM   {$g_table_prefix}accounts\r\n    WHERE  menu_id = {$menu_id}\r\n  ");
    // delete the menu
    mysql_query("DELETE FROM {$g_table_prefix}menus WHERE menu_id = {$menu_id}");
    mysql_query("DELETE FROM {$g_table_prefix}menu_items WHERE menu_id = {$menu_id}");
    // construct the message to return to the administrator
    $client_accounts = array();
    while ($row = mysql_fetch_assoc($client_account_query)) {
        $client_accounts[] = $row;
    }
    if (empty($client_accounts)) {
        $success = true;
        $message = $LANG["notify_client_menu_deleted"];
    } else {
        $success = false;
        $message = $LANG["notify_client_menu_deleted_orphaned_accounts"];
        $accounts_str = "<br />";
        foreach ($client_accounts as $account_info) {
            $client_id = $account_info["account_id"];
            $first_name = $account_info["first_name"];
            $last_name = $account_info["last_name"];
            $accounts_str .= "&bull;&nbsp;<a href=\"{$g_root_url}/admin/clients/edit.php?client_id={$client_id}\" target=\"_blank\">{$first_name} {$last_name}</a><br />\n";
        }
        $message .= $accounts_str;
    }
    return array($success, $message);
}
Пример #6
0
/**
 * This is called by the ft_delete_submission and ft_delete_submissions function. It's passed all relevant
 * information about the submission & file fields that need to be deleted. The function is just a stub to
 * allow file upload modules to add their hooks to.
 *
 * Modules that extend this function should return $problems. That should be an array of hashes. Each hash
 * having keys "filename" and "error". Since the calling functions will blithely delete the submissions even
 * if the file deletion fails, no other info is worth returning.
 *
 * @param integer $form_id
 * @param array $file_info an array of hashes. Each hash has the following keys (all self-explanatory):
 *                    submission_id -
 *                    field_id -
 *                    filename -
 *                    field_type_id -
 * @param string $context. Just used to pass a little more info to the hook. This is the context in which this
 *                    function is being called; i.e. the function name / action.
 */
function ft_delete_submission_files($form_id, $file_field_info, $context = "")
{
    $success = true;
    $problems = array();
    extract(ft_process_hook_calls("start", compact("form_id", "file_field_info"), array("success", "problems")), EXTR_OVERWRITE);
    return array($success, $problems);
}
Пример #7
0
/**
 * Called by the administrator from the Themes settings page. It updates the list of enabled
 * themes, and which theme is assigned to the administrator and (default) client accounts. Note:
 * it doesn't disable any themes that are already assigned to a user account. If that happens,
 * it returns a message listing the accounts (each clickable) and an option to bulk assign them
 * to a different theme.
 *
 * @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_theme_settings($infohash)
{
    global $g_table_prefix, $g_root_url, $g_root_dir, $LANG;
    // lots to validate! First, check the default admin & client themes have been entered
    $rules = array();
    $rules[] = "required,admin_theme,{$LANG["validation_no_admin_theme"]}";
    $rules[] = "required,default_client_theme,{$LANG["validation_no_default_client_theme"]}";
    $errors = validate_fields($infohash, $rules);
    if (!isset($infohash["is_enabled"])) {
        $errors[] = $LANG["validation_no_enabled_themes"];
    }
    if (!empty($errors)) {
        $success = false;
        array_walk($errors, create_function('&$el', '$el = "&bull;&nbsp; " . $el;'));
        $message = join("<br />", $errors);
        return array($success, $message);
    }
    $enabled_themes = $infohash["is_enabled"];
    // next, check that both the admin and default client themes are enabled
    $admin_theme = $infohash["admin_theme"];
    $default_client_theme = $infohash["default_client_theme"];
    if (!in_array($admin_theme, $enabled_themes) || !in_array($default_client_theme, $enabled_themes)) {
        return array(false, $LANG["validation_default_admin_and_client_themes_not_enabled"]);
    }
    // lastly, if there are already client accounts assigned to disabled themes, we need to sort it out.
    // We handle it the same way as deleting the client menus: if anyone is assigned to this theme,
    // we generate a list of their names, each a link to their account page (in a _blank link). We
    // then inform the user of what's going on, and underneath the name list, give them the option of
    // assigning ALL affected accounts to another (enabled) theme.
    $theme_clauses = array();
    foreach ($enabled_themes as $theme) {
        $theme_clauses[] = "theme != '{$theme}'";
    }
    $theme_clause = join(" AND ", $theme_clauses);
    $query = mysql_query("\n    SELECT account_id, first_name, last_name\n    FROM   {$g_table_prefix}accounts\n    WHERE  {$theme_clause}\n  ");
    $client_info = array();
    while ($row = mysql_fetch_assoc($query)) {
        $client_info[] = $row;
    }
    if (!empty($client_info)) {
        $message = $LANG["notify_disabled_theme_already_assigned"];
        $placeholder_str = $LANG["phrase_assign_all_listed_client_accounts_to_theme"];
        $themes = ft_get_themes(true);
        $dd = "<select id=\"mass_update_client_theme\">";
        foreach ($themes as $theme) {
            $dd .= "<option value=\"{$theme["theme_id"]}\">{$theme["theme_name"]}</option>";
        }
        $dd .= "</select>";
        // a bit bad (hardcoded HTML!), but organize the account list in 3 columns
        $client_links_table = "<table cellspacing=\"0\" cellpadding=\"0\" width=\"100%\">\n<tr>";
        $num_affected_clients = count($client_info);
        for ($i = 0; $i < $num_affected_clients; $i++) {
            $account_info = $client_info[$i];
            $client_id = $account_info["account_id"];
            $first_name = $account_info["first_name"];
            $last_name = $account_info["last_name"];
            $client_ids[] = $client_id;
            if ($i != 0 && $i % 3 == 0) {
                $client_links_table .= "</tr>\n<tr>";
            }
            $client_links_table .= "<td width=\"33%\">&bull;&nbsp;<a href=\"{$g_root_url}/admin/clients/edit.php?page=settings&client_id={$client_id}\" target=\"_blank\">{$first_name} {$last_name}</a></td>\n";
        }
        $client_id_str = join(",", $client_ids);
        // close the table
        if ($num_affected_clients % 3 == 1) {
            $client_links_table .= "<td colspan=\"2\" width=\"66%\"> </td>";
        } else {
            if ($num_affected_clients % 3 == 2) {
                $client_links_table .= "<td width=\"33%\"> </td>";
            }
        }
        $client_links_table .= "</tr></table>";
        $submit_button = "<input type=\"button\" value=\"{$LANG["phrase_update_accounts"]}\" onclick=\"window.location='index.php?page=themes&mass_assign=1&accounts={$client_id_str}&theme_id=' + \$('#mass_update_client_theme').val()\" />";
        $placeholders = array("theme_dropdown" => $dd, "submit_button" => $submit_button);
        $mass_assign_html = "<div class=\"margin_top_large margin_bottom_large\">" . ft_eval_smarty_string($placeholder_str, $placeholders) . "</div>";
        $html = $message . $mass_assign_html . $client_links_table;
        return array(false, $html);
    }
    // hoorah! Validation complete, let's update the bloomin' database at last
    // update the admin settings
    $admin_id = $_SESSION["ft"]["account"]["account_id"];
    $admin_swatch = "";
    if (isset($infohash["{$admin_theme}_admin_theme_swatches"])) {
        $admin_swatch = $infohash["{$admin_theme}_admin_theme_swatches"];
    }
    mysql_query("\n    UPDATE {$g_table_prefix}accounts\n    SET    theme = '{$admin_theme}',\n           swatch = '{$admin_swatch}'\n    WHERE  account_id = {$admin_id}\n      ");
    $_SESSION["ft"]["account"]["theme"] = $admin_theme;
    $_SESSION["ft"]["account"]["swatch"] = $admin_swatch;
    $default_client_swatch = "";
    if (isset($infohash["{$default_client_theme}_default_client_theme_swatches"])) {
        $default_client_swatch = $infohash["{$default_client_theme}_default_client_theme_swatches"];
    }
    // update the default client theme & swatch
    $new_settings = array("default_theme" => $default_client_theme, "default_client_swatch" => $default_client_swatch);
    ft_set_settings($new_settings);
    // finally, update the enabled themes list. Only set the theme as enabled if the
    // cache folder is writable
    mysql_query("UPDATE {$g_table_prefix}themes SET is_enabled = 'no'");
    foreach ($enabled_themes as $theme) {
        $cache_folder = "{$g_root_dir}/themes/{$theme}/cache";
        // try and set the cache folder as writable
        if (!is_writable($cache_folder)) {
            @chmod($cache_folder, 0777);
        }
        if (!is_writable($cache_folder)) {
            continue;
        }
        mysql_query("\n      UPDATE {$g_table_prefix}themes\n      SET    is_enabled = 'yes'\n      WHERE  theme_folder = '{$theme}'\n        ");
    }
    // reset the settings in sessions
    $_SESSION["ft"]["settings"] = ft_get_settings();
    $success = true;
    $message = $LANG["notify_themes_settings_updated"];
    extract(ft_process_hook_calls("end", compact("infohash"), array("success", "message")), EXTR_OVERWRITE);
    return array($success, $message);
}
Пример #8
0
/**
 * Generates the placeholders for a particular form submission. This is used in the email templates, and here and there
 * for providing placeholder functionality to fields (like the "Edit Submission Label" textfield for a form, where they can
 * enter placeholders populated here).
 *
 * This returns ALL available placeholders for a form, regardless of View.
 *
 * @param integer $form_id
 * @param integer $submission_id
 * @param array $client_info a hash of information about the appropriate user (optional)
 * @return array a hash of placeholders and their replacement values (e.g. $arr["FORMURL"] => 17)
 */
function ft_get_submission_placeholders($form_id, $submission_id, $client_info = "")
{
    global $g_root_url;
    $placeholders = array();
    $settings = ft_get_settings();
    $form_info = ft_get_form($form_id);
    $submission_info = ft_get_submission($form_id, $submission_id);
    $admin_info = ft_get_admin_info();
    $file_field_type_ids = ft_get_file_field_type_ids();
    $field_types = ft_get_field_types(true);
    // now loop through the info stored for this particular submission and for this particular field,
    // add the custom submission responses to the placeholder hash
    $form_field_params = array("include_field_type_info" => true, "include_field_settings" => true, "evaluate_dynamic_settings" => true);
    $form_fields = ft_get_form_fields($form_id, $form_field_params);
    foreach ($submission_info as $field_info) {
        $field_id = $field_info["field_id"];
        $field_name = $field_info["field_name"];
        $field_type_id = $field_info["field_type_id"];
        if ($field_info["is_system_field"] == "no") {
            $placeholders["QUESTION_{$field_name}"] = $field_info["field_title"];
        }
        if (in_array($field_type_id, $file_field_type_ids)) {
            $field_settings = ft_get_field_settings($field_id);
            $placeholders["FILENAME_{$field_name}"] = $field_info["content"];
            $placeholders["FILEURL_{$field_name}"] = "{$field_settings["folder_url"]}/{$field_info["content"]}";
        } else {
            $detailed_field_info = array();
            foreach ($form_fields as $curr_field_info) {
                if ($curr_field_info["field_id"] != $field_id) {
                    continue;
                }
                $detailed_field_info = $curr_field_info;
                break;
            }
            $params = array("form_id" => $form_id, "submission_id" => $submission_id, "value" => $field_info["content"], "field_info" => $detailed_field_info, "field_types" => $field_types, "settings" => $settings, "context" => "email_template");
            $value = ft_generate_viewable_field($params);
            $placeholders["ANSWER_{$field_name}"] = $value;
            // for backward compatibility
            if ($field_name == "core__submission_date") {
                $placeholders["SUBMISSIONDATE"] = $value;
            } else {
                if ($field_name == "core__last_modified") {
                    $placeholders["LASTMODIFIEDDATE"] = $value;
                } else {
                    if ($field_name == "core__ip_address") {
                        $placeholders["IPADDRESS"] = $value;
                    }
                }
            }
        }
    }
    // other misc placeholders
    $placeholders["ADMINEMAIL"] = $admin_info["email"];
    $placeholders["FORMNAME"] = $form_info["form_name"];
    $placeholders["FORMURL"] = $form_info["form_url"];
    $placeholders["SUBMISSIONID"] = $submission_id;
    $placeholders["LOGINURL"] = $g_root_url . "/index.php";
    if (!empty($client_info)) {
        $placeholders["EMAIL"] = $client_info["email"];
        $placeholders["FIRSTNAME"] = $client_info["first_name"];
        $placeholders["LASTNAME"] = $client_info["last_name"];
        $placeholders["COMPANYNAME"] = $client_info["company_name"];
    }
    extract(ft_process_hook_calls("end", compact("placeholders"), array("placeholders")), EXTR_OVERWRITE);
    return $placeholders;
}
Пример #9
0
/**
 * 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);
}
Пример #10
0
/**
 * Processes a form submission, either for a single page of a multi-page form or the entire form itself. If the
 * "submit_button_name key exists in $params (i.e. if the user just submitted the form), it updates the database for
 * the submission ID.
 *
 * Assumption: the ft_api_init_form_page function has been called on the page prior to calling this function.
 *
 * @param array $params
 *
 *     Required keys:
 *        "submit_button": the "name" attribute value of the form submit button
 *        "form_data": the contents of $_POST (or $_GET, if "method" setting is set to "GET" ... )
 *        "file_data": the contents of $_FILES (only needed if your form contained file fields)
 *
 *     Optional keys:
 *        "next_page": the URL (relative or absolute) of which page to redirect to (e.g. the next page
 *               in the form or the "thankyou" page).
 *        "finalize": this tells the function to finalize the submission. This prevents it being subsequently
 *               editable via this function and makes the submission appear in the Form Tools UI.
 *        "no_sessions_url": for multi-page forms it's a good idea to pass along this value. It should be the URL
 *               of a page (usually the FIRST page in the form sequence) where the user will be redirected to if
 *               they didn't start the form from the first page. It ensures the form submission gets created &
 *               submitted properly.
 *        "may_update_finalized_submissions": true / false (true by default)
 *        "namespace": if you specified a custom namespace for ft_api_init_form_page, for where the form values will
 *               be stored temporarily in sessions, you need to pass that same value to this function - otherwise
 *               it won't be able to retrieve the form and submission ID
 *        "send_emails": (boolean). By default, Form Tools will trigger any emails that have been attached to the
 *               "on submission" event ONLY when the submission is finalized (finalize=true). This setting provides
 *               you with direct control over when the emails get sent. If not specified, will use the default
 *               behaviour.
 *
 * @return mixed ordinarily, this function will just redirect the user to whatever URL is specified in the
 *        "next_page" key. But if that value isn't set, it returns an array:
 *               [0] success / false
 *               [1] if failure, the API Error Code, otherwise blank
 */
function ft_api_process_form($params)
{
    global $g_table_prefix, $g_multi_val_delimiter, $LANG, $g_api_debug, $g_api_recaptcha_private_key, $g_api_recaptcha_error;
    // the form data parameter must ALWAYS be defined
    if (!isset($params["form_data"])) {
        if ($g_api_debug) {
            $page_vars = array("message_type" => "error", "error_code" => 306, "error_type" => "user");
            ft_display_page("error.tpl", $page_vars);
            exit;
        } else {
            return array(false, 306);
        }
    }
    // special case: if "form_tools_delete_image_field__[fieldname]" exists, the user is just deleting an image
    // already uploaded through the form using the HTML generated by the ft_api_display_image_field function.
    // In this case, we process the page normally - even though the form data wasn't submitted & the page may
    // contain nothing in $form_data
    $is_deleting_file = false;
    $file_field_to_delete = "";
    $namespace = isset($params["namespace"]) ? $params["namespace"] : "form_tools_form";
    $form_id = isset($_SESSION[$namespace]["form_tools_form_id"]) ? $_SESSION[$namespace]["form_tools_form_id"] : "";
    $submission_id = isset($_SESSION[$namespace]["form_tools_submission_id"]) ? $_SESSION[$namespace]["form_tools_submission_id"] : "";
    while (list($key, $value) = each($params["form_data"])) {
        if (preg_match("/form_tools_delete_image_field__(.*)\$/", $key, $matches)) {
            $file_field_to_delete = $matches[1];
            $is_deleting_file = true;
            $field_id = ft_get_form_field_id_by_field_name($file_field_to_delete, $form_id);
            ft_delete_file_submission($form_id, $submission_id, $field_id, true);
            unset($_SESSION[$namespace][$file_field_to_delete]);
            unset($params["form_data"][$key]);
        }
    }
    // check the submission exists
    if (is_numeric($form_id) && is_numeric($submission_id) && !ft_check_submission_exists($form_id, $submission_id)) {
        if ($g_api_debug) {
            $page_vars = array("message_type" => "error", "error_code" => 305, "error_type" => "user", "debugging" => "{$LANG["phrase_submission_id"]}: {$submission_id}");
            ft_display_page("error.tpl", $page_vars);
            exit;
        } else {
            return array(false, 305);
        }
    }
    // extract the submission ID and form ID from sessions
    $form_data = $params["form_data"];
    $form_id = isset($_SESSION[$namespace]["form_tools_form_id"]) ? $_SESSION[$namespace]["form_tools_form_id"] : "";
    $submission_id = isset($_SESSION[$namespace]["form_tools_submission_id"]) ? $_SESSION[$namespace]["form_tools_submission_id"] : "";
    $has_captcha = isset($form_data["recaptcha_response_field"]) ? true : false;
    $no_sessions_url = isset($params["no_sessions_url"]) ? $params["no_sessions_url"] : false;
    if (!isset($_GET["ft_sessions_url_override"]) && (empty($form_id) || empty($submission_id))) {
        if (!empty($no_sessions_url)) {
            header("location: {$no_sessions_url}");
            exit;
        } else {
            if ($g_api_debug) {
                $page_vars = array("message_type" => "error", "error_code" => 300, "error_type" => "user");
                ft_display_page("error.tpl", $page_vars);
                exit;
            } else {
                return array(false, 300);
            }
        }
    }
    // if the user is neither deleting a file or making a regular form submission, it means they've just
    // arrived at the page. Cool! Do nothing!
    if (!$is_deleting_file && !isset($params["form_data"][$params["submit_button"]])) {
        return;
    }
    $submit_button_name = $params["submit_button"];
    $next_page = isset($params["next_page"]) ? $params["next_page"] : "";
    $file_data = isset($params["file_data"]) ? $params["file_data"] : array();
    $finalize = isset($params["finalize"]) ? $params["finalize"] : false;
    $namespace = isset($params["namespace"]) ? $params["namespace"] : "form_tools_form";
    $may_update_finalized_submissions = isset($params["may_update_finalized_submissions"]) ? $params["may_update_finalized_submissions"] : true;
    // if we're in test mode, we don't do anything with the database - just store the fields in
    // sessions to emulate
    if ($form_id == "test" || $submission_id == "test") {
        reset($form_data);
        while (list($field_name, $value) = each($form_data)) {
            $_SESSION[$namespace][$field_name] = $value;
        }
    } else {
        if (isset($_SESSION[$namespace]["form_tools_initialize_form"])) {
            // only process the form if this submission is being set to be finalized
            if ($finalize) {
                // if the user is just putting through a test submission and we've reached the finalization step,
                // overwrite $form_data with ALL the
                $all_form_data = array_merge($_SESSION[$namespace], $form_data);
                ft_initialize_form($all_form_data);
            }
            reset($form_data);
            while (list($field_name, $value) = each($form_data)) {
                $_SESSION[$namespace][$field_name] = $value;
            }
        } else {
            // check the form ID is valid
            if (!ft_check_form_exists($form_id)) {
                if ($g_api_debug) {
                    $page_vars = array("message_type" => "error", "error_code" => 301, "error_type" => "user");
                    ft_display_page("error.tpl", $page_vars);
                    exit;
                } else {
                    return array(false, 301);
                }
            }
            // check the submission ID isn't finalized
            if (!$may_update_finalized_submissions && ft_check_submission_finalized($form_id, $submission_id)) {
                if ($g_api_debug) {
                    $page_vars = array("message_type" => "error", "error_code" => 302, "error_type" => "user", "debugging" => "{$LANG["phrase_submission_id"]}: {$submission_id}");
                    ft_display_page("error.tpl", $page_vars);
                    exit;
                } else {
                    return array(false, 302);
                }
            }
            $form_info = ft_get_form($form_id);
            // 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;
                }
                if ($g_api_debug) {
                    $page_vars = array("message_type" => "error", "error_code" => 303, "error_type" => "user");
                    ft_display_page("error.tpl", $page_vars);
                    exit;
                } else {
                    return array(false, 303);
                }
            }
            // now we sanitize the data (i.e. get it ready for the DB query)
            $form_data = ft_sanitize($form_data);
            extract(ft_process_hook_calls("start", compact("form_info", "form_id", "form_data"), array("form_data")), EXTR_OVERWRITE);
            // 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 (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"];
            $is_finalized = $finalize ? "yes" : "no";
            $set_query = "";
            while (list($col_name, $value) = each($valid_form_fields)) {
                $set_query .= "{$col_name} = {$value},\n";
            }
            // in this section, we update the database submission info & upload files. Note: we don't do ANYTHING
            // if the form_tools_ignore_submission key is set in the POST data
            if (!isset($form_data["form_tools_ignore_submission"])) {
                // construct our query. Note that we do TWO queries: one if there was no CAPTCHA sent with this
                // post (which automatically finalizes the result), and one if there WAS. For the latter, the submission
                // is finalized later
                if ($has_captcha && $finalize) {
                    $query = "\n          UPDATE {$g_table_prefix}form_{$form_id}\n          SET    {$set_query}\n                 last_modified_date = '{$now}',\n                 ip_address = '{$ip_address}'\n          WHERE  submission_id = {$submission_id}\n            ";
                } else {
                    // only update the is_finalized setting if $may_update_finalized_submissions === false
                    if (!$finalize && $may_update_finalized_submissions) {
                        $is_finalized_clause = "";
                    } else {
                        $is_finalized_clause = ", is_finalized = '{$is_finalized}'";
                    }
                    $query = "\n          UPDATE {$g_table_prefix}form_{$form_id}\n          SET    {$set_query}\n                 last_modified_date = '{$now}',\n                 ip_address = '{$ip_address}'\n                 {$is_finalized_clause}\n          WHERE  submission_id = {$submission_id}\n            ";
                }
                // only process the query if the form_tools_ignore_submission key isn't defined
                if (!mysql_query($query)) {
                    if ($g_api_debug) {
                        $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;
                    } else {
                        return array(false, 304);
                    }
                }
                // used for uploading files. The error handling is incomplete here, like previous versions. Although the hooks
                // are permitted to return values, they're not used
                extract(ft_process_hook_calls("manage_files", compact("form_id", "submission_id", "file_fields", "namespace"), array("success", "message")), EXTR_OVERWRITE);
            }
            // store all the info in sessions
            reset($form_data);
            while (list($field_name, $value) = each($form_data)) {
                $_SESSION[$namespace][$field_name] = $value;
            }
        }
    }
    // was there a reCAPTCHA response? If so, a recaptcha was just submitted, check it was entered correctly
    $passes_captcha = true;
    if ($has_captcha) {
        $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}/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;
            // if the developer wanted the submission to be finalized at this step, do so - it wasn't earlier!
            if ($finalize) {
                mysql_query("\n          UPDATE {$g_table_prefix}form_{$form_id}\n          SET    is_finalized = 'yes'\n          WHERE  submission_id = {$submission_id}\n            ");
            }
        } else {
            // register the recaptcha as a global, which can be picked up silently by ft_api_display_captcha to
            // let them know they entered it wrong
            $g_api_recaptcha_error = $resp->error;
        }
    }
    if ($passes_captcha && !empty($next_page) && !$is_deleting_file) {
        // if the user wasn't putting through a test submission or initializing the form, we can send safely
        // send emails at this juncture, but ONLY if it was just finalized OR if the send_emails parameter
        // allows for it
        if ($form_id != "test" && $submission_id != "test" && !isset($_SESSION[$namespace]["form_tools_initialize_form"]) && !isset($form_data["form_tools_ignore_submission"])) {
            // send any emails attached to the on_submission trigger
            if (isset($params["send_emails"]) && $params["send_emails"] === true) {
                ft_send_emails("on_submission", $form_id, $submission_id);
            } else {
                if ($is_finalized == "yes" && (!isset($params["send_emails"]) || $params["send_emails"] !== false)) {
                    ft_send_emails("on_submission", $form_id, $submission_id);
                }
            }
        }
        header("location: {$next_page}");
        exit;
    }
    return array(true, "");
}
Пример #11
0
/**
 * This returns all forms and form Views that a client account may access.
 *
 * @param array $account_id
 */
function ft_get_client_form_views($account_id)
{
    $client_forms = ft_search_forms($account_id);
    $info = array();
    foreach ($client_forms as $form_info) {
        $form_id = $form_info["form_id"];
        $views = ft_get_form_views($form_id, $account_id);
        $view_ids = array();
        foreach ($views as $view_info) {
            $view_ids[] = $view_info["view_id"];
        }
        $info[$form_id] = $view_ids;
    }
    extract(ft_process_hook_calls("end", compact("account_id", "info"), array("info")), EXTR_OVERWRITE);
    return $info;
}
Пример #12
0
/**
 * A very simple getter function that retrieves an an ordered array of view_id => view name hashes for a
 * particular form.
 *
 * @param integer $form_id
 * @return array
 */
function ft_get_view_list($form_id)
{
    global $g_table_prefix;
    $query = mysql_query("\r\n    SELECT view_id, view_name\r\n    FROM   {$g_table_prefix}views\r\n    WHERE  form_id = {$form_id}\r\n    ORDER BY view_order\r\n      ") or dir(mysql_error());
    $result = array();
    while ($row = mysql_fetch_assoc($query)) {
        $result[] = $row;
    }
    extract(ft_process_hook_calls("end", compact("form_id", "result"), array("result")), EXTR_OVERWRITE);
    return $result;
}
Пример #13
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;
}
Пример #14
0
/**
 * Deletes a file that has been uploaded through a particular form submission file field.
 *
 * Now say that 10 times fast.
 *
 * @param integer $form_id the unique form ID
 * @param integer $submission_id a unique submission ID
 * @param integer $field_id a unique form field ID
 * @param boolean $force_delete this forces the file to be deleted from the database, even if the
 *                file itself doesn't exist or doesn't have the right permissions.
 * @return array Returns array with indexes:<br/>
 *               [0]: true/false (success / failure)<br/>
 *               [1]: message string<br/>
 */
function ft_file_delete_file_submission($form_id, $submission_id, $field_id, $force_delete = false)
{
    global $g_table_prefix, $LANG;
    // get the column name and upload folder for this field
    $field_info = ft_get_form_field($field_id);
    $col_name = $field_info["col_name"];
    // if the column name wasn't found, the $field_id passed in was invalid. Return false.
    if (empty($col_name)) {
        return array(false, $LANG["notify_submission_no_field_id"]);
    }
    $field_settings = ft_get_field_settings($field_id);
    $file_folder = $field_settings["folder_path"];
    $query = "\n    SELECT {$col_name}\n    FROM   {$g_table_prefix}form_{$form_id}\n    WHERE  submission_id = {$submission_id}\n            ";
    $result = mysql_query($query);
    $file_info = mysql_fetch_row($result);
    $file = $file_info[0];
    $update_database_record = false;
    $success = true;
    $message = "";
    if (!empty($file)) {
        if ($force_delete) {
            @unlink("{$file_folder}/{$file}");
            $message = $LANG["notify_file_deleted"];
            $update_database_record = true;
        } else {
            if (@unlink("{$file_folder}/{$file}")) {
                $success = true;
                $message = $LANG["notify_file_deleted"];
                $update_database_record = true;
            } else {
                if (!is_file("{$file_folder}/{$file}")) {
                    $success = false;
                    $update_database_record = false;
                    $replacements = array("js_link" => "return files_ns.delete_submission_file({$field_id}, true)");
                    $message = ft_eval_smarty_string($LANG["notify_file_not_deleted_no_exist"] . "({$file_folder}/{$file})", $replacements);
                } else {
                    if (is_file("{$file_folder}/{$file}") && (!is_readable("{$file_folder}/{$file}") || !is_writable("{$file_folder}/{$file}"))) {
                        $success = false;
                        $update_database_record = false;
                        $replacements = array("js_link" => "return files_ns.delete_submission_file({$field_id}, true)");
                        $message = ft_eval_smarty_string($LANG["notify_file_not_deleted_permissions"], $replacements);
                    } else {
                        $success = false;
                        $update_database_record = false;
                        $replacements = array("js_link" => "return files_ns.delete_submission_file({$field_id}, true)");
                        $message = ft_eval_smarty_string($LANG["notify_file_not_deleted_unknown_error"], $replacements);
                    }
                }
            }
        }
    }
    // if need be, update the database record to remove the reference to the file in the database. Generally this
    // should always work, but in case something funky happened, like the permissions on the file were changed to
    // forbid deleting, I think it's best if the record doesn't get deleted to remind the admin/client it's still
    // there.
    if ($update_database_record) {
        $query = mysql_query("\n      UPDATE {$g_table_prefix}form_{$form_id}\n      SET    {$col_name} = ''\n      WHERE  submission_id = {$submission_id}\n             ");
    }
    extract(ft_process_hook_calls("end", compact("form_id", "submission_id", "field_id", "force_delete"), array("success", "message")), EXTR_OVERWRITE);
    return array($success, $message);
}
Пример #15
0
/**
 * Deletes an option list from the database. Note: it only deletes lists that don't have any
 * form fields assigned to them; generally this is prevented from being called unless that condition is
 * met, but it also checks here just in case.
 *
 * @param integer $list_id
 * @return array [0] T/F<br />
 *               [1] error/success message
 */
function ft_delete_option_list($list_id)
{
    global $g_table_prefix, $LANG;
    // slight behavioural change in 2.1.0. Now you CAN delete Option Lists that are used by one or more fields.
    // It just clears any references, thus leaving those fields incompletely configured (which isn't the end of
    // the world!)
    $fields = ft_get_fields_using_option_list($list_id);
    foreach ($fields as $field_info) {
        $field_id = $field_info["field_id"];
        $field_type_id = $field_info["field_type_id"];
        $settings = ft_get_field_type_settings($field_type_id);
        $setting_ids = array();
        foreach ($settings as $setting_info) {
            if ($setting_info["field_type"] == "option_list_or_form_field") {
                $setting_ids[] = $setting_info["setting_id"];
            }
        }
        if (empty($setting_ids)) {
            continue;
        }
        $setting_id_str = implode(",", $setting_ids);
        // now we delete any entries in the field_settings table with field_id, setting_id and a NUMERIC value for the
        // setting_value column. That column is also
        mysql_query("\n      DELETE FROM {$g_table_prefix}field_settings\n      WHERE field_id = {$field_id} AND\n            setting_id IN ({$setting_id_str}) AND\n            setting_value NOT LIKE 'form_field%'\n    ");
    }
    mysql_query("DELETE FROM {$g_table_prefix}field_options WHERE list_id = {$list_id}");
    mysql_query("DELETE FROM {$g_table_prefix}option_lists WHERE list_id = {$list_id}");
    mysql_query("DELETE FROM {$g_table_prefix}list_groups WHERE group_type = 'option_list_{$list_id}'");
    $success = true;
    $message = $LANG["notify_option_list_deleted"];
    extract(ft_process_hook_calls("end", compact("list_id"), array("success", "message")), EXTR_OVERWRITE);
    return array(true, $message);
}
Пример #16
0
/**
 * Updates any number of settings for a particular user account. As with the similar ft_set_settings
 * function, it creates the record if it doesn't already exist.
 *
 * @param integer $account_id
 * @param array $settings a hash of setting name => setting value.
 */
function ft_set_account_settings($account_id, $settings)
{
    global $g_table_prefix;
    extract(ft_process_hook_calls("start", compact("account_id", "settings"), array("settings")), EXTR_OVERWRITE);
    while (list($setting_name, $setting_value) = each($settings)) {
        // find out if it already exists
        $result = mysql_query("\r\n      SELECT count(*) as c\r\n      FROM   {$g_table_prefix}account_settings\r\n      WHERE  setting_name = '{$setting_name}' AND\r\n             account_id = {$account_id}\r\n        ");
        $info = mysql_fetch_assoc($result);
        if ($info["c"] == 0) {
            mysql_query("\r\n        INSERT INTO {$g_table_prefix}account_settings (account_id, setting_name, setting_value)\r\n        VALUES ({$account_id}, '{$setting_name}', '{$setting_value}')\r\n          ");
        } else {
            mysql_query("\r\n        UPDATE {$g_table_prefix}account_settings\r\n        SET    setting_value = '{$setting_value}'\r\n        WHERE  setting_name  = '{$setting_name}' AND\r\n               account_id = {$account_id}\r\n          ");
        }
    }
    extract(ft_process_hook_calls("end", compact("account_id", "settings"), array()), EXTR_OVERWRITE);
}
Пример #17
0
/**
 * Added in 2.1.0. This lets modules add an icon to a "quicklink" icon row on the Submission Listing page. To add it,
 * they need to define a hook call and return a $quicklinks hash with the following keys:
 *   icon_url
 *   alt_text
 *
 * @param $context "admin" or "client"
 */
function ft_display_submission_listing_quicklinks($context, $page_data)
{
    global $g_root_url;
    $quicklinks = array();
    extract(ft_process_hook_calls("main", compact("context"), array("quicklinks"), array("quicklinks")), EXTR_OVERWRITE);
    if (empty($quicklinks)) {
        return "";
    }
    echo "<ul id=\"ft_quicklinks\">";
    $num_quicklinks = count($quicklinks);
    for ($i = 0; $i < $num_quicklinks; $i++) {
        $classes = array();
        if ($i == 0) {
            $classes[] = "ft_quicklinks_first";
        }
        if ($i == $num_quicklinks - 1) {
            $classes[] = "ft_quicklinks_last";
        }
        $class = implode(" ", $classes);
        $quicklink_info = $quicklinks[$i];
        $icon_url = isset($quicklink_info["icon_url"]) ? $quicklink_info["icon_url"] : "";
        $title_text = isset($quicklink_info["title_text"]) ? $quicklink_info["title_text"] : "";
        $onclick = isset($quicklink_info["onclick"]) ? $quicklink_info["onclick"] : "";
        $title_text = htmlspecialchars($title_text);
        if (empty($icon_url)) {
            continue;
        }
        echo "<li class=\"{$class}\" onclick=\"{$onclick}\"><img src=\"{$icon_url}\" title=\"{$title_text}\" /></li>\n";
    }
    echo "</ul>";
}
Пример #18
0
/**
 * Added in 2.1.6, to allow for simple "inline" hook overriding from within the PHP pages.
 *
 * @param string $location
 * @param mixed $data
 */
function ft_module_override_data($location, $data)
{
    extract(ft_process_hook_calls("start", compact("location", "data"), array("data")), EXTR_OVERWRITE);
    return $data;
}