/**
  * Handles the upload request. This is a static function to ensure that it is easily
  * accessible to other classes without having to instantiate a {@link Controller} object. 
  * A lot of this code is lifted from {@link AssetAdmin}.
  *
  * @todo Error handling on this is crap.
  * @param SS_HTTPRequest
  * @param Folder A folder that will be the destination of the upload.
  * @return array|string
  */
 public static function handle_upload(SS_HTTPRequest $r, $folder = null, $allowed_extensions = null)
 {
     if (!$folder) {
         $folder = singleton('Folder');
     }
     $newFiles = array();
     $errorResponse = "";
     if (isset($_FILES['file']) && is_array($_FILES['file'])) {
         $file_array = $_FILES['file'];
         foreach ($file_array['tmp_name'] as $index => $value) {
             if (is_uploaded_file($value)) {
                 $tmpFile = array('tmp_name' => $value, 'name' => $file_array['name'][$index], 'size' => $file_array['size'][$index], 'error' => $file_array['error'][$index]);
                 // validate files (only if not logged in as admin)
                 if (!File::$apply_restrictions_to_admin && Permission::check('ADMIN')) {
                     $valid = true;
                 } else {
                     // Set up the validator instance with rules
                     $validator = new Upload_Validator();
                     if (!$allowed_extensions) {
                         $allowed_extensions = File::$allowed_extensions;
                     }
                     $validator->setAllowedExtensions($allowed_extensions);
                     $validator->setAllowedMaxFileSize(self::$allowed_max_file_size);
                     // Do the upload validation with the rules
                     $upload = new Upload();
                     $upload->setValidator($validator);
                     $valid = $upload->validate($tmpFile);
                     if (!$valid) {
                         $errors = $upload->getErrors();
                         if ($errors) {
                             foreach ($errors as $error) {
                                 $errorResponse .= $error;
                             }
                         }
                     }
                 }
                 // move file to given folder
                 if ($valid) {
                     $newFile = $folder->addUploadToFolder($tmpFile);
                     $newFiles[] = $newFile;
                 } else {
                     return $errorResponse;
                 }
                 foreach ($newFiles as $newFile) {
                     $fileIDs[] = $newFile;
                     $fileObj = DataObject::get_one('File', "\"File\".\"ID\"={$newFile}");
                     if (method_exists($fileObj, 'onAfterUpload')) {
                         $fileObj->onAfterUpload();
                     }
                 }
             }
         }
     } else {
         return "File is too large.";
     }
     return $newFiles;
 }
 public function testInvalidFileExtensionValidatingMimeType()
 {
     // setup plaintext file with invalid extension
     $tmpFileName = 'UploadTest-testUpload.jpg';
     $tmpFilePath = TEMP_FOLDER . '/' . $tmpFileName;
     $tmpFileContent = '';
     for ($i = 0; $i < 10000; $i++) {
         $tmpFileContent .= '0';
     }
     file_put_contents($tmpFilePath, $tmpFileContent);
     // emulates the $_FILES array
     $tmpFile = array('name' => $tmpFileName, 'size' => filesize($tmpFilePath), 'tmp_name' => $tmpFilePath, 'extension' => 'jpg', 'error' => UPLOAD_ERR_OK);
     $u = new Upload();
     $u->setValidator(new MimeUploadValidator());
     $result = $u->load($tmpFile);
     $errors = $u->getErrors();
     $this->assertFalse($result, 'Load failed because file extension does not match excepted MIME type');
     $this->assertEquals('File extension does not match known MIME type', $errors[0]);
     unlink($tmpFilePath);
 }
    /**
     * This method processes the results of the UploadForm.
     * It will save the uploaded files to /assets/ and create new File objects as required.
     */
    function doUpload($data, $form)
    {
        $newFiles = array();
        $fileIDs = array();
        $fileNames = array();
        $fileSizeWarnings = '';
        $uploadErrors = '';
        $jsErrors = '';
        $status = '';
        $statusMessage = '';
        $processedFiles = array();
        foreach ($data['Files'] as $param => $files) {
            if (!is_array($files)) {
                $files = array($files);
            }
            foreach ($files as $key => $value) {
                $processedFiles[$key][$param] = $value;
            }
        }
        // Load POST data from arrays in to the correct dohickey.
        $processedData = array();
        foreach ($data as $dataKey => $value) {
            if ($dataKey == 'Files') {
                continue;
            }
            if (is_array($value)) {
                $i = 0;
                foreach ($value as $fileId => $dataValue) {
                    if (!isset($processedData[$i])) {
                        $processedData[$i] = array();
                    }
                    $processedData[$i][$dataKey] = $dataValue;
                    $i++;
                }
            }
        }
        $processedData = array_reverse($processedData);
        if ($data['FolderID'] && $data['FolderID'] != '') {
            $folder = DataObject::get_by_id("Folder", $data['FolderID']);
            if (!$folder) {
                throw new InvalidArgumentException(sprintf("Folder #%d doesn't exist", (int) $data['FolderID']));
            }
        } else {
            $folder = singleton('Folder');
        }
        foreach ($processedFiles as $filePostId => $tmpFile) {
            if ($tmpFile['error'] == UPLOAD_ERR_NO_TMP_DIR) {
                $status = 'bad';
                $statusMessage = _t('AssetAdmin.NOTEMP', 'There is no temporary folder for uploads. Please set upload_tmp_dir in php.ini.');
                break;
            }
            if ($tmpFile['tmp_name']) {
                // Workaround open_basedir problems
                if (ini_get("open_basedir")) {
                    $newtmp = TEMP_FOLDER . '/' . $tmpFile['name'];
                    move_uploaded_file($tmpFile['tmp_name'], $newtmp);
                    $tmpFile['tmp_name'] = $newtmp;
                }
                // validate files (only if not logged in as admin)
                if (!File::$apply_restrictions_to_admin && Permission::check('ADMIN')) {
                    $valid = true;
                } else {
                    // Set up the validator instance with rules
                    $validator = new Upload_Validator();
                    $validator->setAllowedExtensions(File::$allowed_extensions);
                    $validator->setAllowedMaxFileSize(self::$allowed_max_file_size);
                    // Do the upload validation with the rules
                    $upload = new Upload();
                    $upload->setValidator($validator);
                    $valid = $upload->validate($tmpFile);
                    if (!$valid) {
                        $errors = $upload->getErrors();
                        if ($errors) {
                            foreach ($errors as $error) {
                                $jsErrors .= "alert('" . Convert::raw2js($error) . "');";
                            }
                        }
                    }
                }
                // move file to given folder
                if ($valid) {
                    if ($newFile = $folder->addUploadToFolder($tmpFile)) {
                        if (self::$metadata_upload_enabled && isset($processedData[$filePostId])) {
                            $fileObject = DataObject::get_by_id('File', $newFile);
                            $metadataForm = new Form($this, 'MetadataForm', $fileObject->uploadMetadataFields(), new FieldSet());
                            $metadataForm->loadDataFrom($processedData[$filePostId]);
                            $metadataForm->saveInto($fileObject);
                            $fileObject->write();
                        }
                        $newFiles[] = $newFile;
                    }
                }
            }
        }
        if ($newFiles) {
            $numFiles = sizeof($newFiles);
            $statusMessage = sprintf(_t('AssetAdmin.UPLOADEDX', "Uploaded %s files"), $numFiles);
            $status = "good";
        } else {
            if ($status != 'bad') {
                $statusMessage = _t('AssetAdmin.NOTHINGTOUPLOAD', 'There was nothing to upload');
                $status = "";
            }
        }
        $fileObj = false;
        foreach ($newFiles as $newFile) {
            $fileIDs[] = $newFile;
            $fileObj = DataObject::get_one('File', "\"File\".\"ID\"={$newFile}");
            // notify file object after uploading
            if (method_exists($fileObj, 'onAfterUpload')) {
                $fileObj->onAfterUpload();
            }
            $fileNames[] = $fileObj->Name;
        }
        // workaround for content editors image upload.Passing an extra hidden field
        // in the content editors view of 'UploadMode' @see HtmlEditorField
        // this will be refactored for 2.5
        if (isset($data['UploadMode']) && $data['UploadMode'] == "CMSEditor" && $fileObj) {
            // we can use $fileObj considering that the uploader in the cmseditor can only upload
            // one file at a time. Once refactored to multiple files this is going to have to be changed
            $width = is_a($fileObj, 'Image') ? $fileObj->getWidth() : '100';
            $height = is_a($fileObj, 'Image') ? $fileObj->getHeight() : '100';
            $values = array('Filename' => $fileObj->Filename, 'Width' => $width, 'Height' => $height);
            return Convert::raw2json($values);
        }
        $sFileIDs = implode(',', $fileIDs);
        $sFileNames = implode(',', $fileNames);
        echo <<<HTML
\t\t\t<script type="text/javascript">
\t\t\t/* IDs: {$sFileIDs} */
\t\t\t/* Names: {$sFileNames} */
\t\t\t
\t\t\tvar form = parent.document.getElementById('Form_EditForm');
\t\t\tparent.statusMessage("{$statusMessage}","{$status}");
\t\t\t{$jsErrors}
\t\t\tparent.document.getElementById('sitetree').getTreeNodeByIdx( "{$folder->ID}" ).getElementsByTagName('a')[0].className += ' contents';
\t\t\tform.getPageFromServer(form.elements.ID.value);
\t\t\t</script>
HTML;
    }
 public function testFileVersioningWithAnExistingFile()
 {
     $upload = function ($tmpFileName) {
         // create tmp file
         $tmpFilePath = TEMP_FOLDER . '/' . $tmpFileName;
         $tmpFileContent = '';
         for ($i = 0; $i < 10000; $i++) {
             $tmpFileContent .= '0';
         }
         file_put_contents($tmpFilePath, $tmpFileContent);
         // emulates the $_FILES array
         $tmpFile = array('name' => $tmpFileName, 'type' => 'text/plaintext', 'size' => filesize($tmpFilePath), 'tmp_name' => $tmpFilePath, 'extension' => 'jpg', 'error' => UPLOAD_ERR_OK);
         $v = new UploadTest_Validator();
         // test upload into default folder
         $u = new Upload();
         $u->setReplaceFile(false);
         $u->setValidator($v);
         $u->loadIntoFile($tmpFile);
         return $u->getFile();
     };
     // test empty file version prefix
     Config::inst()->update('SilverStripe\\Filesystem\\Storage\\DefaultAssetNameGenerator', 'version_prefix', '');
     $file1 = $upload('UploadTest-IMG001.jpg');
     $this->assertEquals('UploadTest-IMG001.jpg', $file1->Name, 'File does not receive new name');
     $file2 = $upload('UploadTest-IMG001.jpg');
     $this->assertEquals('UploadTest-IMG002.jpg', $file2->Name, 'File does receive new name');
     $file3 = $upload('UploadTest-IMG002.jpg');
     $this->assertEquals('UploadTest-IMG003.jpg', $file3->Name, 'File does receive new name');
     $file4 = $upload('UploadTest-IMG3.jpg');
     $this->assertEquals('UploadTest-IMG3.jpg', $file4->Name, 'File does not receive new name');
     $file1->delete();
     $file2->delete();
     $file3->delete();
     $file4->delete();
     // test '-v' file version prefix
     Config::inst()->update('SilverStripe\\Filesystem\\Storage\\DefaultAssetNameGenerator', 'version_prefix', '-v');
     $file1 = $upload('UploadTest2-IMG001.jpg');
     $this->assertEquals('UploadTest2-IMG001.jpg', $file1->Name, 'File does not receive new name');
     $file2 = $upload('UploadTest2-IMG001.jpg');
     $this->assertEquals('UploadTest2-IMG001-v2.jpg', $file2->Name, 'File does receive new name');
     $file3 = $upload('UploadTest2-IMG001.jpg');
     $this->assertEquals('UploadTest2-IMG001-v3.jpg', $file3->Name, 'File does receive new name');
     $file4 = $upload('UploadTest2-IMG001-v3.jpg');
     $this->assertEquals('UploadTest2-IMG001-v4.jpg', $file4->Name, 'File does receive new name');
 }
