]> git.mxchange.org Git - quix0rs-gnu-social.git/commitdiff
Make uploads work properly if we accept _all_ attachment types
authorMikael Nordfeldth <mmn@hethane.se>
Thu, 25 Feb 2016 21:15:54 +0000 (22:15 +0100)
committerMikael Nordfeldth <mmn@hethane.se>
Thu, 25 Feb 2016 21:15:54 +0000 (22:15 +0100)
Also introduced $config['attachments']['extblacklist'] that can disable
certain file extensions (or rewrite them, for example php => phps)

classes/File.php
lib/default.php
lib/mediafile.php

index 6ba80eb5f66ad976e9269dac32e6235a8ff5f4ed..2115313a81ce5bf7ec43d89abf7b055fdad5cec2 100644 (file)
@@ -237,7 +237,7 @@ class File extends Managed_DataObject
 
     static function filename(Profile $profile, $origname, $mimetype)
     {
-        $ext = self::guessMimeExtension($mimetype);
+        $ext = self::guessMimeExtension($mimetype, $origname);
 
         // Normalize and make the original filename more URL friendly.
         $origname = basename($origname, ".$ext");
@@ -258,19 +258,54 @@ class File extends Managed_DataObject
         return $filename;
     }
 
-    static function guessMimeExtension($mimetype)
+    /**
+     * @param $mimetype The mimetype we've discovered for this file.
+     * @param $filename An optional filename which we can use on failure.
+     */
+    static function guessMimeExtension($mimetype, $filename=null)
     {
+        $ext = null;
         try {
+            // first see if we know the extension for our mimetype
             $ext = common_supported_mime_to_ext($mimetype);
-        } catch (Exception $e) {
-            // We don't support this mimetype, but let's guess the extension
-            $matches = array();
-            if (!preg_match('/\/([a-z0-9]+)/', mb_strtolower($mimetype), $matches)) {
-                throw new Exception('Malformed mimetype: '.$mimetype);
+            // we do, so use it!
+            return $ext;
+        } catch (Exception $e) {    // FIXME: Make this exception more specific to "unknown mime=>ext relation"
+            // We don't know the extension for this mimetype, but let's guess.
+
+            // If we are very liberal with uploads ($config['attachments']['supported'] === true)
+            // then we try to do some guessing based on the filename, if it was supplied.
+            if (!is_null($filename) && common_config('attachments', 'supported')===true
+                    && preg_match('/^.+\.([A-Za-z0-9]+)$/', $filename, $matches)) {
+                // we matched on a file extension, so let's see if it means something.
+                $ext = mb_strtolower($matches[1]);
+
+                $blacklist = common_config('attachments', 'extblacklist');
+                // If we got an extension from $filename we want to check if it's in a blacklist
+                // so we avoid people uploading .php files etc.
+                if (array_key_exists($ext, $blacklist)) {
+                    if (!is_string($blacklist[$ext])) {
+                        // we don't have a safe replacement extension
+                        throw ClientException(_('Blacklisted file extension.'));
+                    }
+                    common_debug('Found replaced extension for filename '._ve($filename).': '._ve($ext));
+
+                    // return a safe replacement extension ('php' => 'phps' for example)
+                    return $blacklist[$ext];
+                }
+                // the attachment extension based on its filename was not blacklisted so it's ok to use it
+                return $ext;
             }
-            $ext = $matches[1];
         }
-        return mb_strtolower($ext);
+
+        // If nothing else has given us a result, try to extract it from
+        // the mimetype value (this turns .jpg to .jpeg for example...)
+        $matches = array();
+        if (!preg_match('/\/([a-z0-9]+)/', mb_strtolower($mimetype), $matches)) {
+            throw new Exception('Malformed mimetype: '.$mimetype);
+        }
+        $ext = mb_strtolower($matches[1]);
+        return $ext;
     }
 
     /**
index f8ce3bd4fe8880effeab8dfa207bfa77439ec1ef..b945c24e207596b0a756400cd7df3bf5baec1ea0 100644 (file)
@@ -266,6 +266,10 @@ $default =
               'show_html' => false,  // show (filtered) text/html attachments (and oEmbed HTML etc.). Doesn't affect AJAX calls.
               'show_thumbs' => true, // show thumbnails in notice lists for uploaded images, and photos and videos linked remotely that provide oEmbed info
               'process_links' => true, // check linked resources for embeddable photos and videos; this will hit referenced external web sites when processing new messages.
+              'extblacklist' => [
+                    'php' => 'phps',
+                    'exe' => false,  // this would deny any uploads to keep the "exe" file extension
+                ],
               ),
         'thumbnail' =>
         array('crop' => false,      // overridden to true if thumb height === null
index 9fe5432ad503273c47d35160a481dc84b6c5d3e7..1e0fb39769953ba772ae6916e6cf7593136c75d6 100644 (file)
@@ -253,15 +253,15 @@ class MediaFile
             File::respectsQuota($scoped, $_FILES[$param]['size']);
 
             $mimetype = self::getUploadedMimeType($_FILES[$param]['tmp_name'], $_FILES[$param]['name']);
+            $basename = basename($_FILES[$param]['name']);
 
             switch (common_config('attachments', 'filename_base')) {
             case 'upload':
-                $basename = basename($_FILES[$param]['name']);
                 $filename = File::filename($scoped, $basename, $mimetype);
                 break;
             case 'hash':
             default:
-                $filename = strtolower($filehash) . '.' . File::guessMimeExtension($mimetype); 
+                $filename = strtolower($filehash) . '.' . File::guessMimeExtension($mimetype, $basename);
             }
             $filepath = File::path($filename);