PluginProbe
SureForms – Contact Form Builder, AI Forms, Payment Form, Survey & Quiz / 2.12.7
SureForms – Contact Form Builder, AI Forms, Payment Form, Survey & Quiz v2.12.7
2.12.7 2.12.6 2.12.5 2.12.4 2.12.3 2.12.2 2.12.1 2.12.0 2.11.1 2.11.0 2.10.1 2.10.0 2.9.1 2.9.0 2.8.2 2.8.1 2.7.0 2.7.1 2.8.0 trunk 0.0.10 0.0.11 0.0.12 0.0.13 0.0.2 All 97 releases
← All changes | inc/export.php +95 -9 2.7.12.12.7 View file →
@@ -79,9 +79,17 @@
79 79 foreach ( $post_ids as $post_id ) {
80 80 $post_id = intval( $post_id );
81 81 $post = get_post( $post_id );
82 82 $post_meta = get_post_meta( $post_id );
83 - $posts[] = [
83 +
84 + // The view counter belongs to this site's traffic, not to the form. These
85 + // payloads feed shared starter templates, so shipping it would hand every
86 + // importer a stranger's numbers. The import side already refuses the key,
87 + // so this is about not exporting it in the first place.
88 + if ( is_array( $post_meta ) ) {
89 + unset( $post_meta[ \SRFM\Inc\Form_Views::META_KEY ] );
90 + }
91 + $posts[] = [
84 92 'post' => $post,
85 93 'post_meta' => $post_meta,
86 94 ];
87 95 }
@@ -252,9 +260,9 @@
252 260 if ( is_string( $cleaned_content ) ) {
253 261 $post_content = $cleaned_content;
254 262 }
255 263
256 - $post_content = addslashes( $post_content );
264 + $post_content = wp_slash( $post_content );
257 265
258 266 // Check if sureforms/form exists in post_content.
259 267 if ( 'sureforms_form' === $post_type ) {
260 268 $new_post = [
@@ -286,18 +294,39 @@
286 294
287 295 $forms_mapping[ $old_id ] = $post_id;
288 296
289 297 // Update post meta.
298 + $allowed_keys = $this->get_allowed_import_meta_keys();
299 + $unserialized_meta_keys = $this->get_unserialized_post_metas();
300 + $registered = get_registered_meta_keys( 'post', SRFM_FORMS_POST_TYPE );
290 301 foreach ( $post_meta as $meta_key => $meta_value ) {
291 - // Check if the meta key is one of the unserialized post metas then add it as is.
292 - if ( in_array( $meta_key, $this->get_unserialized_post_metas(), true ) ) {
293 - add_post_meta( $post_id, $meta_key, $meta_value );
302 + // 1. Whitelist check — skip unknown keys from crafted import files.
303 + if ( ! in_array( $meta_key, $allowed_keys, true ) ) {
304 + continue;
305 + }
306 +
307 + // Note: add_post_meta() internally runs wp_unslash() on the value before
308 + // invoking the registered sanitize_callback. Imported values are unslashed,
309 + // so without re-slashing, backslashes are stripped — corrupting JSON-string
310 + // metas (e.g. _srfm_save_resume, _srfm_conditional_confirmation) whose escaped
311 + // quotes (\") then fail json_decode() in their sanitizers, wiping the value to
312 + // an empty string. wp_slash() pre-escapes so wp_unslash() restores the original.
313 + if ( in_array( $meta_key, $unserialized_meta_keys, true ) ) {
314 + // Complex array metas — sanitize_callback registered via register_post_meta()
315 + // is automatically invoked by add_post_meta() → update_metadata() pipeline.
316 + // When Pro is inactive, some keys may lack a registered callback — apply fallback.
317 + if ( empty( $registered[ $meta_key ]['sanitize_callback'] ) ) {
318 + $meta_value = Helper::sanitize_by_type( $meta_value );
319 + }
320 + add_post_meta( $post_id, $meta_key, wp_slash( $meta_value ) );
294 321 } else {
295 - if ( is_array( $meta_value ) && isset( $meta_value[0] ) ) {
296 - add_post_meta( $post_id, $meta_key, $meta_value[0] );
297 - } else {
298 - add_post_meta( $post_id, $meta_key, $meta_value );
322 + // Scalar metas — unwrap single-element arrays produced by get_post_meta().
323 + $raw_value = is_array( $meta_value ) && isset( $meta_value[0] ) ? $meta_value[0] : $meta_value;
324 + // Fallback sanitization — skip when a registered callback already handles it.
325 + if ( is_string( $raw_value ) && empty( $registered[ $meta_key ]['sanitize_callback'] ) ) {
326 + $raw_value = sanitize_text_field( $raw_value );
299 327 }
328 + add_post_meta( $post_id, $meta_key, wp_slash( $raw_value ) );
300 329 }
301 330 }
302 331 } else {
303 332 return new \WP_Error( 'import_forms_invalid_post_type', __( 'Unable to import form.', 'sureforms' ) );
@@ -304,7 +333,64 @@
304 333 }
305 334 }
306 335
307 336 return $forms_mapping;
337 + }
338 +
339 + /**
340 + * Get the list of meta keys allowed during import.
341 + *
342 + * Only meta keys present in this list will be written to the DB during import.
343 + * Unknown keys from crafted import files are silently ignored.
344 + *
345 + * @since 2.8.0
346 + * @return array<string>
347 + */
348 + private function get_allowed_import_meta_keys(): array {
349 + $scalar_metas = [
350 + '_srfm_additional_classes',
351 + '_srfm_bg_color',
352 + '_srfm_bg_image',
353 + '_srfm_bg_type',
354 + '_srfm_button_border_radius',
355 + '_srfm_captcha_security_type',
356 + '_srfm_cover_image',
357 + '_srfm_form_container_width',
358 + '_srfm_form_custom_css',
359 + '_srfm_form_recaptcha',
360 + '_srfm_form_restriction',
361 + '_srfm_inherit_theme_button',
362 + '_srfm_instant_form',
363 + '_srfm_is_ai_generated',
364 + '_srfm_is_inline_button',
365 + '_srfm_single_page_form_title',
366 + '_srfm_submit_alignment',
367 + '_srfm_submit_alignment_backend',
368 + '_srfm_submit_button_text',
369 + '_srfm_submit_type',
370 + '_srfm_submit_width',
371 + '_srfm_submit_width_backend',
372 + '_srfm_use_label_as_placeholder',
373 + ];
374 +
375 + /**
376 + * Filter the list of scalar meta keys allowed during import.
377 + *
378 + * Pro and other extensions can hook into this to add their own scalar meta keys.
379 + *
380 + * @since 2.8.0
381 + * @param array<string> $scalar_metas List of scalar meta keys.
382 + */
383 + $scalar_metas = apply_filters( 'srfm_import_scalar_meta_keys', $scalar_metas );
384 +
385 + // Ensure filter consumers cannot inject non-SureForms meta keys.
386 + $scalar_metas = array_filter(
387 + $scalar_metas,
388 + static function ( $key ) {
389 + return str_starts_with( $key, '_srfm_' );
390 + }
391 + );
392 +
393 + return array_merge( $this->get_unserialized_post_metas(), $scalar_metas );
308 394 }
309 395
310 396 }