Beispiel #5
0
 /**
  * Set custom validator for this field
  * 
  * @param object $validator
  */
 public function setValidator($validator)
 {
     $this->upload->setValidator($validator);
     return $this;
 }
Beispiel #6
0
 function testUploadFileWithNoExtensionTwiceAppendsNumber()
 {
     // create tmp file
     $tmpFileName = 'UploadTest-testUpload';
     $tmpFilePath = TEMP_FOLDER . '/' . $tmpFileName;
     $tmpFileContent = '';
     for ($i = 0; $i < 10000; $i++) {
         $tmpFileContent .= '0';
     }
     file_put_contents($tmpFilePath, $tmpFileContent);
     // emulates the $_FILES array
     $tmpFile = array('name' => $tmpFileName, 'type' => 'text/plaintext', 'size' => filesize($tmpFilePath), 'tmp_name' => $tmpFilePath, 'extension' => 'txt', 'error' => UPLOAD_ERR_OK);
     // Make sure there are none here, otherwise they get renamed incorrectly for the test.
     $this->deleteTestUploadFiles("/UploadTest-testUpload.*/");
     $v = new UploadTest_Validator();
     $v->setAllowedExtensions(array(''));
     // test upload into default folder
     $u = new Upload();
     $u->setValidator($v);
     $u->load($tmpFile);
     $file = $u->getFile();
     $this->assertEquals('UploadTest-testUpload', $file->Name, 'File is uploaded without extension');
     $u = new Upload();
     $u->setValidator($v);
     $u->load($tmpFile);
     $file2 = $u->getFile();
     $this->assertEquals('UploadTest-testUpload-2', $file2->Name, 'File receives a number attached to the end');
     $file->delete();
     $file2->delete();
 }
 public function testFileVersioningWithAnExistingFile()
 {
     $upload = function ($tmpFileName) {
         // create tmp file
         $tmpFilePath = TEMP_FOLDER . '/' . $tmpFileName;
         $tmpFileContent = '';
         for ($i = 0; $i < 10000; $i++) {
             $tmpFileContent .= '0';
         }
         file_put_contents($tmpFilePath, $tmpFileContent);
         // emulates the $_FILES array
         $tmpFile = array('name' => $tmpFileName, 'type' => 'text/plaintext', 'size' => filesize($tmpFilePath), 'tmp_name' => $tmpFilePath, 'extension' => 'jpg', 'error' => UPLOAD_ERR_OK);
         $v = new UploadTest_Validator();
         // test upload into default folder
         $u = new Upload();
         $u->setReplaceFile(false);
         $u->setValidator($v);
         $u->load($tmpFile);
         return $u->getFile();
     };
     $file1 = $upload('UploadTest-testUpload.jpg');
     $this->assertEquals('UploadTest-testUpload.jpg', $file1->Name, 'File does not receive new name');
     $file2 = $upload('UploadTest-testUpload.jpg');
     $this->assertEquals('UploadTest-testUpload2.jpg', $file2->Name, 'File does receive new name');
     $file3 = $upload('UploadTest-testUpload.jpg');
     $this->assertEquals('UploadTest-testUpload3.jpg', $file3->Name, 'File does receive new name');
     $file4 = $upload('UploadTest-testUpload3.jpg');
     $this->assertEquals('UploadTest-testUpload4.jpg', $file4->Name, 'File does receive new name');
     $file1->delete();
     $file2->delete();
     $file3->delete();
     $file4->delete();
 }
 private function buildScreenshots(Addon $addon, PackageInterface $package, $path)
 {
     $extra = $package->getExtra();
     $screenshots = array();
     $target = self::SCREENSHOTS_DIR . '/' . $addon->Name;
     if (isset($extra['screenshots'])) {
         $screenshots = (array) $extra['screenshots'];
     } elseif (isset($extra['screenshot'])) {
         $screenshots = (array) $extra['screenshot'];
     }
     // Delete existing screenshots.
     foreach ($addon->Screenshots() as $screenshot) {
         $screenshot->delete();
     }
     $addon->Screenshots()->removeAll();
     foreach ($screenshots as $screenshot) {
         if (!is_string($screenshot)) {
             continue;
         }
         $scheme = parse_url($screenshot, PHP_URL_SCHEME);
         // Handle absolute image URLs.
         if ($scheme == 'http' || $scheme == 'https') {
             $temp = TEMP_FOLDER . '/' . md5($screenshot);
             if (!copy($screenshot, $temp)) {
                 continue;
             }
             $data = array('name' => basename($screenshot), 'size' => filesize($temp), 'tmp_name' => $temp, 'error' => 0);
         } else {
             $source = $path . '/' . ltrim($screenshot, '/');
             // Prevent directory traversal.
             if ($source != realpath($source)) {
                 continue;
             }
             if (!file_exists($source)) {
                 continue;
             }
             $data = array('name' => basename($source), 'size' => filesize($source), 'tmp_name' => $source, 'error' => 0);
         }
         $upload = new Upload();
         $upload->setValidator(new AddonBuilderScreenshotValidator());
         $upload->load($data, $target);
         if ($file = $upload->getFile()) {
             $addon->Screenshots()->add($file);
         }
     }
 }
