PageRenderTime 64ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/assets/snippets/eform/eform.inc.php

https://github.com/garryn/evolution
PHP | 1119 lines | 819 code | 131 blank | 169 comment | 234 complexity | aa3b2a3dc903dd0337ae502785460b9e MD5 | raw file
  1. <?php
  2. # eForm 1.4.4.6 - Electronic Form Snippet
  3. # Original created by: Raymond Irving 15-Dec-2004.
  4. # Extended by: Jelle Jager (TobyL) September 2006
  5. # -----------------------------------------------------
  6. #
  7. #
  8. # Captcha image support - thanks to Djamoer
  9. # Multi checkbox, radio, select support - thanks to Djamoer
  10. # Form Parser and extended validation - by Jelle Jager
  11. #
  12. # see docs/eform.htm for installation and usage information
  13. #
  14. # VERSION HISTORY
  15. # Work around for setting required class on check & radio labels
  16. # fixed bug: If eform attibute is set on multiple check boxes only the last
  17. # value is set in values list
  18. # For a full version history see the eform_history.htm file in the docs directory
  19. #
  20. # Some more fixes and problems:
  21. # FIXED: reg expression failed for select and textarea boxes which have regex special
  22. # characters in their name attribute. eg name="multipleSelection[]"
  23. # FIXED: validation of multiple values with #LIST & #SELECT stopped after 1st value
  24. # Caused by repeating $v variable naming (overwriting $v array)
  25. # e.g.
  26. # <select name="multipleSelection[]" multiple="multiple" eform="::1::"/>
  27. # <option value="1">1</option>
  28. # <option value="2">2</option>
  29. # <option value="3">3</option>
  30. # </select>
  31. # would only have the first selected value validated!
  32. #
  33. # bugfix: &jScript parameter doesn't accept chunks, only a link to a JS file if more than one chunk is declared (eg &jScript=`chunk1,chunk2)
  34. # bugfix: &protectSubmit creates hash for all fields instead of fields declared in &protectSubmit
  35. # bugfix: Auto respond email didn't honour the &sendAsText parameter
  36. # bugfix: The #FUNCTION validation rule for select boxes never calls the function
  37. # bugfix: Validation css class isn't being added to labels.
  38. ##
  39. $GLOBALS['optionsName'] = "eform"; //name of pseudo attribute used for format settings
  40. $GLOBALS['efPostBack'] = false;
  41. function eForm($modx,$params) {
  42. global $_lang;
  43. global $debugText;
  44. global $formats,$fields,$efPostBack;
  45. $fields = array(); //reset fields array - needed in case of multiple forms
  46. // define some variables used as array index
  47. $_dfnMaxlength = 6;
  48. extract($params,EXTR_SKIP); // extract params into variables
  49. $fileVersion = '1.4.4';
  50. $version = isset($version)?$version:'prior to 1.4.2';
  51. #include default language file
  52. include_once($snipPath."lang/english.inc.php");
  53. #include other language file if set.
  54. $form_language = isset($language)?$language:$modx->config['manager_language'];
  55. if($form_language!="english" && $form_language!='') {
  56. if(file_exists($snipPath ."lang/".$form_language.".inc.php"))
  57. include_once $snipPath ."lang/".$form_language.".inc.php";
  58. else
  59. if( $isDebug ) $debugText .= "<strong>Language file '$form_language.inc.php' not found!</strong><br />"; //always in english!
  60. }
  61. # add debug warning - moved again...
  62. if( $isDebug ) $debugText .= $_lang['ef_debug_warning'];
  63. //check version differences
  64. if( $version != $fileVersion )
  65. return $_lang['ef_version_error'];
  66. # check for valid form key - moved to below fetching form template to allow id coming from form template
  67. $nomail = $noemail; //adjust variable name confusion
  68. # activate nomail if missing $to
  69. if (!$to) $nomail = 1;
  70. # load templates
  71. if($tpl==$modx->documentIdentifier) return $_lang['ef_is_own_id']."'$tpl'";
  72. //required
  73. if( $tmp=efLoadTemplate($tpl) ) $tpl=$tmp; else return $_lang['ef_no_doc'] . " '$tpl'";
  74. # check for valid form key
  75. if ($formid=="") return $_lang['ef_error_formid'];
  76. // try to get formid from <form> tag id
  77. preg_match('/<form[^>]*?id=[\'"]([^\'"]*?)[\'"]/i',$tpl,$matches);
  78. $form_id = isset($matches[1])?$matches[1]:'';
  79. //check for <input type='hidden name='formid'...>
  80. if( !preg_match('/<input[^>]*?name=[\'"]formid[\'"]/i',$tpl) ){
  81. //insert hidden formid field
  82. $tpl = str_replace('</form>',"<input type=\"hidden\" name=\"formid\" value=\"$form_id\" /></form>",$tpl);
  83. }
  84. $validFormId = ($formid==$_POST['formid'])?1:0;
  85. # check if postback mode
  86. $efPostBack = ($validFormId && count($_POST)>0)? true:false; //retain old variable?
  87. if($efPostBack){
  88. $report = (($tmp=efLoadTemplate($report))!==false)?$tmp:$_lang['ef_no_doc'] . " '$report'";
  89. if($thankyou) $thankyou = (($tmp=efLoadTemplate($thankyou))!==false )?$tmp:$_lang['ef_no_doc'] . " '$thankyou'";
  90. if($autotext) $autotext = (($tmp=efLoadTemplate($autotext))!==false )?$tmp:$_lang['ef_no_doc'] . " '$autotext'";
  91. }
  92. //these will be added to the HEAD section of the document when the form is displayed!
  93. if($cssStyle){
  94. $cssStyle = ( strpos($cssStyle,',') && strpos($cssStyle,'<style')===false ) ? explode(',',$cssStyle) : array($cssStyle);
  95. foreach( $cssStyle as $tmp ) $startupSource[]= array($tmp,'css');
  96. }
  97. if($jScript){
  98. $jScript = ( strpos($jScript,',') && strpos($jScript,'<script')===false ) ? explode(',',$jScript) : array($jScript);
  99. foreach( $jScript as $tmp )
  100. $startupSource[]= array($tmp,'javascript');
  101. }
  102. #New in 1.4.4 - run snippet to include 'event' functions
  103. if( strlen($runSnippet)>0 ){
  104. $modx->runSnippet($runSnippet, array('formid'=>$formid));
  105. //Sadly we cannot know if the snippet fails or if it exists as modx->runsnippet's return value
  106. //is ambiguous
  107. }
  108. # invoke onBeforeFormParse event set by another script
  109. if ($eFormOnBeforeFormParse) {
  110. if( $isDebug && !function_exists($eFormOnBeforeFormParse))
  111. $fields['debug'] .= "eFormOnBeforeFormParse event: Could not find the function " . $eFormOnBeforeFormParse;
  112. else{
  113. $templates = array('tpl'=>$tpl,'report'=>$report,'thankyou'=>$thankyou,'autotext'=>$autotext);
  114. if( $eFormOnBeforeFormParse($fields,$templates)===false )
  115. return "";
  116. elseif(is_array($templates))
  117. extract($templates); // extract back into original variables
  118. }
  119. }
  120. # parse form for formats and generate placeholders
  121. $tpl = eFormParseTemplate($tpl,$isDebug);
  122. if ($efPostBack) {
  123. foreach($formats as $k => $discard)
  124. if(!isset($fields[$k])) $fields[$k] = ""; // store dummy value inside $fields
  125. $disclaimer = (($tmp=efLoadTemplate($disclaimer))!==false )? $tmp:'';
  126. //error message containers
  127. $vMsg = $rMsg = $rClass = array();
  128. # get user post back data
  129. foreach($_POST as $name => $value){
  130. if(is_array($value)){
  131. //remove empty values
  132. $fields[$name] = array_filter($value,create_function('$v','return (!empty($v));'));
  133. } else
  134. $fields[$name] = stripslashes(($allowhtml || $formats[$name][2]=='html')? $value:$modx->stripTags($value));
  135. }
  136. # get uploaded files
  137. foreach($_FILES as $name => $value){
  138. $fields[$name] = $value;
  139. }
  140. # check vericode
  141. if($vericode) {
  142. //add support for captcha code - thanks to Djamoer
  143. $code = $_SESSION['veriword'] ? $_SESSION['veriword'] : $_SESSION['eForm.VeriCode'];
  144. if($fields['vericode']!=$code) {
  145. $vMsg[count($vMsg)]=$_lang['ef_failed_vericode'];
  146. $rClass['vericode']=$invalidClass; //added in 1.4.4
  147. }
  148. }
  149. # validate fields
  150. foreach($fields as $name => $value) {
  151. $fld = $formats[$name];
  152. if ($fld) {
  153. $desc = $fld[1];
  154. $datatype = $fld[2];
  155. $isRequired = $fld[3];
  156. if ($isRequired==1 && $value=="" && $datatype!="file"){
  157. $rMsg[count($rMsg)]="$desc";
  158. $rClass[$name]=$requiredClass;
  159. }elseif( !empty($fld[5]) && $value!="" && $datatype!="file" ) {
  160. $value = validateField($value,$fld,$vMsg,$isDebug);
  161. if($value===false) $rClass[$name]=$invalidClass;
  162. //if returned value is not of type boolean replace value...
  163. elseif($value!==true) $fields[$name]=$value; //replace value.
  164. }else{ //value check
  165. switch ($datatype){
  166. case "integer":
  167. case "float":
  168. if (strlen($value)>0 && !is_numeric($value)){
  169. $vMsg[count($vMsg)]=$desc . $_lang["ef_invalid_number"];
  170. $rClass[$name]=$invalidClass;
  171. }
  172. break;
  173. case "date":
  174. if(strlen($value)==0) break;
  175. //corrected by xwisdom for php version differences
  176. $rt = strtotime($value); //php 5.1.0+ returns false while < 5.1.0 returns -1
  177. if ($rt===false||$rt===-1){
  178. $vMsg[count($vMsg)]=$desc . $_lang["ef_invalid_date"];
  179. $rClass[$name]=$invalidClass;
  180. }
  181. break;
  182. case "email":
  183. //stricter email validation - udated to allow + in local name part
  184. if (strlen($value)>0 && !preg_match(
  185. '/^(?:[a-z0-9+_-]+?\.)*?[a-z0-9_+-]+?@(?:[a-z0-9_-]+?\.)*?[a-z0-9_-]+?\.[a-z0-9]{2,5}$/i', $value) ){
  186. $vMsg[count($vMsg)] = isset($formats[$name][4]) ? $formats[$name][4] : $desc . $_lang["ef_invalid_email"];
  187. $rClass[$name]=$invalidClass;
  188. }
  189. break;
  190. case "file":
  191. if ($_FILES[$name]['error']==1 || $_FILES[$name]['error']==2){
  192. $vMsg[count($vMsg)]=$desc . $_lang['ef_upload_exceeded'];
  193. $rClass[$name]=$invalidClass;
  194. }elseif ($isRequired==1 && ($_FILES[$name] && $_FILES[$name]['type']=='')){
  195. $rMsg[count($rMsg)]=$desc;
  196. $rClass[$name]=$requiredClass;
  197. }elseif ($_FILES[$name]['tmp_name']){
  198. if( substr($fld[5],0,5)!="#LIST" || validateField($_FILES[$name]['name'],$fld,$vMsg,$isDebug) )
  199. $attachments[count($attachments)] = $_FILES[$name]['tmp_name'];
  200. else $rClass[$name]=$invalidClass;
  201. }
  202. break;
  203. case "html":
  204. case "checkbox":
  205. case "string":
  206. default:
  207. break;
  208. }
  209. }//end required test
  210. }
  211. }
  212. // Changed in 1.4.4.5 - now expects 4 parameters
  213. if ($eFormOnValidate) {
  214. if( $isDebug && !function_exists($eFormOnValidate))
  215. $fields['debug'] .= "eformOnValidate event: Could not find the function " . $eFormOnValidate;
  216. else
  217. if ($eFormOnValidate($fields,$vMsg,$rMsg,$rClass)===false) return;
  218. }
  219. if(count($vMsg)>0 || count($rMsg)>0){
  220. //New in 1.4.2 - classes are set in labels and form elements for invalid fields
  221. foreach($rClass as $n => $class){
  222. $fields[$n.'_class'] = $fields[$n.'_class']?$fields[$n.'_class'].' '. $class:$class;
  223. $fields[$n.'_vClass'] = $fields[$n.'_vClass']?$fields[$n.'_vClass'].' '. $class:$class;
  224. //work around for checkboxes
  225. if( isset($formats[$n][6] )){ //have separate id's for check and option tags - set classes as well
  226. foreach( explode(',',$formats[$n][6]) as $id)
  227. $fields[$id.'_vClass'] = $fields[$id.'_vClass'] ? $fields[$id.'_vClass'].' '. $class : $class;
  228. }
  229. }
  230. //add debugging info to fields array
  231. if($isDebug){
  232. ksort($fields);
  233. if($isDebug>1){
  234. $debugText .= "<br /><strong>Formats array:</strong><pre>". var_export($formats,true).'</pre>';
  235. $debugText .= "<br /><strong>Fields array:</strong><pre>". var_export($fields,true).'</pre>';
  236. $debugText .= "<br /><strong>Classes parsed :</strong><pre>" . var_export($rClass,true) ."</pre>";
  237. }
  238. $debugText .= "<br /><strong>eForm configuration:</strong><pre>\n". var_export($params,true).'</pre>';
  239. $fields['debug']=$debugText;
  240. }
  241. #set validation message
  242. $tmp = (count($rMsg)>0)?str_replace("{fields}", implode(", ",$rMsg),$_lang['ef_required_message']):"";
  243. $tmp .= implode("<br />",$vMsg);
  244. if(!strstr($tpl,'[+validationmessage+]'))
  245. $modx->setPlaceholder('validationmessage',str_replace('[+ef_wrapper+]', $tmp, $_lang['ef_validation_message']));
  246. else
  247. $fields['validationmessage'] .= str_replace('[+ef_wrapper+]', $tmp, $_lang['ef_validation_message']);
  248. } else {
  249. # format report fields
  250. foreach($fields as $name => $value) {
  251. $fld = $formats[$name];
  252. if ($fld) {
  253. $datatype = $fld[2];
  254. switch ($datatype) {
  255. case "integer":
  256. $value = number_format($value);
  257. break;
  258. case "float":
  259. $localeInfo = localeconv();
  260. $th_sep = empty($_lang['ef_thousands_separator'])?$localeInfo['thousands_sep']:$_lang['ef_thousands_separator'];
  261. $dec_point= $localeInfo['decimal_point'];
  262. $debugText .= 'Locale<pre>'.var_export($localeInfo,true).'</pre>';
  263. $value = number_format($value, 2, $dec_point, $th_sep);
  264. break;
  265. case "date":
  266. $format_string = isset($_lang['ef_date_format']) ? $_lang['ef_date_format'] : '%d-%b-%Y %H:%M:%S';
  267. $value = ($value)? strftime($format_string,strtotime($value)):"";
  268. $value=str_replace("00:00:00","",$value);// remove trailing zero time values
  269. break;
  270. case "html":
  271. // convert \n to <br />
  272. if(!$sendAsText ) $value = preg_replace('#(\n<br[ /]*?>|<br[ /]*?>\n|\n)#i','<br />',$value);
  273. break;
  274. case "file":
  275. // set file name
  276. if($value['type']!="" && $value['type']!=""){
  277. $value = $value["name"];
  278. $patharray = explode(((strpos($value,"/")===false)? "\\":"/"), $value);
  279. $value = $patharray[count($patharray)-1];
  280. }
  281. else {
  282. $value = "";
  283. }
  284. break;
  285. }
  286. $fields[$name] = $value;
  287. }
  288. }
  289. # set postdate
  290. $fields['postdate'] = strftime("%d-%b-%Y %H:%M:%S",time());
  291. //check against email injection and replace suspect content
  292. if( hasMailHeaders($fields) ){
  293. //send email to webmaster??
  294. if ($reportAbuse){ //set in snippet configuration tab
  295. $body = $_lang['ef_mail_abuse_message'];
  296. $body .="<table>";
  297. foreach($fields as $key => $value)
  298. $body .= "<tr><td>$key</td><td><pre>$value</pre></td></tr>";
  299. $body .="</table>";
  300. include_once "manager/includes/controls/class.phpmailer.php";
  301. # send abuse alert
  302. $mail = new PHPMailer();
  303. $mail->IsMail();
  304. $mail->IsHTML($isHtml);
  305. $mail->From = $modx->config['emailsender'];
  306. $mail->FromName = $modx->config['site_name'];
  307. $mail->Subject = $_lang['ef_mail_abuse_subject'];
  308. $mail->Body = $body;
  309. AddAddressToMailer($mail,"to",$modx->config['emailsender']);
  310. $mail->send(); //ignore mail errors in this case
  311. }
  312. //return empty form with error message
  313. //register css and/or javascript
  314. if( isset($startupSource) ) efRegisterStartupBlock($startupSource);
  315. return formMerge($tpl,array('validationmessage'=> $_lang['ef_mail_abuse_error']));
  316. }
  317. # added in 1.4.2 - Limit the time between form submissions
  318. if($submitLimit>0){
  319. if( time()<$submitLimit+$_SESSION[$formid.'_limit'] ){
  320. return formMerge($_lang['ef_submit_time_limit'],$fields);
  321. }
  322. else unset($_SESSION[$formid.'_limit'], $_SESSION[$formid.'_hash']); //time expired
  323. }
  324. # invoke OnBeforeMailSent event set by another script
  325. if ($eFormOnBeforeMailSent) {
  326. if( $isDebug && !function_exists($eFormOnBeforeMailSent))
  327. $fields['debug'] .= "eFormOnBeforeMailSent event: Could not find the function " . $eFormOnBeforeMailSent;
  328. elseif ($eFormOnBeforeMailSent($fields)===false) {
  329. if( isset($fields['validationmessage']) && !empty($fields['validationmessage']) ){
  330. //register css and/or javascript
  331. if( isset($startupSource) ) efRegisterStartupBlock($startupSource);
  332. return formMerge($tpl,$fields);
  333. }
  334. else
  335. return;
  336. }
  337. }
  338. if( $protectSubmit ){
  339. $hash = '';
  340. # create a hash of key data
  341. if(!is_numeric($protectSubmit)){ //supplied field names
  342. $protectSubmit = (strpos($protectSubmit,','))? explode(',',$protectSubmit):array($protectSubmit);
  343. foreach($protectSubmit as $fld) $hash .= isset($fields[$fld]) ? $fields[$fld] : '';
  344. }else //all required fields
  345. foreach($formats as $fld) $hash .= ($fld[3]==1) ? $fields[$fld[0]] : '';
  346. if($hash) $hash = md5($hash);
  347. if( $isDebug ) $debugText .= "<strong>SESSION HASH</strong>:".$_SESSION[$formid.'_hash']."<br />"."<b>FORM HASH</b>:".$hash."<br />";
  348. # check if already succesfully submitted with same data
  349. if( isset($_SESSION[$formid.'_hash']) && $_SESSION[$formid.'_hash'] == $hash && $hash!='' )
  350. return formMerge($_lang['ef_multiple_submit'],$fields);
  351. }
  352. $fields['disclaimer'] = ($disclaimer)? formMerge($disclaimer,$fields):"";
  353. $subject = isset($fields['subject'])?$fields['subject']:(($subject)? formMerge($subject,$fields):$category);
  354. $fields['subject'] = $subject; //make subject available in report & thank you page
  355. $report = ($report)? formMerge($report,$fields):"";
  356. $keywords = ($keywords)? formMerge($keywords,$fields):"";
  357. $from = ($from)? formMerge($from,$fields):"";
  358. $fromname = ($from)? formMerge($fromname,$fields):"";
  359. $to = formMerge($to,$fields);
  360. if(empty($to) || !strpos($to,'@')) $nomail=1;
  361. if(!$nomail){
  362. # check for mail selector field - select an email from to list
  363. if ($mselector && $fields[$mselector]) {
  364. $i = (int)$fields[$mselector];
  365. $ar = explode(",",$to);
  366. if ($i>0) $i--;
  367. if ($ar[$i]) $to = $ar[$i];
  368. else $to = $ar[0];
  369. }
  370. //set reply-to address
  371. //$replyto snippet parameter must contain email or fieldname
  372. if(!strstr($replyto,'@'))
  373. $replyto = ( $fields[$replyto] && strstr($fields[$replyto],'@') )?$fields[$replyto]:$from;
  374. # include PHP Mailer
  375. include_once "manager/includes/controls/class.phpmailer.php";
  376. # send form
  377. //defaults to html so only test sendasText
  378. $isHtml = ($sendAsText==1 || strstr($sendAsText,'report'))?false:true;
  379. if(!$noemail) {
  380. if($sendirect) $to = $fields['email'];
  381. $mail = new PHPMailer();
  382. $mail->IsMail();
  383. $mail->CharSet = $modx->config['modx_charset'];
  384. $mail->IsHTML($isHtml);
  385. $mail->From = $from;
  386. $mail->FromName = $fromname;
  387. $mail->Subject = $subject;
  388. $mail->Body = $report;
  389. AddAddressToMailer($mail,"replyto",$replyto);
  390. AddAddressToMailer($mail,"to",$to);
  391. AddAddressToMailer($mail,"cc",$cc);
  392. AddAddressToMailer($mail,"bcc",$bcc);
  393. AttachFilesToMailer($mail,$attachments);
  394. if(!$mail->send()) return 'Main mail: ' . $_lang['ef_mail_error'] . $mail->ErrorInfo;
  395. }
  396. # send user a copy of the report
  397. if($ccsender && $fields['email']) {
  398. $mail = new PHPMailer();
  399. $mail->IsMail();
  400. $mail->CharSet = $modx->config['modx_charset'];
  401. $mail->IsHTML($isHtml);
  402. $mail->From = $from;
  403. $mail->FromName = $fromname;
  404. $mail->Subject = $subject;
  405. $mail->Body = $report;
  406. AddAddressToMailer($mail,"to",$fields['email']);
  407. AttachFilesToMailer($mail,$attachments);
  408. if(!$mail->send()) return 'CCSender: ' . $_lang['ef_mail_error'] . $mail->ErrorInfo;
  409. }
  410. # send auto-respond email
  411. //defaults to html so only test sendasText
  412. $isHtml = ($sendAsText==1 || strstr($sendAsText,'autotext'))?false:true;
  413. if ($autotext && $fields['email']!='') {
  414. $autotext = formMerge($autotext,$fields);
  415. $mail = new PHPMailer();
  416. $mail->IsMail();
  417. $mail->CharSet = $modx->config['modx_charset'];
  418. $mail->IsHTML($isHtml);
  419. $mail->From = ($autosender)? $autosender:$from;
  420. $mail->FromName = ($autoSenderName)?$autoSenderName:$fromname;
  421. $mail->Subject = $subject;
  422. $mail->Body = $autotext;
  423. AddAddressToMailer($mail,"to",$fields['email']);
  424. if(!$mail->send()) return 'AutoText: ' . $_lang['ef_mail_error'] . $mail->ErrorInfo;
  425. }
  426. //defaults to text - test for sendAsHtml
  427. $isHTML = ($sendAsHTML==1 || strstr($sendAsHtml,'mobile'))?true:false;
  428. # send mobile email
  429. if ($mobile && $mobiletext) {
  430. $mobiletext = formMerge($mobiletext,$fields);
  431. $mail = new PHPMailer();
  432. $mail->IsMail();
  433. $mail->CharSet = $modx->config['modx_charset'];
  434. $mail->IsHTML($isHtml);
  435. $mail->From = $from;
  436. $mail->FromName = $fromname;
  437. $mail->Subject = $subject;
  438. $mail->Body = $mobiletext;
  439. AddAddressToMailer($mail,"to",$mobile);
  440. $mail->send();
  441. }
  442. }//end test nomail
  443. # added in 1.4.2 - Protection against multiple submit with same form data
  444. if($protectSubmit) $_SESSION[$formid.'_hash'] = $hash; //hash is set earlier
  445. # added in 1.4.2 - Limit the time between form submissions
  446. if($submitLimit>0) $_SESSION[$formid.'_limit'] = time();
  447. # invoke OnMailSent event set by another script
  448. if ($eFormOnMailSent) {
  449. if( $isDebug && !function_exists($eFormOnMailSent) )
  450. $fields['debug'] .= "eFormOnMailSent event: Could not find the function" . $eFormOnMailSent;
  451. else
  452. if ($eFormOnMailSent($fields)===false) return;
  453. }
  454. if($isDebug){
  455. $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 />";
  456. if($isDebug>1){
  457. $debugText .= "<br /><strong>Formats array:</strong><pre>". var_export($formats,true).'</pre>';
  458. $debugText .= "<br /><strong>Fields array:</strong><pre>". var_export($fields,true).'</pre>';
  459. }
  460. $fields['debug'] = $debugText;
  461. }
  462. # show or redirect to thank you page
  463. if ($gid==$modx->documentIdentifier){
  464. if(!empty($thankyou) ){
  465. if($isDebug && !strstr($thankyou,'[+debug+]')) $thankyou .= '[+debug+]';
  466. if( isset($startupSource) ) efRegisterStartupBlock($startupSource,true); //skip scripts
  467. if( $sendAsText ){
  468. foreach($formats as $key => $fmt)
  469. if($fmt[2]=='html') $fields[$key] = str_replace("\n",'<br />',$fields[$key]);
  470. }
  471. $thankyou = formMerge($thankyou,$fields);
  472. return $thankyou;
  473. }else{
  474. return $_lang['ef_thankyou_message'];
  475. }
  476. }
  477. else {
  478. $url = $modx->makeURL($gid);
  479. $modx->sendRedirect($url);
  480. }
  481. return; // stop here
  482. }
  483. }else{ //not postback
  484. //add debugging info to fields array
  485. if($isDebug){
  486. $debugText .= "<br /><strong>eForm configuration:</strong><pre>". var_export($params,true).'</pre>';
  487. $fields['debug']=$debugText;
  488. }
  489. //strip the eform attribute
  490. $regExpr = "#eform=([\"'])[^\\1]*?\\1#si";
  491. $tpl = preg_replace($regExpr,'',$tpl);
  492. }
  493. // set vericode
  494. if($vericode) {
  495. $_SESSION['eForm.VeriCode'] = $fields['vericode'] = substr(uniqid(''),-5);
  496. $fields['verimageurl'] = $modx->config['base_url'].'manager/includes/veriword.php?rand='.rand();
  497. }
  498. # get SESSION data - thanks to sottwell
  499. if($sessionVars){
  500. $sessionVars = (strpos($sessionVars,',',0))?explode(',',$sessionVars):array($sessionVars);
  501. foreach( $sessionVars as $varName ){
  502. if( empty($varName) ) continue;
  503. $varName = trim($varName);
  504. if( isset($_SESSION[$varName]) && !empty($_SESSION[$varName]) )
  505. $fields[$varName] = ( isset($fields[$varName]) && $postOverides )?$fields[$varName]:$_SESSION[$varName];
  506. }
  507. }
  508. # invoke OnBeforeFormMerge event set by another script
  509. if ($eFormOnBeforeFormMerge) {
  510. if( $isDebug && !function_exists($eFormOnBeforeFormMerge))
  511. $fields['debug'] .= "eFormOnBeforeFormMerge event: Could not find the function " . $eFormOnBeforeFormMerge;
  512. else
  513. if ($eFormOnBeforeFormMerge($fields)===false) return;
  514. }
  515. # build form
  516. if($isDebug && !$fields['debug']) $fields['debug'] = $debugText;
  517. if($isDebug && !strstr($tpl,'[+debug+]')) $tpl .= '[+debug+]';
  518. //register css and/or javascript
  519. if( isset($startupSource) ) efRegisterStartupBlock($startupSource);
  520. return formMerge($tpl,$fields);
  521. }
  522. # Form Merge
  523. function formMerge($docText, $docFields, $vClasses='') {
  524. global $formats;
  525. $lastitems;
  526. if(!$docText) return '';
  527. preg_match_all('~\[\+(.*?)\+\]~', $docText, $matches);
  528. for($i=0;$i<count($matches[1]);$i++) {
  529. $name = $matches[1][$i];
  530. list($listName,$listValue) = explode(":",$name);
  531. $value = isset($docFields[$listName])? $docFields[$listName]:'';
  532. // support for multi checkbox, radio and select - Djamoer
  533. if(is_array($value)) $value=implode(', ', $value);
  534. $fld = $formats[$name];
  535. if (!isset($fld)){
  536. // listbox, checkbox, radio select
  537. $colonPost = strpos($name, ':');
  538. $listName = substr($name, 0, $colonPost);
  539. $listValue = substr($name, $colonPost+1);
  540. $datatype = $formats[$listName][2];
  541. if(is_array($docFields[$listName])) {
  542. if($datatype=="listbox" && in_array($listValue, $docFields[$listName])) $docText = str_replace("[+$listName:$listValue+]","selected='selected'",$docText);
  543. if(($datatype=="checkbox"||$datatype=="radio") && in_array($listValue, $docFields[$listName])) $docText = str_replace("[+$listName:$listValue+]","checked='checked'",$docText);
  544. }
  545. else {
  546. if($datatype=="listbox" && $listValue==$docFields[$listName]) $docText = str_replace("[+$listName:$listValue+]","selected='selected'",$docText);
  547. if(($datatype=="checkbox"||$datatype=="radio") && $listValue==$docFields[$listName]) $docText = str_replace("[+$listName:$listValue+]","checked='checked'",$docText);
  548. }
  549. }
  550. if(strpos($name,":")===false) $docText = str_replace("[+$name+]",$value,$docText);
  551. else {
  552. // this might be a listbox item.
  553. // we'll remove this field later
  554. $lastitems[count($lastitems)]="[+$name+]";
  555. }
  556. }
  557. $lastitems[count($lastitems)] = "class=\"\""; //removal off empty class attributes
  558. $docText = str_replace($lastitems,"",$docText);
  559. return $docText;
  560. }
  561. # Adds Addresses to Mailer
  562. function AddAddressToMailer(&$mail,$type,$addr){
  563. $a = explode(",",$addr);
  564. for($i=0;$i<count($a);$i++){
  565. if(!empty($a[$i])) {
  566. if ($type=="to") $mail->AddAddress($a[$i]);
  567. elseif ($type=="cc") $mail->AddCC($a[$i]);
  568. elseif ($type=="bcc") $mail->AddBCC($a[$i]);
  569. elseif ($type=="replyto") $mail->AddReplyTo($a[$i]);
  570. }
  571. }
  572. }
  573. # Attach Files to Mailer
  574. function AttachFilesToMailer(&$mail,&$attachFiles) {
  575. if(count($attachFiles)>0){
  576. foreach($attachFiles as $attachFile){
  577. if(!file_exists($attachFile)) continue;
  578. $FileName = $attachFile;
  579. $contentType = "application/octetstream";
  580. if (is_uploaded_file($attachFile)){
  581. foreach($_FILES as $n => $v){
  582. if($_FILES[$n]['tmp_name']==$attachFile) {
  583. $FileName = $_FILES[$n]['name'];
  584. $contentType = $_FILES[$n]['type'];
  585. }
  586. }
  587. }
  588. $patharray = explode(((strpos($FileName,"/")===false)? "\\":"/"), $FileName);
  589. $FileName = $patharray[count($patharray)-1];
  590. $mail->AddAttachment($attachFile,$FileName,"base64",$contentType);
  591. }
  592. }
  593. }
  594. /*--- Form Parser stuff----------------------*/
  595. function eFormParseTemplate($tpl, $isDebug=false ){
  596. global $modx,$formats,$optionsName,$_lang,$debugText,$fields,$validFormId;
  597. global $efPostBack;
  598. $formats =""; //clear formats so values don't persist through multiple snippet calls
  599. $labels = "";
  600. $regExpr = "#(<label[^>]*?>)(.*?)</label>#si";;
  601. preg_match_all($regExpr,$tpl,$matches);
  602. foreach($matches[1] as $key => $fld){
  603. $attr = attr2array($fld);
  604. if(isset($attr['for'])){
  605. $name = substr($attr['for'],1,-1);
  606. //add class to fields array
  607. $fields[$name."_vClass"] = isset($attr['class'])?substr($attr['class'],1,-1):'';
  608. $labels[$name] = strip_tags($matches[2][$key]);
  609. //create placeholder for class
  610. $attr['class'] = '"[+'.$name.'_vClass+]"';
  611. $newTag = buildTagPlaceholder('label',$attr,$name);
  612. $tpl = str_replace($fld,$newTag,$tpl);
  613. }
  614. }
  615. //retrieve all the form fields
  616. $regExpr = "#(<(input|select|textarea)[^>]*?>)#si";
  617. preg_match_all($regExpr,$tpl,$matches);
  618. $fieldTypes = $matches[2];
  619. $fieldTags = $matches[1];
  620. for($i=0;$i<count($fieldTypes);$i++){
  621. $type = $fieldTypes[$i];
  622. //get array of html attributes
  623. $tagAttributes = attr2array($fieldTags[$i]);
  624. //attribute values are stored including quotes
  625. //strip quotes as well as any brackets to get the raw name
  626. $name = str_replace(array("'",'"','[',']'),'',$tagAttributes['name']);
  627. #skip vericode field - updated in 1.4.4
  628. #special case. We need to set the class placeholder but forget about the rest
  629. if($name=="vericode"){
  630. if(isset($tagAttributes['class'])){
  631. $fields[$name.'_class'] = substr($tagAttributes['class'],1,-1);
  632. }
  633. $tagAttributes['class'] = '"[+'.$name.'_class+]"';
  634. $tagAttributes['value'] = '';
  635. $newTag = buildTagPlaceholder('input',$tagAttributes,$name);
  636. $tpl = str_replace($fieldTags[$i],$newTag,$tpl);
  637. continue;
  638. }
  639. //store the field options
  640. if (isset($tagAttributes[$optionsName])){
  641. //split to max of 5 so validation rule can contain ':'
  642. $formats[$name] = explode(":",stripTagQuotes($tagAttributes[$optionsName]),5) ;
  643. array_unshift($formats[$name],$name);
  644. }else{
  645. if(!isset($formats[$name])) $formats[$name]=array($name,'','',0);
  646. }
  647. //added for 1.4 - use label if it is defined
  648. if(empty($formats[$name][1]))
  649. $formats[$name][1]=(isset($labels[$name])) ? $labels[$name] : $name;
  650. if(isset($id)) $formats[6] = $id; //added in 1.4.4.1
  651. unset($tagAttributes[$optionsName]);
  652. //added in 1.4.2 - add placeholder to class attribute
  653. if(isset($tagAttributes['class'])){
  654. $fields[$name.'_class'] = substr($tagAttributes['class'],1,-1);
  655. }
  656. $tagAttributes['class'] = '"[+'.$name.'_class+]"';
  657. switch($type){
  658. case "select":
  659. //replace with 'cleaned' tag and added placeholder
  660. $newTag = buildTagPlaceholder('select',$tagAttributes,$name);
  661. $tpl = str_replace($fieldTags[$i],$newTag,$tpl);
  662. if($formats[$name]) $formats[$name][2]='listbox';
  663. //Get the whole select block with option tags
  664. //escape any regex characters!
  665. $regExp = "#<select [^><]*?name=".preg_quote($tagAttributes['name'],'#')."[^>]*?".">(.*?)</select>#si";
  666. preg_match($regExp,$tpl,$matches);
  667. $optionTags = $matches[1];
  668. $select = $newSelect = $matches[0];
  669. //get separate option tags and split them up
  670. preg_match_all("#(<option [^>]*?>)#si",$optionTags,$matches);
  671. $validValues = array();
  672. foreach($matches[1] as $option){
  673. $attr = attr2array($option);
  674. //* debug */ print __LINE__.': <pre>'.print_r($attr,true) .'</pre><br />';
  675. $value = substr($attr['value'],1,-1); //strip outer quotes
  676. if( trim($value)!='' ) $validValues[] = $value;
  677. $newTag = buildTagPlaceholder('option',$attr,$name);
  678. $newSelect = str_replace($option,$newTag,$newSelect);
  679. //if no postback, retain any checked values
  680. if(!$efPostBack && !empty($attr['selected'])) $fields[$name][]=$value;
  681. }
  682. //replace complete select block
  683. $tpl = str_replace($select,$newSelect,$tpl);
  684. //add valid values to formats... (extension to $formats)
  685. if($formats[$name] && !$formats[$name][5]){
  686. $formats[$name][4] = $_lang['ef_failed_default'];
  687. //convert commas in values to something else !
  688. $formats[$name][5]= "#LIST " . implode(",",str_replace(',','&#44;',$validValues));
  689. }
  690. break;
  691. case "textarea":
  692. // add support for maxlength attribute for textarea
  693. // attribute get's stripped form form //
  694. if( $tagAttributes['maxlength'] ){
  695. $formats[$name][$_dfnMaxlength] == $tagAttributes['maxlength'];
  696. unset($tagAttributes['maxlength']);
  697. }
  698. $newTag = buildTagPlaceholder($type,$tagAttributes,$name);
  699. $regExp = "#<textarea [^>]*?name=" . $tagAttributes["name"] . "[^>]*?" . ">(.*?)</textarea>#si";
  700. preg_match($regExp,$tpl,$matches);
  701. //if nothing Posted retain the content between start/end tags
  702. $placeholderValue = ($efPostBack)?"[+$name+]":$matches[1];
  703. $tpl = str_replace($matches[0],$newTag.$placeholderValue."</textarea>",$tpl);
  704. break;
  705. default: //all the rest, ie. "input"
  706. $newTag = buildTagPlaceholder($type,$tagAttributes,$name);
  707. $fieldType = stripTagQuotes($tagAttributes['type']);
  708. //validate on maxlength...
  709. if( $fieldType=='text' && $tagAttributes['maxlength'] ){
  710. $formats[$name][$_dfnMaxlength] == $tagAttributes['maxlength'];
  711. }
  712. if($formats[$name] && !$formats[$name][2]) $formats[$name][2]=($fieldType=='text')?"string":$fieldType;
  713. //populate automatic validation values for hidden, checkbox and radio fields
  714. if($fieldType=='hidden'){
  715. if(!$isDebug) $formats[$name][1] = "[undefined]"; //do not want to disclose hidden field names
  716. if(!isset($formats[$name][4])) $formats[$name][4]= $_lang['ef_tamper_attempt'];
  717. if(!isset($formats[$name][5])) $formats[$name][5]= "#VALUE ". stripTagQuotes($tagAttributes['value']);
  718. }elseif($fieldType=='checkbox' || $fieldType=='radio'){
  719. $formats[$name][4]= $_lang['ef_failed_default'];
  720. $formats[$name][5] .= isset($formats[$name][5])?",":"#LIST ";
  721. //convert embedded comma's in values!
  722. $formats[$name][5] .= str_replace(',','&#44;',stripTagQuotes($tagAttributes['value']));
  723. //store the id as well
  724. //if no postback, retain any checked values
  725. if(!$efPostBack && !empty($tagAttributes['checked'])) $fields[$name][]=stripTagQuotes($tagAttributes['value']);
  726. //
  727. $formats[$name][6] .= ( isset($formats[$name][6])?",":"").stripTagQuotes($tagAttributes['id']);
  728. }elseif(empty($fields[$name])){ //plain old text input field
  729. //retain default value set in form template if not already set in code
  730. $fields[$name] = stripTagQuotes($tagAttributes['value']);
  731. }
  732. $tpl = str_replace($fieldTags[$i],$newTag,$tpl);
  733. break;
  734. }
  735. }
  736. if($isDebug>2) $debugText .= "<strong>Parsed template</strong><p style=\"border:1px solid black;padding:2px;\">" . str_replace("\n",'<br />',str_replace('+','&#043;',htmlspecialchars($tpl)))."</p><hr>";
  737. return $tpl;
  738. }
  739. function stripTagQuotes($value){
  740. return substr($value,1,-1);
  741. }
  742. function buildTagPlaceholder($tag,$attributes,$name){
  743. $type = stripTagQuotes($attributes["type"]);
  744. $quotedValue = $attributes['value'];
  745. $val = stripTagQuotes($quotedValue);
  746. foreach ($attributes as $k => $v)
  747. $t .= ($k!='value' && $k!='checked' && $k!='selected')?" $k=$v":"";
  748. switch($tag){
  749. case "select":
  750. return "<$tag$t>"; //only the start tag mind you
  751. case "option":
  752. return "<$tag$t value=".$quotedValue." [+$name:$val+]>";
  753. case "input":
  754. switch($type){
  755. case 'radio':
  756. case 'checkbox':
  757. return "<input$t value=".$quotedValue." [+$name:$val+] />";
  758. case 'text':
  759. if($name=='vericode') return "<input$t value=\"\" />";
  760. //else pass on to next
  761. case 'password':
  762. return "<input$t value=\"[+$name+]\" />";
  763. default: //leave as is - no placeholder
  764. return "<input$t value=".$quotedValue." />";
  765. }
  766. case "file": //no placeholder!
  767. case "textarea": //placeholder needs to be added in calling code
  768. return "<$tag$t>";
  769. case "label":
  770. return "<$tag$t>";
  771. default:
  772. return "<input$t value=\"[+$name+]\" />";
  773. } // switch
  774. return ""; //if we've arrived here we're in trouble
  775. }
  776. function attr2array($tag){
  777. $expr = "#([a-z0-9_]*?)=(([\"'])[^\\3]*?\\3)#si";
  778. preg_match_all($expr,$tag,$matches);
  779. foreach($matches[1] as $i => $key)
  780. $rt[$key]= $matches[2][$i];
  781. return $rt;
  782. }
  783. function validateField($value,$fld,&$vMsg,$isDebug=false){
  784. global $modx,$_lang, $debugText,$fields;
  785. $output = true;
  786. $desc = $fld[1];
  787. $fldMsg = trim($fld[4]);
  788. if(empty($fld[5])) return $output; //if no rule value validates
  789. list($cmd,$param) = explode(" ",trim($fld[5]),2);
  790. $cmd = strtoupper(trim($cmd));
  791. if (substr($cmd,0,1)!='#'){
  792. $vMsg[count($vMsg)] = "$desc &raquo;" . $_lang['ef_error_validation_rule'];
  793. return false;
  794. }
  795. $valList = (is_array($value))?$value:array($value);
  796. //init vars
  797. $errMsg='';
  798. unset($vlist);
  799. for($i=0;$i<count($valList);$i++){
  800. $value = $valList[$i]; //re-using $value, destroying original!!
  801. switch ($cmd) {
  802. //really only used internally for hidden fields
  803. case "#VALUE":
  804. if($value!=$param) $errMsg = $_lang['ef_failed_default'];
  805. break;
  806. case "#RANGE":
  807. if(!isset($vlist)) $vlist = explode(',',strtolower(trim($param))); //cached
  808. //the crude way first - will have to refine this
  809. foreach($vlist as $p){
  810. if( strpos($p,'~')>0)
  811. $range = explode('~',$p);
  812. else
  813. $range = array($p,$p); //yes,.. I know - cheating :)
  814. if($isDebug && (!is_numeric($range[0]) || !is_numeric($range[1])) )
  815. $modx->messageQuit('Error in validating form field!', '',$false,E_USER_WARNING,__FILE__,'','#RANGE rule contains non-numeric values: '.$fld[5],__LINE__);
  816. sort($range);
  817. if( $value>=$range[0] && $value<=$range[1] ) break 2; //valid
  818. }
  819. $errMsg = $_lang['ef_failed_range'];
  820. break;
  821. case "#LIST": // List of comma separated values (not case sensitive)
  822. //added in 1.4 - file upload filetype test
  823. //FS#960 - removed trimming of $param - values with leading or trailing spaces would always fail validation
  824. if($fld[2]=='file')$value = substr($value,strrpos($value,'.')+1); //file extension
  825. if(!isset($vlist)){
  826. $vlist = explode(',',strtolower($param)); //cached
  827. foreach($vlist as $k =>$v ) $vlist[$k]=str_replace('&#44;',',',$v);
  828. } //changes to make sure embedded commma's in values are recognized
  829. if( $isDebug && count($vlist)==1 && empty($vlist[0]) ){
  830. //if debugging bail out big time
  831. $modx->messageQuit('Error in validating form field!', '',$false,E_USER_WARNING,__FILE__,'','#LIST rule declared but no list values supplied: '.$fld[5],__LINE__);
  832. }elseif(!in_array(strtolower($value),$vlist))
  833. $errMsg = ($fld[2]=='file')? $_lang["ef_failed_upload"]: $_lang['ef_failed_list'];
  834. break;
  835. case "#SELECT": //validates against a list of values from the cms database
  836. #cache all this
  837. if( !isset($vlist) ) {
  838. $rt = array();
  839. $param = str_replace('{DBASE}',$modx->db->config['dbase'],$param);
  840. $param = str_replace('{PREFIX}',$modx->db->config['table_prefix'],$param);
  841. //added in 1.4
  842. if( preg_match("/{([^}]*?)\}/",$param,$matches) ){
  843. $tmp = $modx->db->escape(formMerge('[+'.$matches[1].'+]',$fields));
  844. $param = str_replace('{'.$matches[1].'}',$tmp,$param);
  845. }
  846. $rs = $modx->db->query("SELECT $param;");
  847. //select value from 1st field in records only (not case sensitive)
  848. while( $v = $modx->db->getValue($rs) ) $vlist[]=strtolower($v);
  849. }
  850. if(!is_array($vlist)){
  851. //WARNING! if not debugging (and query fails) error is ignored, and value will validate!!
  852. //version 1.4 - replaced fatal error with friendly debug message when debugging
  853. $debugText .= ($isDebug)? "'<strong>$fld[1]</strong>' ".$_lang['ef_sql_no_result'].'<br />':'';
  854. }elseif(!in_array(strtolower($value),$vlist)){
  855. $errMsg = $_lang['ef_failed_list'];
  856. }
  857. break;
  858. case "#EVAL": // php code should return true or false
  859. $tmp = $cmd; //just in case eval destroys cmd
  860. if( eval($param)===false )
  861. $errMsg = $_lang['ef_failed_eval'];
  862. if($isDebug) $debugText .= "<strong>$fld[1]</strong>: ".$_lang['ef_eval_deprecated']." $param";
  863. $cmd = $tmp;
  864. break;
  865. //added in 1.4
  866. case "#FUNCTION":
  867. $tmp = $cmd; //just in case function destroys cmd
  868. if( function_exists($param) )
  869. if( !@$param($value) ) $errMsg = $_lang['ef_failed_eval'];
  870. else
  871. if($isDebug) $debugText .= "<strong>$fld[1]</strong>: ".$_lang['ef_no_function']." $param";
  872. $cmd = $tmp;
  873. break;
  874. case "#REGEX":
  875. if( !$tmp=preg_match($param,$value) )
  876. $errMsg = $_lang['ef_failed_ereg'];
  877. if($isDebug && $tmp===false ) $debugText .= "<strong>$fld[1]</strong>: ".$_lang['ef_regex_error']." $param";
  878. break;
  879. case "#FILTER":
  880. $valList[$i] = filterEformValue($value,$param);
  881. break;
  882. default:
  883. $errMsg = $_lang['ef_error_validation_rule'];
  884. }//end switch
  885. if($isDebug) {
  886. $debugText .="'<strong>$fld[1]</strong>' ";
  887. $debugText .= (empty($errMsg))?'passed':'<span style="color:red;">Failed</span>';
  888. $debugText .= " using rule: $cmd ".$param.', (input='.htmlspecialchars($valList[$i]).")<br />\n";
  889. }
  890. if(!empty($errMsg)){
  891. $errMsg = ($fldMsg)?"$desc &raquo; $fldMsg":"$desc &raquo; $errMsg";
  892. $vMsg[count($vMsg)] = $errMsg;
  893. $output=false;
  894. break; //quit testing more values
  895. }
  896. }//end for
  897. //make sure we have correct return value in case of #filter
  898. $valList = (!is_array($value))?implode('',$valList):$valList;
  899. return ($cmd=="#FILTER")?$valList:$output;
  900. }//end validateField
  901. function filterEformValue($value,$param){
  902. list($cmd,$param) = explode(" ",trim($param),2);
  903. $cmd = trim($cmd);
  904. switch(strtoupper($cmd)){
  905. case "#REGEX":
  906. list($src,$dst) = explode("||",$param,2);
  907. $value = ( $v = preg_replace($src,$dst,$value) )?$v:$value;
  908. break;
  909. case "#LIST":
  910. $param = explode("||",$param,2);
  911. $src = strpos($param[0],',')?explode(',',$param[0]):$param[0];
  912. $dst = strpos($param[1],',')?explode(',',$param[1]):$param[1];
  913. $value = str_replace($src,$dst,$value);
  914. break;
  915. case "#EVAL":
  916. $value = ($v = @eval($param))?$v:$value;
  917. break;
  918. }
  919. return $value;
  920. }
  921. function efLoadTemplate($key){
  922. global $modx;
  923. if( strlen($key)>50 ) return $key;
  924. $tpl = false;
  925. if( is_numeric($key) ) { //get from document id
  926. //try unpublished docs first
  927. $tpl = ( $doc=$modx->getDocument($key,'content',0) )? $doc['content'] :false;
  928. if(!$tpl )
  929. $tpl = ( $doc=$modx->getDocument($key,'content',1) )? $doc['content'] : false;
  930. }elseif( $key ){
  931. $tpl = ( $doc=$modx->getChunk($key) )? $doc : false;
  932. //try snippet if chunk is not found
  933. if(!$tpl) $tpl = ( $doc=$modx->runSnippet($key) )? $doc : false;
  934. }
  935. return $tpl;
  936. }
  937. # registers css and/or javascript to modx class
  938. function efRegisterStartupBlock($src_array,$noScript=false){
  939. global $modx;
  940. if(!array($src_array)) return;
  941. foreach($src_array as $item){
  942. list($src,$type) = $item;
  943. //skip scripts if told to do so
  944. if($type=='javascript' && $noScript) continue;
  945. //try to load from document or chunk
  946. if( $tmp = efLoadtemplate($src) )
  947. $src = $tmp;
  948. $src=trim($src);
  949. if ( $type=='css' )
  950. $modx->regClientCSS($src);
  951. elseif ( $type == 'javascript' )
  952. $modx->regClientStartupScript($src);
  953. else
  954. $modx->regClientStartupHTMLBlock($src);
  955. }//end foreach
  956. }
  957. /**
  958. * adapted from http://php.mirrors.ilisys.com.au/manual/en/ref.mail.php
  959. * If any field contains newline followed by email-header specific string it is replaced by a harmless substitute
  960. * (we hope) If any subsitutiosn are made the function returns true
  961. * Currently tests for
  962. * Content-Transfer-Encoding:
  963. * MIME-Version:
  964. * content-type:
  965. * to:
  966. * cc:
  967. * bcc:
  968. */
  969. function hasMailHeaders( &$fields ){
  970. $injectionAttempt = false;
  971. $re = "/(%0A|%0D|\n+|\r+)(Content-Transfer-Encoding:|MIME-Version:|content-type:|to:|cc:|bcc:)/i";
  972. foreach($fields as $fld => $text){
  973. if( ($match = preg_replace($re,'\\[\2]\\', $text))!=$text ){
  974. $injectionAttempt = true;
  975. $fields[$fld]=$match; //replace with 'disabled' version
  976. }
  977. }
  978. return ($injectionAttempt)?true:false;
  979. }
  980. ?>