Пример #1
0
/**
 * Adds new form field(s) to the database. This was totally re-written in 2.1.0, for the new Edit Fields
 * page.
 *
 * @param integer $infohash a hash containing the contents of the Edit Form Advanced -> Add Fields page.
 * @param integer $form_id The unique form ID
 * @return array Returns array with indexes:<br/>
 *               [0]: true/false (success / failure)<br/>
 *               [1]: message string<br/>
 */
function ft_add_form_fields($form_id, $fields)
{
    global $g_debug, $g_table_prefix, $LANG, $g_field_sizes;
    $success = true;
    $message = "";
    $fields = ft_sanitize($fields);
    foreach ($fields as $field_info) {
        $field_name = $field_info["form_field_name"];
        $field_size = $field_info["field_size"];
        $field_type_id = $field_info["field_type_id"];
        $display_name = $field_info["display_name"];
        $include_on_redirect = $field_info["include_on_redirect"];
        $list_order = $field_info["list_order"];
        $col_name = $field_info["col_name"];
        $is_new_sort_group = $field_info["is_new_sort_group"];
        // in order for the field to be added, it needs to have the label, name, size and column name. Otherwise they're
        // ignored
        if (empty($display_name) || empty($field_name) || empty($field_size) || empty($col_name)) {
            continue;
        }
        // add the new field to form_fields
        $query = "\n      INSERT INTO {$g_table_prefix}form_fields (form_id, field_name, field_size, field_type_id,\n        data_type, field_title, col_name, list_order, is_new_sort_group, include_on_redirect)\n      VALUES ({$form_id}, '{$field_name}', '{$field_size}', {$field_type_id},\n        'string', '{$display_name}', '{$col_name}', {$list_order}, '{$is_new_sort_group}', '{$include_on_redirect}')\n    ";
        $result = mysql_query($query) or ft_handle_error("Failed query in <b>" . __FUNCTION__ . "</b>, line " . __LINE__ . ": <i>{$query}</i>", mysql_error());
        $new_field_id = mysql_insert_id();
        $new_field_size = $g_field_sizes[$field_size]["sql"];
        list($is_success, $err_message) = _ft_add_table_column("{$g_table_prefix}form_{$form_id}", $col_name, $new_field_size);
        // if the alter table didn't work, return with an error message and remove the entry we just added to the form_fields table
        if (!$is_success) {
            if (!empty($new_field_id) && is_numeric($new_field_id)) {
                mysql_query("\n          DELETE FROM {$g_table_prefix}form_fields\n          WHERE field_id = {$new_field_id}\n          LIMIT 1\n        ");
            }
            $success = false;
            $replacement_info = array("fieldname" => $field_name);
            $message = ft_eval_smarty_string($LANG["notify_form_field_not_added"], $replacement_info);
            if ($g_debug) {
                $message .= " <i>\"{$err_message}\"</i>";
            }
            return array($success, $message);
        }
    }
    extract(ft_process_hook_calls("end", compact("infohash", "form_id"), array("success", "message")), EXTR_OVERWRITE);
    return array($success, $message);
}
Пример #2
0
/**
 * Retrieves all information about any user account (administrator or client).
 *
 * @param integer $user_id the unique account ID
 * @return array returns a hash of all pertinent data.
 */
