FormMail. * * Author: Russell Robinson * First released: 2nd October 2001 * * Read This First * ~~~~~~~~~~~~~~~ * This script is very well documented and quite large! It looks daunting, * but really isn't. * If you have experience with PHP or other scripting languages, * here's what you *need* to read: * - Configuration (TARGET_EMAIL & DEF_ALERT) * - Creating Forms * That's it! (Alternatively, just read the Quick Start and/or * Quicker Start section below). * Full configuration documentation is here: * http://www.tectite.com/fmdoc/index.php * * NOTE: do not read or modify this script or any PHP script * with DreamWeaver or FrontPage! * Many versions of those programs silently corrupt PHP scripts. * * Purpose: * ~~~~~~~~ * To accept information from an HTML form via HTTP and mail it to recipients. * * What does this PHP script do? * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * On your web site, you may have one or more HTML forms that accept * information from people visiting your website. Your aim is for your * website to email that information to you and/or add it to a database. * FormMail performs those functions. * * Quick Start * ~~~~~~~~~~~ * 1. Edit this file and set TARGET_EMAIL for your requirements (near * line 512 in this file - replace "yourhost\.com" with your mail server's * name). We also strongly recommend you set DEF_ALERT (the next * configuration below TARGET_EMAIL). * 2. Install this file as formmail.php (or other name ending in .php) * on your web server. * Test alerts by using your browser to open a URL to the script: * http://www.yourhost.com/formmail.php?testalert=1 * Alerts are the only way FormMail can tell you the details of * errors or faults. * 3. Create an HTML form and: * - specify a hidden field called "recipients" with the email address * of the person to receive the form's results. * - in the your form tag set the action attribute to * the formmail.php you uploaded to your web server * * Once you have FormMail working, you may be interested in some advanced * usage and features. We have HOW-TO guides at www.tectite.com which * describe many of the advanced processing you can do with FormMail. * http://www.tectite.com/fmhowto/guides.php * * Quicker Start * ~~~~~~~~~~~~~ * Use the FormMail Configuration Wizard here: * http://www.tectite.com/wizards/fmconf.php * By answering a few questions you'll get a configured FormMail and * a sample HTML form ready to upload and use on your server. * * Features * ~~~~~~~~ * For a list of features go to: http://www.tectite.com/formmailpage.php * * Security * ~~~~~~~~ * Security is the primary concern in accepting data from your website * visitors. * Tectite FormMail has several security features designed into it. Note, * however, it requires configuration for your particular web site. * * Configuration * ~~~~~~~~~~~~~ * To configure this script, go to the section titled "CONFIGURATION" * (after reading the legal stuff below). * * There is only one mandatory setting: TARGET_EMAIL * and one strongly recommended setting: DEF_ALERT * * Full configuration information is available here: * http://www.tectite.com/fmdoc/index.php * * Creating Forms * ~~~~~~~~~~~~~~ * Go to this URL to learn how to write HTML forms for use with * Tectite FormMail: http://www.tectite.com/fmdoc/creating_forms.php * * Copying and Use (Software License) * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * Tectite FormMail is provided free of charge and may be freely distributed * and used provided that you: * 1. keep this header, including copyright and comments, * in place and unmodified; and, * 2. do not charge a fee for distributing it, without an agreement * in writing with Root Software allowing you to do so; and, * 3. if you modify FormMail before distributing it, you clearly * identify: * a) who you are * b) how to contact you * c) what changes you have made * d) why you have made those changes. * * By using any of our products, including this script, you are * agreeing to our standard Terms and Conditions, available here: * http://www.tectite.com/TermsAndConditions.pdf * * This is free software and the Software License shown above * is to be read in conjunction with our standard Terms and Conditions. * * Warranty and Disclaimer * ~~~~~~~~~~~~~~~~~~~~~~~ * Tectite FormMail is provided free-of-charge and with ABSOLUTELY NO WARRANTY. * It has not been verified for use in critical applications, including, * but not limited to, medicine, defense, aircraft, space exploration, * or any other potentially dangerous activity. * * By using Tectite FormMail you agree to indemnify Root Software and * Open Concepts (Vic) Pty Ltd, their agents, employees, directors and * associated companies and businesses from any liability whatsoever. * * We still care * ~~~~~~~~~~~~~ * If you find a bug or fault in FormMail, please report it to us. * We will respond to your report and make endeavours to rectify any * faults you've detected as soon as possible. * * To contact us view our contact information: * http://www.tectite.com/contacts.php * * Version History * ~~~~~~~~~~~~~~~ * Near the top of this file, you'll find its version. The version * line looks like this: * $FM_VERS = "N.MM"; /* script version ... * * The version history used to be located within this file. However, * starting with Version 8.00 we've moved it... * * You can read the complete version history of FormMail on our * main website here: * http://www.tectite.com/fmdoc/version_history.php */ /** * An alternative function for sending email. * You can override this variable in a hook script to use a different function. */ $ALT_MAIL_FUNCTION = ''; FMDebug('Submission to: ' . (isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : '') . ' from: ' . (isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '')); if (isset($_SERVER['REQUEST_METHOD']) && strtoupper($_SERVER['REQUEST_METHOD']) === 'OPTIONS') { FMDebug('CORS OPTIONS request'); CORS_Response(); FormMailExit(); } // // Capture the current date and time, for various purposes. // date_default_timezone_set('UTC'); /* prevent notice in PHP 5.1+ */ $lNow = time(); ini_set('track_errors',1); // enable $php_errormsg $aAlertInfo = array(); $sLangID = ""; // the language ID $aMessages = array(); // all FormMail messages in the appropriate language function FormMailExit($s_mesg = '') { if (!@include(Settings::get('HOOK_DIR') . "/fmhookonexit.inc.php")) { @include(Settings::get('HOOK_DIR') . "/fmhookonexit.inc"); } exit($s_mesg); } /** * Interrogate and manage the execution environment. * * @package tectite_formmail * @subpackage setup */ class ExecEnv { /** * Value of phpversion(). * * @var string */ private $_sPHPVersionString; /** * Array containing the elements of the PHP version * * @var array */ private $_aPHPVersion; /** * The URL for the script. * * @var string */ private $_sScript; /** * Construct the class, and check PHP version. */ function __construct() { $this->_Init(); $this->_CheckVersion(); } /** * Initialise the object. * Sets {@link $_aPHPVersion} and {@link $_sPHPVersionString} */ private function _Init() { $this->_sPHPVersionString = phpversion(); $this->_aPHPVersion = explode(".",$this->_ZapHyphenPart($this->_sPHPVersionString)); } /** * Remove any hyphenated component of a version string. * * @param $str * * @return false|string */ private function _ZapHyphenPart($str) { if (($i_pos = strpos($str,'-')) !== false) { return substr($str,0,$i_pos); } else { return $str; } } /** * @return array */ public function getPHPVersion() { return $this->_aPHPVersion; } /** * @return string */ public function getPHPVersionString() { return $this->_sPHPVersionString; } /** * Check for old version of PHP - die with a message if too old. * * This is actually not required because PHP 4 won't even accept * the syntax of a PHP 5 script. However, we might need some * other version check in the future, so this is a useful method * to have around in that case. */ private function _CheckVersion() { $s_req_string = "5.0.0"; // We only support PHP 5 onward. $a_too_old = explode(".",$s_req_string); $i_cannot_use = ($a_too_old[0] * 10000) + ($a_too_old[1] * 100) + $a_too_old[2]; $i_this_num = ($this->_aPHPVersion[0] * 10000) + ($this->_aPHPVersion[1] * 100) + $this->_aPHPVersion[2]; if ($i_this_num <= $i_cannot_use) { FormMailExit(GetMessage(MSG_SCRIPT_VERSION, array("PHPREQ" => $s_req_string,"PHPVERS" => $this->_sPHPVersionString))); } } /** * Test PHP version against a particular version string. * * @param $s_vers * * @return boolean true if the PHP version is at or later than the version * specified */ public function IsPHPAtLeast($s_vers) { $a_test_version = explode(".",$s_vers); if (count($a_test_version) < 3) { return (false); } return ($this->_aPHPVersion[0] > $a_test_version[0] || ($this->_aPHPVersion[0] == $a_test_version[0] && ($this->_aPHPVersion[1] > $a_test_version[1] || $this->_aPHPVersion[1] == $a_test_version[1] && $this->_aPHPVersion[2] >= $a_test_version[2]))); } public function GetScript() { if (!isset($this->_sScript)) { if (isset($_SERVER["PHP_SELF"]) && !empty($_SERVER["PHP_SELF"]) && isset($_SERVER["SERVER_NAME"]) && !empty($_SERVER["SERVER_NAME"]) ) { if (isset($_SERVER["SERVER_PORT"]) && $_SERVER["SERVER_PORT"] != 80 ) { if ($_SERVER["SERVER_PORT"] == 443) // SSL port // // just use https prefix // { $this->_sScript = "https://" . $_SERVER["SERVER_NAME"] . $_SERVER["PHP_SELF"]; } else // // use http with port number // { $this->_sScript = "http://" . $_SERVER["SERVER_NAME"] . ":" . $_SERVER["SERVER_PORT"] . $_SERVER["PHP_SELF"]; } } else { $this->_sScript = "http://" . $_SERVER["SERVER_NAME"] . $_SERVER["PHP_SELF"]; } } else { Error("no_php_self",GetMessage(MSG_NO_PHP_SELF),false,false); } } return ($this->_sScript); } /** * Get a boolean PHP setting. * * @param string $s_name the name of the setting * * @return bool|null the value of the setting */ public function getINIBool($s_name) { $m_val = ini_get($s_name); if ($m_val !== null) { if (is_numeric($m_val)) { $m_val = (int)$m_val; } elseif (is_string($m_val)) { $m_val = strtolower($m_val); switch ($m_val) { case "1": case "on": case "true": $m_val = true; break; default: $m_val = false; break; } } } return ($m_val); } /** * Return whether the session can be passed in a URL. * * @return bool true if the session can be passed in a URL */ public function allowSessionURL() { $m_only_cookies = $this->getINIBool('session.use_only_cookies'); FMDebug('only_cookies=' . $m_only_cookies); if ($m_only_cookies === null) { $m_only_cookies = $this->IsPHPAtLeast('5.3.0'); FMDebug('php=' . $this->IsPHPAtLeast('5.3.0') . ',only_cookies=' . $m_only_cookies); } return (!$m_only_cookies); } public function getPostMaxSize() { $s_max_value = ini_get('post_max_size'); $number = (int)substr($s_max_value,0,-1); switch (strtoupper(substr($s_max_value,-1))) { case "K": return $number * 1024; case "M": return $number * pow(1024,2); case "G": return $number * pow(1024,3); default: return (int)$s_max_value; } } public function checkUploadSize() { if (isset($_SERVER['CONTENT_LENGTH'])) { $n_size = (int)$_SERVER['CONTENT_LENGTH']; $n_max = $this->getPostMaxSize(); // echo "Size = $n_size, max = $n_max\n"; if ($n_size > $n_max) { UserError("post_size_limit",GetMessage(MSG_POST_SIZE_LIMIT,array(),false,false)); } } } public function checkFileUploadSize($a_file_vars) { if (Settings::get('FILEUPLOADS')) { $a_field_names = array_keys($a_file_vars); foreach ($a_field_names as $s_name => $a_upload) { if (isset($a_upload)) { switch (isset($a_upload['error']) ? $a_upload['error'] : 0) { case 0: // no error case 4: // no file uploaded break; default: UserError('file_upload_error',FieldManager::GetFileUploadErrorMesg($a_upload['error'])); } } } } } } $ExecEnv = new ExecEnv(); if (!$ExecEnv->IsPHPAtLeast("5.3.0")) { // // disable this silly setting (usually not enabled) // it's also deprecated from PHP version 5.3.0 // if (function_exists('set_magic_quotes_runtime')) { /** @noinspection PhpElementIsNotAvailableInCurrentPhpVersionInspection */ @set_magic_quotes_runtime(0); } } // // We set references to the appropriate arrays to handle PHP version differences // Session vars are selected after we start the session. // $aServerVars = &$_SERVER; $aGetVars = &$_GET; $aFormVars = &$_POST; $aFileVars = &$_FILES; $aEnvVars = &$_ENV; $bIsGetMethod = false; $bHasGetData = false; if (!isset($REAL_DOCUMENT_ROOT)) { SetRealDocumentRoot(); } if (isset($aServerVars['SERVER_PORT'])) { $SCHEME = ($aServerVars['SERVER_PORT'] == 80) ? "http://" : "https://"; } else { $SCHEME = ""; } if (isset($aServerVars['SERVER_NAME']) && $aServerVars['SERVER_NAME'] !== "") { $SERVER = $aServerVars['SERVER_NAME']; } elseif (isset($aServerVars['SERVER_ADDR']) && $aServerVars['SERVER_ADDR'] !== "") { $SERVER = $aServerVars['SERVER_ADDR']; } else { $SERVER = ""; } /* * Load an optional include file before the configuration. * You can use this to set variables that can be used in the * configuration section. */ @include("formmail-preconfig.inc.php"); /*****************************************************************************/ /* CONFIGURATION (do not alter this line in any way!!!) */ /***************************************************************************** * This is the *only* place where you need to modify things to use formmail.php * on your particular system. This section finishes at "END OF CONFIGURATION". * Help for all settings can be found on our website: * http://www.tectite.com/fmdoc/index.php * * Also, above each setting is a direct URL to the help information for the * setting. *****************************************************************************/ /* Help: http://www.tectite.com/fmdoc/email_name.php */ $EMAIL_NAME = "^[-a-z0-9._]+"; /* the '^' is an important security feature! */ /* Help: http://www.tectite.com/fmdoc/target_email.php */ $TARGET_EMAIL = array($EMAIL_NAME . "@yourhost\.com$"); /* Help: http://www.tectite.com/fmdoc/email_addrs.php */ $EMAIL_ADDRS = array(); /* Help: http://www.tectite.com/fmdoc/def_alert.php */ $DEF_ALERT = ""; /* Help: http://www.tectite.com/fmdoc/site_domain.php */ $SITE_DOMAIN = ""; /* your website domain name */ /* Help: http://www.tectite.com/fmdoc/set_real_document_root.php */ $SET_REAL_DOCUMENT_ROOT = ""; /* overrides the value set by SetRealDocumentRoot function */ // // override $REAL_DOCUMENT_ROOT from the $SET_REAL_DOCUMENT_ROOT value (if any) // Do not alter the following code (next 3 lines)! // if (isset($SET_REAL_DOCUMENT_ROOT) && $SET_REAL_DOCUMENT_ROOT !== "") { $REAL_DOCUMENT_ROOT = $SET_REAL_DOCUMENT_ROOT; } /* Help: http://www.tectite.com/fmdoc/config_check.php */ $CONFIG_CHECK = array("TARGET_EMAIL"); /* Help: http://www.tectite.com/fmdoc/at_mangle.php */ $AT_MANGLE = ""; /* Help: http://www.tectite.com/fmdoc/target_urls.php */ $TARGET_URLS = array(); /* default; no URLs allowed */ /* Help: http://www.tectite.com/fmdoc/head_crlf.php */ $HEAD_CRLF = "\r\n"; /* Help: http://www.tectite.com/fmdoc/body_lf.php */ $BODY_LF = "\r\n"; /* the new default: use this for CR+LF */ //$BODY_LF = "\n"; /* the old default: just LF */ /* Help: http://www.tectite.com/fmdoc/from_user.php */ $FROM_USER = ""; /* the default - setting not used */ /* Help: http://www.tectite.com/fmdoc/sendmail_f_option.php */ $SENDMAIL_F_OPTION = false; $SENDMAIL_F_OPTION_LINE = __LINE__ - 1; /* don't modify this line! */ /* Help: http://www.tectite.com/fmdoc/fixed_sender.php */ $FIXED_SENDER = ""; /* Help: http://www.tectite.com/fmdoc/set_sender_from_email.php */ $SET_SENDER_FROM_EMAIL = false; /* Help: http://www.tectite.com/fmdoc/ini_set_from.php */ $INI_SET_FROM = false; /* Help: http://www.tectite.com/fmdoc/logdir.php */ $LOGDIR = ""; /* directory for log files; empty string to disallow log files */ /* Help: http://www.tectite.com/fmdoc/autorespondlog.php */ $AUTORESPONDLOG = ""; /* file name in $LOGDIR for the auto responder log; empty string for no auto responder log */ /* Help: http://www.tectite.com/fmdoc/csv_file_settings.php */ $CSVDIR = ""; /* directory for csv files; empty string to disallow csv files */ $CSVSEP = ","; /* comma separator between fields (columns) */ $CSVINTSEP = ";"; /* semicolon is the separator for fields (columns) with multiple values (checkboxes, etc.) */ $CSVQUOTE = '"'; /* all fields in the CSV are quoted with this character; default is double quote. You can change it to single quote or leave it empty for no quotes. */ //$CSVQUOTE = "'"; /* use this if you want single quotes */ $CSVOPEN = ""; /* set to "b" to force line terminations to be kept as $CSVLINE setting below, regardless of operating system. Keep as empty string and leave $CSVLINE unchanged, to get text file terminations for your server's operating system. (Line feed on UNIX, carriage-return line feed on Windows). */ $CSVLINE = "\n"; /* line termination for CSV files. The default is a single line feed, which may be modified for your server's operating system. If you want to change this value, you *must* set $CSVOPEN = "b". */ /* Help: http://www.tectite.com/fmdoc/templatedir.php */ $TEMPLATEDIR = ""; /* directory for template files; empty string if you don't have any templates */ /* Help: http://www.tectite.com/fmdoc/templateurl.php */ $TEMPLATEURL = ""; /* default; no template URL */ /* Help: http://www.tectite.com/fmdoc/multiformdir.php */ $MULTIFORMDIR = ""; /* directory for multi-form template files; empty string if you're not using multi-forms */ /* Help: http://www.tectite.com/fmdoc/multiformurl.php */ $MULTIFORMURL = ""; /* default; no multi-forms templates URL */ /* Help: http://www.tectite.com/fmdoc/text_subs.php */ $TEXT_SUBS = array( array("srch" => "/\\\\r\\\\n/","repl" => "\r\n",), array("srch" => "/\\\\n/","repl" => "\n",), array("srch" => "/\\\\t/","repl" => "\t",), array("srch" => "/\\[NL\\]/","repl" => "\n",), array("srch" => "/\\[TAB\\]/","repl" => "\t",), array("srch" => "/\\[NBSP\\]/","repl" => " ",), array("srch" => "/\\[DQUOT\\]/","repl" => '"',), array("srch" => "/\\[SQUOT\\]/","repl" => "'",), array("srch" => "/\\[COLON\\]/","repl" => ":",), array("srch" => "/\\[SLOSH\\]/","repl" => "\\",), array("srch" => "/\\[OPCURL\\]/","repl" => "{",), array("srch" => "/\\[CLCURL\\]/","repl" => "}",), array("srch" => "/(on[a-z]*|href|src)\\s*=\\s*/i","repl" => ""), /* strip html attributes that could be unsafe */ array("srch" => "/<\\s*(table|tr|td|th|p|ul|ol|li|b|i|u|strong|pre|h[1-6]|em|dl|dd|dt|hr|span|br)(\\b[^>]*?)>/i", "repl" => "<\$1\$2>", ), array("srch" => "#<\\s*/\\s*(table|tr|td|th|p|ul|ol|li|b|i|u|strong|pre|h[1-6]|em|dl|dd|dt|hr|span|br)\\s*>#i", "repl" => "\$1>", ), ); /* Help: http://www.tectite.com/fmdoc/authentication_settings.php */ $AUTHENTICATE = ""; //$AUTHENTICATE = "Basic cnVzc2VsbHI6dGVzdA=="; // example $AUTH_USER = ""; $AUTH_PW = ""; /* Help: http://www.tectite.com/fmdoc/form_ini_file.php */ $FORM_INI_FILE = ""; /* Help: http://www.tectite.com/fmdoc/moduledir.php */ $MODULEDIR = "."; /* Help: http://www.tectite.com/fmdoc/fmcompute.php */ $FMCOMPUTE = "fmcompute.php"; /* Help: http://www.tectite.com/fmdoc/fmgeoip.php */ $FMGEOIP = "fmgeoip.php"; /* Help: http://www.tectite.com/fmdoc/advanced_templates.php */ $ADVANCED_TEMPLATES = false; /* set to true for advanced templates */ /* Help: http://www.tectite.com/fmdoc/limited_import.php */ $LIMITED_IMPORT = true; /* set to true if your database cannot handle escaped quotes or newlines within imported data. Microsoft Access is one example. */ /* Help: http://www.tectite.com/fmdoc/valid_env.php */ $VALID_ENV = array('HTTP_REFERER','REMOTE_HOST','REMOTE_ADDR','REMOTE_USER', 'HTTP_USER_AGENT' ); /* Help: http://www.tectite.com/fmdoc/fileuploads.php */ $FILEUPLOADS = false; /* set to true to allow file attachments */ /* Help: http://www.tectite.com/fmdoc/max_file_upload_size.php */ $MAX_FILE_UPLOAD_SIZE = 0; /* default of 0 means that other software */ // controls the maximum file upload size // (FormMail doesn't test the file size) /* Help: http://www.tectite.com/fmdoc/file_repository.php */ $FILE_REPOSITORY = ""; /* Help: http://www.tectite.com/fmdoc/file_mode.php */ $FILE_MODE = 0664; /* always precede with 0 to specify octal! */ /* Help: http://www.tectite.com/fmdoc/file_overwrite.php */ $FILE_OVERWRITE = true; /* Help: http://www.tectite.com/fmdoc/next_num_file.php */ $NEXT_NUM_FILE = ""; /* Help: http://www.tectite.com/fmdoc/put_data_in_url.php */ $PUT_DATA_IN_URL = true; /* set to true to place data in the URL */ // for bad_url redirects /* Help: http://www.tectite.com/fmdoc/allow_get_method.php */ $ALLOW_GET_METHOD = false; /* Help: http://www.tectite.com/fmdoc/db_see_input.php */ $DB_SEE_INPUT = false; /* set to true to just see the input values */ /* Help: http://www.tectite.com/fmdoc/db_see_ini.php */ $DB_SEE_INI = false; /* set to true to just see the ini file */ /* Help: http://www.tectite.com/fmdoc/maxstring.php */ $MAXSTRING = 1024; /* maximum string length for a value */ /* Help: http://www.tectite.com/fmdoc/require_captcha.php */ $REQUIRE_CAPTCHA = ""; /* set to a message string if your forms */ // must provide a CAPTCHA string /* Help: http://www.tectite.com/fmdoc/recaptcha_private_key.php */ $RECAPTCHA_PRIVATE_KEY = ""; /* Help: http://www.tectite.com/fmdoc/bshowmesgnumbers.php */ $bShowMesgNumbers = false; /* Help: http://www.tectite.com/fmdoc/filters.php */ /* Note for Tectite personnel: the upgrade Wizard will merge new values * but be careful of $var usage and quoting in new entries. */ /** @noinspection PhpUndefinedVariableInspection */ $FILTERS = array("encode" => "$REAL_DOCUMENT_ROOT/cgi-bin/fmencoder -kpubkey.txt", "null" => "null", "csv" => "csv" ); /* Help: http://www.tectite.com/fmdoc/socket_filters.php */ $SOCKET_FILTERS = array( "httpencode" => array("site" => "YourSiteHere", "port" => 80, "path" => "/cgi-bin/fmencoder", "params" => array(array("name" => "key", "file" => "$REAL_DOCUMENT_ROOT/cgi-bin/pubkey.txt" ) ) ), "sslencode" => array("site" => "ssl://YourSecureSiteHere", "port" => 443, "path" => "/cgi-bin/fmencoder", "params" => array(array("name" => "key", "file" => "$REAL_DOCUMENT_ROOT/cgi-bin/pubkey.txt" ) ) ), ); /* Help: http://www.tectite.com/fmdoc/filter_attribs.php */ $FILTER_ATTRIBS = array("encode" => "Strips,MIME=application/vnd.fmencoded,Encrypts", "httpencode" => "Strips,MIME=application/vnd.fmencoded,Encrypts", "sslencode" => "Strips,MIME=application/vnd.fmencoded,Encrypts", "csv" => "Strips,MIME=text/csv", ); /* Help: http://www.tectite.com/fmdoc/check_for_new_version.php */ $CHECK_FOR_NEW_VERSION = true; $CHECK_DAYS = 30; /* Help: http://www.tectite.com/fmdoc/scratch_pad.php */ $SCRATCH_PAD = ""; /* Help: http://www.tectite.com/fmdoc/cleanup_time.php */ $CLEANUP_TIME = 60; /* cleanup time in minutes */ /* Help: http://www.tectite.com/fmdoc/cleanup_chance.php */ $CLEANUP_CHANCE = 20; /* percentage probability that cleanup will be performed */ /* Help: http://www.tectite.com/fmdoc/pear_settings.php */ $PEAR_SMTP_HOST = ""; $PEAR_SMTP_PORT = 25; $PEAR_SMTP_USER = ""; $PEAR_SMTP_PWD = ""; /* Help: http://www.tectite.com/fmdoc/alert_on_user_error.php */ $ALERT_ON_USER_ERROR = true; /* Help: http://www.tectite.com/fmdoc/enable_attack_detection.php */ $ENABLE_ATTACK_DETECTION = true; /* Help: http://www.tectite.com/fmdoc/attack_detection_url.php */ $ATTACK_DETECTION_URL = ""; /* Help: http://www.tectite.com/fmdoc/alert_on_attack_detection.php */ $ALERT_ON_ATTACK_DETECTION = false; /* Help: http://www.tectite.com/fmdoc/attack_detection_mime.php */ $ATTACK_DETECTION_MIME = true; /* Help: http://www.tectite.com/fmdoc/attack_detection_junk.php */ $ATTACK_DETECTION_JUNK = false; $ATTACK_DETECTION_JUNK_CONSONANTS = "bcdfghjklmnpqrstvwxz"; $ATTACK_DETECTION_JUNK_VOWELS = "aeiouy"; $ATTACK_DETECTION_JUNK_CONSEC_CONSONANTS = 5; $ATTACK_DETECTION_JUNK_CONSEC_VOWELS = 4; $ATTACK_DETECTION_JUNK_TRIGGER = 2; $ATTACK_DETECTION_JUNK_LANG_STRIP = array( "aiia", /* Hawaiian */ "aeoa", /* palaeoanthropic */ "aeoe", /* palaeoethnic */ "ayou", /* layout */ "ayee", /* payee */ "buyout", /* buyout */ "clayey", /* clayey */ "hooey", /* hooey */ "ioau", /* radioautograph */ "opoeia", /* pharmacopoeia, onomatopoeia */ "ooee", /* cooee */ "oyee", /* employee */ "ioau", /* radioautograph */ "uaia", /* guaiac */ "uaya", /* uruguayan */ "ueou", /* aqueous */ "uiou", /* obsequious */ "uoya", /* buoyant */ "queue", /* queue, queueing */ "earth", /* earthquake, earthslide */ "cks", /* jockstrap, backscratcher */ "ngth", /* strengths, length */ "ndths", /* thousandths */ "ght", /* nightclub, knightsbridge */ "phth", /* ophthalmology */ "sch", /* rothschild */ "shch", /* borshch */ "scr", /* corkscrew */ "spr", /* wingspread, offspring */ "str", /* armstrong, songstress */ "sts", /* bursts, postscript */ "tch", /* catchphrase, scratchproof */ "thst", /* northstar, birthstone */ "http", /* https, http */ "html", /* HTML, XHTML */ ); $ATTACK_DETECTION_JUNK_IGNORE_FIELDS = array(); /* Help: http://www.tectite.com/fmdoc/attack_detection_dups.php */ $ATTACK_DETECTION_DUPS = array("realname","address1","address2","country","zip", "phone","postcode","state","email" ); /* Help: http://www.tectite.com/fmdoc/attack_detection_specials.php */ $ATTACK_DETECTION_SPECIALS = true; /* Help: http://www.tectite.com/fmdoc/attack_detection_specials.php */ $ATTACK_DETECTION_SPECIALS_ONLY_EMAIL = array("derive_fields","required", "mail_options","good_url","bad_url","good_template", "bad_template" ); /* Help: http://www.tectite.com/fmdoc/attack_detection_specials.php */ $ATTACK_DETECTION_SPECIALS_ANY_EMAIL = array("subject"); /* Help: http://www.tectite.com/fmdoc/attack_detection_many_urls.php */ $ATTACK_DETECTION_MANY_URLS = 0; /* Help: http://www.tectite.com/fmdoc/attack_detection_many_url_fields.php */ $ATTACK_DETECTION_MANY_URL_FIELDS = 0; /* Help: http://www.tectite.com/fmdoc/attack_detection_url_patterns.php */ $ATTACK_DETECTION_URL_PATTERNS = array( '(^|[^-a-z_.0-9]+)(?'; debug_print_backtrace(); echo ''; FormMailExit("No FormMail setting called '$s_name' exists."); } } /** * Tests if the given config setting is empty. * * @param string $s_name the name of the config setting * * @return boolean true if the config setting is empty */ public static function isEmpty($s_name) { Settings::_check($s_name); if (gettype($GLOBALS[$s_name]) == 'string') { return ($GLOBALS[$s_name] === ''); } else { return (empty($GLOBALS[$s_name])); } } /** * Returns the value of the given config setting. * * @param string $s_name the name of the config setting * * @return mixed the value of the config setting */ public static function get($s_name) { Settings::_check($s_name); return ($GLOBALS[$s_name]); } /** * Set the value of a config setting. * * @param string $s_name the name of the config setting * @param mixed $m_value the value to set for the config setting */ public static function set($s_name,$m_value) { Settings::_check($s_name); if (($s_orig_type = gettype($GLOBALS[$s_name])) != ($s_new_type = gettype($m_value))) { echo '
'; debug_print_backtrace(); echo ''; FormMailExit("You cannot set FormMail setting '$s_name' to type '$s_new_type'. It should be type '$s_orig_type'."); } $GLOBALS[$s_name] = $m_value; } } /* * Load an optional include file after the configuration. * You can use this to set variables or make adjustments * based on the results of the configuration section. */ @include("formmail-preconfigdefs.inc.php"); /* * Many configuration settings used to be constants. However, constants * cannot be re-defined in PHP. This limitation reduced the value * of "formmail-postconfig.inc.php" and other hook scripts. * Therefore, all configuration settings have been changed to be global * variables (no define's). * * The following defines are for backward-compatibility with any existing * hook scripts that are expecting the old constants. */ define("EMAIL_NAME",Settings::get("EMAIL_NAME")); define("DEF_ALERT",Settings::get("DEF_ALERT")); define("AT_MANGLE",Settings::get("AT_MANGLE")); define("HEAD_CRLF",Settings::get("HEAD_CRLF")); define("BODY_LF",Settings::get("BODY_LF")); define("SENDMAIL_F_OPTION",Settings::get("SENDMAIL_F_OPTION")); define("SENDMAIL_F_OPTION_LINE",Settings::get("SENDMAIL_F_OPTION_LINE")); define("SET_SENDER_FROM_EMAIL",Settings::get("SET_SENDER_FROM_EMAIL")); define("INI_SET_FROM",Settings::get("INI_SET_FROM")); define("ADVANCED_TEMPLATES",Settings::get("ADVANCED_TEMPLATES")); define("LIMITED_IMPORT",Settings::get("LIMITED_IMPORT")); define("FILEUPLOADS",Settings::get("FILEUPLOADS")); define("MAX_FILE_UPLOAD_SIZE",Settings::get("MAX_FILE_UPLOAD_SIZE")); define("FILE_MODE",Settings::get("FILE_MODE")); define("FILE_OVERWRITE",Settings::get("FILE_OVERWRITE")); define("PUT_DATA_IN_URL",Settings::get("PUT_DATA_IN_URL")); define("DB_SEE_INPUT",Settings::get("DB_SEE_INPUT")); define("DB_SEE_INI",Settings::get("DB_SEE_INI")); define("MAXSTRING",Settings::get("MAXSTRING")); define("CHECK_FOR_NEW_VERSION",Settings::get("CHECK_FOR_NEW_VERSION")); define("CHECK_DAYS",Settings::get("CHECK_DAYS")); define("ALERT_ON_USER_ERROR",Settings::get("ALERT_ON_USER_ERROR")); define("ENABLE_ATTACK_DETECTION",Settings::get("ENABLE_ATTACK_DETECTION")); define("ATTACK_DETECTION_URL",Settings::get("ATTACK_DETECTION_URL")); define("ALERT_ON_ATTACK_DETECTION",Settings::get("ALERT_ON_ATTACK_DETECTION")); define("ATTACK_DETECTION_MIME",Settings::get("ATTACK_DETECTION_MIME")); define("ATTACK_DETECTION_JUNK",Settings::get("ATTACK_DETECTION_JUNK")); define("ATTACK_DETECTION_JUNK_CONSONANTS",Settings::get("ATTACK_DETECTION_JUNK_CONSONANTS")); define("ATTACK_DETECTION_JUNK_VOWELS",Settings::get("ATTACK_DETECTION_JUNK_VOWELS")); define("ATTACK_DETECTION_JUNK_CONSEC_CONSONANTS",Settings::get("ATTACK_DETECTION_JUNK_CONSEC_CONSONANTS")); define("ATTACK_DETECTION_JUNK_CONSEC_VOWELS",Settings::get("ATTACK_DETECTION_JUNK_CONSEC_VOWELS")); define("ATTACK_DETECTION_JUNK_TRIGGER",Settings::get("ATTACK_DETECTION_JUNK_TRIGGER")); define("ATTACK_DETECTION_SPECIALS",Settings::get("ATTACK_DETECTION_SPECIALS")); define("ATTACK_DETECTION_MANY_URLS",Settings::get("ATTACK_DETECTION_MANY_URLS")); define("ATTACK_DETECTION_MANY_URL_FIELDS",Settings::get("ATTACK_DETECTION_MANY_URL_FIELDS")); define("ATTACK_DETECTION_IGNORE_ERRORS",Settings::get("ATTACK_DETECTION_IGNORE_ERRORS")); define("ZERO_IS_EMPTY",Settings::get("ZERO_IS_EMPTY")); define("VALIDATE_EMAIL_DOMAIN",Settings::get("VALIDATE_EMAIL_DOMAIN")); define("DESTROY_SESSION",Settings::get("DESTROY_SESSION")); // // for Ajax allow GET method for cross site JSONP // if (IsAjax()) { Settings::set('ALLOW_GET_METHOD',true); } /* * Load an optional include file after the configuration. * You can use this to set variables or make adjustments * based on the results of the configuration section. */ @include("formmail-postconfig.inc.php"); // @formatter:off // // the following constants define all FormMail messages // // To re-align comments, use these search and replace patterns: // Search Replace // ^(\S{35,39})\s+// $1\t// // ^(\S{31,35})\s+// $1\t\t// // ^(\S{27,31})\s+// $1\t\t\t// // ^(\S{23,27})\s+// $1\t\t\t\t// // ^(\S{19,23})\s+// $1\t\t\t\t\t// // define('MSG_SCRIPT_VERSION',0); // This script requires at least PHP version... define('MSG_END_VERS_CHK',1); // If you're happy... define('MSG_VERS_CHK',2); // A later version of FormMail is available... define('MSG_CHK_FILE_ERROR',3); // Unable to create check file... define('MSG_UNK_VALUE_SPEC',4); // derive_fields: unknown value specification... define('MSG_INV_VALUE_SPEC',5); // derive_fields: invalid value specification... define('MSG_DERIVED_INVALID',6); // Some derive_fields specifications... define('MSG_INT_FORM_ERROR',7); // Internal form error... define('MSG_OPTIONS_INVALID',8); // Some mail_options settings... define('MSG_PLSWAIT_REDIR',9); // Please wait while you are redirected... define('MSG_IFNOT_REDIR',10); // If you are not redirected... define('MSG_PEAR_OBJ',11); // Failed to create PEAR Mail object... define('MSG_PEAR_ERROR',12); // PEAR Mail error... define('MSG_NO_FOPT_ADDR',13); // You have specified "SendMailFOption"... define('MSG_MORE_INFO',14); // More information... define('MSG_INFO_STOPPED',15); // Extra alert information suppressed... define('MSG_FM_ALERT',16); // FormMail alert define('MSG_FM_ERROR',17); // FormMail script error define('MSG_FM_ERROR_LINE',18); // The following error occurred... define('MSG_USERDATA_STOPPED',19); // User data suppressed... define('MSG_FILTERED',20); // This alert has been filtered... define('MSG_TEMPLATES',21); // You must set either TEMPLATEDIR or TEMPLATEURL... define('MSG_OPEN_TEMPLATE',22); // Failed to open template... define('MSG_ERROR_PROC',23); // An error occurred while processing... define('MSG_ALERT_DONE',24); // Our staff have been alerted... define('MSG_PLS_CONTACT',25); // Please contact us directly... define('MSG_APOLOGY',26); // We apologize for any inconvenience... define('MSG_ABOUT_FORMMAIL',27); // Your form submission was processed by... define('MSG_PREG_FAILED',28); // preg_match_all failed in FindCRMFields... define('MSG_URL_INVALID',29); // CRM URL "$URL" is not valid... define('MSG_URL_OPEN',30); // Failed to open Customer Relationship... define('MSG_CRM_FAILED',31); // Failure report from CRM... define('MSG_CRM_FORM_ERROR',32); // Your form submission was not... define('MSG_OR',33); // "$ITEM1" or "$ITEM2" define('MSG_NOT_BOTH',34); // not both "$ITEM1" and "$ITEM2" define('MSG_XOR',35); // "$ITEM1" or "$ITEM2" (but not both) define('MSG_IS_SAME_AS',36); // "$ITEM1" is the same as "$ITEM2" define('MSG_IS_NOT_SAME_AS',37); // "$ITEM1" is not the same as "$ITEM2" define('MSG_REQD_OPER',38); // Operator "$OPER" is not valid for "required" define('MSG_PAT_FAILED',39); // Pattern operator "$OPER" failed: pattern... define('MSG_COND_OPER',40); // Operator "$OPER" is not valid... define('MSG_INV_COND',41); // Invalid "conditions" field... define('MSG_COND_CHARS',42); // The conditions field "$FLD" is not valid... define('MSG_COND_INVALID',43); // The conditions field "$FLD" is not valid... define('MSG_COND_TEST_LONG',44); // Field "$FLD" has too many components... define('MSG_COND_IF_SHORT',45); // Field "$FLD" has too few components for... define('MSG_COND_IF_LONG',46); // Field "$FLD" has too many components for... define('MSG_COND_UNK',47); // Field "$FLD" has an unknown command word... define('MSG_MISSING',48); // Missing "$ITEM"... define('MSG_NEED_ARRAY',49); // "$ITEM" must be an array... define('MSG_SUBM_FAILED',50); // Your form submission has failed... define('MSG_FILTER_WRONG',51); // Filter "$FILTER" is not properly... define('MSG_FILTER_CONNECT',52); // Could not connect to site "$SITE"... define('MSG_FILTER_PARAM',53); // Filter "$FILTER" has invalid parameter... define('MSG_FILTER_OPEN_FILE',54); // Filter "$FILTER" cannot open file... define('MSG_FILTER_FILE_ERROR',55); // Filter "$FILTER": read error on file... define('MSG_FILTER_READ_ERROR',56); // Filter '$filter' failed: read error... define('MSG_FILTER_NOT_OK',57); // Filter 'FILTER' failed... define('MSG_FILTER_UNK',58); // Unknown filter... define('MSG_FILTER_CHDIR',59); // Cannot chdir... define('MSG_FILTER_NOTFOUND',60); // Cannot execute... define('MSG_FILTER_ERROR',61); // Filter "$FILTER" failed... define('MSG_SPARE',62); // this value is now spare define('MSG_TEMPLATE_ERRORS',63); // Template "$NAME" caused the... define('MSG_TEMPLATE_FAILED',64); // Failed to process template "$NAME"... define('MSG_MIME_PREAMBLE',65); // (Your mail reader should not show this... define('MSG_MIME_HTML',66); // This message has been generated by FormMail... define('MSG_FILE_OPEN_ERROR',67); // Failed to open file "$NAME"... define('MSG_ATTACH_DATA',68); // Internal error: AttachFile requires... define('MSG_PHP_HTML_TEMPLATES',69); // HTMLTemplate option is only ... define('MSG_PHP_FILE_UPLOADS',70); // For security reasons, file upload... define('MSG_FILE_UPLOAD',71); // File upload attempt ignored... define('MSG_FILE_UPLOAD_ATTACK',72); // Possible file upload attack... define('MSG_PHP_PLAIN_TEMPLATES',73); // PlainTemplate option is only... define('MSG_ATTACH_NAME',74); // filter_options: Attach must contain a name... define('MSG_PHP_BCC',75); // Warning: BCC is probably not supported... define('MSG_CSVCOLUMNS',76); // The "csvcolumns" setting is not... define('MSG_CSVFILE',77); // The "csvfile" setting is not... define('MSG_TARG_EMAIL_PAT_START',78); // Warning: Your TARGET_EMAIL pattern... define('MSG_TARG_EMAIL_PAT_END',79); // Warning: Your TARGET_EMAIL pattern... define('MSG_CONFIG_WARN',80); // The following potential problems... define('MSG_PHP_AUTORESP',81); // Autorespond is only supported... define('MSG_ALERT',82); // This is a test alert message... define('MSG_NO_DEF_ALERT',83); // No DEF_ALERT value has been set.... define('MSG_TEST_SENT',84); // Test message sent. Check your email..... define('MSG_TEST_FAILED',85); // FAILED to send alert message... define('MSG_NO_DATA_PAGE',86); // This URL is a Form submission program... define('MSG_REQD_ERROR',87); // The form required some values that you... define('MSG_COND_ERROR',88); // Some of the values you provided... define('MSG_CRM_FAILURE',89); // The form submission did not succeed... define('MSG_FOPTION_WARN',90); // Warning: You've used SendMailFOption in... define('MSG_NO_ACTIONS',91); // The form has an internal error... define('MSG_NO_RECIP',92); // The form has an internal error... define('MSG_INV_EMAIL',93); // Invalid email addresses... define('MSG_FAILED_SEND',94); // Failed to send email... define('MSG_ARESP_EMAIL',96); // No "email" field was found. Autorespond... define('MSG_ARESP_SUBJ',97); // Your form submission... define('MSG_LOG_NO_VERIMG',98); // No VerifyImgString in session... define('MSG_ARESP_NO_AUTH',99); // Failed to obtain authorization... define('MSG_LOG_NO_MATCH',100); // User did not match image... define('MSG_ARESP_NO_MATCH',101); // Your entry did not match... define('MSG_LOG_FAILED',102); // Failed define('MSG_ARESP_FAILED',103); // Autoresponder failed define('MSG_LOG_OK',104); // OK define('MSG_THANKS_PAGE',105); // Thanks! We've received your.... define('MSG_LOAD_MODULE',106); // Cannot load module.... define('MSG_LOAD_FMCOMPUTE',107); // Cannot load FMCompute.... define('MSG_REGISTER_MODULE',108); // Cannot register module.... define('MSG_COMP_PARSE',109); // These parse errors occurred.... define('MSG_COMP_REG_DATA',110); // Failed to register data field.... define('MSG_COMP_ALERT',111); // The following alert messages.... define('MSG_COMP_DEBUG',112); // The following debug messages... define('MSG_COMP_EXEC',113); // The following errors occurred.... define('MSG_REG_FMCOMPUTE',114); // Cannot register function... define('MSG_USER_ERRORS',115); // A number of errors occurred... define('MSG_CALL_PARAM_COUNT',116); // Invalid parameter count... define('MSG_CALL_UNK_FUNC',117); // Unknown function... define('MSG_SAVE_FILE',118); // Failed to save file.... define('MSG_CHMOD',119); // Failed to chmod file.... define('MSG_VERIFY_MISSING',120); // Image verification string missing... define('MSG_VERIFY_MATCH',121); // Your entry did not match... define('MSG_FILE_NAMES_INVALID',122); // Some file_names specifications... define('MSG_FILE_NAMES_NOT_FILE',123); // Your file_names specification... define('MSG_TEMPL_ALERT',124); // The following alert messages.... define('MSG_TEMPL_DEBUG',125); // The following debug messages... define('MSG_TEMPL_PROC',126); // The following errors occurred.... define('MSG_SAVE_FILE_EXISTS',127); // Cannot save file.... define('MSG_EMPTY_ADDRESSES',128); // $COUNT empty addresses define('MSG_CALL_INVALID_PARAM',129); // Invalid parameter.... define('MSG_INI_PARSE_WARN',130); // Warning: your INI define('MSG_INI_PARSE_ERROR',131); // The FormMail INI... define('MSG_RECAPTCHA_MATCH',132); // reCaptcha verification failed... define('MSG_AND',133); // "$ITEM1" and "$ITEM2" define('MSG_NEXT_PLUS_GOOD',134); // The form specifies both next_form and.... define('MSG_MULTIFORM',135); // You must set either MULTIFORMDIR or MULTIFORMURL... define('MSG_MULTIFORM_FAILED',136); // Failed to process multi-page form template "$NAME"... define('MSG_NEED_THIS_FORM',137); // Multi-page forms require "this_form" field... define('MSG_NO_PHP_SELF',138); // PHP on the server is not providing "PHP_SELF" define('MSG_RETURN_URL_INVALID',139); // Return "$URL" is not valid... define('MSG_GO_BACK',140); // Cannot 'go back' if not a multi-page form... define('MSG_OPEN_URL',141); // Cannot open URL... define('MSG_CANNOT_RETURN',142); // Cannot return to page.... define('MSG_ATTACK_DETECTED',143); // Server attack detected.... define('MSG_ATTACK_PAGE',144); // Your form submission.... define('MSG_ATTACK_MIME_INFO',145); // The field "$FLD" contained... define('MSG_ATTACK_DUP_INFO',146); // The fields "$FLD1" and... define('MSG_ATTACK_SPEC_INFO',147); // Special field "$FLD"... define('MSG_NEED_SCRATCH_PAD',148); // You need to set SCRATCH_PAD... define('MSG_MULTI_UPLOAD',149); // File upload processing failed during multi-page form processing. define('MSG_OPEN_SCRATCH_PAD',150); // Cannot open directory... define('MSG_NO_NEXT_NUM_FILE',151); // You cannot use the %nextnum% feature... define('MSG_NEXT_NUM_FILE',152); // Cannot process next number... define('MSG_ATTACK_MANYURL_INFO',153); // Field "$FLD"... define('MSG_ATTACK_MANYFIELDS_INFO',154); // $NUM fields have URLs.... define('MSG_REV_CAP',155); // ATTACK_DETECTION_REVERSE_CAPTCHA setting.... define('MSG_ATTACK_REV_CAP_INFO',156); // The field "$FLD" contained... define('MSG_ATTACK_JUNK_INFO',157); // The field "$FLD" contained... define('MSG_ARESP_EMPTY',158); // The autoresponse... define('MSG_LOG_RECAPTCHA',159); // reCaptcha process failed... define('MSG_URL_PARSE',160); // URL parse failed define('MSG_URL_SCHEME',161); // Unsupported URL scheme... define('MSG_SOCKET',162); // Socket error ... define('MSG_GETURL_OPEN',163); // Open URL failed: ... define('MSG_RESOLVE',164); // Cannot resolve... define('MSG_FORM_OK',170); // Form Submission Succeeded define('MSG_FORM_ERROR',171); // Form Submission Error define('MSG_GET_DISALLOWED',172); // GET method has... define('MSG_INVALID_SENDER',173); // The form has specified an invalid sender define('MSG_SET_SENDER_FROM_EMAIL',174); // SET_SENDER_FROM_EMAIL is no longer supported // // The following are PHP's file upload error messages // define('MSG_FILE_UPLOAD_ERR_UNK',180); // Unknown error code. define('MSG_FILE_UPLOAD_ERR1',181); // The uploaded file exceeds the upload_max_filesize directive in php.ini. define('MSG_FILE_UPLOAD_ERR2',182); // The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the html form. define('MSG_FILE_UPLOAD_ERR3',183); // The uploaded file was only partially uploaded. define('MSG_FILE_UPLOAD_ERR4',184); // No file was uploaded. define('MSG_FILE_UPLOAD_ERR6',186); // Missing a temporary folder. define('MSG_FILE_UPLOAD_ERR7',187); // Failed to write file to disk. define('MSG_FILE_UPLOAD_ERR8',188); // File upload stopped by extension. define('MSG_FILE_UPLOAD_SIZE',189); // Uploaded file "$NAME" is too big... (not a PHP error code - internal maximum file size error) define('MSG_POST_SIZE_LIMIT',190); // Your form submission exceeds the server's configured size limit. // // following are for derive_fields functions // define('MSG_DER_FUNC_ERROR',200); // derive_fields: invalid function.... define('MSG_DER_FUNC_SIZE_FMT',201); // function 'size' requires.... define('MSG_DER_FUNC_IF_FMT',202); // function 'if' requires.... define('MSG_DER_FUNC_NEXTNUM_FMT',203); // function 'nextnum' requires.... define('MSG_DER_FUNC_EXT_FMT',204); // function 'ext' requires.... define('MSG_DER_FUNC1_FMT',205); // function 'FUNC' requires.... define('MSG_DER_FUNC_SUBSTR_FMT',206); // function 'substr' requires.... define('MSG_USER_ATTACK_JUNK',220); // The following input ... define('MSG_USER_ATTACK_REV_CAP',221); // Your input ... define('MSG_USER_ATTACK_DUP',222); // You have ... define('MSG_USER_ATTACK_MANY_URLS',223); // Your input ... define('MSG_USER_ATTACK_MANY_URL_FIELDS',224); // Your input ... define('MSG_INVALID_EMAIL',230); // The email address...is invalid // @formatter:on // Jump to: // // Return true if using the built-in language // /** @noinspection PhpUnused */ function IsBuiltInLanguage() { global $sLangID; return (strpos($sLangID,"builtin") !== false); } $sSavePath = ""; $bPathSaved = false; // // Set include path to include the given directory. // function AddIncludePath($s_dir = ".") { global $sSavePath,$bPathSaved; $s_path = ini_get('include_path'); $i_path_len = strlen($s_path); $s_sep = IsServerWindows() ? ";" : ":"; // get path separator // // look for it in the include_path // $b_found = false; $i_pos = 0; $i_len = strlen($s_dir); while (!$b_found && ($i_pos = strpos($s_path,$s_dir,$i_pos)) !== false) { if ($i_pos == 0) { if ($i_len == $i_path_len) { $b_found = true; } // the path only has $s_dir elseif ($s_path[$i_len] == $s_sep) { $b_found = true; } } elseif ($s_path[$i_pos - 1] == $s_sep && ($i_pos + $i_len == $i_path_len || $s_path[$i_pos + $i_len] == $s_sep) ) { $b_found = true; } if (!$b_found) { $i_pos++; } } if (!$b_found) { // // allow multiple calls, but only store the original path once // if (!$bPathSaved) { $sSavePath = $s_path; } if (empty($s_path)) { $s_path = $s_dir; } else // // prepend the directory // { $s_path = $s_dir . $s_sep . $s_path; } ini_set('include_path',$s_path); $bPathSaved = true; } } // // Reset the include path after a call to AddIncludePath. // function ResetIncludePath() { global $sSavePath,$bPathSaved; if ($bPathSaved) { ini_set('include_path',$sSavePath); $bPathSaved = false; } } // // Load a language file // function LoadLanguageFile() { global $aMessages,$sLangID,$sHTMLCharSet; AddIncludePath(); if (!@include("language.inc.php")) { @include("language.inc"); } ResetIncludePath(); if (isset($sHTMLCharSet) && $sHTMLCharSet !== "") { header("Content-Type: text/html; charset=$sHTMLCharSet"); } } // // Load the messages array from the default language, and then // override with an optional language file. // Note: all messages get the MNUM parameter sent which they can use. // If they don't use it, the message number is appended. // function LoadBuiltinLanguage() { global $aMessages,$sLangID; $sLangID = "English (builtin)"; // MSG_SCRIPT_VERSION is shown if the PHP version is too old to run // FormMail // Parameters: // $PHPREQ is the minimum required PHP version // $PHPVERS is the version the server currently has installed. $aMessages[MSG_SCRIPT_VERSION] = 'This script requires at least PHP version ' . '$PHPREQ. You have PHP version $PHPVERS.'; // MSG_END_VERS_CHK is sent at the end of an Alert message when // FormMail detects that there's a newer version available // Parameters: none $aMessages[MSG_END_VERS_CHK] = '***************************************************\n' . 'If you are happy with your current version and want\n' . 'to stop these reminders, edit formmail.php and\n' . 'set CHECK_FOR_NEW_VERSION to false.\n' . '***************************************************\n'; // MSG_VERS_CHK is sent in an Alert message when // FormMail detects that there's a newer version available // Parameters: // $TECTITE the website to go to // $FM_VERS the current FormMail version // $NEWVERS the new FormMail version that's available $aMessages[MSG_VERS_CHK] = 'A later version of FormMail is available from $TECTITE.\n' . 'You are currently using version $FM_VERS.\n' . 'The new version available is $NEWVERS.\n'; // MSG_CHK_FILE_ERROR is sent in an Alert message when // FormMail cannot create a file to record the time of version check. // Parameters: // $FILE the file name that could not be created // $ERROR the actual error message $aMessages[MSG_CHK_FILE_ERROR] = 'Unable to create check file "$FILE": $ERROR'; // MSG_UNK_VALUE_SPEC is sent in an Alert message when // a form uses an unknown value specification in derive_fields. // Parameters: // $SPEC the unknown value specification // $MSG additional message $aMessages[MSG_UNK_VALUE_SPEC] = 'derive_fields: unknown value specification ' . '"$SPEC"$MSG'; // MSG_INV_VALUE_SPEC is sent in an Alert message when // a form uses a value specification in derive_fields that's // formatted incorrectly (missing terminating '%') // Parameters: // $SPEC the invalid value specification $aMessages[MSG_INV_VALUE_SPEC] = 'derive_fields: invalid value specification ' . '"$SPEC" (possibly missing a "%")'; // MSG_DERIVED_INVALID is sent in an Alert message when // a form's derive_fields setting has errors // Parameters: none // A list of errors is appended on separate lines $aMessages[MSG_DERIVED_INVALID] = 'Some derive_fields specifications are invalid $MNUM:\n'; // MSG_INT_FORM_ERROR is sent in an Alert message and displayed // to the form user // Parameters: none $aMessages[MSG_INT_FORM_ERROR] = 'Internal form error'; // MSG_OPTIONS_INVALID is sent in an Alert message when // a form's options settings are invalid. This applies to // mail_options, filter_options, crm_options, and autorespond // Parameters: // $OPT the name of the options field // A list of errors is appended on separate lines $aMessages[MSG_OPTIONS_INVALID] = 'Some $OPT settings are undefined $MNUM:\n'; // MSG_PLSWAIT_REDIR is shown to the user for a redirect // with JavaScript // Parameters: none $aMessages[MSG_PLSWAIT_REDIR] = 'Please wait while you are redirected...'; // MSG_IFNOT_REDIR is shown to the user for a redirect // with JavaScript // Parameters: // $URL the URL to redirect to $aMessages[MSG_IFNOT_REDIR] = 'If you are not automatically redirected, ' . 'please click here.'; // MSG_PEAR_OBJ is shown to the user if the PEAR Mail object // cannot be created // Parameters: none $aMessages[MSG_PEAR_OBJ] = 'Failed to create PEAR Mail object'; // MSG_PEAR_ERROR is sent in an Alert message if the PEAR Mail processing // reports an error // Parameters: // $MSG the error message from PEAR $aMessages[MSG_PEAR_ERROR] = 'PEAR Mail error: $MSG'; // MSG_NO_FOPT_ADDR is sent in an Alert message SendMailFOption is // specified in the form and no email address has been provided // Parameters: none $aMessages[MSG_NO_FOPT_ADDR] = 'You have specified "SendMailFOption" in your ' . 'form, but there is no email address to use'; // MSG_MORE_INFO is sent in an Alert message on a line by itself, just // before extra information about the FormMail processing that may have // led to the alert message // Parameters: none $aMessages[MSG_MORE_INFO] = 'More information:'; // MSG_INFO_STOPPED is sent in an Alert message to say that extra // alert information has been suppressed because of potential security // problems with showing it. // Parameters: none $aMessages[MSG_INFO_STOPPED] = '(Extra alert information suppressed for ' . 'security purposes. $MNUM)'; // MSG_FM_ALERT is sent as the subject line of an Alert message // Parameters: none $aMessages[MSG_FM_ALERT] = 'FormMail alert'; // MSG_FM_ERROR is sent as the subject line of an Alert message // Parameters: none $aMessages[MSG_FM_ERROR] = 'FormMail script error'; // MSG_FM_ERROR_LINE is sent in an Alert message on a // separate line to introduce the actual error message // Parameters: none $aMessages[MSG_FM_ERROR_LINE] = 'The following error occurred in FormMail $MNUM:'; // MSG_USERDATA_STOPPED is sent in an Alert message to say that the // user's data has been suppressed because of potential security // problems with showing it. // Parameters: none $aMessages[MSG_USERDATA_STOPPED] = '(User data suppressed for security ' . 'purposes. $MNUM)'; // MSG_FILTERED is sent in an Alert message to show what filter // has been used on the message // Parameters: // $FILTER the name of the filter $aMessages[MSG_FILTERED] = 'This alert has been filtered through "$FILTER" ' . 'for security purposes.'; // MSG_TEMPLATES is sent in an Alert message when a form tries // to use a template, but templates have not been configured in // formmail.php // Parameters: none $aMessages[MSG_TEMPLATES] = 'You must set either TEMPLATEDIR or TEMPLATEURL ' . 'in formmail.php before you can specify ' . 'templates in your forms.'; // MSG_OPEN_TEMPLATE is sent in an Alert message when FormMail cannot // open a template file // Parameters: // $NAME the name of the template file // $ERROR information about the error $aMessages[MSG_OPEN_TEMPLATE] = 'Failed to open template "$NAME" $MNUM: $ERROR'; // MSG_ERROR_PROC is shown to the user as part of an error // page. This message introduces the error. // Parameters: none $aMessages[MSG_ERROR_PROC] = 'An error occurred while processing the ' . 'form $MNUM.\n\n'; // MSG_ALERT_DONE is shown to the user as part of an error // page if an Alert message has been sent to the website owner. // Parameters: // SERVER the name of the server (website) $aMessages[MSG_ALERT_DONE] = 'The staff at $SERVER have been alerted to the error $MNUM.\n'; // MSG_PLS_CONTACT is shown to the user as part of an error // page if an Alert message could *not* be sent to the website owner. // Parameters: // SERVER the name of the server (website) $aMessages[MSG_PLS_CONTACT] = 'Please contact us ($SERVER) directly since this form ' . 'is not working $MNUM.\n'; // MSG_APOLOGY is shown to the user as part of an error // page as an apology for a problem with the form. // Parameters: // SERVER the name of the server (website) $aMessages[MSG_APOLOGY] = '$SERVER apologizes for any inconvenience this error ' . 'may have caused.'; // MSG_ABOUT_FORMMAIL is shown to the user at the foot of pages // generated by FormMail (e.g. the default "Thanks" page and default // error page). // Parameters: // $FM_VERS the FormMail version number // $TECTITE www.tectite.com $aMessages[MSG_ABOUT_FORMMAIL] = 'Your form submission was processed by ' . 'FormMail ' . '($FM_VERS), a PHP script available from ' . '$TECTITE.'; // MSG_PREG_FAILED is sent in an Alert message if the TectiteCRM // system failed to return the expected result. // Parameters: none $aMessages[MSG_PREG_FAILED] = 'preg_match_all failed in FindCRMFields'; // MSG_URL_INVALID is sent in an Alert message if the specified // URL for TectiteCRM is not valid according to the TARGET_URLS // configuration setting // Parameters: // $URL the invalid URL $aMessages[MSG_URL_INVALID] = 'The URL "$URL" to access the Customer ' . 'Relationship Management System is not valid ' . '(see TARGET_URLS in formmail.php)'; // MSG_URL_OPEN is sent in an Alert message if the specified // URL for TectiteCRM cannot be opened // Parameters: // $URL the invalid URL // $ERROR information about the error $aMessages[MSG_URL_OPEN] = 'Failed to open Customer Relationship ' . 'Management System URL "$URL" $MNUM: $ERROR'; // MSG_CRM_FAILED is sent in an Alert message if the TectiteCRM // system doesn't return an OK message // Parameters: // $URL the invalid URL // $MSG more information $aMessages[MSG_CRM_FAILED] = 'Failure report from Customer Relationship ' . 'Management System (url="$URL") $MNUM: $MSG'; // MSG_CRM_FORM_ERROR is shown to the user if the information // passed to TectiteCRM was not accepted // Parameters: none $aMessages[MSG_CRM_FORM_ERROR] = 'Your form submission was not accepted'; // MSG_AND is shown to the user; it shows two items separated // by "and" // Parameters: // $ITEM1 the first item // $ITEM2 the second item $aMessages[MSG_AND] = '"$ITEM1" and "$ITEM2"'; // MSG_OR is shown to the user; it shows two items separated // by "or" // Parameters: // $ITEM1 the first item // $ITEM2 the second item $aMessages[MSG_OR] = '"$ITEM1" or "$ITEM2"'; // MSG_NOT_BOTH is shown to the user; it shows two items that must // be specified together // Parameters: // $ITEM1 the first item // $ITEM2 the second item $aMessages[MSG_NOT_BOTH] = 'not both "$ITEM1" and "$ITEM2"'; // MSG_XOR is shown to the user; it shows two items that must // not be specified together // Parameters: // $ITEM1 the first item // $ITEM2 the second item $aMessages[MSG_XOR] = '"$ITEM1" or "$ITEM2" (but not both)'; // MSG_IS_SAME_AS is shown to the user; it shows two items that must // not be the same value // Parameters: // $ITEM1 the first item // $ITEM2 the second item $aMessages[MSG_IS_SAME_AS] = '"$ITEM1" is the same as "$ITEM2"'; // MSG_IS_NOT_SAME_AS is shown to the user; it shows two items that must // be the same value // Parameters: // $ITEM1 the first item // $ITEM2 the second item $aMessages[MSG_IS_NOT_SAME_AS] = '"$ITEM1" is not the same as "$ITEM2"'; // MSG_REQD_OPER is sent in an Alert message when an unknown // operator has been used in a "required" specification // Parameters: // $OPER the unknown operator $aMessages[MSG_REQD_OPER] = 'Operator "$OPER" is not valid for "required"'; // MSG_PAT_FAILED is sent in an Alert message when a "conditions" pattern // match has not matched anything (this isn't necessarily an error) // Parameters: // $OPER the "conditions" operator // $PAT the "conditions" pattern // $VALUE the value that was searched $aMessages[MSG_PAT_FAILED] = 'Pattern operator "$OPER" failed: pattern ' . '"$PAT", value searched was "$VALUE".'; // MSG_COND_OPER is sent in an Alert message when a "conditions" // operator is not value // Parameters: // $OPER the "conditions" operator $aMessages[MSG_COND_OPER] = 'Operator "$OPER" is not valid for "conditions"'; // MSG_INV_COND is sent in an Alert message when a "conditions" // field is not valid // Parameters: // FLD the field name $aMessages[MSG_INV_COND] = 'Invalid "conditions" field "$FLD" - not a string or array.'; // MSG_COND_CHARS is sent in an Alert message when a "conditions" // field is missing the mandatory first 2 characters (the separators) // Parameters: // FLD the field name // COND the conditions field value $aMessages[MSG_COND_CHARS] = 'The conditions field "$FLD" is not valid. ' . 'You must provide the two separator ' . 'characters at the beginning. You had "$COND".'; // MSG_COND_INVALID is sent in an Alert message when a "conditions" // field has the wrong format // Parameters: // FLD the field name // COND the conditions field value // SEP the internal separator character for the field. $aMessages[MSG_COND_INVALID] = 'The conditions field "$FLD" is not valid. ' . 'There must be at least 5 components ' . 'separated by "$SEP". Your value was "$COND".'; // MSG_COND_TEST_LONG is sent in an Alert message when a "conditions" // TEST value has too many components // Parameters: // FLD the field name // COND the conditions field value // SEP the list separator character for the field. $aMessages[MSG_COND_TEST_LONG] = 'Field "$FLD" has too many components for ' . 'a "TEST" command: "$COND".\nAre you missing ' . 'a "$SEP"?'; // MSG_COND_IF_SHORT is sent in an Alert message when a "conditions" // IF value has too few components // Parameters: // FLD the field name // COND the conditions field value // SEP the internal separator character for the field. $aMessages[MSG_COND_IF_SHORT] = 'Field "$FLD" has too few components for ' . 'an "IF" command: "$COND".\nThere must be ' . 'at least 6 components separated by "$SEP"'; // MSG_COND_IF_LONG is sent in an Alert message when a "conditions" // IF value has too many components // Parameters: // FLD the field name // COND the conditions field value // SEP the list separator character for the field. $aMessages[MSG_COND_IF_LONG] = 'Field "$FLD" has too many components for ' . 'an "IF" command: "$COND".\nAre you missing ' . 'a "$SEP"?'; // MSG_COND_UNK is sent in an Alert message when a "conditions" // value has an unknown command // Parameters: // FLD the field name // COND the conditions field value // CMD the unknown command $aMessages[MSG_COND_UNK] = 'Field "$FLD" has an unknown command word ' . '"$CMD": "$COND".'; // MSG_MISSING is sent in an Alert message when // a socket filter is incorrectly defined // Parameters: // ITEM the missing item $aMessages[MSG_MISSING] = 'Missing "$ITEM"'; // MSG_NEED_ARRAY is sent in an Alert message when // a socket filter is incorrectly defined // Parameters: // ITEM the item that should be an array $aMessages[MSG_NEED_ARRAY] = '"$ITEM" must be an array'; // MSG_SUBM_FAILED is shown to the user when an internal error // as occurred and that error is not to be shown // Parameters: none $aMessages[MSG_SUBM_FAILED] = 'Your form submission has failed due to ' . 'an error on our server.'; // MSG_FILTER_WRONG is sent in an Alert message when // a socket filter is incorrectly defined // Parameters: // FILTER the filter name // ERRORS a string containing a list of errors $aMessages[MSG_FILTER_WRONG] = 'Filter "$FILTER" is not properly defined: ' . '$ERRORS'; // MSG_FILTER_CONNECT is sent in an Alert message when FormMail // cannot connect to a socket filter // Parameters: // FILTER the filter name // SITE the site // ERRNUM socket error number // ERRSTR socket error message $aMessages[MSG_FILTER_CONNECT] = 'Could not connect to site "$SITE" ' . 'for filter "$FILTER" ($ERRNUM): $ERRSTR'; // MSG_FILTER_PARAM is sent in an Alert message when a socket // filter has an invalid parameter specification // Parameters: // FILTER the filter name // NUM parameter number // NAME parameter name $aMessages[MSG_FILTER_PARAM] = 'Filter "$FILTER" has invalid parameter ' . '#$NUM: no "$NAME"'; // MSG_FILTER_OPEN_FILE is sent in an Alert message when a socket // filter cannot open the required file // Parameters: // FILTER the filter name // FILE the file that could not be opened // ERROR the error message $aMessages[MSG_FILTER_OPEN_FILE] = 'Filter "$FILTER" cannot open file ' . '"$FILE": $ERROR'; // MSG_FILTER_FILE_ERROR is sent in an Alert message when a socket // filter gets an error message during reading a file // Parameters: // FILTER the filter name // FILE the file that could not be opened // ERROR the error message // NLINES the number of lines that were read successfully $aMessages[MSG_FILTER_FILE_ERROR] = 'Filter "$FILTER": read error on file ' . '"$FILE" after $NLINES lines: $ERROR'; // MSG_FILTER_READ_ERROR is sent in an Alert message when a socket // filter gets an error during reading from the socket // Parameters: // FILTER the filter name // ERROR the error message $aMessages[MSG_FILTER_READ_ERROR] = 'Filter "$FILTER" failed: read error: ' . '$ERROR'; // MSG_FILTER_NOT_OK is sent in an Alert message when a socket // filter fails to return the agreed __OK__ indicator // Parameters: // FILTER the filter name // DATA the data returned from the filter $aMessages[MSG_FILTER_NOT_OK] = 'Filter "$FILTER" failed (missing ' . '__OK__ line): $DATA'; // MSG_FILTER_UNK is sent in an Alert message // when an unknown filter is specified by a form // Parameters: // FILTER the filter name $aMessages[MSG_FILTER_UNK] = 'Unknown filter "$FILTER"'; // MSG_FILTER_CHDIR is sent in an Alert message // when FormMail cannot change to the filter's directory // Parameters: // FILTER the filter name // DIR the directory name // ERROR an error message from the system $aMessages[MSG_FILTER_CHDIR] = 'Cannot chdir to "$DIR" to run filter ' . '"$FILTER": $ERROR'; // MSG_FILTER_NOTFOUND is sent in an Alert message // when FormMail cannot execute the filter // Parameters: // FILTER the filter name // CMD the command line being executed // ERROR an error message from the system $aMessages[MSG_FILTER_NOTFOUND] = 'Cannot execute filter "$FILTER" with ' . 'command "$CMD": $ERROR'; // MSG_FILTER_ERROR is sent in an Alert message // when a filter returns a non-zero status // Parameters: // FILTER the filter name // ERROR an error message from the system // STATUS the status return from the command $aMessages[MSG_FILTER_ERROR] = 'Filter "$FILTER" failed (status $STATUS): ' . '$ERROR'; // MSG_SPARE is a spare message $aMessages[MSG_SPARE] = ''; // MSG_TEMPLATE_ERRORS is sent as part of an Alert message // when a template has generated some errors. The message // should end with a new line and the actual errors are // output after it. // Parameters: // NAME the template name $aMessages[MSG_TEMPLATE_ERRORS] = 'Template "$NAME" caused the ' . 'following errors $MNUM:\n'; // MSG_TEMPLATE_FAILED is sent in an Alert message // when processing a template has failed. // Parameters: // NAME the template name $aMessages[MSG_TEMPLATE_FAILED] = 'Failed to process template "$NAME"'; // MSG_MIME_PREAMBLE is sent in the preamble of MIME emails // Parameters: none $aMessages[MSG_MIME_PREAMBLE] = '(Your mail reader should not show this ' . 'text.\nIf it does you may need to ' . 'upgrade to more modern software.)'; // MSG_MIME_HTML is sent in the preamble of HTML emails // Parameters: // NAME the template name $aMessages[MSG_MIME_HTML] = 'This message has been generated by FormMail ' . 'using an HTML template\ncalled "$NAME". The ' . 'raw text of the form results\nhas been ' . 'included below, but your mail reader should ' . 'display the HTML\nversion only (unless it\'s ' . 'not capable of doing so).'; // MSG_FILE_OPEN_ERROR is sent in an Alert message when FormMail // cannot open a file // Parameters: // NAME the file name // TYPE the type of file // ERROR the system error message $aMessages[MSG_FILE_OPEN_ERROR] = 'Failed to open $TYPE file "$NAME": $ERROR'; // MSG_ATTACH_DATA is sent in an Alert message when the file // attachment through 'data' has gone wrong. // Parameters: none $aMessages[MSG_ATTACH_DATA] = 'Internal error: AttachFile requires ' . '"tmp_name" or "data"'; // MSG_PHP_HTML_TEMPLATES is sent in an Alert message when an // HTML template is used but the PHP version is too old. (deprecated) // Parameters: // $PHPVERS the current PHP version $aMessages[MSG_PHP_HTML_TEMPLATES] = ''; // MSG_PHP_FILE_UPLOADS is sent in an Alert message when // file upload is used but the PHP version is too old. (deprecated) // Parameters: // $PHPVERS the current PHP version $aMessages[MSG_PHP_FILE_UPLOADS] = ''; // MSG_FILE_UPLOAD is sent in an Alert message when // file upload is attempted but FormMail is not configured to allow // it // Parameters: none $aMessages[MSG_FILE_UPLOAD] = 'File upload attempt ignored'; // MSG_FILE_UPLOAD_ATTACK is sent in an Alert message when // possible file upload attack is detected // Parameters: // NAME file name // TEMP temporary file name // FLD name of the file upload field $aMessages[MSG_FILE_UPLOAD_ATTACK] = 'Possible file upload attack ' . 'detected: field="$FLD", name="$NAME" ' . 'temp name="$TEMP"'; // MSG_PHP_PLAIN_TEMPLATES is sent in an Alert message when a // Plain template is used but the PHP version is too old. (deprecated) // Parameters: // $PHPVERS the current PHP version $aMessages[MSG_PHP_PLAIN_TEMPLATES] = ''; // MSG_ATTACH_NAME is sent in an Alert message when a // the form uses the Attach feature without specifying a file name // Parameters: none $aMessages[MSG_ATTACH_NAME] = 'filter_options: Attach must contain a name ' . '(e.g. Attach=data.txt)'; // MSG_PHP_BCC is sent in an Alert message when a // the form uses the BCC feature and the PHP version may not support it // (deprecated) // Parameters: // $PHPVERS the current PHP version $aMessages[MSG_PHP_BCC] = ''; // MSG_CSVCOLUMNS is sent in an Alert message when a csvcolumns field // is not correct // Parameters: // $VALUE the csvcolumns field value $aMessages[MSG_CSVCOLUMNS] = 'The "csvcolumns" setting is not ' . 'valid: "$VALUE"'; // MSG_CSVFILE is sent in an Alert message when a csvfile field // is not correct // Parameters: // $VALUE the csvfile field value $aMessages[MSG_CSVFILE] = 'The "csvfile" setting is not valid: "$VALUE"'; // MSG_TARG_EMAIL_PAT_START is sent in an Alert message when a // $TARGET_EMAIL pattern is insecure because of a missing '^' // at the beginning // Parameters: // $PAT the pattern $aMessages[MSG_TARG_EMAIL_PAT_START] = 'Warning: Your TARGET_EMAIL pattern ' . '"$PAT" is missing a ^ at the ' . 'beginning.'; // MSG_TARG_EMAIL_PAT_END is sent in an Alert message when a // $TARGET_EMAIL pattern is insecure because of a missing '$' // at the end // Parameters: // $PAT the pattern $aMessages[MSG_TARG_EMAIL_PAT_END] = 'Warning: Your TARGET_EMAIL pattern ' . '"$PAT" is missing a $ at the end.'; // MSG_CONFIG_WARN is sent in an Alert message when the FormMail // configuration may have some problems. The messages are // passed on separate lines, so the line terminations below // are important. // Parameters: // $MESGS lines of messages $aMessages[MSG_CONFIG_WARN] = 'The following potential problems were found ' . 'in your configuration:\n$MESGS\n\n' . 'These are not necessarily errors, but you ' . 'should review the documentation\n' . 'inside formmail.php. If you are sure your ' . 'configuration is correct\n' . 'you can disable the above messages by ' . 'changing the CONFIG_CHECK settings.'; // MSG_PHP_AUTORESP is sent in an Alert message when the PHP version // does not support autoresponding (deprecated) // Parameters: // $PHPVERS current PHP version $aMessages[MSG_PHP_AUTORESP] = ''; // MSG_ALERT is the test alert message (formmail.php?testalert=1) // Parameters: // $LANG the language ID // $PHPVERS PHP version // $FM_VERS FormMail version // $SERVER server type // $DOCUMENT_ROOT PHP's DOCUMENT_ROOT value // $SCRIPT_FILENAME PHP's SCRIPT_FILENAME value // $PATH_TRANSLATED PHP's PATH_TRANSLATED value // $REAL_DOCUMENT_ROOT the REAL_DOCUMENT_ROOT value $aMessages[MSG_ALERT] = 'This is a test alert message $MNUM\n' . 'Loaded language is $LANG\n' . 'PHP version is $PHPVERS\n' . 'FormMail version is $FM_VERS\n' . 'Server type: $SERVER\n' . '\n' . 'DOCUMENT_ROOT: $DOCUMENT_ROOT\n' . 'SCRIPT_FILENAME: $SCRIPT_FILENAME\n' . 'PATH_TRANSLATED: $PATH_TRANSLATED\n' . 'REAL_DOCUMENT_ROOT: $REAL_DOCUMENT_ROOT'; // MSG_NO_DEF_ALERT is displayed if you use the testalert feature // and no DEF_ALERT setting has been provided. // Parameters: none $aMessages[MSG_NO_DEF_ALERT] = 'No DEF_ALERT value has been set.'; // MSG_TEST_SENT is displayed if when use the testalert feature // Parameters: none $aMessages[MSG_TEST_SENT] = 'Test message sent. Check your email.'; // MSG_TEST_FAILED is displayed if when use the testalert feature // and the mail sending fails. // Parameters: none $aMessages[MSG_TEST_FAILED] = 'FAILED to send alert message. Check your ' . 'server error logs.'; // MSG_NO_DATA_PAGE is the page that's displayed if the user // just opens the URL to FormMail directly. // Parameters: none $aMessages[MSG_NO_DATA_PAGE] = 'This URL is a Form submission program.\n' . 'It appears the form is not working ' . 'correctly as there was no data found.\n' . 'You\'re not supposed to browse to this ' . 'URL; it should be accessed from a form.'; // MSG_REQD_ERROR is displayed to the user as a default error // message when they haven't supplied some required fields // Parameters: none $aMessages[MSG_REQD_ERROR] = 'The form required some values that you ' . 'did not seem to provide.'; // MSG_COND_ERROR is displayed to the user as a default error // message when some form conditions have failed // Parameters: none $aMessages[MSG_COND_ERROR] = 'Some of the values you provided are not valid.'; // MSG_CRM_FAILURE is displayed to the user when submission // to the CRM has failed. // Parameters: // $URL the URL that was used // $DATA data returned from the CRM $aMessages[MSG_CRM_FAILURE] = 'The form submission did not succeed due to ' . 'a CRM failure. URL was \'$URL\'. ' . 'Returned CRM data:\n$DATA'; // MSG_FOPTION_WARN is sent in an Alert message when the form // uses the superseded SendMailFOption feature // Parameters: // $LINE line number for SENDMAIL_F_OPTION $aMessages[MSG_FOPTION_WARN] = 'Warning: You\'ve used SendMailFOption in ' . '"mail_options" in your form. This has been ' . 'superseded with a configuration setting ' . 'inside formmail.php. Please update your ' . 'formmail.php configuration (look for ' . 'SENDMAIL_F_OPTION on line $LINE) and set ' . 'it to "true", then remove SendMailFOption ' . 'from your form(s).'; // MSG_NO_ACTIONS is sent in an Alert message when there is no // action to perform or email address to send to // Parameters: none $aMessages[MSG_NO_ACTIONS] = 'The form has an internal error - no actions ' . 'or recipients were specified.'; // MSG_NO_RECIP is sent in an Alert message when there are no // valid recipients to send to // Parameters: none $aMessages[MSG_NO_RECIP] = 'The form has an internal error - no valid ' . 'recipients were specified.'; // MSG_INV_EMAIL is sent in an Alert message when there are errors // in the email addresses specified in the form // Parameters: // $ERRORS list of errors $aMessages[MSG_INV_EMAIL] = 'Invalid email addresses were specified ' . 'in the form $MNUM:\n$ERRORS'; // MSG_FAILED_SEND is sent in an Alert message when the mail sending fails. // Parameters: none $aMessages[MSG_FAILED_SEND] = 'Failed to send email'; // MSG_ARESP_EMAIL is sent in an Alert message when // no email address has been specified for an autoreponse // Parameters: none $aMessages[MSG_ARESP_EMAIL] = 'No "email" field was found. Autorespond ' . 'requires the submitter\'s email address.'; // MSG_ARESP_SUBJ is the default subject for the auto response email // Parameters: none $aMessages[MSG_ARESP_SUBJ] = 'Your form submission'; // MSG_LOG_NO_VERIMG is written to the auto respond log file // if no VerifyImgString session variable was found // Parameters: none $aMessages[MSG_LOG_NO_VERIMG] = 'No VerifyImgString or turing_string in session, ' . 'no reverse CAPTCHA, no reCaptcha'; // MSG_ARESP_NO_AUTH is shown to the user // if no VerifyImgString session variable was found // Parameters: none $aMessages[MSG_ARESP_NO_AUTH] = 'Failed to obtain authorization to send ' . 'you email. This is probably a fault on ' . 'the server.'; // MSG_LOG_NO_MATCH is written to the auto respond log file // if the user's entry did not match the image verification // Parameters: none $aMessages[MSG_LOG_NO_MATCH] = 'User did not match image'; // MSG_LOG_RECAPTCHA is written to the auto respond log file // if the reCaptcha process fails // Parameters: // ERR the reCaptcha error code $aMessages[MSG_LOG_RECAPTCHA] = 'reCaptcha process failed ($ERR)'; // MSG_ARESP_NO_MATCH is shown to the user // if the user's entry did not match the image verification // Parameters: none $aMessages[MSG_ARESP_NO_MATCH] = 'Your entry did not match the image'; // MSG_LOG_FAILED is written to the auto respond log file // if the autoresponding failed // Parameters: none $aMessages[MSG_LOG_FAILED] = 'Failed'; // MSG_ARESP_FAILED is sent in an Alert message // if the autoresponding failed // Parameters: none $aMessages[MSG_ARESP_FAILED] = 'Autoresponder failed'; // MSG_LOG_OK is written to the auto respond log file // if the autoresponding succeeded // Parameters: none $aMessages[MSG_LOG_OK] = 'OK'; // MSG_THANKS_PAGE is the default page that's displayed if the // submission is successful // Parameters: none $aMessages[MSG_THANKS_PAGE] = 'Thanks! We\'ve received your information ' . 'and, if it\'s appropriate, we\'ll be in ' . 'contact with you soon.'; // MSG_LOAD_MODULE is sent in an alert message if a module // could not be loaded. // Parameters: // $FILE the file name // $ERROR the error message $aMessages[MSG_LOAD_MODULE] = 'Cannot load module from file \'$FILE\': $ERROR'; // MSG_LOAD_FMCOMPUTE is sent in an alert message if the form // specifies at least one "fmcompute" field and the FMCompute // module cannot be loaded. // Parameters: // $FILE the file name // $ERROR the error message $aMessages[MSG_LOAD_FMCOMPUTE] = 'Cannot load FMCompute module from file ' . '\'$FILE\': $ERROR'; // MSG_REGISTER_MODULE is sent in an alert message if a module // could not register with FMCompute // Parameters: // $NAME the name of the module // $ERROR the error message $aMessages[MSG_REGISTER_MODULE] = 'Cannot register module $NAME with ' . 'FMCompute: $ERROR'; // MSG_COMP_PARSE is sent in an alert message if a parse error // occurs in an fmcompute field // Parameters: // $CODE the code with an error // $ERRORS the error messages $aMessages[MSG_COMP_PARSE] = 'These parse errors occurred in the following ' . 'code:\n$ERRORS\n$CODE'; // MSG_COMP_REG_DATA is sent in an alert message if FormMail cannot // register a data field with the FMCompute module // Parameters: // $NAME the field name // $ERROR the error message $aMessages[MSG_COMP_REG_DATA] = 'Failed to register data field \'$NAME\': ' . '$ERROR'; // MSG_COMP_ALERT is sent in an alert message if the FMCompute // module has generated some alert messages. // Parameters: // $ALERTS the alerts $aMessages[MSG_COMP_ALERT] = 'The following alert messages were reported ' . 'from the FMCompute module: $ALERTS'; // MSG_COMP_DEBUG is sent in an alert message if the FMCompute // module has generated some debug messages. // Parameters: // $DEBUG the alerts $aMessages[MSG_COMP_DEBUG] = 'The following debug messages were reported ' . 'from the FMCompute module: $DEBUG'; // MSG_COMP_EXEC is sent in an alert message if the FMCompute // module has generated some error messages during execution // Parameters: // $ERRORS the errors $aMessages[MSG_COMP_EXEC] = 'The following error messages were reported ' . 'from the FMCompute module: $ERRORS'; // MSG_TEMPL_ALERT is sent in an alert message if Advanced Template // Processing has generated some alert messages. // Parameters: // $ALERTS the alerts $aMessages[MSG_TEMPL_ALERT] = 'The following alert messages were reported ' . 'from the Advanced Template Processor: $ALERTS'; // MSG_TEMPL_DEBUG is sent in an alert message if Advanced Template // Processing has generated some debug messages. // Parameters: // $DEBUG the alerts $aMessages[MSG_TEMPL_DEBUG] = 'The following debug messages were reported ' . 'from the Advanced Template Processor: $DEBUG'; // MSG_TEMPL_PROC is sent in an alert message if Advanced Template Processing // has generated some error messages during processing // Parameters: // $ERRORS the errors $aMessages[MSG_TEMPL_PROC] = 'The following error messages were reported ' . 'from the Advanced Template Processor: $ERRORS'; // MSG_REG_FMCOMPUTE is sent in an Alert message when FormMail // cannot register an external function with FMCompute. // Parameters: // FUNC the function that could not be registered // ERROR the error message $aMessages[MSG_REG_FMCOMPUTE] = 'Cannot register function "$FUNC" with ' . 'FMCompute: $ERROR'; // MSG_USER_ERRORS is shown as part of a user error when an FMCompute // has called the "UserError" function one or more times. // Parameters: // NONE $aMessages[MSG_USER_ERRORS] = 'One or more errors occurred in your form submission'; // MSG_CALL_PARAM_COUNT is sent in an alert when a call to a FormMail // function from FMCompute has the wrong number of parameters // Parameters: // FUNC the function name // COUNT the actual number of parameters passed $aMessages[MSG_CALL_PARAM_COUNT] = 'FMCompute called FormMail function ' . '\'$FUNC\' with wrong number of ' . 'parameters: $COUNT'; // MSG_CALL_UNK_FUNC is sent in an alert when FMCompute calls an // unknown FormMail function // Parameters: // FUNC the function name $aMessages[MSG_CALL_UNK_FUNC] = 'FMCompute called unknown FormMail function ' . '\'$FUNC\''; // MSG_SAVE_FILE is sent in an alert when saving a file to // the server has failed // Parameters: // FILE the source file name (usually a temporary file name) // DEST the destination file name // ERR the error message $aMessages[MSG_SAVE_FILE] = 'Failed to save file \'$FILE\' to \'$DEST\': $ERR'; // MSG_SAVE_FILE_EXISTS is sent as part of an alert when saving a file to // the repository ($FILE_REPOSITORY) has failed because the file // already exists and FILE_OVERWRITE is set to false. // Parameters: // FILE the destination file name $aMessages[MSG_SAVE_FILE_EXISTS] = 'Cannot save file to repository as this would ' . 'overwrite \'$FILE\' and you have ' . 'set FILE_OVERWRITE to false.'; // MSG_EMPTY_ADDRESSES is sent as part of an alert when a number of empty // email addresses have been specified in recipients, cc, or bcc // *and* there are no valid addresses provided // in the list // Parameters: // COUNT the number of empty addresses $aMessages[MSG_EMPTY_ADDRESSES] = '$COUNT empty addresses'; // MSG_CALL_INVALID_PARAM is sent in an alert when a call to a FormMail // function from FMCompute has an invalid parameter // Parameters: // FUNC the function name // PARAM the parameter number // CORRECT information about correct values $aMessages[MSG_CALL_INVALID_PARAM] = 'FMCompute called FormMail function ' . '\'$FUNC\' with an invalid parameter ' . 'number $PARAM. Correct values are: $CORRECT'; // MSG_INI_PARSE_WARN is sent in an alert when the INI file // may have a syntax error and cannot be parsed. // Parameters: // FILE the file name $aMessages[MSG_INI_PARSE_WARN] = 'Warning: your INI file \'$FILE\' appears ' . 'to be empty. This may indicate a syntax error.'; // MSG_INI_PARSE_ERROR is shown as an error message when the INI file // has a syntax error and cannot be parsed. // Parameters: // FILE the file name $aMessages[MSG_INI_PARSE_ERROR] = 'The FormMail INI file \'$FILE\' has a syntax error'; // MSG_CHMOD is sent in an alert when changing the protection // mode of a file to has failed // Parameters: // FILE the file name // MODE the mode // ERR the error message $aMessages[MSG_CHMOD] = 'Failed to change protection mode of file \'$FILE\' ' . 'to $MODE: $ERR'; // MSG_VERIFY_MISSING is shown to the user image verification string // was not found // Parameters: none $aMessages[MSG_VERIFY_MISSING] = 'Image verification string missing. This' . ' is probably a fault on the server.'; // MSG_VERIFY_MATCH is shown to the user // if the user's entry did not match the image verification for the // imgverify option // Parameters: none $aMessages[MSG_VERIFY_MATCH] = 'Your entry did not match the image'; // MSG_RECAPTCHA_MATCH is shown to the user // if using the reCaptcha system and there was an error // Parameters: // ERR the error code from the reCaptcha API $aMessages[MSG_RECAPTCHA_MATCH] = 'reCaptcha verification failed ($ERR)'; // MSG_FILE_NAMES_INVALID is sent in an Alert message when // a form's file_names setting has errors // Parameters: none // A list of errors is appended on separate lines $aMessages[MSG_FILE_NAMES_INVALID] = 'Some file_names specifications are invalid $MNUM:\n'; // MSG_FILE_NAMES_NOT_FILE is sent in an Alert message when // a form's file_names setting refers to a file field that doesn't // exist // Parameters: // NAME the name of the file field that doesn't exist $aMessages[MSG_FILE_NAMES_NOT_FILE] = 'Your file_names specification has ' . 'an error. \'$NAME\' is not the name ' . 'of a file upload field\n'; // MSG_NEXT_PLUS_GOOD is sent in an alert message if the form is // ambiguous and specifies both "next_form" and "good_url" or // "good_template" // Parameters: // $WHICH the "good_" field that was specified $aMessages[MSG_NEXT_PLUS_GOOD] = 'The form has specified both "next_form" ' . 'and "$WHICH" fields - the action to ' . 'to perform is ambiguous'; // MSG_MULTIFORM is sent in an Alert message when a form tries // to use a multi-form template, but templates have not been configured in // formmail.php // Parameters: none $aMessages[MSG_MULTIFORM] = 'You must set either MULTIFORMDIR or MULTIFORMURL ' . 'in formmail.php before you can use ' . 'multi-page forms.'; // MSG_MULTIFORM_FAILED is sent in an Alert message // when processing a multi-page form template has failed. // Parameters: // NAME the template name $aMessages[MSG_MULTIFORM_FAILED] = 'Failed to process multi-page form template "$NAME"'; // MSG_NEED_THIS_FORM is sent in an Alert message // when a multi-page form does not specify the "this_form" field. // Parameters: // none $aMessages[MSG_NEED_THIS_FORM] = 'Multi-page forms require "this_form" field'; // MSG_NO_PHP_SELF is sent in an Alert message // when FormMail requires the "PHP_SELF" server variable and PHP is not // providing it. // Parameters: // none $aMessages[MSG_NO_PHP_SELF] = 'PHP on the server is not providing "PHP_SELF"'; // MSG_RETURN_URL_INVALID is sent in an Alert message // when "this_form" is not a valid return URL. This occurs for // multi-page forms. // Parameters: // URL the invalid URL $aMessages[MSG_RETURN_URL_INVALID] = 'Return URL "$URL" is not valid'; // MSG_GO_BACK is sent in an Alert message // when "multi_go_back" has been submitted but this isn't part of a // multi-page form. // Parameters: // none $aMessages[MSG_GO_BACK] = 'Cannot "go back" if not in a multi-page form ' . 'sequence or at the first page of the form ' . 'sequence'; // MSG_OPEN_URL is sent in an Alert message when a URL cannot // be opened. // Parameters: // URL the invalid URL // ERROR error message $aMessages[MSG_OPEN_URL] = 'Cannot open URL "$URL": $ERROR'; // MSG_CANNOT_RETURN is sent in an Alert message when an invalid return // request is made in a multi-page form sequence. // Parameters: // TO the requested page index // TOPINDEX the top page index $aMessages[MSG_CANNOT_RETURN] = 'Cannot return to page $TO. The top page ' . 'index is $TOPINDEX'; // MSG_ATTACK_DETECTED is sent in an Alert message when an attack on // the server has been detected // Parameters: // ATTACK name or description of the attack // INFO more information about the attack $aMessages[MSG_ATTACK_DETECTED] = 'Server attack "$ATTACK" detected. ' . 'Your server is safe as FormMail is ' . 'invulnerable to this attack. You can ' . 'disable these messages by setting ' . 'ALERT_ON_ATTACK_DETECTION to false ' . 'in FormMail\'s configuration section.' . '\nMore information:\n$INFO'; // MSG_ATTACK_PAGE is the contents of the browser page displayed to the // user when an attack is detected // Parameters: // SERVER the name of the server (website) // USERINFO details of the error $aMessages[MSG_ATTACK_PAGE] = 'Your form submission has been rejected ' . 'as it appears to be an abuse of our server (' . '$SERVER).
The following settings were found in the file '$s_file':
"; foreach ($a_sections as $s_sect => $a_settings) { $s_text .= "[$s_sect]\n"; foreach ($a_settings as $s_name => $s_value) { $s_text .= "$s_name = \"$s_value\"\n"; } $s_text .= "
"; } CreatePage($s_text,"Debug Output - INI File Display"); FormMailExit(); } // // Load the email_addresses section. // if (isset($a_sections["email_addresses"])) { $a_addr_list = $a_sections["email_addresses"]; // // make these addresses valid // foreach ($a_addr_list as $s_alias => $s_list) { $EMAIL_ADDRS[$s_alias] = $s_list; $ValidEmails->AddAddresses($s_list); } } // // Process special fields // if (isset($a_sections["special_fields"])) { foreach ($a_sections["special_fields"] as $s_name => $m_value) { if (IsSpecialField($s_name)) { ValidateSpecialField($s_name,$s_value,false); SetSpecialField($s_name,$m_value); // // if this is the recipients, cc, or bcc field, // make the addresses valid // if ($s_name === "recipients" || $s_name === "cc" || $s_name === "bcc") // // coming from the INI file, the values can only be strings // { if (is_string($m_value)) { $ValidEmails->AddAddresses($m_value); } } } // // check for multiple valued special fields // if (($a_multi_fld = IsSpecialMultiField($s_name)) !== false) { SetSpecialMultiField($a_multi_fld[0],$a_multi_fld[1],$m_value); } } } } /** * UnMangle an email address. This means replacing AT_MANGLE in the given * string with the @ symbol. * It can also lookup an email alias and return the corresponding email address. * Email aliases are defined in the EMAIL_ADDRS configuration setting or in an INI file. * * @param string $s_email the email address to unmangle * * @return string the actual email address */ function UnMangle($s_email) { $email_addrs = Settings::get('EMAIL_ADDRS'); // // map from a name to the real email address; if it exists // if (isset($email_addrs[$s_email])) { $s_email = $email_addrs[$s_email]; } // // unmangle // if (Settings::get('AT_MANGLE') != "") { $s_email = str_replace(Settings::get('AT_MANGLE'),"@",$s_email); } return ($s_email); } // // Check a list of email addresses (comma separated); returns a list // of valid email addresses (comma separated). // The list can be an array of comma separated lists. // The return value is true if there is at least one valid email address. // function CheckEmailAddress($m_addr,&$s_valid,&$s_invalid,$b_check = true) { global $ValidEmails; $s_invalid = $s_valid = ""; if (is_array($m_addr)) { $a_list = array(); foreach ($m_addr as $s_addr_list) { $a_list = array_merge($a_list,TrimArray(explode(",",$s_addr_list))); } } else { $a_list = TrimArray(explode(",",$m_addr)); } $a_invalid = array(); $n_empty = 0; for ($ii = 0 ; $ii < count($a_list) ; $ii++) { if ($a_list[$ii] === "") { // // ignore, but count empty addresses // $n_empty++; continue; } $s_email = UnMangle($a_list[$ii]); // // UnMangle works with INI files too, and a single // word can expand to a list of email addresses. // $a_this_list = TrimArray(explode(",",$s_email)); foreach ($a_this_list as $s_email) { if ($s_email === "") { // // ignore, but count empty addresses // $n_empty++; continue; } if ($b_check) { $b_is_valid = $ValidEmails->CheckAddress($s_email); } else { $b_is_valid = true; } if ($b_is_valid) { if (empty($s_valid)) { $s_valid = $s_email; } else { $s_valid .= "," . $s_email; } } else { $a_invalid[] = $s_email; } } } // // just ignore empty recipients unless there are *no* valid recipients // if (empty($s_valid) && $n_empty > 0) { $a_invalid[] = GetMessage(MSG_EMPTY_ADDRESSES,array("COUNT" => $n_empty)); } if (count($a_invalid) > 0) { $s_invalid = implode(",",$a_invalid); } return (!empty($s_valid)); } // // Redirect to another URL // function Redirect($url,$title) { global $ExecEnv; // // for browsers without cookies enabled, append the Session ID // if ($ExecEnv->allowSessionURL()) { if (session_id() !== "") { $url = AddURLParams($url,session_name() . "=" . urlencode(session_id())); } elseif (defined("SID")) { $url = AddURLParams($url,SID); } } //FMDebug("Before redirecting, FormData = ".(isset($_SESSION["FormData"]) ? var_export($_SESSION["FormData"],true) : "NULL")); // // this is probably a good idea to ensure the session data // is written away // if (function_exists('session_write_close')) { session_write_close(); } header("Location: $url"); // // avoid XSS by sanitizing the URL // $url = stripJS(filter_var($url,FILTER_SANITIZE_STRING)); // // if the header doesn't work, try JavaScript. // if that doesn't work, provide a manual link // $s_text = GetMessage(MSG_PLSWAIT_REDIR) . "\n\n"; $s_text .= ""; $s_text .= "\n\n" . GetMessage(MSG_IFNOT_REDIR,array("URL" => $url)); CreatePage($s_text,$title); FormMailExit(); } /** * Remove 'javascript:' from the given text. * * @param string $s_text the text to be modified * * @return string|string[] */ function stripJS($s_text) { return str_ireplace('javascript:','',$s_text); } class JSON { function _Format($m_val) { if (is_bool($m_val)) { $s_value = ($m_val) ? "true" : "false"; } elseif (is_string($m_val)) { // // convert literal line breaks into JavaScript escape sequences // $s_value = '"' . str_replace(array("\r","\n"),array('\\r','\\n'),addslashes($m_val)) . '"'; } elseif (is_numeric($m_val)) { $s_value = $m_val; } elseif (is_array($m_val)) { $s_value = $this->_FormatArray($m_val); } else { $s_value = "null"; } return ($s_value); } function _FormatArray($a_array) { if ($this->_IsNumericArray($a_array)) { $a_values = array(); foreach ($a_array as $m_val) { $a_values[] = $this->_Format($m_val); } $s_value = "[" . implode(",",$a_values) . "]"; } else { // // associative arrays are objects // $s_value = $this->MakeObject($a_array); } return ($s_value); } // // check if we have a numeric array or an associative array // numeric arrays may have holes; numeric array indexes must // be integers // function _IsNumericArray($a_data) { if (empty($a_data)) { return (true); } // empty array - treat as numeric // // check all the keys for numeric // $a_keys = array_keys($a_data); foreach ($a_keys as $m_index) { if (!is_int($m_index)) { return (false); } } return (true); } function MakeObject($a_data) { $a_members = array(); foreach ($a_data as $s_key => $m_val) { $a_members[] = '"' . $s_key . '":' . $this->_Format($m_val); } return ("{" . implode(",",$a_members) . "}"); } } function CORS_Response() { header('Access-Control-Allow-Origin: *'); header('Access-Control-Max-Age: 36000'); header('Access-Control-Allow-Methods: GET, POST, OPTIONS'); header('Access-Control-Allow-Headers: X-Requested-With'); } function JSON_Result($s_result,$a_data = array()) { global $aGetVars; FMDebug("Sending JSON_Result: $s_result"); $a_data["Result"] = $s_result; $json = new JSON(); $s_ret = $json->MakeObject($a_data); CORS_Response(); // // handle JSONP request // if (isset($aGetVars['callback']) && $aGetVars['callback'] != '') { header('Content-Type: text/javascript; charset=utf-8'); $s_ret = $aGetVars['callback'] . "($s_ret);"; FMDebug('JSONP request callback=' . $aGetVars['callback']); } else { header('Content-Encoding: utf-8'); header('Content-Type: application/json; charset=utf-8'); } FMDebug("JSON_Result output: " . $s_ret); echo $s_ret; } // // JoinLines is just like "implode" except that it checks // the end of each array for the separator already being // there. This allows us to join a mixture of mail // header lines (already terminated) with body lines. // This logic works if HEAD_CRLF, for example, is the same // as BODY_LF (i.e. both "\r\n") or if BODY_LF is the // same as the last character in HEAD_CRLF (i.e. // HEAD_CRLF = "\r\n" and BODY_LF = "\n"). // Other value combinations may break things. // function JoinLines($s_sep,$a_lines) { $s_str = ""; if (($i_sep_len = strlen($s_sep)) == 0) // // no separator // { return (implode("",$a_lines)); } $n_lines = count($a_lines); for ($ii = 0 ; $ii < $n_lines ; $ii++) { $s_line = $a_lines[$ii]; if (substr($s_line,-$i_sep_len) == $s_sep) { $s_str .= $s_line; } else { $s_str .= $s_line; // // don't append a separator to the last line // if ($ii < $n_lines - 1) { $s_str .= $s_sep; } } } return ($s_str); } // // Re-orders an array of email headers into the // order recommended by RFC822, section 4.1: // It is recommended that, if present, // headers be sent in the order "Return- // Path", "Received", "Date", "From", "Subject", // "Sender", "To", "cc", etc. // // Note that RFC822 is obsoleted by RFC2822 and // the latter states that field order doesn't // matter (except for some tracing fields). // However, a FormMail user reported that Yahoo doesn't like // email where the CC header appears before the From // header. So, as always, we try to work with broken // servers too... // // Returns an array indexed by the require numerical // order. Each element is an array containing the // header value (name,value pair). // function OrderHeaders($a_headers) { // // we list the headers we're responsible for // in the order suggested // $a_ordering = array("From","Subject","To","Cc","Bcc","Reply-To"); $a_ordered_headers = array(); foreach ($a_ordering as $s_name) { if (isset($a_headers[$s_name])) { $a_ordered_headers[] = array($s_name => $a_headers[$s_name]); unset($a_headers[$s_name]); } } // // now add in the remaining headers // foreach ($a_headers as $s_name => $s_value) { $a_ordered_headers[] = array($s_name => $a_headers[$s_name]); } return ($a_ordered_headers); } // // Makes a mail header field body "safe". // This simply places a backslash in front of every double-quote. // There's probably more we could do if required, but this // attempts to provide the same protection that was in the first // version of FormMail. In that version, every incoming // field had double-quotes replaced with single quotes. // That processing is no longer performed, and this // function is used to protect against potential attacks in // header fields - not by replacing double quotes with single quotes, // but by using the backslash "quoting" feature of RFC2822. // // This code could be improved by parsing the header and rewriting // it to be valid, possibly removing junk. // // That's a lot of code, though! // function SafeHeader($s_str) { return (str_replace('"','\\"',$s_str)); } // // makes a string safe to put as words in a header // function SafeHeaderWords($s_str) { // // We zap various characters and replace them with a question mark. // Also, we don't handle quoted strings, which are valid words. // $s_specials = '()<>@,;:\\".[]'; // special characters defined by RFC822 $s_str = preg_replace('/[[:cntrl:]]+/',"?",$s_str); // zap all control chars $s_str = preg_replace("/[" . preg_quote($s_specials,"/") . "]/","?",$s_str); // zap all specials return ($s_str); } // // makes a string safe to put as a quoted string in a header // function SafeHeaderQString($s_str) { return (str_replace('"','\\"', str_replace("\\","\\\\", str_replace("\r"," ", str_replace("\r\n"," ",$s_str))))); } // // makes a string safe to put in a header comment // function SafeHeaderComment($s_str) { return (str_replace("(","\\(", str_replace(")","\\)", str_replace("\\","\\\\", str_replace("\r"," ", str_replace("\r\n"," ",$s_str)))))); } // // makes a string safe to put in a header as an email address // function SafeHeaderEmail($s_str) { // // An email address is made up of local and domain parts // each of these is made up of "words" separated by "." // each "word" can be a sequence of characters excluding // specials, space and control characters OR it can be // a quoted string. // // The correct processing would be to completely // parse the address, strip junk, double-quote // words that need to be turned into quote strings, // and return a well-formed email address. // // That's a lot of code! // // So, instead, we opt for stripping out control characters. // $s_str = preg_replace('/[[:cntrl:]]+/',"",$s_str); // zap all control chars return ($s_str); } // // Expands an array of mail headers into mail header lines. // function ExpandMailHeaders($a_headers,$b_fold = false) { $s_hdrs = ""; $a_ordered_headers = OrderHeaders($a_headers); for ($ii = 0 ; $ii < count($a_ordered_headers) ; $ii++) { foreach ($a_ordered_headers[$ii] as $s_name => $s_value) { if ($s_name != "") { if ($s_hdrs != "") { $s_hdrs .= Settings::get('HEAD_CRLF'); } if ($b_fold) { $s_hdrs .= HeaderFolding($s_name . ": " . $s_value); } else { $s_hdrs .= $s_name . ": " . $s_value; } } } } //FMDebug("Headers are: $s_hdrs"); return ($s_hdrs); } // // Expands an array of mail headers into an array containing header lines. // function ExpandMailHeadersArray($a_headers) { $a_hdrs = array(); $a_ordered_headers = OrderHeaders($a_headers); for ($ii = 0 ; $ii < count($a_ordered_headers) ; $ii++) { foreach ($a_ordered_headers[$ii] as $s_name => $s_value) { if ($s_name != "") { $a_hdrs[] = $s_name . ": " . $s_value . Settings::get('HEAD_CRLF'); } } } return ($a_hdrs); } // // Low-level email send function; either calls PHP's mail function // or uses the PEAR Mail object. // NOTE: for some errors, there's no point trying to email // an alert message! So, in these cases, we just display the error to // the user. // $s_options are ignored for PEAR sending. // function DoMail($s_to,$s_subject,$s_mesg,$a_headers,$s_options) { global $ALT_MAIL_FUNCTION; if ($ALT_MAIL_FUNCTION !== '') { return ($ALT_MAIL_FUNCTION($s_to,$s_subject,$s_mesg,$a_headers,$s_options)); } else { // // Encode the subject line. // Ideally, we want to encode the relevant parts of To, From, Cc, // Reply-To, and this is the right place to do it. // However, it's another 1000 lines of code! // So, we must compromise the code quality because of this cost. // We encode subject here, and we encode the From line where it's // created. The rest remain for a future version where code size // can be controlled. // $s_subject = EncodeHeaderText($s_subject); if (!Settings::isEmpty('PEAR_SMTP_HOST')) { // // Note that PEAR Mail seems to take responsibility for header line folding // require_once("Mail.php"); $a_params = array("host" => Settings::get('PEAR_SMTP_HOST'), "port" => Settings::get('PEAR_SMTP_PORT') ); if (!Settings::isEmpty('PEAR_SMTP_USER')) { $a_params["auth"] = TRUE; $a_params["username"] = Settings::get('PEAR_SMTP_USER'); $a_params["password"] = Settings::get('PEAR_SMTP_PWD'); } $mailer = Mail::factory("smtp",$a_params); if (!is_object($mailer)) { ShowError("pear_error",GetMessage(MSG_PEAR_OBJ),FALSE,FALSE); FormMailExit(); } if (strtolower(get_class($mailer)) === 'pear_error') { ShowError("pear_error",$mailer->getMessage(),FALSE,FALSE); FormMailExit(); } if (!isset($a_headers['To']) && !isset($a_headers['to'])) { $a_headers['To'] = SafeHeader($s_to); } if (!isset($a_headers['Subject']) && !isset($a_headers['subject'])) { $a_headers['Subject'] = SafeHeader($s_subject); } $res = $mailer->send($s_to,$a_headers,$s_mesg); if ($res === TRUE) { return (TRUE); } global $aAlertInfo; $aAlertInfo[] = GetMessage(MSG_PEAR_ERROR,array("MSG" => $res->getMessage())); return (FALSE); } else { //$s_subject = HeaderFolding($s_subject,RFCLINELEN-10); // "Subject: " is about 10 chars // // Notes from Feb 2010.... // // PHP's mail function (tested in version 5.2.6) does folding of the // To line and the Subject line. // If we do it, then things break. // // This area is quite confusing. It's not clear whether the script // should be folding header lines or whether the MTA should do it. // We *do know* (as stated above) that folding To and Subject breaks things. // // But folding other header lines properly, seems to be OK. // // However, for years FormMail never did header line folding (except for the // soft line breaks inserted by the quoted_printable_encode function we had used), // and we didn't seem to get any reports of breakage (except for problems // with the quoted_printable_encode soft line breaks!). // // So, even though we've implemented all the code for header line folding, // we'll not use it. // No header line folding will be performed in version 8.22 onwards. // if ($s_options !== "") { return (mail($s_to,$s_subject,$s_mesg,ExpandMailHeaders($a_headers),$s_options)); } else { return (mail($s_to,$s_subject,$s_mesg,ExpandMailHeaders($a_headers))); } } } } // // Send an email // function SendCheckedMail($to,$subject,$mesg,$sender,$a_headers = array()) { $b_f_option = false; $b_form_option = IsMailOptionSet("SendMailFOption"); // this is superseded, but still supported if (Settings::get('SENDMAIL_F_OPTION') || $b_form_option) { if (empty($sender)) { // // SENDMAIL_F_OPTION with no sender is silently ignored // if ($b_form_option) { // // form has specified SendMailFOption, but there's no // sender address // static $b_in_here = false; global $SERVER; if (!$b_in_here) // prevent infinite recursion { $b_in_here = true; SendAlert(GetMessage(MSG_NO_FOPT_ADDR)); $b_in_here = false; } // // if there's no from address, create a dummy one // $sender = "dummy@" . (isset($SERVER) ? $SERVER : "UnknownServer"); $a_headers['From'] = $sender; $b_f_option = true; } } else { $b_f_option = true; } } if (Settings::get('INI_SET_FROM') && !empty($sender)) { ini_set('sendmail_from',$sender); } return (DoMail($to,$subject,$mesg,$a_headers,($b_f_option ? "-f$sender" : ""))); } // // Send an alert email, but not if ATTACK_DETECTION_IGNORE_ERRORS is true. // function SendAlertIgnoreSpam($s_error,$b_filter = true,$b_non_error = false) { if (!Settings::get('ATTACK_DETECTION_IGNORE_ERRORS')) { SendAlert($s_error,$b_filter,$b_non_error); } } // // Send an alert email // function SendAlert($s_error,$b_filter = true,$b_non_error = false) { global $SPECIAL_VALUES,$FORMATTED_INPUT,$aServerVars,$aStrippedFormVars; global $aAlertInfo,$aCleanedValues,$aFieldOrder,$sHTMLCharSet; // // The following initialisations are so that ShowError can run from fmhookpreinit scripts // $aSpecialValues = isset($SPECIAL_VALUES) ? $SPECIAL_VALUES : array(); $aFormattedInputValues = isset($FORMATTED_INPUT) ? $FORMATTED_INPUT : array(); $aServerVarValues = isset($aServerVars) ? $aServerVars : array(); $aStrippedFormVarValues = isset($aStrippedFormVars) ? $aStrippedFormVars : array(); $aAlertInfoValues = isset($aAlertInfo) ? $aAlertInfo : array(); $aCleaned = isset($aCleanedValues) ? $aCleanedValues : array(); $aFieldOrderValues = isset($aFieldOrder) ? $aFieldOrder : array(); $s_error = str_replace("\n",Settings::get('BODY_LF'),$s_error); $b_got_filter = GetFilterSpec($s_filter_name,$a_filter_list); // // if there is a filter specified and we're not sending the alert // through the filter, don't show the user's data. This is // on the assumption that the filter is an encryption program; so, // we don't want to send the user's data in clear text inside the // alerts. // $b_show_data = true; if ($b_got_filter && !$b_filter) { $b_show_data = false; } $s_form_subject = $s_alert_to = ""; $b_check = true; // // might be too early to have $aSpecialValues set, so // look in the form vars too // if (isset($aSpecialValues["alert_to"])) { $s_alert_to = trim($aSpecialValues["alert_to"]); } if (empty($s_alert_to) && isset($aStrippedFormVarValues["alert_to"])) { $s_alert_to = trim($aStrippedFormVarValues["alert_to"]); } if (isset($aSpecialValues["subject"])) { $s_form_subject = trim($aSpecialValues["subject"]); } if (empty($s_form_subject) && isset($aStrippedFormVarValues["subject"])) { $s_form_subject = trim($aStrippedFormVarValues["subject"]); } if (empty($s_alert_to)) { $s_alert_to = Settings::get('DEF_ALERT'); $b_check = false; } if (!empty($s_alert_to)) { $s_from_addr = $s_from = ""; $a_headers = array(); if (!Settings::isEmpty('FROM_USER')) { if (Settings::get('FROM_USER') != "NONE") { $a_headers['From'] = Settings::get('FROM_USER'); $s_from_addr = Settings::get('FROM_USER'); $s_from = "From: $s_from_addr"; } } else { global $SERVER; $s_from_addr = "FormMail@" . $SERVER; $a_headers['From'] = $s_from_addr; $s_from = "From: $s_from_addr"; } $s_mesg = "To: " . UnMangle($s_alert_to) . Settings::get('BODY_LF'); // // if a language pack has been included, a lot of error messages // may need the character set to be provided. // If that's available from the language pack, use it, // otherwise, if it's a mail_option, use it from there. // $s_charset = ""; if (isset($sHTMLCharSet) && $sHTMLCharSet !== "") { $s_charset = $sHTMLCharSet; } else { if (IsMailOptionSet("CharSet")) { $s_charset = GetMailOption("CharSet"); } } // // Alerts are plain text emails, so convert any HTML entities // back to their original characters. Note, this will only work on PHP // version 4.3.0 and above. // if (function_exists("html_entity_decode")) { $s_error = @html_entity_decode($s_error,ENT_COMPAT,$s_charset); } if ($s_charset !== "") { $a_headers['Content-Type'] = SafeHeader("text/plain; charset=$s_charset"); } if (!empty($s_from)) { $s_mesg .= $s_from . Settings::get('BODY_LF'); } $s_mesg .= Settings::get('BODY_LF'); if (count($aAlertInfoValues) > 0) { if ($b_show_data) { $s_error .= Settings::get('BODY_LF') . GetMessage(MSG_MORE_INFO) . Settings::get('BODY_LF'); $s_error .= implode(Settings::get('BODY_LF'),$aAlertInfoValues); } else { $s_error .= Settings::get('BODY_LF') . GetMessage(MSG_INFO_STOPPED) . Settings::get('BODY_LF'); } } // // some fields aren't security issues - show those in the alert // $a_safe_fields = array( "email: " . isset($aSpecialValues["email"]) ? $aSpecialValues["email"] : '', "realname: " . isset($aSpecialValues["realname"]) ? $aSpecialValues["realname"] : '', ); $s_safe_data = implode(Settings::get('BODY_LF'),$a_safe_fields); if ($b_non_error) { $s_preamble = $s_error . Settings::get('BODY_LF') . Settings::get('BODY_LF'); $s_mesg .= $s_preamble; $s_subj = GetMessage(MSG_FM_ALERT); if (!empty($s_form_subject)) { $s_subj .= " ($s_form_subject)"; } } else { $s_preamble = GetMessage(MSG_FM_ERROR_LINE) . Settings::get('BODY_LF') . $s_error . Settings::get('BODY_LF') . Settings::get('BODY_LF'); $s_mesg .= $s_preamble; $s_subj = GetMessage(MSG_FM_ERROR); if (!empty($s_form_subject)) { $s_subj .= " ($s_form_subject)"; } $s_mesg .= $s_safe_data; $s_mesg .= Settings::get('BODY_LF') . Settings::get('BODY_LF'); if ($b_show_data) { $s_mesg .= implode(Settings::get('BODY_LF'),$aFormattedInputValues); } else { $s_mesg .= GetMessage(MSG_USERDATA_STOPPED); } } /* * We only need to filter the form fields if the filter that * is specified is an encrypting filter. */ if ($b_filter && $b_got_filter && IsFilterAttribSet($aSpecialValues["filter"],"Encrypts") ) { $s_new_mesg = $s_preamble . $s_safe_data; $s_new_mesg .= Settings::get('BODY_LF') . Settings::get('BODY_LF'); if ($a_filter_list !== false) { // // just filter the critical fields // list($s_unfiltered,$s_filtered_results) = GetFilteredOutput($aFieldOrderValues,$aCleaned, $s_filter_name,$a_filter_list); $s_new_mesg .= $s_unfiltered; } else { // // filter everything // $s_filtered_results = Filter($s_filter_name,$s_mesg); } $s_new_mesg .= GetMessage(MSG_FILTERED,array("FILTER" => $s_filter_name)) . Settings::get('BODY_LF') . Settings::get('BODY_LF') . $s_filtered_results; $s_mesg = $s_new_mesg; } $s_mesg .= Settings::get('BODY_LF'); if (isset($aServerVarValues['HTTP_REFERER'])) { $s_mesg .= "Referring page was " . $aServerVarValues['HTTP_REFERER']; } elseif (isset($aSpecialValues['this_form']) && $aSpecialValues['this_form'] !== "") { $s_mesg .= "Referring form was " . $aSpecialValues['this_form']; } $s_mesg .= Settings::get('BODY_LF'); if (isset($aServerVarValues['SERVER_NAME'])) { $s_mesg .= "SERVER_NAME was " . $aServerVarValues['SERVER_NAME'] . Settings::get('BODY_LF'); } if (isset($aServerVarValues['REQUEST_URI'])) { $s_mesg .= "REQUEST_URI was " . $aServerVarValues['REQUEST_URI'] . Settings::get('BODY_LF'); } $s_mesg .= Settings::get('BODY_LF'); if (isset($aServerVarValues['REMOTE_ADDR'])) { $s_mesg .= "User IP address was " . $aServerVarValues['REMOTE_ADDR'] . Settings::get('BODY_LF'); } if (isset($aServerVarValues['HTTP_USER_AGENT'])) { $s_mesg .= "User agent was " . $aServerVarValues['HTTP_USER_AGENT'] . Settings::get('BODY_LF'); } if ($b_check) { if (CheckEmailAddress($s_alert_to,$s_valid,$s_invalid)) { return (SendCheckedMail($s_valid,$s_subj,$s_mesg,$s_from_addr,$a_headers)); } } else { return (SendCheckedMail($s_alert_to,$s_subj,$s_mesg,$s_from_addr,$a_headers)); } } return (false); } // // Read the lines in a file and return an array. // Each line is stripped of line termination characters. // function ReadLines($fp) { $a_lines = array(); while (!feof($fp)) { $s_line = fgets($fp,4096); // // strip carriage returns and line feeds // $s_line = str_replace("\r","",$s_line); $s_line = str_replace("\n","",$s_line); $a_lines[] = $s_line; } return ($a_lines); } // // Open a URL and return the data from it as a string or array of lines. // Returns false on failure ($s_error has the error string) // function GetURL($s_url,&$s_error,$b_ret_lines = false,$n_depth = 0) { global $php_errormsg,$aServerVars,$sUserAgent,$ExecEnv; // // open the URL with the same session as we have // if ($ExecEnv->allowSessionURL()) { if (session_id() !== "") { $s_url = AddURLParams($s_url,session_name() . "=" . urlencode(session_id())); } if (defined("SID")) { $s_url = AddURLParams($s_url,SID); } } $http_get = new HTTPGet($s_url); // // Determine authentication requirements // if (Settings::get('AUTHENTICATE') !== "" || Settings::get('AUTH_USER') !== "" || Settings::get('AUTH_PW') !== "") { if (Settings::get('AUTHENTICATE') === "") { $http_get->SetAuthentication("Basic",Settings::get('AUTH_USER'),Settings::get('AUTH_PW')); } else { $http_get->SetAuthenticationLine(Settings::get('AUTHENTICATE')); } } else { $a_parts = $http_get->GetURLSplit(); if (isset($a_parts["user"]) || isset($a_parts["pass"])) { $s_auth_user = isset($a_parts["user"]) ? $a_parts["user"] : ""; $s_auth_pass = isset($a_parts["pass"]) ? $a_parts["pass"] : ""; } else { $s_auth_type = isset($aServerVars["PHP_AUTH_TYPE"]) ? $aServerVars["PHP_AUTH_TYPE"] : ""; $s_auth_user = isset($aServerVars["PHP_AUTH_USER"]) ? $aServerVars["PHP_AUTH_USER"] : ""; $s_auth_pass = isset($aServerVars["PHP_AUTH_PW"]) ? $aServerVars["PHP_AUTH_PW"] : ""; } if (!isset($s_auth_type) || $s_auth_type === "") { $s_auth_type = "Basic"; } if ($s_auth_user !== "" || $s_auth_pass !== "") { $http_get->SetAuthentication($s_auth_type,$s_auth_user,$s_auth_pass); } } // // set the user agent // $http_get->SetAgent($sUserAgent); // // resolve the name now so the DNS cache can be written to the session // $http_get->Resolve(); // // Since we might be opening a URL within the same session, we can // get locks. So, close the session for writing to prevent this. // $b_closed = false; if (function_exists('session_write_close')) { session_write_close(); $b_closed = true; //ob_flush(); // this prevents automatic redirects if $TEMPLATEURL // is in use and JavaScript is switched off } $m_buf = FALSE; //FMDebug("Begin read"); if (($a_lines = $http_get->Read()) === FALSE) { $http_get->Close(); // // get the error code and send the appropriate alert // list($i_error,$i_sys_err,$s_sys_msg) = $http_get->GetError(); switch ($i_error) { case $http_get->nErrParse: $s_error = GetMessage(MSG_URL_PARSE); break; case $http_get->nErrScheme: $a_parts = $http_get->GetURLSplit(); $s_error = GetMessage(MSG_URL_SCHEME,array("SCHEME" => $a_parts["scheme"])); break; default: $s_error = GetMessage(MSG_SOCKET, array("ERRNO" => $i_sys_err, "ERRSTR" => $s_sys_msg, "PHPERR" => isset($php_errormsg) ? $php_errormsg : "" )); break; } } else { $http_get->Close(); // // check the HTTP response for actual status. Anything outside // 200-299 is a failure, but we also handle redirects. // list($i_http_code,$s_http_status) = $http_get->GetHTTPStatus(); if ($i_http_code < 200 || $i_http_code > 299) { switch ($i_http_code) { case 300: // multiple choices (we'll take the first) case 301: // moved permanently case 302: // found case 303: // see other /** @noinspection PhpMissingBreakStatementInspection */ case 307: // temporary redirect // // a "location" header must be present for us to continue // In the case of infinite redirects, we need to stop. // So, we limit to a maximum of 10 redirects. // if ($n_depth < 10) { if (($s_location = $http_get->FindHeader("location")) !== false) { FMDebug("Redirect from '$s_url' to '$s_location'"); $m_buf = GetURL($s_location,$s_error,$b_ret_lines,$n_depth + 1); $b_closed = false; break; } FMDebug("Redirect FAILED - no location header"); } else { FMDebug("Redirect FAILED depth=$n_depth"); } // FALL THRU default: $s_error = GetMessage(MSG_GETURL_OPEN,array("STATUS" => $s_http_status,"URL" => $s_url)); break; } } elseif ($b_ret_lines) { $m_buf = $a_lines; } else // // return lines as one big string buffer // { $m_buf = implode("",$a_lines); } } // // re-open our session // if ($b_closed) { session_start(); } return ($m_buf); } // // Write to the debug log if it exists and is writable. // function FMDebug($s_mesg) { static $fDebug = NULL; if (!isset($fDebug)) { $fDebug = false; // only initialize once $s_db_file = "fmdebug.log"; // look for debug file in current directory // // we only open an existing file - we don't create one // if (file_exists($s_db_file)) { if (($fDebug = fopen($s_db_file,"a")) === false) { return; } } } if ($fDebug !== false) { fwrite($fDebug,date('r') . ": " . $s_mesg . "\n"); fflush($fDebug); } } /* * Class: NetIO * Description: * A class to provide internet input/output capabilities. * Use as a base class for more specific functions. */ class NetIO { var $_sHost; var $_iPort; var $_sPrefix; var $_iConnTimeout; var $_fSock; var $_aIPs; var $_iError = 0; var $_iSysErr; var $_sSysMesg; var $nErrInit = -1; // not initialized var $nErrRead = -2; // read error var $nErrWrite = -3; // write error var $nErrWriteShort = -4; // failed to write all bytes var $nErrSocket = -100; // error in socket open function __construct($s_host = NULL,$i_port = NULL,$s_prefix = "") { if (isset($s_host)) { $this->_sHost = $s_host; } if (isset($i_port)) { $this->_iPort = $i_port; } $this->_sPrefix = $s_prefix; $this->_iConnTimeout = 30; $this->_iSysErr = 0; $this->_sSysMesg = ""; } function _SetError($i_error,$i_sys_err = 0,$s_sys_mesg = "") { $this->_iError = $i_error; $this->_iSysErr = $i_sys_err; $this->_sSysMesg = $s_sys_mesg; return (FALSE); } function IsError() { return $this->_iError !== 0; } function ClearError() { $this->_SetError(0); } function GetError() { return (array($this->_iError,$this->_iSysErr,$this->_sSysMesg)); } function SetHost($s_host) { $this->_sHost = $s_host; } function SetPort($i_port) { $this->_iPort = $i_port; } function SetConnectionTimeout($i_secs) { $this->_iConnTimeout = $i_secs; } function SetPrefix($s_prefix) { $this->_sPrefix = $s_prefix; } function GetHost() { return (isset($this->_sHost) ? $this->_sHost : ""); } function GetPort() { return (isset($this->_iPort) ? $this->_iPort : 0); } function GetPrefix() { return ($this->_sPrefix); } function GetConnectionTimeout() { return ($this->_iConnTimeout); } function _CacheIt() { FMDebug("Caching " . implode(",",$this->_aIPs)); if (IsSetSession("FormNetIODNSCache")) { $a_cache = GetSession("FormNetIODNSCache"); } else { $a_cache = array(); } $a_cache[$this->_sHost] = $this->_aIPs; SetSession("FormNetIODNSCache",$a_cache); } /* * Some versions of PHP seem to have a major slowdown when resolving * names with gethostbyname (5 seconds with PHP 4.3.9). * So, in the case of multi-page forms using MULTIFORMURL, we get a big speed up * by caching the IP address of the server. */ function _CheckCache() { if (!IsSetSession("FormNetIODNSCache")) { return (FALSE); } $a_cache = GetSession("FormNetIODNSCache"); if (!is_array($a_cache) || !isset($a_cache[$this->_sHost]) || !is_array($a_cache[$this->_sHost])) { return (FALSE); } $this->_aIPs = $a_cache[$this->_sHost]; return (TRUE); } function Resolve() { $this->ClearError(); if (!isset($this->_sHost)) { return ($this->_SetError($this->nErrInit)); } if ($this->_CheckCache()) { return (TRUE); } FMDebug("Start resolve of " . $this->_sHost); // // if host is an actual IP address, then it is returned unchanged, which is good! // if (($a_ip_list = gethostbynamel($this->_sHost)) === FALSE) { FMDebug("Resolve failed"); return ($this->_SetError($this->nErrInit,0, GetMessage(MSG_RESOLVE,array("NAME" => $this->_sHost)))); } FMDebug("Done resolve: " . implode(",",$a_ip_list)); $this->_aIPs = $a_ip_list; $this->_CacheIt(); return (TRUE); } function _SSLOpen($s_ip,&$errno,&$errstr,$i_timeout) { global $ExecEnv; FMDebug("Using _SSLOpen (stream_socket_client), SNI, host=" . $this->GetHost()); $context = stream_context_create(); $result = stream_context_set_option($context,'ssl','verify_host',true); $result = stream_context_set_option($context,'ssl','verify_peer',false); $result = stream_context_set_option($context,'ssl','allow_self_signed',true); $result = stream_context_set_option($context,'ssl','SNI_enabled',true); if ($ExecEnv->IsPHPAtLeast("5.6.0")) { $result = stream_context_set_option($context,'ssl','peer_name',$this->GetHost()); } else { $result = stream_context_set_option($context,'ssl','SNI_server_name',$this->GetHost()); } // // Note that even if SNI fails, the socket will still open, but the // web server should send a 400 error. // return (stream_socket_client($this->GetPrefix() . $s_ip . ":" . $this->GetPort(), $errno,$errstr,$i_timeout,STREAM_CLIENT_CONNECT,$context)); } /** @noinspection PhpUndefinedVariableInspection */ function Open() { $this->ClearError(); if (!isset($this->_sHost) || !isset($this->_iPort)) { return ($this->_SetError($this->nErrInit)); } if (!$this->Resolve()) { return (FALSE); } FMDebug("Starting socket open"); $f_sock = FALSE; // // Now, run through the list of IPs until we find one that connects. // However, this can cause problems with SNI in SSL/TLS connections. // If there is only one IP address, use the host name. // Otherwise, if we can specify SNI and it's an SSL connection // use streams, otherwise try each IP individually. // if (count($this->_aIPs) == 1) { FMDebug("Trying host " . $this->_sHost . ", timeout " . $this->GetConnectionTimeout()); $f_sock = @fsockopen($this->GetPrefix() . $this->_sHost,$this->GetPort(), $errno,$errstr,$this->GetConnectionTimeout()); } else { foreach ($this->_aIPs as $s_ip) { global $ExecEnv; FMDebug("Trying IP $s_ip, timeout " . $this->GetConnectionTimeout()); if ($ExecEnv->IsPHPAtLeast("5.3.2") && substr($this->GetPrefix(),0,3) == "ssl") { if (($f_sock = $this->_SSLOpen($s_ip,$errno,$errstr, $this->GetConnectionTimeout())) !== FALSE ) { break; } } elseif (($f_sock = @fsockopen($this->GetPrefix() . $s_ip,$this->GetPort(), $errno,$errstr,$this->GetConnectionTimeout())) !== FALSE ) { break; } } } if ($f_sock === FALSE) { FMDebug("open failed: $errno $errstr"); return ($this->_SetError($this->nErrSocket,$errno,$errstr)); } $this->_fSock = $f_sock; FMDebug("Done socket open"); return (TRUE); } function Read() { $this->ClearError(); $a_lines = array(); while (($s_line = fgets($this->_fSock)) !== FALSE) { $a_lines[] = $s_line; } FMDebug("Read " . count($a_lines) . " lines"); return ($a_lines); } function Write($s_str,$b_flush = TRUE) { $this->ClearError(); if (!isset($this->_fSock)) { return ($this->_SetError($this->nErrInit)); } if (($n_write = fwrite($this->_fSock,$s_str)) === FALSE) { return ($this->_SetError($this->nErrWrite)); } if ($n_write != strlen($s_str)) { return ($this->_SetError($this->nErrWriteShort)); } if ($b_flush) { if (fflush($this->_fSock) === FALSE) { return ($this->_SetError($this->nErrWriteShort)); } } return (TRUE); } function Close() { if (isset($this->_fSock)) { fclose($this->_fSock); unset($this->_fSock); } } } /* * Class: HTTPGet * Description: * A class that implements HTTP GET method. */ class HTTPGet extends NetIO { var $_sURL; var $_aURLSplit; var $_sRequest; var $_aResponse; var $_aRespHeaders; var $_sAuthLine; var $_sAuthType; var $_sAuthUser; var $_sAuthPass; var $_sAgent; var $nErrParse = -1000; // failed to parse URL var $nErrScheme = -1001; // unsupported URL scheme function __construct($s_url = "") { parent::__construct(); $this->_aURLSplit = array(); if (($this->_sURL = $s_url) !== "") { $this->_SplitURL(); } } function _SplitURL() { FMDebug("URL: " . $this->_sURL); if (($this->_aURLSplit = parse_url($this->_sURL)) === FALSE) { $this->_aURLSplit = array(); return ($this->_SetError($this->nErrParse)); } return (TRUE); } function GetURLSplit() { return ($this->_aURLSplit); } function SetURL($s_url) { $this->_aURLSplit = array(); $this->_sURL = $s_url; return ($this->_SplitURL()); } function _Init() { if (!isset($this->_aURLSplit["host"])) { return ($this->_SetError($this->nErrInit)); } $this->SetHost($this->_aURLSplit["host"]); $i_port = 80; $b_use_ssl = false; if (isset($this->_aURLSplit["scheme"])) { switch (strtolower($this->_aURLSplit["scheme"])) { case "http": break; case "https": $b_use_ssl = true; $i_port = 443; break; default: return ($this->_SetError($this->nErrScheme)); } } if (isset($this->_aURLSplit["port"])) { $i_port = $this->_aURLSplit["port"]; } if ($b_use_ssl) // // we require ssl:// for port 443 // { $this->SetPrefix("ssl://"); } $this->SetPort($i_port); return (TRUE); } function _SendRequest() { $this->_PrepareRequest(); return (parent::Write($this->_sRequest)); } function _PrepareRequest($s_method = 'GET') { FMDebug("Path: " . $this->_aURLSplit["path"]); if (!isset($this->_aURLSplit["path"]) || $this->_aURLSplit["path"] === "") { $s_path = "/"; } // default path else { $s_path = $this->_aURLSplit["path"]; } if (isset($this->_aURLSplit["query"])) { // // add the query to the path // Note that parse_url decodes the query string (urldecode), so // we need to split it into its component parameters // are re-encode their values. Calling urlencode($this->_aURLSplit["query"]) // encodes the '=' between parameters and this breaks things. // $a_params = explode('&',$this->_aURLSplit["query"]); foreach ($a_params as $i_idx => $s_param) { if (($i_pos = strpos($s_param,"=")) === false) { $a_params[$i_idx] = urlencode($s_param); } else { $a_params[$i_idx] = substr($s_param,0,$i_pos) . '=' . urlencode(substr($s_param,$i_pos + 1)); } } $s_path .= "?" . implode('&',$a_params); } // // add the fragment to the path. // if (isset($this->_aURLSplit["fragment"])) { $s_path .= '#' . urlencode($this->_aURLSplit["fragment"]); } // // build the request // $s_req = $s_method . " $s_path HTTP/1.0\r\n"; // // Add authentication // if (isset($this->_sAuthLine)) { $s_req .= "Authorization: $this->_sAuthLine\r\n"; } elseif (isset($this->_sAuthType)) { $s_req .= "Authorization: " . $this->_sAuthType . " " . base64_encode($this->_sAuthUser . ":" . $this->_sAuthPass) . "\r\n"; } // // Specify the host name // $s_req .= "Host: " . $this->GetHost() . "\r\n"; // // Specify the user agent // if (isset($this->_sAgent)) { $s_req .= "User-Agent: " . $this->_sAgent . "\r\n"; } // // Accept any output // $s_req .= "Accept: */*\r\n"; $s_req .= $this->_AdditionalHeaders(); // // End of request headers // $s_req .= "\r\n"; $this->_sRequest = $s_req; } function _AdditionalHeaders() { return (''); } function _GetResponse() { FMDebug("Reading"); if (($a_lines = parent::Read()) === FALSE) { return (FALSE); } $this->_aRespHeaders = $this->_aResponse = array(); $b_body = FALSE; for ($ii = 0 ; $ii < count($a_lines) ; $ii++) { if ($b_body) { //FMDebug("Body line: ".rtrim($a_lines[$ii])); $this->_aResponse[] = $a_lines[$ii]; } elseif ($a_lines[$ii] == "\r\n" || $a_lines[$ii] == "\n") { $b_body = TRUE; } else { //FMDebug("Header line: ".rtrim($a_lines[$ii])); $this->_aRespHeaders[] = $a_lines[$ii]; } } return (TRUE); } function GetResponseHeaders() { return ($this->_aRespHeaders); } function FindHeader($s_name) { $s_name = strtolower($s_name); $i_len = strlen($s_name); for ($ii = 0 ; $ii < count($this->_aRespHeaders) ; $ii++) { $s_line = $this->_aRespHeaders[$ii]; if (($s_hdr = substr($s_line,0,$i_len)) !== false) { $s_hdr = strtolower($s_hdr); if ($s_hdr === $s_name && substr($s_line,$i_len,1) === ":") { return (trim(substr($s_line,$i_len + 1))); } } } return (false); } function GetHTTPStatus() { $i_http_code = 0; $s_status = ""; for ($ii = 0 ; $ii < count($this->_aRespHeaders) ; $ii++) { $s_line = $this->_aRespHeaders[$ii]; if (substr($s_line,0,4) == "HTTP") { $i_pos = strpos($s_line," "); $s_status = substr($s_line,$i_pos + 1); $i_end_pos = strpos($s_status," "); if ($i_end_pos === false) { $i_end_pos = strlen($s_status); } $i_http_code = (int)substr($s_status,0,$i_end_pos); } } return (array($i_http_code,$s_status)); } function Resolve() { if (!$this->_Init()) { return (FALSE); } return (parent::Resolve()); } function Read() { if (!$this->_Init()) { return (FALSE); } FMDebug("Init done"); if (!$this->Open()) { return (FALSE); } FMDebug("Open done"); if (!$this->_SendRequest()) { return (FALSE); } FMDebug("Send done"); if (!$this->_GetResponse()) { return (FALSE); } FMDebug("Get done"); $this->Close(); return ($this->_aResponse); } function SetAuthenticationLine($s_auth) { $this->_sAuthLine = $s_auth; } function SetAuthentication($s_type,$s_user,$s_pass) { $this->_sAuthType = $s_type; $this->_sAuthUser = $s_user; $this->_sAuthPass = $s_pass; } function SetAgent($s_agent) { $this->_sAgent = $s_agent; } } /* * Class: HTTPPost * Description: * A class that implements HTTP POST method. */ class HTTPPost extends HTTPGet { var $_sPostData; /* data to POST */ function __construct($s_url = "") { $this->_sPostData = ''; parent::__construct($s_url); } function _SendRequest() { $this->_PrepareRequest(); return (NetIO::Write($this->_sRequest)); } function _PrepareRequest($s_method = 'POST') { parent::_PrepareRequest($s_method); $this->_AddData(); } function _AdditionalHeaders() { // // we don't handle file uploads yet // $a_hdrs = array( 'Content-Type: application/x-www-form-urlencoded', 'Content-Length: ' . strlen($this->_sPostData), ); return (implode("\r\n",$a_hdrs)); } function _AddData() { $this->_sRequest .= "\r\n"; // blank line after headers $this->_sRequest .= $this->_sPostData; } function _EncodeData($a_fields) { $s_data = ''; foreach ($a_fields as $s_name => $s_value) { if ($s_data != '') { $s_data .= '&'; } if (is_string($s_value)) { $s_data .= urlencode($s_name) . '=' . urlencode($s_value); } else { $s_data .= urlencode($s_name) . '=' . urlencode(serialize($s_value)); } } return ($s_data); } function Post($a_fields) { // // we don't handle file uploads yet // $this->_sPostData = $this->_EncodeData($a_fields); return ($this->Read()); } } // // Load a template file into a string. // function LoadTemplate($s_name,$s_dir,$s_url,$b_ret_lines = false) { global $php_errormsg; $s_buf = ""; $a_lines = array(); if (!empty($s_dir)) { $s_name = "$s_dir/" . basename($s_name); @ $fp = fopen($s_name,"r"); if ($fp === false) { SendAlert(GetMessage(MSG_OPEN_TEMPLATE,array("NAME" => $s_name, "ERROR" => CheckString($php_errormsg) ))); return (false); } if ($b_ret_lines) { $a_lines = ReadLines($fp); } else // // load the whole template into a string // { $s_buf = fread($fp,filesize($s_name)); } fclose($fp); } else { if (substr($s_url,-1) == '/') { $s_name = "$s_url" . basename($s_name); } else { $s_name = "$s_url/" . basename($s_name); } if (($m_data = GetURL($s_name,$s_error,$b_ret_lines)) === false) { SendAlert($s_error); return (false); } if ($b_ret_lines) { $a_lines = $m_data; // // strip line terminations from each line // for ($ii = count($a_lines) ; --$ii >= 0 ;) { $s_line = $a_lines[$ii]; $s_line = str_replace("\r","",$s_line); $s_line = str_replace("\n","",$s_line); $a_lines[$ii] = $s_line; } } else { $s_buf = $m_data; } } return ($b_ret_lines ? $a_lines : $s_buf); } // // To show an error template. The template must be HTML and, for security // reasons, must be a file on the server in the directory specified // by $TEMPLATEDIR or $TEMPLATEURL. // $a_specs is an array of substitutions to perform, as follows: // tag-name replacement string // // For example: // "fmerror"=>"An error message" // function ShowErrorTemplate($s_name,$a_specs,$b_user_error) { if (function_exists('FMHookShowErrorTemplate')) { if (FMHookShowErrorTemplate($s_name,$a_specs,$b_user_error)) { return (true); } } if (Settings::isEmpty('TEMPLATEDIR') && Settings::isEmpty('TEMPLATEURL')) { SendAlert(GetMessage(MSG_TEMPLATES)); return (false); } if (($s_buf = LoadTemplate($s_name,Settings::get('TEMPLATEDIR'),Settings::get('TEMPLATEURL'))) === false) { return (false); } // // now look for the tags to replace // foreach ($a_specs as $s_tag => $s_value) // // search for //\n"; echo GetMessage(MSG_ABOUT_FORMMAIL,array("FM_VERS" => $FM_VERS, "TECTITE" => "www.tectite.com" )); echo "
\n"; } echo "\n"; echo "\n"; } } // // Strip slashes if magic_quotes_gpc is set. // function StripGPC($s_value) { global $ExecEnv; if (!$ExecEnv->IsPHPAtLeast("5.4.0")) { // the magic_quotes_gpc setting was removed in PHP 5.4.0 if (get_magic_quotes_gpc() != 0) { $s_value = stripslashes($s_value); } } return ($s_value); } // // return an array, stripped of slashes if magic_quotes_gpc is set // function StripGPCArray($a_values) { global $ExecEnv; if (!$ExecEnv->IsPHPAtLeast("5.4.0")) { // the magic_quotes_gpc setting was removed in PHP 5.4.0 if (get_magic_quotes_gpc() != 0) { foreach ($a_values as $m_key => $m_value) { if (is_array($m_value)) // // strip arrays recursively // { $a_values[$m_key] = StripGPCArray($m_value); } else // // convert scalar to string and strip // { $a_values[$m_key] = stripslashes("$m_value"); } } } } return ($a_values); } // // Strip a value of unwanted characters, which might be hacks. // The stripping of \r and \n is a *critical* security feature. // function Strip($value) { // // When working with character sets such as UTF-8, stripping // control characters is a *really bad idea* and breaks things. // From version 8.22, FormMail only strips \r and \n as these // are really the only characters that can cause header hacks // to be inserted. (Strip means replace with a single space). // We also handle multiple spaces. // $value = preg_replace('/[ \r\n]+/'," ",$value); // zap all CRLF and multiple blanks return ($value); } // // Clean a value. This means: // 1. convert to string // 2. truncate to maximum length // 3. strip the value of unwanted or dangerous characters (hacks) // 4. trim both ends of whitespace // Each element of an array is cleaned as above. This process occurs // recursively, so arrays of arrays work OK too (though there's no // need for that in this program). // // Non-scalar values are changed to the string "