function smarty_function_display_account_name($params, &$smarty) { $account_id = isset($params["account_id"]) ? $params["account_id"] : ""; $format = isset($params["format"]) ? $params["format"] : "first_last"; // first_last, or last_first if (empty($account_id)) { return; } $account_info = ft_get_account_info($account_id); if ($format == "first_last") { $html = "{$account_info["first_name"]} {$account_info["last_name"]}"; } else { $html = "{$account_info["last_name"]}, {$account_info["first_name"]}"; } return $html; }
// if this user is already logged in, redirect them to their specified login page if (isset($_SESSION["ft"]["account"]) && isset($_SESSION["ft"]["account"]["is_logged_in"]) && isset($_SESSION["ft"]["account"]["login_page"]) && $_SESSION["ft"]["account"]["is_logged_in"] == 1) { $login_page = $_SESSION["ft"]["account"]["login_page"]; $page = ft_construct_page_url($login_page); header("location: {$g_root_url}{$page}"); exit; } // default settings $settings = ft_get_settings(); $g_theme = $settings["default_theme"]; $g_swatch = $settings["default_client_swatch"]; // if an account id is included in the query string, use it to determine the appearance of the // interface, including logo and footer and even language $id = ft_load_field("id", "id", ""); if (!empty($id)) { $info = ft_get_account_info($id); if (isset($info["account_id"])) { // just in case, boot up the appropriate language file (this overrides any language file already loaded) $g_theme = $info["theme"]; $language = $info["ui_language"]; if (!empty($language) && is_file("global/lang/{$language}.php")) { include_once "global/lang/{$language}.php"; } } } $error = ""; if (isset($_POST["username"]) && !empty($_POST["username"])) { $error = ft_login($_POST); } $username = isset($_POST["username"]) && !empty($_POST["username"]) ? $_POST["username"] : ""; $username = ft_strip_chars($username);
<?php if (isset($request["update_account_settings"])) { $account_id = $_SESSION["ft"]["account"]["account_id"]; $request["page"] = "settings"; list($g_success, $g_message) = ft_update_client($account_id, $request); } $client_info = ft_get_account_info($account_id); // compile header information $page_vars = array(); $page_vars["head_title"] = ft_eval_smarty_string($_SESSION["ft"]["account"]["settings"]["page_titles"], array("page" => $LANG["phrase_account_settings"])); $page_vars["page"] = "settings"; $page_vars["tabs"] = $tabs; $page_vars["client_info"] = $client_info; $page_vars["page_url"] = ft_get_page_url("client_account_settings"); $js = array("var rules = []"); if ($client_info["settings"]["may_edit_page_titles"] == "yes") { $js[] = "rules.push(\"required,page_titles,{$LANG["validation_no_titles"]}\")"; } if ($client_info["settings"]["may_edit_theme"] == "yes") { $js[] = "rules.push(\"required,theme,{$LANG["validation_no_theme"]}\")"; $js[] = "rules.push(\"function,validate_swatch\")"; } if ($client_info["settings"]["may_edit_logout_url"] == "yes") { $js[] = "rules.push(\"required,logout_url,{$LANG["validation_no_logout_url"]}\")"; } if ($client_info["settings"]["may_edit_language"] == "yes") { $js[] = "rules.push(\"required,ui_language,{$LANG["validation_no_ui_language"]}\")"; } if ($client_info["settings"]["may_edit_timezone_offset"] == "yes") { $js[] = "rules.push(\"required,timezone_offset,{$LANG["validation_no_timezone_offset"]}\")";
/** * Returns an array of hashes. Each hash contains the contents of the email_template_recipients table; i.e. * the raw information about a particular recipient. For convenience, this function also determines the * actual name and email of the recipients, returned in "final_name" and "final_email" keys. Also, it returns a * "final_recipient" containing the complete recipient string, like: * * Tom Jones <*****@*****.**> * * If the name doesn't exist, that key just returns the email address. ASSUMPTION: All clients and administrator * MUST have a first name, last name and email address. For form email fields, the final recipient just contains * the title of the email field (the display value). * * This is obviously used for display purposes only, whereas that value for the other recipient types is used both * for display purposes & in the actual email construction. This seemed an adequate approach because this function * will never be able to know the individual submission content so it can't construct it properly. * * The returned results are ordered by (a) recipient type (main, cc then bcc), then (b) recipient user type * (admin, client, form_email_field then custom) * * @param integer $email_id * @return array an array of hashes */ function ft_get_email_template_recipients($form_id, $email_id) { global $g_table_prefix, $LANG; // now add any recipients for this email template $recipient_query = mysql_query("\r\n SELECT etr.*, a.first_name, a.last_name, a.email\r\n FROM {$g_table_prefix}email_template_recipients etr\r\n LEFT JOIN {$g_table_prefix}accounts a ON a.account_id = etr.account_id\r\n WHERE etr.email_template_id = {$email_id}\r\n ORDER BY etr.recipient_type, etr.recipient_user_type\r\n "); $recipients = array(); while ($recipient_info = mysql_fetch_assoc($recipient_query)) { // construct and append the extra keys (final_name, final_email and final_recipient) switch ($recipient_info["recipient_user_type"]) { case "admin": $admin_info = ft_get_admin_info(); $recipient_info["final_name"] = "{$admin_info["first_name"]} {$admin_info["last_name"]}"; $recipient_info["final_email"] = $admin_info["email"]; $recipient_info["final_recipient"] = "{$recipient_info["final_name"]} <{$recipient_info["final_email"]}>"; break; case "client": $client_info = ft_get_account_info($recipient_info["account_id"]); $recipient_info["final_name"] = "{$client_info["first_name"]} {$client_info["last_name"]}"; $recipient_info["final_email"] = $client_info["email"]; $recipient_info["final_recipient"] = "{$recipient_info["final_name"]} <{$recipient_info["final_email"]}>"; break; case "form_email_field": $form_email_field_info = ft_get_form_email_field_info($recipient_info["form_email_id"]); $email_field_id = $form_email_field_info["email_field_id"]; $recipient_info["final_recipient"] = ft_get_field_title_by_field_id($email_field_id); break; case "custom": $recipient_info["final_name"] = $recipient_info["custom_recipient_name"]; $recipient_info["final_email"] = $recipient_info["custom_recipient_email"]; if (!empty($recipient_info["final_name"])) { $recipient_info["final_recipient"] = "{$recipient_info["final_name"]} <{$recipient_info["final_email"]}>"; } else { $recipient_info["final_recipient"] = $recipient_info["final_email"]; } break; } $recipients[] = $recipient_info; } return $recipients; }
/** * The login procedure for both administrators and clients in. If successful, redirects them to the * appropriate page, otherwise returns an error. * * @param array $infohash This parameter should be a hash (e.g. $_POST or $_GET) containing both * "username" and "password" keys, containing that information for the user trying * to log in. * @param boolean $login_as_client [optional] This optional parameter is used by administrators * to log in as a particular client, allowing them to view how the account looks, * even if it is disabled. * @return string error message string (if error occurs). Otherwise it redirects the user to the * appropriate page, based on account type. */ function ft_login($infohash, $login_as_client = false) { global $g_root_url, $g_table_prefix, $LANG; $settings = ft_get_settings("", "core"); $username = strip_tags($infohash["username"]); $username = ft_sanitize($username); $password = isset($infohash["password"]) ? ft_sanitize($infohash["password"]) : ""; $password = strip_tags($password); // extract info about this user's account $query = mysql_query("\r\n SELECT account_id, account_type, account_status, password, temp_reset_password, login_page\r\n FROM {$g_table_prefix}accounts\r\n WHERE username = '******'\r\n "); $account_info = mysql_fetch_assoc($query); $has_temp_reset_password = empty($account_info["temp_reset_password"]) ? false : true; // error check user login info if (!$login_as_client) { if (empty($password)) { return $LANG["validation_no_password"]; } if ($account_info["account_status"] == "disabled") { return $LANG["validation_account_disabled"]; } if ($account_info["account_status"] == "pending") { return $LANG["validation_account_pending"]; } if (empty($username)) { return $LANG["validation_account_not_recognized"]; } $password_correct = md5(md5($password)) == $account_info["password"]; $temp_password_correct = md5(md5($password)) == $account_info["temp_reset_password"]; if (!$password_correct && !$temp_password_correct) { // if this is a client account and the administrator has enabled the maximum failed login attempts feature, // keep track of the count $account_settings = ft_get_account_settings($account_info["account_id"]); // stores the MAXIMUM number of failed attempts permitted, before the account gets disabled. If the value // is empty in either the user account or for the default value, that means the administrator doesn't want // to track the failed login attempts $max_failed_login_attempts = isset($account_settings["max_failed_login_attempts"]) ? $account_settings["max_failed_login_attempts"] : $settings["default_max_failed_login_attempts"]; if ($account_info["account_type"] == "client" && !empty($max_failed_login_attempts)) { $num_failed_login_attempts = isset($account_settings["num_failed_login_attempts"]) && !empty($account_settings["num_failed_login_attempts"]) ? $account_settings["num_failed_login_attempts"] : 0; $num_failed_login_attempts++; if ($num_failed_login_attempts >= $max_failed_login_attempts) { ft_disable_client($account_info["account_id"]); ft_set_account_settings($account_info["account_id"], array("num_failed_login_attempts" => 0)); return $LANG["validation_account_disabled"]; } else { ft_set_account_settings($account_info["account_id"], array("num_failed_login_attempts" => $num_failed_login_attempts)); } } return $LANG["validation_wrong_password"]; } } extract(ft_process_hook_calls("main", compact("account_info"), array("account_info")), EXTR_OVERWRITE); // all checks out. Log them in, after populating sessions $_SESSION["ft"]["settings"] = $settings; $_SESSION["ft"]["account"] = ft_get_account_info($account_info["account_id"]); $_SESSION["ft"]["account"]["is_logged_in"] = true; // this is deliberate. $_SESSION["ft"]["account"]["password"] = md5(md5($password)); ft_cache_account_menu($account_info["account_id"]); // if this is an administrator, ensure the API version is up to date if ($account_info["account_type"] == "admin") { ft_update_api_version(); } else { ft_set_account_settings($account_info["account_id"], array("num_failed_login_attempts" => 0)); } // for clients, store the forms & form Views that they are allowed to access if ($account_info["account_type"] == "client") { $_SESSION["ft"]["permissions"] = ft_get_client_form_views($account_info["account_id"]); } // if the user just logged in with a temporary password, append some args to pass to the login page // so that they will be prompted to changing it upon login $reset_password_args = array(); if (md5(md5($password)) == $account_info["temp_reset_password"]) { $reset_password_args["message"] = "change_temp_password"; } // redirect the user to whatever login page they specified in their settings $login_url = ft_construct_page_url($account_info["login_page"], "", $reset_password_args); $login_url = "{$g_root_url}{$login_url}"; if (!$login_as_client) { ft_update_last_logged_in($account_info["account_id"]); } session_write_close(); header("Location: {$login_url}"); exit; }
/** * 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 = "• " . $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); }
/** * Updates a client account. Used for whomever is currently logged in. * * @param array $info This parameter should be a hash (e.g. $_POST or $_GET) containing keys * named the same as the database fields. * @return array [0]: true/false (success / failure) * [1]: message string */ function ft_update_client($account_id, $info) { global $g_table_prefix, $LANG, $g_password_special_chars; $success = true; $message = $LANG["notify_account_updated"]; $info = ft_sanitize($info); extract(ft_process_hook_calls("start", compact("account_id", "info"), array("info")), EXTR_OVERWRITE); $client_info = ft_get_account_info($account_id); $page = $info["page"]; switch ($page) { case "main": $first_name = $info["first_name"]; $last_name = $info["last_name"]; $email = $info["email"]; $username = $info["username"]; $password_clause = ""; $rules = array(); if (!empty($info["password"])) { $required_password_chars = explode(",", $client_info["settings"]["required_password_chars"]); if (in_array("uppercase", $required_password_chars)) { $rules[] = "reg_exp,password,[A-Z],{$LANG["validation_client_password_missing_uppercase"]}"; } if (in_array("number", $required_password_chars)) { $rules[] = "reg_exp,password,[0-9],{$LANG["validation_client_password_missing_number"]}"; } if (in_array("special_char", $required_password_chars)) { $error = ft_eval_smarty_string($LANG["validation_client_password_missing_special_char"], array("chars" => $g_password_special_chars)); $password_special_chars = preg_quote($g_password_special_chars); $rules[] = "reg_exp,password,[{$password_special_chars}],{$error}"; } if (!empty($client_info["settings"]["min_password_length"])) { $rule = ft_eval_smarty_string($LANG["validation_client_password_too_short"], array("number" => $client_info["settings"]["min_password_length"])); $rules[] = "length>={$client_info["settings"]["min_password_length"]},password,{$rule}"; } // encrypt the password on the assumption that it passes validation. It'll be used in the update query $password = md5(md5($info['password'])); $password_clause = "password = '******',"; } $errors = validate_fields($info, $rules); // check to see if username is already taken list($valid_username, $problem) = _ft_is_valid_username($username, $account_id); if (!$valid_username) { $errors[] = $problem; } // check the password isn't already in password history (if relevant) if (!empty($info["password"])) { if (!empty($client_info["settings"]["num_password_history"])) { $encrypted_password = md5(md5($info["password"])); if (ft_password_in_password_history($account_id, $encrypted_password, $client_info["settings"]["num_password_history"])) { $errors[] = ft_eval_smarty_string($LANG["validation_password_in_password_history"], array("history_size" => $client_info["settings"]["num_password_history"])); } else { ft_add_password_to_password_history($account_id, $encrypted_password); } } } if (!empty($errors)) { $success = false; array_walk($errors, create_function('&$el', '$el = "• " . $el;')); $message = implode("<br />", $errors); return array($success, $message); } $query = "\n UPDATE {$g_table_prefix}accounts\n SET {$password_clause}\n first_name = '{$first_name}',\n last_name = '{$last_name}',\n username = '******',\n email = '{$email}'\n WHERE account_id = {$account_id}\n "; if (mysql_query($query)) { // if the password wasn't empty, reset the temporary password, in case it was set if (!empty($info["password"])) { mysql_query("UPDATE {$g_table_prefix}accounts SET temp_reset_password = NULL where account_id = {$account_id}"); } } else { ft_handle_error("Failed query in <b>" . __FUNCTION__ . "</b>: <i>{$query}</i>", mysql_error()); } break; case "settings": $rules = array(); if ($client_info["settings"]["may_edit_page_titles"] == "yes") { $rules[] = "required,page_titles,{$LANG["validation_no_titles"]}"; } if ($client_info["settings"]["may_edit_theme"] == "yes") { $rules[] = "required,theme,{$LANG["validation_no_theme"]}"; } if ($client_info["settings"]["may_edit_logout_url"] == "yes") { $rules[] = "required,logout_url,{$LANG["validation_no_logout_url"]}"; } if ($client_info["settings"]["may_edit_language"] == "yes") { $rules[] = "required,ui_language,{$LANG["validation_no_ui_language"]}"; } if ($client_info["settings"]["may_edit_timezone_offset"] == "yes") { $rules[] = "required,timezone_offset,{$LANG["validation_no_timezone_offset"]}"; } if ($client_info["settings"]["may_edit_sessions_timeout"] == "yes") { $rules[] = "required,sessions_timeout,{$LANG["validation_no_sessions_timeout"]}"; $rules[] = "digits_only,sessions_timeout,{$LANG["validation_invalid_sessions_timeout"]}"; } if ($client_info["settings"]["may_edit_date_format"] == "yes") { $rules[] = "required,date_format,{$LANG["validation_no_date_format"]}"; } $errors = validate_fields($info, $rules); if (!empty($errors)) { $success = false; array_walk($errors, create_function('&$el', '$el = "• " . $el;')); $message = implode("<br />", $errors); return array($success, $message); } // update the main accounts table. Only update those settings they're ALLOWED to $settings = array(); if ($client_info["settings"]["may_edit_language"] == "yes") { $settings["ui_language"] = $info["ui_language"]; } if ($client_info["settings"]["may_edit_timezone_offset"] == "yes") { $settings["timezone_offset"] = $info["timezone_offset"]; } if ($client_info["settings"]["may_edit_logout_url"] == "yes") { $settings["logout_url"] = $info["logout_url"]; } if ($client_info["settings"]["may_edit_sessions_timeout"] == "yes") { $settings["sessions_timeout"] = $info["sessions_timeout"]; } if ($client_info["settings"]["may_edit_theme"] == "yes") { $settings["theme"] = $info["theme"]; $settings["swatch"] = ""; if (isset($info["{$info["theme"]}_theme_swatches"])) { $settings["swatch"] = $info["{$info["theme"]}_theme_swatches"]; } } if ($client_info["settings"]["may_edit_date_format"] == "yes") { $settings["date_format"] = $info["date_format"]; } if (!empty($settings)) { $sql_rows = array(); while (list($column, $value) = each($settings)) { $sql_rows[] = "{$column} = '{$value}'"; } $sql = implode(",\n", $sql_rows); $query = "\n UPDATE {$g_table_prefix}accounts\n SET {$sql}\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()); } $settings = array(); if (isset($info["page_titles"])) { $settings["page_titles"] = $info["page_titles"]; } if (isset($info["footer_text"])) { $settings["footer_text"] = $info["footer_text"]; } if (isset($info["max_failed_login_attempts"])) { $settings["max_failed_login_attempts"] = $info["max_failed_login_attempts"]; } if (!empty($settings)) { ft_set_account_settings($account_id, $settings); } break; } extract(ft_process_hook_calls("end", compact("account_id", "info"), array("success", "message")), EXTR_OVERWRITE); // update sessions $_SESSION["ft"]["settings"] = ft_get_settings(); $_SESSION["ft"]["account"] = ft_get_account_info($account_id); $_SESSION["ft"]["account"]["is_logged_in"] = true; return array($success, $message); }
/** * Completely deletes a client account from the database. * * @param integer $account_id * @return mixed * if success: * returns array with two indexes: [0] true, [1] empty string * * if error: * if $g_api_debug == true * the error page will be displayed displaying the error code. * * if $g_api_debug == false, it returns an array with two indexes: * [0] false * [1] the API error code */ function ft_api_delete_client_account($account_id) { global $g_api_debug; $account_id = ft_sanitize($account_id); $account_info = ft_get_account_info($account_id); // check the account ID was valid (i.e. the account exists) and that it's a CLIENT account if (!isset($account_info["account_id"])) { if ($g_api_debug) { $page_vars = array("message_type" => "error", "error_code" => 800, "error_type" => "user"); ft_display_page("error.tpl", $page_vars); exit; } else { return array(false, 800); } } if ($account_info["account_type"] != "client") { if ($g_api_debug) { $page_vars = array("message_type" => "error", "error_code" => 801, "error_type" => "user"); ft_display_page("error.tpl", $page_vars); exit; } else { return array(false, 801); } } ft_delete_client($account_id); return array(true, ""); }