function ft_get_account_info($account_id)
{
    global $g_table_prefix;
    $query = "\r\n    SELECT  *\r\n    FROM    {$g_table_prefix}accounts\r\n    WHERE   account_id = {$account_id}\r\n           ";
    $result = mysql_query($query) or ft_handle_error("Failed query in <b>" . __FUNCTION__ . "</b>: <i>{$query}</i>", mysql_error());
    $account_info = mysql_fetch_assoc($result);
    if (empty($account_info)) {
        return array();
    }
    // also extract any account-specific settings from account_settings
    $query = mysql_query("SELECT * FROM {$g_table_prefix}account_settings WHERE account_id = {$account_id}");
    $settings = array();
    while ($row = mysql_fetch_assoc($query)) {
        $settings[$row["setting_name"]] = $row["setting_value"];
    }
    $account_info["settings"] = $settings;
    extract(ft_process_hook_calls("main", compact("account_info"), array("account_info")), EXTR_OVERWRITE);
    return $account_info;
}
Пример #3
0
/**
 * Creates and returns a search for any form View, and any subset of its columns, returning results in
 * any column order and for any single page subset (or all pages). The final $search_columns parameter
 * was added most recently to fix bug #173. That parameter lets the caller differentiate between the
 * columns being returned ($columns param) and columns to be searched ($search_columns).
 *
 * @param integer $form_id the unique form ID
 * @param integer $view_id the unique View ID
 * @param mixed $results_per_page an integer, or "all".
 * @param integer $page_num The current page number - or empty string, if this function is returning all
 *              results in one page (e.g. printer friendly page).
 * @param string $order A string of form: "{db column}_{ASC|DESC}"
 * @param mixed $columns An array containing which database columns to search and return, or a string:
 *              "all" - which returns all columns in the form.
 * @param array $search_fields an optional hash with these keys:<br/>
 *                  search_field<br/>
 *                  search_date<br/>
 *                  search_keyword<br/>
 * @param array submission_ids - an optional array containing a list of submission IDs to return.
 *     This may seem counterintuitive to pass the results that it needs to return to the function that
 *     figures out WHICH results to return, but it's actually kinda handy: this function returns exactly
 *     the field information that's needed in the order that's needed.
 * @param array $submission_ids an optional array of submission IDs to return
 * @param array $search_columns an optional array determining which database columns should be included
 *     in the search. Note: this is different from the $columns parameter which just determines which
 *     database columns will be returned. If it's not defined, it's just set to $columns.
 *
 * @return array returns a hash with these keys:<br/>
 *                ["search_query"]       => an array of hashes, each index a search result row<br />
 *                ["search_num_results"] => the number of results in the search (not just the 10 or so
 *                                          that will appear in the current page, listed in the
 *                                          "search_query" key<br />
 *                ["view_num_results"]   => the total number of results in this View, regardless of the
 *                                          current search values.
 */
function ft_search_submissions($form_id, $view_id, $results_per_page, $page_num, $order, $columns_to_return, $search_fields = array(), $submission_ids = array(), $searchable_columns = array())
{
    global $g_table_prefix;
    // for backward compatibility
    if (empty($searchable_columns)) {
        $searchable_columns = $columns_to_return;
    }
    // determine the various SQL clauses for the searches
    $order_by = _ft_get_search_submissions_order_by_clause($form_id, $order);
    $limit_clause = _ft_get_limit_clause($page_num, $results_per_page);
    $select_clause = _ft_get_search_submissions_select_clause($columns_to_return);
    $filter_clause = _ft_get_search_submissions_view_filter_clause($view_id);
    $submission_id_clause = _ft_get_search_submissions_submission_id_clause($submission_ids);
    $search_where_clause = _ft_get_search_submissions_search_where_clause($form_id, $search_fields, $searchable_columns);
    // (1) our main search query that returns a PAGE of submission info
    $search_query = "\n      SELECT {$select_clause}\n      FROM   {$g_table_prefix}form_{$form_id}\n      WHERE  is_finalized = 'yes'\n             {$search_where_clause}\n             {$filter_clause}\n             {$submission_id_clause}\n      ORDER BY {$order_by}\n             {$limit_clause}\n  ";
    $search_result = mysql_query($search_query) or ft_handle_error("Failed query in <b>" . __FUNCTION__ . "</b>; Query: {$search_query}; Error: ", mysql_error());
    $search_result_rows = array();
    while ($row = mysql_fetch_assoc($search_result)) {
        $search_result_rows[] = $row;
    }
    // (2) find out how many results there are in this current search
    $search_results_count_query = mysql_query("\n      SELECT count(*) as c\n      FROM   {$g_table_prefix}form_{$form_id}\n      WHERE  is_finalized = 'yes'\n             {$search_where_clause}\n             {$filter_clause}\n             {$submission_id_clause}\n                 ") or ft_handle_error("Failed query in <b>" . __FUNCTION__ . "</b>: ", mysql_error());
    $search_num_results_info = mysql_fetch_assoc($search_results_count_query);
    $search_num_results = $search_num_results_info["c"];
    // (3) find out how many results should appear in the View, regardless of the current search criteria
    $view_results_count_query = mysql_query("\n      SELECT count(*) as c\n      FROM   {$g_table_prefix}form_{$form_id}\n      WHERE  is_finalized = 'yes'\n             {$filter_clause}\n                 ") or ft_handle_error("Failed query in <b>" . __FUNCTION__ . "</b>: ", mysql_error());
    $view_num_results_info = mysql_fetch_assoc($view_results_count_query);
    $view_num_results = $view_num_results_info["c"];
    $return_hash["search_rows"] = $search_result_rows;
    $return_hash["search_num_results"] = $search_num_results;
    $return_hash["view_num_results"] = $view_num_results;
    extract(ft_process_hook_calls("end", compact("form_id", "submission_id", "view_id", "results_per_page", "page_num", "order", "columns", "search_fields", "submission_ids", "return_hash"), array("return_hash")), EXTR_OVERWRITE);
    return $return_hash;
}
Пример #4
0
/**
 * This function is called whenever the user adds an option list through the Add External form process. It checks
 * all existing option lists to see if an identical set already exists. If it does, it returns the existing
 * option list ID and if not, creates a new one and returns that ID.
 *
 * @param integer $form_id
 * @param array $option_list_info
 * @return integer $list_id the new or existing option list ID
 */
