";
}
else
$s_text = $aMessages[$i_msg_num];
$s_mno = $bShowMesgNumbers ? "[M$i_msg_num]" : "";
$s_orig_text = $s_text;
//
// substitute parameters; only works with PHP version 4.0.5 or later
//
if (strpos($s_text,'$') !== false)
{
global $aGetMessageValues,$aGetMessageSubstituteErrors;
global $aGetMessageSubstituteFound,$bGetMessageSubstituteNoErrors;
$aGetMessageSubstituteErrors = array();
$aGetMessageSubstituteFound = array();
$aGetMessageValues = $a_params;
$bGetMessageSubstituteNoErrors = $b_no_errors;
$aGetMessageValues["MNUM"] = $s_mno; // add the message number
//
// search for words in this form:
// $word
// where word begins with an alphabetic character and
// consists of alphanumeric and underscore
//
$s_text = preg_replace_callback('/\$([a-z][a-z0-9_]*)/i',
'GetMessageSubstituteParam',$s_text);
if (count($aGetMessageSubstituteErrors) > 0)
SendAlert("Message Number $i_msg_num ('$s_orig_text') in language $sLangID ".
"specified the following unsupported parameters: ".
implode(',',$aGetMessageSubstituteErrors));
if (!in_array("MNUM",$aGetMessageSubstituteFound))
//
// append the message number
//
$s_text .= $b_show_mnum ? " $s_mno" : "";
}
else
//
// append the message number
//
$s_text .= $b_show_mnum ? " $s_mno" : "";
//
// replace '\n' sequences with new lines
//
return (str_replace('\n',"\n",$s_text));
}
//
// Check for old version of PHP - die if too old.
//
function IsOldVersion(&$a_this_version)
{
$a_modern = array(4,1,0); // versions prior to this are "old" - "4.1.0"
$s_req_string = "4.0.5"; // version 4.0.5 of PHP is required from
// FormMail 5.00 onward (because we use
// preg_replace_callback for all messages to
// support languages other than English)
$a_too_old = explode(".",$s_req_string);
$i_cannot_use = ($a_too_old[0] * 10000) +
($a_too_old[1] * 100) +
$a_too_old[2];
$s_vers_string = phpversion();
$a_this_version = explode(".",$s_vers_string);
$i_this_num = ($a_this_version[0] * 10000) +
($a_this_version[1] * 100) +
$a_this_version[2];
if ($i_this_num <= $i_cannot_use)
die(GetMessage(MSG_SCRIPT_VERSION,array("PHPREQ"=>$s_req_string,
"PHPVERS"=>$s_vers_string)));
$i_modern_num = ($a_modern[0] * 10000) +
($a_modern[1] * 100) +
$a_modern[2];
return ($i_this_num < $i_modern_num);
}
//
// Check if the server is Windows
//
function IsServerWindows()
{
static $bGotAnswer = false;
static $bAnswer;
if (!$bGotAnswer)
{
if ((isset($_ENV["OS"]) && stristr($_ENV["OS"],"windows") !== false) ||
(isset($_SERVER["PATH"]) && stristr($_SERVER["PATH"],"winnt") !== false) ||
(isset($_SERVER["PATH"]) && stristr($_SERVER["PATH"],"windows") !== false) ||
(isset($_SERVER["SystemRoot"]) && stristr($_SERVER["SystemRoot"],"winnt") !== false) ||
(isset($_ENV["SystemRoot"]) && stristr($_ENV["SystemRoot"],"winnt") !== false) ||
(isset($_SERVER["SystemRoot"]) && stristr($_SERVER["SystemRoot"],"windows") !== false) ||
(isset($_ENV["SystemRoot"]) && stristr($_ENV["SystemRoot"],"windows") !== false) ||
(isset($_SERVER["Path"]) && stristr($_SERVER["Path"],"windows") !== false))
$bAnswer = true;
else
$bAnswer = false;
$bGotAnswer = true;
}
return ($bAnswer);
}
//
// To return a temporary file name from $SCRATCH_PAD
//
function GetScratchPadFile($s_prefix)
{
global $SCRATCH_PAD;
switch (substr($SCRATCH_PAD,-1))
{
case '/':
case '\\':
$s_dir = substr($SCRATCH_PAD,0,-1);
break;
default:
$s_dir = $SCRATCH_PAD;
break;
}
//
// Ideally, we could use tempnam. But,
// tempnam is system dependent and might not use the
// SCRATCH_PAD directory even if we tell it to.
// So, we'll force the file into SCRATCH_PAD.
//
// Note that we do *not* create the file, even though tempnam
// does create it in PHP version 4.0.3 and above. (The reason is
// we can't guarantee a non-race condition anyway.)
//
do
{
$i_rand = mt_rand(0,16777215); // 16777215 is FFFFFF in hex
$s_name = $SCRATCH_PAD."/".$s_prefix.sprintf("%06X",$i_rand);
}
while (file_exists($s_name));
return ($s_name);
}
//
// To return a temporary file name.
//
function GetTempName($s_prefix)
{
global $SCRATCH_PAD;
if (isset($SCRATCH_PAD) && !empty($SCRATCH_PAD))
$s_name = GetScratchPadFile($s_prefix);
else
$s_name = tempnam("/tmp",$s_prefix);
return ($s_name);
}
//
// To find a directory on the server for temporary files.
//
function GetTempDir()
{
$s_name = GetTempName("fm");
if (file_exists($s_name))
unlink($s_name);
$s_dir = dirname($s_name);
return ($s_dir);
}
//
// Returns true if the PHP version is at or later than the string specified
// (can't use "version_compare" before 4.1.0).
//
function IsPHPAtLeast($s_vers)
{
global $aPHPVERSION;
$a_test_version = explode(".",$s_vers);
if (count($a_test_version) < 3)
return (false);
return ($aPHPVERSION[0] > $a_test_version[0] ||
($aPHPVERSION[0] == $a_test_version[0] &&
($aPHPVERSION[1] > $a_test_version[1] ||
$aPHPVERSION[1] == $a_test_version[1] &&
$aPHPVERSION[2] >= $a_test_version[2])));
}
define('DEBUG',false); // for production
//define('DEBUG',true); // for development and debugging
if (DEBUG)
{
error_reporting(E_ALL); // trap everything!
LoadLanguage();
}
else
{
$iOldLevel = error_reporting(E_ALL ^ E_WARNING);
LoadLanguage();
//
// report everyting except warnings and notices
//
error_reporting(E_ALL ^ E_WARNING ^ E_NOTICE);
}
function SetRealDocumentRoot()
{
global $aServerVars,$REAL_DOCUMENT_ROOT;
if (isset($aServerVars['SCRIPT_FILENAME']))
$REAL_DOCUMENT_ROOT = $aServerVars['SCRIPT_FILENAME'];
elseif (isset($aServerVars['PATH_TRANSLATED']))
$REAL_DOCUMENT_ROOT = $aServerVars['PATH_TRANSLATED'];
else
$REAL_DOCUMENT_ROOT = "";
//
// look for 'www' or 'public_html' and strip back to that if found,
// otherwise just get the directory name
//
if (($i_pos = strpos($REAL_DOCUMENT_ROOT,"/www/")) !== false)
$REAL_DOCUMENT_ROOT = substr($REAL_DOCUMENT_ROOT,0,$i_pos+4);
elseif (($i_pos = strpos($REAL_DOCUMENT_ROOT,"/public_html/")) !== false)
$REAL_DOCUMENT_ROOT = substr($REAL_DOCUMENT_ROOT,0,$i_pos+12);
elseif (!empty($REAL_DOCUMENT_ROOT))
$REAL_DOCUMENT_ROOT = dirname($REAL_DOCUMENT_ROOT);
elseif (isset($aServerVars['DOCUMENT_ROOT']) &&
!empty($aServerVars['DOCUMENT_ROOT']))
$REAL_DOCUMENT_ROOT = $aServerVars['DOCUMENT_ROOT'];
}
//
// Hook system: before initialization (but after configuration)
//
if ($HOOK_DIR !== "")
@include("$HOOK_DIR/fmhookpreinit.inc");
if (!empty($SESSION_NAME))
session_name($SESSION_NAME);
session_start();
function ZapSession()
{
session_destroy();
}
if ($bUseOldVars)
$aSessionVars = &$HTTP_SESSION_VARS;
else
$aSessionVars = &$_SESSION;
$aSessionVars["FormError"] = NULL;
unset($aSessionVars["FormError"]); // start with no error
$aSessionVars["FormErrorInfo"] = NULL;
unset($aSessionVars["FormErrorInfo"]); // start with no error
$aSessionVars["FormErrorCode"] = NULL;
unset($aSessionVars["FormErrorCode"]); // start with no error
$aSessionVars["FormErrorItems"] = NULL;
unset($aSessionVars["FormErrorItems"]); // start with no error
$aSessionVars["FormData"] = NULL;
unset($aSessionVars["FormData"]); // start with no data
$aSessionVars["FormIsUserError"] = NULL;
unset($aSessionVars["FormIsUserError"]); // start with no data
$aSessionVars["FormAlerted"] = NULL;
unset($aSessionVars["FormAlerted"]); // start with no data
//
// Note that HTTP_REFERER is easily spoofed, so there's no point in
// using it for security.
//
//
// SPECIAL_FIELDS is the list of fields that formmail.php looks for to
// control its operation
//
$SPECIAL_FIELDS = array(
"email", // email address of the person who filled in the form
"realname", // the real name of the person who filled in the form
"recipients", // comma-separated list of email addresses to which we'll send the results
"cc", // comma-separated list of email addresses to which we'll CC the results
"bcc", // comma-separated list of email addresses to which we'll BCC the results
"required", // comma-separated list of fields that must be found in the input
"conditions", // complex condition tests
"fmcompute", // computations
"fmmodules", // list of modules required
"mail_options", // comma-separated list of options
"good_url", // URL to go to on success
"good_template",// template file to display on success
"bad_url", // URL to go to on error
"bad_template", // template file to display on error
"template_list_sep", // separator when expanding lists in templates
"this_form", // the URL of the form (can be used by bad_url)
"subject", // subject for the email
"env_report", // comma-separated list of environment variables to report
"filter", // a supported filter to use
"filter_options",// options for using the filter
"filter_fields",// list of fields to filter (default is to filter all fields)
"logfile", // log file to write to
"csvfile", // file to write CSV records to
"csvcolumns", // columns to save in the csvfile
"crm_url", // URL for sending data to the CRM; note that the
// value must have a valid prefix specified in TARGET_URLS
"crm_spec", // CRM specification (field mapping)
"crm_options", // comma-separated list of options to control CRM processing
"derive_fields", // a list of fields to derive from other fields
"file_names", // specifies names for files being uploaded
"autorespond", // specification for auto-responding
"arverify", // verification field to allow auto-responding
"imgverify", // verification field to allow submission
"multi_start", // set this field on the first page of a multi-page form sequence
"multi_keep", // set this field on the pages of a multi-page form sequence
// to the list of fields that should be kept when moving
// forward after going backwards
"next_form", // next form name or empty for last form
"multi_go_back",// this field should be set when the user clicks the
// back button or link in a multi-page form sequence
"alert_to"); // email address to send alerts (errors) to
//
// $SPECIAL_MULTI is the list of fields from $SPECIAL_FIELDS that can
// have multiple values, for example:
// name="conditions1"
// name="conditions2"
//
$SPECIAL_MULTI = array(
"conditions",
"fmcompute",
);
//
// $SPECIAL_NOSTRIP is the list of fields from $SPECIAL_FIELDS that
// should not be stripped (other than for magic_quotes_gpc reasons).
//
$SPECIAL_NOSTRIP = array(
"conditions",
"fmcompute",
);
//
// VALID_MAIL_OPTIONS lists the valid mail_options words
//
$VALID_MAIL_OPTIONS = array(
"AlwaysList"=>true,
"CharSet"=>true,
"DupHeader"=>true,
"Exclude"=>true,
"FromAddr"=>true,
"HTMLTemplate"=>true,
"KeepLines"=>true,
"NoEmpty"=>true,
"NoPlain"=>true,
"PlainTemplate"=>true,
"SendMailFOption"=>true,
"StartLine"=>true,
"TemplateMissing"=>true,
);
//
// VALID_CRM_OPTIONS lists the valid crm_options words
//
$VALID_CRM_OPTIONS = array(
"ErrorOnFail"=>true,
);
//
// VALID_AR_OPTIONS lists the valid autorespond words
//
$VALID_AR_OPTIONS = array(
"Subject"=>true,
"HTMLTemplate"=>true,
"PlainTemplate"=>true,
"TemplateMissing"=>true,
"FromAddr"=>true,
);
//
// VALID_FILTER_OPTIONS lists the valid filter_options words
//
$VALID_FILTER_OPTIONS = array(
"Attach"=>true,
"KeepInLine"=>true,
"CSVHeading"=>true,
"CSVSep"=>true,
"CSVIntSep"=>true,
"CSVQuote"=>true,
"CSVEscPolicy"=>true,
"CSVRaw"=>true,
);
//
// SPECIAL_VALUES is set to the value of the fields we've found
// usage: $SPECIAL_VALUES["email"] is the value of the email field
//
$SPECIAL_VALUES = array();
//
// Array of mail options; set by the function 'ProcessMailOptions'
//
$MAIL_OPTS = array();
//
// Array of crm options; set by the function 'ProcessCRMOptions'
//
$CRM_OPTS = array();
//
// Array of autorespond options; set by the function 'ProcessAROptions'
//
$AR_OPTS = array();
//
// Array of filter options; set by the function 'ProcessFilterOptions'
//
$FILTER_OPTS = array();
//
// initialise $SPECIAL_VALUES so that we don't fail on using unset values
//
foreach ($SPECIAL_FIELDS as $sFieldName)
$SPECIAL_VALUES[$sFieldName] = "";
//
// Special defaults for some fields....
//
$SPECIAL_VALUES['template_list_sep'] = ",";
//
// FORMATTED_INPUT contains the input variables formatted nicely
// This is used for error reporting and debugging only.
//
$FORMATTED_INPUT = array();
//
// $FILTER_ATTRIBS_LOOKUP is the parsed $FILTER_ATTRIBS array
//
$FILTER_ATTRIBS_LOOKUP = array();
//
// $EMAIL_ADDRS is the array of email addresses from the $FORM_INI_FILE
//
$EMAIL_ADDRS = array();
//
// Access the www.tectite.com website to get the current version.
//
function CheckVersion()
{
global $FM_VERS;
@ $fp = fopen("http://www.tectite.com/fmversion.txt","r");
if ($fp !== false)
{
//
// version file looks like this:
// Version=versionumber
// Message=a message to send in the alert
//
$s_version = "";
$s_message = "";
$s_line = "";
$b_in_mesg = false;
while (!feof($fp))
{
$s_line = fgets($fp,1024);
if ($b_in_mesg)
$s_message .= $s_line;
else
{
$s_prefix = substr($s_line,0,8);
if ($s_prefix == "Message=")
{
$s_message .= substr($s_line,8);
$b_in_mesg = true;
}
elseif ($s_prefix == "Version=")
$s_version = substr($s_line,8);
}
}
fclose($fp);
$s_version = str_replace("\r","",$s_version);
$s_version = str_replace("\n","",$s_version);
$s_stop_mesg = GetMessage(MSG_END_VERS_CHK);
if ((float) $s_version > (float) $FM_VERS)
SendAlert(GetMessage(MSG_VERS_CHK,array(
"TECTITE"=>"www.tectite.com",
"FM_VERS"=>"$FM_VERS",
"NEWVERS"=>$s_version,
))."\n$s_message\n$s_stop_mesg",true,true);
}
}
//
// Check for new FormMail version
//
function Check4Update($s_chk_file,$s_id = "")
{
global $lNow,$php_errormsg;
@ $l_last_chk = filemtime($s_chk_file);
if ($l_last_chk === false || $lNow - $l_last_chk >= (CHECK_DAYS*24*60*60))
{
CheckVersion();
//
// update the check file's time stamp
//
@ $fp = fopen($s_chk_file,"w");
if ($fp !== false)
{
fwrite($fp,"FormMail version check ".
(empty($s_id) ? "" : "for identifier '$s_id' ").
"at ".date("H:i:s d-M-Y",$lNow)."\n");
fclose($fp);
}
else
SendAlert(GetMessage(MSG_CHK_FILE_ERROR,array("FILE"=>$s_chk_file,
"ERROR"=>CheckString($php_errormsg))));
}
}
//
// Perform various processing at the end of the script's execution.
//
function OnExit()
{
global $TARGET_EMAIL,$CHECK_FILE;
//
// Check the www.tectite.com website for a new version, but only
// do this check once every CHECK_DAYS days (or on server reboot).
//
if (CHECK_FOR_NEW_VERSION)
{
global $SERVER;
if (isset($TARGET_EMAIL[0]))
{
//
// use the first few characters of the MD5 of first email
// address pattern from $TARGET_EMAIL to get a unique file
// for the server
//
$s_id = "";
if (isset($SERVER) && !empty($SERVER))
$s_id = $SERVER;
$s_dir = GetTempDir();
$s_md5 = md5($TARGET_EMAIL[0]);
$s_uniq = substr($s_md5,0,6);
$s_chk_file = "fm"."$s_uniq".".txt";
Check4Update($s_dir."/".$s_chk_file,$s_id);
}
}
}
register_shutdown_function('OnExit');
//
// Return the array with each string urlencode'd.
//
function URLEncodeArray($a_array)
{
foreach ($a_array as $m_key=>$s_str)
{
//
// only encode the value after the '='
//
if (($i_pos = strpos($s_str,'=')) !== false)
$a_array[$m_key] = substr($s_str,0,$i_pos+1).
urlencode(substr($s_str,$i_pos+1));
else
$a_array[$m_key] = urlencode($s_str);
}
return ($a_array);
}
//
// Add a parameter or list of parameters to a URL.
//
function AddURLParams($s_url,$m_params,$b_encode = true)
{
if (!empty($m_params))
{
if (!is_array($m_params))
$m_params = array($m_params);
if (strpos($s_url,'?') === false)
$s_url .= '?';
else
$s_url .= '&';
$s_url .= implode('&',($b_encode) ? URLEncodeArray($m_params) : $m_params);
}
return ($s_url);
}
//
// Recursively trim an array of strings (non string values are converted
// to a string first).
//
function TrimArray($a_list)
{
foreach ($a_list as $m_key=>$m_item)
if (is_array($m_item))
$a_list[$m_key] = TrimArray($m_item);
elseif (is_scalar($m_item))
$a_list[$m_key] = trim("$m_item");
else
$a_list[$m_key] = "";
return ($a_list);
}
//
// Parse a derivation specification and return an array of
// field names and operators.
//
function ParseDerivation($a_form_data,$s_fld_spec,$s_name,&$a_errors)
{
$a_deriv = array();
while (($i_len = strlen($s_fld_spec)) > 0)
{
//
// we support the following operators:
// + concatenate with a single space between, but skip the space
// if the next field is empty
// * concatenate with a single space between
// . concatenate with no space between
//
$i_span = strcspn($s_fld_spec,'+*.');
if ($i_span == 0)
{
$a_errors[] = $s_name;
return (false);
}
$a_deriv[] = trim(substr($s_fld_spec,0,$i_span));
if ($i_span < $i_len)
{
$a_deriv[] = substr($s_fld_spec,$i_span,1);
$s_fld_spec = substr($s_fld_spec,$i_span+1);
}
else
$s_fld_spec = "";
}
return ($a_deriv);
}
//
// Test if a character is an alphabetic.
//
function IsAlpha($ch)
{
return (strpos("abcdefghijklmnopqrstuvwxyz",strtolower($ch)) !== false);
}
//
// Test if a character is a digit.
//
function IsNumeric($ch)
{
return (strpos("0123456789",$ch) !== false);
}
//
// Test if a character is an alphanumeric
//
function IsAlnum($ch)
{
return (IsAlpha($ch) || IsNumeric($ch));
}
//
// Return an array of tokens extracted from the given string.
// A token is:
// - a word (begins with alpha or _, and is followed by any number
// of alphanumerics or _ chars)
// - a number (any number of consecutive digits with up to one period)
// - a string enclosed in specified quotes (this can be disabled)
// - any punctuation character
//
// Anything not matching the above is silently ignored!
//
function GetTokens($s_str,$s_quotes = "'\"")
{
$b_allow_strings = ($s_quotes !== "") ? true : false;
$ii = 0;
$i_len = strlen($s_str);
$a_toks = array();
while ($ii < $i_len)
{
switch ($ch = $s_str{$ii})
{
case " ":
case "\t":
case "\n":
case "\r":
$ii++;
continue;
}
//
// start of a token
//
$i_start = $ii;
if ($ch == "_" || IsAlpha($ch))
{
//
// a word
//
$i_count = 1;
while (++$ii < $i_len &&
($s_str{$ii} == "_" || IsAlnum($s_str{$ii})))
++$i_count;
$a_toks[] = substr($s_str,$i_start,$i_count);
}
elseif (($ch == "." && $ii < ($i_len-1) && IsNumeric($s_str{$ii+1}))||
IsNumeric($ch))
{
//
// a number
//
$b_had_dot = ($ch == ".");
$i_count = 1;
while (++$ii < $i_len)
{
if (IsNumeric($s_str{$ii}))
++$i_count;
elseif ($s_str{$ii} == "." && !$b_had_dot)
{
++$i_count;
$b_had_dot = true;
}
else
break;
}
$a_toks[] = substr($s_str,$i_start,$i_count);
}
elseif ($b_allow_strings && strpos($s_quotes,$ch) !== false)
{
$c_quote = $ch;
//
// a quoted string
//
while (++$ii < $i_len)
{
if ($s_str{$ii} == $c_quote)
{
++$ii; // include the terminating quote
break;
}
}
$a_toks[] = substr($s_str,$i_start,$ii-$i_start);
}
else
{
$s_punct = "~!@#$%^&*()-+={}[]|:;<>,.?/`\\";
if (!$b_allow_strings)
$s_punct .= "'\"";
if (strpos($s_punct,$ch) !== false)
$a_toks[] = $ch;
++$ii;
}
}
return ($a_toks);
}
//
// Return the value from a derive_fields specification.
// Specifications are in this format:
// %info%
// where info is a predefined word or a literal in quotes
// (e.g. 'the time is ')
//
function ValueSpec($s_spec,$a_form_data,&$a_errors)
{
global $lNow;
$s_value = "";
switch (trim($s_spec))
{
case 'date': // "standard" date format: DD-MMM-YYYY
$s_value = date('d-M-Y',$lNow);
break;
case 'time': // "standard" time format: HH:MM:SS
$s_value = date('H:i:s',$lNow);
break;
case 'ampm': // am or pm
$s_value = date('a',$lNow);
break;
case 'AMPM': // AM or PM
$s_value = date('A',$lNow);
break;
case 'dom0': // day of month with possible leading zero
$s_value = date('d',$lNow);
break;
case 'dom': // day of month with no leading zero
$s_value = date('j',$lNow);
break;
case 'day': // day name (abbreviated)
$s_value = date('D',$lNow);
break;
case 'dayname': // day name (full)
$s_value = date('l',$lNow);
break;
case 'daysuffix': // day number suffix for English (st for 1st, nd for 2nd, etc.)
$s_value = date('S',$lNow);
break;
case 'moy0': // month of year with possible leading zero
$s_value = date('m',$lNow);
break;
case 'moy': // month of year with no leading zero
$s_value = date('n',$lNow);
break;
case 'month': // month name (abbreviated)
$s_value = date('M',$lNow);
break;
case 'monthname': // month name (full)
$s_value = date('F',$lNow);
break;
case 'year': // year (two digits)
$s_value = date('y',$lNow);
break;
case 'fullyear': // year (full)
$s_value = date('Y',$lNow);
break;
case 'rfcdate': // date formatted according to RFC 822
$s_value = date('r',$lNow);
break;
case 'tzname': // timezone name
$s_value = date('T',$lNow);
break;
case 'tz': // timezone difference from Greenwich +NNNN or -NNNN
$s_value = date('O',$lNow);
break;
case 'hour120': // hour of day (01-12) with possible leading zero
$s_value = date('h',$lNow);
break;
case 'hour240': // hour of day (00-23) with possible leading zero
$s_value = date('H',$lNow);
break;
case 'hour12': // hour of day (1-12) with no leading zero
$s_value = date('g',$lNow);
break;
case 'hour24': // hour of day (0-23) with no leading zero
$s_value = date('G',$lNow);
break;
case 'min': // minute of hour (00-59)
$s_value = date('i',$lNow);
break;
case 'sec': // seconds of minute (00-59)
$s_value = date('s',$lNow);
break;
default:
if ($s_spec{0} == "'")
{
//
// to get a quote, use 3 quotes:
// '''
//
if ($s_spec == "'''")
$s_value = "'";
elseif (substr($s_spec,-1,1) == "'")
$s_value = substr($s_spec,1,-1);
else
//
// missing final quote is OK
//
$s_value = substr($s_spec,1);
}
elseif (strspn($s_spec,"0123456789ABCDEF") == 2)
{
//
// insert the ASCII character corresponding to
// the hexadecimal value
//
$i_val = intval(substr($s_spec,0,2),16);
$s_value = chr($i_val);
}
else
{
//
// look for supported functions, start by getting all
// the tokens
//
$a_toks = GetTokens($s_spec);
if (count($a_toks) > 0)
{
switch ($a_toks[0])
{
case "if":
//
// "if" function: test first field
// if not empty, then use second field
// else, use third field
//
// Example: if(fld1 ; fld2 ; fld3)
//
// tokens are:
// 1 (
// 2 the field name to test (first)
// 3 ;
// 4 the "then" spec (can be missing)
// 5 ;
// 6 the "else" spec (can be missing)
// 7 )
//
if (($n_tok = count($a_toks)) < 6 ||
$a_toks[1] != "(" ||
$a_toks[3] != ";" ||
$a_toks[$n_tok-1] != ")")
SendAlert(GetMessage(MSG_DER_FUNC_ERROR,
array("SPEC"=>$s_spec,
"MSG"=>GetMessage(MSG_DER_FUNC_IF_FMT))));
else
{
$b_ok = true;
$s_fld_name = $a_toks[2];
$s_then_spec = $s_else_spec = "";
for ($ii = 4 ; $ii < $n_tok && $a_toks[$ii] != ';' ; $ii++)
$s_then_spec .= $a_toks[$ii];
if ($ii == $n_tok)
$b_ok = false;
else
{
//
// Concatenate tokens until the ')'.
// This provides the "else" spec.
//
for ( ; ++$ii < $n_tok && $a_toks[$ii] != ')' ; )
$s_else_spec .= $a_toks[$ii];
if ($ii == $n_tok)
$b_ok = false;
}
if ($b_ok)
{
if (!TestFieldEmpty($s_fld_name,$a_form_data,$s_mesg))
$s_fld_spec = $s_then_spec;
else
$s_fld_spec = $s_else_spec;
$s_value = GetDerivedValue($a_form_data,$s_fld_spec);
}
else
SendAlert(GetMessage(MSG_DER_FUNC_ERROR,
array("SPEC"=>$s_spec,
"MSG"=>GetMessage(MSG_DER_FUNC_IF_FMT))));
}
break;
case "size":
//
// "size" function: return size of uploaded file
//
// Example: size(fieldname)
//
// tokens are:
// 1 (
// 2 the field name for the file upload
// 3 )
//
if (count($a_toks) != 4 ||
$a_toks[1] != "(" ||
$a_toks[3] != ")")
SendAlert(GetMessage(MSG_DER_FUNC_ERROR,
array("SPEC"=>$s_spec,
"MSG"=>GetMessage(MSG_DER_FUNC_SIZE_FMT))));
elseif (($i_size = GetFileSize($a_toks[2])) !== false)
$s_value = "$i_size";
break;
case "ext":
//
// "ext" function: return filename extension of uploaded file
//
// Example: ext(fieldname)
//
// tokens are:
// 1 (
// 2 the field name for the file upload
// 3 )
//
if (count($a_toks) != 4 ||
$a_toks[1] != "(" ||
$a_toks[3] != ")")
SendAlert(GetMessage(MSG_DER_FUNC_ERROR,
array("SPEC"=>$s_spec,
"MSG"=>GetMessage(MSG_DER_FUNC_EXT_FMT))));
elseif (($s_name = GetFileName($a_toks[2])) !== false)
{
if (($i_pos = strrpos($s_name,".")) !== false)
$s_value = substr($s_name,$i_pos+1);
}
break;
case "ucase":
case "lcase":
//
// "ucase" and "lcase" functions: return field
// converted to upper or lower case
//
// Example: lcase(fieldname)
//
// tokens are:
// 1 (
// 2 the field name to convert
// 3 )
//
if (count($a_toks) != 4 ||
$a_toks[1] != "(" ||
$a_toks[3] != ")")
SendAlert(GetMessage(MSG_DER_FUNC_ERROR,
array("SPEC"=>$s_spec,
"MSG"=>GetMessage(MSG_DER_FUNC1_FMT,
array("FUNC"=>$a_toks[0])))));
elseif ($a_toks[0] == "ucase")
$s_value = strtoupper(GetFieldValue($a_toks[2],$a_form_data));
else
$s_value = strtolower(GetFieldValue($a_toks[2],$a_form_data));
break;
case "ltrim":
case "rtrim":
case "trim":
//
// trim functions: return field with whitespace removed
// from left (ltrim), right (rtrim), or both (trim)
// ends.
//
// Example: ltrim(fieldname)
//
// tokens are:
// 1 (
// 2 the field name to trim
// 3 )
//
if (count($a_toks) != 4 ||
$a_toks[1] != "(" ||
$a_toks[3] != ")")
SendAlert(GetMessage(MSG_DER_FUNC_ERROR,
array("SPEC"=>$s_spec,
"MSG"=>GetMessage(MSG_DER_FUNC1_FMT,
array("FUNC"=>$a_toks[0])))));
else
$s_value = $a_toks[0](GetFieldValue($a_toks[2],$a_form_data));
break;
case "ltrim0":
//
// ltrim0 function: return field with blanks and
// leading 0's removed from the left.
//
// Example: ltrim0(fieldname)
//
// tokens are:
// 1 (
// 2 the field name to trim
// 3 )
//
if (count($a_toks) != 4 ||
$a_toks[1] != "(" ||
$a_toks[3] != ")")
SendAlert(GetMessage(MSG_DER_FUNC_ERROR,
array("SPEC"=>$s_spec,
"MSG"=>GetMessage(MSG_DER_FUNC1_FMT,
array("FUNC"=>$a_toks[0])))));
else
{
$s_value = GetFieldValue($a_toks[2],$a_form_data);
$s_value = ltrim($s_value); // trim blanks on left
$i_len = strspn($s_value,"0");
//
// if the whole string is zeroes, make sure we leave
// one of them!
//
if ($i_len == strlen($s_value))
if (--$i_len < 0)
$i_len = 0;
$s_value = substr($s_value,$i_len);
}
break;
case "nextnum":
//
// "nextnum" function: return a unique number (next number)
//
// Usage: nextnum[(pad[,base])]
//
// Examples:
// %nextnum%
// %nextnum(8)%
// %nextnum(5;16)%
//
// You can provide a padding amount. In this case, the
// number is padded on the left with zeroes to the number
// of digits specified.
//
// You can also provide a base for your numbers. Valid
// values for base are 2 to 36, inclusive.
//
// tokens are:
// 1 (
// 2 the padding amount
// 3 ;
// 4 the base
// 5 )
//
$i_pad = 0; // no padding
$i_base = 10; // base 10
if (($n_tok = count($a_toks)) > 1)
{
if (($n_tok != 4 && $n_tok != 6) ||
$a_toks[1] != "(" ||
$a_toks[$n_tok-1] != ")")
SendAlert(GetMessage(MSG_DER_FUNC_ERROR,
array("SPEC"=>$s_spec,
"MSG"=>GetMessage(MSG_DER_FUNC_NEXTNUM_FMT)." (T1)")));
if ($n_tok == 6 && $a_toks[3] != ";")
SendAlert(GetMessage(MSG_DER_FUNC_ERROR,
array("SPEC"=>$s_spec,
"MSG"=>GetMessage(MSG_DER_FUNC_NEXTNUM_FMT)." (T2)")));
if (!is_numeric($a_toks[2]) ||
($n_tok == 6 && !is_numeric($a_toks[4])))
SendAlert(GetMessage(MSG_DER_FUNC_ERROR,
array("SPEC"=>$s_spec,
"MSG"=>GetMessage(MSG_DER_FUNC_NEXTNUM_FMT)." (T3)")));
$i_pad = intval($a_toks[2]);
if ($n_tok == 6)
{
$i_base = intval($a_toks[4]);
if ($i_base < 2 || $i_base > 36)
{
SendAlert(GetMessage(MSG_DER_FUNC_ERROR,
array("SPEC"=>$s_spec,
"MSG"=>GetMessage(MSG_DER_FUNC_NEXTNUM_FMT)." (T4)")));
$i_base = 10;
}
}
$s_value = GetNextNum($i_pad,$i_base);
}
else
{
$s_value = GetNextNum($i_pad,$i_base);
}
break;
default:
SendAlert(GetMessage(MSG_UNK_VALUE_SPEC,
array("SPEC"=>$s_spec,"MSG"=>"")));
break;
}
}
else
SendAlert(GetMessage(MSG_UNK_VALUE_SPEC,array("SPEC"=>$s_spec,
"MSG"=>"")));
}
break;
}
return ($s_value);
}
//
// Return the next number or fail on error
//
function GetNextNum($i_pad,$i_base)
{
global $NEXT_NUM_FILE,$php_errormsg;
if (!isset($NEXT_NUM_FILE) || $NEXT_NUM_FILE === "")
{
ErrorWithIgnore("next_num_config",GetMessage(MSG_NO_NEXT_NUM_FILE));
exit;
}
if (($fp = @fopen($NEXT_NUM_FILE,"r+")) === false)
{
Error("next_num_file",GetMessage(MSG_NEXT_NUM_FILE,
array("FILE"=>$NEXT_NUM_FILE,
"ACT"=>"open",
"ERR"=>$php_errormsg)));
exit;
}
if (!flock($fp,defined("LOCK_EX") ? LOCK_EX : 2))
{
Error("next_num_file",GetMessage(MSG_NEXT_NUM_FILE,
array("FILE"=>$NEXT_NUM_FILE,
"ACT"=>"flock",
"ERR"=>$php_errormsg)));
exit;
}
//
// read the first line only
//
if (!feof($fp))
{
if (($s_line = fread($fp,1024)) === false)
$i_next = 1;
elseif (($i_next = intval($s_line)) <= 0)
$i_next = 1;
}
else
$i_next = 1;
if (rewind($fp) == 0)
{
Error("next_num_file",GetMessage(MSG_NEXT_NUM_FILE,
array("FILE"=>$NEXT_NUM_FILE,
"ACT"=>"rewind",
"ERR"=>$php_errormsg)));
exit;
}
$s_ret = strval($i_next++);
if (fputs($fp,"$i_next\r\n") <= 0)
{
Error("next_num_file",GetMessage(MSG_NEXT_NUM_FILE,
array("FILE"=>$NEXT_NUM_FILE,
"ACT"=>"fputs",
"ERR"=>$php_errormsg)));
exit;
}
fclose($fp);
if ($i_base != 10)
{
$s_ret = base_convert($s_ret,10,$i_base);
$s_ret = strtoupper($s_ret); // always upper case if alphas are used
}
if ($i_pad != 0)
$s_ret = str_pad($s_ret,$i_pad,"0",STR_PAD_LEFT);
return ($s_ret);
}
//
// Return the value of an object or array as a string.
//
function GetObjectAsString($m_value)
{
ob_start();
print_r($m_value);
$s_ret = ob_get_contents();
ob_end_clean();
return ($s_ret);
}
//
// Return a Server or Environment variable value. Returns false if
// not found, otherwise a string value.
//
function GetEnvValue($s_name)
{
global $aServerVars,$aEnvVars;
if (isset($aEnvVars[$s_name]))
$m_value = $aEnvVars[$s_name];
elseif (isset($aServerVars[$s_name]))
$m_value = $aServerVars[$s_name];
//
// some values might not be strings - so convert
//
if (isset($m_value) && !is_scalar($m_value))
$m_value = GetObjectAsString($m_value);
return (isset($m_value) ? ((string) $m_value) : false);
}
//
// Same as "empty" but checks for true emptiness if ZERO_IS_EMPTY is
// set to false.
//
function IsFieldEmpty($s_value)
{
if (ZERO_IS_EMPTY || is_array($s_value))
return (empty($s_value));
else
return ($s_value === "");
}
//
// Test if a field is set in the given vars array or in the uploaded
// files.
//
function IsFieldSet($s_fld,$a_main_vars)
{
global $aFileVars;
return (isset($a_main_vars[$s_fld]) ||
(FILEUPLOADS && isset($aFileVars[$s_fld])));
}
//
// Return the info for the uploaded file, or false on error.
//
function GetFileInfo($s_fld)
{
global $aFileVars;
if (FILEUPLOADS && isset($aFileVars[$s_fld]))
{
$a_upload = $aFileVars[$s_fld];
if (isset($a_upload['tmp_name']) && !empty($a_upload['tmp_name']) &&
isset($a_upload['name']) && !empty($a_upload['name']) &&
IsUploadedFile($a_upload))
return ($a_upload);
}
return (false);
}
//
// Return the original name of the uploaded file or false on error.
//
function GetFileName($s_fld)
{
if (($a_upload = GetFileInfo($s_fld)) !== false)
return ($a_upload['name']);
return (false);
}
//
// Return the size of the uploaded file or false on error.
//
function GetFileSize($s_fld)
{
if (($a_upload = GetFileInfo($s_fld)) !== false)
return ($a_upload['size']);
return (false);
}
//
// Return a field value. Empty string is returned if the field is
// not found. File fields return the original name of the uploaded file.
//
function GetFieldValue($s_fld,$a_main_vars)
{
if (!isset($a_main_vars[$s_fld]))
{
if (($s_name = GetFileName($s_fld)) === false)
$s_name = "";
return ($s_name);
}
return ((string) $a_main_vars[$s_fld]);
}
//
// Tests a field against an array of vars for emptyness.
// If the var isn't found there, then the POSTed files array is checked.
// Returns true if the field is empty (a specific error may
// be returned in the $s_mesg parameter).
//
function TestFieldEmpty($s_fld,$a_main_vars,&$s_mesg)
{
global $aFileVars;
$s_mesg = "";
$b_empty = TRUE;
if (!isset($a_main_vars[$s_fld]))
{
//
// Each file var is an array with these elements:
// 'name' => The original name of the file on the client machine.
// 'type' => The mime type of the file, if the browser provided this information.
// 'tmp_name' => The temporary filename of the file in which the uploaded file was stored on the server.
// 'error' => The error code associated with this file upload.
// NOTE: 'error' was added in PHP 4.2.0
// 'size' => The size, in bytes, of the uploaded file.
//
// Error codes (the constants are only available from PHP 4.3.0 so
// we have to use the raw numbers):
// UPLOAD_ERR_OK
// Value: 0; There is no error, the file uploaded with success.
// UPLOAD_ERR_INI_SIZE
// Value: 1; The uploaded file exceeds the upload_max_filesize directive in php.ini.
// UPLOAD_ERR_FORM_SIZE
// Value: 2; The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the html form.
// UPLOAD_ERR_PARTIAL
// Value: 3; The uploaded file was only partially uploaded.
// UPLOAD_ERR_NO_FILE
// Value: 4; No file was uploaded.
//
if (FILEUPLOADS && isset($aFileVars[$s_fld]))
{
$a_upload = $aFileVars[$s_fld];
if (isset($a_upload['tmp_name']) && !empty($a_upload['tmp_name']) &&
isset($a_upload['name']) && !empty($a_upload['name']))
{
if (IsUploadedFile($a_upload))
$b_empty = false;
}
if ($b_empty && isset($a_upload['error']))
switch ($a_upload['error'])
{
case 1:
$s_mesg = GetMessage(MSG_FILE_UPLOAD_ERR1);
break;
case 2:
$s_mesg = GetMessage(MSG_FILE_UPLOAD_ERR2);
break;
case 3:
$s_mesg = GetMessage(MSG_FILE_UPLOAD_ERR3);
break;
case 4:
$s_mesg = GetMessage(MSG_FILE_UPLOAD_ERR4);
break;
case 6:
$s_mesg = GetMessage(MSG_FILE_UPLOAD_ERR6);
break;
case 7:
$s_mesg = GetMessage(MSG_FILE_UPLOAD_ERR7);
break;
case 8:
$s_mesg = GetMessage(MSG_FILE_UPLOAD_ERR8);
break;
default:
$s_mesg = GetMessage(MSG_FILE_UPLOAD_ERR_UNK,
array("ERRNO"=>$a_upload['error']));
break;
}
}
}
else
$b_empty = IsFieldEmpty($a_main_vars[$s_fld]);
return ($b_empty);
}
//
// Return a derived field value or value specification.
//
function GetDerivedValue($a_form_data,$s_word,&$a_errors)
{
global $aFileVars;
$s_value = "";
//
// a field name or a value specification
// value specifications have the following format:
// %spec%
//
if (substr($s_word,0,1) == '%')
{
if (substr($s_word,-1,1) != '%')
{
SendAlert(GetMessage(MSG_INV_VALUE_SPEC,array("SPEC"=>$s_word)));
$s_value = $s_word;
}
else
{
$s_spec = substr($s_word,1,-1);
$s_value = ValueSpec($s_spec,$a_form_data,$a_errors);
}
}
else
{
$s_fld_name = $s_word;
//
// try form data first, then the environment/server data
//
if (IsFieldSet($s_fld_name,$a_form_data))
$s_value = GetFieldValue($s_fld_name,$a_form_data);
elseif (($s_value = GetEnvValue($s_fld_name)) === false)
$s_value = "";
$s_value = trim($s_value);
}
return ($s_value);
}
//
// Derive a value from the form data using the specification returned
// from ParseDerivation.
//
function DeriveValue($a_form_data,$a_value_spec,$s_name,&$a_errors)
{
$s_value = "";
for ($ii = 0 ; $ii < count($a_value_spec) ; $ii++)
{
switch ($a_value_spec[$ii])
{
case '+':
//
// concatenate with a single space between, but skip the space
// if the next field is empty
//
if ($ii < count($a_value_spec)-1)
{
$s_temp = GetDerivedValue($a_form_data,$a_value_spec[$ii+1],$a_errors);
if (!IsFieldEmpty($s_temp))
$s_value .= ' ';
}
break;
case '.':
//
// concatenate with no space between
//
break;
case '*':
//
// concatenate with a single space between
//
$s_value .= ' ';
break;
default:
//
// a field name or a value specification
// value specifications have the following format:
// %name%
//
$s_value .= GetDerivedValue($a_form_data,$a_value_spec[$ii],$a_errors);
break;
}
}
return ($s_value);
}
//
// Create derived fields specified by the "derive_fields" value.
//
function CreateDerived($a_form_data)
{
if (isset($a_form_data["derive_fields"]))
{
$a_errors = array();
//
// get the list of derived field specifications
//
$a_list = TrimArray(explode(",",$a_form_data["derive_fields"]));
foreach ($a_list as $s_fld_spec)
{
if ($s_fld_spec === "")
//
// silently ignore empty derivations
//
continue;
if (($i_pos = strpos($s_fld_spec,"=")) === false)
{
$a_errors[] = $s_fld_spec;
continue;
}
$s_name = trim(substr($s_fld_spec,0,$i_pos));
$s_fld_spec = substr($s_fld_spec,$i_pos+1);
if (($a_value_spec = ParseDerivation($a_form_data,$s_fld_spec,
$s_name,$a_errors)) === false)
break;
$a_form_data[$s_name] = DeriveValue($a_form_data,$a_value_spec,$s_name,$a_errors);
}
if (count($a_errors) > 0)
{
SendAlert(GetMessage(MSG_DERIVED_INVALID).implode("\n",$a_errors));
Error("derivation_failure",GetMessage(MSG_INT_FORM_ERROR));
}
}
return ($a_form_data);
}
//
// To process the name specification for files and update the
// array of file variables accordingly.
//
function SetFileNames($s_name_spec,$a_order,$a_fields,$a_raw_fields,$a_all_raw_values,$a_file_vars)
{
$a_errors = array();
//
// get the list of file name derivations
//
$a_list = TrimArray(explode(",",$s_name_spec));
foreach ($a_list as $s_fld_spec)
{
if ($s_fld_spec === "")
//
// silently ignore empty file name derivations
//
continue;
if (($i_pos = strpos($s_fld_spec,"=")) === false)
{
$a_errors[] = $s_fld_spec;
continue;
}
$s_name = trim(substr($s_fld_spec,0,$i_pos));
$s_fld_spec = substr($s_fld_spec,$i_pos+1);
if (($a_value_spec = ParseDerivation($a_raw_fields,$s_fld_spec,
$s_name,$a_errors)) === false)
break;
if (isset($a_file_vars[$s_name]) && is_array($a_file_vars[$s_name]))
{
//
// we create our own special entry in the file variable's data
//
$a_file_vars[$s_name]['new_name'] = DeriveValue($a_raw_fields,
$a_value_spec,$s_name,
$a_errors);
//
// we also create (derive) a new field called 'name_of_X'
// where X is the file fields's name
//
ProcessField("name_of_$s_name",$a_file_vars[$s_name]['new_name'],
$a_order,$a_fields,$a_raw_fields);
$a_all_raw_values["name_of_$s_name"] = $a_file_vars[$s_name]['new_name'];
}
/* This is annoying if a file upload is optional. Just ignore missing
file upload fields.
else
SendAlert(GetMessage(MSG_FILE_NAMES_NOT_FILE,
array("NAME"=>$s_name)));*/
}
if (count($a_errors) > 0)
{
SendAlert(GetMessage(MSG_FILE_NAMES_INVALID).implode("\n",$a_errors));
Error("file_names_derivation_failure",GetMessage(MSG_INT_FORM_ERROR));
}
return (array($a_order,$a_fields,$a_raw_fields,$a_all_raw_values,$a_file_vars));
}
//
// Process a list of attributes or options.
// Format for each attribute/option:
// name
// or
// name=value
//
// Values can be simple values or semicolon (;) separated lists:
// avalue
// value1;value2;value3;...
//
// Returns attribute/options in the associative array $a_attribs.
// Optionally, valid attributes can be provided in $a_valid_attribs
// (if empty, all attributes found are considered valid).
// Errors are returned in $a_errors.
//
function ProcessAttributeList($a_list,&$a_attribs,&$a_errors,
$a_valid_attribs = array())
{
$b_got_valid_list = (count($a_valid_attribs) > 0);
foreach ($a_list as $s_attrib)
{
//
// if the name begins with '.' then silently ignore it;
// this allows you to temporarily disable an option without
// getting an alert message
//
if (($i_pos = strpos($s_attrib,"=")) === false)
{
$s_name = trim($s_attrib);
if (empty($s_name) || $s_name{0} == '.')
continue;
//
// option is a simple "present" value
//
$a_attribs[$s_name] = true;
}
else
{
$s_name = trim(substr($s_attrib,0,$i_pos));
if (empty($s_name) || $s_name{0} == '.')
continue;
$s_value_list = substr($s_attrib,$i_pos+1);
if (($i_pos = strpos($s_value_list,";")) === false)
//
// single value
//
$a_attribs[$s_name] = trim($s_value_list);
else
//
// list of values
//
$a_attribs[$s_name] = TrimArray(explode(";",$s_value_list));
}
if ($b_got_valid_list && !isset($a_valid_attribs[$s_name]))
$a_errors[] = $s_name;
}
}
//
// Process the options specified in the form.
// Options can be specified in this format:
// option1,option2,option3,...
// Each option can be a simple word or a word and value:
// name
// name=value
// No name or value can contain a comma.
// Values can be simple values or semicolon (;) separated lists:
// avalue
// value1;value2;value3;...
// No value can contain a semicolon.
// Be careful of values beginning and ending with whitespace characters;
// they will be trimmed.
//
function ProcessOptions($s_name,$a_form_data,&$a_options,$a_valid_options)
{
$a_errors = array();
$a_options = array();
if (isset($a_form_data[$s_name]))
{
//
// get the options list and trim each one
//
$a_list = TrimArray(explode(",",$a_form_data[$s_name]));
ProcessAttributeList($a_list,$a_options,$a_errors,$a_valid_options);
}
if (count($a_errors) > 0)
SendAlert(GetMessage(MSG_OPTIONS_INVALID,array("OPT"=>$s_name)).
implode("\n",$a_errors));
}
//
// Process the mail_options specified in the form.
//
function ProcessMailOptions($a_form_data)
{
global $MAIL_OPTS,$VALID_MAIL_OPTIONS;
ProcessOptions("mail_options",$a_form_data,$MAIL_OPTS,$VALID_MAIL_OPTIONS);
}
//
// Check if an option is set
//
function IsMailOptionSet($s_name)
{
global $MAIL_OPTS;
return (isset($MAIL_OPTS[$s_name]));
}
//
// Return an option's value or NULL if not set.
//
function GetMailOption($s_name)
{
global $MAIL_OPTS;
return (isset($MAIL_OPTS[$s_name]) ? $MAIL_OPTS[$s_name] : NULL);
}
//
// Process the crm_options specified in the form.
//
function ProcessCRMOptions($a_form_data)
{
global $CRM_OPTS,$VALID_CRM_OPTIONS;
ProcessOptions("crm_options",$a_form_data,$CRM_OPTS,$VALID_CRM_OPTIONS);
}
//
// Check if an option is set
//
function IsCRMOptionSet($s_name)
{
global $CRM_OPTS;
return (isset($CRM_OPTS[$s_name]));
}
//
// Return an option's value or NULL if not set.
//
function GetCRMOption($s_name)
{
global $CRM_OPTS;
return (isset($CRM_OPTS[$s_name]) ? $CRM_OPTS[$s_name] : NULL);
}
//
// Check if a field is in the mail exclusion list.
//
function IsMailExcluded($s_name)
{
$a_list = GetMailOption("Exclude");
if (!isset($a_list))
return (false);
if (is_array($a_list))
return (in_array($s_name,$a_list));
else
return ($s_name === $a_list);
}
//
// Process the autorespond specified in the form.
//
function ProcessAROptions($a_form_data)
{
global $AR_OPTS,$VALID_AR_OPTIONS;
ProcessOptions("autorespond",$a_form_data,$AR_OPTS,$VALID_AR_OPTIONS);
}
//
// Check if an option is set
//
function IsAROptionSet($s_name)
{
global $AR_OPTS;
return (isset($AR_OPTS[$s_name]));
}
//
// Return an option's value or NULL if not set.
//
function GetAROption($s_name)
{
global $AR_OPTS;
return (isset($AR_OPTS[$s_name]) ? $AR_OPTS[$s_name] : NULL);
}
//
// Process the mail_options specified in the form.
//
function ProcessFilterOptions($a_form_data)
{
global $FILTER_OPTS,$VALID_FILTER_OPTIONS;
ProcessOptions("filter_options",$a_form_data,$FILTER_OPTS,$VALID_FILTER_OPTIONS);
}
//
// Check if an option is set
//
function IsFilterOptionSet($s_name)
{
global $FILTER_OPTS;
return (isset($FILTER_OPTS[$s_name]));
}
//
// Return an option's value or NULL if not set.
//
function GetFilterOption($s_name)
{
global $FILTER_OPTS;
return (isset($FILTER_OPTS[$s_name]) ? $FILTER_OPTS[$s_name] : NULL);
}
//
// Lookup a filter attribute for the given filter.
// Return it's value or false if not set.
//
function GetFilterAttrib($s_filter,$s_attrib)
{
global $FILTER_ATTRIBS,$FILTER_ATTRIBS_LOOKUP;
if (!isset($FILTER_ATTRIBS[$s_filter]))
//
// no attributes for the filter
//
return (false);
if (!isset($FILTER_ATTRIBS_LOOKUP[$s_filter]))
{
//
// the attributes have not yet been parsed - create the lookup table
//
$a_list = TrimArray(explode(",",$FILTER_ATTRIBS[$s_filter]));
$FILTER_ATTRIBS_LOOKUP[$s_filter] = array();
$a_errors = array();
ProcessAttributeList($a_list,$FILTER_ATTRIBS_LOOKUP[$s_filter],$a_errors);
}
//
// perform the lookup and return the value
//
if (!isset($FILTER_ATTRIBS_LOOKUP[$s_filter][$s_attrib]))
return (false);
return ($FILTER_ATTRIBS_LOOKUP[$s_filter][$s_attrib]);
}
//
// Check the filter attributes for the given filter.
// Return true if the given attribute is set otherwise false.
//
function IsFilterAttribSet($s_filter,$s_attrib)
{
return (GetFilterAttrib($s_filter,$s_attrib));
}
//
// Process the given .ini file.
//
function ProcessFormIniFile($s_file)
{
global $EMAIL_ADDRS;
$a_sections = parse_ini_file($s_file,TRUE);
if (DB_SEE_INI)
{
//
// just display the ini file
//
$s_text = "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);
exit;
}
//
// Load the email_addresses section.
//
if (isset($a_sections["email_addresses"]))
$EMAIL_ADDRS = $a_sections["email_addresses"];
//
// Process special fields
//
if (isset($a_sections["special_fields"]))
{
foreach ($a_sections["special_fields"] as $s_name=>$m_value)
{
if (IsSpecialField($s_name))
SetSpecialField($s_name,$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
//
function UnMangle($email)
{
global $EMAIL_ADDRS;
//
// map from a name to the real email address
//
if (isset($EMAIL_ADDRS[$email]))
$email = $EMAIL_ADDRS[$email];
//
// unmangle
//
if (AT_MANGLE != "")
$email = str_replace(AT_MANGLE,"@",$email);
return ($email);
}
//
// Check a list of email addresses (comma separated); returns a list
// of valid email addresses (comma separated).
// The return value is true if there is at least one valid email address.
//
function CheckEmailAddress($s_addr,&$s_valid,&$s_invalid)
{
global $TARGET_EMAIL;
$s_invalid = $s_valid = "";
$a_list = TrimArray(explode(",",$s_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;
}
$b_is_valid = false;
for ($jj = 0 ; $jj < count($TARGET_EMAIL) ; $jj++)
if (eregi($TARGET_EMAIL[$jj],$s_email))
{
if (empty($s_valid))
$s_valid = $s_email;
else
$s_valid .= ",".$s_email;
$b_is_valid = true;
break;
}
if (!$b_is_valid)
$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)
{
//
// for browsers without cookies enabled, append the Session ID
//
if (session_id() !== "")
$url = AddURLParams($url,session_name()."=".urlencode(session_id()));
if (defined("SID"))
$url = AddURLParams($url,SID);
//
// 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");
//
// 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);
exit;
}
//
// 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);
}
//
// Expands an array of mail headers into mail header lines.
//
function ExpandMailHeaders($a_headers)
{
$s_hdrs = "";
foreach ($a_headers as $s_name=>$s_value)
if ($s_name != "")
{
if ($s_hdrs != "")
$s_hdrs .= HEAD_CRLF;
$s_hdrs .= $s_name.": ".$s_value;
}
return ($s_hdrs);
}
//
// Expands an array of mail headers into an array containing header lines.
//
function ExpandMailHeadersArray($a_headers)
{
$a_hdrs = array();
foreach ($a_headers as $s_name=>$s_value)
if ($s_name != "")
$a_hdrs[] = $s_name.": ".$s_value.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.
//
function DoMail($s_to,$s_subject,$s_mesg,$a_headers)
{
global $PEAR_SMTP_HOST,$PEAR_SMTP_PORT,$PEAR_SMTP_USER,$PEAR_SMTP_PWD;
if (isset($PEAR_SMTP_HOST) && !empty($PEAR_SMTP_HOST))
{
require_once("Mail.php");
$a_params = array( "host"=>$PEAR_SMTP_HOST,
"port"=>$PEAR_SMTP_PORT);
if (isset($PEAR_SMTP_USER) && !empty($PEAR_SMTP_USER))
{
$a_params["auth"] = TRUE;
$a_params["username"] = $PEAR_SMTP_USER;
$a_params["password"] = $PEAR_SMTP_PWD;
}
$mailer = Mail::factory("smtp",$a_params);
if (!is_object($mailer))
{
ShowError("pear_error",GetMessage(MSG_PEAR_OBJ),FALSE,FALSE);
exit;
}
if (get_class($mailer) === 'pear_error')
{
ShowError("pear_error",$mailer->getMessage(),FALSE,FALSE);
exit;
}
if (!isset($a_headers['To']) && !isset($a_headers['to']))
$a_headers['To'] = $s_to;
if (!isset($a_headers['Subject']) && !isset($a_headers['subject']))
$a_headers['Subject'] = $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);
}
return (mail($s_to,$s_subject,$s_mesg,ExpandMailHeaders($a_headers)));
}
//
// Send an email
//
function SendCheckedMail($to,$subject,$mesg,$sender,$a_headers = array())
{
global $PEAR_SMTP_HOST;
$b_f_option = false;
$b_form_option = IsMailOptionSet("SendMailFOption"); // this is superseded, but still supported
if (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 (INI_SET_FROM && !empty($sender))
ini_set('sendmail_from',$sender);
if ((!isset($PEAR_SMTP_HOST) || empty($PEAR_SMTP_HOST)) && $b_f_option)
return (mail($to,$subject,$mesg,ExpandMailHeaders($a_headers),"-f$sender"));
else
return (DoMail($to,$subject,$mesg,$a_headers));
}
//
// Send an alert email
//
function SendAlert($s_error,$b_filter = true,$b_non_error = false)
{
global $SPECIAL_VALUES,$FORMATTED_INPUT,$FROM_USER,$aServerVars,$aStrippedFormVars;
global $aAlertInfo,$aCleanedValues,$aFieldOrder;
$s_error = str_replace("\n",BODY_LF,$s_error);
$b_got_filter = (isset($SPECIAL_VALUES["filter"]) && !empty($SPECIAL_VALUES["filter"]));
//
// 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 $SPECIAL_VALUES set, so
// look in the form vars too
//
if (isset($SPECIAL_VALUES["alert_to"]))
$s_alert_to = trim($SPECIAL_VALUES["alert_to"]);
if (empty($s_alert_to) && isset($aStrippedFormVars["alert_to"]))
$s_alert_to = trim($aStrippedFormVars["alert_to"]);
if (isset($SPECIAL_VALUES["subject"]))
$s_form_subject = trim($SPECIAL_VALUES["subject"]);
if (empty($s_form_subject) && isset($aStrippedFormVars["subject"]))
$s_form_subject = trim($aStrippedFormVars["subject"]);
if (empty($s_alert_to))
{
$s_alert_to = DEF_ALERT;
$b_check = false;
}
if (!empty($s_alert_to))
{
$s_from_addr = $s_from = "";
$a_headers = array();
if (isset($FROM_USER) && !empty($FROM_USER))
{
if ($FROM_USER != "NONE")
{
$a_headers['From'] = $FROM_USER;
$s_from = "From: $FROM_USER";
$s_from_addr = $FROM_USER;
}
}
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).BODY_LF;
if (!empty($s_from))
$s_mesg .= $s_from.BODY_LF;
$s_mesg .= BODY_LF;
if (count($aAlertInfo) > 0)
{
if ($b_show_data)
{
$s_error .= BODY_LF.GetMessage(MSG_MORE_INFO).BODY_LF;
$s_error .= implode(BODY_LF,$aAlertInfo);
}
else
$s_error .= BODY_LF.GetMessage(MSG_INFO_STOPPED).BODY_LF;
}
//
// some fields aren't security issues - show those in the alert
//
$a_safe_fields = array(
"email: ".$SPECIAL_VALUES["email"],
"realname: ".$SPECIAL_VALUES["realname"],
);
$s_safe_data = implode(BODY_LF,$a_safe_fields);
if ($b_non_error)
{
$s_preamble = $s_error.BODY_LF.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).BODY_LF.
$s_error.BODY_LF.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 .= BODY_LF.BODY_LF;
if ($b_show_data)
$s_mesg .= implode(BODY_LF,$FORMATTED_INPUT);
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($SPECIAL_VALUES["filter"],"Encrypts"))
{
$s_new_mesg = $s_preamble.$s_safe_data;
$s_new_mesg .= BODY_LF.BODY_LF;
$s_filter = $SPECIAL_VALUES["filter"];
if (($a_filter_list = GetFilterList()) !== false)
{
//
// just filter the critical fields
//
list($s_unfiltered,$s_filtered_results) =
GetFilteredOutput($aFieldOrder,$aCleanedValues,
$s_filter,$a_filter_list);
$s_new_mesg .= $s_unfiltered;
}
else
{
//
// filter everything
//
$s_filtered_results = Filter($s_filter,$s_mesg);
}
$s_new_mesg .= GetMessage(MSG_FILTERED,array("FILTER"=>$s_filter)).
BODY_LF.BODY_LF.
$s_filtered_results;
$s_mesg = $s_new_mesg;
}
if (isset($aServerVars['HTTP_REFERER']))
$s_mesg .= BODY_LF.BODY_LF."Referring page was ".$aServerVars['HTTP_REFERER'];
elseif (isset($SPECIAL_VALUES['this_form']) && $SPECIAL_VALUES['this_form'] !== "")
$s_mesg .= BODY_LF.BODY_LF."Referring form was ".$SPECIAL_VALUES['this_form'];
if (isset($aServerVars['REMOTE_ADDR']))
$s_mesg .= BODY_LF.BODY_LF."User IP address was ".$aServerVars['REMOTE_ADDR'];
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.
// Returns false on failure ($s_error has the error string)
//
function GetURL($s_url,&$s_error)
{
global $php_errormsg,$aServerVars,$FM_VERS;
global $AUTHENTICATE,$AUTH_USER,$AUTH_PW;
//
// open the URL with the same session as we have
//
if (session_id() !== "")
$s_url = AddURLParams($s_url,session_name()."=".urlencode(session_id()));
if (defined("SID"))
$s_url = AddURLParams($s_url,SID);
//
// parse the URL to get the component parts
//
$a_parts = parse_url($s_url);
//
// must have a host
//
if (!isset($a_parts["host"]))
{
$s_error = GetMessage(MSG_URL_PARSE);
return (false);
}
$s_host_hdr = $a_parts["host"];
//
// if no port number is given, we support http and https
//
if (!isset($a_parts["port"]))
{
if (!isset($a_parts["scheme"]) || strtolower($a_parts["scheme"]) == "http")
$a_parts["port"] = 80;
elseif (strtolower($a_parts["scheme"]) == "https")
$a_parts["port"] = 443;
else
{
$s_error = GetMessage(MSG_URL_SCHEME,
array("SCHEME"=>$a_parts["scheme"]));
return (false);
}
}
if ($a_parts["port"] == 443)
//
// fsockopen requires ssl:// in the host name
//
$a_parts["host"] = "ssl://".$a_parts["host"];
//
// default the path if empty
//
if (!isset($a_parts["path"]) || $a_parts["path"] === "")
$a_parts["path"] = "/";
$f_sock = @fsockopen($a_parts["host"],(int) $a_parts["port"],$i_errno,$s_errstr,30);
if ($f_sock === false)
{
$s_error = GetMessage(MSG_SOCKET,
array("ERRNO"=>$i_errno,
"ERRSTR"=>$s_errstr,
"PHPERR"=>isset($php_errormsg) ? $php_errormsg : ""));
return (false);
}
$s_req = $a_parts["path"];
//
// 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($a_parts["query"])
// encodes the '=' between parameters and this breaks things.
//
if (isset($a_parts["query"]))
{
$a_params = explode('&',$a_parts["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_req .= '?'.implode('&',$a_params);
}
//
// add the fragment to the path. Note, however, this
// won't actually make the user's browser jump to that
// location (because we'd need to alter our current URL
// and add the fragment to achieve that - we might
// add that feature in a later version if we can
// figure out how to do it!)
//
if (isset($a_parts["fragment"]))
$s_req .= '#'.urlencode($a_parts["fragment"]);
//
// Since we might be opening a URL within the same session, we can
// get locks. So, close the session for writing to prevent this.
//
if (function_exists('session_write_close'))
{
session_write_close();
ob_flush(); // probably a good idea
}
//
// the GET request
//
fputs($f_sock,"GET ".$s_req." HTTP/1.0\r\n");
//
// Determine authentication requirements
//
if ($AUTHENTICATE !== "" || $AUTH_USER !== "" || $AUTH_PW !== "")
{
if ($AUTHENTICATE === "")
fputs($f_sock,"Authorization: Basic ".
base64_encode("$AUTH_USER:$AUTH_PW")."\r\n");
else
fputs($f_sock,"Authorization: $AUTHENTICATE\r\n");
}
else
{
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";
//
// Add the authentication header
//
if ($s_auth_user !== "" || $s_auth_pass !== "")
fputs($f_sock,"Authorization: $s_auth_type ".
base64_encode("$s_auth_user:$s_auth_pass")."\r\n");
}
//
// Specify the host name
//
fputs($f_sock,"Host: $s_host_hdr\r\n");
//
// Specify the user agent
//
fputs($f_sock,"User-Agent: FormMail/$FM_VERS (from www.tectite.com)\r\n");
//
// Accept any output
//
fputs($f_sock,"Accept: */*\r\n");
//
// End of request headers
//
fputs($f_sock,"\r\n");
//
// Read and parse the response header
//
$i_http_code = 0;
$s_status = "";
while (!feof($f_sock))
{
$s_line = fgets($f_sock,4096);
if ($s_line == "\r\n" || $s_line == "\n")
break;
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);
}
}
if ($i_http_code < 200 || $i_http_code > 299)
{
$s_error = GetMessage(MSG_GETURL_OPEN,array("STATUS"=>$s_status));
$m_buf = false;
}
else
{
//
// read content into one big string buffer and return
//
$m_buf = "";
while (!feof($f_sock))
$m_buf .= fread($f_sock,1024);
}
fclose($f_sock);
//
// re-open our session
//
session_start();
return ($m_buf);
}
//
// 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
{
global $aServerVars;
$s_name = "$s_url/".basename($s_name);
if (isset($aServerVars['HTTP_USER_AGENT']))
$s_name = AddURLParams($s_name,"USER_AGENT=".$aServerVars['HTTP_USER_AGENT']);
//
// open the URL with the same session as we have
//
if (session_id() !== "")
$s_name = AddURLParams($s_name,session_name()."=".urlencode(session_id()));
if (defined("SID"))
$s_name = AddURLParams($s_name,SID);
//
// Since we might be opening a URL within the same session, we can
// get locks. So, close the session for writing to prevent this.
//
if (function_exists('session_write_close'))
{
session_write_close();
ob_flush(); // probably a good idea
}
@ $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
//
while (!feof($fp))
$s_buf .= fread($fp,4096);
fclose($fp);
//
// now re-open our session
//
session_start();
}
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)
{
global $TEMPLATEURL,$TEMPLATEDIR;
if (empty($TEMPLATEDIR) && empty($TEMPLATEURL))
{
SendAlert(GetMessage(MSG_TEMPLATES));
return (false);
}
if (($s_buf = LoadTemplate($s_name,$TEMPLATEDIR,$TEMPLATEURL)) === false)
return (false);
//
// now look for the tags to replace
//
foreach ($a_specs as $s_tag=>$s_value)
//
// search for
//
// with optional whitespace
//
$s_buf = preg_replace('/<\s*'.preg_quote($s_tag,"/").'\s*\/\s*>/ims',
nl2br($s_value),$s_buf);
if ($b_user_error)
{
// strip any and tags
//
// You can show information that's specific to user
// errors between these special tags.
//
$s_buf = preg_replace('/<\s*\/?\s*fmusererror\s*>/ims','',$s_buf);
//
// since this isn't a system error, strip anything between
// and
//
$s_buf = preg_replace('/<\s*fmsyserror\s*>.*<\s*\/\s*fmsyserror\s*>/ims','',$s_buf);
}
else
{
// strip any and tags
//
// You can show information that's specific to system
// errors between these special tags.
//
$s_buf = preg_replace('/<\s*\/?\s*fmsyserror\s*>/ims','',$s_buf);
//
// since this isn't a user error, strip anything between
// and
//
$s_buf = preg_replace('/<\s*fmusererror\s*>.*<\s*\/\s*fmusererror\s*>/ims','',$s_buf);
}
//
// just output the page
//
echo $s_buf;
return (true);
}
//
// To show an error to the user.
//
function ShowError($error_code,$error_mesg,$b_user_error,
$b_alerted = false,$a_item_list = array(),$s_extra_info = "")
{
global $SPECIAL_FIELDS,$SPECIAL_MULTI,$SPECIAL_VALUES;
global $aServerVars,$aSessionVars,$aStrippedFormVars;
//
// Testing with PHP 4.0.6 indicates that sessions don't always work.
// So, we'll also add the error to the URL, unless
// PUT_DATA_IN_URL is false.
//
$aSessionVars["FormError"] = $error_mesg;
$aSessionVars["FormErrorInfo"] = $s_extra_info;
$aSessionVars["FormErrorCode"] = $error_code;
$aSessionVars["FormErrorItems"] = $a_item_list;
$aSessionVars["FormIsUserError"] = $b_user_error;
$aSessionVars["FormAlerted"] = $b_alerted;
$aSessionVars["FormData"] = array();
$bad_url = $SPECIAL_VALUES["bad_url"];
$bad_template = $SPECIAL_VALUES["bad_template"];
$this_form = $SPECIAL_VALUES["this_form"];
if (!empty($bad_url))
{
$a_params = array();
$a_params[] = "this_form=".urlencode("$this_form");
$a_params[] = "bad_template=".urlencode("$bad_template");
if (PUT_DATA_IN_URL)
{
$a_params[] = "error=".urlencode("$error_mesg");
$a_params[] = "extra=".urlencode("$s_extra_info");
$a_params[] = "errcode=".urlencode("$error_code");
$a_params[] = "isusererror=".($b_user_error ? "1" : "0");
$a_params[] = "alerted=".($b_alerted ? "1" : "0");
$i_count = 1;
foreach ($a_item_list as $s_item)
{
$a_params[] = "erroritem$i_count=".urlencode("$s_item");
$i_count++;
}
}
else
//
// tell the bad_url to look in the session only
//
$a_params[] = "insession=1";
//
// Add the posted data to the URL so that an intelligent
// $bad_url can call the form again
//
foreach ($aStrippedFormVars as $s_name=>$m_value)
{
//
// skip special fields
//
$b_special = false;
if (in_array($s_name,$SPECIAL_FIELDS))
$b_special = true;
else
{
foreach ($SPECIAL_MULTI as $s_multi_fld)
{
$i_len = strlen($s_multi_fld);
if (substr($s_name,0,$i_len) == $s_multi_fld)
{
$i_index = (int) substr($s_name,$i_len);
if ($i_index > 0)
{
$b_special = true;
break;
}
}
}
}
if (!$b_special)
{
if (PUT_DATA_IN_URL)
{
if (is_array($m_value))
foreach ($m_value as $s_value)
$a_params[] = "$s_name".'[]='.
urlencode(substr($s_value,0,MAXSTRING));
else
$a_params[] = "$s_name=".urlencode(substr($m_value,0,MAXSTRING));
}
else
{
if (is_array($m_value))
$aSessionVars["FormData"]["$s_name"] = $m_value;
else
$aSessionVars["FormData"]["$s_name"] = substr($m_value,0,MAXSTRING);
}
}
}
//
// Now add the authentication data, if any
//
if ((isset($aServerVars["PHP_AUTH_USER"]) &&
$aServerVars["PHP_AUTH_USER"] !== "") ||
(isset($aServerVars["PHP_AUTH_PW"]) &&
$aServerVars["PHP_AUTH_PW"] !== ""))
{
if (PUT_DATA_IN_URL)
{
if (isset($aServerVars["PHP_AUTH_USER"]))
$a_params[] = "PHP_AUTH_USER=".urlencode($aServerVars["PHP_AUTH_USER"]);
if (isset($aServerVars["PHP_AUTH_PW"]))
$a_params[] = "PHP_AUTH_PW=".urlencode($aServerVars["PHP_AUTH_PW"]);
if (isset($aServerVars["PHP_AUTH_TYPE"]))
$a_params[] = "PHP_AUTH_TYPE=".urlencode($aServerVars["PHP_AUTH_TYPE"]);
}
else
{
if (isset($aServerVars["PHP_AUTH_USER"]))
$aSessionVars["FormData"]["PHP_AUTH_USER"] = $aServerVars["PHP_AUTH_USER"];
if (isset($aServerVars["PHP_AUTH_PW"]))
$aSessionVars["FormData"]["PHP_AUTH_PW"] = $aServerVars["PHP_AUTH_PW"];
if (isset($aServerVars["PHP_AUTH_TYPE"]))
$aSessionVars["FormData"]["PHP_AUTH_TYPE"] = $aServerVars["PHP_AUTH_TYPE"];
}
}
$bad_url = AddURLParams($bad_url,$a_params,false);
Redirect($bad_url);
}
else
{
if (!empty($bad_template))
{
$a_specs = array("fmerror"=>htmlspecialchars("$error_mesg"),
"fmerrorcode"=>htmlspecialchars("$error_code"),
"fmfullerror"=>htmlspecialchars("$error_mesg")."\n".
htmlspecialchars("$s_extra_info"),
"fmerrorextra"=>htmlspecialchars("$s_extra_info"),);
$i_count = 1;
foreach ($a_item_list as $s_item)
{
$a_specs["fmerroritem$i_count"] = htmlspecialchars($s_item);
$i_count++;
}
$s_list = "";
foreach ($a_item_list as $s_item)
$s_list .= "".htmlspecialchars($s_item)."\n";
$a_specs["fmerroritemlist"] = $s_list;
if (ShowErrorTemplate($bad_template,$a_specs,$b_user_error))
return;
}
$s_text = GetMessage(MSG_ERROR_PROC);
if ($b_user_error)
$s_text .= $error_mesg."\n".$s_extra_info;
else
{
if ($b_alerted)
$s_text .= GetMessage(MSG_ALERT_DONE);
else
$s_text .= GetMessage(MSG_PLS_CONTACT);
$s_text .= GetMessage(MSG_APOLOGY);
}
CreatePage($s_text);
//
// the session data is not needed now
//
ZapSession();
}
}
//
// Report an error. Same as Error, but implements
// ATTACK_DETECTION_IGNORE_ERRORS.
//
function ErrorWithIgnore($error_code,$error_mesg,$b_filter = true,$show = true,$int_mesg = "")
{
$b_alerted = false;
if (!ATTACK_DETECTION_IGNORE_ERRORS)
if (SendAlert("$error_code\n *****$int_mesg*****\nError=$error_mesg\n",$b_filter))
$b_alerted = true;
if ($show)
ShowError($error_code,$error_mesg,false,$b_alerted);
else
//
// show something to the user
//
ShowError($error_code,GetMessage(MSG_SUBM_FAILED),false,$b_alerted);
exit;
}
//
// Report an error
//
function Error($error_code,$error_mesg,$b_filter = true,$show = true,$int_mesg = "")
{
$b_alerted = false;
if (SendAlert("$error_code\n *****$int_mesg*****\nError=$error_mesg\n",$b_filter))
$b_alerted = true;
if ($show)
ShowError($error_code,$error_mesg,false,$b_alerted);
else
//
// show something to the user
//
ShowError($error_code,GetMessage(MSG_SUBM_FAILED),false,$b_alerted);
exit;
}
//
// Report a user error
//
function UserError($s_error_code,$s_error_mesg,
$s_extra_info = "",$a_item_list = array())
{
$b_alerted = false;
if (ALERT_ON_USER_ERROR &&
SendAlert("$s_error_code\nError=$s_error_mesg\n$s_extra_info\n"))
$b_alerted = true;
ShowError($s_error_code,$s_error_mesg,true,$b_alerted,$a_item_list,$s_extra_info);
exit;
}
//
// Create a simple page with the given text.
//
function CreatePage($text)
{
global $FM_VERS,$sHTMLCharSet;
echo "\n";
echo "\n";
if (isset($sHTMLCharSet) && $sHTMLCharSet !== "")
echo "\n";
echo "\n";
echo "\n";
echo nl2br($text);
echo "";
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)
{
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)
{
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.
// If $b_conv_quotes is true, also swaps all double quotes with single quotes.
//
function Strip($value,$b_conv_quotes = true)
{
if ($b_conv_quotes)
//
// "standard" quote conversion
//
$value = str_replace("\"","'",$value);
$value = preg_replace('/[[:cntrl:][:space:]]+/'," ",$value); // zap all control chars 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 "" where X is the type.
// In general, FormMail won't receive non-scalar non-array values, so this
// is more a future-proofing measure.
//
function CleanValue($m_value,$b_conv_quotes = true)
{
if (is_array($m_value))
{
foreach ($m_value as $m_key=>$m_item)
$m_value[$m_key] = CleanValue($m_item,$b_conv_quotes);
}
elseif (!is_scalar($m_value))
$m_value = "<".gettype($m_value).">";
else
{
//
// convert to string and truncate
//
$m_value = substr("$m_value",0,MAXSTRING);
//
// strip unwanted chars and trim
//
$m_value = trim(Strip($m_value,$b_conv_quotes));
}
return ($m_value);
}
//
// Clean a special value. Special values listed in $SPECIAL_NOSTRIP
// will not be cleaned.
//
function SpecialCleanValue($s_name,$m_value)
{
global $SPECIAL_NOSTRIP;
if (!in_array($s_name,$SPECIAL_NOSTRIP))
$m_value = CleanValue($m_value);
return ($m_value);
}
//
// Return the fields and their values in a string containing one
// field per line.
//
function MakeFieldOutput($a_order,$a_fields,$s_line_feed = BODY_LF)
{
$n_order = count($a_order);
$s_output = "";
for ($ii = 0 ; $ii < $n_order ; $ii++)
{
$s_name = $a_order[$ii];
if (isset($a_fields[$s_name]))
$s_output .= "$s_name: ".$a_fields[$s_name].$s_line_feed;
}
return ($s_output);
}
//
// Check if a field name is special. Returns true if it is.
//
function IsSpecialField($s_name)
{
global $SPECIAL_FIELDS;
return (in_array($s_name,$SPECIAL_FIELDS));
}
//
// Set a special field value.
//
function SetSpecialField($s_name,$m_value)
{
global $SPECIAL_VALUES;
//
// special values cannot be arrays; ignore them if they are
//
if (!is_array($m_value))
$SPECIAL_VALUES[$s_name] = SpecialCleanValue($s_name,$m_value);
}
//
// Check if a field name is a special "multi" field.
// A multi field is the name plus a sequence number. For example,
// conditions1
// conditions2
// Returns a list (array) if it is, otherwise false if not.
// The list contains:
// 1. the name of the special multi field
// 2. the index number for multi field
//
function IsSpecialMultiField($s_name)
{
global $SPECIAL_MULTI;
foreach ($SPECIAL_MULTI as $s_multi_fld)
{
$i_len = strlen($s_multi_fld);
//
// look for nameN where N is a number starting from 1
//
if (substr($s_name,0,$i_len) == $s_multi_fld)
{
$i_index = (int) substr($s_name,$i_len);
if ($i_index > 0)
{
//
// re-index to zero
//
--$i_index;
return (array($s_multi_fld,$i_index));
}
}
}
return (false);
}
//
// Set a multi field value.
//
function SetSpecialMultiField($s_name,$i_index,$m_value)
{
global $SPECIAL_VALUES;
//
// special fields cannot be arrays - ignore if it is
//
if (!is_array($m_value))
$SPECIAL_VALUES[$s_name][$i_index] = SpecialCleanValue($s_name,$m_value);
}
//
// Process a field
//
function ProcessField($s_name,$raw_value,&$a_order,&$a_fields,&$a_raw_fields)
{
global $FORMATTED_INPUT;
//
// fields go into an array of special values or an array of other values
//
$b_special = false;
if (IsSpecialField($s_name))
{
SetSpecialField($s_name,$raw_value);
$b_special = true;
}
//
// check for multiple valued special fields
//
if (($a_multi_fld = IsSpecialMultiField($s_name)) !== false)
{
SetSpecialMultiField($a_multi_fld[0],$a_multi_fld[1],$raw_value);
$b_special = true;
}
if (!$b_special)
{
//
// return the raw value unchanged in the $a_raw_fields array
//
$a_raw_fields[$s_name] = $raw_value;
//
// handle checkboxes and multiple-selection lists
// Thanks go to Theodore Boardman for the suggestion
// and initial working code.
//
if (is_array($raw_value))
{
//
// the array must be an array of scalars (not an array
// of arrays, for example)
//
if (is_scalar($raw_value[0]))
{
$a_cleaned_values = CleanValue($raw_value);
//
// the output is a comma separated list of values for the
// checkbox. For example,
// events: Diving,Cycling,Running
//
// Set the clean value to the list of cleaned checkbox
// values.
// First, remove any commas in the values themselves.
//
$a_cleaned_values = str_replace(",","",$a_cleaned_values);
$s_cleaned_value = implode(",",$a_cleaned_values);
}
else
$s_cleaned_value = "";
}
else
{
//
// NOTE: there is a minor bug here now that we support
// $FORM_INI_FILE. The INI file is processed at the end
// so if you set the mail_options below in the INI file they
// won't get processed here. This means you must set
// the following mail_options in the HTML form for now.
// (To be fixed at a later date. RJR 17-Feb-06).
//
//
// if the form specifies the "KeepLines" option,
// don't strip new lines
//
if (IsMailOptionSet("KeepLines") && strpos($raw_value,"\n") !== false)
{
//
// truncate first
//
$s_truncated = substr("$raw_value",0,MAXSTRING);
//
// split into lines, clean each individual line,
// then put it back together again
//
$a_lines = explode("\n",$s_truncated);
$a_lines = CleanValue($a_lines);
$s_cleaned_value = implode(BODY_LF,$a_lines);
//
// and, for this special case, prepend a new line
// so that the value is shown on a fresh line
//
$s_cleaned_value = BODY_LF.$s_cleaned_value;
}
else
$s_cleaned_value = CleanValue($raw_value);
}
//
// if the form specifies the "NoEmpty" option, skip
// empty values.
//
if (!IsMailOptionSet("NoEmpty") || !IsFieldEmpty($s_cleaned_value))
if (!IsMailExcluded($s_name))
{
//
// by default, we maintain the order as passed in
// the HTTP request
//
$a_order[] = $s_name;
$a_fields[$s_name] = $s_cleaned_value;
}
//
// add to the $FORMATTED_INPUT array for debugging and
// error reporting
//
array_push($FORMATTED_INPUT,"$s_name: '$s_cleaned_value'");
}
}
//
// Parse the input variables and return:
// 1. an array that specifies the required field order in the output
// 2. an array containing the non-special cleaned field values indexed
// by field name.
// 3. an array containing the non-special raw field values indexed by
// field name.
//
function ParseInput($a_vars)
{
$a_order = array();
$a_fields = array();
$a_raw_fields = array();
//
// scan the array of values passed in (name-value pairs) and
// produce slightly formatted (not HTML) textual output
// and extract any special values found.
//
foreach ($a_vars as $s_name=>$raw_value)
ProcessField($s_name,$raw_value,$a_order,$a_fields,$a_raw_fields);
return (array($a_order,$a_fields,$a_raw_fields));
}
//
// Get the URL for sending to the CRM.
//
function GetCRMURL($spec,$vars,$url)
{
$bad = false;
$list = TrimArray(explode(",",$spec));
$map = array();
for ($ii = 0 ; $ii < count($list) ; $ii++)
{
$name = $list[$ii];
if ($name)
{
//
// the specification must be in this format:
// form-field-name:CRM-field-name
//
if (($i_crm_name_pos = strpos($name,":")) > 0)
{
$s_crm_name = substr($name,$i_crm_name_pos + 1);
$name = substr($name,0,$i_crm_name_pos);
if (isset($vars[$name]))
{
$map[] = $s_crm_name."=".urlencode($vars[$name]);
$map[] = "Orig_".$s_crm_name."=".urlencode($name);
}
}
else
{
//
// not the right format, so just include as a parameter
// check for name=value format to choose encoding
//
$a_values = explode("=",$name);
if (count($a_values) > 1)
$map[] = urlencode($a_values[0])."=".urlencode($a_values[1]);
else
$map[] = urlencode($a_values[0]);
}
}
}
if (count($map) == 0)
return ("");
return (AddURLParams($url,$map,false));
}
//
// strip the HTML from a string
//
function StripHTML($s_str,$s_line_feed = "\n")
{
//
// strip HTML comments (s option means include new lines in matches)
//
$s_str = preg_replace('//s','',$s_str);
//
// strip any scripts (i option means case-insensitive)
//
$s_str = preg_replace('/