Skip to content

Commit

Permalink
v1.26.0
Browse files Browse the repository at this point in the history
  • Loading branch information
optipic-io committed Dec 15, 2021
1 parent 25e3f6e commit 4d5204c
Show file tree
Hide file tree
Showing 4 changed files with 173 additions and 42 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

PrestaShop module to integrate with OptiPic.io (automatic images optimization and compression service)

[<img src="https://optipic.io/images/download-button-w200.png"/>](https://github.com/optipic-io/optipic-prestashop/releases/download/v1.19.1/optipic-prestashop-v1.19.1.zip)
[<img src="https://optipic.io/images/download-button-w200.png"/>](https://github.com/optipic-io/optipic-prestashop/releases/download/v1.26.0/optipic-prestashop-v1.26.0.zip)
209 changes: 170 additions & 39 deletions optipic/classes/ImgUrlConverter.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class ImgUrlConverter
/**
* Library version number
*/
const VERSION = '1.19';
const VERSION = '1.26';

/**
* ID of your site on CDN OptiPic.io service
Expand Down Expand Up @@ -50,6 +50,10 @@ class ImgUrlConverter

public static $cdnDomain = 'cdn.optipic.io';

public static $url = null;

public static $host = null;

/**
* Constructor
*/
Expand All @@ -63,26 +67,35 @@ public function __construct($config = array())
/**
* Convert whole HTML-block contains image urls
*/
public static function convertHtml($content)
public static function convertHtml($content, $detectBaseUrl = true)
{

if(empty(self::$url)) {
self::$url = $_SERVER['REQUEST_URI'];
}
if(empty(self::$host)) {
self::$host = $_SERVER['HTTP_HOST'];
}

$timeStart = microtime(true);

//ini_set('pcre.backtrack_limit', 100000000);

$content = self::removeBomFromUtf($content);

$contentOrig = $content;

// try auto load config from __DIR__.'config.php'
if (empty(self::$siteId)) {
self::loadConfig();
}

if (empty(self::$siteId)) {
return $content;
return $contentOrig;
}

if (!self::isEnabled()) {
return $content;
return $contentOrig;
}

$gziped = false;
Expand All @@ -93,9 +106,27 @@ public static function convertHtml($content)
}
}

self::$baseUrl = self::getBaseUrlFromHtml($content);
if (self::$baseUrl) {
self::$baseUrl = parse_url(self::$baseUrl, PHP_URL_PATH);

$needToConvert = true;

if ($needToConvert && self::htmlHasAmpMarkup($content)) {
$needToConvert = false;
}

if ($needToConvert && self::htmlHasXmlMarkup($content)) {
$needToConvert = false;
}

if (!$needToConvert) {
return $contentOrig;
}


if($detectBaseUrl) {
self::$baseUrl = self::getBaseUrlFromHtml($content);
if (self::$baseUrl) {
self::$baseUrl = parse_url(self::$baseUrl, PHP_URL_PATH);
}
}

//if (self::isBinary($content)) {
Expand Down Expand Up @@ -167,7 +198,7 @@ public static function convertHtml($content)
}
$srcSetAttrsRegexp = implode('|', $srcSetAttrsRegexp);
//$content = preg_replace_callback('#<(?P<tag>[^\s]+)(?P<prefix>.*?)\s+(?P<attr>'.$srcSetAttrsRegexp.')=(?P<quote1>"|\')(?P<set>[^"]+?)(?P<quote2>"|\')(?P<suffix>[^>]*?)>#siS', array(__NAMESPACE__ .'\ImgUrlConverter', 'callbackForPregReplaceSrcset'), $content);
$contentAfterReplace = preg_replace_callback('#<(?P<tag>source|img|picture)(?P<prefix>[^>]*)\s+(?P<attr>'.$srcSetAttrsRegexp.')=(?P<quote1>"|\')(?P<set>[^"\']+?)(?P<quote2>"|\')(?P<suffix>[^>]*)>#siS', array(__NAMESPACE__ .'\ImgUrlConverter', 'callbackForPregReplaceSrcset'), $content);
$contentAfterReplace = preg_replace_callback('#<(?P<tag>source|img|picture)(?P<prefix>[^>]*)\s+(?P<attr>'.$srcSetAttrsRegexp.')=(?P<quote1>"|\'|\\\"|\\\')(?P<set>[^"\']+?)(?P<quote2>"|\'|\\\"|\\\')(?P<suffix>[^>]*)>#siS', array(__NAMESPACE__ .'\ImgUrlConverter', 'callbackForPregReplaceSrcset'), $content);
if (!empty($contentAfterReplace)) {
$content = $contentAfterReplace;
}
Expand All @@ -180,9 +211,11 @@ public static function convertHtml($content)
//$regexp = '#("|\'|\()'.$host.'('.$firstPartOfUrl.'[^"|\'|\)\(]+\.(png|jpg|jpeg){1}(\?.*?)?)("|\'|\))#siS';

$urlBorders = array(
array('"', '"'), // "<url>"
array('\'', '\''), // '<url>'
array('\(', '\)'), // (<url>)
array('"', '"', '"'), // "<url>"
array('\'', '\'', '\''), // '<url>'
array('\(', '\)', '\)\('), // (<url>)
array('\\\"', '\\\"', '"'), // "<url>" in JSON
array("\\\'", "\\\'", "'"), // '<url>' in JSON
);

$cdnDomains = array(
Expand All @@ -194,13 +227,15 @@ public static function convertHtml($content)

$cdnDomainsForRegexp = array();
foreach ($cdnDomains as $cdnDomain) {
$cdnDomainsForRegexp[] = '\/\/'.preg_quote($cdnDomain, '#');
$cdnDomainsForRegexp[] = '\/\/'.preg_quote($cdnDomain, '#'); // plain html
$cdnDomainsForRegexp[] = '\\/\\/'.preg_quote($cdnDomain, '#'); // html in json

}
$cdnDomainsForRegexp = implode("|", $cdnDomainsForRegexp);

$regexp = array();
foreach ($urlBorders as $border) {
$regexp[] = '#('.$border[0].')'.$host.'('.$firstPartOfUrl.'(?!'.$cdnDomainsForRegexp.')[^'.$border[1].']+\.(png|jpg|jpeg){1}(\?[^"\'\s]*?)?)('.$border[1].')#siS';
$regexp[] = '#('.$border[0].')\s*'.$host.'('.$firstPartOfUrl.'(?!'.$cdnDomainsForRegexp.')[^'.$border[2].']+\.(png|jpg|jpeg){1}(\?[^"\'\s]*?)?)\s*('.$border[1].')#siS';
}
//var_dump($regexp);exit;

Expand All @@ -214,7 +249,7 @@ public static function convertHtml($content)

//}

self::$baseUrl = false;
//self::$baseUrl = false; // ?
$content = str_replace('<head>', '<head>' . PHP_EOL . self::getPreloadTags(), $content);

Expand Down Expand Up @@ -322,7 +357,8 @@ public static function loadConfig($source = false)
*/
public static function isEnabled()
{
$url = $_SERVER['REQUEST_URI'];
//$url = $_SERVER['REQUEST_URI'];
$url = self::$url;
if (in_array($url, self::$exclusionsUrl)) {
return false;
}
Expand All @@ -346,14 +382,28 @@ public static function callbackForPregReplace($matches)
self::log($matches, 'callbackForPregReplace -> $matches');
$replaceWithoutOptiPic = $matches[0];

$urlOriginal = $matches[2];

$slash = '/';
// skip images from json (json-encoded)
if (stripos($replaceWithoutOptiPic, "\\/")!==false) {
return $replaceWithoutOptiPic;
//return $replaceWithoutOptiPic;
$slash = '\\/';
//var_dump($urlOriginal);
$parseUrl = parse_url(json_decode('"'.$urlOriginal.'"'));
//var_dump($parseUrl);
$parseUrl['path'] = trim(json_encode($parseUrl['path']), "'\"");
if (!empty($parseUrl['query'])) {
$parseUrl['query'] = trim(json_encode($parseUrl['query']), "'\"");
}
//var_dump($parseUrl);exit;
}
else {
$parseUrl = parse_url($urlOriginal);
}

$urlOriginal = $matches[2];

$parseUrl = parse_url($urlOriginal);


if (!empty($parseUrl['host'])) {
if (!in_array($parseUrl['host'], self::$domains)) {
Expand All @@ -368,14 +418,17 @@ public static function callbackForPregReplace($matches)
return $replaceWithoutOptiPic;
}

if (self::urlHasPhpScript($urlOriginal)) {
return $replaceWithoutOptiPic;
}

$urlOriginal = $parseUrl['path'];
if (!empty($parseUrl['query'])) {
$urlOriginal .= '?'.$parseUrl['query'];
}
$urlOriginal = self::getUrlFromRelative($urlOriginal, self::$baseUrl);

$urlOriginal = self::getUrlFromRelative($urlOriginal, self::$baseUrl, $slash);

$replaceWithOptiPic = $matches[1].'//'.self::$cdnDomain.'/site-'.self::$siteId.$urlOriginal.$matches[5];
$replaceWithOptiPic = $matches[1].$slash.$slash.self::$cdnDomain.$slash.'site-'.self::$siteId.$urlOriginal.$matches[5];

self::log($urlOriginal, 'callbackForPregReplace -> url original:');
self::log($replaceWithOptiPic, 'callbackForPregReplace -> url with optipic:');
Expand Down Expand Up @@ -422,8 +475,8 @@ public static function callbackForPregReplaceSrcset($matches)
$source = preg_split("/[\s,]+/siS", trim($item));
$url = trim($source[0]);
$size = (isset($source[1]))? trim($source[1]): '';
$toConvertUrl = "(".$url.")";
$convertedUrl = self::convertHtml($toConvertUrl);
$toConvertUrl = "'".$url."'";
$convertedUrl = self::convertHtml($toConvertUrl, false);
if ($toConvertUrl!=$convertedUrl) {
$isConverted = true;
$listConverted[] = trim(self::substr($convertedUrl, 1, -1).' '.$size);
Expand Down Expand Up @@ -463,35 +516,62 @@ public static function isGz($str)
return (ord(self::substr($str, 0, 1)) == 0x1f && ord(self::substr($str, 1, 1)) == 0x8b);
}

public static function getUrlFromRelative($relativeUrl, $baseUrl = false)
public static function getUrlFromRelative($relativeUrl, $baseUrl = false, $slash = '/')
{
self::log($relativeUrl, 'getUrlFromRelative -> param orig');
if (stripos($relativeUrl, '../')!==false) {
$relativeUrl = self::resolveFilename($relativeUrl);
$relativeUrl = self::resolveFilename($relativeUrl, $slash);
}

if (self::substr($relativeUrl, 0, 1)=='/') {
if (self::substr($relativeUrl, 0, strlen($slash))==$slash) {
return $relativeUrl;
}
if (self::substr($relativeUrl, 0, 2)=='\/') { // for json-encoded urls when / --> \/
/*if (self::substr($relativeUrl, 0, 2)=='\/') { // for json-encoded urls when / --> \/
return $relativeUrl;
}
}*/

if (!$baseUrl) {
//$baseUrl = pathinfo($_SERVER['REQUEST_URI'], PATHINFO_DIRNAME);
$baseUrl = self::getBaseDirOfUrl($_SERVER['REQUEST_URI']);
//$baseUrl = pathinfo(self::$url, PATHINFO_DIRNAME);
$baseUrl = self::getBaseDirOfUrl(self::$url);
}
//$baseUrl .= '/';

$url = str_replace('//', '/', $baseUrl.$relativeUrl);
// CASE filepath ".img.png" (remove first dot)
if (substr($relativeUrl, 0, 1) == '.' && substr($relativeUrl, 1, 1) != '.') {
$relativeUrl = substr($relativeUrl, 1);
}
// CASE baseUrl "." (remove first dot)
if (strlen($baseUrl)>0 && substr($baseUrl, 0, 1) == '.' && substr($baseUrl, 1, 1) != '.') {
$baseUrl = (strlen($baseUrl)>1)? "".substr($baseUrl, 1): "";
}

// CASE /catalog + img.png (/catalogimg.png is wrong)
if (substr($baseUrl, -1)!='/' && substr($relativeUrl, 0, 1) != '/') {
$tryUrl = str_replace($slash.$slash, $slash, $baseUrl.$slash.$relativeUrl);
// Try to /catalog/img.png
if (file_exists(self::getDocumentDoot().$slash.$tryUrl)) {
return $tryUrl;
}
// Try to /img.png
else {
$tryUrl = str_replace($slash.$slash, $slash, '/'.$relativeUrl);
if (file_exists(self::getDocumentDoot().$slash.$tryUrl)) {
return $tryUrl;
}
}
}

// double slash to one slash
$url = str_replace($slash.$slash, $slash, $baseUrl.$relativeUrl);
return $url;
}



public static function resolveFilename($filename)
public static function resolveFilename($filename, $slash = '/')
{
$filename = str_replace('//', '/', $filename);
$parts = explode('/', $filename);
$filename = str_replace($slash.$slash, $slash, $filename);
$parts = explode($slash, $filename);
$out = array();
foreach ($parts as $part) {
if ($part == '.') {
Expand All @@ -503,7 +583,7 @@ public static function resolveFilename($filename)
}
$out[] = $part;
}
return implode('/', $out);
return implode($slash, $out);
}


Expand Down Expand Up @@ -590,7 +670,7 @@ public static function log($data, $comment = '')
}
$dateFormatted = $date->format("Y-m-d H:i:s u");

$line = "[$dateFormatted] {$_SERVER['REQUEST_URI']}\n";
$line = "[$dateFormatted] ".self::$url."\n";
if ($comment) {
$line .= "# ".$comment."\n";
}
Expand Down Expand Up @@ -627,11 +707,15 @@ public static function getDefaultSettings($settingKey = false)

public static function getCurrentDomain($trimWww = false)
{
if (empty($_SERVER['HTTP_HOST'])) {
if (is_null(self::$host) && !empty($_SERVER['HTTP_HOST'])) {
self::$host = $_SERVER['HTTP_HOST'];
}

if (empty(self::$host)) {
return false;
}

$currentHost = explode(":", $_SERVER['HTTP_HOST']);
$currentHost = explode(":", self::$host);
$currentHost = trim($currentHost[0]);
if ($trimWww) {
if (stripos($currentHost, 'www.')===0) {
Expand Down Expand Up @@ -668,4 +752,51 @@ public static function strtolower($str)

return \Tools::strtolower($str);
}
}


public static function htmlHasAmpMarkup($html)
{
return (stripos($html, "<html amp")!==false);
}


public static function htmlHasXmlMarkup($html)
{
return (stripos($html, "<?xml")!==false);
}

public static function getDocumentDoot()
{
return $_SERVER['DOCUMENT_ROOT'];
}


/**
* Check if URL has php script logic (no static image)
* Examples:
* - /index.php?route=product/image/catalog/payment.png
* - /manager/?a=system/file/edit&file=assets/template/css/../images/lines.png
*/
public static function urlHasPhpScript($url) {
$ext = pathinfo($url, PATHINFO_EXTENSION);
$posQ = stripos($url, '?');

if (!$posQ) {
$posQ = stripos($url, '&');
if (!$posQ) {
return false;
}
}

if (!$ext) {
return true;
}

$posExt = stripos($url, $ext);
if ($posQ < $posExt) {
return true;
}

return false;
}
}
2 changes: 1 addition & 1 deletion optipic/config.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<module>
<name>optipic</name>
<displayName><![CDATA[OptiPic]]></displayName>
<version><![CDATA[1.19.2]]></version>
<version><![CDATA[1.26.0]]></version>
<description><![CDATA[OptiPic - image optimization via smart CDN. The module automates the process of optimizing and compressing all images on the site according to the recommendations of Google PageSpeed Insights.]]></description>
<author><![CDATA[OptiPic]]></author>
<tab><![CDATA[seo]]></tab>
Expand Down
Loading

0 comments on commit 4d5204c

Please sign in to comment.