Plugin Directory

Changeset 3486541


Ignore:
Timestamp:
03/19/2026 01:58:57 PM (9 days ago)
Author:
petredobrescu
Message:

Version 3.11.2

🛡️ The Compatibility & Security Update

Release Date: March 19, 2026

🛠️ Fixes

  • open_basedir Warning Fix: Resolved cases where open_basedir restrictions triggered PHP warnings, including when using the "Replace in CSS" option.

✨ Tweaks & Improvements

  • Chatbot Expansion: The ShortPixel AI chatbot is now available in the Settings and onboarding pages for quicker assistance.
  • CSP Nonce Integration: Added support for Content Security Policy (CSP) nonces to improve compatibility with stricter security setups.

Update now for improved compatibility, smoother setup, and enhanced security support! 🚀

Location:
shortpixel-adaptive-images
Files:
18 edited
1 copied

Legend:

Unmodified
Added
Removed
  • shortpixel-adaptive-images/tags/3.11.2/includes/controllers/lqip.class.php

    r3340495 r3486541  
    10421042                ] );
    10431043
     1044                \ShortPixelUrlTools::applyNonce('spai-lqip');
    10441045                wp_enqueue_script( 'spai-lqip' );
    10451046            }
  • shortpixel-adaptive-images/tags/3.11.2/includes/controllers/notice.class.php

    r3340495 r3486541  
    726726            wp_register_script( 'spai-notice', $this->ctrl->plugin_url . $scripts[ 'notice' ][ 'file' ], [ 'jquery' ], $scripts[ 'notice' ][ 'version' ] );
    727727
    728             // Enqueueing scripts
     728            \ShortPixelUrlTools::applyNonce('spai-notice');
     729            // Enqueueing scripts
    729730            wp_enqueue_script( 'spai-notice' );
    730731        }
  • shortpixel-adaptive-images/tags/3.11.2/includes/controllers/page.class.php

    r3340495 r3486541  
    124124                // Commented because of WordPress Plugins Reviewing team
    125125                // echo '<div class="shortpixel-ai-beacon"></div>';
     126            }
     127
     128            // Add chatbot script to settings and on-boarding pages
     129            if ( self::isCurrent( 'settings' ) || self::isCurrent( 'on-boarding' ) ) {
     130                ?>
     131<script>
     132(function() {
     133    if (!window.chatbase || window.chatbase("getState") !== "initialized") {
     134        window.chatbase = (...arguments) => {
     135            if (!window.chatbase.q) {
     136                window.chatbase.q = [];
     137            }
     138            window.chatbase.q.push(arguments);
     139        };
     140        window.chatbase = new Proxy(window.chatbase, {
     141            get(target, prop) {
     142                if (prop === "q") {
     143                    return target.q;
     144                }
     145                return (...args) => target(prop, ...args);
     146            }
     147        });
     148    }
     149    const onLoad = function() {
     150        const script = document.createElement("script");
     151        script.src = "https://www.chatbase.co/embed.min.js";
     152        script.id = "M__c7Yk58ZL23gk7UIWY-";
     153        script.domain = "www.chatbase.co";
     154        document.body.appendChild(script);
     155    };
     156    if (document.readyState === "complete") {
     157        onLoad();
     158    } else {
     159        window.addEventListener("load", onLoad);
     160    }
     161})();
     162</script>
     163                <?php
    126164            }
    127165        }
     
    170208                    ],
    171209                ] );
     210                \ShortPixelUrlTools::applyNonce('spai-settings');
    172211                wp_enqueue_script( 'spai-settings' );
    173212
  • shortpixel-adaptive-images/tags/3.11.2/includes/controllers/short-pixel-ai.class.php

    r3367153 r3486541  
    906906            ],
    907907        ] );
     908        \ShortPixelUrlTools::applyNonce('spai-sniper');
    908909
    909910        wp_enqueue_script( 'spai-sniper');
     
    11171118            ['nonce' => \ShortPixel\AI\Page::_( ShortPixelAI::_() )->getNonce(),]
    11181119        );
     1120        \ShortPixelUrlTools::applyNonce('spai-admin-scripts');
     1121
    11191122    }
    11201123
  • shortpixel-adaptive-images/tags/3.11.2/includes/front/js-loader.class.php

    r3209129 r3486541  
    8686                    ],
    8787                ] );
     88                \ShortPixelUrlTools::applyNonce('spai-front-worker');
    8889                wp_enqueue_script( 'spai-front-worker' );
    8990            }
  • shortpixel-adaptive-images/tags/3.11.2/includes/front/vanilla-js-loader.class.php

    r3340495 r3486541  
    104104                'eager_paths'           => array_map( 'base64_encode', $this->ctrl->splitSelectors( $this->settings->exclusions->eager_paths, PHP_EOL ) ),
    105105            ]);
     106            \ShortPixelUrlTools::applyNonce('spai-snip-action');
    106107            wp_enqueue_script( 'spai-snip-action'  );
    107108            wp_add_inline_script('spai-snip-action',
  • shortpixel-adaptive-images/tags/3.11.2/includes/helpers/url-tools.class.php

    r3340495 r3486541  
    224224            SHORTPIXEL_AI_DEBUG && ShortPixelAILogger::instance()->log("TAKE1: $path");
    225225        }
    226         if(!file_exists($path)) { //search in the wp-content directory too
     226        if(!self::spai_safe_file_exists($path)) { //search in the wp-content directory too
    227227            $baseUrlPattern = "/" . str_replace("/", "\/", preg_replace("/^http[s]{0,1}:\/\//", "^http[s]{0,1}://", dirname($updir['baseurl']))) . "/";
    228228            SHORTPIXEL_AI_DEBUG && ShortPixelAILogger::instance()->log("BASE URL PATTERN2: $baseUrlPattern");
     
    231231                ShortPixelAILogger::instance()->log("TAKE2: $path");
    232232            }
    233             if(!file_exists($path)) {
     233            if(!self::spai_safe_file_exists($path)) {
    234234                //that's the root folder, it will match the ABSPATH
    235235                $absPath = untrailingslashit(function_exists('get_home_path') ? get_home_path() : ABSPATH);
     
    240240                }
    241241                //cases for multisite when the URL contains an extra element but the local path doesn't (eg food here: path: https://stagegie.wpengine.com/food/wp-content/uploads/sites/5/2020/01/Healthy-Chicken-Sheet-Pan-Fajitas-Get-Inspired-Everyday-5.jpg)
    242                 if(!file_exists($path)) {
     242                if(!self::spai_safe_file_exists($path)) {
    243243                    $baseDir = explode(DIRECTORY_SEPARATOR, $updir['basedir']);
    244244                    $contentUploads = implode('/', array_slice($baseDir, -2, 2));
     
    247247                        $path = $updir['basedir'] . $contentSubdir[1];
    248248                        SHORTPIXEL_AI_DEBUG && ShortPixelAILogger::instance()->log("TAKE3BIS: $path");
    249                         if(!file_exists($path) && preg_match('/https?:\/\//', $image_url) === false) {
     249                        if(!self::spai_safe_file_exists($path) && preg_match('/https?:\/\//', $image_url) === false) {
    250250                            $path = $absPath . ($image_url[0] == '/' ? '' : '/') . $image_url;
    251251                            SHORTPIXEL_AI_DEBUG && ShortPixelAILogger::instance()->log("TAKE4: $path");
    252                             if(!file_exists($path)) {
     252                            if(!self::spai_safe_file_exists($path)) {
    253253                                //for cases when the WP directory is a subdir of the root
    254254                                $path = dirname($absPath) . ($image_url[0] == '/' ? '' : '/') . $image_url;
     
    261261        }
    262262
    263         SHORTPIXEL_AI_DEBUG && ShortPixelAILogger::instance()->log("URL TO PATH TO SIZES, checking: " . $path . ' EXISTS? ' . (file_exists($path) ? 'YEE, sizes: ' . json_encode(getimagesize($path)) : 'Nope. UPLOAD url:' . $updir['baseurl'] . ' BaseUrlPattern:' . $baseUrlPattern));
    264 
    265         if(@file_exists($path)) {
    266             return self::getimagesizeOrSvg($path);
    267         } elseif (@file_exists(urldecode($path))) {
    268             return self::getimagesizeOrSvg(urldecode($path));
     263        SHORTPIXEL_AI_DEBUG && ShortPixelAILogger::instance()->log("URL TO PATH TO SIZES, checking: " . $path . ' EXISTS? ' . (self::spai_safe_file_exists($path) ? 'YEE, sizes: ' . json_encode(getimagesize($path)) : 'Nope. UPLOAD url:' . $updir['baseurl'] . ' BaseUrlPattern:' . $baseUrlPattern));
     264
     265        $abs = self::spai_normalize_fs_path($path);
     266        if ($abs && self::spai_safe_file_exists($abs)) {
     267            return self::getimagesizeOrSvg($abs);
     268        }
     269        $abs2 = $abs ? urldecode($abs) : self::spai_normalize_fs_path(urldecode($path));
     270        if ($abs2 && self::spai_safe_file_exists($abs2)) {
     271            return self::getimagesizeOrSvg($abs2);
    269272        } else {
    270273            //LOG open_basedir warnings: https://secure.helpscout.net/conversation/1229180365/34854/
     
    273276            //try the default location for cases like this one which had wrong baseurl so the replace above did not work: https://secure.helpscout.net/conversation/943639884/20602?folderId=1117588
    274277            $path = trailingslashit(ABSPATH) . 'wp-content/uploads/' . wp_basename(dirname(dirname($image_url))) . '/' . wp_basename(dirname($image_url)) . '/' . wp_basename($image_url);
    275             if(@file_exists($path)) {
     278            if(self::spai_safe_file_exists($path)) {
    276279                return self::getimagesizeOrSvg($path);
    277             } elseif (@file_exists(urldecode($path))) {
     280            } elseif (self::spai_safe_file_exists(urldecode($path))) {
    278281                return self::getimagesizeOrSvg(urldecode($path));
    279282            }
     
    283286
    284287    static function getimagesizeOrSvg($path) {
     288        $abs = ShortPixelUrlTools::spai_normalize_fs_path($path);
     289        if (!$abs || !ShortPixelUrlTools::check_open_basedir($abs)) {
     290            return [1,1];
     291        }
     292        $path = $abs;
     293
    285294        if(strtolower(pathinfo($path, PATHINFO_EXTENSION)) === 'svg') {
    286295            $svg = file_get_contents($path);
     
    355364        }
    356365        return true;
     366    }
     367
     368    /** converts any relative/absolute path to an absolute path under WP dir */
     369    private static function spai_normalize_fs_path($candidate) {
     370        if (!$candidate || preg_match('#^[a-z][a-z0-9+.\-]*://#i', $candidate)) return false; // e URL, nu cale
     371        $root = wp_normalize_path( untrailingslashit( function_exists('get_home_path') ? get_home_path() : ABSPATH ) );
     372        $p    = wp_normalize_path($candidate);
     373
     374        if ($p === $root || strpos($p, $root . '/') === 0) { // BUg :)) heere i checked if it's already under root, before i didn't and gave double root path
     375            return $p;
     376        }
     377
     378        // if starts with "/" ( /wp-content/...), prefix with ABSPATH
     379        if (isset($p[0]) && $p[0] === '/') {
     380            return $root . $p;
     381        }
     382        return $root . '/' . ltrim($p, '/');
     383    }
     384
     385    /** check if the file exists on the disk, but only if the path is allowed by open_basedir */
     386    private static function spai_safe_file_exists($candidate): bool {
     387        $abs = self::spai_normalize_fs_path($candidate);
     388        if (!$abs) return false;
     389        if (!self::check_open_basedir($abs)) return false;
     390        return @file_exists($abs);
    357391    }
    358392
     
    606640        return urldecode(str_replace('data-u="', '', $matches[0]));
    607641    }
     642
     643    public static function applyNonce($name)
     644    {
     645        $nonce = apply_filters( 'spai_script_nonce', '' );
     646        if($nonce) {
     647            wp_scripts()->add_data( $name, 'nonce',  $nonce);
     648        }
     649    }
    608650}
  • shortpixel-adaptive-images/tags/3.11.2/readme.txt

    r3451959 r3486541  
    55Tested up to: 6.9
    66Requires PHP: 5.6.40
    7 Stable tag: 3.11.1
     7Stable tag: 3.11.2
    88License: GPLv2 or later
    99License URI: http://www.gnu.org/licenses/gpl-2.0.html
     
    249249
    250250== Changelog ==
     251
     252= 3.11.2 =
     253
     254🛡️ The Compatibility & Security Update
     255
     256Release Date: March 19, 2026
     257
     258🛠️ Fixes
     259
     260* open_basedir Warning Fix: Resolved cases where open_basedir restrictions triggered PHP warnings, including when using the "Replace in CSS" option.
     261
     262✨ Tweaks & Improvements
     263
     264* Chatbot Expansion: The ShortPixel AI chatbot is now available in the Settings and onboarding pages for quicker assistance.
     265* CSP Nonce Integration: Added support for Content Security Policy (CSP) nonces to improve compatibility with stricter security setups.
     266
     267Update now for improved compatibility, smoother setup, and enhanced security support! 🚀
    251268
    252269= 3.11.1 =
  • shortpixel-adaptive-images/tags/3.11.2/short-pixel-ai.php

    r3367153 r3486541  
    44     * Plugin URI: https://shortpixel.com/
    55     * Description: Display properly sized, smart cropped and optimized images on your website. Images are processed on the fly and served from our CDN.
    6      * Version: 3.11.1
     6     * Version: 3.11.2
    77     * Author: ShortPixel
    88     * GitHub Plugin URI: https://github.com/short-pixel-optimizer/shortpixel-adaptive-images
     
    1616
    1717    if ( !class_exists( 'ShortPixelAI' ) ) {
    18         define( 'SHORTPIXEL_AI_VERSION', '3.11.1' );
     18        define( 'SHORTPIXEL_AI_VERSION', '3.11.2' );
    1919        define( 'SPAI_SNIP_VERSION', '3.1.0' );
    2020        define( 'SHORTPIXEL_AI_VANILLAJS_VER', '1.1' );
  • shortpixel-adaptive-images/trunk/includes/controllers/lqip.class.php

    r3340495 r3486541  
    10421042                ] );
    10431043
     1044                \ShortPixelUrlTools::applyNonce('spai-lqip');
    10441045                wp_enqueue_script( 'spai-lqip' );
    10451046            }
  • shortpixel-adaptive-images/trunk/includes/controllers/notice.class.php

    r3340495 r3486541  
    726726            wp_register_script( 'spai-notice', $this->ctrl->plugin_url . $scripts[ 'notice' ][ 'file' ], [ 'jquery' ], $scripts[ 'notice' ][ 'version' ] );
    727727
    728             // Enqueueing scripts
     728            \ShortPixelUrlTools::applyNonce('spai-notice');
     729            // Enqueueing scripts
    729730            wp_enqueue_script( 'spai-notice' );
    730731        }
  • shortpixel-adaptive-images/trunk/includes/controllers/page.class.php

    r3340495 r3486541  
    124124                // Commented because of WordPress Plugins Reviewing team
    125125                // echo '<div class="shortpixel-ai-beacon"></div>';
     126            }
     127
     128            // Add chatbot script to settings and on-boarding pages
     129            if ( self::isCurrent( 'settings' ) || self::isCurrent( 'on-boarding' ) ) {
     130                ?>
     131<script>
     132(function() {
     133    if (!window.chatbase || window.chatbase("getState") !== "initialized") {
     134        window.chatbase = (...arguments) => {
     135            if (!window.chatbase.q) {
     136                window.chatbase.q = [];
     137            }
     138            window.chatbase.q.push(arguments);
     139        };
     140        window.chatbase = new Proxy(window.chatbase, {
     141            get(target, prop) {
     142                if (prop === "q") {
     143                    return target.q;
     144                }
     145                return (...args) => target(prop, ...args);
     146            }
     147        });
     148    }
     149    const onLoad = function() {
     150        const script = document.createElement("script");
     151        script.src = "https://www.chatbase.co/embed.min.js";
     152        script.id = "M__c7Yk58ZL23gk7UIWY-";
     153        script.domain = "www.chatbase.co";
     154        document.body.appendChild(script);
     155    };
     156    if (document.readyState === "complete") {
     157        onLoad();
     158    } else {
     159        window.addEventListener("load", onLoad);
     160    }
     161})();
     162</script>
     163                <?php
    126164            }
    127165        }
     
    170208                    ],
    171209                ] );
     210                \ShortPixelUrlTools::applyNonce('spai-settings');
    172211                wp_enqueue_script( 'spai-settings' );
    173212
  • shortpixel-adaptive-images/trunk/includes/controllers/short-pixel-ai.class.php

    r3367153 r3486541  
    906906            ],
    907907        ] );
     908        \ShortPixelUrlTools::applyNonce('spai-sniper');
    908909
    909910        wp_enqueue_script( 'spai-sniper');
     
    11171118            ['nonce' => \ShortPixel\AI\Page::_( ShortPixelAI::_() )->getNonce(),]
    11181119        );
     1120        \ShortPixelUrlTools::applyNonce('spai-admin-scripts');
     1121
    11191122    }
    11201123
  • shortpixel-adaptive-images/trunk/includes/front/js-loader.class.php

    r3209129 r3486541  
    8686                    ],
    8787                ] );
     88                \ShortPixelUrlTools::applyNonce('spai-front-worker');
    8889                wp_enqueue_script( 'spai-front-worker' );
    8990            }
  • shortpixel-adaptive-images/trunk/includes/front/vanilla-js-loader.class.php

    r3340495 r3486541  
    104104                'eager_paths'           => array_map( 'base64_encode', $this->ctrl->splitSelectors( $this->settings->exclusions->eager_paths, PHP_EOL ) ),
    105105            ]);
     106            \ShortPixelUrlTools::applyNonce('spai-snip-action');
    106107            wp_enqueue_script( 'spai-snip-action'  );
    107108            wp_add_inline_script('spai-snip-action',
  • shortpixel-adaptive-images/trunk/includes/helpers/url-tools.class.php

    r3340495 r3486541  
    224224            SHORTPIXEL_AI_DEBUG && ShortPixelAILogger::instance()->log("TAKE1: $path");
    225225        }
    226         if(!file_exists($path)) { //search in the wp-content directory too
     226        if(!self::spai_safe_file_exists($path)) { //search in the wp-content directory too
    227227            $baseUrlPattern = "/" . str_replace("/", "\/", preg_replace("/^http[s]{0,1}:\/\//", "^http[s]{0,1}://", dirname($updir['baseurl']))) . "/";
    228228            SHORTPIXEL_AI_DEBUG && ShortPixelAILogger::instance()->log("BASE URL PATTERN2: $baseUrlPattern");
     
    231231                ShortPixelAILogger::instance()->log("TAKE2: $path");
    232232            }
    233             if(!file_exists($path)) {
     233            if(!self::spai_safe_file_exists($path)) {
    234234                //that's the root folder, it will match the ABSPATH
    235235                $absPath = untrailingslashit(function_exists('get_home_path') ? get_home_path() : ABSPATH);
     
    240240                }
    241241                //cases for multisite when the URL contains an extra element but the local path doesn't (eg food here: path: https://stagegie.wpengine.com/food/wp-content/uploads/sites/5/2020/01/Healthy-Chicken-Sheet-Pan-Fajitas-Get-Inspired-Everyday-5.jpg)
    242                 if(!file_exists($path)) {
     242                if(!self::spai_safe_file_exists($path)) {
    243243                    $baseDir = explode(DIRECTORY_SEPARATOR, $updir['basedir']);
    244244                    $contentUploads = implode('/', array_slice($baseDir, -2, 2));
     
    247247                        $path = $updir['basedir'] . $contentSubdir[1];
    248248                        SHORTPIXEL_AI_DEBUG && ShortPixelAILogger::instance()->log("TAKE3BIS: $path");
    249                         if(!file_exists($path) && preg_match('/https?:\/\//', $image_url) === false) {
     249                        if(!self::spai_safe_file_exists($path) && preg_match('/https?:\/\//', $image_url) === false) {
    250250                            $path = $absPath . ($image_url[0] == '/' ? '' : '/') . $image_url;
    251251                            SHORTPIXEL_AI_DEBUG && ShortPixelAILogger::instance()->log("TAKE4: $path");
    252                             if(!file_exists($path)) {
     252                            if(!self::spai_safe_file_exists($path)) {
    253253                                //for cases when the WP directory is a subdir of the root
    254254                                $path = dirname($absPath) . ($image_url[0] == '/' ? '' : '/') . $image_url;
     
    261261        }
    262262
    263         SHORTPIXEL_AI_DEBUG && ShortPixelAILogger::instance()->log("URL TO PATH TO SIZES, checking: " . $path . ' EXISTS? ' . (file_exists($path) ? 'YEE, sizes: ' . json_encode(getimagesize($path)) : 'Nope. UPLOAD url:' . $updir['baseurl'] . ' BaseUrlPattern:' . $baseUrlPattern));
    264 
    265         if(@file_exists($path)) {
    266             return self::getimagesizeOrSvg($path);
    267         } elseif (@file_exists(urldecode($path))) {
    268             return self::getimagesizeOrSvg(urldecode($path));
     263        SHORTPIXEL_AI_DEBUG && ShortPixelAILogger::instance()->log("URL TO PATH TO SIZES, checking: " . $path . ' EXISTS? ' . (self::spai_safe_file_exists($path) ? 'YEE, sizes: ' . json_encode(getimagesize($path)) : 'Nope. UPLOAD url:' . $updir['baseurl'] . ' BaseUrlPattern:' . $baseUrlPattern));
     264
     265        $abs = self::spai_normalize_fs_path($path);
     266        if ($abs && self::spai_safe_file_exists($abs)) {
     267            return self::getimagesizeOrSvg($abs);
     268        }
     269        $abs2 = $abs ? urldecode($abs) : self::spai_normalize_fs_path(urldecode($path));
     270        if ($abs2 && self::spai_safe_file_exists($abs2)) {
     271            return self::getimagesizeOrSvg($abs2);
    269272        } else {
    270273            //LOG open_basedir warnings: https://secure.helpscout.net/conversation/1229180365/34854/
     
    273276            //try the default location for cases like this one which had wrong baseurl so the replace above did not work: https://secure.helpscout.net/conversation/943639884/20602?folderId=1117588
    274277            $path = trailingslashit(ABSPATH) . 'wp-content/uploads/' . wp_basename(dirname(dirname($image_url))) . '/' . wp_basename(dirname($image_url)) . '/' . wp_basename($image_url);
    275             if(@file_exists($path)) {
     278            if(self::spai_safe_file_exists($path)) {
    276279                return self::getimagesizeOrSvg($path);
    277             } elseif (@file_exists(urldecode($path))) {
     280            } elseif (self::spai_safe_file_exists(urldecode($path))) {
    278281                return self::getimagesizeOrSvg(urldecode($path));
    279282            }
     
    283286
    284287    static function getimagesizeOrSvg($path) {
     288        $abs = ShortPixelUrlTools::spai_normalize_fs_path($path);
     289        if (!$abs || !ShortPixelUrlTools::check_open_basedir($abs)) {
     290            return [1,1];
     291        }
     292        $path = $abs;
     293
    285294        if(strtolower(pathinfo($path, PATHINFO_EXTENSION)) === 'svg') {
    286295            $svg = file_get_contents($path);
     
    355364        }
    356365        return true;
     366    }
     367
     368    /** converts any relative/absolute path to an absolute path under WP dir */
     369    private static function spai_normalize_fs_path($candidate) {
     370        if (!$candidate || preg_match('#^[a-z][a-z0-9+.\-]*://#i', $candidate)) return false; // e URL, nu cale
     371        $root = wp_normalize_path( untrailingslashit( function_exists('get_home_path') ? get_home_path() : ABSPATH ) );
     372        $p    = wp_normalize_path($candidate);
     373
     374        if ($p === $root || strpos($p, $root . '/') === 0) { // BUg :)) heere i checked if it's already under root, before i didn't and gave double root path
     375            return $p;
     376        }
     377
     378        // if starts with "/" ( /wp-content/...), prefix with ABSPATH
     379        if (isset($p[0]) && $p[0] === '/') {
     380            return $root . $p;
     381        }
     382        return $root . '/' . ltrim($p, '/');
     383    }
     384
     385    /** check if the file exists on the disk, but only if the path is allowed by open_basedir */
     386    private static function spai_safe_file_exists($candidate): bool {
     387        $abs = self::spai_normalize_fs_path($candidate);
     388        if (!$abs) return false;
     389        if (!self::check_open_basedir($abs)) return false;
     390        return @file_exists($abs);
    357391    }
    358392
     
    606640        return urldecode(str_replace('data-u="', '', $matches[0]));
    607641    }
     642
     643    public static function applyNonce($name)
     644    {
     645        $nonce = apply_filters( 'spai_script_nonce', '' );
     646        if($nonce) {
     647            wp_scripts()->add_data( $name, 'nonce',  $nonce);
     648        }
     649    }
    608650}
  • shortpixel-adaptive-images/trunk/readme.txt

    r3451959 r3486541  
    55Tested up to: 6.9
    66Requires PHP: 5.6.40
    7 Stable tag: 3.11.1
     7Stable tag: 3.11.2
    88License: GPLv2 or later
    99License URI: http://www.gnu.org/licenses/gpl-2.0.html
     
    249249
    250250== Changelog ==
     251
     252= 3.11.2 =
     253
     254🛡️ The Compatibility & Security Update
     255
     256Release Date: March 19, 2026
     257
     258🛠️ Fixes
     259
     260* open_basedir Warning Fix: Resolved cases where open_basedir restrictions triggered PHP warnings, including when using the "Replace in CSS" option.
     261
     262✨ Tweaks & Improvements
     263
     264* Chatbot Expansion: The ShortPixel AI chatbot is now available in the Settings and onboarding pages for quicker assistance.
     265* CSP Nonce Integration: Added support for Content Security Policy (CSP) nonces to improve compatibility with stricter security setups.
     266
     267Update now for improved compatibility, smoother setup, and enhanced security support! 🚀
    251268
    252269= 3.11.1 =
  • shortpixel-adaptive-images/trunk/short-pixel-ai.php

    r3367153 r3486541  
    44     * Plugin URI: https://shortpixel.com/
    55     * Description: Display properly sized, smart cropped and optimized images on your website. Images are processed on the fly and served from our CDN.
    6      * Version: 3.11.1
     6     * Version: 3.11.2
    77     * Author: ShortPixel
    88     * GitHub Plugin URI: https://github.com/short-pixel-optimizer/shortpixel-adaptive-images
     
    1616
    1717    if ( !class_exists( 'ShortPixelAI' ) ) {
    18         define( 'SHORTPIXEL_AI_VERSION', '3.11.1' );
     18        define( 'SHORTPIXEL_AI_VERSION', '3.11.2' );
    1919        define( 'SPAI_SNIP_VERSION', '3.1.0' );
    2020        define( 'SHORTPIXEL_AI_VANILLAJS_VER', '1.1' );
Note: See TracChangeset for help on using the changeset viewer.