Beispiel #9
0
 /**
  * The main upload handler. Takes the $_FILES data from the request and stores a File
  * record {@see $defaults['file_class']}. Returns the ID of this new file to the 
  * Javascript handler, for insertion into the parent form.
  * Note: This handler may require authentication, and that may not be possible
  * if the PHP setting "session_use_only_cookies" is on.
  *
  * @return int
  */
 public function upload()
 {
     if (isset($_FILES["Filedata"]) && is_uploaded_file($_FILES["Filedata"]["tmp_name"])) {
         $upload_folder = $this->getUploadFolder();
         if ($this->Backend()) {
             if (isset($_REQUEST['FolderID'])) {
                 if ($folder = DataObject::get_by_id("Folder", Convert::raw2sql($_REQUEST['FolderID']))) {
                     $upload_folder = self::relative_asset_dir($folder->Filename);
                 }
             }
         }
         $ext = strtolower(end(explode('.', $_FILES['Filedata']['name'])));
         $class = in_array($ext, self::$image_extensions) ? $this->getSetting('image_class') : $this->getSetting('file_class');
         $file = new $class();
         // Perform check on allowed file extension, preventing upload of unallowed file types
         $u = new Upload();
         $u->setValidator($validator = new Upload_Validator());
         $validator->setAllowedExtensions(File::$allowed_extensions);
         if ($u->validate($_FILES['Filedata'])) {
             $u->loadIntoFile($_FILES['Filedata'], $file, $upload_folder);
         } else {
             return _t('Uploadify.FILETYPENOTALLOWED', 'File type not allowed!');
         }
         $file->write();
         if (method_exists($file, 'onAfterUpload')) {
             $file->onAfterUpload();
         }
         echo $file->ID;
     } else {
         echo ' ';
         // return something or SWFUpload won't fire uploadSuccess
     }
 }
 /**
  * @param ISummit $summit
  * @param $speaker_id
  * @param $tmp_file
  * @return BetterImage
  */
 public function uploadSpeakerPic(ISummit $summit, $speaker_id, $tmp_file)
 {
     $speaker_repository = $this->speaker_repository;
     return $this->tx_service->transaction(function () use($summit, $speaker_id, $tmp_file, $speaker_repository) {
         $speaker_id = intval($speaker_id);
         $speaker = $speaker_repository->getById($speaker_id);
         if (is_null($speaker)) {
             throw new NotFoundEntityException('PresentationSpeaker');
         }
         $image = new BetterImage();
         $upload = new Upload();
         $validator = new Upload_Validator();
         $validator->setAllowedExtensions(array('png', 'jpg', 'jpeg', 'gif'));
         $validator->setAllowedMaxFileSize(800 * 1024);
         // 300Kb
         $upload->setValidator($validator);
         if (!$upload->loadIntoFile($tmp_file, $image, 'profile-images')) {
             throw new EntityValidationException($upload->getErrors());
         }
         $image->write();
         return $image;
     });
 }
 public function testDeleteResampledImagesOnUpload()
 {
     $tmpFileName = 'UploadTest-testUpload.jpg';
     $tmpFilePath = TEMP_FOLDER . '/' . $tmpFileName;
     $uploadImage = function () use($tmpFileName, $tmpFilePath) {
         copy(__DIR__ . '/gdtest/test_jpg.jpg', $tmpFilePath);
         // emulates the $_FILES array
         $tmpFile = array('name' => $tmpFileName, 'type' => 'text/plaintext', 'size' => filesize($tmpFilePath), 'tmp_name' => $tmpFilePath, 'extension' => 'jpg', 'error' => UPLOAD_ERR_OK);
         $v = new UploadTest_Validator();
         // test upload into default folder
         $u = new Upload();
         $u->setReplaceFile(true);
         $u->setValidator($v);
         $u->load($tmpFile);
         return $u->getFile();
     };
     // Image upload and generate a resampled image
     $image = $uploadImage();
     $resampled = $image->ResizedImage(123, 456);
     $resampledPath = $resampled->getFullPath();
     $this->assertTrue(file_exists($resampledPath));
     // Re-upload the image, overwriting the original
     // Resampled images should removed when their parent file is overwritten
     $image = $uploadImage();
     $this->assertFalse(file_exists($resampledPath));
     unlink($tmpFilePath);
     $image->delete();
 }