PluginProbe
Contact Forms by Cimatti / 1.9.2
Contact Forms by Cimatti v1.9.2
2.3.6 2.3.5 2.3.0 2.2.32 2.2.4 2.2.0 2.1.2 2.1.1 trunk 1.0 1.1 1.2 1.2.1 1.3 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 All 62 releases
contact-forms / AccuaForm.php

AccuaForm.php in Contact Forms by Cimatti 1.9.2, at AccuaForm.php

1,155 lines 38.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 class AccuaForm extends Form {
3 protected static $submitted = null;
4 protected static $valid = null;
5 protected static $submittedID = null;
6 protected static $submittedBuildID = null;
7 protected static $submittedForm = null;
8 protected static $submittedFormUsed = false;
9 protected static $submittedData = null;
10 protected static $rawData = null;
11 protected static $submittedMessages = '';
12
13 protected $formID = null;
14 protected $buildID = null;
15 protected $validate_functions = array();
16 protected $submit_functions = array();
17 protected $elements_sleep;
18 public $stats = array();
19 protected $accua_ajax;
20 protected $locale = null;
21 protected $language = null;
22 protected $files = array();
23 protected $ga_track = array();
24
25 protected $original_locale = null;
26 protected $original_language = null;
27 protected $original_l10n = null;
28 protected $forced_language = false;
29 protected $elementsByName = array();
30 protected $elementCounter = 0;
31
32 public function force_language() {
33 if ((!$this->forced_language) && $this->language && function_exists('qtrans_getLanguage')) {
34 global $q_config;
35 $this->original_language = $q_config['language'];
36
37 if ($this->language != $this->original_language) {
38 $this->original_locale =& $GLOBALS['wp_locale'];
39 $this->original_l10n =& $GLOBALS['l10n'];
40
41 unset($GLOBALS['wp_locale']);
42 unset($GLOBALS['l10n']);
43 $GLOBALS['l10n'] = array();
44
45 $GLOBALS['q_config']['language'] = $this->language;
46 load_default_textdomain();
47 load_plugin_textdomain( 'contact-forms', false, ACCUA_FORM_API_PLUGIN_TEXTDOMAIN_PATH);
48 require_once( ABSPATH . WPINC . '/locale.php' );
49 $GLOBALS['wp_locale'] = new WP_Locale();
50 $GLOBALS['wp_locale']->register_globals();
51
52 $this->forced_language = true;
53 }
54 }
55 }
56
57 public function restore_language() {
58 if ($this->forced_language) {
59 unset($GLOBALS['wp_locale']);
60 unset($GLOBALS['l10n']);
61
62 $GLOBALS['q_config']['language'] = $this->original_language;
63 $GLOBALS['l10n'] =& $this->original_l10n;
64 $GLOBALS['wp_locale'] =& $this->original_locale;
65 if ($GLOBALS['wp_locale']) {
66 $GLOBALS['wp_locale']->register_globals();
67 }
68
69 $this->forced_language = false;
70 }
71 }
72
73 public function __sleep() {
74 $this->elements_sleep = $this->getElements();
75 return array('attributes', 'elements_sleep', 'error', 'view', 'prefix', 'widthSuffix', 'ajax', 'ajaxCallback', 'jQueryUITheme', 'resourcesPath', 'prevent', 'width', 'formID', 'buildID', 'validate_functions', 'submit_functions', 'stats', 'accua_ajax', 'locale', 'language', 'files');
76 }
77
78 public function __wakeup() {
79 foreach ($this->elements_sleep as $element) {
80 $this->addElement($element);
81 }
82 unset($this->elements_sleep);
83 if ($this->view) {
84 $this->view->setForm($this);
85 }
86 if ($this->error) {
87 $this->error->setForm($this);
88 }
89 }
90
91 public function addElement(Element $element) {
92 $name = $element->getName();
93 if ($name) {
94 $this->elementsByName[$name] = $element;
95 }
96 $id = $element->getID();
97 if(empty($id)) {
98 $element->setID($this->attributes["id"] . "-element-" . $this->elementCounter);
99 }
100 $this->elementCounter++;
101 return parent::addElement($element);
102 }
103
104 public function getElementByName($name) {
105 if (isset($this->elementsByName[$name])) {
106 return $this->elementsByName[$name];
107 } else {
108 return null;
109 }
110 }
111
112 public function removeElement($element) {
113 foreach ($this->elements as $k => $e) {
114 if ($e === $element) {
115 $name = $element->getName();
116 if ($name) {
117 unset ($this->elementsByName[$name]);
118 }
119 unset($this->elements[$k]);
120 return true;
121 }
122 }
123 return false;
124 }
125
126 public static function sessionID() {
127 $sessionid = session_id();
128 if ($sessionid === '' && !defined('DOING_CRON')) {
129 $started = session_start();
130 if (!$started) {
131 $file = $line = '';
132 if(headers_sent($file,$line)) {
133 error_log("headers already sent at {$file}:{$line}");
134 }
135 }
136 $sessionid = session_id();
137 }
138 return $sessionid;
139 }
140
141 public static function getBaseURL() {
142 static $ret = null;
143 if ($ret === null) {
144 $s = empty($_SERVER["HTTPS"]) ? '' : (($_SERVER["HTTPS"] == "on") ? "s" : "");
145 $sp = strtolower($_SERVER["SERVER_PROTOCOL"]);
146 $protocol = substr($sp, 0, strpos($sp, "/")) . $s;
147 $port = ($_SERVER["SERVER_PORT"] == "80") ? "" : (":".$_SERVER["SERVER_PORT"]);
148 $ret = $protocol . "://" . $_SERVER['SERVER_NAME'] . $port;
149 }
150 return $ret;
151 }
152
153 public static function create($baseid = 'pfbc', $params = array()) {
154 if (self::isSubmit() && (!self::isValid()) && ($baseid === self::$submittedID) && (!self::$submittedFormUsed)) {
155 self::$submittedFormUsed = true;
156 if (!(self::isValid() || empty(self::$submittedForm))) {
157 $form = self::$submittedForm;
158 $form->setValues(self::$submittedData);
159 return $form;
160 }
161 $form = new AccuaForm ($baseid, $params, self::$submittedBuildID);
162 $form->setValues(self::$submittedData);
163 } else {
164 $form = new AccuaForm($baseid, $params);
165 }
166 if (function_exists($baseid)) {
167 call_user_func($baseid, $form);
168 }
169 do_action('accua_form_alter', $baseid, $form);
170 return $form;
171 }
172
173 function __construct($id = 'pfbc', $params = array()) {
174 if (func_num_args() > 2) {
175 $buildid = (string) func_get_arg(2);
176 } else {
177 $buildid = '';
178 }
179 if ($buildid === '') {
180 $buildid = 'accua-form_' . $id . '_' . uniqid();
181 }
182
183 $predefined_params = array(
184 'width' => '',
185 'layout' => 'sidebyside',
186 'title' => '',
187 'track_submit' => false,
188 'track_fields' => false,
189 );
190 if (is_array($params)) {
191 $params += $predefined_params;
192 $width = $params['width'];
193 } else {
194 $width = $params;
195 $params = $predefined_params;
196 $params['width'] = $width;
197 }
198 $class = 'accua-form ' . $id;
199 switch ($params['layout']) {
200 case 'toplabel':
201 $this->view = new AccuaForm_View_Standard();
202 $class .= ' accua-form-view-standard';
203 break;
204 case 'sidebyside':
205 default:
206 $this->view = new AccuaForm_View_SideBySide(
207 '19',
208 array('labelPaddingRight' => '1')
209 );
210 $class .= ' accua-form-view-sidebyside';
211 }
212 $this->error = new AccuaForm_Error_Standard(array(
213 'errorfound' => '',
214 'errorsfound' => '',
215 ));
216 if ($width === ""){
217 $width = "100%";
218 }
219 $this->attributes = array(
220 'class' => $class,
221 'novalidate' => 'novalidate',
222 );
223 foreach (array('title', 'track_submit', 'track_fields') as $i) {
224 $this->ga_track[$i] = $params[$i];
225 }
226
227 parent::__construct($buildid, $width);
228
229
230 $this->formID = $id;
231 $this->buildID = $buildid;
232 $this->addElement(new Element_Hidden('_AccuaForm_ID', $id));
233 $this->addElement(new Element_Hidden('_AccuaForm_buildID', $buildid));
234 $this->addElement(new Element_Hidden('_AccuaForm_wpnonce', wp_create_nonce( $buildid )));
235 $this->addElement(new Element_Hidden('_AccuaForm_jsuuid', ''));
236 $this->addElement(new Element_Hidden('_AccuaForm_referrer', ''));
237 $this->addElement(new Element_Hidden('_AccuaForm_user_agent', ''));
238 $this->addElement(new Element_Hidden('_AccuaForm_platform', ''));
239 $this->addElement(new Element_Hidden('_AccuaForm_tentatives', '0'));
240 $this->addElement(new Element_Hidden('_AccuaForm_submit_method', 'normal'));
241 $this->addElement(new Element_Hidden('_AccuaForm_hash', ''));
242 $this->addElement(new Element_Hidden('_AccuaForm_iv', ''));
243 $this->addElement(new Element_Hidden('_AccuaForm_data', ''));
244 /*
245 * - Prima di generare l'html del form, salva una copia serializzata compreso di codice SHA2, criptato, in _AccuaForm_serialized
246 * - Quando ricevi il form, decripta _AccuaForm_serialized e controlla che sia valido
247 *
248 * */
249
250 //$this->addElement(new Element_Hidden('PHPSESSID', self::sessionID()));
251 $this->prevent = array('jQuery', 'jQueryUI', 'jQueryUIButtons', 'focus', 'style');
252 $this->configure(array('action' => ''));
253
254 if (function_exists('qtrans_getLanguage')) {
255 $this->language = qtrans_getLanguage();
256 $this->locale = $GLOBALS['q_config']['locale'][$this->language];
257 } else {
258 $this->locale = get_locale();
259 $this->language = explode('_', $this->locale);
260 $this->language = $this->language[0];
261 }
262
263 global $post;
264 $pid = empty($post->ID) ? 0 : $post->ID;
265
266 $uri = isset($GLOBALS['q_config']['url_info']['original_url']) ? $GLOBALS['q_config']['url_info']['original_url'] : $_SERVER['REQUEST_URI'];
267
268 $url = self::getBaseURL() . $uri ;
269
270 $referrer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '';
271
272 $this->stats = array(
273 'pid' => $pid,
274 'ip' => $_SERVER['REMOTE_ADDR'], //updated after submit
275 'original_ip' => $_SERVER['REMOTE_ADDR'], //unreliable if using a static page caching system
276 'uri' => $uri,
277 'url' => $url,
278 'referrer' => $referrer, //updated after submit using javascript
279 'original_referrer' => $referrer, //unreliable if using a static page caching system
280 'lang' => $this->language,
281 'locale' => $this->locale,
282 'created' => time(),
283 'submitted' => null,
284 'user_agent' => '',
285 'platform' => '',
286 'tentatives' => '',
287 'submit_method' => '',
288 );
289
290 $this->view->setForm($this);
291 $this->error->setForm($this);
292 }
293
294 public static function isSubmit() {
295 if (self::$submitted !== null) {
296 return self::$submitted;
297 }
298 self::$submitted = false;
299 $sessid = self::sessionID();
300
301 if($_SERVER['REQUEST_METHOD'] == 'POST') {
302 self::$rawData = stripslashes_deep($_POST);
303 } else {
304 self::$rawData = stripslashes_deep($_GET);
305 }
306
307 if (empty(self::$rawData['_AccuaForm_ID']) || empty(self::$rawData['_AccuaForm_buildID']) || empty(self::$rawData['_AccuaForm_wpnonce']) /* || empty(self::$rawData['PHPSESSID']) */
308 || empty(self::$rawData['_AccuaForm_hash']) || empty(self::$rawData['_AccuaForm_iv']) || empty(self::$rawData['_AccuaForm_data'])) {
309 return false;
310 }
311
312 /*
313 if (self::$rawData['PHPSESSID'] !== $sessid) {
314 return false;
315 }
316 */
317
318 $id = self::$rawData['_AccuaForm_buildID'];
319 $form = self::wp_recover(self::$rawData['_AccuaForm_hash'], self::$rawData['_AccuaForm_iv'], self::$rawData['_AccuaForm_data']);
320
321 if (empty($form)) {
322 return false;
323 }
324
325 if ($form->formID !== self::$rawData['_AccuaForm_ID'] || $form->buildID !== $id ) {
326 return false;
327 }
328
329 /*
330 if (!wp_verify_nonce(self::$rawData['_AccuaForm_wpnonce'], $id)) {
331 return false;
332 }
333 */
334
335 /* check if already submitted from uuid and other parameters */
336 $already_submitted = false;
337 if (!empty(self::$rawData['_AccuaForm_jsuuid'])) {
338 if (preg_match("/^[a-z0-9]{25}$/", self::$rawData['_AccuaForm_jsuuid'])) {
339 $already_submitted_data = get_transient('accuaformsub_'.self::$rawData['_AccuaForm_jsuuid']);
340 if ($already_submitted_data && $already_submitted_data['buildID'] == $form->buildID) {
341 $form = $already_submitted_data['form'];
342 self::$submittedMessages = $already_submitted_data['submittedMessages'];
343 self::$valid = true;
344 $already_submitted = true;
345 }
346 } else {
347 return false;
348 }
349 }
350
351 if (!$already_submitted) {
352 $form->stats['submitted'] = time();
353 $form->stats['ip'] = $_SERVER['REMOTE_ADDR'];
354 foreach (array('referrer', 'jsuuid', 'user_agent', 'platform', 'tentatives', 'submit_method') as $i){
355 $form->stats[$i] = isset(self::$rawData["_AccuaForm_{$i}"]) ? ((string)self::$rawData["_AccuaForm_{$i}"]) : '';
356 }
357 }
358 self::$submitted = true;
359 self::$submittedID = $form->formID;
360 self::$submittedBuildID = $form->buildID;
361 self::$submittedForm = $form;
362 return true;
363 }
364
365 public static function isValid($id = "pfbc", $clearValues = true) {
366 if (!self::isSubmit()){
367 return null;
368 }
369 if (self::$valid !== null) {
370 return self::$valid;
371 }
372
373 //$subdata = array();
374 $id = self::$submittedBuildID;
375 //$form = self::wp_recover($id);
376 $form = self::$submittedForm;
377 $valid = true;
378
379 $form->force_language();
380
381 /*Any values/errors stored in the session for this form are cleared.*/
382 self::clearValues($id);
383 self::clearErrors($id);
384
385 self::$submittedData = array();
386 /*Each element's value is saved in the session and checked against any validation rules applied
387 to the element.*/
388 $elements = $form->getElements();
389 if(!empty($elements)) {
390 foreach($elements as $element) {
391 $invalidFile = false;
392 $name = $element->getName();
393 if(substr($name, -2) == "[]") {
394 $name = substr($name, 0, -2);
395 }
396
397 /*The File element must be handled differently b/c it uses the $_FILES superglobal and
398 not $_GET or $_POST.*/
399 if($element instanceof AccuaForm_Element_File) {
400 if (!empty($form->files[$name]['name'])) {
401 $value = $form->files[$name]['name'];
402 } else if ((!empty($_FILES[$name])) && ($_FILES[$name]['error'] != UPLOAD_ERR_NO_FILE)) {
403 //$file = $_FILES[$name];
404 //include_once( ABSPATH . '/wp-admin/includes/file.php' );
405 //$overrides = array( 'test_form' => false );
406 //$file = wp_handle_upload( $file, $overrides );
407
408 $file = $element->handle_upload($_FILES[$name]);
409 $value = $file['name'];
410
411 if (empty($file['errors'])) {
412 $form->files[$name] = $file;
413 } else {
414 self::setError($id, $file['errors'] , $name);
415 $valid = false;
416 $invalidFile = true;
417 }
418 } else {
419 $value = null;
420 }
421 } else if ($element instanceof Element_File){
422 $value = $_FILES[$name]["name"];
423 } else if (isset(self::$rawData[$name])) {
424 $value = self::$rawData[$name];
425 if(is_array($value)) {
426 foreach($value as $key => $value_i) {
427 $value[$key] = (string) $value_i;
428 }
429 } else {
430 $value = (string) $value;
431 }
432 } else {
433 $value = null;
434 }
435
436 //self::setSessionValue($id, $name, $value);
437
438 /*If a validation error is found, the error message is saved in the session along with
439 the element's name.*/
440 if(!$element->isValid($value)) {
441 self::setError($id, $element->getErrors(), $name);
442 $valid = false;
443 if ($element instanceof AccuaForm_Element_File) {
444 $invalidFile = true;
445 }
446 }
447
448 if($invalidFile) {
449 if (isset($file['tmp_name'])) {
450 unlink($element->getDestPath . $file['tmp_name']);
451 unset($form->files[$name]);
452 }
453 } else if($name !== '') {
454 self::$submittedData[$name] = $value;
455 }
456 }
457 }
458 $_SESSION["pfbc"][$id]["values"] = self::$submittedData;
459
460
461 if (function_exists(self::$submittedID.'_validate')) {
462 $valid = call_user_func(self::$submittedID.'_validate', $valid, self::$submittedID, self::$submittedData, $form);
463 }
464 $valid = apply_filters('accua_form_validate', $valid, self::$submittedID, self::$submittedData, $form);
465
466 asort($form->validate_functions);
467 foreach($form->validate_functions as $func => $priority){
468 if (function_exists($func)) {
469 $valid = call_user_func($func, $valid, self::$submittedID, self::$submittedData, $form);
470 }
471 }
472
473 if ($valid) {
474 if (function_exists(self::$submittedID.'_submit')) {
475 call_user_func(self::$submittedID.'_submit', self::$submittedID, self::$submittedData, $form);
476 }
477 do_action('accua_form_submit', self::$submittedID, self::$submittedData, $form);
478 asort($form->submit_functions);
479 foreach($form->submit_functions as $func => $priority){
480 if (function_exists($func)) {
481 call_user_func($func, self::$submittedID, self::$submittedData, $form);
482 }
483 }
484 }
485
486 /*If no validation errors were found, the form's session values are cleared.*/
487 /*
488 if($valid) {
489 if($clearValues)
490 self::clearValues($id);
491 self::clearErrors($id);
492 }
493 */
494
495 //TODO: Should i save here?
496 //$form->save();
497 //$_SESSION["pfbc"][$id]["form"] = serialize($form);
498
499 $form->restore_language();
500
501 if ($valid && self::$rawData['_AccuaForm_jsuuid'] ) {
502 set_transient('accuaformsub_'.self::$rawData['_AccuaForm_jsuuid'], array(
503 'buildID' => self::$submittedBuildID,
504 'form' => self::$submittedForm,
505 'submittedMessages' => self::$submittedMessages,
506 ), 86400);
507 }
508
509 return self::$valid = (bool)$valid;
510 }
511
512 public static function getSubmittedData() {
513 self::isValid();
514 return self::$submittedData;
515 }
516
517 public static function getSumbittedID() {
518 trigger_error('Use getSubmittedID() instead', (defined('E_USER_DEPRECATED')?E_USER_DEPRECATED:E_USER_NOTICE));
519 return self::getSubmittedID();
520 }
521
522 public static function getSubmittedID() {
523 if (self::isSubmit()) {
524 return self::$submittedID;
525 } else {
526 return null;
527 }
528 }
529
530 public static function getSubmittedForm() {
531 if (self::isSubmit()) {
532 return self::$submittedForm;
533 } else {
534 return null;
535 }
536 }
537
538 /*This method restores the serialized form instance.*/
539 protected static function wp_recover($hash,$iv,$data) {
540 /*
541 if(!empty($_SESSION["pfbc"][$id]["form"]))
542 return unserialize($_SESSION["pfbc"][$id]["form"]);
543 */
544 /*
545 $storename = 'accua_form_' . md5($id);
546 if ($stored = get_transient($storename)) {
547 return unserialize($stored);
548 }
549 */
550
551 $keys = get_option('accua_form_api_keys', array());
552 @ $hash = base64_decode($hash);
553 @ $iv = base64_decode($iv);
554 @ $data = base64_decode($data);
555
556 if (!($hash && $iv && $data)) {
557 return;
558 }
559
560 if (!class_exists('Crypt_Hash')) {
561 require_once('phpseclib-crypt/Hash.php');
562 }
563 $hasher = new Crypt_Hash('sha1');
564 $hasher->setKey($keys['hash']);
565 @ $hash2 = $hasher->hash($iv.$data);
566
567 if ($hash !== $hash2) {
568 return;
569 }
570
571 if (!class_exists('Crypt_AES')) {
572 require_once('phpseclib-crypt/AES.php');
573 }
574
575 $cipher = new Crypt_AES();
576 $cipher->setPassword($keys['aes']);
577 @ $cipher->setIV($iv);
578 @ $data = $cipher->decrypt($data);
579
580 if ($data) {
581 @ $form = unserialize($data);
582 if ($form) {
583 return $form;
584 }
585 }
586 }
587
588 protected function wp_save() {
589 /*
590 $storename = 'accua_form_' . md5($this->buildID);
591 //$serialized = isset($_SESSION["pfbc"][$this->buildID]["form"]) ? $_SESSION["pfbc"][$this->buildID]["form"] : serialize($this);
592 $serialized = serialize($this);
593 set_transient($storename, $serialized, 2764800); // 32 days
594 */
595
596 if (!class_exists('Crypt_Hash')) {
597 require_once('phpseclib-crypt/Hash.php');
598 }
599 if (!class_exists('Crypt_AES')) {
600 require_once('phpseclib-crypt/AES.php');
601 }
602
603 $keys = get_option('accua_form_api_keys', array());
604 if (!(isset($keys['aes']) && isset($keys['hash']))) {
605 accua_form_api_install();
606 $keys = get_option('accua_form_api_keys', array());
607 }
608
609 $data = serialize($this);
610 $iv = wp_generate_password(64,true,true);
611
612 $cipher = new Crypt_AES();
613 $cipher->setPassword($keys['aes']);
614 $cipher->setIV($iv);
615 $data = $cipher->encrypt($data);
616
617 $hasher = new Crypt_Hash('sha1');
618 $hasher->setKey($keys['hash']);
619 $hash = $hasher->hash($iv.$data);
620
621 $ret = array(
622 '_AccuaForm_hash' => base64_encode($hash),
623 '_AccuaForm_iv' => base64_encode($iv),
624 '_AccuaForm_data' => base64_encode($data),
625 );
626 if (isset($_SESSION["pfbc"][$this->buildID]["values"])) {
627 $_SESSION["pfbc"][$this->buildID]["values"] = $ret + $_SESSION["pfbc"][$this->buildID]["values"];
628 }
629 $this->setValues($ret);
630 return $ret;
631 }
632
633 public function getLocale() {
634 return $this->locale;
635 }
636
637 public function getLanguage() {
638 return $this->language;
639 }
640
641 public function addValidateFunction($function_name, $priority = 0) {
642 $this->validate_functions[$function_name] = $priority;
643 }
644
645 public function addSubmitFunction($function_name, $priority = 0) {
646 $this->submit_functions[$function_name] = $priority;
647 }
648
649 public static function getSubmittedMessages(){
650 return self::$submittedMessages;
651 }
652
653 public static function setSubmittedMessages($msg){
654 return self::$submittedMessages = $msg;
655 }
656
657 public static function appendSubmittedmessages($msg){
658 return self::$submittedMessages .= $msg;
659 }
660
661 protected static function get_anchor_id($id) {
662 static $used_anchor_id = array();
663 if (substr($id, 0, 14) === '__accua-form__') {
664 $id = substr($id, 14);
665 }
666 $id = preg_replace('/[^a-zA-Z0-9]+/m','_',$id);
667 if (empty($used_anchor_id[$id])) {
668 $used_anchor_id[$id] = 1;
669 } else {
670 $used_anchor_id[$id]++;
671 $id = $id . '-' . $used_anchor_id[$id];
672 }
673 return $id;
674 }
675
676 public function render($returnHTML = false) {
677 $this->wp_save();
678 if($returnHTML) {
679 ob_start();
680 }
681 parent::render(false);
682 if (!empty($this->accua_ajax)) {
683 $ajax_url = _accua_forms_json_encode(admin_url('admin-ajax.php?action=accua_form_submit'));
684 $submit_fail_message = _accua_forms_json_encode('<li>'.__('Unable to submit the form, please retry', 'contact-forms').'</li>');
685 $required_message = _accua_forms_json_encode(__('Please fill in all required fields', 'contact-forms'));
686 $valid_mail_message = _accua_forms_json_encode(__('You have to enter a valid email address where required', 'contact-forms'));
687 $js_buildid = preg_replace('/[^a-zA-Z0-9_]/m','_',$this->buildID);
688 $formid = $this->getId();
689 $hostname = _accua_forms_json_encode($_SERVER['SERVER_NAME']);
690
691 $post_url = _accua_forms_json_encode($this->stats['url']);
692 $js_ga_track = _accua_forms_json_encode($this->ga_track);
693
694 $anchor_id = _accua_forms_json_encode(self::get_anchor_id($this->formID));
695
696 echo <<<JS
697 <script type="text/javascript">
698 <!--
699 var _handle_ajax_submit_{$js_buildid} = function() {return true;}
700 var _handle_ajax_submit_complete_{$js_buildid} = function() {return false;}
701 var _handle_ajax_submit_timeout_{$js_buildid} = function() {return false;}
702 var _handle_ajax_submit_message_{$js_buildid} = function() {}
703 var _handle_ajax_submit_response_{$js_buildid} = function() {}
704
705 jQuery(function($) {
706 var thisform = $("#{$this->buildID}");
707 var ajax_enabled = {$hostname} == location.hostname ;
708 var anchor_id = $anchor_id ;
709
710 var response_messages = $("#_response_messages_{$this->buildID}");
711 if (! response_messages.length) {
712 thisform.before('\\x3Ca id="formSubmitSuccess-'+anchor_id+'" name="formSubmitSuccess-'+anchor_id+'" /\\x3E');
713 response_messages = $('\\x3Cdiv id="_response_messages_{$this->buildID}" class="accua-form-messages"\\x3E\\x3C/div\\x3E');
714 thisform.before(response_messages);
715 }
716 var throbbler = $("\\x3Cspan class='accua_form_api_throbbler'\\x3E\\x3C/span\\x3E");
717
718 var _ajax_submitting_{$js_buildid} = false;
719 var timeout_handler = false;
720 var timeout_count = 0;
721 var fail_count = 0;
722 var disabled_fields = false;
723
724 var jsuuid_field = $('input[name="_AccuaForm_jsuuid"]', thisform);
725 var jsuuid = jsuuid_field.val();
726 if (jsuuid == '') {
727 var chars = '0123456789abcdefghijklmnopqrstuvwxyz'.split('');
728 var radix = chars.length
729 for (i = 0; i < 25; i++) {
730 jsuuid += chars[0 | Math.random()*radix];
731 }
732 jsuuid_field.val(jsuuid);
733 }
734
735 var ga_track = {$js_ga_track} ;
736 var ga_event, ga_submit_event, ga_field_event, ga_field_events_fired = {};
737 ga_event = function(eventCategory, eventAction){
738 if (typeof window.gtag == 'function') {
739 window.gtag('event', eventAction, {'event_category': eventCategory, 'event_label': ga_track.title});
740 } else if (window.dataLayer && (typeof window.dataLayer.push == 'function')) {
741 dataLayer.push({'event': 'ContactForms', 'eventAction': eventAction, 'eventCategory': eventCategory, 'eventLabel': ga_track.title});
742 //backward compatibility
743 var gtag = function(){window.dataLayer.push(arguments);}
744 gtag('event', eventAction, {'event_category': eventCategory, 'event_label': ga_track.title});
745 } else if (typeof window.ga == 'function') {
746 window.ga('send', 'event', eventCategory, eventAction, ga_track.title);
747 } else if (window._gaq && (typeof window._gaq.push == 'function')) {
748 window._gaq.push(['_trackEvent', eventCategory, eventAction, ga_track.title]);
749 } else if (window.gaq && (typeof window.gaq.push == 'function')) {
750 window.gaq.push(['_trackEvent', eventCategory, eventAction, ga_track.title]);
751 } else if (window.pageTracker && (typeof window.pageTracker._trackEvent == 'function')) {
752 window.pageTracker._trackEvent(eventCategory, eventAction, ga_track.title);
753 }
754 }
755 ga_submit_event = function(eventAction){
756 if (ga_track.track_submit) {
757 ga_event('ContactFormsSubmit', eventAction);
758 }
759 thisform.trigger('ContactFormsSubmit', [eventAction]);
760 }
761 ga_field_event = function(field_name){
762 if (!ga_field_events_fired[field_name]){
763 if (ga_track.track_fields) {
764 ga_event('ContactFormsFieldFilledIn', field_name);
765 ga_field_events_fired[field_name] = true;
766 }
767 thisform.trigger('ContactFormsFieldFilledIn', [field_name]);
768 }
769 }
770 $('input, textarea, select', thisform).change(function(){
771 ga_field_event($(this).attr('name'));
772 });
773
774 var show_error_messages = function(message) {
775 thisform.append('\\x3Cdiv class="pfbc-error ui-state-error ui-corner-all"\\x3E\\x3Cul\\x3E' + message + '\\x3C/ul\\x3E\\x3C/div\\x3E');
776 }
777
778 _handle_ajax_submit_{$js_buildid} = function() {
779 if (_ajax_submitting_{$js_buildid}) {
780 return false;
781 }
782
783 JS;
784 $this->error->clear();
785 echo <<<JS
786
787 var valid_empty = true;
788 var valid_mail = true;
789
790 $("#{$this->buildID} .pfbc-element").removeClass('pfbc-invalid');
791
792 $('.accuaforms-field-required', thisform).each(function(){
793 var field = $(this);
794 var type = field.attr('type');
795
796 if (type === 'checkbox' || type === 'radio') {
797 if ($("[name='"+field.attr("name")+"']:checked", "#{$this->buildID}").length > 0) {
798 return true;
799 }
800 } else {
801 var val = field.val();
802 if (typeof(val) == "string") {
803 if (! val.match(/^\s*$/)) {
804 return true;
805 }
806 } else if ((typeof(val) == "object") && val && (val.length > 0)) {
807 return true;
808 } else if (val) {
809 return true;
810 }
811 }
812
813 valid_empty = false;
814 field.parents("#{$this->buildID} .pfbc-element").addClass('pfbc-invalid');
815 });
816
817 $('.pfbc-textbox[type="email"]', thisform).each(function(){
818 var field = $(this);
819
820 if (field.val().match(/^\s*$/)) {
821 return true;
822 }
823
824 if (field.val().match( /^([a-zA-Z0-9_.+%-])+@(([a-zA-Z0-9-])+\.)+([a-zA-Z0-9])+$/ )) {
825 return true;
826 }
827
828 valid_mail = false;
829 field.parents("#{$this->buildID} .pfbc-element").addClass('pfbc-invalid');
830
831 });
832
833 if (valid_empty && valid_mail) {
834 thisform.append(throbbler);
835 _ajax_submitting_{$js_buildid} = true;
836 $('input[name="_AccuaForm_tentatives"]', thisform).val(fail_count);
837 disabled_fields = $("input, textarea, button, select", thisform).not('[type="submit"]').not(':disabled');
838 disabled_fields.attr('readonly','readonly');
839 timeout_count = 0;
840 if (ajax_enabled) {
841 $("#submit_target_{$js_buildid}").attr('src','').removeAttr('src');
842 timeout_handler = setTimeout(_handle_ajax_submit_timeout_{$js_buildid}, 5000);
843 }
844 return true;
845 } else {
846 ga_submit_event('formSubmitInvalid');
847 location.href = "#formSubmitInvalid-"+anchor_id;
848 var message = '';
849 if (!valid_empty) {
850 message += '\\x3Cli\\x3E' + $required_message + '\\x3C/li\\x3E';
851 }
852 if (!valid_mail) {
853 message += '\\x3Cli\\x3E' + $valid_mail_message + '\\x3C/li\\x3E';
854 }
855 show_error_messages(message);
856 return false;
857 }
858 }
859
860
861 _handle_ajax_submit_timeout_{$js_buildid} = function() {
862 if (_ajax_submitting_{$js_buildid}) {
863 if (timeout_count < 60) {
864 timeout_count++;
865 timeout_handler = setTimeout(_handle_ajax_submit_timeout_{$js_buildid}, 500);
866 _handle_ajax_submit_complete_{$js_buildid}();
867 } else {
868 timeout_handler = false;
869 _handle_ajax_submit_complete_{$js_buildid}();
870 if (_ajax_submitting_{$js_buildid}) {
871 _handle_ajax_submit_response_{$js_buildid}(false);
872 }
873 }
874 }
875 }
876
877 _handle_ajax_submit_complete_{$js_buildid} = function() {
878 if (_ajax_submitting_{$js_buildid}) {
879 var response = false;
880 try {
881 var responsedoc = frames['submit_target_{$js_buildid}'].document;
882 if (responsedoc.getElementById("accua-form-ajax-response-loaded")) {
883 response = $.parseJSON(responsedoc.getElementById("accua-form-ajax-response").innerHTML);
884 }
885 } catch (err) {
886 response = false;
887 }
888 if (response) {
889 return _handle_ajax_submit_response_{$js_buildid} (response);
890 }
891 }
892 }
893
894 _handle_ajax_submit_message_{$js_buildid} = function(message) {
895 if (_ajax_submitting_{$js_buildid}) {
896 var response = false;
897 try {
898 response = $.parseJSON(message.data);
899 if (response.jsuuid != jsuuid || response.buildID != "{$this->buildID}") {
900 response = false;
901 }
902 } catch (err) {
903 response = false;
904 }
905 if (response) {
906 return _handle_ajax_submit_response_{$js_buildid} (response);
907 }
908 }
909 }
910
911 _handle_ajax_submit_response_{$js_buildid} = function(response) {
912 if (_ajax_submitting_{$js_buildid}) {
913 if(response && typeof(response) == "object" && typeof(response.submitted) == "boolean") {
914 response_messages.html(response.messages);
915 if (response.submitted) {
916 if (response.valid) {
917 ga_submit_event('formSubmitSuccess');
918 location.href = "#formSubmitSuccess-"+anchor_id;
919 JS;
920 /*A callback function can be specified to handle any post submission events.*/
921 if(!empty($this->ajaxCallback)) {
922 echo $this->ajaxCallback, "(response);";
923 } else {
924 echo "$('#{$this->buildID}').hide();";
925 }
926 echo <<<JS
927 } else {
928 ga_submit_event('formSubmitInvalid');
929 location.href = "#formSubmitInvalid-"+anchor_id;
930 JS;
931 if (method_exists($this->error,'applyAjaxErrorResponseUsingShowErrorMessages')) {
932 $this->error->applyAjaxErrorResponseUsingShowErrorMessages();
933 } else {
934 $this->error->applyAjaxErrorResponse();
935 }
936 echo <<<JS
937
938 for (var name in response.files) {
939 $(".pfbc-fieldwrap:has(input[type='file'][name='"+name+"'])", thisform).html(response.files[name]);
940 }
941
942 $("input[name='_AccuaForm_hash']",thisform).val(response._AccuaForm_hash);
943 $("input[name='_AccuaForm_iv']", thisform).val(response._AccuaForm_iv);
944 $("input[name='_AccuaForm_data']",thisform).val(response._AccuaForm_data);
945
946 disabled_fields.removeAttr('readonly');
947 }
948 }
949 } else {
950 ga_submit_event('formSubmitError');
951 location.href = "#formSubmitError-"+anchor_id;
952 fail_count++;
953 if (fail_count > 2) {
954 ajax_enabled = false;
955 thisform.attr("action", {$post_url} );
956 thisform.removeAttr("target");
957 $('input[name="_AccuaForm_submit_method"]', thisform).val('fallback');
958 }
959 show_error_messages( $submit_fail_message );
960 }
961 $('.accua_forms_show_recaptcha_button', thisform).click();
962 if (((typeof accuaform_recaptcha2_initialized) != 'undefined') && accuaform_recaptcha2_initialized) {
963 $('.accua_forms_recaptcha2_container', thisform).each(function(){
964 accua_forms_reload_recaptcha2($(this).attr('id'));
965 });
966 }
967 throbbler.remove();
968 _ajax_submitting_{$js_buildid} = false;
969 if (timeout_handler) {
970 clearTimeout(timeout_handler);
971 timeout_handler = false;
972 }
973 }
974 }
975
976 if (ajax_enabled) {
977 thisform.attr("action", {$ajax_url} );
978 thisform.attr("target","submit_target_{$js_buildid}");
979 try {
980 window.addEventListener('message', _handle_ajax_submit_message_{$js_buildid}, false);
981 } catch (e) { }
982 $('input[name="_AccuaForm_submit_method"]', thisform).val('iframe');
983 } else {
984 thisform.attr("action", {$post_url} );
985 }
986 thisform.attr("onsubmit","return _handle_ajax_submit_{$js_buildid}()");
987 });
988 // -->
989 </script>
990 <iframe id="submit_target_{$js_buildid}" title="" name="submit_target_{$js_buildid}" onload="_handle_ajax_submit_complete_{$js_buildid}()" onerror="_handle_ajax_submit_complete_{$js_buildid}()" style="width:0;height:0;border:0px solid #fff"></iframe>
991 JS;
992 }
993
994 echo <<<JSREFERRER
995 <script type="text/javascript">
996 <!--
997 jQuery(function($){
998 var referrerfield = $("#{$this->buildID} input[name='_AccuaForm_referrer']");
999 if (referrerfield.val() == '') {
1000 referrerfield.val(document.referrer);
1001 }
1002 $("#{$this->buildID} input[name='_AccuaForm_user_agent']").val(navigator.userAgent);
1003 $("#{$this->buildID} input[name='_AccuaForm_platform']").val(navigator.platform);
1004 });
1005 // -->
1006 </script>
1007 JSREFERRER;
1008
1009 if($returnHTML) {
1010 $html = ob_get_contents();
1011 ob_end_clean();
1012 return $html;
1013 }
1014 }
1015
1016 protected function renderJS() {
1017 $this->renderJSFiles();
1018
1019 echo <<<JS
1020 <script type="text/javascript">
1021 <!--
1022
1023 JS;
1024 $this->view->renderJS();
1025 foreach($this->elements as $element)
1026 $element->renderJS();
1027
1028 $id = $this->attributes["id"];
1029
1030 echo 'jQuery(document).ready(function() {';
1031 /*jQuery is used to set the focus of the form's initial element.*/
1032 if(!in_array("focus", $this->prevent))
1033 echo 'jQuery("#', $id, ' :input:visible:enabled:first").focus();';
1034
1035 $this->view->jQueryDocumentReady();
1036 foreach($this->elements as $element) {
1037 $element->jQueryDocumentReady();
1038 }
1039
1040 /*For ajax, an anonymous onsubmit javascript function is bound to the form using jQuery. jQuery's
1041 serialize function is used to grab each element's name/value pair.* /
1042 if(!empty($this->ajax)) {
1043 echo 'jQuery("#', $id, '").bind("submit", function() {';
1044 $this->error->clear();
1045 echo <<<JS
1046 jQuery.ajax({
1047 url: "{$this->attributes["action"]}",
1048 type: "{$this->attributes["method"]}",
1049 data: jQuery("#$id").serialize(),
1050 success: function(response) {
1051 if(response != undefined && typeof response == "object" && response.errors) {
1052 JS;
1053 $this->error->applyAjaxErrorResponse();
1054 echo <<<JS
1055 jQuery("html, body").animate({ scrollTop: jQuery("#$id").offset().top }, 500 );
1056 }
1057 else {
1058 JS;
1059 /*A callback function can be specified to handle any post submission events.* /
1060 if(!empty($this->ajaxCallback))
1061 echo $this->ajaxCallback, "(response);";
1062 echo <<<JS
1063 }
1064 }
1065 });
1066 return false;
1067 });
1068
1069 JS;
1070 }
1071 */
1072 echo <<<JS
1073 });
1074 // -->
1075 </script>
1076 JS;
1077 }
1078
1079 protected function renderCSS() {
1080
1081 }
1082
1083 public function getAjax() {
1084 return $this->accua_ajax;
1085 }
1086
1087 public function getFile($fieldname) {
1088 if (isset($this->files[$fieldname])) {
1089 return $this->files[$fieldname];
1090 }
1091 }
1092
1093 public function renameFile($fieldname, $newname) {
1094 if (isset($this->files[$fieldname])) {
1095 $file = $this->files[$fieldname];
1096 @ $renamed = rename($file['dest_path'].$file['tmp_name'], $file['dest_path'].$newname);
1097 if ($renamed) {
1098 $this->files[$fieldname]['new_name'] = $newname;
1099 return true;
1100 }
1101 }
1102 return false;
1103 }
1104
1105 public static function renderAjaxErrorResponse($unused = 'pfbc') {
1106 if ($form = self::$submittedForm) {
1107 $form->error->setForm($form);
1108 return $form->error->renderAjaxErrorResponse();
1109 }
1110 }
1111
1112 public static function getAjaxErrorResponse() {
1113 if ($form = self::$submittedForm) {
1114 $form->error->setForm($form);
1115 return $form->error->getAjaxErrorResponse();
1116 }
1117 }
1118
1119 public function setFormError($errors, $element = '') {
1120 return self::setError($this->buildID, $errors, $element);
1121 }
1122
1123 public function setClass($class) {
1124 if(!empty($this->attributes["class"]))
1125 $this->attributes["class"] .= " " . $class;
1126 else
1127 $this->attributes["class"] = $class;
1128 }
1129
1130 public static function ajaxSubmit() {
1131 $ret = array(
1132 'valid' => false,
1133 'messages' => self::getSubmittedMessages(),
1134 'jsuuid' => self::$rawData['_AccuaForm_jsuuid'],
1135 'buildID' => self::$submittedBuildID,
1136 'files' => array(),
1137 );
1138 if ($ret['submitted'] = self::isSubmit()){
1139 if ($ret['valid'] = self::isValid()) {
1140
1141 } else {
1142 $ret['errors'] = self::getAjaxErrorResponse();
1143 }
1144 $form = self::$submittedForm;
1145 foreach ($form->files as $fieldname => $file) {
1146 if (!empty($file['name'])) {
1147 $ret['files'][$fieldname] = $form->getElementByName($fieldname)->getAlreadySubmittedText();
1148 }
1149 }
1150 $ret += $form->wp_save();
1151 }
1152 return $ret;
1153 }
1154 }
1155