]> git.mxchange.org Git - quix0rs-gnu-social.git/commitdiff
[CORE][StoreRemoteMedia] Fixed bug where sometimes images were written outside the...
authorMiguel Dantas <biodantasgs@gmail.com>
Thu, 11 Jul 2019 22:49:16 +0000 (23:49 +0100)
committerDiogo Cordeiro <diogo@fc.up.pt>
Sat, 3 Aug 2019 16:31:43 +0000 (17:31 +0100)
actions/attachment.php
classes/File.php
classes/File_thumbnail.php
lib/httpclient.php
lib/imagefile.php
lib/mediafile.php
plugins/StoreRemoteMedia/StoreRemoteMediaPlugin.php

index f261cc30bd4a024cdafce3f79b41aea3249cd7f4..993f94b007834d5347a69904c841020e68b0dab0 100644 (file)
@@ -208,7 +208,8 @@ class AttachmentAction extends ManagedAction
      */
     static function sendFile(string $filepath, $filesize) {
         if (is_string(common_config('site', 'x-static-delivery'))) {
-            $relative_path = end(explode(INSTALLDIR, $filepath));
+            $tmp = explode(INSTALLDIR, $filepath);
+            $relative_path = end($tmp);
             common_debug("Using Static Delivery with header: '" .
                          common_config('site', 'x-static-delivery') . ": {$relative_path}'");
             header(common_config('site', 'x-static-delivery') . ": {$relative_path}");
index 564bdb00551f374a8c87040a4a87a4c490b32310..95127c6aeedcf53b44df2963ae2d5941f83cf93f 100644 (file)
@@ -617,7 +617,7 @@ class File extends Managed_DataObject
             }
         } else {
             try {
-                return File_thumbnail::byFile($this)->getPath();
+                return File_thumbnail::byFile($this, true)->getPath();
             } catch (NoResultException $e) {
                 // File not stored locally
                 throw new FileNotStoredLocallyException($this);
@@ -637,10 +637,10 @@ class File extends Managed_DataObject
     {
         if (!empty($thumbnail)) {
             $filepath = $thumbnail->getPath();
-        } elseif (empty($this->filename)) {
-            $filepath = File_thumbnail::byFile($this)->getPath();
-        } else {
+        } elseif (!empty($this->filename)) {
             return $this->mimetype;
+        } else {
+            $filepath = File_thumbnail::byFile($this, true)->getPath();
         }
 
         $info = @getimagesize($filepath);
index 5e751c3c4db9cff0b50ad9aeadd3a8e0c3a5b5c9..eb6295501a6fa8d7f9f6f7552e37fd172236cf8a 100644 (file)
@@ -244,11 +244,9 @@ class File_thumbnail extends Managed_DataObject
      */
     public function getHtmlAttrs(array $orig=array(), $overwrite=true)
     {
-        $attrs = [
-                'height' => $this->getHeight(),
-                'width'  => $this->getWidth(),
-                'src'    => $this->getUrl(),
-            ];
+        $attrs = [ 'height' => $this->getHeight(),
+                   'width'  => $this->getWidth(),
+                   'src'    => $this->getUrl() ];
         return $overwrite ? array_merge($orig, $attrs) : array_merge($attrs, $orig);
     }
 
index 819a5e6e0799140646ac01aa8c76cd6e0b058608..184b2c2e13870c429c06281b1763857b7e13f259 100644 (file)
@@ -402,4 +402,19 @@ class HTTPClient extends HTTP_Request2
         } while ($maxRedirs);
         return new GNUsocial_HTTPResponse($response, $this->getUrl(), $redirs);
     }
+
+    public static function get_filename(string $url, array $headers = null) : string {
+        if ($headers === null) {
+            $head = (new HTTPClient())->head($url);
+            $headers = $head->getHeader();
+            $headers = array_change_key_case($headers, CASE_LOWER);
+        }
+        if (array_key_exists('content-disposition', $headers) &&
+            preg_match('/^.+; filename="(.+?)"$/', $headers['content-disposition'], $matches) === 1) {
+            return $matches[1];
+        } else {
+            common_log(LOG_INFO, "Couldn't determine filename for url: {$url}");
+            return _('Untitled attachment');
+        }
+    }
 }
index c6465c52b1442ffb07fe2a635b4aaccf0f1bde40..b921a2483c81e3f91b7f57410d24671ae8590348 100644 (file)
@@ -125,12 +125,10 @@ class ImageFile extends MediaFile
             }
 
             // And we'll only consider it an image if it has such a media type
-            switch ($media) {
-            case 'image':
-                $imgPath = $file->getPath();
-                break;
-            default:
+            if($media !== 'image') {
                 throw new UnsupportedMediaException(_m('Unsupported media format.'), $file->getPath());
+            } else if (!empty($file->filename)) {
+                $imgPath = $file->getPath();
             }
         }
 
@@ -376,7 +374,11 @@ class ImageFile extends MediaFile
 
         $type = $this->preferredType();
         $ext = image_type_to_extension($type, true);
-        $outpath = preg_replace("/\.[^\.]+$/", $ext, $outpath);
+        // Decoding returns null if the file is in the old format
+        $filename = MediaFile::decodeFilename(basename($outpath));
+        // Encoding null makes the file use 'untitled', and also replaces the extension
+        $outfilename = MediaFile::encodeFilename($filename, $this->filehash, $ext);
+        $outpath = dirname($outpath) . DIRECTORY_SEPARATOR . $outfilename;
 
         switch ($type) {
          case IMAGETYPE_GIF:
@@ -573,9 +575,8 @@ class ImageFile extends MediaFile
             return $thumb;
         }
 
