MDL-31112 Repository upload - check for completely null files (likely to be folders...
authorDavo Smith <git@davosmith.co.uk>
Tue, 7 Feb 2012 07:26:54 +0000 (07:26 +0000)
committerDavo Smith <git@davosmith.co.uk>
Tue, 14 Feb 2012 08:25:04 +0000 (08:25 +0000)
repository/upload/lang/en/repository_upload.php
repository/upload/lib.php

index 614b219..1d5664d 100644 (file)
@@ -34,3 +34,4 @@ $string['upload_error_no_file'] = 'No file was uploaded.';
 $string['upload_error_no_tmp_dir'] = 'PHP is missing a temporary folder.';
 $string['upload_error_cant_write'] = 'Failed to write file to disk.';
 $string['upload_error_extension'] = 'A PHP extension stopped the file upload.';
+$string['upload_error_invalid_file'] = 'The file \'{$a}\' has no data in it - did you try to upload a folder?';
\ No newline at end of file
index 823a68b..e0ce433 100644 (file)
@@ -129,6 +129,12 @@ class repository_upload extends repository {
             }
         }
 
+        // Check the file has some non-null contents - usually an indication that a user has
+        // tried to upload a folder by mistake
+        if (!$this->check_valid_contents($_FILES[$elname]['tmp_name'])) {
+            throw new moodle_exception('upload_error_invalid_file', 'repository_upload', '', $record->filename);
+        }
+
         if ($this->mimetypes != '*') {
             // check filetype
             $filemimetype = mimeinfo('type', $_FILES[$elname]['name']);
@@ -178,6 +184,32 @@ class repository_upload extends repository {
         }
     }
 
+    /**
+     * Checks the contents of the given file is not completely NULL - this can happen if a
+     * user drags & drops a folder onto a filemanager / filepicker element
+     * @param filepath full path (including filename) to file to check
+     * @return true if file has at least one non-null byte within it
+     */
+    protected function check_valid_contents($filepath) {
+        $buffersize = 4096;
+
+        $fp = fopen($filepath, 'r');
+        if (!$fp) {
+            return false; // Cannot read the file - something has gone wrong
+        }
+        while (!feof($fp)) {
+            // Read the file 4k at a time
+            $data = fread($fp, $buffersize);
+            if (preg_match('/[^\0]+/', $data)) {
+                fclose($fp);
+                return true; // Return as soon as a non-null byte is found
+            }
+        }
+        // Entire file is NULL
+        fclose($fp);
+        return false;
+    }
+
     /**
      * Return a upload form
      * @return array