diff --git a/admin/CF7_AntiSpam_Admin_Customizations.php b/admin/CF7_AntiSpam_Admin_Customizations.php
index f6d4d72..3071068 100644
--- a/admin/CF7_AntiSpam_Admin_Customizations.php
+++ b/admin/CF7_AntiSpam_Admin_Customizations.php
@@ -5,6 +5,7 @@
use CF7_AntiSpam\Core\CF7_AntiSpam;
use CF7_AntiSpam\Core\CF7_Antispam_Geoip;
use WP_Query;
+use function cli\err;
/**
* The plugin settings.
@@ -1007,6 +1008,37 @@ private function cf7a_input_cron_schedule( $input, $input_name, $cron_task, $sch
}
+ private function cf7a_clean_agnostic( $value ) {
+ if ( is_bool( $value ) ) {
+ $input = boolval( $value );
+ } elseif ( is_numeric( $value ) ) {
+ $input = floatval( $value );
+ } else {
+ $input = sanitize_text_field( $value );
+ }
+ return $input;
+ }
+
+ /**
+ * Clean and sanitize a value recursively.
+ *
+ * @param string $key The key of the value to be cleaned.
+ * @param mixed $value The value to be cleaned.
+ *
+ * @return array|bool|int|string
+ */
+ private function cf7a_clean_recursive( $json_data ) {
+ $input = array();
+ foreach ( $json_data as $key => $value ) {
+ if ( is_array( $value ) || is_object( $value ) ) {
+ $input[ $key ] = $this->cf7a_clean_recursive( $value );
+ } else {
+ $input[ $key ] = $this->cf7a_clean_agnostic( $value );
+ }
+ }
+ return $input;
+ }
+
/**
* Sanitize each setting field as needed
*
@@ -1014,10 +1046,29 @@ private function cf7a_input_cron_schedule( $input, $input_name, $cron_task, $sch
* @return array $options sanitized
*/
public function cf7a_sanitize_options( $input ) {
- $new_input['cf7a_enabled'] = isset( $input['cf7a_enabled'] ) ? 1 : 0;
+ /* get the import options */
+ $new_input = $this->options;
+ $import_data = isset( $_POST['to-import'] ) ? $_POST['to-import'] : false;
+ if ( ! empty( $import_data ) ) {
+ $json_data = json_decode( wp_unslash( $_POST['to-import'] ) );
+ $input = $this->cf7a_clean_recursive( $json_data );
+ // monkey pathing arrays that needs to be imploded
+ $input['bad_ip_list'] = implode( ',', $input['bad_ip_list'] );
+ $input['ip_whitelist'] = implode( ',', $input['ip_whitelist'] );
+ $input['bad_email_strings_list'] = implode( ',', $input['bad_email_strings_list'] );
+ $input['bad_user_agent_list'] = implode( ',', $input['bad_user_agent_list'] );
+ $input['dnsbl_list'] = implode( ',', $input['dnsbl_list'] );
+ $input['honeypot_input_names'] = implode( ',', $input['honeypot_input_names'] );
+ $input['bad_words_list'] = implode( ',', $input['bad_words_list'] );
+ $input['languages_locales']['allowed'] = implode( ',', $input['languages_locales']['allowed'] );
+ $input['languages_locales']['disallowed'] = implode( ',', $input['languages_locales']['disallowed'] );
+ $input['cf7a_enabled'] = 1;
+ $input['cf7a_enable'] = 1;
+ $input['cf7a_version'] = CF7ANTISPAM_VERSION;
+ }
+ error_log( print_r( $input, true ) );
- /* get the existing options */
- $new_input = $this->options;
+ $new_input['cf7a_enabled'] = isset( $input['cf7a_enabled'] ) ? 1 : 0;
$new_input['cf7a_enable'] = isset( $input['cf7a_enable'] ) ? $input['cf7a_enable'] : $new_input['cf7a_enable'];
@@ -1036,15 +1087,17 @@ public function cf7a_sanitize_options( $input ) {
* Checking if the enable_geoip_download is not set (note the name is $new_input but actually is the copy of the stored options)
* and the user has chosen to enable the geoip, in this case download the database if needed
*/
- if ( empty( $new_input['enable_geoip_download'] ) && isset( $input['enable_geoip_download'] ) ) {
+ if ( empty( $import_data ) && empty( $new_input['enable_geoip_download'] ) && isset( $input['enable_geoip_download'] ) ) {
$this->cf7a_enable_geo( $new_input['enable_geoip_download'] );
}
$new_input['enable_geoip_download'] = isset( $input['enable_geoip_download'] ) ? 1 : 0;
- $new_input['geoip_dbkey'] = isset( $input['geoip_dbkey'] ) ? sanitize_textarea_field( $input['geoip_dbkey'] ) : false;
+
+
+ $new_input['geoip_dbkey'] = isset( $input['geoip_dbkey'] ) ? sanitize_textarea_field( $input['geoip_dbkey'] ) : false;
/* browser language check enabled */
- $new_input['check_language'] = isset( $input['check_language'] ) ? 1 : 0;
+ $new_input['check_language'] = ! empty( $input['check_language'] ) ? 1 : 0;
/* geo-ip location check enabled */
$new_input['check_geo_location'] = isset( $input['check_geo_location'] ) ? 1 : 0;
@@ -1057,6 +1110,7 @@ public function cf7a_sanitize_options( $input ) {
? $this->cf7a_settings_format_user_input( sanitize_textarea_field( $input['languages_locales']['disallowed'] ) )
: array();
+
/* max attempts before ban */
$new_input['max_attempts'] = isset( $input['max_attempts'] ) ? intval( $input['max_attempts'] ) : 3;
@@ -1126,7 +1180,7 @@ public function cf7a_sanitize_options( $input ) {
/* honeyform */
$new_input['check_honeyform'] = isset( $input['check_honeyform'] ) ? 1 : 0;
$new_input['honeyform_position'] = ! empty( $input['honeyform_position'] ) ? sanitize_title( $input['honeyform_position'] ) : 'wp_body_open';
- $new_input['honeyform_excluded_pages'] = ! empty( $input['honeyform_excluded_pages'] ) ? cf7a_str_array_to_uint_array( $input['honeyform_excluded_pages'] ) : '';
+ $new_input['honeyform_excluded_pages'] = ! empty( $input['honeyform_excluded_pages'] ) ? cf7a_str_array_to_uint_array( $input['honeyform_excluded_pages'] ) : array();
/* identity protection */
$new_input['mailbox_protection_multiple_send'] = isset( $input['mailbox_protection_multiple_send'] ) ? 1 : 0;
@@ -1526,9 +1580,8 @@ public function cf7a_honeyform_excluded_pages_callback() {
}
}
- $admin_options = get_option( 'cf7a_options' );
- $excluded = isset( $admin_options['honeyform_excluded_pages'] ) ? $admin_options['honeyform_excluded_pages'] : array();
- $str_excluded = '';
+ $excluded = isset( $this->options['honeyform_excluded_pages'] ) ? $this->options['honeyform_excluded_pages'] : array();
+ $str_excluded = '';
if ( is_array( $excluded ) ) {
foreach ( $excluded as $entry ) {
$str_excluded .= '';
diff --git a/admin/CF7_AntiSpam_Admin_Display.php b/admin/CF7_AntiSpam_Admin_Display.php
index f1e7650..f8a332e 100644
--- a/admin/CF7_AntiSpam_Admin_Display.php
+++ b/admin/CF7_AntiSpam_Admin_Display.php
@@ -110,7 +110,10 @@ public function cf7a_display_content() {
?>
+
cf7a_export_options();
}
/**
@@ -188,6 +191,35 @@ public static function cf7a_get_blacklisted_table() {
}
}
+ private function cf7a_export_options() {
+
+ ?>
+
+ 0 && intval( $value ) == $value;
+ return is_int( $value ) || is_numeric( $value ) && $value > 0 && intval( $value ) == $value;
}
)
);
diff --git a/engine/CF7_AntiSpam_Activator.php b/engine/CF7_AntiSpam_Activator.php
index 22f51bb..84e1e5d 100644
--- a/engine/CF7_AntiSpam_Activator.php
+++ b/engine/CF7_AntiSpam_Activator.php
@@ -39,53 +39,54 @@ class CF7_AntiSpam_Activator {
*/
public static function init_vars() {
self::$default_cf7a_options = array(
- 'cf7a_enable' => true,
- 'cf7a_version' => CF7ANTISPAM_VERSION,
- 'cf7a_customizations_class' => CF7ANTISPAM_HONEYPOT_CLASS,
- 'cf7a_customizations_prefix' => CF7ANTISPAM_PREFIX,
- 'cf7a_cipher' => 'aes-128-cbc',
- 'cf7a_score_preset' => 'weak',
- 'cf7a_disable_reload' => true,
- 'check_bot_fingerprint' => true,
- 'check_bot_fingerprint_extras' => true,
- 'append_on_submit' => true,
- 'check_time' => true,
- 'check_time_min' => 6,
- 'check_time_max' => YEAR_IN_SECONDS,
- 'check_bad_ip' => true,
- 'autostore_bad_ip' => true,
- 'max_attempts' => 3,
- 'unban_after' => 'disabled',
- 'check_bad_words' => true,
- 'check_bad_email_strings' => true,
- 'check_bad_user_agent' => true,
- 'check_dnsbl' => false,
- 'check_refer' => true,
- 'check_honeypot' => true,
- 'check_honeyform' => false,
- 'identity_protection_user' => false,
- 'identity_protection_wp' => false,
- 'enable_geoip_download' => false,
- 'geoip_dbkey' => false,
- 'check_language' => false,
- 'check_geo_location' => false,
- 'honeyform_position' => 'the_content',
- 'enable_b8' => true,
- 'b8_threshold' => 0.95,
- 'enable_advanced_settings' => 0,
- 'bad_words_list' => array(),
- 'bad_ip_list' => array(),
- 'ip_whitelist' => array(),
- 'bad_email_strings_list' => array(),
- 'bad_user_agent_list' => array(),
- 'dnsbl_list' => array(),
- 'honeypot_input_names' => array(),
- 'honeyform_excluded_pages' => array(),
- 'languages_locales' => array(
+ 'cf7a_enable' => true,
+ 'cf7a_version' => CF7ANTISPAM_VERSION,
+ 'cf7a_customizations_class' => CF7ANTISPAM_HONEYPOT_CLASS,
+ 'cf7a_customizations_prefix' => CF7ANTISPAM_PREFIX,
+ 'cf7a_cipher' => 'aes-128-cbc',
+ 'cf7a_score_preset' => 'weak',
+ 'cf7a_disable_reload' => true,
+ 'check_bot_fingerprint' => true,
+ 'check_bot_fingerprint_extras' => true,
+ 'append_on_submit' => true,
+ 'check_time' => true,
+ 'check_time_min' => 6,
+ 'check_time_max' => YEAR_IN_SECONDS,
+ 'check_bad_ip' => true,
+ 'autostore_bad_ip' => true,
+ 'max_attempts' => 3,
+ 'unban_after' => 'disabled',
+ 'check_bad_words' => true,
+ 'check_bad_email_strings' => true,
+ 'check_bad_user_agent' => true,
+ 'check_dnsbl' => false,
+ 'check_refer' => true,
+ 'check_honeypot' => true,
+ 'check_honeyform' => false,
+ 'identity_protection_user' => false,
+ 'identity_protection_wp' => false,
+ 'enable_geoip_download' => false,
+ 'geoip_dbkey' => false,
+ 'check_language' => false,
+ 'check_geo_location' => false,
+ 'honeyform_position' => 'the_content',
+ 'enable_b8' => true,
+ 'b8_threshold' => 0.95,
+ 'enable_advanced_settings' => 0,
+ 'mailbox_protection_multiple_send' => 0,
+ 'bad_words_list' => array(),
+ 'bad_ip_list' => array(),
+ 'ip_whitelist' => array(),
+ 'bad_email_strings_list' => array(),
+ 'bad_user_agent_list' => array(),
+ 'dnsbl_list' => array(),
+ 'honeypot_input_names' => array(),
+ 'honeyform_excluded_pages' => array(),
+ 'languages_locales' => array(
'allowed' => array(),
'disallowed' => array(),
),
- 'score' => array(
+ 'score' => array(
'_fingerprinting' => 0.1,
'_time' => 0.3,
'_bad_string' => 0.5,
@@ -213,7 +214,19 @@ public static function update_options( $reset_options = false ) {
$options = get_option( 'cf7a_options' );
- if ( false !== $options && ! $reset_options ) {
+ if ( false === $options || $reset_options ) {
+
+ // Delete all options
+ if ( $reset_options === true ) {
+ delete_option( 'cf7a_options' );
+ }
+
+ /* if the plugin options are missing Init the plugin with the default option + the default settings */
+ $new_options = array_merge( self::$default_cf7a_options, self::$default_cf7a_options_bootstrap );
+
+ add_option( 'cf7a_options', $new_options );
+
+ } else {
/* update the plugin options but add the new options automatically */
if ( isset( $options['cf7a_version'] ) ) {
@@ -226,11 +239,6 @@ public static function update_options( $reset_options = false ) {
cf7a_log( 'CF7-antispam plugin options updated', 1 );
update_option( 'cf7a_options', $new_options );
- } else {
- /* if the plugin options are missing Init the plugin with the default option + the default settings */
- $new_options = array_merge( self::$default_cf7a_options, self::$default_cf7a_options_bootstrap );
-
- add_option( 'cf7a_options', $new_options );
}
cf7a_log( $new_options, 1 );
diff --git a/src/admin-scripts.js b/src/admin-scripts.js
index fb6f025..d2be9d9 100644
--- a/src/admin-scripts.js
+++ b/src/admin-scripts.js
@@ -5,3 +5,5 @@ import './integration/integration.scss';
import './settings/settings.js';
import './settings/settings.scss';
+
+import './settings/importExport.js';
diff --git a/src/settings/importExport.js b/src/settings/importExport.js
new file mode 100644
index 0000000..ba92206
--- /dev/null
+++ b/src/settings/importExport.js
@@ -0,0 +1,85 @@
+window.onload = function () {
+ // Example for download button
+ document
+ .getElementById('cf7a_download_button')
+ .addEventListener('click', () => downloadOptions());
+
+ document
+ .getElementById('import-export-options')
+ .addEventListener('submit', (e) => importExportOptions(e));
+};
+
+/**
+ * Import and export options from/to JSON
+ *
+ * @param {SubmitEvent} e The submit event from the form
+ */
+function importExportOptions(e) {
+ e.preventDefault();
+
+ // eslint-disable-next-line no-alert
+ const confirmImport = confirm(
+ 'Are you sure you want to import options? This will overwrite your current settings.'
+ );
+ if (!confirmImport) {
+ return;
+ }
+ /**
+ * Parse the JSON string and get the cf7-antispam options
+ */
+ const optionsContent = document.getElementById('cf7a_options_area').value;
+ let cf7aOptions = null;
+ try {
+ cf7aOptions = JSON.parse(optionsContent);
+ } catch (err) {
+ // eslint-disable-next-line no-console
+ console.error(err);
+ // eslint-disable-next-line no-alert
+ alert('Invalid JSON. Please check your file and try again.');
+ return;
+ }
+ /**
+ * Get the submit form data and append the cf7-ntispam options to the form data options
+ * @type {FormData}
+ */
+ const data = new FormData(e.target);
+ data.append('to-import', encodeURIComponent(JSON.stringify(cf7aOptions)));
+
+ // Make an AJAX request to save the merged options
+ fetch(e.target.getAttribute('action'), {
+ method: 'POST',
+ body: data,
+ })
+ .then((response) => response)
+ .then((response) => {
+ // Handle the response
+ // eslint-disable-next-line no-console
+ console.log(response);
+ if (response.status === 200) {
+ // emulate the php non async behavior
+ window.location.href = response.url;
+ }
+ })
+ .catch((error) => {
+ // Handle the error
+ // eslint-disable-next-line no-console
+ console.error(error);
+ });
+}
+
+function downloadOptions() {
+ const optionsContent = document.getElementById('cf7a_options_area').value;
+ const blob = new Blob([optionsContent], {
+ type: 'application/json',
+ });
+ const url = window.URL.createObjectURL(blob);
+ const a = document.createElement('a');
+ a.style.display = 'none';
+ a.href = url;
+ a.download = 'cf7a-' + new Date().getTime() / 1000 + '.json';
+ document.body.appendChild(a);
+ a.click();
+ window.URL.revokeObjectURL(url);
+ // eslint-disable-next-line no-alert
+ alert('Your file has downloaded!');
+}