function modx_sanitize_gpc(&$target, $count = 0) { global $sanitize_seed; $brackets = array('[[', ']]', '[!', '!]', '[*', '*]', '[(', ')]', '{{', '}}', '[+', '+]', '[~', '~]', '[^', '^]'); foreach ($brackets as $bracket) { $r[] = $sanitize_seed . $bracket['0'] . $sanitize_seed . $bracket['1'] . $sanitize_seed; } foreach ($target as $key => $value) { if (is_array($value)) { $count++; if (10 < $count) { echo 'GPC Array nested too deep!'; exit; } modx_sanitize_gpc($value, $count); $count--; } else { $value = str_replace($brackets, $r, $value); $value = preg_replace('/<script/i', 'sanitized_by_modx<s cript', $value); $value = preg_replace('/&#(\\d+);/', 'sanitized_by_modx& #$1', $value); $target[$key] = $value; } } return $target; }
function modx_sanitize_gpc(&$target, $count = 0) { global $sanitize_seed; $sanitize_seed = 'sanitize_seed_' . base_convert(md5(__FILE__), 16, 36); $s = array('[[', ']]', '[!', '!]', '[*', '*]', '[(', ')]', '{{', '}}', '[+', '+]', '[~', '~]', '[^', '^]'); foreach ($s as $_) { $r[] = $sanitize_seed . $_['0'] . $sanitize_seed . $_['1'] . $sanitize_seed; } foreach ($target as $key => $value) { if (is_array($value)) { $count++; if (10 < $count) { echo 'too many nested array'; exit; } modx_sanitize_gpc($value, $count); } else { $value = str_replace($s, $r, $value); $value = preg_replace('/<script/i', 'sanitized_by_modx<s cript', $value); $value = preg_replace('/&#(\\d+);/', 'sanitized_by_modx& #$1', $value); $target[$key] = $value; } $count = 0; } return $target; }
function modx_sanitize_gpc(&$target, $modxtags, $limit = 3) { foreach ($target as $key => $value) { if (is_array($value) && $limit > 0) { modx_sanitize_gpc($value, $modxtags, $limit - 1); } else { $target[$key] = preg_replace($modxtags, "", $value); } } return $target; }
function eForm($modx, $params) { global $_lang; global $debugText; global $formats, $fields, $efPostBack; $fields = array(); //reset fields array - needed in case of multiple forms // define some variables used as array index $_dfnMaxlength = 6; extract($params, EXTR_SKIP); // extract params into variables #include default language file include_once $snipPath . "lang/english.inc.php"; #include other language file if set. $form_language = isset($language) ? $language : $modx->config['manager_language']; if ($form_language != "english" && $form_language != '') { if (file_exists("{$snipPath}lang/{$form_language}.inc.php")) { include_once "{$snipPath}lang/{$form_language}.inc.php"; } else { if ($isDebug) { $debugText .= "<strong>Language file '{$form_language}.inc.php' not found!</strong><br />"; } } //always in english! } # add debug warning - moved again... if ($isDebug) { $debugText .= $_lang['ef_debug_warning']; } # check for valid form key - moved to below fetching form template to allow id coming from form template $nomail = $noemail; //adjust variable name confusion # activate nomail if missing $to if (!$to) { $nomail = 1; } # load templates if ($tpl == $modx->documentIdentifier) { return $_lang['ef_is_own_id'] . "'{$tpl}'"; } //required if (empty($tpl)) { $formid = "eform"; $tpl = get_default_tpl(); } elseif ($tmp = efLoadTemplate($tpl)) { $tpl = $tmp; } else { return $_lang['ef_no_doc'] . " '{$tpl}'"; } # check for valid form key if ($formid == '') { $formid = 'eform'; } // try to get formid from <form> tag id preg_match('/<form[^>]*?id=[\'"]([^\'"]*?)[\'"]/i', $tpl, $matches); $form_id = isset($matches[1]) ? $matches[1] : ''; //check for <input type='hidden name='formid'...> if (!preg_match('/<input[^>]*?name=[\'"]formid[\'"]/i', $tpl)) { //insert hidden formid field $tpl = str_replace('</form>', "<input type=\"hidden\" name=\"formid\" value=\"{$formid}\" /></form>", $tpl); } $validFormId = isset($_POST['formid']) && $formid == $_POST['formid'] ? 1 : 0; # check if postback mode $efPostBack = $validFormId && count($_POST) > 0 ? true : false; //retain old variable? if ($efPostBack) { if (empty($report)) { $report = get_default_report(); } else { $report = ($tmp = efLoadTemplate($report)) !== false ? $tmp : $_lang['ef_no_doc'] . " '{$report}'"; } if ($thankyou) { $thankyou = ($tmp = efLoadTemplate($thankyou)) !== false ? $tmp : $_lang['ef_no_doc'] . " '{$thankyou}'"; } if ($autotext) { $autotext = ($tmp = efLoadTemplate($autotext)) !== false ? $tmp : $_lang['ef_no_doc'] . " '{$autotext}'"; } } //these will be added to the HEAD section of the document when the form is displayed! if ($cssStyle) { $cssStyle = strpos($cssStyle, ',') && strpos($cssStyle, '<style') === false ? explode(',', $cssStyle) : array($cssStyle); foreach ($cssStyle as $tmp) { $startupSource[] = array($tmp, 'css'); } } if ($jScript) { $jScript = strpos($jScript, ',') && strpos($jScript, '<script') === false ? explode(',', $jScript) : array($jScript); foreach ($jScript as $tmp) { $startupSource[] = array($tmp, 'javascript'); } } #New in 1.4.4 - run snippet to include 'event' functions if (strlen($runSnippet) > 0) { $modx->runSnippet($runSnippet, array('formid' => $formid)); //Sadly we cannot know if the snippet fails or if it exists as modx->runsnippet's return value //is ambiguous } # invoke onBeforeFormParse event set by another script if ($eFormOnBeforeFormParse) { if ($isDebug && !function_exists($eFormOnBeforeFormParse)) { $fields['debug'] .= "eFormOnBeforeFormParse event: Could not find the function " . $eFormOnBeforeFormParse; } else { $templates = array('tpl' => $tpl, 'report' => $report, 'thankyou' => $thankyou, 'autotext' => $autotext); if ($eFormOnBeforeFormParse($fields, $templates) === false) { return ""; } elseif (is_array($templates)) { extract($templates); } // extract back into original variables } } # parse form for formats and generate placeholders $tpl = eFormParseTemplate($tpl, $isDebug); if ($efPostBack) { foreach ($formats as $k => $discard) { if (!isset($fields[$k])) { $fields[$k] = ""; } } // store dummy value inside $fields $disclaimer = ($tmp = efLoadTemplate($disclaimer)) !== false ? $tmp : ''; //error message containers $vMsg = $rMsg = $rClass = array(); # get user post back data foreach ($_POST as $name => $value) { if (is_array($value)) { //remove empty values $fields[$name] = array_filter($value, create_function('$v', 'return (!empty($v));')); } else { $value = htmlspecialchars($value, ENT_QUOTES, $modx->config['modx_charset']); if ($allowhtml || $formats[$name][2] == 'html') { $fields[$name] = stripslashes($value); } else { $fields[$name] = strip_tags(stripslashes($value)); } } } # get uploaded files foreach ($_FILES as $name => $value) { $fields[$name] = $value; } # check vericode if ($vericode) { //add support for captcha code - thanks to Djamoer $code = $_SESSION['veriword'] ? $_SESSION['veriword'] : $_SESSION['eForm.VeriCode']; if ($fields['vericode'] != $code) { $vMsg[count($vMsg)] = $_lang['ef_failed_vericode']; $rClass['vericode'] = $invalidClass; //added in 1.4.4 } } # sanitize the values with slashes stripped to avoid remote execution of Snippets modx_sanitize_gpc($fields); # validate fields foreach ($fields as $name => $value) { $fld = isset($formats[$name]) ? $formats[$name] : ''; if ($fld) { $desc = $fld[1]; $datatype = $fld[2]; $isRequired = $fld[3]; if ($isRequired == 1 && $value == "" && $datatype != "file") { $rMsg[count($rMsg)] = "{$desc}"; $rClass[$name] = $requiredClass; } elseif (!empty($fld[5]) && $value != "" && $datatype != "file") { $value = validateField($value, $fld, $vMsg, $isDebug); if ($value === false) { $rClass[$name] = $invalidClass; } elseif ($value !== true) { $fields[$name] = $value; } //replace value. } else { //value check switch ($datatype) { case "integer": case "float": if (strlen($value) > 0 && !is_numeric($value)) { $vMsg[count($vMsg)] = $desc . $_lang["ef_invalid_number"]; $rClass[$name] = $invalidClass; } break; case "date": if (strlen($value) == 0) { break; } //corrected by xwisdom for php version differences $rt = strtotime($value); //php 5.1.0+ returns false while < 5.1.0 returns -1 if ($rt === false || $rt === -1) { $vMsg[count($vMsg)] = $desc . $_lang["ef_invalid_date"]; $rClass[$name] = $invalidClass; } break; case "email": //stricter email validation - udated to allow + in local name part if (strlen($value) > 0 && !preg_match('/^(?:[a-z0-9+_-]+?\\.)*?[a-z0-9_+-]+?@(?:[a-z0-9_-]+?\\.)*?[a-z0-9_-]+?\\.[a-z0-9]{2,5}$/i', $value)) { $vMsg[count($vMsg)] = isset($formats[$name][4]) ? $formats[$name][4] : $desc . $_lang["ef_invalid_email"]; $rClass[$name] = $invalidClass; } break; case "file": if ($_FILES[$name]['error'] == 1 || $_FILES[$name]['error'] == 2) { $vMsg[count($vMsg)] = $desc . $_lang['ef_upload_exceeded']; $rClass[$name] = $invalidClass; } elseif ($isRequired == 1 && ($_FILES[$name] && $_FILES[$name]['type'] == '')) { $rMsg[count($rMsg)] = $desc; $rClass[$name] = $requiredClass; } elseif ($_FILES[$name]['tmp_name']) { if (substr($fld[5], 0, 5) != "#LIST" || validateField($_FILES[$name]['name'], $fld, $vMsg, $isDebug)) { $attachments[count($attachments)] = $_FILES[$name]['tmp_name']; } else { $rClass[$name] = $invalidClass; } } break; case "html": case "checkbox": case "string": default: break; } } //end required test } } // Changed in 1.4.4.5 - now expects 4 parameters if ($eFormOnValidate) { if ($isDebug && !function_exists($eFormOnValidate)) { $fields['debug'] .= "eformOnValidate event: Could not find the function " . $eFormOnValidate; } else { if ($eFormOnValidate($fields, $vMsg, $rMsg, $rClass) === false) { return; } } } if (count($vMsg) > 0 || count($rMsg) > 0) { //New in 1.4.2 - classes are set in labels and form elements for invalid fields foreach ($rClass as $n => $class) { $fields[$n . '_class'] = $fields[$n . '_class'] ? $fields[$n . '_class'] . ' ' . $class : $class; $fields[$n . '_vClass'] = isset($fields[$n . '_vClass']) ? $fields[$n . '_vClass'] . ' ' . $class : $class; //work around for checkboxes if (isset($formats[$n][6])) { //have separate id's for check and option tags - set classes as well foreach (explode(',', $formats[$n][6]) as $id) { $fields[$id . '_vClass'] = $fields[$id . '_vClass'] ? $fields[$id . '_vClass'] . ' ' . $class : $class; } } } //add debugging info to fields array if ($isDebug) { ksort($fields); if ($isDebug > 1) { $debugText .= "<br /><strong>Formats array:</strong><pre>" . var_export($formats, true) . '</pre>'; $debugText .= "<br /><strong>Fields array:</strong><pre>" . var_export($fields, true) . '</pre>'; $debugText .= "<br /><strong>Classes parsed :</strong><pre>" . var_export($rClass, true) . "</pre>"; } $debugText .= "<br /><strong>eForm configuration:</strong><pre>\n" . var_export($params, true) . '</pre>'; $fields['debug'] = $debugText; } #set validation message $tmp = count($rMsg) > 0 ? str_replace("{fields}", implode(", ", $rMsg), $_lang['ef_required_message']) : ""; $tmp .= implode("<br />", $vMsg); if (!strstr($tpl, '[+validationmessage+]')) { $modx->setPlaceholder('validationmessage', str_replace('[+ef_wrapper+]', $tmp, $_lang['ef_validation_message'])); } else { if (!isset($fields['validationmessage'])) { $fields['validationmessage'] = ''; } $fields['validationmessage'] .= str_replace('[+ef_wrapper+]', $tmp, $_lang['ef_validation_message']); } } else { # format report fields foreach ($fields as $name => $value) { $fld = $formats[$name]; if ($fld) { $datatype = $fld[2]; switch ($datatype) { case "integer": $value = number_format($value); break; case "float": $localeInfo = localeconv(); $th_sep = empty($_lang['ef_thousands_separator']) ? $localeInfo['thousands_sep'] : $_lang['ef_thousands_separator']; $dec_point = $localeInfo['decimal_point']; $debugText .= 'Locale<pre>' . var_export($localeInfo, true) . '</pre>'; $value = number_format($value, 2, $dec_point, $th_sep); break; case "date": $format_string = isset($_lang['ef_date_format']) ? $_lang['ef_date_format'] : '%d-%b-%Y %H:%M:%S'; $value = $value ? strftime($format_string, strtotime($value)) : ""; $value = str_replace("00:00:00", "", $value); // remove trailing zero time values break; case "html": // convert \n to <br /> if (!$sendAsText) { $value = preg_replace('#(\\n<br[ /]*?>|<br[ /]*?>\\n|\\n)#i', '<br />', $value); } break; case "file": // set file name if ($value['type'] != "" && $value['type'] != "") { $value = $value["name"]; $patharray = explode(strpos($value, "/") === false ? "\\" : "/", $value); $value = $patharray[count($patharray) - 1]; } else { $value = ""; } break; } $fields[$name] = $value; } } # set postdate $fields['postdate'] = strftime($modx->toDateFormat(null, 'formatOnly') . " %H:%M:%S", time()); //check against email injection and replace suspect content if (hasMailHeaders($fields)) { //send email to webmaster?? if ($reportAbuse) { //set in snippet configuration tab $body = $_lang['ef_mail_abuse_message']; $body .= "<table>"; foreach ($fields as $key => $value) { $body .= "<tr><td>{$key}</td><td><pre>{$value}</pre></td></tr>"; } $body .= "</table>"; include_once $modx->config['base_path'] . 'manager/includes/controls/modxmailer.inc.php'; $mail = new MODxMailer(); # send abuse alert $mail->IsHTML($isHtml); $mail->From = $modx->config['emailsender']; $mail->FromName = $modx->config['site_name']; $mail->Subject = $_lang['ef_mail_abuse_subject']; $mail->Body = $body; AddAddressToMailer($mail, "to", $modx->config['emailsender']); $mail->Send(); //ignore mail errors in this case } //return empty form with error message //register css and/or javascript if (isset($startupSource)) { efRegisterStartupBlock($startupSource); } return formMerge($tpl, array('validationmessage' => $_lang['ef_mail_abuse_error'])); } # added in 1.4.2 - Limit the time between form submissions if ($submitLimit > 0) { if (time() < $submitLimit + $_SESSION[$formid . '_limit']) { return formMerge($_lang['ef_submit_time_limit'], $fields); } else { unset($_SESSION[$formid . '_limit'], $_SESSION[$formid . '_hash']); } //time expired } # invoke OnBeforeMailSent event set by another script if ($eFormOnBeforeMailSent) { if ($isDebug && !function_exists($eFormOnBeforeMailSent)) { $fields['debug'] .= "eFormOnBeforeMailSent event: Could not find the function " . $eFormOnBeforeMailSent; } elseif ($eFormOnBeforeMailSent($fields) === false) { if (isset($fields['validationmessage']) && !empty($fields['validationmessage'])) { //register css and/or javascript if (isset($startupSource)) { efRegisterStartupBlock($startupSource); } return formMerge($tpl, $fields); } else { return; } } } if ($protectSubmit) { $hash = ''; # create a hash of key data if (!is_numeric($protectSubmit)) { //supplied field names $protectSubmit = strpos($protectSubmit, ',') ? explode(',', $protectSubmit) : array($protectSubmit); foreach ($protectSubmit as $fld) { $hash .= isset($fields[$fld]) ? $fields[$fld] : ''; } } else { foreach ($formats as $fld) { $hash .= $fld[3] == 1 ? $fields[$fld[0]] : ''; } } if ($hash) { $hash = md5($hash); } if ($isDebug) { $debugText .= "<strong>SESSION HASH</strong>:" . $_SESSION[$formid . '_hash'] . "<br />" . "<b>FORM HASH</b>:" . $hash . "<br />"; } # check if already succesfully submitted with same data if (isset($_SESSION[$formid . '_hash']) && $_SESSION[$formid . '_hash'] == $hash && $hash != '') { return formMerge($_lang['ef_multiple_submit'], $fields); } } $fields['disclaimer'] = $disclaimer ? formMerge($disclaimer, $fields) : ""; $from = $from ? formMerge($from, $fields) : ""; $fromname = $from ? formMerge($fromname, $fields) : ""; if (isset($fields['subject'])) { $subject = $fields['subject']; } else { $subject = $subject ? formMerge($subject, $fields) : "from {$fromname}"; } $fields['subject'] = $subject; //make subject available in report & thank you page $report = $report ? formMerge($report, $fields) : ""; $keywords = $keywords ? formMerge($keywords, $fields) : ""; $to = formMerge($to, $fields); if (empty($to) || !strpos($to, '@')) { $nomail = 1; } if (!$nomail) { # check for mail selector field - select an email from to list if ($mselector && $fields[$mselector]) { $i = (int) $fields[$mselector]; $ar = explode(",", $to); if ($i > 0) { $i--; } if ($ar[$i]) { $to = $ar[$i]; } else { $to = $ar[0]; } } //set reply-to address //$replyto snippet parameter must contain email or fieldname if (!strstr($replyto, '@')) { $replyto = $fields[$replyto] && strstr($fields[$replyto], '@') ? $fields[$replyto] : $from; } # include PHP Mailer include_once $modx->config['base_path'] . 'manager/includes/controls/modxmailer.inc.php'; $mail = new MODxMailer(); # send form //defaults to html so only test sendasText $isHtml = $sendAsText == 1 || strstr($sendAsText, 'report') ? false : true; if (!$noemail) { if ($sendirect) { $to = $fields['email']; } $mail = new MODxMailer(); $mail->IsHTML($isHtml); $mail->From = $from; $mail->FromName = $fromname; $mail->Subject = $subject; $mail->Body = $report; AddAddressToMailer($mail, "replyto", $replyto); AddAddressToMailer($mail, "to", $to); AddAddressToMailer($mail, "cc", $cc); AddAddressToMailer($mail, "bcc", $bcc); AttachFilesToMailer($mail, $attachments); if (!$mail->Send()) { return 'Main mail: ' . $_lang['ef_mail_error'] . $mail->ErrorInfo; } } # send user a copy of the report if ($ccsender && $fields['email']) { $mail = new MODxMailer(); $mail->IsHTML($isHtml); $mail->From = $from; $mail->FromName = $fromname; $mail->Subject = $subject; $mail->Body = $report; AddAddressToMailer($mail, 'to', $fields['email']); AttachFilesToMailer($mail, $attachments); if (!$mail->Send()) { return 'CCSender: ' . $_lang['ef_mail_error'] . $mail->ErrorInfo; } } # send auto-respond email //defaults to html so only test sendasText $isHtml = $sendAsText == 1 || strstr($sendAsText, 'autotext') ? false : true; if ($autotext && $fields['email'] != '') { $autotext = formMerge($autotext, $fields); $mail = new MODxMailer(); $mail->IsHTML($isHtml); $mail->From = $autosender ? $autosender : $from; $mail->FromName = $autoSenderName ? $autoSenderName : $fromname; $mail->Subject = $subject; $mail->Body = $autotext; AddAddressToMailer($mail, 'to', $fields['email']); if (!$mail->Send()) { return 'AutoText: ' . $_lang['ef_mail_error'] . $mail->ErrorInfo; } } //defaults to text - test for sendAsHtml $isHTML = $sendAsHTML == 1 || strstr($sendAsHtml, 'mobile') ? true : false; # send mobile email if ($mobile && $mobiletext) { $mobiletext = formMerge($mobiletext, $fields); $mail = new MODxMailer(); $mail->IsHTML($isHtml); $mail->From = $from; $mail->FromName = $fromname; $mail->Subject = $subject; $mail->Body = $mobiletext; AddAddressToMailer($mail, 'to', $mobile); $mail->Send(); } } //end test nomail # added in 1.4.2 - Protection against multiple submit with same form data if ($protectSubmit) { $_SESSION[$formid . '_hash'] = $hash; } //hash is set earlier # added in 1.4.2 - Limit the time between form submissions if ($submitLimit > 0) { $_SESSION[$formid . '_limit'] = time(); } # invoke OnMailSent event set by another script if ($eFormOnMailSent) { if ($isDebug && !function_exists($eFormOnMailSent)) { $fields['debug'] .= "eFormOnMailSent event: Could not find the function" . $eFormOnMailSent; } else { if ($eFormOnMailSent($fields) === false) { return; } } } if ($isDebug) { $debugText .= "<strong>Mail Headers:</strong><br />From: {$from} ({$fromname})<br />Reply-to:{$replyto}<br />To: {$to}<br />Subject: {$subject}<br />CC: {$cc}<br /> BCC:{$bcc}<br />"; if ($isDebug > 1) { $debugText .= "<br /><strong>Formats array:</strong><pre>" . var_export($formats, true) . '</pre>'; $debugText .= "<br /><strong>Fields array:</strong><pre>" . var_export($fields, true) . '</pre>'; } $fields['debug'] = $debugText; } # show or redirect to thank you page if ($gid == $modx->documentIdentifier) { if (!empty($thankyou)) { if ($isDebug && !strstr($thankyou, '[+debug+]')) { $thankyou .= '[+debug+]'; } if (isset($startupSource)) { efRegisterStartupBlock($startupSource, true); } //skip scripts if ($sendAsText) { foreach ($formats as $key => $fmt) { if ($fmt[2] == 'html') { $fields[$key] = str_replace("\n", '<br />', $fields[$key]); } } } $thankyou = formMerge($thankyou, $fields); return $thankyou; } else { return $_lang['ef_thankyou_message']; } } else { $url = $modx->makeURL($gid); $modx->sendRedirect($url); } return; // stop here } } else { //not postback //add debugging info to fields array if ($isDebug) { $debugText .= "<br /><strong>eForm configuration:</strong><pre>" . var_export($params, true) . '</pre>'; $fields['debug'] = $debugText; } //strip the eform attribute $regExpr = "#eform=([\"'])[^\\1]*?\\1#si"; $tpl = preg_replace($regExpr, '', $tpl); } // set vericode if ($vericode) { $_SESSION['eForm.VeriCode'] = $fields['vericode'] = substr(uniqid(''), -5); $fields['verimageurl'] = $modx->config['base_url'] . 'captcha.php?rand=' . mt_rand(); } # get SESSION data - thanks to sottwell if ($sessionVars) { $sessionVars = strpos($sessionVars, ',', 0) ? explode(',', $sessionVars) : array($sessionVars); foreach ($sessionVars as $varName) { if (empty($varName)) { continue; } $varName = trim($varName); if (isset($_SESSION[$varName]) && !empty($_SESSION[$varName])) { $fields[$varName] = isset($fields[$varName]) && $postOverides ? $fields[$varName] : $_SESSION[$varName]; } } } # invoke OnBeforeFormMerge event set by another script if ($eFormOnBeforeFormMerge) { if ($isDebug && !function_exists($eFormOnBeforeFormMerge)) { $fields['debug'] .= "eFormOnBeforeFormMerge event: Could not find the function " . $eFormOnBeforeFormMerge; } else { if ($eFormOnBeforeFormMerge($fields) === false) { return; } } } # build form if ($isDebug && !$fields['debug']) { $fields['debug'] = $debugText; } if ($isDebug && !strstr($tpl, '[+debug+]')) { $tpl .= '[+debug+]'; } //register css and/or javascript if (isset($startupSource)) { efRegisterStartupBlock($startupSource); } return formMerge($tpl, $fields); }