function ft_create_unique_option_list($form_id, $option_list_info)
{
    global $g_table_prefix;
    $existing_option_lists = ft_get_option_lists("all");
    $already_exists = false;
    $list_id = "";
    foreach ($existing_option_lists["results"] as $existing_option_list) {
        $curr_list_id = $existing_option_list["list_id"];
        // when comparing field groups, just compare the actual field options. The option list name & original
        // form aren't considered. This may lead to a little head-shaking in the UI when they see an inappropriate
        // option list name, but it's easily changed
        $grouped_option_list_info = ft_get_option_list_options($curr_list_id);
        // $curr_options contains an array of hashes. Each hash contains information about the group & info about
        // the options in that group. Since we're just comparing a brand new list, we know that it only has one group:
        // hence, rule out those option lists with more than one group
        if (count($grouped_option_list_info) > 1) {
            continue;
        }
        // fringe case. Technically, a user may have created an Option List then deleted all options & groups.
        if (count($grouped_option_list_info) == 0) {
            continue;
        }
        $curr_options = $grouped_option_list_info[0]["options"];
        if (count($curr_options) != count($option_list_info["options"])) {
            continue;
        }
        $has_same_option_fields = true;
        for ($i = 0; $i < count($curr_options); $i++) {
            $val = ft_sanitize($curr_options[$i]["option_value"]);
            $txt = ft_sanitize($curr_options[$i]["option_name"]);
            $val2 = $option_list_info["options"][$i]["value"];
            $txt2 = $option_list_info["options"][$i]["text"];
            if ($val != $val2 || $txt != $txt2) {
                $has_same_option_fields = false;
                break;
            }
        }
        if (!$has_same_option_fields) {
            continue;
        }
        $already_exists = true;
        $list_id = $curr_list_id;
        break;
    }
    // if this group didn't already exist, add it!
    if (!$already_exists) {
        $option_list_name = $option_list_info["option_list_name"];
        $query = "INSERT INTO {$g_table_prefix}option_lists (option_list_name, is_grouped, original_form_id)\n      VALUES ('{$option_list_name}', 'no', {$form_id})";
        $result = mysql_query($query) or ft_handle_error($query, mysql_error());
        if (!$result) {
            return false;
        }
        $list_id = mysql_insert_id();
        // now add the list group entry
        $query = mysql_query("\n      INSERT INTO {$g_table_prefix}list_groups (group_type, list_order)\n      VALUES ('option_list_{$list_id}', 1)\n    ") or die(mysql_error());
        $list_group_id = mysql_insert_id();
        // add the options
        $order = 1;
        foreach ($option_list_info["options"] as $option) {
            $value = ft_sanitize($option["value"]);
            $text = ft_sanitize($option["text"]);
            $query = "\n        INSERT INTO {$g_table_prefix}field_options (list_id, list_group_id, option_value, option_name, option_order)\n        VALUES ({$list_id}, {$list_group_id}, '{$value}', '{$text}', {$order})\n          ";
            $result = mysql_query($query) or ft_handle_error($query, mysql_error());
            $order++;
        }
    }
    return $list_id;
}
Пример #5
0
/**
 * Caches the total number of (finalized) submissions in a particular form - or all forms -
 * in the $_SESSION["ft"]["form_{$form_id}_num_submissions"] key. That value is used on the administrators
 * main Forms page to list the form submission count.
 *
 * @param integer $form_id
 */
