summaryrefslogtreecommitdiff
path: root/includes
diff options
context:
space:
mode:
authorDries Buytaert <dries@buytaert.net>2010-06-26 19:55:47 +0000
committerDries Buytaert <dries@buytaert.net>2010-06-26 19:55:47 +0000
commit344f5cb850ce47e5e01ca4dac1957437a92a7fea (patch)
treeff3c15854ecf56bdb7e05f64196497c0f92062d8 /includes
parent151fb3f94307e2167592c0a0973e2ef46d85fbe8 (diff)
downloadbrdo-344f5cb850ce47e5e01ca4dac1957437a92a7fea.tar.gz
brdo-344f5cb850ce47e5e01ca4dac1957437a92a7fea.tar.bz2
- Patch #693084 by dhthwy, jpmckinney, reglogge, clemens.tolboom, naxoc, chx: file_munge_filename() extension handling broken by move to File Field.
Diffstat (limited to 'includes')
-rw-r--r--includes/file.inc56
1 files changed, 45 insertions, 11 deletions
diff --git a/includes/file.inc b/includes/file.inc
index de05c799f..59ecadfe3 100644
--- a/includes/file.inc
+++ b/includes/file.inc
@@ -1098,6 +1098,12 @@ function file_space_used($uid = NULL, $status = FILE_STATUS_PERMANENT) {
* @param $validators
* An optional, associative array of callback functions used to validate the
* file. See file_validate() for a full discussion of the array format.
+ * If no extension validator is provided it will default to a limited safe
+ * list of extensions which is as follows: "jpg jpeg gif png txt
+ * doc xls pdf ppt pps odt ods odp". To allow all extensions you must
+ * explicitly set the 'file_validate_extensions' validator to an empty array
+ * (Beware: this is not safe and should only be allowed for trusted users, if
+ * at all).
* @param $destination
* A string containing the URI $source should be copied to.
* This must be a stream wrapper URI. If this value is omitted, Drupal's
@@ -1160,28 +1166,56 @@ function file_save_upload($source, $validators = array(), $destination = FALSE,
return FALSE;
}
- // Build the list of non-munged extensions.
- // @todo: this should not be here. we need to figure out the right place.
- $extensions = '';
- foreach ($user->roles as $rid => $name) {
- $extensions .= ' ' . variable_get("upload_extensions_$rid",
- variable_get('upload_extensions_default', 'jpg jpeg gif png txt html doc xls pdf ppt pps odt ods odp'));
- }
-
// Begin building file object.
$file = new stdClass();
$file->uid = $user->uid;
$file->status = 0;
- $file->filename = file_munge_filename(trim(basename($_FILES['files']['name'][$source]), '.'), $extensions);
+ $file->filename = trim(basename($_FILES['files']['name'][$source]), '.');
$file->uri = $_FILES['files']['tmp_name'][$source];
$file->filemime = file_get_mimetype($file->filename);
$file->filesize = $_FILES['files']['size'][$source];
- // Rename potentially executable files, to help prevent exploits.
- if (preg_match('/\.(php|pl|py|cgi|asp|js)$/i', $file->filename) && (substr($file->filename, -4) != '.txt')) {
+ $extensions = '';
+ if (isset($validators['file_validate_extensions'])) {
+ if (isset($validators['file_validate_extensions'][0])) {
+ // Build the list of non-munged extensions if the caller provided them.
+ $extensions = $validators['file_validate_extensions'][0];
+ }
+ else {
+ // If 'file_validate_extensions' is set and the list is empty then the
+ // caller wants to allow any extension. In this case we have to remove the
+ // validator or else it will reject all extensions.
+ unset($validators['file_validate_extensions']);
+ }
+ }
+ else {
+ // No validator was provided, so add one using the default list.
+ // Build a default non-munged safe list for file_munge_filename().
+ $extensions = 'jpg jpeg gif png txt doc xls pdf ppt pps odt ods odp';
+ $validators['file_validate_extensions'] = array();
+ $validators['file_validate_extensions'][0] = $extensions;
+ }
+
+ if (!empty($extensions)) {
+ // Munge the filename to protect against possible malicious extension hiding
+ // within an unknown file type (ie: filename.html.foo).
+ $file->filename = file_munge_filename($file->filename, $extensions);
+ }
+
+ // Rename potentially executable files, to help prevent exploits (i.e. will
+ // rename filename.php.foo and filename.php to filename.php.foo.txt and
+ // filename.php.txt, respectively). Don't rename if 'allow_insecure_uploads'
+ // evaluates to TRUE.
+ if (!variable_get('allow_insecure_uploads', 0) && preg_match('/\.(php|pl|py|cgi|asp|js)(\.|$)/i', $file->filename) && (substr($file->filename, -4) != '.txt')) {
$file->filemime = 'text/plain';
$file->uri .= '.txt';
$file->filename .= '.txt';
+ // The .txt extension may not be in the allowed list of extensions. We have
+ // to add it here or else the file upload will fail.
+ if (!empty($extensions)) {
+ $validators['file_validate_extensions'][0] .= ' txt';
+ drupal_set_message(t('For security reasons, your upload has been renamed to %filename.', array('%filename' => $file->filename)));
+ }
}
// If the destination is not provided, use the temporary directory.