PluginProbe
Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder / V3.3.2
Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder vV3.3.2
V3.3.2 3.3.1 V-3.3.0 3.2.2 3.2.1 3.2.0 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 V3.0.3 V3.0.2 -3.0.1 V_3.0.0 1.1.1 1.1.8 1.2 1.3 1.4 1.4.18 1.5.2 1.9 2.0 2.10.0 All 139 releases
← All changes | includes/Frontend/Form/FrontendFormHandler.php +55 -24 3.3.1 → V3.3.2 View file →
@@ -8,8 +8,9 @@
8 8
9 9 use BitCode\BitForm\Admin\Form\AdminFormHandler;
10 10 use BitCode\BitForm\Admin\Form\FrontEndScriptGenerator;
11 11 use BitCode\BitForm\Admin\Form\Helpers;
12 +use BitCode\BitForm\Core\Cryptography\Cryptography;
12 13 use BitCode\BitForm\Core\Database\FormEntryMetaModel;
13 14 use BitCode\BitForm\Core\Database\FormModel;
14 15 use BitCode\BitForm\Core\Form\FormManager;
15 16 use BitCode\BitForm\Core\Integration\IntegrationHandler;
@@ -40,26 +41,32 @@
40 41 // their formID), before wp_print_footer_scripts at 20.
41 42 add_action('wp_footer', [$this, 'generateJS'], 15);
42 43 }
43 44
44 - private function validPassowordResetToken($token, $userID, $formId)
45 + /**
46 + * A reset form opened from a used or expired link cannot succeed, so show why instead of
47 + * the form. Returns the notice markup, or '' when the link is fine or the form is not a
48 + * reset form. Rendered in place of the form (the old exit() cut the page off mid-theme).
49 + *
50 + * @param string $token key from the reset link
51 + * @param string $userID user ID from the reset link
52 + * @param int $formId form being rendered
53 + *
54 + * @return string
55 + */
56 + private function invalidPasswordResetNotice($token, $userID, $formId)
45 57 {
46 58 $existResetInteg = (new IntegrationHandler($formId))->getAllIntegration('wp_user_auth', 'wp_auth', 1);
47 - if (!is_wp_error($existResetInteg) && count($existResetInteg) > 0) {
48 - if ('reset' === $existResetInteg[0]->integration_name) {
49 - $user = get_userdata($userID);
50 - if ($user) {
51 - $validKey = check_password_reset_key($token, $user->user_login);
52 - if (is_wp_error($validKey)) {
53 - echo "<div id='bf-resp' style='display:grid;justify-content:center;color:#860000;'>This password reset token is invalid.</div>";
54 - exit();
55 - }
56 - } else {
57 - echo "<div id='bf-resp' style='display:grid;justify-content:center;color:#860000;'>Invalid User!!</div>";
58 - exit();
59 - }
60 - }
59 + if (is_wp_error($existResetInteg) || empty($existResetInteg) || 'reset' !== $existResetInteg[0]->integration_name) {
60 + return '';
61 61 }
62 + $user = get_userdata((int) $userID);
63 + if ($user && !is_wp_error(check_password_reset_key($token, $user->user_login))) {
64 + return '';
65 + }
66 + return "<div id='bf-resp' role='alert' style='display:grid;justify-content:center;color:#860000;'>"
67 + . esc_html__('This password reset link is invalid or has expired. Please request a new one.', 'bit-form')
68 + . '</div>';
62 69 }
63 70
64 71 private function getJSFileSrc($postId)
65 72 {
@@ -410,10 +417,13 @@
410 417 /* translators: %s: form ID */
411 418 return sprintf(__('#%s no. Form doesn\'t exists', 'bit-form'), $formID);
412 419 }
413 420
414 - // Add-ons may detect whether the current visitor is resuming an abandoned entry.
415 - $isAbandoned = (bool) apply_filters('bitform_is_abandoned_entry', false, $formID, $entryId, $atts);
421 + // Add-ons return the id of the abandoned entry this visitor can resume. A bare
422 + // true (older Pro) carries no id, so nothing is restored rather than entry #1.
423 + $abandonedEntryId = apply_filters('bitform_is_abandoned_entry', false, $formID, $entryId, $atts);
424 + $abandonedEntryId = (!is_bool($abandonedEntryId) && is_numeric($abandonedEntryId)) ? (int) $abandonedEntryId : 0;
425 + $isAbandoned = $abandonedEntryId > 0;
416 426
417 427 FrontendHelpers::setBfFrontendFormIds($formID);
418 428 $bfFrontendFormIds = FrontendHelpers::$bfFrontendFormIds;
419 429 $shortCodeCounter = count($bfFrontendFormIds);
@@ -433,9 +443,13 @@
433 443 }
434 444
435 445 // Read-only: password reset token from URL for display-time validation. No state written until form is submitted.
436 446 if (!empty($_GET['token']) && !empty($_GET['id'])) {
437 - $this->validPassowordResetToken(sanitize_text_field(wp_unslash($_GET['token'])), sanitize_text_field(wp_unslash($_GET['id'])), $formID);
447 + $resetNotice = $this->invalidPasswordResetNotice(sanitize_text_field(wp_unslash($_GET['token'])), sanitize_text_field(wp_unslash($_GET['id'])), $formID);
448 + if ('' !== $resetNotice) {
449 + ob_end_clean();
450 + return $resetNotice;
451 + }
438 452 }
439 453
440 454 $previousValue = $this->getValuesFromQueryParams();
441 455 $errorMessages = []; // delete
@@ -616,14 +630,19 @@
616 630 if (isset($additional->enabled->validateFocusLost)) {
617 631 $bitFormFrontArr['validateFocusLost'] = true;
618 632 }
619 633
620 - if (!empty($isAbandoned)) {
634 + if ($isAbandoned) {
621 635 // One visitor's typed values, so this response must not be page-cached.
622 - $bitFormFrontArr['oldValues'] = $this->getFieldsValue($formID, $isAbandoned);
636 + $bitFormFrontArr['oldValues'] = $this->getFieldsValue($formID, $abandonedEntryId);
623 637 self::markResponseUncacheable();
624 638 if (empty($entryId)) {
625 - $bitFormFrontArr['entryId'] = $entryId;
639 + // Later draft saves must update this entry, not start a new one each time.
640 + $bitFormFrontArr['entryId'] = $abandonedEntryId;
641 + $entryToken = Cryptography::encrypt($abandonedEntryId, Helpers::getBitformSalt());
642 + if (is_string($entryToken)) {
643 + $bitFormFrontArr['entryToken'] = $entryToken;
644 + }
626 645 }
627 646 }
628 647
629 648 $formInfo = $FrontendFormManager->getFormInfo();
@@ -890,8 +909,12 @@
890 909 } else {
891 910 $metaVal = implode(BITFORMS_BF_SEPARATOR, $metaVal);
892 911 }
893 912 }
913 + // A restored draft never gets the password back; the visitor types it again.
914 + if (isset($formFields[$metaKey]['type']) && 'password' === $formFields[$metaKey]['type']) {
915 + continue;
916 + }
894 917 if (!isset($fldsData->{$metaKey})) {
895 918 $fldsData->{$metaKey} = '';
896 919 }
897 920 $fldsData->{$metaKey} = $metaVal;
@@ -944,8 +967,16 @@
944 967 } else {
945 968 $metaVal = implode(BITFORMS_BF_SEPARATOR, $metaVal);
946 969 }
947 970 }
971 + if (property_exists($fields, $metaKey) && 'password' === $fields->{$metaKey}->typ) {
972 + // Never hand a stored password back to the browser; blank keeps it on update.
973 + $fields->{$metaKey}->val = '';
974 + if ('' !== (string) $metaValue->meta_value && isset($fields->{$metaKey}->valid) && is_object($fields->{$metaKey}->valid)) {
975 + $fields->{$metaKey}->valid->req = false;
976 + }
977 + continue;
978 + }
948 979 if (property_exists($fields, $metaKey)) {
949 980 $fields->{$metaKey}->val = $metaVal;
950 981 if ('file-up' === $fields->{$metaKey}->typ || 'advanced-file-up' === $fields->{$metaKey}->typ) {
951 982 $fields->{$metaKey}->val = $metaValue->meta_value;
@@ -1027,9 +1058,9 @@
1027 1058 $formUpdateVersion = get_option('bitform_form_update_version');
1028 1059 if (!wp_style_is('bitform-style-' . $newFormId) && is_readable(BITFORMS_CONTENT_DIR . '/form-styles/bitform-' . $newFormId . '.css')) {
1029 1060 wp_enqueue_style(
1030 1061 'bitform-style-' . $newFormId,
1031 - BITFORMS_UPLOAD_BASE_URL . "/form-styles/bitform-{$newFormId}.css",
1062 + FrontendHelpers::styleSrc("form-styles/bitform-{$newFormId}.css"),
1032 1063 [],
1033 1064 $formUpdateVersion
1034 1065 );
1035 1066 if ($isPageBuilder) {
@@ -1039,9 +1070,9 @@
1039 1070 }
1040 1071 if (!wp_style_is('bitform-style-custom-' . $formID) && is_readable(BITFORMS_CONTENT_DIR . '/form-styles/bitform-custom-' . $formID . '.css')) {
1041 1072 wp_enqueue_style(
1042 1073 'bitform-style-custom-' . $formID,
1043 - BITFORMS_UPLOAD_BASE_URL . "/form-styles/bitform-custom-{$formID}.css",
1074 + FrontendHelpers::styleSrc("form-styles/bitform-custom-{$formID}.css"),
1044 1075 [],
1045 1076 $formUpdateVersion
1046 1077 );
1047 1078 if ($isPageBuilder) {
@@ -1054,9 +1085,9 @@
1054 1085 if (!wp_style_is('bitform-conversational-style-' . $formID) &&
1055 1086 is_readable(BITFORMS_CONTENT_DIR . "/form-styles/bitform-conversational-{$formID}.css")) {
1056 1087 wp_enqueue_style(
1057 1088 'bitform-conversational-style',
1058 - BITFORMS_UPLOAD_BASE_URL . "/form-styles/bitform-conversational-{$formID}.css",
1089 + FrontendHelpers::styleSrc("form-styles/bitform-conversational-{$formID}.css"),
1059 1090 [],
1060 1091 $formUpdateVersion
1061 1092 );
1062 1093 }