-        $filename = basename($this->filepath);
         $extension = File::guessMimeExtension($this->mimetype);
-        $outname = "thumb-{$this->fileRecord->getID()}-{$width}x{$height}-{$filename}";
+        $outname = "thumb-{$this->fileRecord->getID()}-{$width}x{$height}-{$this->filename}";
         $outpath = File_thumbnail::path($outname);
 
         // The boundary box for our resizing
@@ -601,16 +602,8 @@ class ImageFile extends MediaFile
         ));
 
         // Perform resize and store into file
-        $this->resizeTo($outpath, $box);
-
-        try {
-            // Avoid deleting the original
-            if (!in_array($this->getPath(), [File::path($this->filename), File_thumbnail::path($this->filename)])) {
-                $this->unlink();
-            }
-        } catch (FileNotFoundException $e) {
-            // $this->getPath() says the file doesn't exist anyway, so no point in trying to delete it!
-        }
+        $outpath = $this->resizeTo($outpath, $box);
+        $outname = basename($outpath);
 
         return File_thumbnail::saveThumbnail(
             $this->fileRecord->getID(),
index 0efdbada76391f76df75aa14e8633482af049873..5086add5836ae22af256d05bda509db4b1f87e6d 100644 (file)
@@ -241,7 +241,7 @@ class MediaFile
      * having an extension in the file, removing trust in extensions, while keeping the original name
      * @throws ClientException
      */
-    public static function encodeFilename(string $original_name, string $filehash, string $ext = null) : string
+    public static function encodeFilename($original_name, string $filehash, $ext = null) : string
     {
         if (empty($original_name)) {
             $original_name = _('Untitled attachment');
@@ -274,7 +274,8 @@ class MediaFile
      */
     public static function decodeFilename(string $encoded_filename)
     {
-        $ret = preg_match('/^([^-]+?)-[^-]+$/', $encoded_filename, $matches);
+        // The x is because it is using in thumbnails
+        $ret = preg_match('/^([^-x]+?)-[^-]+$/', $encoded_filename, $matches);
         if ($ret === false) {
             return false;
         } elseif ($ret === 0) {
@@ -650,7 +651,7 @@ class MediaFile
         } elseif ($filename === null) {
             // The old file name format was "{hash}.{ext}" so we didn't have a name
             // This extracts the extension
-            $ret = preg_match('/^.+?\.(.+)$/', $file->filename, $matches);
+            $ret = preg_match('/^.+?\.+?(.+)$/', $file->filename, $matches);
             if ($ret !== 1) {
                 common_log(LOG_ERR, $log_error_msg);
                 return _('Untitled attachment');
index a722f9535aa32364ce2d30cf33bbb1db4d9a66fc..582fc5f4e07dbd48a3dff8ea707e807a5fac301f 100644 (file)
@@ -75,8 +75,15 @@ class StoreRemoteMediaPlugin extends Plugin
                                  'unnecessarily downloading too large files. URL: %s',
                                  $file->getID(), $remoteUrl));
 
+            $url = $remoteUrl;
             $head = $http->head($remoteUrl);
             $remoteUrl = $head->getEffectiveUrl();   // to avoid going through redirects again
+
+            if (empty($remoteUrl)) {
+                common_log(LOG_ERR, "URL after redirects is somehow empty, for URL {$url}");
+                return true;
+            }
+
             if (!$this->checkBlackList($remoteUrl)) {
                 common_log(LOG_WARN, sprintf('%s: Non-blacklisted URL %s redirected to blacklisted URL %s',
                                              __CLASS__, $file->getUrl(), $remoteUrl));
@@ -84,6 +91,7 @@ class StoreRemoteMediaPlugin extends Plugin
             }
 
             $headers = $head->getHeader();
+            $headers = array_change_key_case($headers, CASE_LOWER);
             $filesize = isset($headers['content-length']) ?: $file->getSize();
 
             if (empty($filesize)) {
@@ -133,18 +141,16 @@ class StoreRemoteMediaPlugin extends Plugin
 
             //FIXME: Add some code so we don't have to store duplicate File rows for same hash files.
         } catch (NoResultException $e) {
-            if (preg_match('/^.+; filename="(.+?)"$/', $headers['content-disposition'], $matches) === 1) {
-                $filename = MediaFile::encodeFilename($matches[1], $filehash);
-            } else {
-                common_log(LOG_ERR, "Couldn't determine filename for url: {$remoteUrl}");
-                // throw new ServerError(_("Couldn't determine filename for url: {$remoteUrl}"));
-            }
+            $original_name = HTTPClient::get_filename($remoteUrl, $headers);
+            $filename = MediaFile::encodeFilename($original_name, $filehash);
             $fullpath = File::path($filename);
 
-            common_debug("StoreRemoteMedia retrieved file with id={$file->id} and will store in {$filename}");
+            common_debug("StoreRemoteMedia retrieved url {$remoteUrl} for file with id={$file->id} " .
+                         "and will store in {$fullpath}");
 
             // Write the file to disk if it doesn't exist yet. Throw Exception on failure.
-            if (!file_exists($fullpath) && file_put_contents($fullpath, $imgData) === false) {
+            if ((!file_exists($fullpath) || substr($fullpath, 0, strlen(INSTALLDIR)) != INSTALLDIR) &&
+                file_put_contents($fullpath, $imgData) === false) {
                 throw new ServerException(_('Could not write downloaded file to disk.'));
             }