]> git.immae.eu Git - github/wallabag/wallabag.git/blobdiff - src/Wallabag/CoreBundle/Helper/DownloadImages.php
Merge remote-tracking branch 'origin/master' into 2.3
[github/wallabag/wallabag.git] / src / Wallabag / CoreBundle / Helper / DownloadImages.php
index c83f96187f8a2c9b01479ae2a15cc34467065231..ed888cdb031ae52afd2b6624378c7927a0366e4d 100644 (file)
@@ -5,6 +5,7 @@ namespace Wallabag\CoreBundle\Helper;
 use Psr\Log\LoggerInterface;
 use Symfony\Component\DomCrawler\Crawler;
 use GuzzleHttp\Client;
+use GuzzleHttp\Message\Response;
 use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeExtensionGuesser;
 use Symfony\Component\Finder\Finder;
 
@@ -54,7 +55,7 @@ class DownloadImages
         $crawler = new Crawler($html);
         $result = $crawler
             ->filterXpath('//img')
-            ->extract(array('src'));
+            ->extract(['src']);
 
         $relativePath = $this->getRelativePath($entryId);
 
@@ -66,6 +67,11 @@ class DownloadImages
                 continue;
             }
 
+            // if image contains "&" and we can't find it in the html it might be because it's encoded as &
+            if (false !== stripos($image, '&') && false === stripos($html, $image)) {
+                $image = str_replace('&', '&', $image);
+            }
+
             $html = str_replace($image, $imagePath, $html);
         }
 
@@ -111,13 +117,11 @@ class DownloadImages
             return false;
         }
 
-        $ext = $this->mimeGuesser->guess($res->getHeader('content-type'));
-        $this->logger->debug('DownloadImages: Checking extension', ['ext' => $ext, 'header' => $res->getHeader('content-type')]);
-        if (!in_array($ext, ['jpeg', 'jpg', 'gif', 'png'], true)) {
-            $this->logger->error('DownloadImages: Processed image with not allowed extension. Skipping '.$imagePath);
-
+        $ext = $this->getExtensionFromResponse($res, $imagePath);
+        if (false === $res) {
             return false;
         }
+
         $hashImage = hash('crc32', $absolutePath);
         $localPath = $folderPath.'/'.$hashImage.'.'.$ext;
 
@@ -144,6 +148,8 @@ class DownloadImages
                 $this->logger->debug('DownloadImages: Re-creating jpg');
                 break;
             case 'png':
+                imagealphablending($im, false);
+                imagesavealpha($im, true);
                 imagepng($im, $localPath, ceil(self::REGENERATE_PICTURES_QUALITY / 100 * 9));
                 $this->logger->debug('DownloadImages: Re-creating png');
         }
@@ -230,4 +236,45 @@ class DownloadImages
 
         return false;
     }
+
+    /**
+     * Retrieve and validate the extension from the response of the url of the image.
+     *
+     * @param Response $res       Guzzle Response
+     * @param string   $imagePath Path from the src image from the content (used for log only)
+     *
+     * @return string|false Extension name or false if validation failed
+     */
+    private function getExtensionFromResponse(Response $res, $imagePath)
+    {
+        $ext = $this->mimeGuesser->guess($res->getHeader('content-type'));
+        $this->logger->debug('DownloadImages: Checking extension', ['ext' => $ext, 'header' => $res->getHeader('content-type')]);
+
+        // ok header doesn't have the extension, try a different way
+        if (empty($ext)) {
+            $types = [
+                'jpeg' => "\xFF\xD8\xFF",
+                'gif' => 'GIF',
+                'png' => "\x89\x50\x4e\x47\x0d\x0a",
+            ];
+            $bytes = substr((string) $res->getBody(), 0, 8);
+
+            foreach ($types as $type => $header) {
+                if (0 === strpos($bytes, $header)) {
+                    $ext = $type;
+                    break;
+                }
+            }
+
+            $this->logger->debug('DownloadImages: Checking extension (alternative)', ['ext' => $ext]);
+        }
+
+        if (!in_array($ext, ['jpeg', 'jpg', 'gif', 'png'], true)) {
+            $this->logger->error('DownloadImages: Processed image with not allowed extension. Skipping: '.$imagePath);
+
+            return false;
+        }
+
+        return $ext;
+    }
 }