Plugin Directory

Changeset 3399346


Ignore:
Timestamp:
11/20/2025 03:38:02 AM (4 months ago)
Author:
matrixaddons
Message:

Update to version 2.1.5 from GitHub

Location:
easy-invoice
Files:
8 edited
1 copied

Legend:

Unmodified
Added
Removed
  • easy-invoice/tags/2.1.5/easy-invoice.php

    r3393362 r3399346  
    44 * Plugin URI: https://matrixaddons.com/plugins/easy-invoice
    55 * Description: A beautiful, full-featured invoicing solution for WordPress. Create professional invoices, quotes, and manage payments with ease.
    6  * Version: 2.1.4
     6 * Version: 2.1.5
    77 * Author: MatrixAddons
    88 * Author URI: https://matrixaddons.com
     
    2525
    2626// Define plugin constants.
    27 define( 'EASY_INVOICE_VERSION', '2.1.4' );
     27define( 'EASY_INVOICE_VERSION', '2.1.5' );
    2828define( 'EASY_INVOICE_PLUGIN_FILE', __FILE__ );
    2929define( 'EASY_INVOICE_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
  • easy-invoice/tags/2.1.5/includes/Controllers/InvoiceController.php

    r3377511 r3399346  
    795795        }
    796796
    797         // Get template name
     797        // Get template name and validate it securely
    798798        $template = isset($_POST['template']) ? sanitize_text_field($_POST['template']) : 'standard';
     799        $template = $this->validateTemplateName($template, 'invoice');
    799800        $invoice_id = isset($_POST['invoice_id']) ? intval($_POST['invoice_id']) : 0;
     801
     802        // Get secure template file path
     803        $template_file = $this->getSecureTemplatePath($template, 'invoice');
     804       
     805        if (!$template_file) {
     806            wp_send_json_error(array('message' => __('Invalid template', 'easy-invoice')));
     807        }
    800808
    801809        // For new invoices (no ID), just return the template without invoice data
    802810        if ($invoice_id === 0) {
    803             // Get template file path
    804             $template_file = EASY_INVOICE_PLUGIN_DIR . 'templates/invoice-templates/' . $template . '.php';
    805            
    806             if (!file_exists($template_file)) {
    807                 $template_file = EASY_INVOICE_PLUGIN_DIR . 'templates/invoice-templates/standard.php';
    808             }
    809 
    810811            // Start output buffering
    811812            ob_start();
     
    815816            $formatter = null;
    816817           
    817            
    818818            include_once $template_file;
    819819            $html = ob_get_clean();
     
    834834        // Initialize formatter for currency formatting
    835835        $formatter = new \EasyInvoice\Helpers\InvoiceFormatter($invoice);
    836 
    837         // Get template file path
    838         $template_file = EASY_INVOICE_PLUGIN_DIR . 'templates/invoice-templates/' . $template . '.php';
    839        
    840         if (!file_exists($template_file)) {
    841             $template_file = EASY_INVOICE_PLUGIN_DIR . 'templates/invoice-templates/standard.php';
    842         }
    843836
    844837        // Start output buffering
     
    849842        // Send response
    850843        wp_send_json_success(array('html' => $html));
     844    }
     845
     846    /**
     847     * Validate and sanitize template name to prevent directory traversal attacks
     848     *
     849     * @param string $template The template name to validate
     850     * @param string $type Either 'invoice' or 'quote'
     851     * @return string Validated template name or 'standard' as fallback
     852     */
     853    private function validateTemplateName($template, $type = 'invoice') {
     854        // Whitelist of allowed template names
     855        $allowed_templates = array(
     856            'invoice' => array('classic', 'corporate', 'creative', 'elegant', 'legacy', 'minimal', 'modern', 'professional', 'standard'),
     857            'quote' => array('legacy', 'minimal', 'minimalist', 'modern', 'standard')
     858        );
     859
     860        // Strip any directory components using basename
     861        $template = basename($template);
     862       
     863        // Remove any file extension
     864        $template = preg_replace('/\.(php|html|htm)$/i', '', $template);
     865       
     866        // Remove any non-alphanumeric characters except hyphens and underscores
     867        $template = preg_replace('/[^a-z0-9_-]/i', '', $template);
     868       
     869        // Check if template is in whitelist
     870        if (isset($allowed_templates[$type]) && in_array($template, $allowed_templates[$type], true)) {
     871            return $template;
     872        }
     873       
     874        // Return default template if not in whitelist
     875        return 'standard';
     876    }
     877
     878    /**
     879     * Get secure template file path with directory traversal protection
     880     *
     881     * @param string $template The validated template name
     882     * @param string $type Either 'invoice' or 'quote'
     883     * @return string|false The secure template file path or false if invalid
     884     */
     885    private function getSecureTemplatePath($template, $type = 'invoice') {
     886        // Define template directories
     887        $template_dirs = array(
     888            'invoice' => EASY_INVOICE_PLUGIN_DIR . 'templates/invoice-templates/',
     889            'quote' => EASY_INVOICE_PLUGIN_DIR . 'templates/quote-templates/'
     890        );
     891
     892        if (!isset($template_dirs[$type])) {
     893            return false;
     894        }
     895
     896        $template_dir = $template_dirs[$type];
     897       
     898        // Ensure template directory exists and is a directory
     899        if (!is_dir($template_dir)) {
     900            return false;
     901        }
     902
     903        // Get the real path of the template directory (resolves any symlinks)
     904        $real_template_dir = realpath($template_dir);
     905        if ($real_template_dir === false) {
     906            return false;
     907        }
     908
     909        // Construct the template file path
     910        $template_file = $real_template_dir . DIRECTORY_SEPARATOR . $template . '.php';
     911       
     912        // Get the real path of the template file (resolves any .. or . components)
     913        $real_template_file = realpath($template_file);
     914       
     915        // Verify that the resolved path is within the template directory
     916        // This prevents directory traversal attacks
     917        if ($real_template_file === false || strpos($real_template_file, $real_template_dir) !== 0) {
     918            // If template doesn't exist or is outside the directory, use default
     919            $default_file = $real_template_dir . DIRECTORY_SEPARATOR . 'standard.php';
     920            $real_default_file = realpath($default_file);
     921           
     922            if ($real_default_file !== false && strpos($real_default_file, $real_template_dir) === 0) {
     923                return $real_default_file;
     924            }
     925           
     926            return false;
     927        }
     928
     929        // Verify the file exists and is readable
     930        if (!is_file($real_template_file) || !is_readable($real_template_file)) {
     931            // Fallback to standard template
     932            $default_file = $real_template_dir . DIRECTORY_SEPARATOR . 'standard.php';
     933            $real_default_file = realpath($default_file);
     934           
     935            if ($real_default_file !== false && strpos($real_default_file, $real_template_dir) === 0 && is_file($real_default_file) && is_readable($real_default_file)) {
     936                return $real_default_file;
     937            }
     938           
     939            return false;
     940        }
     941
     942        return $real_template_file;
    851943    }
    852944
  • easy-invoice/tags/2.1.5/includes/Controllers/QuoteController.php

    r3393362 r3399346  
    567567        }
    568568       
     569        // Validate template name securely
     570        $template_id = $this->validateTemplateName($template_id, 'quote');
     571       
     572        // Get secure template file path
     573        $template_file = $this->getSecureTemplatePath($template_id, 'quote');
     574       
     575        if (!$template_file) {
     576            wp_send_json_error(['message' => __('Template not found.', 'easy-invoice')]);
     577        }
     578       
    569579        // Load quote if provided
    570580        $quote = null;
     
    573583        }
    574584       
    575         // Check if template file exists
    576         $template_file = EASY_INVOICE_PLUGIN_DIR . 'templates/quote-templates/' . $template_id . '.php';
    577        
    578         if (!file_exists($template_file)) {
    579             wp_send_json_error(['message' => __('Template not found.', 'easy-invoice')]);
    580         }
    581        
    582585        // Start output buffering to capture template HTML
    583586        ob_start();
     
    590593       
    591594        wp_send_json_success(['html' => $html]);
     595    }
     596
     597    /**
     598     * Validate and sanitize template name to prevent directory traversal attacks
     599     *
     600     * @param string $template The template name to validate
     601     * @param string $type Either 'invoice' or 'quote'
     602     * @return string Validated template name or 'standard' as fallback
     603     */
     604    private function validateTemplateName($template, $type = 'quote') {
     605        // Whitelist of allowed template names
     606        $allowed_templates = array(
     607            'invoice' => array('classic', 'corporate', 'creative', 'elegant', 'legacy', 'minimal', 'modern', 'professional', 'standard'),
     608            'quote' => array('legacy', 'minimal', 'minimalist', 'modern', 'standard')
     609        );
     610
     611        // Strip any directory components using basename
     612        $template = basename($template);
     613       
     614        // Remove any file extension
     615        $template = preg_replace('/\.(php|html|htm)$/i', '', $template);
     616       
     617        // Remove any non-alphanumeric characters except hyphens and underscores
     618        $template = preg_replace('/[^a-z0-9_-]/i', '', $template);
     619       
     620        // Check if template is in whitelist
     621        if (isset($allowed_templates[$type]) && in_array($template, $allowed_templates[$type], true)) {
     622            return $template;
     623        }
     624       
     625        // Return default template if not in whitelist
     626        return 'standard';
     627    }
     628
     629    /**
     630     * Get secure template file path with directory traversal protection
     631     *
     632     * @param string $template The validated template name
     633     * @param string $type Either 'invoice' or 'quote'
     634     * @return string|false The secure template file path or false if invalid
     635     */
     636    private function getSecureTemplatePath($template, $type = 'quote') {
     637        // Define template directories
     638        $template_dirs = array(
     639            'invoice' => EASY_INVOICE_PLUGIN_DIR . 'templates/invoice-templates/',
     640            'quote' => EASY_INVOICE_PLUGIN_DIR . 'templates/quote-templates/'
     641        );
     642
     643        if (!isset($template_dirs[$type])) {
     644            return false;
     645        }
     646
     647        $template_dir = $template_dirs[$type];
     648       
     649        // Ensure template directory exists and is a directory
     650        if (!is_dir($template_dir)) {
     651            return false;
     652        }
     653
     654        // Get the real path of the template directory (resolves any symlinks)
     655        $real_template_dir = realpath($template_dir);
     656        if ($real_template_dir === false) {
     657            return false;
     658        }
     659
     660        // Construct the template file path
     661        $template_file = $real_template_dir . DIRECTORY_SEPARATOR . $template . '.php';
     662       
     663        // Get the real path of the template file (resolves any .. or . components)
     664        $real_template_file = realpath($template_file);
     665       
     666        // Verify that the resolved path is within the template directory
     667        // This prevents directory traversal attacks
     668        if ($real_template_file === false || strpos($real_template_file, $real_template_dir) !== 0) {
     669            // If template doesn't exist or is outside the directory, use default
     670            $default_file = $real_template_dir . DIRECTORY_SEPARATOR . 'standard.php';
     671            $real_default_file = realpath($default_file);
     672           
     673            if ($real_default_file !== false && strpos($real_default_file, $real_template_dir) === 0) {
     674                return $real_default_file;
     675            }
     676           
     677            return false;
     678        }
     679
     680        // Verify the file exists and is readable
     681        if (!is_file($real_template_file) || !is_readable($real_template_file)) {
     682            // Fallback to standard template
     683            $default_file = $real_template_dir . DIRECTORY_SEPARATOR . 'standard.php';
     684            $real_default_file = realpath($default_file);
     685           
     686            if ($real_default_file !== false && strpos($real_default_file, $real_template_dir) === 0 && is_file($real_default_file) && is_readable($real_default_file)) {
     687                return $real_default_file;
     688            }
     689           
     690            return false;
     691        }
     692
     693        return $real_template_file;
    592694    }
    593695   
  • easy-invoice/tags/2.1.5/readme.txt

    r3393362 r3399346  
    55Tested up to: 6.8
    66Requires PHP: 7.4
    7 Stable tag: 2.1.4
     7Stable tag: 2.1.5
    88License: GPLv2 or later
    99License URI: https://www.gnu.org/licenses/gpl-2.0.html
     
    138138== Changelog ==
    139139
     140= 2.1.5 - 2025-11-20 =
     141* Fixed - Template loading issue fixed
     142
    140143= 2.1.4 - 2025-11-11 =
    141144* Fixed - Email issue fixed
  • easy-invoice/trunk/easy-invoice.php

    r3393362 r3399346  
    44 * Plugin URI: https://matrixaddons.com/plugins/easy-invoice
    55 * Description: A beautiful, full-featured invoicing solution for WordPress. Create professional invoices, quotes, and manage payments with ease.
    6  * Version: 2.1.4
     6 * Version: 2.1.5
    77 * Author: MatrixAddons
    88 * Author URI: https://matrixaddons.com
     
    2525
    2626// Define plugin constants.
    27 define( 'EASY_INVOICE_VERSION', '2.1.4' );
     27define( 'EASY_INVOICE_VERSION', '2.1.5' );
    2828define( 'EASY_INVOICE_PLUGIN_FILE', __FILE__ );
    2929define( 'EASY_INVOICE_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
  • easy-invoice/trunk/includes/Controllers/InvoiceController.php

    r3377511 r3399346  
    795795        }
    796796
    797         // Get template name
     797        // Get template name and validate it securely
    798798        $template = isset($_POST['template']) ? sanitize_text_field($_POST['template']) : 'standard';
     799        $template = $this->validateTemplateName($template, 'invoice');
    799800        $invoice_id = isset($_POST['invoice_id']) ? intval($_POST['invoice_id']) : 0;
     801
     802        // Get secure template file path
     803        $template_file = $this->getSecureTemplatePath($template, 'invoice');
     804       
     805        if (!$template_file) {
     806            wp_send_json_error(array('message' => __('Invalid template', 'easy-invoice')));
     807        }
    800808
    801809        // For new invoices (no ID), just return the template without invoice data
    802810        if ($invoice_id === 0) {
    803             // Get template file path
    804             $template_file = EASY_INVOICE_PLUGIN_DIR . 'templates/invoice-templates/' . $template . '.php';
    805            
    806             if (!file_exists($template_file)) {
    807                 $template_file = EASY_INVOICE_PLUGIN_DIR . 'templates/invoice-templates/standard.php';
    808             }
    809 
    810811            // Start output buffering
    811812            ob_start();
     
    815816            $formatter = null;
    816817           
    817            
    818818            include_once $template_file;
    819819            $html = ob_get_clean();
     
    834834        // Initialize formatter for currency formatting
    835835        $formatter = new \EasyInvoice\Helpers\InvoiceFormatter($invoice);
    836 
    837         // Get template file path
    838         $template_file = EASY_INVOICE_PLUGIN_DIR . 'templates/invoice-templates/' . $template . '.php';
    839        
    840         if (!file_exists($template_file)) {
    841             $template_file = EASY_INVOICE_PLUGIN_DIR . 'templates/invoice-templates/standard.php';
    842         }
    843836
    844837        // Start output buffering
     
    849842        // Send response
    850843        wp_send_json_success(array('html' => $html));
     844    }
     845
     846    /**
     847     * Validate and sanitize template name to prevent directory traversal attacks
     848     *
     849     * @param string $template The template name to validate
     850     * @param string $type Either 'invoice' or 'quote'
     851     * @return string Validated template name or 'standard' as fallback
     852     */
     853    private function validateTemplateName($template, $type = 'invoice') {
     854        // Whitelist of allowed template names
     855        $allowed_templates = array(
     856            'invoice' => array('classic', 'corporate', 'creative', 'elegant', 'legacy', 'minimal', 'modern', 'professional', 'standard'),
     857            'quote' => array('legacy', 'minimal', 'minimalist', 'modern', 'standard')
     858        );
     859
     860        // Strip any directory components using basename
     861        $template = basename($template);
     862       
     863        // Remove any file extension
     864        $template = preg_replace('/\.(php|html|htm)$/i', '', $template);
     865       
     866        // Remove any non-alphanumeric characters except hyphens and underscores
     867        $template = preg_replace('/[^a-z0-9_-]/i', '', $template);
     868       
     869        // Check if template is in whitelist
     870        if (isset($allowed_templates[$type]) && in_array($template, $allowed_templates[$type], true)) {
     871            return $template;
     872        }
     873       
     874        // Return default template if not in whitelist
     875        return 'standard';
     876    }
     877
     878    /**
     879     * Get secure template file path with directory traversal protection
     880     *
     881     * @param string $template The validated template name
     882     * @param string $type Either 'invoice' or 'quote'
     883     * @return string|false The secure template file path or false if invalid
     884     */
     885    private function getSecureTemplatePath($template, $type = 'invoice') {
     886        // Define template directories
     887        $template_dirs = array(
     888            'invoice' => EASY_INVOICE_PLUGIN_DIR . 'templates/invoice-templates/',
     889            'quote' => EASY_INVOICE_PLUGIN_DIR . 'templates/quote-templates/'
     890        );
     891
     892        if (!isset($template_dirs[$type])) {
     893            return false;
     894        }
     895
     896        $template_dir = $template_dirs[$type];
     897       
     898        // Ensure template directory exists and is a directory
     899        if (!is_dir($template_dir)) {
     900            return false;
     901        }
     902
     903        // Get the real path of the template directory (resolves any symlinks)
     904        $real_template_dir = realpath($template_dir);
     905        if ($real_template_dir === false) {
     906            return false;
     907        }
     908
     909        // Construct the template file path
     910        $template_file = $real_template_dir . DIRECTORY_SEPARATOR . $template . '.php';
     911       
     912        // Get the real path of the template file (resolves any .. or . components)
     913        $real_template_file = realpath($template_file);
     914       
     915        // Verify that the resolved path is within the template directory
     916        // This prevents directory traversal attacks
     917        if ($real_template_file === false || strpos($real_template_file, $real_template_dir) !== 0) {
     918            // If template doesn't exist or is outside the directory, use default
     919            $default_file = $real_template_dir . DIRECTORY_SEPARATOR . 'standard.php';
     920            $real_default_file = realpath($default_file);
     921           
     922            if ($real_default_file !== false && strpos($real_default_file, $real_template_dir) === 0) {
     923                return $real_default_file;
     924            }
     925           
     926            return false;
     927        }
     928
     929        // Verify the file exists and is readable
     930        if (!is_file($real_template_file) || !is_readable($real_template_file)) {
     931            // Fallback to standard template
     932            $default_file = $real_template_dir . DIRECTORY_SEPARATOR . 'standard.php';
     933            $real_default_file = realpath($default_file);
     934           
     935            if ($real_default_file !== false && strpos($real_default_file, $real_template_dir) === 0 && is_file($real_default_file) && is_readable($real_default_file)) {
     936                return $real_default_file;
     937            }
     938           
     939            return false;
     940        }
     941
     942        return $real_template_file;
    851943    }
    852944
  • easy-invoice/trunk/includes/Controllers/QuoteController.php

    r3393362 r3399346  
    567567        }
    568568       
     569        // Validate template name securely
     570        $template_id = $this->validateTemplateName($template_id, 'quote');
     571       
     572        // Get secure template file path
     573        $template_file = $this->getSecureTemplatePath($template_id, 'quote');
     574       
     575        if (!$template_file) {
     576            wp_send_json_error(['message' => __('Template not found.', 'easy-invoice')]);
     577        }
     578       
    569579        // Load quote if provided
    570580        $quote = null;
     
    573583        }
    574584       
    575         // Check if template file exists
    576         $template_file = EASY_INVOICE_PLUGIN_DIR . 'templates/quote-templates/' . $template_id . '.php';
    577        
    578         if (!file_exists($template_file)) {
    579             wp_send_json_error(['message' => __('Template not found.', 'easy-invoice')]);
    580         }
    581        
    582585        // Start output buffering to capture template HTML
    583586        ob_start();
     
    590593       
    591594        wp_send_json_success(['html' => $html]);
     595    }
     596
     597    /**
     598     * Validate and sanitize template name to prevent directory traversal attacks
     599     *
     600     * @param string $template The template name to validate
     601     * @param string $type Either 'invoice' or 'quote'
     602     * @return string Validated template name or 'standard' as fallback
     603     */
     604    private function validateTemplateName($template, $type = 'quote') {
     605        // Whitelist of allowed template names
     606        $allowed_templates = array(
     607            'invoice' => array('classic', 'corporate', 'creative', 'elegant', 'legacy', 'minimal', 'modern', 'professional', 'standard'),
     608            'quote' => array('legacy', 'minimal', 'minimalist', 'modern', 'standard')
     609        );
     610
     611        // Strip any directory components using basename
     612        $template = basename($template);
     613       
     614        // Remove any file extension
     615        $template = preg_replace('/\.(php|html|htm)$/i', '', $template);
     616       
     617        // Remove any non-alphanumeric characters except hyphens and underscores
     618        $template = preg_replace('/[^a-z0-9_-]/i', '', $template);
     619       
     620        // Check if template is in whitelist
     621        if (isset($allowed_templates[$type]) && in_array($template, $allowed_templates[$type], true)) {
     622            return $template;
     623        }
     624       
     625        // Return default template if not in whitelist
     626        return 'standard';
     627    }
     628
     629    /**
     630     * Get secure template file path with directory traversal protection
     631     *
     632     * @param string $template The validated template name
     633     * @param string $type Either 'invoice' or 'quote'
     634     * @return string|false The secure template file path or false if invalid
     635     */
     636    private function getSecureTemplatePath($template, $type = 'quote') {
     637        // Define template directories
     638        $template_dirs = array(
     639            'invoice' => EASY_INVOICE_PLUGIN_DIR . 'templates/invoice-templates/',
     640            'quote' => EASY_INVOICE_PLUGIN_DIR . 'templates/quote-templates/'
     641        );
     642
     643        if (!isset($template_dirs[$type])) {
     644            return false;
     645        }
     646
     647        $template_dir = $template_dirs[$type];
     648       
     649        // Ensure template directory exists and is a directory
     650        if (!is_dir($template_dir)) {
     651            return false;
     652        }
     653
     654        // Get the real path of the template directory (resolves any symlinks)
     655        $real_template_dir = realpath($template_dir);
     656        if ($real_template_dir === false) {
     657            return false;
     658        }
     659
     660        // Construct the template file path
     661        $template_file = $real_template_dir . DIRECTORY_SEPARATOR . $template . '.php';
     662       
     663        // Get the real path of the template file (resolves any .. or . components)
     664        $real_template_file = realpath($template_file);
     665       
     666        // Verify that the resolved path is within the template directory
     667        // This prevents directory traversal attacks
     668        if ($real_template_file === false || strpos($real_template_file, $real_template_dir) !== 0) {
     669            // If template doesn't exist or is outside the directory, use default
     670            $default_file = $real_template_dir . DIRECTORY_SEPARATOR . 'standard.php';
     671            $real_default_file = realpath($default_file);
     672           
     673            if ($real_default_file !== false && strpos($real_default_file, $real_template_dir) === 0) {
     674                return $real_default_file;
     675            }
     676           
     677            return false;
     678        }
     679
     680        // Verify the file exists and is readable
     681        if (!is_file($real_template_file) || !is_readable($real_template_file)) {
     682            // Fallback to standard template
     683            $default_file = $real_template_dir . DIRECTORY_SEPARATOR . 'standard.php';
     684            $real_default_file = realpath($default_file);
     685           
     686            if ($real_default_file !== false && strpos($real_default_file, $real_template_dir) === 0 && is_file($real_default_file) && is_readable($real_default_file)) {
     687                return $real_default_file;
     688            }
     689           
     690            return false;
     691        }
     692
     693        return $real_template_file;
    592694    }
    593695   
  • easy-invoice/trunk/readme.txt

    r3393362 r3399346  
    55Tested up to: 6.8
    66Requires PHP: 7.4
    7 Stable tag: 2.1.4
     7Stable tag: 2.1.5
    88License: GPLv2 or later
    99License URI: https://www.gnu.org/licenses/gpl-2.0.html
     
    138138== Changelog ==
    139139
     140= 2.1.5 - 2025-11-20 =
     141* Fixed - Template loading issue fixed
     142
    140143= 2.1.4 - 2025-11-11 =
    141144* Fixed - Email issue fixed
Note: See TracChangeset for help on using the changeset viewer.