(if you're using apache), check that the LimitRequestBody directive isn't
set too low (it's optional, so it may not be there at all).
+* `extblacklist`: associative array to either deny certain extensions or
+ change them to a different one. For example:
+ $config['attachments']['extblacklist']['php'] = 'phps'; // this turns .php into .phps
+ $config['attachments']['extblacklist']['exe'] = false; // this would deny any uploads
+ // of files with the "exe" extension
+
* `process_links`: follow redirects and save all available file information
(mimetype, date, size, oembed, etc.). Defaults to true.
-# GNU social 1.21.x
+# GNU social 1.22.x
(c) 2010-2019 Free Software Foundation, Inc
This is the README file for GNU social, the free
return $filename;
}
+ /**
+ * @param string $filename
+ * @return string|bool Value from the 'extblacklist' array, in the config
+ */
+ public static function getSafeExtension(string $filename) {
+ if (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 restricted files
+ if (array_key_exists($ext, $blacklist)) {
+ if (!is_string($blacklist[$ext])) {
+ return false;
+ }
+ // 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;
+ } else {
+ return false;
+ }
+ }
+
/**
* @param $mimetype string The mimetype we've discovered for this file.
* @param $filename string An optional filename which we can use on failure.
return $ext;
} catch (UnknownMimeExtensionException $e) {
// We don't know the extension for this mimetype, but let's guess.
-
// If we can't recognize the extension from the MIME, we try
// to guess based on filename, if one was supplied.
- if (!is_null($filename) && 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 new 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];
+ if (!is_null($filename)) {
+ $ext = getSafeExtension($filename);
+ if ($ext === false) {
+ // we don't have a safe replacement extension
+ throw new ClientException(_('Blacklisted file extension.'));
+ } else {
+ return $ext;
}
- // the attachment extension based on its filename was not blacklisted so it's ok to use it
- return $ext;
}
} catch (Exception $e) {
common_log(LOG_INFO, 'Problem when figuring out extension for mimetype: '._ve($e));
// 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();
- // FIXME: try to build a regexp that will get jpeg from image/jpeg as well as json from application/jrd+json
- if (!preg_match('/\/([a-z0-9]+)/', mb_strtolower($mimetype), $matches)) {
- throw new Exception('Malformed mimetype: '.$mimetype);
+ // Will get jpeg from image/jpeg as well as json from application/jrd+json
+ if (!preg_match('/[\/+-\.]([a-z0-9]+)/', mb_strtolower($mimetype), $matches)) {
+ throw new Exception("Malformed mimetype: {$mimetype}");
}
return mb_strtolower($matches[1]);
}
'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', // this turns .php into .phps
- 'exe' => false, // this would deny any uploads to keep the "exe" file extension
- ],
+ 'extblacklist' => [],
'memory_limit' => '1024M' // PHP's memory limit to use temporarily when handling images
),
'thumbnail' => [
define('GNUSOCIAL_ENGINE', 'GNU social');
define('GNUSOCIAL_ENGINE_URL', 'https://www.gnu.org/software/social/');
-define('GNUSOCIAL_BASE_VERSION', '1.21.3');
+define('GNUSOCIAL_BASE_VERSION', '1.22.0');
define('GNUSOCIAL_LIFECYCLE', 'dev'); // 'dev', 'alpha[0-9]+', 'beta[0-9]+', 'rc[0-9]+', 'release'
define('GNUSOCIAL_VERSION', GNUSOCIAL_BASE_VERSION . '-' . GNUSOCIAL_LIFECYCLE);
-define('GNUSOCIAL_CODENAME', 'The Invicta Crusade');
+define('GNUSOCIAL_CODENAME', 'Undecided');
define('AVATAR_PROFILE_SIZE', 96);
define('AVATAR_STREAM_SIZE', 48);
File::respectsQuota($scoped, $_FILES[$param]['size']);
}
+ // Gets a replacement extension if configured in the config, returns false if it's blocked
+ $ext = File::getSafeExtension($_FILES[$param]['name']);
+ if ($ext === false) {
+ throw new ClientException(_('Blacklisted file extension.'));
+ }
+
$mimetype = self::getUploadedMimeType($_FILES[$param]['tmp_name'], $_FILES[$param]['name']);
$media = common_get_mime_media($mimetype);
}
// New file name format
- $original_filename = bin2hex("{$basename}.{$ext}");
+ $original_filename = bin2hex($basename);
$filename = "{$original_filename}-{$filehash}";
$filepath = File::path($filename);
*/
public static function getDisplayName(File $file) : string {
// New file name format is "{bin2hex(original_name.ext)}-{$hash}"
- $ret = preg_match('/^([^\-]+)-.+$/', $file->filename, $matches);
+ $ret = preg_match('/^([^\.-]+)-.+$/', $file->filename, $matches);
// If there was an error in the match, something's wrong with some piece
// of code (could be a file with utf8 chars in the name)
- $user_error_mesg = "Invalid file name ({$file->filename}).";
- $log_error_msg = "Invalid file name for File with id={$file->id} " .
- "({$file->filename}). Some plugin probably did something wrong.";
+ $log_error_msg = "Invalid file name for File with id={$file->id} " .
+ "({$file->filename}). Some plugin probably did something wrong.";
if ($ret === false) {
common_log(LOG_ERR, $log_error_msg);
- throw new ServerException($user_error_msg);
} elseif ($ret === 1) {
$filename = hex2bin($matches[1]);
} else {
// The old file name format was "{hash}.{ext}"
// This estracts 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');