function _ft_cache_form_stats($form_id = "")
{
    global $g_table_prefix;
    $where_clause = "";
    if (!empty($form_id)) {
        $where_clause = "AND form_id = {$form_id}";
    }
    $query = mysql_query("\n    SELECT form_id\n    FROM   {$g_table_prefix}forms\n    WHERE  is_complete = 'yes'\n    {$where_clause}\n          ");
    // loop through all forms, extract the submission count and first submission date
    while ($form_info = mysql_fetch_assoc($query)) {
        $form_id = $form_info["form_id"];
        $count_query = mysql_query("\n      SELECT count(*) as c\n      FROM   {$g_table_prefix}form_{$form_id}\n      WHERE  is_finalized = 'yes'\n        ") or ft_handle_error("Failed query in <b>" . __FUNCTION__ . "</b>, line " . __LINE__, mysql_error());
        $info = mysql_fetch_assoc($count_query);
        $_SESSION["ft"]["form_{$form_id}_num_submissions"] = $info["c"];
    }
}
Пример #6
0
<?php

require "../../global/session_start.php";
// this just checks that SOMEONE's logged in - even someone via the Submission Accounts module
ft_check_permission("user");
ft_include_module("pages");
$request = array_merge($_POST, $_GET);
$page_id = $request["id"];
$page_info = pg_get_page($page_id);
// check permissions! The above code handles booting a user out if they're not logged in,
// so the only case we're worried about
$account_type = isset($_SESSION["ft"]["account"]["account_type"]) ? $_SESSION["ft"]["account"]["account_type"] : "";
$account_id = isset($_SESSION["ft"]["account"]["account_id"]) ? $_SESSION["ft"]["account"]["account_id"] : "";
if ($account_type == "client" && $page_info["access_type"] == "private") {
    if (!in_array($account_id, $page_info["clients"])) {
        ft_handle_error("Sorry, you do not have permissions to see this page.");
        exit;
    }
}
$content = $page_info["content"];
switch ($page_info["content_type"]) {
    case "php":
        ob_start();
        eval($page_info["content"]);
        $content = ob_get_contents();
        ob_end_clean();
        break;
    case "smarty":
        $content = ft_eval_smarty_string($page_info["content"]);
        break;
}
Пример #7
0
// if the form ID is specified in GET or POST, store it in sessions as curr_form_id
$form_id = ft_load_field("form_id", "curr_form_id");
if (empty($form_id)) {
    session_write_close();
    header("location: index.php");
    exit;
}
$view_id = ft_load_field("view_id", "form_{$form_id}_view_id");
// check the current client is permitted to view this information!
ft_check_client_may_view($account_id, $form_id, $view_id);
// this returns all and ONLY the Views accessible by this client
$grouped_views = ft_get_grouped_views($form_id, array("omit_hidden_views" => true, "omit_empty_groups" => true, "account_id" => $account_id));
if (empty($view_id) || !ft_check_view_exists($view_id, true)) {
    if (count($grouped_views[0]["views"]) == 0) {
        // no Views defined for this client
        ft_handle_error($LANG["notify_no_views_assigned_to_client_form"], "", "notify");
        exit;
    } else {
        $view_id = $grouped_views[0]["views"][0]["view_id"];
    }
}
$_SESSION["ft"]["form_{$form_id}_view_id"] = $view_id;
$form_info = ft_get_form($form_id);
$view_info = ft_get_view($view_id);
if (isset($_GET["add_submission"]) && $view_info["may_add_submissions"] == "yes") {
    $submission_id = ft_create_blank_submission($form_id, $view_id, true);
    header("location: edit_submission.php?form_id={$form_id}&view_id={$view_id}&submission_id={$submission_id}");
    exit;
}
// if the View just changed (i.e. it was just selected by the user), deselect any items in
// this form
Пример #8
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);
}
Пример #9
0
/**
 * Retrieves a list of all clients in the database ordered by last name. N.B. As of 2.0.0, this function
 * no longer returns a MySQL resource.
 *
 * @return array $clients an array of hashes. Each hash is the client info.
 */
