← All changes
|
includes/widgets/Form_Builder/helpers/Send_Email.php
+351
-0
51.1.2
→
51.1.86
View file →
| @@ -1,0 +1,351 @@ | ||
| 1 | +<?php | |
| 2 | + | |
| 3 | +namespace King_Addons; | |
| 4 | + | |
| 5 | +use King_Addons\Core; | |
| 6 | + | |
| 7 | +if (!defined('ABSPATH')) { | |
| 8 | + exit; | |
| 9 | +} | |
| 10 | + | |
| 11 | +class Send_Email | |
| 12 | +{ | |
| 13 | + | |
| 14 | + public function __construct() | |
| 15 | + { | |
| 16 | + add_action('wp_ajax_king_addons_form_builder_email', [$this, 'send_email']); | |
| 17 | + add_action('wp_ajax_nopriv_king_addons_form_builder_email', [$this, 'send_email']); | |
| 18 | + } | |
| 19 | + | |
| 20 | + public function send_email() | |
| 21 | + { | |
| 22 | + | |
| 23 | + $nonce = $_POST['nonce']; | |
| 24 | + | |
| 25 | + // Security fix: Generate nonce server-side instead of relying on client-provided nonce | |
| 26 | + $server_nonce = wp_create_nonce('king-addons-js'); | |
| 27 | + if (!wp_verify_nonce($nonce, 'king-addons-js')) { | |
| 28 | + return; | |
| 29 | + } | |
| 30 | + | |
| 31 | + Form_Builder_Security::guard_spam(); | |
| 32 | + | |
| 33 | + $message_body = []; | |
| 34 | + | |
| 35 | + // Security fix: Validate and sanitize form_content array | |
| 36 | + $form_content = isset($_POST['form_content']) && is_array($_POST['form_content']) ? $_POST['form_content'] : []; | |
| 37 | + | |
| 38 | + foreach ($form_content as $field) { | |
| 39 | + if (!is_array($field) || count($field) < 2) { | |
| 40 | + continue; // Skip malformed fields | |
| 41 | + } | |
| 42 | + | |
| 43 | + if ($field[0] === 'email') { | |
| 44 | + if (!is_email(sanitize_email($field[1]))) { | |
| 45 | + wp_send_json_error(array( | |
| 46 | + 'action' => 'king_addons_form_builder_email', | |
| 47 | + 'message' => esc_html__('Email provided is invalid', 'king-addons'), | |
| 48 | + 'status' => 'error' | |
| 49 | + )); | |
| 50 | + } | |
| 51 | + } | |
| 52 | + } | |
| 53 | + | |
| 54 | + | |
| 55 | + $content_type = get_option('king_addons_email_content_type_' . $_POST['king_addons_form_id']); | |
| 56 | + | |
| 57 | + $line_break = 'html' === $content_type ? '<br>' : "\n"; | |
| 58 | + | |
| 59 | + $email_fields = trim(get_option('king_addons_email_fields_' . $_POST['king_addons_form_id'])); | |
| 60 | + | |
| 61 | + if ($email_fields === '[all-fields]' || str_contains($email_fields, '[all-fields]')) { | |
| 62 | + | |
| 63 | + | |
| 64 | + $replace_shortcode_with_value = function ($matches) use ($form_content) { | |
| 65 | + $field_id = sanitize_text_field($matches[1]); | |
| 66 | + foreach ($form_content as $key => $value) { | |
| 67 | + $key_parts = explode('-', $key); | |
| 68 | + $last_part = end($key_parts); | |
| 69 | + if ($last_part === $field_id) { | |
| 70 | + // Security fix: Sanitize form field values before using in email | |
| 71 | + return is_array($value[1]) ? implode("\n", array_map('sanitize_text_field', $value[1])) : sanitize_text_field($value[1]); | |
| 72 | + } | |
| 73 | + } | |
| 74 | + return ''; | |
| 75 | + }; | |
| 76 | + | |
| 77 | + | |
| 78 | + $all_fields_content = []; | |
| 79 | + | |
| 80 | + foreach ($form_content as $key => $value) { | |
| 81 | + if (!is_array($value) || count($value) < 3) { | |
| 82 | + continue; // Skip malformed fields | |
| 83 | + } | |
| 84 | + // Security fix: Sanitize all field data before using in email | |
| 85 | + $field_label = sanitize_text_field($value[2]); | |
| 86 | + $field_value = is_array($value[1]) ? implode("\n", array_map('sanitize_text_field', $value[1])) : sanitize_text_field($value[1]); | |
| 87 | + $all_fields_content[] = $field_label . ': ' . $field_value; | |
| 88 | + } | |
| 89 | + $all_fields_content = implode("\n", $all_fields_content); | |
| 90 | + | |
| 91 | + | |
| 92 | + $processed_message = str_replace('[all-fields]', $all_fields_content, $email_fields); | |
| 93 | + | |
| 94 | + $processed_message = preg_replace_callback( | |
| 95 | + '/\[id="([^"]+)"\]/', | |
| 96 | + $replace_shortcode_with_value, | |
| 97 | + $processed_message | |
| 98 | + ); | |
| 99 | + } else { | |
| 100 | + | |
| 101 | + | |
| 102 | + $replace_shortcode_with_value = function ($matches) use ($form_content) { | |
| 103 | + $field_id = sanitize_text_field($matches[1]); | |
| 104 | + foreach ($form_content as $key => $value) { | |
| 105 | + if (!is_array($value) || count($value) < 3) { | |
| 106 | + continue; // Skip malformed fields | |
| 107 | + } | |
| 108 | + $key_parts = explode('-', $key); | |
| 109 | + $last_part = end($key_parts); | |
| 110 | + if ($last_part === $field_id) { | |
| 111 | + // Security fix: Sanitize form field data | |
| 112 | + $field_label = sanitize_text_field($value[2]); | |
| 113 | + $field_value = is_array($value[1]) ? implode("\n", array_map('sanitize_text_field', $value[1])) : sanitize_text_field($value[1]); | |
| 114 | + return $field_label . ': ' . $field_value; | |
| 115 | + } | |
| 116 | + } | |
| 117 | + return ''; | |
| 118 | + }; | |
| 119 | + | |
| 120 | + | |
| 121 | + $processed_message = preg_replace_callback( | |
| 122 | + '/\[id="([^"]+)"\]/', | |
| 123 | + $replace_shortcode_with_value, | |
| 124 | + $email_fields | |
| 125 | + ); | |
| 126 | + } | |
| 127 | + | |
| 128 | + $meta_keys = get_option('king_addons_meta_keys_' . $_POST['king_addons_form_id']); | |
| 129 | + $meta_fields = []; | |
| 130 | + | |
| 131 | + foreach ($meta_keys as $metadata_type) { | |
| 132 | + switch ($metadata_type) { | |
| 133 | + case 'date': | |
| 134 | + $meta_fields['date'] = [ | |
| 135 | + 'title' => esc_html__('Date', 'king-addons'), | |
| 136 | + 'value' => date_i18n(get_option('date_format')), | |
| 137 | + ]; | |
| 138 | + break; | |
| 139 | + | |
| 140 | + case 'time': | |
| 141 | + $meta_fields['time'] = [ | |
| 142 | + 'title' => esc_html__('Time', 'king-addons'), | |
| 143 | + 'value' => date_i18n(get_option('time_format')), | |
| 144 | + ]; | |
| 145 | + break; | |
| 146 | + | |
| 147 | + case 'page_url': | |
| 148 | + $meta_fields['page_url'] = [ | |
| 149 | + 'title' => esc_html__('Page URL', 'king-addons'), | |
| 150 | + | |
| 151 | + 'value' => get_option('king_addons_referrer_' . $_POST['king_addons_form_id']) ? get_option('king_addons_referrer_' . $_POST['king_addons_form_id']) : '', | |
| 152 | + ]; | |
| 153 | + break; | |
| 154 | + | |
| 155 | + case 'page_title': | |
| 156 | + $meta_fields['page_title'] = [ | |
| 157 | + 'title' => esc_html__('Page Title', 'king-addons'), | |
| 158 | + | |
| 159 | + 'value' => get_option('king_addons_referrer_title_' . $_POST['king_addons_form_id']) ? get_option('king_addons_referrer_title_' . $_POST['king_addons_form_id']) : '', | |
| 160 | + ]; | |
| 161 | + break; | |
| 162 | + | |
| 163 | + case 'user_agent': | |
| 164 | + $meta_fields['user_agent'] = [ | |
| 165 | + 'title' => esc_html__('User Agent', 'king-addons'), | |
| 166 | + 'value' => isset($_SERVER['HTTP_USER_AGENT']) ? sanitize_textarea_field(wp_unslash($_SERVER['HTTP_USER_AGENT'])) : '', | |
| 167 | + ]; | |
| 168 | + break; | |
| 169 | + | |
| 170 | + case 'remote_ip': | |
| 171 | + $meta_fields['remote_ip'] = [ | |
| 172 | + 'title' => esc_html__('Remote IP', 'king-addons'), | |
| 173 | + 'value' => Core::getClientIP(), | |
| 174 | + ]; | |
| 175 | + break; | |
| 176 | + | |
| 177 | + case 'credit': | |
| 178 | + $meta_fields['credit'] = [ | |
| 179 | + 'title' => esc_html__('Powered by', 'king-addons'), | |
| 180 | + 'value' => esc_html__('King Addons', 'king-addons'), | |
| 181 | + ]; | |
| 182 | + break; | |
| 183 | + } | |
| 184 | + } | |
| 185 | + | |
| 186 | + $email_meta = []; | |
| 187 | + | |
| 188 | + foreach ($meta_fields as $key => $value) { | |
| 189 | + $email_meta[] = $value['title'] . ': ' . $value['value']; | |
| 190 | + } | |
| 191 | + | |
| 192 | + $to = get_option('king_addons_email_to_' . $_POST['king_addons_form_id']); | |
| 193 | + | |
| 194 | + $to = preg_replace_callback( | |
| 195 | + '/\[id="(\w+)"\]/', | |
| 196 | + function ($matches) { | |
| 197 | + return $this->get_field_value($matches[1]); | |
| 198 | + }, | |
| 199 | + $to | |
| 200 | + ); | |
| 201 | + | |
| 202 | + $subject = get_option('king_addons_email_subject_' . $_POST['king_addons_form_id']); | |
| 203 | + | |
| 204 | + $subject = preg_replace_callback( | |
| 205 | + '/\[id="(\w+)"\]/', | |
| 206 | + function ($matches) { | |
| 207 | + return $this->get_field_value($matches[1]); | |
| 208 | + }, | |
| 209 | + $subject | |
| 210 | + ); | |
| 211 | + | |
| 212 | + if ($processed_message) { | |
| 213 | + $message_body[] = $processed_message; | |
| 214 | + } | |
| 215 | + | |
| 216 | + | |
| 217 | + if ($content_type === 'html') { | |
| 218 | + | |
| 219 | + foreach ($message_body as &$item) { | |
| 220 | + $item = nl2br($item); | |
| 221 | + } | |
| 222 | + unset($item); | |
| 223 | + } | |
| 224 | + | |
| 225 | + $body = implode($line_break, $message_body) . $line_break . '-----' . $line_break . implode($line_break, $email_meta); | |
| 226 | + | |
| 227 | + $cc_header = ''; | |
| 228 | + if (!empty(get_option('king_addons_cc_header_' . $_POST['king_addons_form_id']))) { | |
| 229 | + $cc_header = 'Cc: ' . get_option('king_addons_cc_header_' . $_POST['king_addons_form_id']); | |
| 230 | + | |
| 231 | + $cc_header = preg_replace_callback( | |
| 232 | + '/\[id="(\w+)"\]/', | |
| 233 | + function ($matches) { | |
| 234 | + return $this->get_field_value($matches[1]); | |
| 235 | + }, | |
| 236 | + $cc_header | |
| 237 | + ); | |
| 238 | + } | |
| 239 | + | |
| 240 | + $bcc_header = ''; | |
| 241 | + if (!empty(get_option('king_addons_bcc_header_' . $_POST['king_addons_form_id']))) { | |
| 242 | + $bcc_header = 'Bcc: ' . get_option('king_addons_bcc_header_' . $_POST['king_addons_form_id']); | |
| 243 | + | |
| 244 | + $bcc_header = preg_replace_callback( | |
| 245 | + '/\[id="([^\"]+)"\]/', | |
| 246 | + function ($matches) { | |
| 247 | + return $this->get_field_value($matches[1]); | |
| 248 | + }, | |
| 249 | + $bcc_header | |
| 250 | + ); | |
| 251 | + } | |
| 252 | + | |
| 253 | + // Initialize reply-to and email-from variables to avoid undefined variable warnings | |
| 254 | + $reply_to_address = ''; | |
| 255 | + $email_from_name = ''; | |
| 256 | + $email_from_mail = ''; | |
| 257 | + $reply_to = ''; | |
| 258 | + | |
| 259 | + if (!empty(get_option('king_addons_reply_to_' . $_POST['king_addons_form_id'])) && !empty(get_option('king_addons_email_from_name_' . $_POST['king_addons_form_id'])) && !empty(get_option('king_addons_email_from_' . $_POST['king_addons_form_id']))) { | |
| 260 | + | |
| 261 | + preg_match_all('/id="([^"]+)"/', get_option('king_addons_reply_to_' . $_POST['king_addons_form_id']), $matche); | |
| 262 | + $reply_to_field_id = $matche[1]; | |
| 263 | + | |
| 264 | + preg_match_all('/id="([^"]+)"/', get_option('king_addons_email_from_name_' . $_POST['king_addons_form_id']), $matche); | |
| 265 | + $email_from_name_field_id = $matche[1]; | |
| 266 | + | |
| 267 | + preg_match_all('/id="([^"]+)"/', get_option('king_addons_email_from_' . $_POST['king_addons_form_id']), $matche); | |
| 268 | + $email_from_field_id = $matche[1]; | |
| 269 | + | |
| 270 | + foreach ($form_content as $key => $value) { | |
| 271 | + if (!is_array($value) || count($value) < 2) { | |
| 272 | + continue; // Skip malformed fields | |
| 273 | + } | |
| 274 | + | |
| 275 | + $key_parts = explode('-', $key); | |
| 276 | + $last_part = end($key_parts); | |
| 277 | + | |
| 278 | + if (in_array($last_part, $reply_to_field_id)) { | |
| 279 | + $reply_to_address = sanitize_email($value[1]); | |
| 280 | + } | |
| 281 | + | |
| 282 | + if (in_array($last_part, $email_from_name_field_id)) { | |
| 283 | + $email_from_name = sanitize_text_field($value[1]); | |
| 284 | + } | |
| 285 | + | |
| 286 | + if (in_array($last_part, $email_from_field_id)) { | |
| 287 | + $email_from_mail = sanitize_email($value[1]); | |
| 288 | + } | |
| 289 | + } | |
| 290 | + | |
| 291 | + if (!$reply_to_address) { | |
| 292 | + $reply_to_address = get_option('king_addons_reply_to_' . $_POST['king_addons_form_id']); | |
| 293 | + } | |
| 294 | + | |
| 295 | + if (!$email_from_name) { | |
| 296 | + $email_from_name = get_option('king_addons_email_from_name_' . $_POST['king_addons_form_id']); | |
| 297 | + } | |
| 298 | + | |
| 299 | + if (!$email_from_mail) { | |
| 300 | + $email_from_mail = get_option('king_addons_email_from_' . $_POST['king_addons_form_id']); | |
| 301 | + } | |
| 302 | + | |
| 303 | + $reply_to = 'Reply-To: ' . $reply_to_address; | |
| 304 | + } | |
| 305 | + | |
| 306 | + $email_from = sprintf('From: %s <%s>' . "\r\n", $email_from_name, $email_from_mail); | |
| 307 | + | |
| 308 | + $headers = array('Content-Type: text/' . $content_type . '; charset=UTF-8', $email_from, $cc_header, $bcc_header, $reply_to); | |
| 309 | + | |
| 310 | + | |
| 311 | + $sent = wp_mail($to, $subject, $body, $headers); | |
| 312 | + | |
| 313 | + if ($sent) { | |
| 314 | + wp_send_json_success(array( | |
| 315 | + 'action' => 'king_addons_form_builder_email', | |
| 316 | + 'message' => esc_html__('Message sent successfully', 'king-addons'), | |
| 317 | + 'status' => 'success' | |
| 318 | + // Security fix: Removed potentially unsafe details from response | |
| 319 | + )); | |
| 320 | + } else { | |
| 321 | + wp_send_json_error(array( | |
| 322 | + 'action' => 'king_addons_form_builder_email', | |
| 323 | + 'message' => esc_html__('Message could not be sent', 'king-addons'), | |
| 324 | + 'status' => 'error' | |
| 325 | + // Security fix: Removed potentially unsafe details from response | |
| 326 | + )); | |
| 327 | + } | |
| 328 | + } | |
| 329 | + | |
| 330 | + public function get_field_value($field_id) | |
| 331 | + { | |
| 332 | + // Security fix: Use sanitized form_content instead of $_POST directly | |
| 333 | + $form_content = isset($_POST['form_content']) && is_array($_POST['form_content']) ? $_POST['form_content'] : []; | |
| 334 | + | |
| 335 | + foreach ($form_content as $key => $field) { | |
| 336 | + if (!is_array($field) || count($field) < 2) { | |
| 337 | + continue; // Skip malformed fields | |
| 338 | + } | |
| 339 | + | |
| 340 | + $key_parts = explode('-', $key); | |
| 341 | + $last_part = end($key_parts); | |
| 342 | + | |
| 343 | + if ($last_part === $field_id) { | |
| 344 | + return sanitize_text_field($field[1]); | |
| 345 | + } | |
| 346 | + } | |
| 347 | + return ''; | |
| 348 | + } | |
| 349 | +} | |
| 350 | + | |
| 351 | +new Send_Email(); | |