--- a/email-customizer-for-woocommerce/classes/class-wecmf-settings.php
+++ b/email-customizer-for-woocommerce/classes/class-wecmf-settings.php
@@ -75,17 +75,22 @@
}
public function prepare_preview(){
- if ( isset( $_GET['preview'] ) && isset( $_GET['page'] ) && $_GET['page'] === 'thwecmf_email_customizer' && WECMF_Utils::is_user_capable() ) {
- $order_id = isset( $_GET['id'] ) ? absint( base64_decode( $_GET['id'] ) ) : false;
- $email_index = isset( $_GET['email'] ) ? sanitize_text_field( base64_decode( $_GET['email'] ) ) : false;
- $template = isset($_GET['preview']) ? sanitize_text_field( base64_decode( $_GET['preview'] ) ) : '';
- $content = $this->admin_instance->prepare_preview( $order_id, $email_index, $template, true );
- echo $this->render_preview( $content );
- die;
- }
+ if ( isset( $_GET['preview'] ) && isset( $_GET['page'] ) && $_GET['page'] === 'thwecmf_email_customizer' && WECMF_Utils::is_user_capable() ) {
+ // Add nonce verification
+ if ( ! isset( $_GET['_wpnonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ), 'thwecmf_preview_order' ) ) {
+ wp_die( 'Security check failed.' );
+ }
+ $order_id = isset( $_GET['id'] ) ? absint( base64_decode( sanitize_text_field( wp_unslash( $_GET['id'] ) ) ) ) : false;
+ $email_index = isset( $_GET['email'] ) ? sanitize_text_field( base64_decode( sanitize_text_field( wp_unslash( $_GET['email'] ) ) ) ) : false;
+ $template = isset( $_GET['preview'] ) ? sanitize_text_field( base64_decode( sanitize_text_field( wp_unslash( $_GET['preview'] ) ) ) ) : '';
+ $content = $this->admin_instance->prepare_preview( $order_id, $email_index, $template, true );
+ $this->render_preview( $content );
+ die;
}
+}
- public function render_preview( $content ){
+ public function render_preview( $content ){
+ $allowed_html = WECMF_Utils::get_email_allowed_html();
?>
<html>
<head>
@@ -98,13 +103,18 @@
</head>
<body>
- <?php echo $content; ?>
+ <!-- added wp_kses because of security -->
+ <?php echo wp_kses( $content, $allowed_html ); ?>
<script>
var links = document.getElementsByClassName('thwecmf-link');
var email = '';
for (var i = 0; i < links.length; i++){
email = links[i].innerHTML;
+ //Error i guess here some security issue here want to look deeper
links[i].innerHTML = '<a href="mailto:'+esc_attr( email )+'">'+esc_html( email )+'</a>';
+ // Suggested fix:
+ // var safeEmail = email.replace(/[^a-zA-Z0-9@._-]/g, '');
+ // links[i].innerHTML = '<a href="mailto:' + safeEmail + '">' + safeEmail + '</a>';
}
</script>
</body>
@@ -149,29 +159,36 @@
}
public function admin_menu() {
+ // if (!empty($_GET) && isset($_GET['_wpnonce'])) {
+ // $nonce = sanitize_text_field(wp_unslash($_GET['_wpnonce']));
+ // if (!wp_verify_nonce($nonce, 'admin_menu_nonce')) {
+ // wp_die('Security check failed.');
+ // }
+ // }
global $wp;
-
- $page = isset( $_GET['page'] ) ? esc_attr( $_GET['page'] ) : 'thwecmf_email_customizer';
+ // Sanitize and unslash the 'page' parameter
+ // phpcs:ignore WordPress.Security.NonceVerification.Recommended
+ $page = isset($_GET['page']) ? sanitize_text_field(wp_unslash($_GET['page'])) : 'thwecmf_email_customizer';
$capability = $this->wecmf_capability();
- $this->screen_id = add_menu_page(esc_attr__('Email Customizer'), esc_attr__('Email Customizer'), esc_html( $capability ), 'thwecmf_email_customizer', array($this, 'output_settings'), 'dashicons-admin-customizer', 56);
- add_submenu_page('thwecmf_email_customizer', esc_attr__('Templates'), esc_attr__('Templates'), $capability, 'thwecmf_email_customizer', array($this, 'output_settings'));
- add_submenu_page('thwecmf_email_customizer', esc_attr__('Email Mapping'), esc_attr__('Email Mapping'), esc_html( $capability ), 'thwecmf_email_mapping', array($this, 'output_settings'));
- add_submenu_page('thwecmf_email_customizer', esc_attr__('Pro Features'), esc_attr__('Pro Features'), esc_html( $capability ), 'thwecmf_premium_features', array($this, 'output_settings'));
+ $this->screen_id = add_menu_page(esc_attr__('Email Customizer','email-customizer-for-woocommerce'), esc_attr__('Email Customizer','email-customizer-for-woocommerce'), esc_html( $capability ), 'thwecmf_email_customizer', array($this, 'output_settings'), 'dashicons-admin-customizer', 56);
+ add_submenu_page('thwecmf_email_customizer', esc_attr__('Templates','email-customizer-for-woocommerce'), esc_attr__('Templates','email-customizer-for-woocommerce'), $capability, 'thwecmf_email_customizer', array($this, 'output_settings'));
+ add_submenu_page('thwecmf_email_customizer', esc_attr__('Email Mapping','email-customizer-for-woocommerce'), esc_attr__('Email Mapping','email-customizer-for-woocommerce'), esc_html( $capability ), 'thwecmf_email_mapping', array($this, 'output_settings'));
+ add_submenu_page('thwecmf_email_customizer', esc_attr__('Pro Features','email-customizer-for-woocommerce'), esc_attr__('Pro Features','email-customizer-for-woocommerce'), esc_html( $capability ), 'thwecmf_premium_features', array($this, 'output_settings'));
add_action('admin_print_scripts', array($this, 'disable_admin_notices'));
add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts'));
}
public function add_screen_id($ids){
$ids[] = 'woocommerce_page_thwecmf_email_customizer';
- $ids[] = strtolower(__('WooCommerce', 'woocommerce')) .'_page_thwecmf_email_customizer';
+ $ids[] = strtolower(__('WooCommerce', 'email-customizer-for-woocommerce')) .'_page_thwecmf_email_customizer';
return $ids;
}
public function add_settings_link($links) {
- $settings_link = '<a href="'.admin_url('admin.php?page=thwecmf_email_customizer').'">'. esc_html__('Settings') .'</a>';
+ $settings_link = '<a href="'.admin_url('admin.php?page=thwecmf_email_customizer').'">'. esc_html__('Settings','email-customizer-for-woocommerce') .'</a>';
array_unshift($links, $settings_link);
- $pro_link = '<a style="color:green; font-weight:bold" target="_blank" href="https://www.themehigh.com/product/woocommerce-email-customizer/?utm_source=free&utm_medium=plugin_action_link&utm_campaign=wec_upgrade_link">'. __('Get Pro', 'woo-email-customizer') .'</a>';
+ $pro_link = '<a style="color:green; font-weight:bold" target="_blank" href="https://www.themehigh.com/product/woocommerce-email-customizer/?utm_source=free&utm_medium=plugin_action_link&utm_campaign=wec_upgrade_link">'. __('Get Pro', 'email-customizer-for-woocommerce') .'</a>';
array_push($links,$pro_link);
if (array_key_exists('deactivate', $links)) {
$links['deactivate'] = str_replace('<a', '<a class="thwecmf-deactivate-link"', $links['deactivate']);
@@ -181,7 +198,8 @@
}
public function output_settings() {
- $page = isset( $_GET['page'] ) ? sanitize_text_field( $_GET['page'] ) : 'thwecmf_email_customizer';
+ // phpcs:ignore WordPress.Security.NonceVerification.Recommended
+ $page = isset( $_GET['page'] ) ? sanitize_text_field(wp_unslash( $_GET['page'] ) ) : 'thwecmf_email_customizer';
if( WECMF_Utils::edit_template( $page ) ){
$fields_instance = WECMF_General_Template::instance();
$fields_instance->render_page();
@@ -197,7 +215,8 @@
}
public function disable_admin_notices(){
- $page = isset( $_GET['page'] ) ? sanitize_text_field( $_GET['page'] ) : '';
+ // phpcs:ignore WordPress.Security.NonceVerification.Recommended
+ $page = isset( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : '';
if( WECMF_Utils::edit_template( $page ) ){
global $wp_filter;
if (is_user_admin() ) {
@@ -270,9 +289,11 @@
}
public function verify_nonce(){
- $template_details = isset($_POST['i_template_name']) ? sanitize_text_field($_POST['i_template_name']): false;
+ $template_details = isset($_POST['i_template_name']) ? sanitize_text_field( wp_unslash( $_POST['i_template_name'] ) ) : false;
if ( isset( $_POST['i_edit_template'] ) && $template_details ){
- if( !wp_verify_nonce( $_POST['thwecmf_edit_template_'.$template_details], 'thwecmf_edit_template' ) || !WECMF_Utils::is_user_capable() ){
+ // 1. Define the dynamic key
+ $nonce_key = 'thwecmf_edit_template_' . $template_details;
+ if( ! isset( $_POST[ $nonce_key ] ) || !wp_verify_nonce(sanitize_text_field( wp_unslash( $_POST[ $nonce_key ] ) ), 'thwecmf_edit_template' ) || !WECMF_Utils::is_user_capable() ){
wp_die( '<div class="wecm-wp-die-message">Action failed. Could not verify nonce.</div>' );
}
}
@@ -286,19 +307,22 @@
*/
public function add_thwecmf_body_class( $classes ){
$pages = array('thwecmf_email_customizer', 'thwecmf_email_mapping');
- $page = isset( $_GET['page'] ) ? sanitize_text_field( $_GET['page'] ) : false;
+ // phpcs:ignore WordPress.Security.NonceVerification.Recommended
+ $page = isset( $_GET['page'] ) ? sanitize_text_field(wp_unslash( $_GET['page'] ) ) : false;
if( in_array($page, $pages) ){
$classes .= ' thwecmf-page';
}
if( $page === 'thwecmf_email_mapping' ){
$classes .= ' thwecmf-mapping-page';
}else if( $page === 'thwecmf_email_customizer' ){
+ // phpcs:ignore WordPress.Security.NonceVerification.Missing
$classes .= isset( $_POST['i_edit_template'] ) ? ' thwecmf-builder-page' : ' thwecmf-template-page';
}
return $classes;
}
private function is_editor_page( $hook ){
+ // phpcs:ignore WordPress.Security.NonceVerification.Missing
if( $hook === "toplevel_page_thwecmf_email_customizer" && isset($_POST["i_template_name"]) && !isset($_POST["reset_template"]) ){
return true;
}
@@ -319,22 +343,23 @@
}
$additional = array();
-
+ // phpcs:ignore WordPress.Security.NonceVerification.Missing
+ $template_name = isset( $_POST['i_template_name'] ) ? sanitize_text_field( wp_unslash( $_POST['i_template_name'] ) ) : '';
wp_enqueue_media();
wp_enqueue_style (array('woocommerce_admin_styles', 'jquery-ui-style'));
wp_enqueue_style ('thwecmf-admin-style', plugins_url('/assets/css/thwecmf-admin.min.css', dirname(__FILE__)), array(), TH_WECMF_VERSION);
wp_enqueue_style('wp-color-picker');
- wp_enqueue_style('raleway-style','https://fonts.googleapis.com/css?family=Raleway:400,600,800');
+ wp_enqueue_style('raleway-style','https://fonts.googleapis.com/css?family=Raleway:400,600,800', array(), TH_WECMF_VERSION);
if( $this->is_editor_page($hook) ){
wp_enqueue_script( 'thwecmf-admin-script', plugins_url('/assets/js/thwecmf-editor.min.js', dirname(__FILE__)), ['wp-element', 'jquery'], TH_WECMF_VERSION, true );
$additional = array(
'woo_orders' => $this->get_woo_orders(),
'woo_emails' => $this->get_woo_emails(),
- 'template' => $this->get_template_details(sanitize_text_field($_POST["i_template_name"])),
+ 'template' => $this->get_template_details($template_name),
'bloginfo' => get_bloginfo(),
'testmail_recepient' => apply_filters('thwecmf_set_testmail_recepient', true) ? THWECMF_LOGIN_USER : "",
'admin_plugin_url' => TH_WECMF_ASSETS_URL,
- 'allowed_tags' => apply_filters('thwecmf_set_allowed_tags_in_text', ['b', 'strong', 'u', 'i', 'a']),
+ 'allowed_tags' => apply_filters('thwecmf_set_allowed_tags_in_text', ['p', 'br', 'strong', 'em', 'b', 'i', 'u', 'span', 'div', 'a', 'ul', 'ol', 'li', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6']),
'remove_unencoded_html' => $this->should_remove_unencoded(),
);
}else{
@@ -350,7 +375,7 @@
'ajax_banner_nonce' => wp_create_nonce('thwecmf_banner_ajax_security'),
'admin_plugin_url' => TH_WECMF_URL,
'tstatus' => WECMF_Utils::get_status(),
- 'template_name' => isset( $_POST['i_template_name'] ) ? sanitize_text_field( $_POST['i_template_name'] ) : '',
+ 'template_name' => $template_name,
'preview_order' => wp_create_nonce( 'thwecmf_preview_order' ),
'reset_preview' => wp_create_nonce('thwecmf_reset_preview'),
);
@@ -367,6 +392,7 @@
$template_data = false;
if($t_name){
$t_list = WECMF_Utils::thwecmf_get_template_settings();
+ // write_log("we are here in get template details");
if( WECMF_Utils::wecm_valid( $t_name, true ) ){
$template_data = isset( $t_list['templates'][$t_name] ) ? WECMF_Utils::sanitize_template_data( $t_list['templates'][$t_name], true ) : WECMF_Utils::thwecmf_get_templates($t_name);
}else{
@@ -395,7 +421,8 @@
*/
private function thwecmf_invalid_template(){
$url = admin_url('admin.php?page=thwecmf_email_customizer');
- wp_redirect($url);
+ wp_safe_redirect($url);
+ exit;
}
private function get_woo_emails(){
@@ -442,7 +469,8 @@
private function get_buyer_info( $order ){
$buyer = false;
if ( $order->get_billing_first_name() || $order->get_billing_last_name() ) {
- $buyer = trim( sprintf( _x( '%1$s %2$s', 'full name', 'woocommerce' ), $order->get_billing_first_name(), $order->get_billing_last_name() ) );
+ /* translators: 1: customer's first name, 2: customer's last name */
+ $buyer = trim( sprintf( _x( '%1$s %2$s', 'full name', 'email-customizer-for-woocommerce' ), $order->get_billing_first_name(), $order->get_billing_last_name() ) );
} elseif ( $order->get_billing_company() ) {
$buyer = trim( $order->get_billing_company() );
} elseif ( $order->get_customer_id() ) {
@@ -453,8 +481,10 @@
}
public function set_wecmf_title($admin_title, $title){
+ // phpcs:ignore WordPress.Security.NonceVerification.Missing
if( isset($_POST["i_template_name"]) ){
- $template = str_replace("_", "", sanitize_text_field($_POST["i_template_name"]));
+ // phpcs:ignore WordPress.Security.NonceVerification.Missing
+ $template = str_replace("_", "", sanitize_text_field( wp_unslash( $_POST["i_template_name"] )));
$admin_title = str_replace($title, "Edit Template", $admin_title);
}
@@ -605,16 +635,16 @@
background-position: 18px 8px;
}
.thwecmf-yes{
- background-image: url(<?php echo TH_WECMF_URL; ?>assets/images/tick.svg);
+ background-image: url(<?php echo esc_url( TH_WECMF_URL. 'assets/images/tick.svg');?>);
}
.thwecmf-remind{
- background-image: url(<?php echo TH_WECMF_URL; ?>assets/images/reminder.svg);
+ background-image: url(<?php echo esc_url( TH_WECMF_URL. 'assets/images/reminder.svg');?>);
}
.thwecmf-dismiss{
- background-image: url(<?php echo TH_WECMF_URL; ?>assets/images/close.svg);
+ background-image: url(<?php echo esc_url( TH_WECMF_URL. 'assets/images/close.svg');?>);
}
.thwecmf-done{
- background-image: url(<?php echo TH_WECMF_URL; ?>assets/images/done.svg);
+ background-image: url(<?php echo esc_url( TH_WECMF_URL. 'assets/images/done.svg');?>);
}
.thwecmf-notice-action.thwecmf-yes{
background-color: #2271b1;
@@ -625,6 +655,7 @@
}
private function render_review_request_notice(){
+ // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$current_page = isset( $_GET['page'] ) ? sanitize_key( $_GET['page'] ) : 'thwecmf_email_customizer';
$remind_url = add_query_arg(array('thwecmf_remind' => true, 'thwecmf_review_nonce' => wp_create_nonce( 'thwecmf_notice_security')));
@@ -632,28 +663,28 @@
$reviewed_url= add_query_arg(array('thwecmf_reviewed' => true, 'thwecmf_review_nonce' => wp_create_nonce( 'thwecmf_notice_security')));
?>
- <div class="notice notice-info thpladmin-notice is-dismissible thwecmf-review-wrapper" data-nonce="<?php echo wp_create_nonce( 'thwecmf_notice_security'); ?>">
+ <div class="notice notice-info thpladmin-notice is-dismissible thwecmf-review-wrapper" data-nonce="<?php echo esc_attr( wp_create_nonce( 'thwecmf_notice_security')); ?>">
<div class="thwecmf-review-image">
<img src="<?php echo esc_url(TH_WECMF_URL .'assets/images/review-left.png'); ?>" alt="themehigh">
</div>
<div class="thwecmf-review-content">
- <h3><?php _e('Tell us how it was!', 'woo-email-customizer'); ?></h3>
- <p><?php _e('Thank you for choosing us. We would love to hear about your experience while using the new Drag and Drop UI. Could you please do us a Big favor by leaving a review on WordPress to help us spread the word and boost our motivation?', 'woo-email-customizer'); ?></p>
+ <h3><?php esc_html_e('Tell us how it was!', 'email-customizer-for-woocommerce'); ?></h3>
+ <p><?php esc_html_e('Thank you for choosing us. We would love to hear about your experience while using the new Drag and Drop UI. Could you please do us a Big favor by leaving a review on WordPress to help us spread the word and boost our motivation?', 'email-customizer-for-woocommerce'); ?></p>
<div class="action-row">
<a class="thwecmf-notice-action thwecmf-yes" onclick="window.open('https://wordpress.org/support/plugin/email-customizer-for-woocommerce/reviews/?rate=5#new-post', '_blank')" style="margin-right:16px; text-decoration: none">
- <?php _e("Ok, You deserve it", 'woo-email-customizer'); ?>
+ <?php esc_html_e("Ok, You deserve it", 'email-customizer-for-woocommerce'); ?>
</a>
<a class="thwecmf-notice-action thwecmf-done" href="<?php echo esc_url($reviewed_url); ?>" style="margin-right:16px; text-decoration: none">
- <?php _e('Already, did', 'woo-email-customizer'); ?>
+ <?php esc_html_e('Already, did', 'email-customizer-for-woocommerce'); ?>
</a>
<a class="thwecmf-notice-action thwecmf-remind" href="<?php echo esc_url($remind_url); ?>" style="margin-right:16px; text-decoration: none">
- <?php _e('Maybe later', 'woo-email-customizer'); ?>
+ <?php esc_html_e('Maybe later', 'email-customizer-for-woocommerce'); ?>
</a>
<a class="thwecmf-notice-action thwecmf-dismiss" href="<?php echo esc_url($dismiss_url); ?>" style="margin-right:16px; text-decoration: none">
- <?php _e("Nah, never", 'woo-email-customizer'); ?>
+ <?php esc_html_e("Nah, never", 'email-customizer-for-woocommerce'); ?>
</a>
</div>
</div>
@@ -670,11 +701,12 @@
}
public function wecmf_notice_actions(){
+ //phpcs:ignore WordPress.Security.NonceVerification.Recommended
if( !(isset($_GET['thwecmf_remind']) || isset($_GET['thwecmf_dissmis']) || isset($_GET['thwecmf_reviewed'])) ) {
return;
}
- $nonce = isset($_GET['thwecmf_review_nonce']) ? $_GET['thwecmf_review_nonce'] : false;
+ $nonce = isset($_GET['thwecmf_review_nonce']) ? sanitize_text_field( wp_unslash( $_GET['thwecmf_review_nonce'] ) ) : false;
$capability = WECMF_Utils::wecmf_capability();
if(!wp_verify_nonce($nonce, 'thwecmf_notice_security') || !current_user_can($capability)){
@@ -768,11 +800,11 @@
<div class="modal-body">
<div class="model-header">
<img class="th-logo" src="<?php echo esc_url(TH_WECMF_URL .'assets/images/themehigh.svg'); ?>" alt="themehigh-logo">
- <span><?php echo __('Quick Feedback', 'woo-email-customizer'); ?></span>
+ <span><?php echo esc_html__('Quick Feedback', 'email-customizer-for-woocommerce'); ?></span>
</div>
<main class="form-container main-full">
- <p class="thwecm-title-text"><?php echo __('If you have a moment, please let us know why you want to deactivate this plugin', 'woo-email-customizer'); ?></p>
- <ul class="deactivation-reason" data-nonce="<?php echo wp_create_nonce('thwecm_deactivate_nonce'); ?>">
+ <p class="thwecm-title-text"><?php echo esc_html__('If you have a moment, please let us know why you want to deactivate this plugin', 'email-customizer-for-woocommerce'); ?></p>
+ <ul class="deactivation-reason" data-nonce="<?php echo esc_attr( wp_create_nonce( 'thwecm_deactivate_nonce' ) ); ?>">
<?php
if($deactivation_reasons){
foreach($deactivation_reasons as $key => $reason){
@@ -790,18 +822,18 @@
}
?>
</ul>
- <p class="thwecm-privacy-cnt"><?php echo __('This form is only for getting your valuable feedback. We do not collect your personal data. To know more read our ', 'woo-email-customizer'); ?> <a class="thwecm-privacy-link" target="_blank" href="<?php echo esc_url('https://www.themehigh.com/privacy-policy/');?>"><?php echo __('Privacy Policy', 'woo-email-customizer'); ?></a></p>
+ <p class="thwecm-privacy-cnt"><?php echo esc_html__('This form is only for getting your valuable feedback. We do not collect your personal data. To know more read our ', 'email-customizer-for-woocommerce'); ?> <a class="thwecm-privacy-link" target="_blank" href="<?php echo esc_url('https://www.themehigh.com/privacy-policy/');?>"><?php echo esc_html__('Privacy Policy', 'email-customizer-for-woocommerce'); ?></a></p>
</main>
<footer class="modal-footer">
<div class="thwecm-left">
- <a class="thwecm-link thwecm-left-link thwecmf-deactivate" href="#"><?php echo __('Skip & Deactivate', 'woo-email-customizer'); ?></a>
+ <a class="thwecm-link thwecm-left-link thwecmf-deactivate" href="#"><?php echo esc_html__('Skip & Deactivate', 'email-customizer-for-woocommerce'); ?></a>
</div>
<div class="thwecm-right">
- <a class="thwecm-link thwecm-right-link thwecm-active" target="_blank" href="https://help.themehigh.com/hc/en-us/requests/new?utm_source=wec_free&utm_medium=feedback_form&utm_campaign=get_support"><?php echo __('Get Support', 'woo-email-customizer'); ?></a>
+ <a class="thwecm-link thwecm-right-link thwecm-active" target="_blank" href="https://help.themehigh.com/hc/en-us/requests/new?utm_source=wec_free&utm_medium=feedback_form&utm_campaign=get_support"><?php echo esc_html__('Get Support', 'email-customizer-for-woocommerce'); ?></a>
- <a class="thwecm-link thwecm-right-link thwecm-active thwecm-submit-deactivate" href="#"><?php echo __('Submit and Deactivate', 'woo-email-customizer'); ?></a>
- <a class="thwecm-link thwecm-right-link thwecm-close" href="#"><?php echo __('Cancel', 'woo-email-customizer'); ?></a>
+ <a class="thwecm-link thwecm-right-link thwecm-active thwecm-submit-deactivate" href="#"><?php echo esc_html__('Submit and Deactivate', 'email-customizer-for-woocommerce'); ?></a>
+ <a class="thwecm-link thwecm-right-link thwecm-close" href="#"><?php echo esc_html__('Cancel', 'email-customizer-for-woocommerce'); ?></a>
</div>
</footer>
</div>
@@ -1013,23 +1045,25 @@
reason_input += '<input type="checkbox" id="th-snooze" name="th-snooze" class="th-snooze-checkbox">';
reason_input += '<label for="th-snooze">Snooze this panel while troubleshooting</label>';
reason_input += '<select name="th-snooze-time" class="th-snooze-select" disabled>';
- reason_input += '<option value="<?php echo HOUR_IN_SECONDS ?>">1 Hour</option>';
- reason_input += '<option value="<?php echo 12*HOUR_IN_SECONDS ?>">12 Hour</option>';
- reason_input += '<option value="<?php echo DAY_IN_SECONDS ?>">24 Hour</option>';
- reason_input += '<option value="<?php echo WEEK_IN_SECONDS ?>">1 Week</option>';
- reason_input += '<option value="<?php echo MONTH_IN_SECONDS ?>">1 Month</option>';
+ reason_input += '<option value="<?php echo esc_attr ( HOUR_IN_SECONDS); ?>">1 Hour</option>';
+ reason_input += '<option value="<?php echo esc_attr ( 12*HOUR_IN_SECONDS); ?>">12 Hour</option>';
+ reason_input += '<option value="<?php echo esc_attr ( DAY_IN_SECONDS); ?>">24 Hour</option>';
+ reason_input += '<option value="<?php echo esc_attr ( WEEK_IN_SECONDS); ?>">1 Week</option>';
+ reason_input += '<option value="<?php echo esc_attr ( MONTH_IN_SECONDS); ?>">1 Month</option>';
reason_input += '</select>';
reason_input += '</div>';
}else if('reviewlink' == type){
reason_input += '<div class="reason-input wecm-review-link">';
+ // commented code is showing in ERROR category in PCP check
/*
- reason_input += '<?php _e('Deactivate and ', 'woo-email-customizer');?>'
+ reason_input += '<?php echo esc_attr__('Deactivate and ', 'email-customizer-for-woocommerce');?>'
reason_input += '<a href="#" target="_blank" class="thwecm-review-and-deactivate">';
- reason_input += '<?php _e('leave a review', 'woo-email-customizer'); ?>';
+ reason_input += '<?php echo esc_attr__('leave a review', 'email-customizer-for-woocommerce'); ?>';
reason_input += '<span class="wecm-rating-link"> ★★★★★ </span>';
reason_input += '</a>';
*/
- reason_input += '<input type="hidden" value="<?php _e('Upgraded', 'woo-email-customizer');?>">';
+ reason_input += '<input type="hidden" value="<?php echo esc_attr__( 'Upgraded', 'email-customizer-for-woocommerce' ); ?>">';
+ // reason_input += '<input type="hidden" value="<?php echo esc_attr__('Upgraded', 'email-customizer-for-woocommerce');?>">';
reason_input += '</div>';
}
@@ -1091,51 +1125,51 @@
return array(
'upgraded_to_pro' => array(
'radio_val' => 'upgraded_to_pro',
- 'radio_label' => __('Upgraded to premium.', 'woo-email-customizer'),
+ 'radio_label' => __('Upgraded to premium.', 'email-customizer-for-woocommerce'),
'reason_type' => 'reviewlink',
'reason_placeholder' => '',
),
'feature_missing'=> array(
'radio_val' => 'feature_missing',
- 'radio_label' => __('A specific feature is missing', 'woo-email-customizer'),
+ 'radio_label' => __('A specific feature is missing', 'email-customizer-for-woocommerce'),
'reason_type' => 'text',
- 'reason_placeholder' => __('Type in the feature', 'woo-email-customizer'),
+ 'reason_placeholder' => __('Type in the feature', 'email-customizer-for-woocommerce'),
),
'error_or_not_working'=> array(
'radio_val' => 'error_or_not_working',
- 'radio_label' => __('Found an error in the plugin/ Plugin was not working', 'woo-email-customizer'),
+ 'radio_label' => __('Found an error in the plugin/ Plugin was not working', 'email-customizer-for-woocommerce'),
'reason_type' => 'text',
- 'reason_placeholder' => __('Specify the issue', 'woo-email-customizer'),
+ 'reason_placeholder' => __('Specify the issue', 'email-customizer-for-woocommerce'),
),
'found_better_plugin' => array(
'radio_val' => 'found_better_plugin',
- 'radio_label' => __('I found a better Plugin', 'woo-email-customizer'),
+ 'radio_label' => __('I found a better Plugin', 'email-customizer-for-woocommerce'),
'reason_type' => 'text',
- 'reason_placeholder' => __('Could you please mention the plugin?', 'woo-email-customizer'),
+ 'reason_placeholder' => __('Could you please mention the plugin?', 'email-customizer-for-woocommerce'),
),
'hard_to_use' => array(
'radio_val' => 'hard_to_use',
- 'radio_label' => __('It was hard to use', 'woo-email-customizer'),
+ 'radio_label' => __('It was hard to use', 'email-customizer-for-woocommerce'),
'reason_type' => 'text',
- 'reason_placeholder' => __('How can we improve your experience?', 'woo-email-customizer'),
+ 'reason_placeholder' => __('How can we improve your experience?', 'email-customizer-for-woocommerce'),
),
'temporary' => array(
'radio_val' => 'temporary',
- 'radio_label' => __('It’s a temporary deactivation - I’m troubleshooting an issue', 'woo-email-customizer'),
+ 'radio_label' => __('It’s a temporary deactivation - I’m troubleshooting an issue', 'email-customizer-for-woocommerce'),
'reason_type' => 'checkbox',
- 'reason_placeholder' => __('Could you please mention the plugin?', 'woo-email-customizer'),
+ 'reason_placeholder' => __('Could you please mention the plugin?', 'email-customizer-for-woocommerce'),
),
'other' => array(
'radio_val' => 'other',
- 'radio_label' => __('Not mentioned here', 'woo-email-customizer'),
+ 'radio_label' => __('Not mentioned here', 'email-customizer-for-woocommerce'),
'reason_type' => 'textarea',
- 'reason_placeholder' => __('Kindly tell us your reason, so that we can improve', 'woo-email-customizer'),
+ 'reason_placeholder' => __('Kindly tell us your reason, so that we can improve', 'email-customizer-for-woocommerce'),
),
);
}
@@ -1151,7 +1185,7 @@
if($_POST['reason'] === 'temporary'){
- $snooze_period = isset($_POST['th-snooze-time']) && $_POST['th-snooze-time'] ? $_POST['th-snooze-time'] : MINUTE_IN_SECONDS ;
+ $snooze_period = isset($_POST['th-snooze-time']) && sanitize_text_field(wp_unslash($_POST['th-snooze-time'])) ? sanitize_text_field(wp_unslash($_POST['th-snooze-time'])) : MINUTE_IN_SECONDS ;
$time_now = time();
$snooze_time = $time_now + $snooze_period;
@@ -1162,10 +1196,10 @@
$data = array(
'plugin' => 'wecm',
- 'reason' => sanitize_text_field($_POST['reason']),
+ 'reason' => sanitize_text_field( wp_unslash($_POST['reason'])),
'comments' => isset($_POST['comments']) ? sanitize_textarea_field(wp_unslash($_POST['comments'])) : '',
'date' => gmdate("M d, Y h:i:s A"),
- 'software' => $_SERVER['SERVER_SOFTWARE'],
+ 'software' => isset($_SERVER['SERVER_SOFTWARE']) ? sanitize_text_field(wp_unslash($_SERVER['SERVER_SOFTWARE'])) : '',
'php_version' => phpversion(),
'mysql_version' => $wpdb->db_version(),
'wp_version' => get_bloginfo('version'),
--- a/email-customizer-for-woocommerce/classes/inc/class-wecmf-email-customizer-utils.php
+++ b/email-customizer-for-woocommerce/classes/inc/class-wecmf-email-customizer-utils.php
@@ -128,13 +128,18 @@
foreach( $files as $file ){ // iterate files
if( $file != '.' && $file != '..' ){ //scandir() contains two values '.' & '..'
if( is_file( $dir.'/'.$file ) ){
- unlink( $dir.'/'.$file ); // delete file
+ wp_delete_file( $dir.'/'.$file ); // delete file
}else if( is_dir( $dir.'/'.$file ) ){
self::delete_directory( $dir.'/'.$file );
}
}
}
- return rmdir( $dir );
+ global $wp_filesystem;
+ if ( empty( $wp_filesystem ) ) {
+ require_once ABSPATH . 'wp-admin/includes/file.php';
+ WP_Filesystem();
+ }
+ return $wp_filesystem->rmdir( $dir );
}
/**
@@ -421,13 +426,16 @@
*
* @return boolean valid template or not
*/
+
public static function wecm_valid( $name = '', $key=false ){
- if( $key && !empty( $name ) ){
- $name = str_replace("_", "-", $name);
- }else{
- $name = isset($_POST['template_name']) ? sanitize_text_field($_POST['template_name']) : "";
- $name = $name === "Customer Partial Refunded Order" ? "Customer Partially Refunded Order" : $name;
- $name = $name ? str_replace(" ", "-", strtolower($name)) : $name;
+ if(!empty($name)){
+ if($key){
+ $name = str_replace("_","-",$name);
+ }
+ else{
+ $name = $name === "Customer Partial Refunded Order" ? "Customer Partially Refunded Order" : $name;
+ $name = $name ? str_replace(" ", "-", strtolower($name)) : $name;
+ }
}
if( $name && array_key_exists( $name, self::email_statuses() ) ){
return true;
@@ -455,7 +463,8 @@
*/
public static function is_template($name=''){
$template = !empty( $name ) ? $name : false;
- $template = !$template && isset( $_POST['template_name'] ) ? sanitize_text_field( $_POST['template_name'] ) : $template;
+ // phpcs:ignore WordPress.Security.NonceVerification.Missing
+ $template = !$template && isset( $_POST['template_name'] ) ? sanitize_text_field( wp_unslash( $_POST['template_name'] ) ) : $template;
$template = str_replace( " ", "_", $template);
if( $template && in_array( $template, self::THWECMF_EMAIL_INDEX ) ){
return true;
@@ -564,6 +573,7 @@
* @return boolean template edit action or not
*/
public static function edit_template( $page ){
+ // phpcs:ignore WordPress.Security.NonceVerification.Missing
if( $page == 'thwecmf_email_customizer' && isset( $_POST['i_edit_template'] ) ){
return true;
}
@@ -576,7 +586,8 @@
* @return boolean template file existence
*/
public static function get_status(){
- $filename = isset( $_POST['i_template_name'] ) ? sanitize_text_field( $_POST['i_template_name'] ) : false;
+ // phpcs:ignore WordPress.Security.NonceVerification.Missing
+ $filename = isset( $_POST['i_template_name'] ) ? sanitize_text_field(wp_unslash( $_POST['i_template_name'] ) ) : false;
if( $filename ){
$file = rtrim(THWECMF_CUSTOM_T_PATH, '/').'/'.$filename.'.php';
if( file_exists( $file ) ){
@@ -701,13 +712,182 @@
return $capability;
}
- public static function dump( $str, $margin="100" ){
- ?>
- <pre style="margin-left:<?php echo esc_attr($margin); ?>px;">
- <?php echo var_dump($str); ?>
- </pre>
- <?php
+ /**
+ * Get allowed HTML tags and attributes for email template previews and sanitization
+ *
+ * @return array Allowed HTML elements with their attributes
+ */
+ public static function get_email_allowed_html() {
+ // Start with WordPress 'post' context
+ $allowed_html = wp_kses_allowed_html( 'post' );
+
+ // Allow <style> for CSS
+ $allowed_html['style'] = array(
+ 'type' => true,
+ );
+
+ // Fix for React Hooks - hooks.jsx uses data-block-name
+ $allowed_html['b'] = true;
+ $allowed_html['i'] = true;
+ $allowed_html['u'] = true;
+
+ $allowed_html['table']['data-block-name'] = true;
+ $allowed_html['table']['cellspacing'] = true;
+ $allowed_html['table']['cellpadding'] = true;
+ $allowed_html['table']['border'] = true;
+ $allowed_html['table']['align'] = true;
+ $allowed_html['table']['bgcolor'] = true;
+ $allowed_html['table']['width'] = true;
+ $allowed_html['table']['height'] = true;
+
+ // Table cells and rows
+ $allowed_html['table']['valign'] = true;
+ $allowed_html['td']['align'] = true;
+ $allowed_html['tr']['align'] = true;
+ $allowed_html['tr']['valign'] = true;
+ $allowed_html['p']['align'] = true;
+ $allowed_html['div']['align'] = true;
+ $allowed_html['h1']['align'] = true;
+ $allowed_html['h2']['align'] = true;
+ $allowed_html['h3']['align'] = true;
+ $allowed_html['td']['bgcolor'] = true;
+ $allowed_html['td']['width'] = true;
+ $allowed_html['td']['height'] = true;
+ $allowed_html['td']['valign'] = true;
+ $allowed_html['td']['colspan'] = true;
+ $allowed_html['td']['rowspan'] = true;
+ $allowed_html['td']['scope'] = true;
+
+ $allowed_html['th']['scope'] = true;
+ $allowed_html['th']['colspan'] = true;
+ $allowed_html['th']['rowspan'] = true;
+ $allowed_html['th']['width'] = true;
+ $allowed_html['th']['align'] = true;
+
+ $allowed_html['tr']['class'] = true;
+ $allowed_html['tr']['style'] = true;
+
+ // Table sections (WooCommerce uses these extensively)
+ $allowed_html['tbody'] = array();
+ $allowed_html['thead'] = array();
+ $allowed_html['tfoot'] = array();
+
+ // Time tag (for order dates)
+ $allowed_html['time'] = array(
+ 'datetime' => true,
+ 'title' => true,
+ );
+
+ // Address tag (WooCommerce billing/shipping addresses)
+ $allowed_html['address'] = array(
+ 'class' => true,
+ 'style' => true,
+ );
+
+ // Headings
+ $allowed_html['h1']['style'] = true;
+
+ $allowed_html['p']['class'] = true;
+ $allowed_html['p']['style'] = true;
+ // Images (WooCommerce uses inline styles heavily)
+ $allowed_html['img']['style'] = true;
+ $allowed_html['img']['loading'] = true; // lazy loading attribute
+ $allowed_html['img']['border'] = true;
+ // Links
+ $allowed_html['a']['rel'] = true;
+ $allowed_html['a']['style'] = true;
+
+ // Fix for Downloadable Products Table
+ $allowed_html['time'] = array(
+ 'datetime' => true,
+ 'title' => true,
+ );
+ $allowed_html['h2']['class'] = true;
+ $allowed_html['h2']['style'] = true;
+
+ $allowed_html['th'] = array(
+ 'scope' => true,
+ 'style' => true,
+ 'class' => true,
+ 'colspan' => true,
+ 'align' => true,
+ );
+
+ // Fix for WooCommerce Hooks (Order Details, Images, etc.)
+ $allowed_html['div']['class'] = true;
+ $allowed_html['div']['style'] = true;
+ $allowed_html['div']['id'] = true;
+
+ $allowed_html['span']['class'] = true;
+ $allowed_html['span']['style'] = true;
+
+ $allowed_html['img']['style'] = true; // WC emails use inline styles on images
+
+ $allowed_html['p']['class'] = true; // For "thwecmf-hook-code" class
+
+ return $allowed_html;
+ }
+
+
+ /**
+ * Get allowed HTML tags for textarea_content fields in template JSON used in sanitize_template_recursive.
+ * Only simple formatting elements — no img, script, iframe, table, etc.
+ *
+ * @return array Allowed HTML elements with their attributes
+ */
+ public static function get_template_json_allowed_html() {
+ return array(
+ // Basic formatting
+ 'b' => array(),
+ 'strong' => array(),
+ 'i' => array(),
+ 'em' => array(),
+ 'u' => array(),
+ 's' => array(),
+ 'strike' => array(),
+ 'del' => array(),
+ 'br' => array(),
+ 'hr' => array(),
+
+ // Text wrapping
+ 'p' => array(
+ 'style' => true,
+ 'class' => true,
+ 'align' => true,
+ ),
+ 'span' => array(
+ 'style' => true,
+ 'class' => true,
+ ),
+ 'div' => array(
+ 'style' => true,
+ 'class' => true,
+ ),
+
+ // Links
+ 'a' => array(
+ 'href' => true,
+ 'style' => true,
+ 'rel' => true,
+ ),
+
+ // Lists
+ 'ul' => array(),
+ 'ol' => array(),
+ 'li' => array(
+ 'style' => true,
+ ),
+
+ // Headings
+ 'h1' => array( 'style' => true ),
+ 'h2' => array( 'style' => true ),
+ 'h3' => array( 'style' => true ),
+ 'h4' => array( 'style' => true ),
+ 'h5' => array( 'style' => true ),
+ 'h6' => array( 'style' => true ),
+ );
}
+
}
endif;
No newline at end of file
--- a/email-customizer-for-woocommerce/classes/inc/class-wecmf-general-template.php
+++ b/email-customizer-for-woocommerce/classes/inc/class-wecmf-general-template.php
@@ -6,9 +6,9 @@
* @category Admin
*/
-use PelagoEmogrifierCssInliner;
-use PelagoEmogrifierHtmlProcessorCssToAttributeConverter;
-use PelagoEmogrifierHtmlProcessorHtmlPruner;
+// use PelagoEmogrifierCssInliner;
+// use PelagoEmogrifierHtmlProcessorCssToAttributeConverter;
+// use PelagoEmogrifierHtmlProcessorHtmlPruner;
if(!defined('ABSPATH')){ exit; }
@@ -22,6 +22,7 @@
private $wecm_order_item = '';
private $temp_wrapper_styles;
private $wecmf_ot_helper;
+
public function __construct() {
add_action('wp_ajax_thwecmf_template_actions', array($this,'save_template_content'));
@@ -84,12 +85,22 @@
public function preview_template(){
$response = false;
check_ajax_referer( 'thwecmf_preview_order', 'security' );
- $task = isset( $_POST['task'] ) ? sanitize_text_field( $_POST['task'] ) : false;
- if( WECMF_Utils::wecm_valid() && WECMF_Utils::is_user_capable() ){
+ $task = isset( $_POST['task'] ) ? sanitize_text_field( wp_unslash( $_POST['task'] ) ) : false;
+ // Get template name after nonce is verified
+ $template_name = isset( $_POST['template_name'] ) ? sanitize_text_field( wp_unslash( $_POST['template_name'] ) ) : '';
+ if( WECMF_Utils::wecm_valid($template_name) && WECMF_Utils::is_user_capable() ){
if( $task === 'reset_preview' ){
$this->reset_preview();
}else if( $task === 'create_preview' ){
- $response = $this->prepare_template();
+ $data = array(
+ 'order_id' => isset( $_POST['order_id'] ) ? absint( $_POST['order_id'] ) : false,
+ 'email_status' => isset( $_POST['email_status'] ) ? sanitize_text_field( wp_unslash( $_POST['email_status'] ) ) : false,
+ 'content_html' => isset( $_POST['content_html'] ) ? wp_kses_post( wp_unslash( $_POST['content_html'] ) ) : false,
+ 'template_name' => $template_name,
+ 'content_css' => isset( $_POST['content_css'] ) ? wp_kses_post( wp_unslash( $_POST['content_css'] ) ) : false,
+ 'imgDimensions' => isset( $_POST['imgDimensions'] ) ? map_deep( wp_unslash( $_POST['imgDimensions'] ), 'sanitize_text_field' ) : array(),
+ );
+ $response = $this->prepare_template($data);
}
}
wp_send_json( $response );
@@ -113,24 +124,26 @@
return $layout_css.$styles;
}
- private function prepare_template(){
- $order_id = isset( $_POST['order_id'] ) ? absint( $_POST['order_id'] ) : false;
- $email = isset( $_POST['email_status'] ) ? sanitize_text_field( $_POST['email_status'] ) : false;
- $content = isset( $_POST['content_html'] ) ? wp_kses_post( stripslashes( $_POST['content_html'] ) ) : false;
- $css = isset( $_POST['content_css'] ) ? wp_kses_post( stripslashes( $_POST['content_css'] ) ) : false;
- $css = $this->php8_comaptibiltiy_css( $css );
+ private function prepare_template($data){
+ $order_id = $data['order_id'];
+ $email = $data['email_status'];
+ $content = $data['content_html'];
+ $css = $data['content_css'];
+ $css = $this->php8_comaptibiltiy_css( $css );
+
if( $content && $css ){
- $css = $this->prepare_images($css);
+ $css = $this->prepare_images($css,$data['imgDimensions']);
$content = $this->prepare_email_content_wrapper($content);
$content = $this->create_inline_styles( $content, $css );
$content = $this->insert_dynamic_data($content, true);
WECMF_Utils::create_preview();
- $template_name = WECMF_Utils::prepare_template_name( sanitize_text_field( $_POST['template_name'] ) );
+ $template_name = WECMF_Utils::prepare_template_name( $data['template_name'] );
$template_name = $template_name == "customer_partial_refunded_order" ? "customer_partially_refunded_order" : $template_name;
$path_template = WECMF_Utils::preview_path($template_name);
return $this->save_template_file($content, $path_template);
}
return false;
+
}
/**
@@ -139,8 +152,12 @@
* @param string $css template styles
* @return string $css template styles
*/
- public function prepare_images($css){
- $dimensions = isset( $_POST['imgDimensions'] ) ? $_POST['imgDimensions'] : false;
+ public function prepare_images($css, $dimensions=null){
+ // Fallback: If caller didn't pass dimensions, try to find them in POST (Backwards Compatibility)
+ if ( $dimensions === null ) {
+ // phpcs:ignore WordPress.Security.NonceVerification.Missing
+ $dimensions = isset( $_POST['imgDimensions'] ) ? map_deep( wp_unslash( $_POST['imgDimensions'] ), 'sanitize_text_field' ) : false;
+ }
if(is_array($dimensions) && !empty($dimensions)){
foreach ($dimensions as $id => $dimension) {
$block = isset($dimension['blockName']) ? $dimension['blockName'] : false;
@@ -188,7 +205,8 @@
public function reset_preview(){
$ajaxAction = false;
$deleted = false;
- if( isset( $_POST["action"] ) && sanitize_text_field( $_POST["action"] ) === "thwecmf_reset_preview" ){
+ // phpcs:ignore WordPress.Security.NonceVerification.Missing
+ if( isset( $_POST["action"] ) && sanitize_text_field(wp_unslash( $_POST["action"] )) === "thwecmf_reset_preview" ){
$ajaxAction = true;
check_ajax_referer( 'thwecmf_reset_preview', 'security' );
}
@@ -206,14 +224,24 @@
* @return boolean action done or not
*/
public function save_template_content(){
+ check_ajax_referer( 'thwecmf_ajax_save', 'thwecmf_security' );
$response = '';
if( WECMF_Utils::is_valid_action() ){//Nonce, Capability
- $template_display_name = isset($_POST['template_name']) ? sanitize_text_field($_POST['template_name']) : "";
- if( WECMF_Utils::wecm_valid() ){
- $render_data = isset($_POST['contents']) ? wp_kses_post( trim( stripslashes( $_POST['contents'] ) ) ) : false;
- $render_css = isset($_POST['styles']) ? sanitize_textarea_field( stripslashes($_POST['styles'] ) ) : '';
+ $template_display_name = isset($_POST['template_name']) ? sanitize_text_field( wp_unslash( $_POST['template_name'] ) ) : "";
+ if( WECMF_Utils::wecm_valid($template_display_name) ){
+ // $render_data = isset($_POST['contents']) ? wp_kses_post( trim( stripslashes( $_POST['contents'] ) ) ) : false;
+ $render_data = isset($_POST['contents']) ? wp_kses( wp_unslash( $_POST['contents'] ), WECMF_Utils::get_email_allowed_html() ) : false;
+ $render_css = isset($_POST['styles']) ? wp_strip_all_tags( wp_unslash( $_POST['styles'] ) ) : '';
$render_css = $this->php8_comaptibiltiy_css( $render_css );
- $template_json = isset($_POST['template_tree']) ? wp_kses_post( trim( stripslashes( $_POST['template_tree'] ) ) ) : '';
+ // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- JSON decoded and sanitized via sanitize_template_recursive()
+ $raw_data = isset($_POST['template_tree']) ? sanitize_text_field (wp_unslash($_POST['template_tree'])) : '';
+ $decoded = json_decode($raw_data, true);
+ if (json_last_error() !== JSON_ERROR_NONE || !is_array($decoded)) {
+ wp_send_json_error('Invalid template data');
+ exit;
+ }
+ $sanitized_data = $this->sanitize_template_recursive($decoded);
+ $template_json = wp_json_encode($sanitized_data);
if($render_data){
$save_meta = false;
$template_name = WECMF_Utils::prepare_template_name($template_display_name);
@@ -232,6 +260,26 @@
}
/**
+ * Recursively sanitize template data
+ *
+ * @param mixed $data The data to sanitize
+ * @return mixed Sanitized data
+ */
+ private function sanitize_template_recursive($data) {
+ if (is_array($data)) {
+ foreach ($data as $key => &$value) {
+ if ($key === 'textarea_content' && is_string($value)) {
+ $value = wp_kses($value, WECMF_Utils::get_template_json_allowed_html());
+ } elseif (is_array($value)) {
+ $value = $this->sanitize_template_recursive($value);
+ }
+ }
+ }
+ return $data;
+ }
+
+
+ /**
* Save the template settings to database
*
* @param string $template_name template name key
@@ -270,18 +318,29 @@
public function send_test_mail(){
$response = "failure";
$created = false;
- if( isset( $_POST['template'] ) && WECMF_Utils::wecm_valid() && WECMF_Utils::is_user_capable() ){
+ // Add nonce verification
+ check_ajax_referer( 'thwecmf_ajax_save', 'thwecmf_security' );
+ // Get template name (it's being sent!)
+ $template_name = isset( $_POST['template_name'] )
+ ? sanitize_text_field( wp_unslash( $_POST['template_name'] ) )
+ : '';
+ if( isset( $_POST['template'] ) && WECMF_Utils::wecm_valid($template_name) && WECMF_Utils::is_user_capable() ){
$order_id = isset( $_POST['order_id'] ) ? absint( $_POST['order_id'] ) : false;
- $email = isset( $_POST['email_status'] ) ? sanitize_text_field( $_POST['email_status'] ) : false;
- $content = isset( $_POST['template'] ) ? wp_kses_post( stripslashes( $_POST['template'] ) ) : false;
- $css = isset( $_POST['styles'] ) ? wp_kses_post( stripslashes( $_POST['styles'] ) ) : false;
+ $email = isset( $_POST['email_status'] ) ? sanitize_text_field( wp_unslash( $_POST['email_status'] ) ) : false;
+ $content = isset( $_POST['template'] ) ? wp_kses_post( wp_unslash( $_POST['template'] ) ) : false;
+ $css = isset( $_POST['styles'] ) ? wp_kses_post( wp_unslash( $_POST['styles'] ) ) : false;
$css = $this->php8_comaptibiltiy_css( $css );
$css = $this->prepare_images($css);
$content = $this->prepare_email_content_wrapper($content);
$content = $this->create_inline_styles( $content, $css );
$content = $this->insert_dynamic_data($content, true);
WECMF_Utils::create_preview();
- $template_name = WECMF_Utils::prepare_template_name( sanitize_text_field( $_POST['template_name'] ) );
+ // $template_name = WECMF_Utils::prepare_template_name( sanitize_text_field( $_POST['template_name'] ) );
+ $template_name = isset( $_POST['template_name'] )
+ ? WECMF_Utils::prepare_template_name(
+ sanitize_text_field( wp_unslash( $_POST['template_name'] ) )
+ )
+ : '';
$template_name = $template_name == "customer_partial_refunded_order" ? "customer_partially_refunded_order" : $template_name;
$path_template = WECMF_Utils::preview_path($template_name);
@@ -302,17 +361,24 @@
* @return boolean $send_mail mail sent or not
*/
public function send_mail( $message ){
- $to = $this->get_from_address();
+ check_ajax_referer( 'thwecmf_ajax_save', 'thwecmf_security' );
+ $email_id = isset( $_POST['email_id'] ) ? sanitize_email( wp_unslash( $_POST['email_id'] ) ) : '';
+ $to = $this->get_from_address($email_id);
$subject = "[".get_bloginfo('name')."] Test Email";
$headers = $this->setup_test_mail_variables( $to );
+
+ // 3. Use a closure to force the filter to use our resolved $to address
+ $from_callback = function( $original_from ) use ( $to ) {
+ return $to ? $to : $original_from;
+ };
- add_filter( 'wp_mail_from', array( $this, 'get_from_address' ) );
+ add_filter( 'wp_mail_from', $from_callback);
add_filter( 'wp_mail_from_name', array( $this, 'get_from_name' ) );
add_filter( 'wp_mail_content_type', array( $this, 'get_content_type' ) );
$send_mail = wp_mail( $to, $subject, $message, $headers );
- remove_filter( 'wp_mail_from', array( $this, 'get_from_address' ) );
+ remove_filter( 'wp_mail_from', $from_callback);
remove_filter( 'wp_mail_from_name', array( $this, 'get_from_name' ) );
remove_filter( 'wp_mail_content_type', array( $this, 'get_content_type' ) );
return $send_mail;
@@ -332,9 +398,15 @@
*
* @return string from email
*/
- public function get_from_address() {
+ public function get_from_address($email_id='') {
+ // 1. If we have a passed parameter, use it immediately
+ if ( ! empty( $email_id ) ) {
+ return $email_id;
+ }
+ // phpcs:ignore WordPress.Security.NonceVerification.Missing
if( isset( $_POST['email_id'] ) && !empty( $_POST['email_id'] ) ){
- return sanitize_email( $_POST['email_id'] );
+ //phpcs:ignore WordPress.Security.NonceVerification.Missing
+ return sanitize_email(wp_unslash( $_POST['email_id'] ));
}
}
@@ -394,14 +466,25 @@
* @return boolean $saved file created or not
*/
public function save_template_file($content, $path){
- $saved = false;
- $myfile_template = fopen($path, "w") or die("Unable to open file!");
- if(false !== $myfile_template){
- fwrite($myfile_template, $content);
- fclose($myfile_template);
- $saved = true;
+ if ( ! function_exists( 'WP_Filesystem' ) ) {
+ require_once ABSPATH . 'wp-admin/includes/file.php';
+ }
+ WP_Filesystem();
+ global $wp_filesystem;
+ if ( ! $wp_filesystem ) {
+ return false;
}
- return $saved;
+
+ $saved = false;
+ // Normalize path for safety
+ $path = wp_normalize_path( $path );
+
+ // Write file using WP filesystem API
+ return $wp_filesystem->put_contents(
+ $path,
+ $content,
+ FS_CHMOD_FILE
+ );
}
/**
@@ -413,19 +496,34 @@
*/
public function create_inline_styles( $content, $css ) {
if( WECMF_Utils::thwecmf_woo_version_check('6.5.0') ){
- $css_inliner_class = CssInliner::class;
+ // WooCommerce 10.4+ uses vendor-prefixed namespace
+ if( WECMF_Utils::thwecmf_woo_version_check('10.4.0') ){
+ $css_inliner_class = 'AutomatticWooCommerceEmailEditorVendorPelagoEmogrifierCssInliner';
+ $html_pruner_class = 'AutomatticWooCommerceEmailEditorVendorPelagoEmogrifierHtmlProcessorHtmlPruner';
+ $css_to_attr_class = 'AutomatticWooCommerceEmailEditorVendorPelagoEmogrifierHtmlProcessorCssToAttributeConverter';
+ } else {
+ $css_inliner_class = 'PelagoEmogrifierCssInliner';
+ $html_pruner_class = 'PelagoEmogrifierHtmlProcessorHtmlPruner';
+ $css_to_attr_class = 'PelagoEmogrifierHtmlProcessorCssToAttributeConverter';
+ }
if ( class_exists( 'DOMDocument' ) && class_exists( $css_inliner_class ) ) {
try {
- $css_inliner = CssInliner::fromHtml( $content )->inlineCss( $css );
+ // $css_inliner = CssInliner::fromHtml( $content )->inlineCss( $css );
+ $css_inliner = $css_inliner_class::fromHtml( $content )->inlineCss( $css );
do_action( 'woocommerce_emogrifier', $css_inliner, $this );
$dom_document = $css_inliner->getDomDocument();
- HtmlPruner::fromDomDocument( $dom_document )->removeElementsWithDisplayNone();
- $content = CssToAttributeConverter::fromDomDocument( $dom_document )
- ->convertCssToVisualAttributes()
- ->render();
+ // HtmlPruner::fromDomDocument( $dom_document )->removeElementsWithDisplayNone();
+ $html_pruner_class::fromDomDocument( $dom_document )->removeElementsWithDisplayNone();
+ // $content = CssToAttributeConverter::fromDomDocument( $dom_document )
+ // ->convertCssToVisualAttributes()
+ // ->render();
+ $content = $css_to_attr_class::fromDomDocument( $dom_document )
+ ->convertCssToVisualAttributes()
+ ->render();
+ // $content = htmlspecialchars_decode($content);
$content = htmlspecialchars_decode($content);
} catch ( Exception $e ) {
$logger = wc_get_logger();
--- a/email-customizer-for-woocommerce/classes/inc/class-wecmf-template-settings.php
+++ b/email-customizer-for-woocommerce/classes/inc/class-wecmf-template-settings.php
@@ -131,13 +131,21 @@
*
* @return string $settings settings to be saved
*/
- private function prepare_settings(){
+ private function prepare_settings( $template_list=array() ){
$settings = WECMF_Utils::thwecmf_get_template_settings();
$template_map = isset( $settings[WECMF_Utils::SETTINGS_KEY_TEMPLATE_MAP] ) ? $settings[WECMF_Utils::SETTINGS_KEY_TEMPLATE_MAP] : array();
$file_ext = 'php';
- foreach ($_POST['i_template-list'] as $key => $value) {
- $template_map[$this->template_status[sanitize_text_field( $key )]] = sanitize_text_field($value);
- }
+ if (is_array( $template_list ) && !empty( $template_list )) {
+ // return $settings;
+ // $template_list = wp_unslash( $_POST['i_template-list'] );
+ foreach ($template_list as $key => $value) {
+ $sanitized_key = sanitize_text_field( $key );
+ $sanitized_value = sanitize_text_field( $value );
+ if ( isset( $this->template_status[ $sanitized_key ] ) ) {
+ $template_map[ $this->template_status[ $sanitized_key ] ] = $sanitized_value;
+ }
+ }
+ }
$settings[WECMF_Utils::SETTINGS_KEY_TEMPLATE_MAP] = $template_map;
return $settings;
}
@@ -149,11 +157,13 @@
*/
private function save_settings(){
$result = false;
- if( !isset($_POST['i_template-list']) || !isset( $_POST['thwecmf_template_map'] ) || !wp_verify_nonce( $_POST['thwecmf_template_map'], 'template_map_action' ) || !WECMF_Utils::is_user_capable() ){
+ if( !isset($_POST['i_template-list']) || !isset( $_POST['thwecmf_template_map'] ) || !wp_verify_nonce(sanitize_text_field( wp_unslash( $_POST['thwecmf_template_map'] ) ), 'template_map_action' ) || !WECMF_Utils::is_user_capable() ){
wp_die( '<div class="wecm-wp-die-message">Action failed. Could not verify nonce.</div>' );
}
$temp_data = array();
- $settings = $this->prepare_settings();
+ // $template_list = isset( $_POST['i_template-list'] ) ? wp_unslash( $_POST['i_template-list'] ) : array();
+ $template_list = isset( $_POST['i_template-list'] ) ? array_map( 'sanitize_text_field', wp_unslash( $_POST['i_template-list'] ) ) : array();
+ $settings = $this->prepare_settings($template_list);
$result = WECMF_Utils::thwecmf_save_template_settings($settings);
return $result;
}
@@ -183,9 +193,11 @@
private function reset_template(){
$result = false;
$file_reset = false;
- $template = isset( $_POST['i_template_name'] ) ? sanitize_text_field( $_POST['i_template_name'] ) : false;
+ $template = isset( $_POST['i_template_name'] ) ? sanitize_text_field(wp_unslash( $_POST['i_template_name'] ) ) : false;
if( $template ){
- if( !wp_verify_nonce( $_POST['thwecmf_edit_template_'.$template], 'thwecmf_edit_template' ) || !WECMF_Utils::is_user_capable() ){
+ $nonce_key = 'thwecmf_edit_template_' . $template;
+ if (! isset( $_POST[ $nonce_key ] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST[ $nonce_key ] ) ), 'thwecmf_edit_template' ) || ! WECMF_Utils::is_user_capable())
+ {
wp_die( '<div class="wecm-wp-die-message">Action failed. Could not verify nonce.</div>' );
}
$result = WECMF_Utils::thwecmf_reset_templates( $template );
@@ -206,7 +218,7 @@
private function reset_settings(){
$result = false;
- if( !isset( $_POST['thwecmf_template_map'] ) || !wp_verify_nonce( $_POST['thwecmf_template_map'], 'template_map_action' ) || !WECMF_Utils::is_user_capable() ){
+ if( !isset( $_POST['thwecmf_template_map'] ) || !wp_verify_nonce(sanitize_text_field( wp_unslash( $_POST['thwecmf_template_map'] ) ), 'template_map_action' ) || !WECMF_Utils::is_user_capable() ){
wp_die( '<div class="wecm-wp-die-message">Action failed. Could not verify nonce.</div>' );
}else{
$result = $this->reset_to_default();
@@ -273,7 +285,7 @@
$url = $key === "customer_cancelled_order" ? "admin_cancelled_order" : $url;
?>
<div class="thwecmf-template-box">
- <form name="thwecmf_edit_template_form_<?php echo $key; ?>" action="" method="POST">
+ <form name="thwecmf_edit_template_form_<?php echo esc_attr( $key ); ?>" action="" method="POST">
<?php
if ( function_exists('wp_nonce_field') ){
wp_nonce_field( 'thwecmf_edit_template', 'thwecmf_edit_template_'.$key );
@@ -289,10 +301,10 @@
<div class="template-manage-menu">
<div class="template-manage-menu-item">
<button type="submit" class="thwecmf-template-action-links" formaction="<?php $this->get_admin_url(); ?>" name="i_edit_template">
- <img src="<?php echo TH_WECMF_ASSETS_URL ?>images/template-edit.svg" class="template-edit-icon">
+ <img src="<?php echo esc_url( TH_WECMF_ASSETS_URL . "images/template-edit.svg" ); ?>" class="template-edit-icon">
</button>
<button type="submit" class="thwecmf-template-action-links thwecmf-reset-link" name="reset_template" onclick="return confirm('Template will be reset to initial condition. Do you want to proceed ?');">
- <img src="<?php echo TH_WECMF_ASSETS_URL ?>images/template-reset.svg">
+ <img src="<?php echo esc_url( TH_WECMF_ASSETS_URL . "images/template-reset.svg" ); ?>" class="template-reset-icon">
</button>
</div>
</div>
@@ -308,14 +320,15 @@
public function render_notifications(){
$result = "load";
$action = "";
+ //phpcs:ignore WordPress.Security.NonceVerification.Missing
if( isset( $_POST['save_settings'] ) ){
$result = $this->save_settings();
$action = "save";
-
+ //phpcs:ignore WordPress.Security.NonceVerification.Missing
}else if( isset( $_POST['reset_settings'] ) ){
$result = $this->reset_settings();
$action = "reset";
-
+ //phpcs:ignore WordPress.Security.NonceVerification.Missing
}else if( isset( $_POST['res