function ft_get_client_list()
{
    global $g_table_prefix;
    $query = "SELECT * FROM {$g_table_prefix}accounts WHERE account_type = 'client' ORDER BY last_name";
    $result = mysql_query($query) or ft_handle_error("Failed query in <b>" . __FUNCTION__ . "</b>: <i>{$query}</i>", mysql_error());
    $clients = array();
    while ($client = mysql_fetch_assoc($result)) {
        $clients[] = $client;
    }
    return $clients;
}
Пример #10
0
/**
 * Caches the total number of (finalized) submissions in a particular form - or all forms -
 * in the $_SESSION["ft"]["form_{$form_id}_num_submissions"] key. That value is used on the administrators
 * main Forms page to list the form submission count.
 *
 * @param integer $form_id
 */
function _ft_cache_view_stats($form_id, $view_id = "")
{
    global $g_table_prefix;
    $view_ids = array();
    if (empty($view_id)) {
        $view_ids = ft_get_view_ids($form_id);
    } else {
        $view_ids[] = $view_id;
    }
    foreach ($view_ids as $view_id) {
        $filters = ft_get_view_filter_sql($view_id);
        // if there aren't any filters, just set the submission count & first submission date to the same
        // as the parent form
        if (empty($filters)) {
            $_SESSION["ft"]["view_{$view_id}_num_submissions"] = $_SESSION["ft"]["form_{$form_id}_num_submissions"];
        } else {
            $filter_clause = join(" AND ", $filters);
            $count_query = mysql_query("\r\n        SELECT count(*) as c\r\n        FROM   {$g_table_prefix}form_{$form_id}\r\n        WHERE  is_finalized = 'yes' AND\r\n        {$filter_clause}\r\n          ") or ft_handle_error("Failed query in <b>" . __FUNCTION__ . "</b>, line " . __LINE__, mysql_error());
            $info = mysql_fetch_assoc($count_query);
            $_SESSION["ft"]["view_{$view_id}_num_submissions"] = $info["c"];
        }
    }
}
Пример #11
0
<?php

require "../../global/session_start.php";
ft_check_permission("admin");
$request = array_merge($_POST, $_GET);
// if the form ID is specified in GET or POST, store it in sessions as curr_form_id
$form_id = ft_load_field("form_id", "curr_form_id");
if (empty($form_id) || !is_numeric($form_id)) {
    session_write_close();
    header("location: index.php");
    exit;
}
// check this is a valid form
if (!ft_check_form_exists($form_id)) {
    ft_handle_error($LANG["notify_form_does_not_exist"]);
    exit;
}
// next, get the View. If it's not defined, the user has just arrives at the page. We grab the first View in
// (ordered) list of Views for this form. If THAT doesn't exist, the user has deleted all Views (doh!), so
// there's nothing to show. In that case, just redirect them to the Views tab, where an error / warning message
// will appear in the page
$view_id = ft_load_field("view_id", "form_{$form_id}_view_id");
$grouped_views = ft_get_grouped_views($form_id, array("omit_hidden_views" => true, "omit_empty_groups" => true));
if (empty($view_id) || !ft_check_view_exists($view_id, true)) {
    // here, we know that the first View group has at least one item. [hmm...]
    if (count($grouped_views[0]["views"]) == 0) {
        // no Views defined for this form! redirect to the Views page and display a message
        header("location: edit.php?page=views&form_id={$form_id}&message=no_views");
        exit;
    } else {
        $view_id = $grouped_views[0]["views"][0]["view_id"];