[FEATURE] Integrate File Abstraction Layer API
authorTYPO3 FAL Team <typo3v4@typo3.org>
Sat, 25 Feb 2012 21:52:35 +0000 (22:52 +0100)
committerSteffen Ritter <info@rs-websystems.de>
Fri, 2 Mar 2012 16:05:51 +0000 (17:05 +0100)
Change-Id: Id0d5071aed6c9a03b75069bb9ba970ccfa5ca525
Resolves: #33749
Releases: 4.7
Reviewed-on: http://review.typo3.org/9208
Reviewed-by: Steffen Ritter
Tested-by: Steffen Ritter
62 files changed:
t3lib/config_default.php
t3lib/core_autoload.php
t3lib/file/AbstractFile.php [new file with mode: 0644]
t3lib/file/Collection/AbstractFileCollection.php [new file with mode: 0644]
t3lib/file/Collection/FolderBasedFileCollection.php [new file with mode: 0644]
t3lib/file/Collection/StaticFileCollection.php [new file with mode: 0644]
t3lib/file/Driver/AbstractDriver.php [new file with mode: 0644]
t3lib/file/Driver/Configuration/LocalDriverFlexForm.xml [new file with mode: 0644]
t3lib/file/Driver/DriverRegistry.php [new file with mode: 0644]
t3lib/file/Driver/LocalDriver.php [new file with mode: 0644]
t3lib/file/Exception/AbstractFileException.php [new file with mode: 0644]
t3lib/file/Exception/AbstractFileOperationException.php [new file with mode: 0644]
t3lib/file/Exception/ExistingTargetFileNameException.php [new file with mode: 0644]
t3lib/file/Exception/ExistingTargetFolderException.php [new file with mode: 0644]
t3lib/file/Exception/FileDoesNotExistException.php [new file with mode: 0644]
t3lib/file/Exception/FileOperationErrorException.php [new file with mode: 0644]
t3lib/file/Exception/FolderDoesNotExistException.php [new file with mode: 0644]
t3lib/file/Exception/IllegalFileExtensionException.php [new file with mode: 0644]
t3lib/file/Exception/InsufficientFileAccessPermissionsException.php [new file with mode: 0644]
t3lib/file/Exception/InsufficientFileReadPermissionsException.php [new file with mode: 0644]
t3lib/file/Exception/InsufficientFileWritePermissionsException.php [new file with mode: 0644]
t3lib/file/Exception/InsufficientFolderAccessPermissionsException.php [new file with mode: 0644]
t3lib/file/Exception/InsufficientFolderReadPermissionsException.php [new file with mode: 0644]
t3lib/file/Exception/InsufficientFolderWritePermissionsException.php [new file with mode: 0644]
t3lib/file/Exception/InsufficientUserPermissionsException.php [new file with mode: 0644]
t3lib/file/Exception/InvalidFileException.php [new file with mode: 0644]
t3lib/file/Exception/InvalidFileNameException.php [new file with mode: 0644]
t3lib/file/Exception/InvalidFolderException.php [new file with mode: 0644]
t3lib/file/Exception/InvalidPathException.php [new file with mode: 0644]
t3lib/file/Exception/InvalidTargetFolderException.php [new file with mode: 0644]
t3lib/file/Exception/NotInMountPointException.php [new file with mode: 0644]
t3lib/file/Exception/UploadException.php [new file with mode: 0644]
t3lib/file/Exception/UploadSizeException.php [new file with mode: 0644]
t3lib/file/Factory.php [new file with mode: 0644]
t3lib/file/File.php [new file with mode: 0644]
t3lib/file/FileInterface.php [new file with mode: 0644]
t3lib/file/FileReference.php [new file with mode: 0644]
t3lib/file/Folder.php [new file with mode: 0644]
t3lib/file/ProcessedFile.php [new file with mode: 0644]
t3lib/file/Repository/AbstractRepository.php [new file with mode: 0644]
t3lib/file/Repository/FileCollectionRepository.php [new file with mode: 0644]
t3lib/file/Repository/FileRepository.php [new file with mode: 0644]
t3lib/file/Repository/ProcessedFileRepository.php [new file with mode: 0644]
t3lib/file/Repository/StorageRepository.php [new file with mode: 0644]
t3lib/file/ResourceInterface.php [new file with mode: 0644]
t3lib/file/Service/BackwardsCompatibility/TslibContentAdapterService.php [new file with mode: 0644]
t3lib/file/Service/FileProcessingService.php [new file with mode: 0644]
t3lib/file/Service/ImageProcessingService.php [new file with mode: 0644]
t3lib/file/Service/IndexerService.php [new file with mode: 0644]
t3lib/file/Service/UserfilemountService.php [new file with mode: 0644]
t3lib/file/Storage.php [new file with mode: 0644]
tests/t3lib/file/BaseTestCase.php [new file with mode: 0644]
tests/t3lib/file/Driver/AbstractDriverTest.php [new file with mode: 0644]
tests/t3lib/file/Driver/DriverRegistryTest.php [new file with mode: 0644]
tests/t3lib/file/Driver/LocalDriverTest.php [new file with mode: 0644]
tests/t3lib/file/FactoryTest.php [new file with mode: 0644]
tests/t3lib/file/FileTest.php [new file with mode: 0644]
tests/t3lib/file/FolderTest.php [new file with mode: 0644]
tests/t3lib/file/Repository/AbstractRepositoryTest.php [new file with mode: 0644]
tests/t3lib/file/Service/IndexerServiceTest.php [new file with mode: 0644]
tests/t3lib/file/StorageTest.php [new file with mode: 0644]
typo3/sysext/lang/locallang_mod_file_list.xlf

index 23d48c9..a59922f 100644 (file)
@@ -169,6 +169,16 @@ $TYPO3_CONF_VARS = array(
                'belogErrorReporting' => E_ALL ^ E_NOTICE,      // Integer: Configures which PHP errors should be logged to the "syslog" table (extension: belog). If set to "0" no PHP errors are logged to the sys_log table. Default is "E_ALL ^ E_NOTICE" (6135).
                'locallangXMLOverride' => array(),                              // For extension/overriding of the arrays in 'locallang' files in frontend and backend. See 'Inside TYPO3' for more information.
                'generateApacheHtaccess' => 1,                  // Boolean: TYPO3 can create <em>.htaccess</em> files which are used by Apache Webserver. They are useful for access protection or performance improvements. Currently <em>.htaccess</em> files in the following directories are created, if they do not exist: <ul><li>typo3temp/compressor/</li></ul>You want to disable this feature, if you are not running Apache or want to use own rulesets.
+               'fal' => array(
+                       'registeredDrivers' => array(
+                               'Local' => array(
+                                       'class' => 't3lib_file_Driver_LocalDriver',
+                                       'shortName' => 'Local',
+                                       'flexFormDS' => 'FILE:t3lib/file/Driver/Configuration/LocalDriverFlexForm.xml',
+                                       'label' => 'Local filesystem'
+                               )
+                       )
+               )
        ),
        'EXT' => array (        // Options related to the Extension Management
                'noEdit' => TRUE,                                               // Boolean: If set, the Extension Manager does NOT allow extension files to be edited! (Otherwise both local and global extensions can be edited.)
@@ -493,7 +503,7 @@ $TYPO3_CONF_VARS = array(
                        // This configuration below accepts everything in ftpspace and everything in webspace except php3,php4,php5 or php files
                'fileExtensions' => array (
                        'webspace' => array('allow'=>'', 'deny'=> PHP_EXTENSIONS_DEFAULT),
-                       'ftpspace' => array('allow'=>'*', 'deny'=>'')
+                       'ftpspace' => array('allow'=>'*', 'deny'=>'')   // @todo: remove this option in the future
                ),
                'customPermOptions' => array(),                 // Array with sets of custom permission options. Syntax is; 'key' => array('header' => 'header string, language splitted', 'items' => array('key' => array('label, language splitted', 'icon reference', 'Description text, language splitted'))). Keys cannot contain ":|," characters.
                'fileDenyPattern' => FILE_DENY_PATTERN_DEFAULT ,        // A perl-compatible regular expression (without delimiters!) that - if it matches a filename - will deny the file upload/rename or whatever in the webspace. For security reasons, files with multiple extensions have to be denied on an Apache environment with mod_alias, if the filename contains a valid php handler in an arbitary position. Also, ".htaccess" files have to be denied. Matching is done case-insensitive. Default value is stored in constant FILE_DENY_PATTERN_DEFAULT
index 4d71644..4ff4ba8 100644 (file)
@@ -1,6 +1,6 @@
 <?php
 // DO NOT CHANGE THIS FILE! It is automatically generated by extdeveval::buildAutoloadRegistry.
-// This file was generated on 2012-01-13 11:56
+// This file was generated on 2012-01-29 14:31
 
 
 $t3libClasses = array(
@@ -99,6 +99,58 @@ $t3libClasses = array(
        't3lib_extmgm' => PATH_t3lib . 'class.t3lib_extmgm.php',
        't3lib_extobjbase' => PATH_t3lib . 'class.t3lib_extobjbase.php',
        't3lib_exttables_postprocessinghook' => PATH_t3lib . 'interfaces/interface.t3lib_exttables_postprocessinghook.php',
+       't3lib_file_collection_abstractfilecollection' => PATH_t3lib . 'file/Collection/AbstractFileCollection.php',
+       't3lib_file_collection_folderbasedfilecollection' => PATH_t3lib . 'file/Collection/FolderBasedFileCollection.php',
+       't3lib_file_collection_staticfilecollection' => PATH_t3lib . 'file/Collection/StaticFileCollection.php',
+       't3lib_file_driver_abstractdriver' => PATH_t3lib . 'file/Driver/AbstractDriver.php',
+       't3lib_file_driver_driverregistry' => PATH_t3lib . 'file/Driver/DriverRegistry.php',
+       't3lib_file_driver_localdriver' => PATH_t3lib . 'file/Driver/LocalDriver.php',
+       't3lib_file_exception_abstractfileexception' => PATH_t3lib . 'file/Exception/AbstractFileException.php',
+       't3lib_file_exception_abstractfileoperationexception' => PATH_t3lib . 'file/Exception/AbstractFileOperationException.php',
+       't3lib_file_exception_existingtargetfilenameexception' => PATH_t3lib . 'file/Exception/ExistingTargetFileNameException.php',
+       't3lib_file_exception_existingtargetfolderexception' => PATH_t3lib . 'file/Exception/ExistingTargetFolderException.php',
+       't3lib_file_exception_fileoperationerrorexception' => PATH_t3lib . 'file/Exception/FileOperationErrorException.php',
+       't3lib_file_exception_filedoesnotexistexception' => PATH_t3lib . 'file/Exception/FileDoesNotExistException.php',
+       't3lib_file_exception_folderdoesnotexistexception' => PATH_t3lib . 'file/Exception/FolderDoesNotExistException.php',
+       't3lib_file_exception_illegalfileextensionexception' => PATH_t3lib . 'file/Exception/IllegalFileExtensionException.php',
+       't3lib_file_exception_insufficientfileaccesspermissionsexception' => PATH_t3lib . 'file/Exception/InsufficientFileAccessPermissionsException.php',
+       't3lib_file_exception_insufficientfilereadpermissionsexception' => PATH_t3lib . 'file/Exception/InsufficientFileReadPermissionsException.php',
+       't3lib_file_exception_insufficientfilewritepermissionsexception' => PATH_t3lib . 'file/Exception/InsufficientFileWritePermissionsException.php',
+       't3lib_file_exception_insufficientfolderaccesspermissionsexception' => PATH_t3lib . 'file/Exception/InsufficientFolderAccessPermissionsException.php',
+       't3lib_file_exception_insufficientfolderreadpermissionsexception' => PATH_t3lib . 'file/Exception/InsufficientFolderReadPermissionsException.php',
+       't3lib_file_exception_insufficientfolderwritepermissionsexception' => PATH_t3lib . 'file/Exception/InsufficientFolderWritePermissionsException.php',
+       't3lib_file_exception_insufficientuserpermissionsexception' => PATH_t3lib . 'file/Exception/InsufficientUserPermissionsException.php',
+       't3lib_file_exception_invalidfileexception' => PATH_t3lib . 'file/Exception/InvalidFileException.php',
+       't3lib_file_exception_invalidfilenameexception' => PATH_t3lib . 'file/Exception/InvalidFileNameException.php',
+       't3lib_file_exception_invalidfolderexception' => PATH_t3lib . 'file/Exception/InvalidFolderException.php',
+       't3lib_file_exception_invalidpathexception' => PATH_t3lib . 'file/Exception/InvalidPathException.php',
+       't3lib_file_exception_invalidtargetfolderexception' => PATH_t3lib . 'file/Exception/InvalidTargetFolderException.php',
+       't3lib_file_exception_notinmountpointexception' => PATH_t3lib . 'file/Exception/NotInMountPointException.php',
+       't3lib_file_exception_uploadexception' => PATH_t3lib . 'file/Exception/UploadException.php',
+       't3lib_file_exception_uploadsizeexception' => PATH_t3lib . 'file/Exception/UploadSizeException.php',
+       't3lib_file_abstractfile' => PATH_t3lib . 'file/AbstractFile.php',
+       't3lib_file_factory' => PATH_t3lib . 'file/Factory.php',
+       't3lib_file_file' => PATH_t3lib . 'file/File.php',
+       't3lib_file_fileinterface' => PATH_t3lib . 'file/FileInterface.php',
+       't3lib_file_filereference' => PATH_t3lib . 'file/FileReference.php',
+       't3lib_file_folder' => PATH_t3lib . 'file/Folder.php',
+       't3lib_file_mimetype' => PATH_t3lib . 'file/MimeType.php',
+       't3lib_file_processedfile' => PATH_t3lib . 'file/ProcessedFile.php',
+       't3lib_file_repository_abstractrepository' => PATH_t3lib . 'file/Repository/AbstractRepository.php',
+       't3lib_file_repository_filecollectionrepository' => PATH_t3lib . 'file/Repository/FileCollectionRepository.php',
+       't3lib_file_repository_filerepository' => PATH_t3lib . 'file/Repository/FileRepository.php',
+       't3lib_file_repository_processedfilerepository' => PATH_t3lib . 'file/Repository/ProcessedFileRepository.php',
+       't3lib_file_repository_storagerepository' => PATH_t3lib . 'file/Repository/StorageRepository.php',
+       't3lib_file_resourceinterface' => PATH_t3lib . 'file/ResourceInterface.php',
+       't3lib_file_service_backwardscompatibility_tslibcontentadapterservice' => PATH_t3lib . 'file/Service/BackwardsCompatibility/TslibContentAdapterService.php',
+       't3lib_file_service_fileprocessingservice' => PATH_t3lib . 'file/Service/FileProcessingService.php',
+       't3lib_file_service_imageprocessingservice' => PATH_t3lib . 'file/Service/ImageProcessingService.php',
+       't3lib_file_service_indexerservice' => PATH_t3lib . 'file/Service/IndexerService.php',
+       't3lib_file_service_publishing_abstractpublisher' => PATH_t3lib . 'file/Service/Publishing/AbstractPublisher.php',
+       't3lib_file_service_publishing_filesystempublisher' => PATH_t3lib . 'file/Service/Publishing/FilesystemPublisher.php',
+       't3lib_file_service_publishing_publisher' => PATH_t3lib . 'interfaces/file/Service/Publishing/Publisher.php',
+       't3lib_file_service_userfilemountservice' => PATH_t3lib . 'file/Service/UserfilemountService.php',
+       't3lib_file_storage' => PATH_t3lib . 'file/Storage.php',
        't3lib_flashmessage' => PATH_t3lib . 'class.t3lib_flashmessage.php',
        't3lib_flashmessagequeue' => PATH_t3lib . 'class.t3lib_flashmessagequeue.php',
        't3lib_flexformtools' => PATH_t3lib . 'class.t3lib_flexformtools.php',
diff --git a/t3lib/file/AbstractFile.php b/t3lib/file/AbstractFile.php
new file mode 100644 (file)
index 0000000..f3a439d
--- /dev/null
@@ -0,0 +1,555 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Ingmar Schlecht <ingmar@typo3.org>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *  A copy is found in the textfile GPL.txt and important notices to the license
+ *  from the author is found in LICENSE.txt distributed with these scripts.
+ *
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * Abstract file representation in the file abstraction layer.
+ *
+ * @author Ingmar Schlecht <ingmar@typo3.org>
+ * @package  TYPO3
+ * @subpackage  t3lib
+ */
+abstract class t3lib_file_AbstractFile implements t3lib_file_FileInterface {
+
+       /**
+        * Various file properties
+        *
+        * Note that all properties, which only the persisted (indexed) files have are stored in this
+        * overall properties array only. The only properties which really exist as object properties of
+        * the file object are the storage, the identifier, the fileName and the indexing status.
+        *
+        * @var array
+        */
+       protected $properties;
+
+       /**
+        * The storage this file is located in
+        *
+        * @var t3lib_file_Storage
+        */
+       protected $storage = NULL;
+
+       /**
+        * The identifier of this file to identify it on the storage.
+        * On some drivers, this is the path to the file, but drivers could also just
+        * provide any other unique identifier for this file on the specific storage.
+        *
+        * @var string
+        */
+       protected $identifier;
+
+       /**
+        * The file name of this file
+        *
+        * @var string
+        */
+       protected $name;
+
+       /**
+        * If set to true, this file is regarded as being deleted.
+        *
+        * @var boolean
+        */
+       protected $deleted = FALSE;
+
+
+       /**
+        * any other file
+        */
+       const FILETYPE_UNKNOWN = 0;
+
+       /**
+        * Any kind of text
+        */
+       const FILETYPE_TEXT = 1;
+
+       /**
+        * Any kind of image
+        */
+       const FILETYPE_IMAGE = 2;
+
+       /**
+        * Any kind of audio file
+        */
+       const FILETYPE_AUDIO = 3;
+
+       /**
+        * Any kind of video
+        */
+       const FILETYPE_VIDEO = 4;
+
+       /**
+        * Any kind of software, often known as "application"
+        */
+       const FILETYPE_SOFTWARE = 5;
+
+       /*******************************
+        * VARIOUS FILE PROPERTY GETTERS
+        *******************************
+
+       /**
+        * Returns true if the given property key exists for this file.
+        *
+        * @param string $key
+        * @return boolean
+        */
+       public function hasProperty($key) {
+               return isset($this->properties[$key]);
+       }
+
+       /**
+        * Returns a property value
+        *
+        * @param string $key
+        * @return mixed Property value
+        */
+       public function getProperty($key) {
+               return $this->properties[$key];
+       }
+
+       /**
+        * Returns the properties of this object.
+        *
+        * @return array
+        */
+       public function getProperties() {
+               return $this->properties;
+       }
+
+       /**
+        * Returns the identifier of this file
+        *
+        * @return string
+        */
+       public function getIdentifier() {
+               return $this->identifier;
+       }
+
+
+       /**
+        * Returns the name of this file
+        *
+        * @return string
+        */
+       public function getName() {
+                       // Do not check if file has been deleted because we might need the name for undeleting it.
+               return $this->name;
+       }
+
+
+       /**
+        * Returns the size of this file
+        *
+        * @return integer
+        */
+       public function getSize() {
+               if ($this->deleted) {
+                       throw new RuntimeException('File has been deleted.', 1329821480);
+               }
+
+               return $this->properties['size'];
+       }
+
+       /**
+        * Returns the uid of this file
+        *
+        * @return integer
+        */
+       public function getUid() {
+               return $this->getProperty('uid');
+       }
+
+       /**
+        * Returns the Sha1 of this file
+        *
+        * @return string
+        */
+       public function getSha1() {
+               if ($this->deleted) {
+                       throw new RuntimeException('File has been deleted.', 1329821481);
+               }
+
+               return $this->getStorage()->hashFile($this, 'sha1');
+       }
+
+       /**
+        * Returns the creation time of the file as Unix timestamp
+        *
+        * @return integer
+        */
+       public function getCreationTime() {
+               if ($this->deleted) {
+                       throw new RuntimeException('File has been deleted.', 1329821487);
+               }
+
+               return $this->getProperty('creation_date');
+       }
+
+       /**
+        * Returns the date (as UNIX timestamp) the file was last modified.
+        *
+        * @return integer
+        */
+       public function getModificationTime() {
+               if ($this->deleted) {
+                       throw new RuntimeException('File has been deleted.', 1329821488);
+               }
+
+               return $this->getProperty('modification_date');
+       }
+
+       /**
+        * Get the extension of this file
+        *
+        * @return string The file extension
+        */
+       public function getExtension() {
+               return pathinfo($this->getName(), PATHINFO_EXTENSION);
+       }
+
+       /**
+        * Get the MIME type of this file
+        *
+        * @return array file information
+        */
+       public function getMimeType() {
+               // TODO this will be slow - use the cached version if possible
+               $stat = $this->getStorage()->getFileInfo($this);
+               return $stat['mimetype'];
+       }
+
+       /**
+        * Returns the fileType of this file
+        * basically there are only five main "file types"
+        * "audio"
+        * "image"
+        * "software"
+        * "text"
+        * "video"
+        * "other"
+        * see the constants in this class
+        *
+        * @return integer $fileType
+        */
+       public function getType() {
+                       // this basically extracts the mimetype and guess the filetype based on the first part of the mimetype
+                       // works for 99% of all cases, and we don't need to make an SQL statement like EXT:media does currently
+               if (!$this->properties['type']) {
+                       $mimeType = $this->getMimeType();
+                       list($fileType) = explode('/', $mimeType);
+
+                       switch (strtolower($fileType)) {
+                               case 'text':
+                                       $this->properties['type'] = self::FILETYPE_TEXT;
+                               break;
+                               case 'image':
+                                       $this->properties['type'] = self::FILETYPE_IMAGE;
+                               break;
+                               case 'audio':
+                                       $this->properties['type'] = self::FILETYPE_AUDIO;
+                               break;
+                               case 'video':
+                                       $this->properties['type'] = self::FILETYPE_VIDEO;
+                               break;
+                               case 'application':
+                               case 'software':
+                                       $this->properties['type'] = self::FILETYPE_SOFTWARE;
+                               break;
+                               default:
+                                       $this->properties['type'] = self::FILETYPE_UNKNOWN;
+                               break;
+                       }
+               }
+
+               return $this->properties['type'];
+       }
+
+
+       /******************
+        * CONTENTS RELATED
+        ******************/
+
+       /**
+        * Get the contents of this file
+        *
+        * @return string File contents
+        */
+       public function getContents() {
+               if ($this->deleted) {
+                       throw new RuntimeException('File has been deleted.', 1329821479);
+               }
+
+               return $this->getStorage()->getFileContents($this);
+       }
+
+       /**
+        * Replace the current file contents with the given string
+        *
+        * @param string $contents The contents to write to the file.
+        * @return t3lib_file_File The file object (allows chaining).
+        */
+       public function setContents($contents) {
+               if ($this->deleted) {
+                       throw new RuntimeException('File has been deleted.', 1329821478);
+               }
+
+               $this->getStorage()->setFileContents($this, $contents);
+               return $this;
+       }
+
+
+
+
+
+       /****************************************
+        * STORAGE AND MANAGEMENT RELATED METHDOS
+        ****************************************/
+
+
+       /**
+        * Get the storage this file is located in
+        *
+        * @return t3lib_file_Storage
+        */
+       public function getStorage() {
+               if ($this->storage === NULL) {
+                       $this->loadStorage();
+               }
+
+               return $this->storage;
+       }
+
+
+       protected function loadStorage() {
+               $storageUid = $this->getProperty('storage');
+               if (t3lib_utility_Math::canBeInterpretedAsInteger($storageUid)) {
+
+                       /** @var $fileFactory t3lib_file_Factory */
+                       $fileFactory = t3lib_div::makeInstance('t3lib_file_Factory');
+                       $this->storage = $fileFactory->getStorageObject($storageUid);
+               }
+       }
+
+       /**
+        * Checks if this file exists. This should normally always return TRUE; it might only return FALSE when
+        * this object has been created from an index record without checking for.
+        *
+        * @return boolean TRUE if this file physically exists
+        */
+       public function exists() {
+               if ($this->deleted) {
+                       return FALSE;
+               }
+
+               return $this->storage->hasFile($this->getIdentifier());
+       }
+
+
+       /**
+        * Sets the storage this file is located in. This is only meant for t3lib/file/-internal usage; don't use it to move files.
+        *
+        * @internal Should only be used by other parts of the File API (e.g. drivers after moving a file)
+        * @param integer|t3lib_file_Storage $storage
+        * @return t3lib_file_File
+        */
+       public function setStorage($storage) {
+                       // Do not check for deleted file here as we might need this method for the recycler later on
+               if (is_object($storage) && $storage instanceof t3lib_file_Storage) {
+                       $this->storage = $storage;
+                       $this->properties['storage'] = $storage->getUid();
+               } else {
+                       $this->properties['storage'] = $storage;
+                       $this->storage = NULL;
+               }
+               return $this;
+       }
+
+       /**
+        * Set the identifier of this file
+        *
+        * @internal Should only be used by other parts of the File API (e.g. drivers after moving a file)
+        * @param string $identifier
+        * @return string
+        */
+       public function setIdentifier($identifier) {
+               $this->identifier = $identifier;
+       }
+
+       /**
+        * Returns a combined identifier of this file, i.e. the storage UID and the folder identifier
+        * separated by a colon ":".
+        *
+        * @return string Combined storage and file identifier, e.g. StorageUID:path/and/fileName.png
+        */
+       public function getCombinedIdentifier() {
+               if (is_array($this->properties) && t3lib_utility_Math::canBeInterpretedAsInteger($this->properties['storage'])) {
+                       $combinedIdentifier = $this->properties['storage'] . ':' . $this->getIdentifier();
+               } else {
+                       $combinedIdentifier = $this->getStorage()->getUid() . ':' . $this->getIdentifier();
+               }
+
+               return $combinedIdentifier;
+       }
+
+       /**
+        * Deletes this file from its storage. This also means that this object becomes useless.
+        *
+        * @return bool TRUE if deletion succeeded
+        * TODO mark file internally as deleted, throw exceptions on all method calls afterwards
+        * TODO undelete mechanism?
+        */
+       public function delete() {
+                       // The storage will mark this file as deleted
+               return $this->getStorage()->deleteFile($this);
+       }
+
+       /**
+        * Marks this file as deleted. This should only be used inside the File Abstraction Layer, as it is a low-level API method.
+        *
+        * @return void
+        */
+       public function setDeleted() {
+               $this->deleted = TRUE;
+       }
+
+       /**
+        * Returns TRUE if this file has been deleted
+        *
+        * @return boolean
+        */
+       public function isDeleted() {
+               return $this->deleted;
+       }
+
+       /**
+        * Renames this file.
+        *
+        * @param string $newName The new file name
+        * @return t3lib_file_File
+        */
+       public function rename($newName) {
+               if ($this->deleted) {
+                       throw new RuntimeException('File has been deleted.', 1329821482);
+               }
+
+               return $this->getStorage()->renameFile($this, $newName);
+       }
+
+       /**
+        * Copies this file into a target folder
+        *
+        * @param t3lib_file_Folder $targetFolder Folder to copy file into.
+        * @param string $targetFileName an optional destination fileName
+        * @param string $conflictMode overrideExistingFile", "renameNewFile", "cancel"
+        *
+        * @return t3lib_file_File The new (copied) file.
+        */
+       public function copyTo(t3lib_file_Folder $targetFolder, $targetFileName = NULL, $conflictMode = 'renameNewFile') {
+               if ($this->deleted) {
+                       throw new RuntimeException('File has been deleted.', 1329821483);
+               }
+
+               return $targetFolder->getStorage()->copyFile($this, $targetFolder, $targetFileName, $conflictMode);
+       }
+
+       /**
+        * Moves the file into the target folder
+        *
+        * @param t3lib_file_Folder $targetFolder Folder to move file into.
+        * @param string $targetFileName an optional destination fileName
+        * @param string $conflictMode overrideExistingFile", "renameNewFile", "cancel"
+        *
+        * @return t3lib_file_File This file object, with updated properties.
+        */
+       public function moveTo(t3lib_file_Folder $targetFolder, $targetFileName = NULL, $conflictMode = 'renameNewFile') {
+               if ($this->deleted) {
+                       throw new RuntimeException('File has been deleted.', 1329821484);
+               }
+
+               return $targetFolder->getStorage()->moveFile($this, $targetFolder, $targetFileName, $conflictMode);
+       }
+
+
+       /*****************
+        * SPECIAL METHODS
+        *****************/
+
+       /**
+        * Returns a publicly accessible URL for this file
+        *
+        * WARNING: Access to the file may be restricted by further means, e.g. some web-based authentication. You have to take care of this
+        * yourself.
+        *
+        * @param bool  $relativeToCurrentScript   Determines whether the URL returned should be relative to the current script, in case it is relative at all (only for the LocalDriver)
+        *
+        * @return string
+        */
+       public function getPublicUrl($relativeToCurrentScript = FALSE) {
+               if ($this->deleted) {
+                       throw new RuntimeException('File has been deleted.', 1329821485);
+               }
+
+               return $this->getStorage()->getPublicUrlForFile($this, $relativeToCurrentScript);
+       }
+
+       /**
+        * Returns a path to a local version of this file to process it locally (e.g. with some system tool).
+        * If the file is normally located on a remote storages, this creates a local copy.
+        * If the file is already on the local system, this only makes a new copy if $writable is set to TRUE.
+        *
+        * @param boolean $writable Set this to FALSE if you only want to do read operations on the file.
+        * @return string
+        */
+       public function getForLocalProcessing($writable = TRUE) {
+               if ($this->deleted) {
+                       throw new RuntimeException('File has been deleted.', 1329821486);
+               }
+
+               return $this->getStorage()->getFileForLocalProcessing($this, $writable);
+       }
+
+
+       /***********************
+        * INDEX RELATED METHODS
+        ***********************/
+
+       /**
+        * Updates properties of this object.
+        * This method is used to reconstitute settings from the
+        * database into this object after being intantiated.
+        *
+        * @param array $properties
+        */
+       abstract public function updateProperties(array $properties);
+}
+
+
+if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/file/AbstractFile.php'])) {
+       include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/file/AbstractFile.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/file/Collection/AbstractFileCollection.php b/t3lib/file/Collection/AbstractFileCollection.php
new file mode 100644 (file)
index 0000000..ccb1c5a
--- /dev/null
@@ -0,0 +1,261 @@
+<?php
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2011 Steffen Ritter <steffen.ritter@typo3.org>
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ * A copy is found in the textfile GPL.txt and important notices to the license
+ * from the author is found in LICENSE.txt distributed with these scripts.
+ *
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * Abstract collection.
+ *
+ * @author Steffen Ritter <steffen.ritter@typo3.org>
+ * @package TYPO3
+ * @subpackage t3lib
+ */
+abstract class t3lib_file_Collection_AbstractFileCollection extends t3lib_collection_AbstractRecordCollection  {
+
+       /**
+        * The table name collections are stored to
+        *
+        * @var string
+        */
+       protected static $storageTableName = 'sys_file_collection';
+
+
+       /**
+        * The type of file collection
+        * (see t3lib_collection_RecordCollectionRepository::TYPE constants)
+        *
+        * @var string
+        */
+       protected static $type;
+
+
+       /**
+        * The name of the field items are handled with
+        * (ususally either criteria, items or folder)
+        *
+        * @var string
+        */
+       protected static $itemsCriteriaField;
+
+
+       /**
+        * Field contents of $itemsCriteriaField. Defines which the items or search criteria for the items
+        * depending on the type (see self::$type above) of this file collection.
+        *
+        * @var mixed
+        */
+       protected $itemsCriteria;
+
+       /**
+        * Name of the table records of this collection are stored in
+        *
+        * @var string
+        */
+       protected $itemTableName = 'sys_file';
+
+       /**
+        * Sets the description.
+        *
+        * @param string $description
+        */
+       public function setDescription($description) {
+               $this->description = $description;
+       }
+
+       /**
+        * Sets the title.
+        *
+        * @param string $title
+        */
+       public function setTitle($title) {
+               $this->title = $title;
+       }
+
+       /**
+        * Return the key of the current element
+        *
+        * @return string
+        */
+       public function key() {
+               /** @var $currentRecord t3lib_file_File */
+               $currentRecord = $this->storage->current();
+               return $currentRecord->getIdentifier();
+       }
+
+       /**
+        * Generates comma-separated list of entry uids for usage in TCEmain
+        *
+        * @param boolean $includeTableName
+        * @return string
+        */
+       protected function getItemUidList($includeTableName = FALSE) {
+               $list = array();
+
+               /** @var $entry t3lib_file_File */
+               foreach ($this->storage as $entry) {
+                       $list[] = $this->getItemTableName() . '_' . $entry->getUid();
+               }
+
+               return implode(',', $list);
+       }
+
+       /**
+        * Returns an array of the persistable properties and contents
+        * which are processable by TCEmain.
+        *
+        * @return array
+        */
+       protected function getPersistableDataArray() {
+               return array(
+                       'title' => $this->getTitle(),
+                       'type' => static::$type,
+                       'description' => $this->getDescription(),
+                       static::$itemsCriteriaField => $this->getItemsCriteria()
+               );
+       }
+
+       /**
+        * Similar to method in t3lib_collection_AbstractRecordCollection,
+        * but without 'table_name' => $this->getItemTableName()
+        *
+        * @return array
+        */
+       public function toArray() {
+               $itemArray = array();
+
+               /** @var $item t3lib_file_File */
+               foreach ($this->storage as $item) {
+                       $itemArray[] = $item->toArray();
+               }
+
+               return array(
+                       'uid' => $this->getIdentifier(),
+                       'title' => $this->getTitle(),
+                       'description' => $this->getDescription(),
+                       'items' => $itemArray
+               );
+       }
+
+       /**
+        * Gets the current available items.
+        *
+        * @return array
+        */
+       public function getItems() {
+               $itemArray = array();
+
+               /** @var $item t3lib_file_File */
+               foreach ($this->storage as $item) {
+                       $itemArray[] = $item;
+               }
+
+               return $itemArray;
+       }
+
+       /**
+        * Similar to method in t3lib_collection_AbstractRecordCollection,
+        * but without $this->itemTableName= $array['table_name'],
+        * but with $this->storageItemsFieldContent = $array[self::$storageItemsField];
+        *
+        * @param array $array
+        */
+       public function fromArray(array $array) {
+               $this->uid = $array['uid'];
+               $this->title = $array['title'];
+               $this->description = $array['description'];
+               $this->itemsCriteria = $array[static::$itemsCriteriaField];
+       }
+
+       /**
+        * Gets ths items criteria.
+        *
+        * @return mixed
+        */
+       public function getItemsCriteria() {
+               return $this->itemsCriteria;
+       }
+
+       /**
+        * Sets the items criteria.
+        *
+        * @param mixed $itemsCriteria
+        */
+       public function setItemsCriteria($itemsCriteria) {
+               $this->itemsCriteria = $itemsCriteria;
+       }
+
+       /**
+        * Adds a file to this collection.
+        *
+        * @param t3lib_file_FileInterface $data
+        */
+       public function add(t3lib_file_FileInterface $data) {
+               $this->storage->push($data);
+       }
+
+       /**
+        * Adds all files of another collection to the corrent one.
+        *
+        * @param t3lib_collection_Collection $other
+        */
+       public function addAll(t3lib_collection_Collection $other) {
+               /** @var $value t3lib_file_File */
+               foreach ($other as $value) {
+                       $this->add($value);
+               }
+       }
+
+       /**
+        * Removes a file from this collection.
+        *
+        * @param t3lib_file_File $file
+        */
+       public function remove(t3lib_file_File $file) {
+               $offset = 0;
+
+               /** @var $value t3lib_file_File */
+               foreach ($this->storage as $value) {
+                       if ($value === $file) {
+                               break;
+                       }
+                       $offset++;
+               }
+
+               $this->storage->offsetUnset($offset);
+       }
+
+       /**
+        * Removes all elements of the current collection.
+        */
+       public function removeAll() {
+               $this->storage = new SplDoublyLinkedList();
+       }
+}
+
+if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/file/Collection/AbstractFileCollection.php'])) {
+       include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/file/Collection/AbstractFileCollection.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/file/Collection/FolderBasedFileCollection.php b/t3lib/file/Collection/FolderBasedFileCollection.php
new file mode 100644 (file)
index 0000000..3d27322
--- /dev/null
@@ -0,0 +1,132 @@
+<?php
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2011 Andreas Wolf <andreas.wolf@ikt-werk.de>
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ * A copy is found in the textfile GPL.txt and important notices to the license
+ * from the author is found in LICENSE.txt distributed with these scripts.
+ *
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * A collection containing a a set files to be represented as a (virtual) folder.
+ * This collection is persisted to the database with the accordant folder reference.
+ *
+ * @author Andreas Wolf <andreas.wolf@ikt-werk.de>
+ * @package TYPO3
+ * @subpackage t3lib
+ */
+class t3lib_file_Collection_FolderBasedFileCollection extends t3lib_file_Collection_AbstractFileCollection {
+       /**
+        * @var string
+        */
+       protected static $storageTableName = 'sys_file_collection';
+
+       /**
+        * @var string
+        */
+       protected static $type = 'folder';
+
+       /**
+        * @var string
+        */
+       protected static $itemsCriteriaField = 'folder';
+
+       /**
+        * The folder
+        *
+        * @var t3lib_file_Folder
+        */
+       protected $folder;
+
+       /**
+        * Populates the content-entries of the storage
+        *
+        * Queries the underlying storage for entries of the collection
+        * and adds them to the collection data.
+        *
+        * If the content entries of the storage had not been loaded on creation
+        * ($fillItems = false) this function is to be used for loading the contents
+        * afterwards.
+        *
+        * @return void
+        */
+       public function loadContents() {
+               $entries = $this->folder->getFiles();
+               foreach ($entries as $entry) {
+                       $this->add($entry);
+               }
+       }
+
+       /**
+        * Gets the items criteria.
+        *
+        * @return string
+        */
+       public function getItemsCriteria() {
+               return $this->folder->getCombinedIdentifier();
+       }
+
+       /**
+        * Returns an array of the persistable properties and contents
+        * which are processable by TCEmain.
+        *
+        * @return array
+        */
+       protected function getPersistableDataArray() {
+               return array(
+                       'title' => $this->getTitle(),
+                       'type' => self::$type,
+                       'description' => $this->getDescription(),
+                       'folder' => $this->folder->getIdentifier(),
+                       'storage' => $this->folder->getStorage()->getUid()
+               );
+       }
+
+       /**
+        * Similar to method in t3lib_collection_AbstractRecordCollection,
+        * but without $this->itemTableName= $array['table_name'],
+        * but with $this->storageItemsFieldContent = $array[self::$storageItemsField];
+        *
+        * @param array $array
+        */
+       public function fromArray(array $array) {
+               $this->uid                      = $array['uid'];
+               $this->title            = $array['title'];
+               $this->description      = $array['description'];
+
+               if (!empty($array['folder']) && !empty($array['storage'])) {
+                       /**  @var $storageRepository t3lib_file_Repository_StorageRepository */
+                       $storageRepository = t3lib_div::makeInstance('t3lib_file_Repository_StorageRepository');
+                       /**  @var $storage t3lib_file_Storage */
+                       $storage = $storageRepository->findByUid($array['storage']);
+
+                       if ($storage) {
+                               $this->folder = $storage->getFolder($array['folder']);
+                       }
+               }
+       }
+}
+
+if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/file/Collection/FolderBasedFileCollection.php'])) {
+       include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/file/Collection/FolderBasedFileCollection.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/file/Collection/StaticFileCollection.php b/t3lib/file/Collection/StaticFileCollection.php
new file mode 100644 (file)
index 0000000..fd1284d
--- /dev/null
@@ -0,0 +1,81 @@
+<?php
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2011 Andreas Wolf <andreas.wolf@ikt-werk.de>
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ * A copy is found in the textfile GPL.txt and important notices to the license
+ * from the author is found in LICENSE.txt distributed with these scripts.
+ *
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * A collection containing a static set of files. This collection is persisted to the database with references to all
+ * files it contains.
+ *
+ * @author Andreas Wolf <andreas.wolf@ikt-werk.de>
+ * @package TYPO3
+ * @subpackage t3lib
+ */
+class t3lib_file_Collection_StaticFileCollection extends t3lib_file_Collection_AbstractFileCollection {
+       /**
+        * @var string
+        */
+       protected static $type = 'static';
+
+       /**
+        * @var string
+        */
+       protected static $itemsCriteriaField = 'items';
+
+       /**
+        * @var string
+        */
+       protected $itemTableName = 'sys_file_reference';
+
+       /**
+        * Populates the content-entries of the storage
+        *
+        * Queries the underlying storage for entries of the collection
+        * and adds them to the collection data.
+        *
+        * If the content entries of the storage had not been loaded on creation
+        * ($fillItems = false) this function is to be used for loading the contents
+        * afterwards.
+        *
+        * @return void
+        */
+       public function loadContents() {
+               /**
+                * @var t3lib_file_Repository_FileRepository $fileRepository
+                */
+               $fileRepository = t3lib_div::makeInstance('t3lib_file_Repository_FileRepository');
+               $fileReferences = $fileRepository->findByRelation('sys_file_collection', 'files', $this->getIdentifier());
+
+               foreach ($fileReferences as $file) {
+                       $this->add($file);
+               }
+       }
+}
+
+if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/file/Collection/StaticFileCollection.php'])) {
+       include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/file/Collection/StaticFileCollection.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/file/Driver/AbstractDriver.php b/t3lib/file/Driver/AbstractDriver.php
new file mode 100644 (file)
index 0000000..faf89cb
--- /dev/null
@@ -0,0 +1,669 @@
+<?php
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2011 Ingmar Schlecht <ingmar.schlecht@typo3.org>
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ * A copy is found in the textfile GPL.txt and important notices to the license
+ * from the author is found in LICENSE.txt distributed with these scripts.
+ *
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * An abstract implementation of a storage driver.
+ *
+ * @author Ingmar Schlecht <ingmar.schlecht@typo3.org>
+ * @author  Andreas Wolf <andreas.wolf@ikt-werk.de>
+ * @package    TYPO3
+ * @subpackage t3lib
+ */
+abstract class t3lib_file_Driver_AbstractDriver {
+
+       /**
+        * The mount object this driver instance belongs to
+        *
+        * @var t3lib_file_Storage
+        */
+       protected $storage;
+
+       /**
+        * A list of all supported hash algorithms, written all lower case and without any dashes etc. (e.g. sha1 instead of SHA-1)
+        * Be sure to set this in inherited classes!
+        *
+        * @var array
+        */
+       protected $supportedHashAlgorithms = array();
+
+       /**
+        * The storage folder that forms the root of this FS tree
+        *
+        * @var t3lib_file_Folder
+        */
+       protected $rootLevelFolder;
+
+       /**
+        * The default folder new files should be put into.
+        *
+        * @var t3lib_file_Folder
+        */
+       protected $defaultLevelFolder;
+
+       /**
+        * The configuration of this driver
+        *
+        * @var array
+        */
+       protected $configuration = array();
+
+       /**
+        * The callback method to handle the files when listing folder contents
+        *
+        * @var string
+        */
+       protected $fileListCallbackMethod = 'getFileList_itemCallback';
+
+       /**
+        * The callback method to handle the folders when listing folder contents
+        *
+        * @var string
+        */
+       protected $folderListCallbackMethod = 'getFolderList_itemCallback';
+
+       /**
+        * Creates this object.
+        *
+        * @param array $configuration
+        */
+       public function __construct(array $configuration = array()) {
+               $this->configuration = $configuration;
+               $this->processConfiguration();
+       }
+
+       /**
+        * Initializes this object. This is called by the storage after the driver has been attached.
+        *
+        * @return void
+        */
+       abstract public function initialize();
+
+       /**
+        * Checks a fileName for validity. This could be overriden in concrete drivers if they have different file naming
+        * rules.
+        *
+        * @param string $fileName
+        * @return boolean TRUE if file name is valid
+        */
+       public function isValidFilename($fileName) {
+               if (strpos($fileName, '/') !== FALSE) {
+                       return FALSE;
+               }
+               if (!preg_match('/^[[:alnum:][:blank:]\.-_]*$/iu', $fileName)) {
+                       return FALSE;
+               }
+
+               return TRUE;
+       }
+
+       /**
+        * Sets the storage object that works with this driver
+        *
+        * @param t3lib_file_Storage $storage
+        * @return t3lib_file_Driver_AbstractDriver
+        */
+       public function setStorage(t3lib_file_Storage $storage) {
+               $this->storage = $storage;
+               return $this;
+       }
+
+       /**
+        * Checks if a configuration is valid for this driver.
+        * Throws an exception if a configuration will not work.
+        *
+        * @abstract
+        * @param array $configuration
+        * @return void
+        */
+       abstract public static function verifyConfiguration(array $configuration);
+
+       /**
+        * processes the configuration, should be overridden by subclasses
+        * but we do this because PHPUnit cannot work if this is an abstract configuration
+        *
+        * @return void
+        */
+       protected function processConfiguration() {
+               throw new RuntimeException(
+                       'Method processConfiguration() needs to be implemented for the specific driver',
+                       1328899740
+               );
+       }
+
+       /**
+        * Generic handler method for directory listings - gluing together the listing items is done
+        *
+        * @param string $path
+        * @param integer $start
+        * @param integer $numberOfItems
+        * @param string $itemHandlerMethod
+        * @param bool $excludeHiddenItems
+        * @param array $itemRows
+        * @return array
+        */
+       protected function getDirectoryItemList($path, $start, $numberOfItems, $itemHandlerMethod, $excludeHiddenItems, $itemRows = array()) {
+               // This is not abstract because PHPUnit cannot mock abstract protected/private methods
+       }
+
+       /*******************
+        * CAPABILITIES
+        *******************/
+
+       /**
+        * The capabilities of this driver. See CAPABILITY_* constants for possible values
+        *
+        * @var integer
+        */
+       protected $capabilities = 0;
+
+       /**
+        * Capability for being browsable by (backend) users
+        */
+       const CAPABILITY_BROWSABLE = 1;
+
+       /**
+        * Capability for publicly accessible drivers (= accessible from the web)
+        */
+       const CAPABILITY_PUBLIC = 2;
+
+       /**
+        * Capability for writable drivers
+        */
+       const CAPABILITY_WRITABLE = 4;
+
+       /**
+        * Returns the capabilities of this driver.
+        *
+        * @return integer
+        * @see CAPABILITY_* constants
+        */
+       public function getCapabilities() {
+               return $this->capabilities;
+       }
+
+       /**
+        * Returns TRUE if this driver has the given capability.
+        *
+        * @param int $capability A capability, as defined in a CAPABILITY_* constant
+        * @return boolean
+        */
+       public function hasCapability($capability) {
+               return $this->capabilities && $capability;
+       }
+
+       /*******************
+        * FILE FUNCTIONS
+        *******************/
+
+       /**
+        * Returns a temporary path for a given file, including the file extension.
+        *
+        * @param t3lib_file_FileInterface $file
+        * @return string
+        */
+       protected function getTemporaryPathForFile(t3lib_file_FileInterface $file) {
+               return t3lib_div::tempnam('fal-tempfile-') . '.' . $file->getExtension();
+               // @todo: we need to remove the temporary file again
+       }
+
+       /**
+        * Returns the public URL to a file.
+        *
+        * @abstract
+        * @param t3lib_file_FileInterface $file
+        * @param bool  $relativeToCurrentScript    Determines whether the URL returned should be relative to the current script, in case it is relative at all (only for the LocalDriver)
+        * @return string
+        */
+       abstract public function getPublicUrl(t3lib_file_FileInterface $file, $relativeToCurrentScript = FALSE);
+
+       /**
+        * Returns a list of all hashing algorithms this Storage supports.
+        *
+        * @return array
+        */
+       public function getSupportedHashAlgorithms() {
+               return $this->supportedHashAlgorithms;
+       }
+
+       /**
+        * Creates a (cryptographic) hash for a file.
+        *
+        * @abstract
+        * @param t3lib_file_FileInterface $file
+        * @param string $hashAlgorithm The hash algorithm to use
+        * @return string
+        * TODO switch parameter order?
+        */
+       abstract public function hash(t3lib_file_FileInterface $file, $hashAlgorithm);
+
+       /**
+        * Creates a new file and returns the matching file object for it.
+        *
+        * @abstract
+        * @param string $fileName
+        * @param t3lib_file_Folder $parentFolder
+        * @return t3lib_file_File
+        */
+       abstract public function createFile($fileName, t3lib_file_Folder $parentFolder);
+
+       /**
+        * Returns the contents of a file. Beware that this requires to load the complete file into memory and also may
+        * require fetching the file from an external location. So this might be an expensive operation (both in terms of
+        * processing resources and money) for large files.
+        *
+        * @param t3lib_file_FileInterface $file
+        * @return string The file contents
+        */
+       abstract public function getFileContents(t3lib_file_FileInterface $file);
+
+       /**
+        * Sets the contents of a file to the specified value.
+        *
+        * @param t3lib_file_FileInterface $file
+        * @param string $contents
+        * @return integer The number of bytes written to the file
+        * @throws RuntimeException if the operation failed
+        */
+       abstract public function setFileContents(t3lib_file_FileInterface $file, $contents);
+
+       /**
+        * Adds a file from the local server hard disk to a given path in TYPO3s virtual file system.
+        *
+        * This assumes that the local file exists, so no further check is done here!
+        *
+        * @param string $localFilePath
+        * @param t3lib_file_Folder $targetFolder
+        * @param string $fileName The name to add the file under
+        * @param t3lib_file_AbstractFile $updateFileObject Optional file object to update (instead of creating a new object). With this parameter, this function can be used to "populate" a dummy file object with a real file underneath.
+        * @return t3lib_file_FileInterface
+        */
+       abstract public function addFile($localFilePath, t3lib_file_Folder $targetFolder, $fileName, t3lib_file_AbstractFile $updateFileObject = NULL);
+
+       /**
+        * Checks if a file exists.
+        *
+        * @abstract
+        * @param string $identifier
+        * @return boolean
+        */
+       abstract public function fileExists($identifier);
+
+       /**
+        * Checks if a file inside a storage folder exists.
+        *
+        * @abstract
+        * @param string $fileName
+        * @param t3lib_file_Folder $folder
+        * @return boolean
+        */
+       abstract public function fileExistsInFolder($fileName, t3lib_file_Folder $folder);
+
+       /**
+        * Returns a (local copy of) a file for processing it. When changing the file, you have to take care of replacing the
+        * current version yourself!
+        *
+        * @abstract
+        * @param t3lib_file_FileInterface $file
+        * @param bool $writable Set this to FALSE if you only need the file for read operations. This might speed up things, e.g. by using a cached local version. Never modify the file if you have set this flag!
+        * @return string The path to the file on the local disk
+        */
+       // TODO decide if this should return a file handle object
+       abstract public function getFileForLocalProcessing(t3lib_file_FileInterface $file, $writable = TRUE);
+
+       /**
+        * Returns the permissions of a file as an array (keys r, w) of boolean flags
+        *
+        * @abstract
+        * @param t3lib_file_FileInterface $file
+        * @return array
+        */
+       abstract public function getFilePermissions(t3lib_file_FileInterface $file);
+
+       /**
+        * Returns the permissions of a folder as an array (keys r, w) of boolean flags
+        *
+        * @abstract
+        * @param t3lib_file_Folder $folder
+        * @return array
+        */
+       abstract public function getFolderPermissions(t3lib_file_Folder $folder);
+
+       /**
+        * Renames a file
+        *
+        * @abstract
+        * @param t3lib_file_FileInterface $file
+        * @param string $newName
+        * @return string The new identifier of the file if the operation succeeds
+        * @throws RuntimeException if renaming the file failed
+        */
+       abstract public function renameFile(t3lib_file_FileInterface $file, $newName);
+
+       /**
+        * Replaces the contents (and file-specific metadata) of a file object with a local file.
+        *
+        * @abstract
+        * @param t3lib_file_AbstractFile $file
+        * @param string $localFilePath
+        * @return boolean
+        */
+       abstract public function replaceFile(t3lib_file_AbstractFile $file, $localFilePath);
+
+       /**
+        * Returns information about a file for a given file identifier.
+        *
+        * @param string $identifier The (relative) path to the file.
+        * @return array
+        */
+       abstract public function getFileInfoByIdentifier($identifier);
+
+       /**
+        * Returns information about a file for a given file object.
+        *
+        * @param t3lib_file_FileInterface $file
+        * @return array
+        */
+       public function getFileInfo(t3lib_file_FileInterface $file) {
+               return $this->getFileInfoByIdentifier($file->getIdentifier());
+       }
+
+       /**
+        * Returns a file object by its identifier.
+        *
+        * @param string $identifier
+        * @return t3lib_file_FileInterface
+        */
+       public function getFile($identifier) {
+               $fileObject = NULL;
+
+               if (!$this->fileExists($identifier)) {
+                       throw new t3lib_file_exception_FileDoesNotExistException();
+               }
+               $fileInfo = $this->getFileInfoByIdentifier($identifier);
+               $fileObject = $this->getFileObject($fileInfo);
+
+               return $fileObject;
+       }
+
+       /**
+        * Creates a file object from a given file data array
+        *
+        * @param array $fileData
+        * @return t3lib_file_File
+        */
+       protected function getFileObject(array $fileData) {
+               $fileObject = t3lib_file_Factory::getInstance()->createFileObject($fileData);
+
+               return $fileObject;
+       }
+
+       /**
+        * Returns a folder by its identifier.
+        *
+        * @param string $identifier
+        * @return t3lib_file_Folder
+        */
+       public function getFolder($identifier) {
+               if (!$this->folderExists($identifier)) {
+                       throw new t3lib_file_exception_FolderDoesNotExistException("Folder $identifier does not exist.", 1320575630);
+               }
+
+               return t3lib_file_Factory::getInstance()->createFolderObject(
+                       $this->storage,
+                       $identifier,
+                       ''
+               );
+       }
+
+       /**
+        * Returns TRUE if a file should be excluded from a file listing.
+        *
+        * @param string $identifier
+        * @param string $filename
+        * @return boolean
+        */
+       protected function isHiddenFile($identifier, $filename) {
+               if (substr($filename, 0, 1) == '.') {
+                       return TRUE;
+               }
+
+               return FALSE;
+       }
+
+       /**
+        * Returns a list of files inside the specified path
+        *
+        * @param string $path
+        * @param string $pattern
+        * @param integer $start The position to start the listing; if not set, start from the beginning
+        * @param integer $numberOfItems The number of items to list; if not set, return all items
+        * @param boolean $excludeHiddenFiles Set this to TRUE if you want to exclude hidden files (starting with a dot) from the listing
+        * @param array $fileData Two-dimensional, identifier-indexed array of file index records from the database
+        * @return array
+        */
+       // TODO add unit tests
+       // TODO implement pattern matching
+       public function getFileList($path, $pattern = '', $start = 0, $numberOfItems = 0, $excludeHiddenFiles = TRUE, $fileData = array()) {
+               return $this->getDirectoryItemList($path, $start, $numberOfItems, $this->fileListCallbackMethod, $excludeHiddenFiles, $fileData);
+       }
+
+       /**
+        * Copies a file to a temporary path and returns that path.
+        *
+        * @abstract
+        * @param t3lib_file_FileInterface $file
+        * @return string The temporary path
+        */
+       abstract public function copyFileToTemporaryPath(t3lib_file_FileInterface $file);
+
+       /**
+        * Moves a file *within* the current storage.
+        * Note that this is only about an intra-storage move action, where a file is just
+        * moved to another folder in the same storage.
+        *
+        * @param t3lib_file_FileInterface $file
+        * @param t3lib_file_Folder $targetFolder
+        * @param string $fileName
+        * @return string The new identifier of the file
+        */
+       abstract public function moveFileWithinStorage(t3lib_file_FileInterface $file, t3lib_file_Folder $targetFolder, $fileName);
+
+       /**
+        * Copies a file *within* the current storage.
+        * Note that this is only about an intra-storage copy action, where a file is just
+        * copied to another folder in the same storage.
+        *
+        * @param t3lib_file_FileInterface $file
+        * @param t3lib_file_Folder $targetFolder
+        * @param string $fileName
+        * @return t3lib_file_FileInterface The new (copied) file object.
+        */
+       abstract public function copyFileWithinStorage(t3lib_file_FileInterface $file, t3lib_file_Folder $targetFolder, $fileName);
+
+
+       /**
+        * Folder equivalent to moveFileWithinStorage().
+        *
+        * @param t3lib_file_Folder $folderToMove
+        * @param t3lib_file_Folder $targetFolder
+        * @param string $newFolderName
+        * @return array A map of old to new file identifiers
+        */
+       abstract public function moveFolderWithinStorage(t3lib_file_Folder $folderToMove, t3lib_file_Folder $targetFolder, $newFolderName);
+
+       /**
+        * Folder equivalent to copyFileWithinStorage().
+        *
+        * @param t3lib_file_Folder $folderToMove
+        * @param t3lib_file_Folder $targetFolder
+        * @param string $newFileName
+        * @return boolean
+        */
+       abstract public function copyFolderWithinStorage(t3lib_file_Folder $folderToMove, t3lib_file_Folder $targetFolder, $newFileName);
+
+
+       /**
+        * Removes a file from this storage. This does not check if the file is still used or if it is a bad idea to delete
+        * it for some other reason - this has to be taken care of in the upper layers (e.g. the Storage)!
+        *
+        * @abstract
+        * @param t3lib_file_FileInterface $file
+        * @return boolean TRUE if deleting the file succeeded
+        */
+       abstract public function deleteFile(t3lib_file_FileInterface $file);
+
+       /**
+        * Removes a folder from this storage.
+        *
+        * @param t3lib_file_Folder $folder
+        * @param boolean $deleteRecursively
+        * @return boolean
+        */
+       abstract public function deleteFolder(t3lib_file_Folder $folder, $deleteRecursively = FALSE);
+
+       /**
+        * Adds a file at the specified location. This should only be used internally.
+        *
+        * @abstract
+        * @param string $localFilePath
+        * @param t3lib_file_Folder $targetFolder
+        * @param string $targetFileName
+        * @return string The new identifier of the file
+        */
+       // TODO check if this is still necessary if we move more logic to the storage
+       abstract public function addFileRaw($localFilePath, t3lib_file_Folder $targetFolder, $targetFileName);
+
+       /**
+        * Deletes a file without access and usage checks. This should only be used internally.
+        *
+        * This accepts an identifier instead of an object because we might want to delete files that have no object
+        * associated with (or we don't want to create an object for) them - e.g. when moving a file to another storage.
+        *
+        * @abstract
+        * @param string $identifier
+        * @return boolean TRUE if removing the file succeeded
+        */
+       abstract public function deleteFileRaw($identifier);
+
+       /*******************
+        * FOLDER FUNCTIONS
+        *******************/
+
+       /**
+        * Returns the root level folder of the storage.
+        *
+        * @abstract
+        * @return t3lib_file_Folder
+        */
+       abstract public function getRootLevelFolder();
+
+       /**
+        * Returns the default folder new files should be put into.
+        *
+        * @abstract
+        * @return t3lib_file_Folder
+        */
+       abstract public function getDefaultFolder();
+
+       /**
+        * Creates a folder.
+        *
+        * @param string $newFolderName
+        * @param t3lib_file_Folder $parentFolder
+        * @return t3lib_file_Folder The new (created) folder object
+        */
+       abstract public function createFolder($newFolderName, t3lib_file_Folder $parentFolder);
+
+       /**
+        * Returns a list of all folders in a given path
+        *
+        * @param string $path
+        * @param string $pattern
+        * @param integer $start The position to start the listing; if not set, start from the beginning
+        * @param integer $numberOfItems The number of items to list; if not set, return all items
+        * @param boolean $excludeHiddenFolders Set to TRUE to exclude hidden folders (starting with a dot)
+        * @return array
+        */
+       public function getFolderList($path, $pattern = '', $start = 0, $numberOfItems = 0, $excludeHiddenFolders = TRUE) {
+               return $this->getDirectoryItemList($path, $start, $numberOfItems, $this->folderListCallbackMethod, $excludeHiddenFolders);
+       }
+
+       /**
+        * Checks if a folder exists
+        *
+        * @abstract
+        * @param string $identifier
+        * @return boolean
+        */
+       abstract public function folderExists($identifier);
+
+       /**
+        * Checks if a file inside a storage folder exists.
+        *
+        * @abstract
+        * @param string $folderName
+        * @param t3lib_file_Folder $folder
+        * @return boolean
+        */
+       abstract public function folderExistsInFolder($folderName, t3lib_file_Folder $folder);
+
+       /**
+        * Renames a folder in this storage.
+        *
+        * @param t3lib_file_Folder $folder
+        * @param string $newName The target path (including the file name!)
+        * @return array A map of old to new file identifiers
+        * @throws RuntimeException if renaming the folder failed
+        */
+       abstract public function renameFolder(t3lib_file_Folder $folder, $newName);
+
+       /**
+        * Checks if a given object or identifier is within a container, e.g. if a file or folder is within another folder.
+        * This can e.g. be used to check for webmounts.
+        *
+        * @abstract
+        * @param t3lib_file_Folder $container
+        * @param mixed $content An object or an identifier to check
+        * @return boolean TRUE if $content is within $container
+        */
+       abstract public function isWithin(t3lib_file_Folder $container, $content);
+
+       /**
+        * Checks if a folder contains files and (if supported) other folders.
+        *
+        * @param t3lib_file_Folder $folder
+        * @return boolean TRUE if there are no files and folders within $folder
+        */
+       abstract public function isFolderEmpty(t3lib_file_Folder $folder);
+}
+
+if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/file/Driver/AbstractDriver.php'])) {
+       include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/file/Driver/AbstractDriver.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/file/Driver/Configuration/LocalDriverFlexForm.xml b/t3lib/file/Driver/Configuration/LocalDriverFlexForm.xml
new file mode 100644 (file)
index 0000000..04cfafd
--- /dev/null
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<T3DataStructure>
+       <meta>
+               <langDisable>1</langDisable>
+       </meta>
+       <ROOT>
+               <type>array</type>
+               <el>
+                       <basePath>
+                               <TCEforms>
+                                       <label>LLL:EXT:lang/locallang_mod_file_list.xlf:localDriverFlexform_basePath</label>
+                                       <config>
+                                               <type>input</type>
+                                               <default>fileadmin/</default>
+                                               <size>30</size>
+                                       </config>
+                               </TCEforms>
+                       </basePath>
+                       <pathType>
+                               <TCEforms>
+                                       <label>LLL:EXT:lang/locallang_mod_file_list.xlf:localDriverFlexform_pathType</label>
+                                       <config>
+                                               <type>radio</type>
+                                               <items type="array">
+                                                       <numIndex index="0" type="array">
+                                                               <numIndex index="0">LLL:EXT:lang/locallang_mod_file_list.xlf:localDriverFlexform_pathType_relative</numIndex>
+                                                               <numIndex index="1">relative</numIndex>
+                                                       </numIndex>
+                                                       <numIndex index="1" type="array">
+                                                               <numIndex index="0">LLL:EXT:lang/locallang_mod_file_list.xlf:localDriverFlexform_pathType_absolute</numIndex>
+                                                               <numIndex index="1">absolute</numIndex>
+                                                       </numIndex>
+                                               </items>
+                                               <default>relative</default>
+                                       </config>
+                               </TCEforms>
+                       </pathType>
+               </el>
+       </ROOT>
+</T3DataStructure>
\ No newline at end of file
diff --git a/t3lib/file/Driver/DriverRegistry.php b/t3lib/file/Driver/DriverRegistry.php
new file mode 100644 (file)
index 0000000..5196439
--- /dev/null
@@ -0,0 +1,150 @@
+<?php
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2011 Andreas Wolf <andreas.wolf@ikt-werk.de>
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ * A copy is found in the textfile GPL.txt and important notices to the license
+ * from the author is found in LICENSE.txt distributed with these scripts.
+ *
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * Registry for driver classes.
+ *
+ * @author Andreas Wolf <andreas.wolf@ikt-werk.de>
+ * @package TYPO3
+ * @subpackage t3lib
+ */
+class t3lib_file_Driver_DriverRegistry implements t3lib_Singleton {
+       /**
+        * @var string[]
+        */
+       protected $drivers = array();
+
+       /**
+        * @var array
+        */
+       protected $driverConfigurations = array();
+
+       /**
+        * Creates this object.
+        */
+       public function __construct() {
+               t3lib_div::sysLog(
+                       't3lib_file_Driver_DriverRegistry::__construct: ' . t3lib_utility_Debug::debugTrail(),
+                       't3lib_file_Driver_DriverRegistry'
+               );
+
+               $driverConfigurations = $GLOBALS['TYPO3_CONF_VARS']['SYS']['fal']['registeredDrivers'];
+
+               foreach ($driverConfigurations as $shortName => $driverConfig) {
+                       $shortName = ($shortName ? : $driverConfig['shortName']);
+                       $this->registerDriverClass(
+                               $driverConfig['class'],
+                               $shortName,
+                               $driverConfig['label'],
+                               $driverConfig['flexFormDS']
+                       );
+               }
+       }
+
+       /**
+        * Registers a driver class with an optional short name.
+        *
+        * @param string $className
+        * @param string $shortName
+        * @param string $label
+        * @param string $flexFormDataStructurePathAndFilename
+        * @return boolean TRUE if registering succeeded
+        */
+       public function registerDriverClass($className, $shortName = NULL, $label = NULL, $flexFormDataStructurePathAndFilename = NULL) {
+                       // check if the class is available for TYPO3 before registering the driver
+               if (!class_exists($className)) {
+                       throw new InvalidArgumentException("Class $className does not exist.", 1314979197);
+               }
+
+               if ($shortName === '') {
+                       $shortName = $className;
+               }
+
+               if (array_key_exists($shortName, $this->drivers)) {
+                       throw new InvalidArgumentException("Driver $shortName is already registered.", 1314979451);
+               }
+
+               $this->drivers[$shortName] = $className;
+               $this->driverConfigurations[$shortName] = array(
+                       'class' => $className,
+                       'shortName' => $shortName,
+                       'label' => $label,
+                       'flexFormDS' => $flexFormDataStructurePathAndFilename
+               );
+
+               t3lib_div::sysLog("Registered driver $shortName ($className) " . t3lib_utility_Debug::debugTrail(), 't3lib_file_Driver_DriverRegistry');
+
+               return TRUE;
+       }
+
+       /**
+        * @return void
+        */
+       public function addDriversToTCA() {
+               // Add driver to TCA of sys_file_storage
+               if (TYPO3_MODE !== 'BE') {
+                       return;
+               }
+
+               foreach ($this->driverConfigurations as $driver) {
+                       $label = $driver['label'] ? : $driver['class'];
+
+                       t3lib_div::loadTCA('sys_file_storage');
+                       $driverFieldConfig = &$GLOBALS['TCA']['sys_file_storage']['columns']['driver']['config'];
+                       $driverFieldConfig['items'][] = array($label, $driver['shortName']);
+
+                       if ($driver['flexFormDS']) {
+                               $configurationFieldConfig = &$GLOBALS['TCA']['sys_file_storage']['columns']['configuration']['config'];
+                               $configurationFieldConfig['ds'][$driver['shortName']] = $driver['flexFormDS'];
+                       }
+               }
+       }
+
+       /**
+        * Returns a class name for a given class name or short name.
+        *
+        * @param string $shortName
+        * @return string The class name
+        */
+       public function getDriverClass($shortName) {
+               if (class_exists($shortName) && in_array($shortName, $this->drivers)) {
+                       return $shortName;
+               }
+
+               if (!array_key_exists($shortName, $this->drivers)) {
+                       throw new InvalidArgumentException('Desired storage is not in the list of available storages.', 1314085990);
+               }
+
+               return $this->drivers[$shortName];
+       }
+}
+
+if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/file/Driver/DriverRegistry.php'])) {
+       include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/file/Driver/DriverRegistry.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/file/Driver/LocalDriver.php b/t3lib/file/Driver/LocalDriver.php
new file mode 100644 (file)
index 0000000..eb84c3c
--- /dev/null
@@ -0,0 +1,1194 @@
+<?php
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2011 Andreas Wolf <andreas.wolf@ikt-werk.de>
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ * A copy is found in the textfile GPL.txt and important notices to the license
+ * from the author is found in LICENSE.txt distributed with these scripts.
+ *
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * Driver for the local file system
+ *
+ * @author  Andreas Wolf <andreas.wolf@ikt-werk.de>
+ * @package    TYPO3
+ * @subpackage t3lib
+ */
+class t3lib_file_Driver_LocalDriver extends t3lib_file_Driver_AbstractDriver {
+       /**
+        * The absolute base path. It always contains a trailing slash.
+        *
+        * @var string
+        */
+       protected $absoluteBasePath;
+
+       /**
+        * A list of all supported hash algorithms, written all lower case.
+        *
+        * @var array
+        */
+       protected $supportedHashAlgorithms = array('sha1', 'md5');
+
+       /**
+        * The base URL that points to this driver's storage. As long is this is not set, it is assumed that this folder
+        * is not publicly available
+        *
+        * @var string
+        */
+       protected $baseUri;
+
+       /**
+        * @var t3lib_cs
+        */
+       protected $charsetConversion;
+
+       /**
+        * Checks if a configuration is valid for this storage.
+        *
+        * @param array $configuration The configuration
+        * @return void
+        * @throws RuntimeException
+        */
+       public static function verifyConfiguration(array $configuration) {
+               self::calculateBasePath($configuration);
+       }
+
+       /**
+        * Processes the configuration for this driver.
+        *
+        * @return void
+        */
+       protected function processConfiguration() {
+               $this->absoluteBasePath = $this->calculateBasePath($this->configuration);
+       }
+
+       /**
+        * Initializes this object. This is called by the storage after the driver has been attached.
+        *
+        * @return void
+        */
+       public function initialize() {
+               $this->determineBaseUrl();
+
+                       // The capabilities of this driver. See CAPABILITY_* constants for possible values
+               $this->capabilities = (self::CAPABILITY_BROWSABLE && self::CAPABILITY_PUBLIC && self::CAPABILITY_WRITABLE);
+       }
+
+       /**
+        * Determines the base URL for this driver, from the configuration or the TypoScript frontend object
+        *
+        * @return void
+        */
+       protected function determineBaseUrl() {
+               if (t3lib_div::isFirstPartOfStr($this->absoluteBasePath, PATH_site)) {
+                       // TODO use site URL (where to get it from e.g. on CLI?)
+                       if (is_object($GLOBALS['TSFE'])) {
+                               $this->baseUri = $GLOBALS['TSFE']->absRefPrefix;
+                       } else {
+                               // use site-relative URLs
+                               // TODO add unit test
+                               $this->baseUri = substr($this->absoluteBasePath, strlen(PATH_site));
+                       }
+               } elseif (isset($this->configuration['baseUri']) && t3lib_div::isValidUrl($this->configuration['baseUri'])) {
+                       $this->baseUri = rtrim($this->configuration['baseUri'], '/') . '/';
+               } else {
+                       // TODO throw exception? -> not if we have a publisher set
+               }
+       }
+
+       /**
+        * Calculates the absolute path to this drivers storage location.
+        *
+        * @throws RuntimeException
+        * @param array $configuration
+        * @return string
+        */
+       protected function calculateBasePath(array $configuration) {
+               if ($configuration['pathType'] === 'relative') {
+                       $relativeBasePath = $configuration['basePath'];
+                       $absoluteBasePath = PATH_site.$relativeBasePath;
+               } else {
+                       $absoluteBasePath = $configuration['basePath'];
+               }
+
+               $absoluteBasePath = rtrim($absoluteBasePath, '/') . '/';
+
+               if (!is_dir($absoluteBasePath)) {
+                       throw new RuntimeException("Base path $absoluteBasePath does not exist or is no directory.", 1299233097);
+               }
+
+               return $absoluteBasePath;
+       }
+
+       /**
+        * Returns the public URL to a file. For the local driver, this will always return a path relative to PATH_site.
+        *
+        * @param t3lib_file_FileInterface $file
+        * @param bool  $relativeToCurrentScript    Determines whether the URL returned should be relative to the current script, in case it is relative at all (only for the LocalDriver)
+        * @return string
+        */
+       public function getPublicUrl(t3lib_file_FileInterface $file, $relativeToCurrentScript = FALSE) {
+
+               if ($this->configuration['pathType'] === 'relative' && rtrim($this->configuration['basePath'], '/') !== '') {
+                       $publicUrl = rtrim($this->configuration['basePath'], '/') . '/' . ltrim($file->getIdentifier(), '/');
+               } elseif (isset($this->baseUri)) {
+                       $publicUrl = $this->baseUri . ltrim($file->getIdentifier(), '/');
+               } else {
+                       throw new t3lib_file_exception_AbstractFileException(
+                               'Public URL of file cannot be determined',
+                               1329765518
+                       );
+               }
+
+                       // if requested, make the path relative to the current script in order to make it possible
+                       // to use the relative file
+               if ($relativeToCurrentScript) {
+                       $publicUrl = t3lib_utility_Path::getRelativePathTo(dirname(PATH_site . $publicUrl)) . basename($publicUrl);
+               }
+
+               return $publicUrl;
+
+       }
+
+       /**
+        * Returns the root level folder of the storage.
+        *
+        * @return t3lib_file_Folder
+        */
+       public function getRootLevelFolder() {
+               if (!$this->rootLevelFolder) {
+                       $this->rootLevelFolder = t3lib_file_Factory::getInstance()->createFolderObject(
+                               $this->storage,
+                               '/',
+                               ''
+                       );
+               }
+
+               return $this->rootLevelFolder;
+       }
+
+       /**
+        * Returns the default folder new files should be put into.
+        *
+        * @return t3lib_file_Folder
+        */
+       public function getDefaultFolder() {
+               if (!$this->defaultLevelFolder) {
+                       if (!file_exists($this->absoluteBasePath . '_temp_/')) {
+                               mkdir($this->absoluteBasePath . '_temp_/');
+                       }
+
+                       $this->defaultLevelFolder = t3lib_file_Factory::getInstance()->createFolderObject(
+                               $this->storage,
+                               '/_temp_/',
+                               ''
+                       );
+               }
+
+               return $this->defaultLevelFolder;
+       }
+
+       /**
+        * Creates a folder.
+        *
+        * @param string $newFolderName
+        * @param t3lib_file_Folder $parentFolder
+        * @return t3lib_file_Folder The new (created) folder object
+        */
+       public function createFolder($newFolderName, t3lib_file_Folder $parentFolder) {
+               // TODO we should have some convenience method to create a deeper directory structure. Maybe this would fit into Storage
+               $newFolderName = $this->sanitizeFileName($newFolderName);
+
+               $newFolderPath = $this->getAbsolutePath($parentFolder) . trim($newFolderName, '/');
+
+               if (!$this->folderExists($parentFolder->getIdentifier())) {
+                       throw new RuntimeException("Cannot create folder $newFolderName because the parent folder does not exist.", 1315401669);
+               }
+
+               t3lib_div::mkdir($newFolderPath);
+
+               return t3lib_file_Factory::getInstance()->createFolderObject(
+                       $this->storage,
+                               rtrim($parentFolder->getIdentifier(), '/') . $newFolderName,
+                       $newFolderName
+               );
+       }
+
+       /**
+        * Returns information about a file.
+        *
+        * @param string $fileIdentifier In the case of the LocalDriver, this is the (relative) path to the file.
+        * @return array
+        */
+       public function getFileInfoByIdentifier($fileIdentifier) {
+                       // Makes sure the Path given as parameter is valid
+               $this->checkFilePath($fileIdentifier);
+
+               $dirPath = dirname($fileIdentifier);
+               if ($dirPath !== '' && $dirPath !== '/') {
+                       $dirPath = '/' . trim($dirPath, '/') . '/';
+               }
+
+               $absoluteFilePath = $this->absoluteBasePath . ltrim($fileIdentifier, '/');
+
+                       // don't use $this->fileExists() because we need the absolute path to the file anyways, so we can directly
+                       // use PHP's filesystem method.
+               if (!file_exists($absoluteFilePath)) {
+                       throw new InvalidArgumentException("File $fileIdentifier does not exist.", 1314516809);
+               }
+
+               return $this->extractFileInformation(new SplFileInfo($absoluteFilePath), $dirPath);
+       }
+
+       /**
+        * Wrapper for t3lib_div::validPathStr()
+        *
+        * @param string $theFile Filepath to evaluate
+        * @return boolean TRUE if no '/', '..' or '\' is in the $theFile
+        * @see t3lib_div::validPathStr()
+        */
+       protected function isPathValid($theFile) {
+               return t3lib_div::validPathStr($theFile);
+       }
+
+       /**
+        * Returns a string where any character not matching [.a-zA-Z0-9_-] is substituted by '_'
+        * Trailing dots are removed
+        *
+        * previously in t3lib_basicFileFunctions::cleanFileName()
+        *
+        * @param string $fileName Input string, typically the body of a fileName
+        * @param string $charset Charset of the a fileName (defaults to current charset; depending on context)
+        * @return string Output string with any characters not matching [.a-zA-Z0-9_-] is substituted by '_' and trailing dots removed
+        */
+       protected function sanitizeFileName($fileName, $charset = '') {
+                       // Handle UTF-8 characters
+               if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['UTF8filesystem']) {
+                               // allow ".", "-", 0-9, a-z, A-Z and everything beyond U+C0 (latin capital letter a with grave)
+                       $cleanFileName = preg_replace('/[\x00-\x2C\/\x3A-\x3F\x5B-\x60\x7B-\xBF]/u', '_', trim($fileName));
+
+                       // Handle other character sets
+               } else {
+                               // Define character set
+                       if (!$charset) {
+                               if (TYPO3_MODE === 'FE') {
+                                       $charset = $GLOBALS['TSFE']->renderCharset;
+                               } elseif (is_object($GLOBALS['LANG'])) { // BE assumed:
+                                       $charset = $GLOBALS['LANG']->charSet;
+                               } else { // best guess
+                                       $charset = 'utf-8';
+                               }
+                       }
+
+                               // If a charset was found, convert fileName
+                       if ($charset) {
+                               $fileName = $this->getCharsetConversion()->specCharsToASCII($charset, $fileName);
+                       }
+
+                               // Replace unwanted characters by underscores
+                       $cleanFileName = preg_replace('/[^.[:alnum:]_-]/', '_', trim($fileName));
+               }
+
+                       // Strip trailing dots and return
+               $cleanFileName = preg_replace('/\.*$/', '', $cleanFileName);
+               if (!$cleanFileName) {
+                       throw new t3lib_file_exception_InvalidFileNameException("File name $cleanFileName is invalid.", 1320288991);
+               }
+
+               return $cleanFileName;
+       }
+
+       /**
+        * Generic wrapper for extracting a list of items from a path. The extraction itself is done by the given handler method
+        *
+        * @param string $path
+        * @param integer $start The position to start the listing; if not set, start from the beginning
+        * @param integer $numberOfItems The number of items to list; if not set, return all items
+        * @param string $itemHandlerMethod The method (in this class) that handles the single iterator elements.
+        * @param boolean $excludeHiddenItems
+        * @param array $itemRows
+        * @return array
+        */
+       protected function getDirectoryItemList($path, $start, $numberOfItems, $itemHandlerMethod, $excludeHiddenItems, $itemRows = array()) {
+               $realPath = $this->absoluteBasePath . trim($path, '/') . '/';
+
+               if (!is_dir($realPath)) {
+                       throw new InvalidArgumentException("Cannot list items in directory $path - does not exist or is no directory", 1314349666);
+               }
+
+               if ($start > 0) {
+                       $start--;
+               }
+
+                       // Fetch the files and folders and sort them by name; we have to do this here because the directory iterator
+                       // does return them in an arbitrary order
+               $items = $this->getFileAndFoldernamesInPath($realPath);
+               natcasesort($items);
+               $iterator = new ArrayIterator($items);
+               $iterator->seek($start);
+
+               if ($path !== '' && $path !== '/') {
+                       $path = '/' . trim($path, '/') . '/';
+               }
+
+                       // $c is the counter for how many items we still have to fetch (-1 is unlimited)
+               $c = ($numberOfItems > 0) ? $numberOfItems : -1;
+
+               $items = array();
+               while ($iterator->valid() && ($numberOfItems == 0 || $c > 0)) {
+                               // $iteratorItem is the file or folder name
+                       $iteratorItem = $iterator->current();
+
+                       $iterator->next();
+                       $identifier = $path . $iteratorItem;
+
+                       if ($excludeHiddenItems && $this->isHiddenFile($identifier, $iteratorItem)) {
+                               continue;
+                       }
+
+                       if (isset($itemRows[$identifier])) {
+                               list($key, $item) = $this->$itemHandlerMethod($iteratorItem, $path, $itemRows[$identifier]);
+                       } else {
+                               list($key, $item) = $this->$itemHandlerMethod($iteratorItem, $path);
+                       }
+
+                       if (empty($item)) {
+                               continue;
+                       }
+                       $items[$key] = $item;
+
+                               // Decrement item counter to make sure we only return $numberOfItems if it is set
+                       --$c;
+               }
+
+               return $items;
+       }
+
+       /**
+        * Handler for items in a file list.
+        *
+        * @param string $fileName
+        * @param string $path
+        * @param array $fileRow The pre-loaded file row
+        * @return array
+        */
+       protected function getFileList_itemCallback($fileName, $path, array $fileRow = array()) {
+               $filePath = $this->getAbsolutePath($path . $fileName);
+
+               if (!is_file($filePath)) {
+                       return array('', array());
+               }
+
+                       // TODO add unit test for existing file row case
+               if (!empty($fileRow) && filemtime($filePath) <= $fileRow['modification_date']) {
+                       return array($fileName, $fileRow);
+               } else {
+                       return array($fileName, $this->extractFileInformation(new SplFileInfo($filePath), $path));
+               }
+
+       }
+
+       /**
+        * Handler for items in a directory listing.
+        *
+        * @param string $fileName
+        * @param string $path
+        * @param array $folderRow
+        * @return array
+        */
+       protected function getFolderList_itemCallback($fileName, $path, array $folderRow = array()) {
+               $filePath = $this->getAbsolutePath($path . $fileName);
+
+               if (!is_dir($filePath)) {
+                       return array('', array());
+               }
+                       // also don't show hidden files
+               if ($fileName === '..' || $fileName === '.' || $fileName === '' || t3lib_div::isFirstPartOfStr($fileName, '.') === TRUE) {
+                       return array('', array());
+               }
+               $fileName = substr($fileName, 0, -1);
+
+               return array($fileName, array(
+                       'name' => $fileName,
+                       'identifier' => $path . $fileName . '/',
+                       'creationDate' => filectime($filePath),//$fileInfo->getCTime(),
+                       'modificationDate' => filemtime($filePath),
+                       'storage' => $this->storage->getUid()
+                       // TODO add more information
+               ));
+       }
+
+       /**
+        * Returns a list with the names of all files and folders in a path, optionally recursive.
+        * Folder names have a trailing slash.
+        *
+        * @param string $path The absolute path
+        * @param bool $recursive If TRUE, recursively fetches files and folders
+        * @return array
+        */
+       protected function getFileAndFoldernamesInPath($path, $recursive = FALSE) {
+               if ($recursive) {
+                       $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path, FilesystemIterator::CURRENT_AS_FILEINFO));
+               } else {
+                       $iterator = new RecursiveDirectoryIterator($path, FilesystemIterator::CURRENT_AS_FILEINFO);
+               }
+
+               $directoryEntries = array();
+               while ($iterator->valid()) {
+                       /** @var $entry SplFileInfo */
+                       $entry = $iterator->current();
+
+                               // skip non-files/non-folders, and empty entries
+                       if ((!$entry->isFile() && !$entry->isDir()) || $entry->getFilename() == '') {
+                               continue;
+                       }
+
+                       $entryPath = substr($entry->getPathname(), strlen($path));
+                       if ($entry->isDir()) {
+                               $entryPath .= '/';
+                       }
+                       $directoryEntries[] = $entryPath;
+
+                       $iterator->next();
+               }
+
+               return $directoryEntries;
+       }
+
+       /**
+        * Extracts information about a file from an SplFileInfo object.
+        *
+        * @param SplFileInfo $splFileObject
+        * @param string $containerPath
+        * @return array
+        */
+       protected function extractFileInformation(SplFileInfo $splFileObject, $containerPath) {
+               $filePath = $splFileObject->getPathname();
+               $fileInfo = new finfo();
+
+               $fileInformation = array(
+                       'size' => $splFileObject->getSize(),
+                       'atime' => $splFileObject->getATime(),
+                       'mtime' => $splFileObject->getMTime(),
+                       'ctime' => $splFileObject->getCTime(),
+                       'mimetype' => $fileInfo->file($filePath, FILEINFO_MIME_TYPE),
+                       'name' => $splFileObject->getFilename(),
+                       'identifier' => $containerPath . $splFileObject->getFilename(),
+                       'storage' => $this->storage->getUid()
+               );
+
+               return $fileInformation;
+       }
+
+       /**
+        * Returns the absolute path of the folder this driver operates on.
+        *
+        * @return string
+        */
+       public function getAbsoluteBasePath() {
+               return $this->absoluteBasePath;
+       }
+
+       /**
+        * Returns the absolute path of a file or folder.
+        *
+        * @param t3lib_file_FileInterface|t3lib_file_Folder|string $file
+        * @return string
+        */
+       public function getAbsolutePath($file) {
+               if ($file instanceof t3lib_file_FileInterface) {
+                       $path = $this->absoluteBasePath . ltrim($file->getIdentifier(), '/');
+               } elseif ($file instanceof t3lib_file_Folder) {
+                               // We can assume a trailing slash here because it is added by the folder object on construction.
+                       $path = $this->absoluteBasePath . ltrim($file->getIdentifier(), '/');
+               } elseif (is_string($file)) {
+                       $path = $this->absoluteBasePath . ltrim($file, '/');
+               } else {
+                       throw new RuntimeException('Type "' . gettype($file) . '" is not supported.', 1325191178);
+               }
+
+               return $path;
+       }
+
+       /**
+        * Returns metadata of a file (size, times, mimetype)
+        *
+        * @param t3lib_file_FileInterface $file
+        * @return array
+        */
+       public function getLowLevelFileInfo(t3lib_file_FileInterface $file) {
+               // TODO define which data should be returned
+               // TODO write unit test
+               // TODO cache this info. Registry?
+               $filePath = $this->getAbsolutePath($file);
+               $fileStat = stat($filePath);
+               $fileInfo = new finfo();
+
+               $stat = array(
+                       'size' => filesize($filePath),
+                       'atime' => $fileStat['atime'],
+                       'mtime' => $fileStat['mtime'],
+                       'ctime' => $fileStat['ctime'],
+                       'nlink' => $fileStat['nlink'],
+                       'type' => $fileInfo->file($filePath, FILEINFO_MIME_TYPE),
+                       'mimetype' => $fileInfo->file($filePath, FILEINFO_MIME_TYPE),
+               );
+               return $stat;
+       }
+
+       /**
+        * Creates a (cryptographic) hash for a file.
+        *
+        * @param t3lib_file_FileInterface $file
+        * @param string $hashAlgorithm The hash algorithm to use
+        * @return string
+        */
+       public function hash(t3lib_file_FileInterface $file, $hashAlgorithm) {
+               if (!in_array($hashAlgorithm, $this->getSupportedHashAlgorithms())) {
+                       throw new InvalidArgumentException("Hash algorithm $hashAlgorithm is not supported.", 1304964032);
+               }
+
+               switch ($hashAlgorithm) {
+                       case 'sha1':
+                               $hash = sha1_file($this->getAbsolutePath($file));
+                               break;
+                       case 'md5':
+                               $hash = md5_file($this->getAbsolutePath($file));
+                               break;
+                       default:
+                               throw new RuntimeException(
+                                       "Hash algorithm $hashAlgorithm is not implemented.",
+                                       1329644451
+                               );
+               }
+
+               return $hash;
+       }
+
+       /**
+        * Adds a file from the local server hard disk to a given path in TYPO3s virtual file system.
+        *
+        * This assumes that the local file exists, so no further check is done here!
+        *
+        * @param string $localFilePath
+        * @param t3lib_file_Folder $targetFolder
+        * @param string $fileName The name to add the file under
+        * @param t3lib_file_AbstractFile $updateFileObject File object to update (instead of creating a new object). With this parameter, this function can be used to "populate" a dummy file object with a real file underneath.
+        * @todo t3lib_file_File $updateFileObject should be t3lib_file_FileInterface, but indexer logic is only in t3lib_file_File
+        * @return t3lib_file_FileInterface
+        */
+       public function addFile($localFilePath, t3lib_file_Folder $targetFolder, $fileName, t3lib_file_AbstractFile $updateFileObject = NULL) {
+                       // as for the "virtual storage" for backwards-compatibility, this check always fails, as the file probably lies under PATH_site
+                       // thus, it is not checked here
+               if (t3lib_div::isFirstPartOfStr($localFilePath, $this->absoluteBasePath) && $this->storage->getUid() > 0) {
+                       throw new InvalidArgumentException("Cannot add a file that is already part of this storage.", 1314778269);
+               }
+
+               $relativeTargetPath = ltrim($targetFolder->getIdentifier(), '/');
+               $relativeTargetPath .= $fileName ? $fileName : basename($localFilePath);
+               $targetPath = $this->absoluteBasePath . $relativeTargetPath;
+
+               if (is_uploaded_file($localFilePath)) {
+                       $moveResult = move_uploaded_file($localFilePath, $targetPath);
+               }
+               else {
+                       $moveResult = rename($localFilePath, $targetPath);
+               }
+
+               if ($moveResult !== TRUE) {
+                       throw new RuntimeException("Moving file $localFilePath to $targetPath failed.", 1314803096);
+               }
+
+               clearstatcache();
+               t3lib_div::fixPermissions($targetPath); // Change the permissions of the file
+
+               $fileInfo = $this->getFileInfoByIdentifier($relativeTargetPath);
+
+               if ($updateFileObject) {
+                       $updateFileObject->updateProperties($fileInfo);
+                       return $updateFileObject;
+               } else {
+                       $fileObject = $this->getFileObject($fileInfo);
+                       return $fileObject;
+               }
+       }
+
+       /**
+        * Checks if a file exists.
+        *
+        * @param string $identifier
+        * @return boolean
+        */
+       public function fileExists($identifier) {
+               $absoluteFilePath = $this->absoluteBasePath . ltrim($identifier, '/');
+
+               return is_file($absoluteFilePath);
+       }
+
+       /**
+        * Checks if a file inside a storage folder exists
+        *
+        * @param string $fileName
+        * @param t3lib_file_Folder $folder
+        * @return boolean
+        */
+       public function fileExistsInFolder($fileName, t3lib_file_Folder $folder) {
+               $identifier = ltrim($folder->getIdentifier(), '/') . $fileName;
+
+               return $this->fileExists($identifier);
+       }
+
+       /**
+        * Checks if a folder exists.
+        *
+        * @param string $identifier
+        * @return boolean
+        */
+       public function folderExists($identifier) {
+               $absoluteFilePath = $this->absoluteBasePath . ltrim($identifier, '/');
+
+               return is_dir($absoluteFilePath);
+       }
+
+
+       /**
+        * Checks if a file inside a storage folder exists.
+        *
+        * @param string $folderName
+        * @param t3lib_file_Folder $folder
+        * @return boolean
+        */
+       public function folderExistsInFolder($folderName, t3lib_file_Folder $folder) {
+               $identifier = ltrim($folder->getIdentifier(), '/') . $folderName;
+
+               return $this->folderExists($identifier);
+       }
+
+       /**
+        * Replaces the contents (and file-specific metadata) of a file object with a local file.
+        *
+        * @param t3lib_file_AbstractFile $file
+        * @param string $localFilePath
+        * @return boolean TRUE if the operation succeeded
+        */
+       public function replaceFile(t3lib_file_AbstractFile $file, $localFilePath) {
+               $filePath = $this->getAbsolutePath($file);
+
+               $result = rename($localFilePath, $filePath);
+               if ($result === FALSE) {
+                       throw new RuntimeException("Replacing file $filePath with $localFilePath failed.", 1315314711);
+               }
+
+               $fileInfo = $this->getFileInfoByIdentifier($file->getIdentifier());
+               $file->updateProperties($fileInfo);
+               // TODO update index
+
+               return $result;
+       }
+
+       /**
+        * Adds a file at the specified location. This should only be used internally.
+        *
+        * @param string $localFilePath
+        * @param t3lib_file_Folder $targetFolder
+        * @param string $targetFileName
+        * @return boolean TRUE if adding the file succeeded
+        */
+       public function addFileRaw($localFilePath, t3lib_file_Folder $targetFolder, $targetFileName) {
+               $fileIdentifier = $targetFolder->getIdentifier() . $targetFileName;
+               $absoluteFilePath = $this->absoluteBasePath . $fileIdentifier;
+               $result = copy($localFilePath, $absoluteFilePath);
+
+               if ($result === FALSE || !file_exists($absoluteFilePath)) {
+                       throw new RuntimeException("Adding file $localFilePath at $fileIdentifier failed.");
+               }
+
+               return $fileIdentifier;
+       }
+
+       /**
+        * Deletes a file without access and usage checks. This should only be used internally.
+        *
+        * This accepts an identifier instead of an object because we might want to delete files that have no object
+        * associated with (or we don't want to create an object for) them - e.g. when moving a file to another storage.
+        *
+        * @param string $identifier
+        * @return bool TRUE if removing the file succeeded
+        */
+       public function deleteFileRaw($identifier) {
+               $targetPath = $this->absoluteBasePath . ltrim($identifier, '/');
+               $result = unlink($targetPath);
+
+               if ($result === FALSE || file_exists($targetPath)) {
+                       throw new RuntimeException("Deleting file $identifier failed.", 1320381534);
+               }
+
+               return TRUE;
+       }
+
+       /**
+        * Copies a file *within* the current storage.
+        * Note that this is only about an intra-storage move action, where a file is just
+        * moved to another folder in the same storage.
+        *
+        * @param t3lib_file_FileInterface $file
+        * @param t3lib_file_Folder $targetFolder
+        * @param string $fileName
+        * @return t3lib_file_FileInterface The new (copied) file object.
+        */
+       public function copyFileWithinStorage(t3lib_file_FileInterface $file, t3lib_file_Folder $targetFolder, $fileName) {
+               // TODO add unit test
+               $sourcePath = $this->getAbsolutePath($file);
+               $targetPath = ltrim($targetFolder->getIdentifier(), '/') . $fileName;
+
+               copy($sourcePath, $this->absoluteBasePath . $targetPath);
+
+               return $this->getFile($targetPath);
+       }
+
+       /**
+        * Moves a file *within* the current storage.
+        * Note that this is only about an intra-storage move action, where a file is just
+        * moved to another folder in the same storage.
+        *
+        * @param t3lib_file_FileInterface $file
+        * @param t3lib_file_Folder $targetFolder
+        * @param string $fileName
+        * @return boolean
+        */
+       public function moveFileWithinStorage(t3lib_file_FileInterface $file, t3lib_file_Folder $targetFolder, $fileName) {
+               $sourcePath = $this->getAbsolutePath($file);
+               $targetIdentifier = $targetFolder->getIdentifier() . $fileName;
+
+               $result = rename($sourcePath, $this->absoluteBasePath . $targetIdentifier);
+               if ($result === FALSE) {
+                       throw new RuntimeException("Moving file $sourcePath to $targetIdentifier failed.", 1315314712);
+               }
+
+               return $targetIdentifier;
+       }
+
+       /**
+        * Copies a file to a temporary path and returns that path.
+        *
+        * @param t3lib_file_FileInterface $file
+        * @return string The temporary path
+        */
+       public function copyFileToTemporaryPath(t3lib_file_FileInterface $file) {
+               $sourcePath = $this->getAbsolutePath($file);
+               $temporaryPath = $this->getTemporaryPathForFile($file);
+
+               $result = copy($sourcePath, $temporaryPath);
+               if ($result === FALSE) {
+                       throw new RuntimeException('Copying file ' . $file->getIdentifier() . ' to temporary path failed.', 1320577649);
+               }
+               return $temporaryPath;
+       }
+
+       /**
+        * Creates a map of old and new file/folder identifiers after renaming or moving a folder. The old identifier is used
+        * as the key, the new one as the value.
+        *
+        * @param array $filesAndFolders
+        * @param string $relativeSourcePath
+        * @param string $relativeTargetPath
+        * @return array
+        */
+       protected function createIdentifierMap(array $filesAndFolders, $relativeSourcePath, $relativeTargetPath) {
+               $identifierMap = array();
+               foreach ($filesAndFolders as $oldSubIdentifier) {
+                       $oldIdentifier = $relativeSourcePath . $oldSubIdentifier;
+                       $newIdentifier = $relativeTargetPath . $oldSubIdentifier;
+
+                       if (!$this->fileExists($newIdentifier)) {
+                               throw new t3lib_file_exception_FileOperationErrorException('Copying file "'
+                                       . $oldIdentifier . '" to "' . $newIdentifier . '" failed.', 1330119453);
+                       }
+
+                       $identifierMap[$oldIdentifier] = $newIdentifier;
+               }
+               return $identifierMap;
+       }
+
+       /**
+        * Folder equivalent to moveFileWithinStorage().
+        *
+        * @param t3lib_file_Folder $folderToMove
+        * @param t3lib_file_Folder $targetFolder
+        * @param string $newFolderName
+        * @return array A map of old to new file identifiers
+        */
+       public function moveFolderWithinStorage(t3lib_file_Folder $folderToMove, t3lib_file_Folder $targetFolder, $newFolderName) {
+               $relativeSourcePath = $folderToMove->getIdentifier();
+               $sourcePath = $this->getAbsolutePath($relativeSourcePath);
+               $relativeTargetPath = $targetFolder->getIdentifier() . $newFolderName . '/';
+               $targetPath = $this->getAbsolutePath($relativeTargetPath);
+
+                       // get all files and folders we are going to move, to have a map for updating later.
+               $filesAndFolders = $this->getFileAndFoldernamesInPath($sourcePath, TRUE);
+
+               $result = rename($sourcePath, $targetPath);
+               if ($result === FALSE) {
+                       throw new RuntimeException("Moving folder $sourcePath to $targetPath failed.", 1320711817);
+               }
+
+                       // Create a mapping from old to new identifiers
+               $identifierMap = $this->createIdentifierMap($filesAndFolders, $relativeSourcePath, $relativeTargetPath);
+
+               return $identifierMap;
+       }
+
+       /**
+        * Folder equivalent to copyFileWithinStorage().
+        *
+        * @param t3lib_file_Folder $folderToCopy
+        * @param t3lib_file_Folder $targetFolder
+        * @param string $newFolderName
+        * @return boolean
+        */
+       public function copyFolderWithinStorage(t3lib_file_Folder $folderToCopy, t3lib_file_Folder $targetFolder, $newFolderName) {
+                       // This target folder path already includes the topmost level, i.e. the folder this method knows as $folderToCopy.
+                       // We can thus rely on this folder being present and just create the subfolder we want to copy to.
+               $targetFolderPath = $this->getAbsolutePath($targetFolder) . $newFolderName . '/';
+               mkdir($targetFolderPath);
+
+               $sourceFolderPath = $this->getAbsolutePath($folderToCopy);
+
+               /** @var $iterator RecursiveDirectoryIterator */
+               $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($sourceFolderPath));
+
+               while ($iterator->valid()) {
+                       /** @var $current RecursiveDirectoryIterator */
+                       $current = $iterator->current();
+                       $itemSubPath = $iterator->getSubPathname();
+
+                       if ($current->isDir()) {
+                               mkdir($targetFolderPath . $itemSubPath);
+                       } elseif ($current->isFile()) {
+                               $result = copy($sourceFolderPath . $itemSubPath, $targetFolderPath . $itemSubPath);
+                               if ($result === FALSE) {
+                                       throw new t3lib_file_exception_FileOperationErrorException('Copying file "'
+                                               . $sourceFolderPath . $itemSubPath . '" to "' . $targetFolderPath . $itemSubPath . '" failed.', 1330119452);
+                                       // TODO should we stop here or continue?
+                               }
+                       }
+
+                       $iterator->next();
+               }
+
+               return TRUE;
+       }
+
+
+       /**
+        * Renames a file in this storage.
+        *
+        * @param t3lib_file_FileInterface $file
+        * @param string $newName The target path (including the file name!)
+        * @return string The identifier of the file after renaming
+        */
+       public function renameFile(t3lib_file_FileInterface $file, $newName) {
+                       // Makes sure the Path given as parameter is valid
+               $newName = $this->sanitizeFileName($newName);
+               $newIdentifier = rtrim(dirname($file->getIdentifier()), '/') . '/' . $newName;
+
+               // The target should not exist already
+               if ($this->fileExists($newIdentifier)) {
+                       throw new t3lib_file_exception_ExistingTargetFileNameException("The target file already exists.", 1320291063);
+               }
+
+               $sourcePath = $this->getAbsolutePath($file);
+               $targetPath = $this->absoluteBasePath . '/' . ltrim($newIdentifier, '/');
+
+               $result = rename($sourcePath, $targetPath);
+               if ($result === FALSE) {
+                       throw new RuntimeException("Renaming file $sourcePath to $targetPath failed.", 1320375115);
+               }
+
+               return $newIdentifier;
+       }
+
+       /**
+        * Makes sure the Path given as parameter is valid
+        *
+        * @param string $filePath The file path (including the file name!)
+        * @return void
+        */
+       protected function checkFilePath($filePath) {
+                       // filePath must be valid
+               if (!$this->isPathValid($filePath)) {
+                       throw new t3lib_file_exception_InvalidPathException("File $filePath is not valid (\"..\" and \"//\" is not allowed in path).", 1320286857);
+               }
+       }
+
+       /**
+        * Renames a folder in this storage.
+        *
+        * @param t3lib_file_Folder $folder
+        * @param string $newName The target path (including the file name!)
+        * @return array A map of old to new file identifiers
+        * @throws RuntimeException if renaming the folder failed
+        */
+       public function renameFolder(t3lib_file_Folder $folder, $newName) {
+                       // Makes sure the path given as parameter is valid
+               $newName = $this->sanitizeFileName($newName);
+
+               $relativeSourcePath = $folder->getIdentifier();
+               $sourcePath = $this->getAbsolutePath($relativeSourcePath);
+               $relativeTargetPath = rtrim(dirname($relativeSourcePath), '/') . '/' . $newName . '/';
+               $targetPath = $this->getAbsolutePath($relativeTargetPath);
+
+                       // get all files and folders we are going to move, to have a map for updating later.
+               $filesAndFolders = $this->getFileAndFoldernamesInPath($sourcePath, TRUE);
+
+               $result = rename($sourcePath, $targetPath);
+               if ($result === FALSE) {
+                       //throw new RuntimeException("Renaming folder $sourceIdentifier to $newIdentifier failed.", 1320375116);
+               }
+
+                       // Create a mapping from old to new identifiers
+               $identifierMap = $this->createIdentifierMap($filesAndFolders, $relativeSourcePath, $relativeTargetPath);
+
+               return $identifierMap;
+       }
+
+       /**
+        * Removes a file from this storage.
+        *
+        * @param t3lib_file_FileInterface $file
+        * @return boolean TRUE if deleting the file succeeded
+        */
+       public function deleteFile(t3lib_file_FileInterface $file) {
+               $filePath = $this->getAbsolutePath($file);
+
+               $result = unlink($filePath);
+               if ($result === FALSE) {
+                       throw new RuntimeException("Deletion of file " . $file->getIdentifier() . " failed.", 1320855304);
+               }
+
+               return $result;
+       }
+
+       /**
+        * Removes a folder from this storage.
+        *
+        * @param t3lib_file_Folder $folder
+        * @param bool $deleteRecursively
+        * @return boolean
+        */
+       public function deleteFolder(t3lib_file_Folder $folder, $deleteRecursively = FALSE) {
+               $folderPath = $this->getAbsolutePath($folder);
+
+               $result = t3lib_div::rmdir($folderPath, $deleteRecursively);
+               if ($result === FALSE) {
+                       throw new t3lib_file_exception_FileOperationErrorException('Deleting folder "' . $folder->getIdentifier() . '" failed.', 1330119451);
+               }
+               return $result;
+       }
+
+       /**
+        * Checks if a folder contains files and (if supported) other folders.
+        *
+        * @param t3lib_file_Folder $folder
+        * @return boolean TRUE if there are no files and folders within $folder
+        */
+       public function isFolderEmpty(t3lib_file_Folder $folder) {
+               $path = $this->getAbsolutePath($folder);
+
+               $dirHandle = opendir($path);
+               while ($entry = readdir($dirHandle)) {
+                       if ($entry !== '.' && $entry !== '..') {
+                               closedir($dirHandle);
+                               return FALSE;
+                       }
+               }
+               return TRUE;
+       }
+
+       /**
+        * Returns a (local copy of) a file for processing it. This makes a copy first when in writable mode, so if you change the file,
+        * you have to update it yourself afterwards.
+        *
+        * @param t3lib_file_FileInterface $file
+        * @param boolean $writable Set this to FALSE if you only need the file for read operations. This might speed up things, e.g. by using a cached local version. Never modify the file if you have set this flag!
+        * @return string The path to the file on the local disk
+        */
+       public function getFileForLocalProcessing(t3lib_file_FileInterface $file, $writable = TRUE) {
+               if ($writable === FALSE) {
+                               // TODO check if this is ok or introduce additional measures against file changes
+                       return $this->getAbsolutePath($file);
+               } else {
+                               // TODO check if this might also serve as a dump basic implementation in the abstract driver.
+                       return $this->copyFileToTemporaryPath($file);
+               }
+       }
+
+       /**
+        * Returns the permissions of a file as an array (keys r, w) of boolean flags
+        *
+        * @param t3lib_file_FileInterface $file The file object to check
+        * @return array
+        * @throws RuntimeException If fetching the permissions failed
+        */
+       public function getFilePermissions(t3lib_file_FileInterface $file) {
+               $filePath = $this->getAbsolutePath($file);
+
+               return $this->getPermissions($filePath);
+       }
+
+       /**
+        * Returns the permissions of a folder as an array (keys r, w) of boolean flags
+        *
+        * @param t3lib_file_Folder $folder
+        * @return array
+        * @throws RuntimeException If fetching the permissions failed
+        */
+       public function getFolderPermissions(t3lib_file_Folder $folder) {
+               $folderPath = $this->getAbsolutePath($folder);
+
+               return $this->getPermissions($folderPath);
+       }
+
+       /**
+        * Helper function to unify access to permission information
+        *
+        * @param string $path
+        * @return array
+        * @throws RuntimeException If fetching the permissions failed
+        */
+       protected function getPermissions($path) {
+               $permissionBits = fileperms($path);
+
+               if ($permissionBits === FALSE) {
+                       throw new RuntimeException('Error while fetching permissions for ' . $path, 1319455097);
+               }
+
+               return array(
+                       'r' => (bool)is_readable($path),
+                       'w' => (bool)is_writable($path)
+               );
+       }
+
+       /**
+        * Checks if a given object or identifier is within a container, e.g. if a file or folder is within another folder.
+        * This can e.g. be used to check for webmounts.
+        *
+        * @param t3lib_file_Folder $container
+        * @param mixed $content An object or an identifier to check
+        * @return bool TRUE if $content is within $container, always FALSE if $container is not within this storage
+        */
+       public function isWithin(t3lib_file_Folder $container, $content) {
+               if ($container->getStorage() != $this->storage) {
+                       return FALSE;
+               }
+
+               if ($content instanceof t3lib_file_FileInterface || $content instanceof t3lib_file_Folder) {
+                       $content = $container->getIdentifier();
+               }
+               $folderPath = $container->getIdentifier();
+               $content = '/' . ltrim($content, '/');
+
+               return t3lib_div::isFirstPartOfStr($content, $folderPath);
+       }
+
+       /**
+        * Creates a new file and returns the matching file object for it.
+        *
+        * @param string $fileName
+        * @param t3lib_file_Folder $parentFolder
+        * @return t3lib_file_File
+        */
+       public function createFile($fileName, t3lib_file_Folder $parentFolder) {
+               if (!$this->isValidFilename($fileName)) {
+                       throw new t3lib_file_exception_InvalidFileNameException("Invalid characters in fileName '$fileName'.", 1320572272);
+               }
+               $filePath = $parentFolder->getIdentifier() . ltrim($fileName, '/');
+               // TODO set permissions of new file
+               $result = touch($this->absoluteBasePath . $filePath);
+               clearstatcache();
+               if ($result !== TRUE) {
+                       throw new RuntimeException("Creating file $filePath failed.", 1320569854);
+               }
+               $fileInfo = $this->getFileInfoByIdentifier($filePath);
+
+               return $this->getFileObject($fileInfo);
+       }
+
+       /**
+        * Returns the contents of a file. Beware that this requires to load the complete file into memory and also may
+        * require fetching the file from an external location. So this might be an expensive operation (both in terms of
+        * processing resources and money) for large files.
+        *
+        * @param t3lib_file_FileInterface $file
+        * @return string The file contents
+        */
+       public function getFileContents(t3lib_file_FileInterface $file) {
+               $filePath = $this->getAbsolutePath($file);
+
+               return file_get_contents($filePath);
+       }
+
+       /**
+        * Sets the contents of a file to the specified value.
+        *
+        * @param t3lib_file_FileInterface $file
+        * @param string $contents
+        * @return integer The number of bytes written to the file
+        * @throws RuntimeException if the operation failed
+        */
+       public function setFileContents(t3lib_file_FileInterface $file, $contents) {
+               $filePath = $this->getAbsolutePath($file);
+
+               $result = file_put_contents($filePath, $contents);
+
+               if ($result === FALSE) {
+                       throw new RuntimeException('Setting contents of file ' . $file->getIdentifier() . ' failed.', 1325419305);
+               }
+
+               return $result;
+       }
+
+       /**
+        * Gets the charset conversion object.
+        *
+        * @return t3lib_cs
+        */
+       protected function getCharsetConversion() {
+               if (!isset($this->charsetConversion)) {
+                       if (TYPO3_MODE === 'FE') {
+                               $this->charsetConversion = $GLOBALS['TSFE']->csConvObj;
+                       } elseif (is_object($GLOBALS['LANG'])) { // BE assumed:
+                               $this->charsetConversion = $GLOBALS['LANG']->csConvObj;
+                       } else { // The object may not exist yet, so we need to create it now. Happens in the Install Tool for example.
+                               $this->charsetConversion = t3lib_div::makeInstance('t3lib_cs');
+                       }
+               }
+
+               return $this->charsetConversion;
+       }
+}
+
+if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/file/Driver/LocalDriver.php'])) {
+       include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/file/Driver/LocalDriver.php']);
+}
+
+?>
diff --git a/t3lib/file/Exception/AbstractFileException.php b/t3lib/file/Exception/AbstractFileException.php
new file mode 100644 (file)
index 0000000..1e9ff78
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Benjamin Mack <benni@typo3.org>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * An exception when something is wrong with the file handling
+ *
+ * @package TYPO3
+ * @subpackage t3lib_file
+ */
+class t3lib_file_exception_AbstractFileException extends t3lib_exception {
+
+}
+
+if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/Exception/AbstractFileException.php'])) {
+       include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/Exception/AbstractFileException.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/file/Exception/AbstractFileOperationException.php b/t3lib/file/Exception/AbstractFileOperationException.php
new file mode 100644 (file)
index 0000000..4442b70
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Benjamin Mack <benni@typo3.org>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * An exception when something is wrong with the file handling
+ *
+ * @package TYPO3
+ * @subpackage t3lib_file
+ */
+class t3lib_file_exception_AbstractFileOperationException extends t3lib_file_exception_AbstractFileException {
+
+}
+
+if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/Exception/AbstractFileOperationException.php'])) {
+       include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/Exception/AbstractFileOperationException.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/file/Exception/ExistingTargetFileNameException.php b/t3lib/file/Exception/ExistingTargetFileNameException.php
new file mode 100644 (file)
index 0000000..ac194d2
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Benjamin Mack <benni@typo3.org>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * An exception when something is wrong with the file handling
+ *
+ * @package TYPO3
+ * @subpackage t3lib_file
+ */
+class t3lib_file_exception_ExistingTargetFileNameException extends t3lib_file_exception_AbstractFileException {
+
+}
+
+if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/Exception/ExistingTargetFileNameException.php'])) {
+       include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/Exception/ExistingTargetFileNameException.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/file/Exception/ExistingTargetFolderException.php b/t3lib/file/Exception/ExistingTargetFolderException.php
new file mode 100644 (file)
index 0000000..b29ab3a
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Benjamin Mack <benni@typo3.org>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * An exception when something is wrong with the file handling
+ *
+ * @package TYPO3
+ * @subpackage t3lib_file
+ */
+class t3lib_file_exception_ExistingTargetFolderException extends t3lib_file_exception_AbstractFileException {
+
+}
+
+if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/Exception/ExistingTargetFolderException.php'])) {
+       include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/Exception/ExistingTargetFolderException.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/file/Exception/FileDoesNotExistException.php b/t3lib/file/Exception/FileDoesNotExistException.php
new file mode 100644 (file)
index 0000000..c351c1a
--- /dev/null
@@ -0,0 +1,39 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2012 Andreas Wolf <andreas.wolf@ikt-werk.de>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * An exception to throw if a file does not exist
+ *
+ * @package TYPO3
+ * @subpackage t3lib_file
+ */
+class t3lib_file_exception_FileDoesNotExistException extends t3lib_file_exception_AbstractFileException {
+}
+
+if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/file/Exception/FileDoesNotExistException.php'])) {
+       include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/file/Exception/FileDoesNotExistException.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/file/Exception/FileOperationErrorException.php b/t3lib/file/Exception/FileOperationErrorException.php
new file mode 100644 (file)
index 0000000..5e0661e
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Benjamin Mack <benni@typo3.org>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * An exception when something is wrong with the file handling
+ *
+ * @package TYPO3
+ * @subpackage t3lib_file
+ */
+class t3lib_file_exception_FileOperationErrorException extends t3lib_file_exception_AbstractFileOperationException {
+
+}
+
+if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/Exception/FileOperationErrorException.php'])) {
+       include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/Exception/FileOperationErrorException.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/file/Exception/FolderDoesNotExistException.php b/t3lib/file/Exception/FolderDoesNotExistException.php
new file mode 100644 (file)
index 0000000..47aa679
--- /dev/null
@@ -0,0 +1,39 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2012 Andreas Wolf <andreas.wolf@ikt-werk.de>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * An exception to throw if a folder does not exist
+ *
+ * @package TYPO3
+ * @subpackage t3lib_file
+ */
+class t3lib_file_exception_FolderDoesNotExistException extends t3lib_file_exception_AbstractFileException {
+}
+
+if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/file/Exception/FolderDoesNotExistException.php'])) {
+       include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/file/Exception/FolderDoesNotExistException.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/file/Exception/IllegalFileExtensionException.php b/t3lib/file/Exception/IllegalFileExtensionException.php
new file mode 100644 (file)
index 0000000..6b3ec0d
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Benjamin Mack <benni@typo3.org>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * An exception when something is wrong with the file handling
+ *
+ * @package TYPO3
+ * @subpackage t3lib_file
+ */
+class t3lib_file_exception_IllegalFileExtensionException extends t3lib_file_exception_AbstractFileException {
+
+}
+
+if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/Exception/IllegalFileExtensionException.php'])) {
+       include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/Exception/IllegalFileExtensionException.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/file/Exception/InsufficientFileAccessPermissionsException.php b/t3lib/file/Exception/InsufficientFileAccessPermissionsException.php
new file mode 100644 (file)
index 0000000..ad3a215
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Benjamin Mack <benni@typo3.org>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * An exception when something is wrong with the file handling
+ *
+ * @package TYPO3
+ * @subpackage t3lib_file
+ */
+class t3lib_file_exception_InsufficientFileAccessPermissionsException extends t3lib_file_exception_AbstractFileException {
+
+}
+
+if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/Exception/InsufficientFileAccessPermissionsException.php'])) {
+       include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/Exception/InsufficientFileAccessPermissionsException.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/file/Exception/InsufficientFileReadPermissionsException.php b/t3lib/file/Exception/InsufficientFileReadPermissionsException.php
new file mode 100644 (file)
index 0000000..2faa684
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Benjamin Mack <benni@typo3.org>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * An exception when something is wrong with the file handling
+ *
+ * @package TYPO3
+ * @subpackage t3lib_file
+ */
+class t3lib_file_exception_InsufficientFileReadPermissionsException extends t3lib_file_exception_InsufficientFileAccessPermissionsException {
+
+}
+
+if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/Exception/InsufficientFileReadPermissionsException.php'])) {
+       include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/Exception/InsufficientFileReadPermissionsException.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/file/Exception/InsufficientFileWritePermissionsException.php b/t3lib/file/Exception/InsufficientFileWritePermissionsException.php
new file mode 100644 (file)
index 0000000..f4e2fc9
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Benjamin Mack <benni@typo3.org>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * An exception when something is wrong with the file handling
+ *
+ * @package TYPO3
+ * @subpackage t3lib_file
+ */
+class t3lib_file_exception_InsufficientFileWritePermissionsException extends t3lib_file_exception_InsufficientFileAccessPermissionsException {
+
+}
+
+if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/Exception/InsufficientFileWritePermissionsException.php'])) {
+       include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/Exception/InsufficientFileWritePermissionsException.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/file/Exception/InsufficientFolderAccessPermissionsException.php b/t3lib/file/Exception/InsufficientFolderAccessPermissionsException.php
new file mode 100644 (file)
index 0000000..87474ca
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Benjamin Mack <benni@typo3.org>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * An exception when something is wrong with the file handling
+ *
+ * @package TYPO3
+ * @subpackage t3lib_file
+ */
+class t3lib_file_exception_InsufficientFolderAccessPermissionsException extends t3lib_file_exception_AbstractFileException {
+
+}
+
+if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/Exception/InsufficientFolderAccessPermissionsException.php'])) {
+       include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/Exception/InsufficientFolderAccessPermissionsException.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/file/Exception/InsufficientFolderReadPermissionsException.php b/t3lib/file/Exception/InsufficientFolderReadPermissionsException.php
new file mode 100644 (file)
index 0000000..61e36d4
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Benjamin Mack <benni@typo3.org>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * An exception when something is wrong with the file handling
+ *
+ * @package TYPO3
+ * @subpackage t3lib_file
+ */
+class t3lib_file_exception_InsufficientFolderReadPermissionsException extends t3lib_file_exception_AbstractFileException {
+
+}
+
+if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/Exception/InsufficientFolderReadPermissionsException.php'])) {
+       include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/Exception/InsufficientFolderReadPermissionsException.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/file/Exception/InsufficientFolderWritePermissionsException.php b/t3lib/file/Exception/InsufficientFolderWritePermissionsException.php
new file mode 100644 (file)
index 0000000..08649c1
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Benjamin Mack <benni@typo3.org>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * An exception when something is wrong with the file handling
+ *
+ * @package TYPO3
+ * @subpackage t3lib_file
+ */
+class t3lib_file_exception_InsufficientFolderWritePermissionsException extends t3lib_file_exception_AbstractFileException {
+
+}
+
+if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/Exception/InsufficientFolderWritePermissionsException.php'])) {
+       include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/Exception/InsufficientFolderWritePermissionsException.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/file/Exception/InsufficientUserPermissionsException.php b/t3lib/file/Exception/InsufficientUserPermissionsException.php
new file mode 100644 (file)
index 0000000..6b5c17b
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Benjamin Mack <benni@typo3.org>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * An exception when something is wrong with the file handling
+ *
+ * @package TYPO3
+ * @subpackage t3lib_file
+ */
+class t3lib_file_exception_InsufficientUserPermissionsException extends t3lib_file_exception_AbstractFileException {
+
+}
+
+if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/Exception/InsufficientUserPermissionsException.php'])) {
+       include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/Exception/InsufficientUserPermissionsException.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/file/Exception/InvalidFileException.php b/t3lib/file/Exception/InvalidFileException.php
new file mode 100644 (file)
index 0000000..804e9eb
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Benjamin Mack <benni@typo3.org>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * An exception when something is wrong with the File
+ *
+ * @package TYPO3
+ * @subpackage t3lib_file
+ */
+class t3lib_file_exception_InvalidFileException extends t3lib_file_exception_AbstractFileException {
+
+}
+
+if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/Exception/InvalidFileNameException.php'])) {
+       include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/Exception/InvalidFileNameException.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/file/Exception/InvalidFileNameException.php b/t3lib/file/Exception/InvalidFileNameException.php
new file mode 100644 (file)
index 0000000..38e7b5e
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Benjamin Mack <benni@typo3.org>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * An exception when something is wrong with the File name
+ *
+ * @package TYPO3
+ * @subpackage t3lib_file
+ */
+class t3lib_file_exception_InvalidFileNameException extends t3lib_file_exception_AbstractFileException {
+
+}
+
+if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/Exception/InvalidFileNameException.php'])) {
+       include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/Exception/InvalidFileNameException.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/file/Exception/InvalidFolderException.php b/t3lib/file/Exception/InvalidFolderException.php
new file mode 100644 (file)
index 0000000..ae6c659
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Benjamin Mack <benni@typo3.org>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * An exception when something is wrong with the Folder
+ *
+ * @package TYPO3
+ * @subpackage t3lib_file
+ */
+class t3lib_file_exception_InvalidFolderException extends t3lib_file_exception_AbstractFileException {
+
+}
+
+if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/Exception/InvalidFolderException.php'])) {
+       include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/Exception/InvalidFolderException.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/file/Exception/InvalidPathException.php b/t3lib/file/Exception/InvalidPathException.php
new file mode 100644 (file)
index 0000000..c54ec61
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Benjamin Mack <benni@typo3.org>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * An exception when something is wrong with the path
+ *
+ * @package TYPO3
+ * @subpackage t3lib_file
+ */
+class t3lib_file_exception_InvalidPathException extends t3lib_file_exception_AbstractFileException {
+
+}
+
+if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/Exception/InvalidPathException.php'])) {
+       include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/Exception/InvalidPathException.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/file/Exception/InvalidTargetFolderException.php b/t3lib/file/Exception/InvalidTargetFolderException.php
new file mode 100644 (file)
index 0000000..b68fb91
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Benjamin Mack <benni@typo3.org>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * An exception when something is wrong with the file handling
+ *
+ * @package TYPO3
+ * @subpackage t3lib_file
+ */
+class t3lib_file_exception_InvalidTargetFolderException extends t3lib_file_exception_AbstractFileException {
+
+}
+
+if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/Exception/InvalidTargetFolderException.php'])) {
+       include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/Exception/InvalidTargetFolderException.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/file/Exception/NotInMountPointException.php b/t3lib/file/Exception/NotInMountPointException.php
new file mode 100644 (file)
index 0000000..d40bab6
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Benjamin Mack <benni@typo3.org>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * An exception when something is wrong with the Mount Point
+ *
+ * @package TYPO3
+ * @subpackage t3lib_file
+ */
+class t3lib_file_exception_NotInMountPointException extends t3lib_file_exception_AbstractFileException {
+
+}
+
+if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/Exception/NotInMountPointException.php'])) {
+       include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/Exception/NotInMountPointException.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/file/Exception/UploadException.php b/t3lib/file/Exception/UploadException.php
new file mode 100644 (file)
index 0000000..fc1e68c
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Benjamin Mack <benni@typo3.org>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * An exception when the upload goes wrong
+ *
+ * @package TYPO3
+ * @subpackage t3lib_file
+ */
+class t3lib_file_exception_UploadException extends t3lib_file_exception_AbstractFileOperationException {
+
+}
+
+if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/Exception/UploadException.php'])) {
+       include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/Exception/UploadException.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/file/Exception/UploadSizeException.php b/t3lib/file/Exception/UploadSizeException.php
new file mode 100644 (file)
index 0000000..52cfa7a
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Benjamin Mack <benni@typo3.org>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * An exception when the size of the uploaded file has exceeded
+ *
+ * @package TYPO3
+ * @subpackage t3lib_file
+ */
+class t3lib_file_exception_UploadSizeException extends t3lib_file_exception_AbstractFileOperationException {
+
+}
+
+if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/Exception/UploadSizeException.php'])) {
+       include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/Exception/UploadSizeException.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/file/Factory.php b/t3lib/file/Factory.php
new file mode 100644 (file)
index 0000000..084ce6b
--- /dev/null
@@ -0,0 +1,481 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Andreas Wolf <andreas.wolf@ikt-werk.de>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *  A copy is found in the textfile GPL.txt and important notices to the license
+ *  from the author is found in LICENSE.txt distributed with these scripts.
+ *
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * Factory class for FAL objects.
+ *
+ * NOTE: This class is part of the lowlevel FAL API and should not be used from outside the FAL package.
+ *
+ * @author Andreas Wolf <andreas.wolf@ikt-werk.de>
+ * @package TYPO3
+ * @subpackage t3lib
+ */
+// TODO implement constructor-level caching
+class t3lib_file_Factory implements t3lib_Singleton {
+       /**
+        * Gets a singleton instance of this class.
+        *
+        * @return t3lib_file_Factory
+        */
+       public static function getInstance() {
+               return t3lib_div::makeInstance('t3lib_file_Factory');
+       }
+
+       /**
+        * @var t3lib_file_Storage[]
+        */
+       protected $storageInstances = array();
+
+       /**
+        * @var t3lib_file_AbstractCollection[]
+        */
+       protected $collectionInstances = array();
+
+       /**
+        * @var t3lib_file_File[]
+        */
+       protected $fileInstances = array();
+
+       /**
+        * @var t3lib_file_FileReference[]
+        */
+       protected $fileReferenceInstances = array();
+
+       /**
+        * Creates a driver object for a specified storage object.
+        *
+        * @param string $driverIdentificationString The driver class (or identifier) to use.
+        * @param array $driverConfiguration The configuration of the storage
+        * @return t3lib_file_Driver_AbstractDriver
+        * @throws InvalidArgumentException
+        */
+       public function getDriverObject($driverIdentificationString, array $driverConfiguration) {
+               /** @var $driverRegistry t3lib_file_Driver_DriverRegistry */
+               $driverRegistry = t3lib_div::makeInstance('t3lib_file_Driver_DriverRegistry');
+               $driverClass = $driverRegistry->getDriverClass($driverIdentificationString);
+
+               $driverObject = t3lib_div::makeInstance($driverClass, $driverConfiguration);
+
+               return $driverObject;
+       }
+
+       /**
+        * Creates an instance of the storage from given UID. The $recordData can be supplied to increase performance.
+        *
+        * @param integer $uid The uid of the storage to instantiate.
+        * @param array $recordData The record row from database.
+        * @return t3lib_file_Storage
+        */
+       public function getStorageObject($uid, array $recordData = array()) {
+               if (!is_numeric($uid)) {
+                       throw new InvalidArgumentException('uid of Storage has to be numeric.', 1314085991);
+               }
+
+               if (!$this->storageInstances[$uid]) {
+                       $storageConfiguration = NULL;
+
+                               // If the built-in storage with UID=0 is requested:
+                       if (intval($uid) === 0) {
+                               $recordData = array(
+                                       'uid' => 0,
+                                       'pid' => 0,
+                                       'name' => 'Default Storage',
+                                       'description' => 'Internal storage, mounting the main TYPO3_site directory.',
+                                       'driver' => 'Local',
+                                       'processingfolder' => 'typo3temp/_processed_/', // legacy code
+                                       'configuration' => '',
+                                       'is_browsable' => TRUE,
+                                       'is_public' => TRUE,
+                                       'is_writable' => TRUE,
+                               );
+
+                               $storageConfiguration = array(
+                                       'basePath' => '/',
+                                       'pathType' => 'relative'
+                               );
+
+                               // If any other (real) storage is requested:
+                       } elseif (count($recordData) === 0 || $recordData['uid'] !== $uid) {    // Get storage data if not already supplied as argument to this function
+                               /** @var $GLOBALS['TYPO3_DB'] t3lib_DB */
+                               $recordData = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow('*', 'sys_file_storage', 'uid=' . intval($uid) . ' AND deleted=0');
+                               if (!is_array($recordData) || count($recordData) === 0) {
+                                       throw new InvalidArgumentException('No storage found for given UID.', 1314085992);
+                               }
+                       }
+
+                       $storageObject = $this->createStorageObject($recordData, $storageConfiguration);
+                       $this->storageInstances[$uid] = $storageObject;
+               }
+
+               return $this->storageInstances[$uid];
+       }
+
+       /**
+        * Converts a flexform data string to a flat array with key value pairs
+        *
+        * @param string $flexFormData
+        * @return array Array with key => value pairs of the field data in the FlexForm
+        */
+       public function convertFlexFormDataToConfigurationArray($flexFormData) {
+               $configuration = array();
+               if ($flexFormData) {
+                       $flexFormContents = t3lib_div::xml2array($flexFormData);
+                       if (!empty($flexFormContents['data']['sDEF']['lDEF']) && is_array($flexFormContents['data']['sDEF']['lDEF'])) {
+                               foreach ($flexFormContents['data']['sDEF']['lDEF'] as $key => $value) {
+                                       if (isset($value['vDEF'])) {
+                                               $configuration[$key] = $value['vDEF'];
+                                       }
+                               }
+                       }
+               }
+
+               return $configuration;
+       }
+
+
+       /**
+        * Creates an instance of the collection from given UID. The $recordData can be supplied to increase performance.
+        *
+        * @param integer $uid The uid of the collection to instantiate.
+        * @param array $recordData The record row from database.
+        * @return t3lib_file_Collection_AbstractFileCollection
+        */
+       public function getCollectionObject($uid, array $recordData = array()) {
+               if (!is_numeric($uid)) {
+                       throw new InvalidArgumentException('uid of collection has to be numeric.', 1314085999);
+               }
+
+               if (!$this->collectionInstances[$uid]) {
+                               // Get mount data if not already supplied as argument to this function
+                       if (count($recordData) === 0 || $recordData['uid'] !== $uid) {
+                               /** @var $GLOBALS['TYPO3_DB'] t3lib_DB */
+                               $recordData = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow(
+                                       '*',
+                                       'sys_file_collection',
+                                               'uid=' . intval($uid) . ' AND deleted=0'
+                               );
+
+                               if (!is_array($recordData) || count($recordData) === 0) {
+                                       throw new InvalidArgumentException('No collection found for given UID.', 1314085992);
+                               }
+                       }
+
+                       $collectionObject = $this->createCollectionObject($recordData);
+                       $this->collectionInstances[$uid] = $collectionObject;
+               }
+
+               return $this->collectionInstances[$uid];
+       }
+
+       /**
+        * Creates a collection object.
+        *
+        * @param array $collectionData The database row of the sys_file_collection record.
+        * @return t3lib_file_Collection_AbstractFileCollection
+        */
+       public function createCollectionObject(array $collectionData) {
+
+               switch ($collectionData['type']) {
+                       case 'static':
+                               $collection = t3lib_file_Collection_StaticFileCollection::create($collectionData);
+                               break;
+                       case 'folder':
+                               $collection = t3lib_file_Collection_FolderBasedFileCollection::create($collectionData);
+                               break;
+                       default:
+                               $collection = NULL;
+               }
+
+               return $collection;
+       }
+
+       /**
+        * Creates a storage object from a storage database row.
+        *
+        * @param array $storageRecord
+        * @param array $storageConfiguration Storage configuration (if given, this won't be extracted from the FlexForm value but the supplied array used instead)
+        * @return t3lib_file_Storage
+        */
+       public function createStorageObject(array $storageRecord, array $storageConfiguration=NULL) {
+               $className = 't3lib_file_Storage';
+
+               if (!$storageConfiguration) {
+                       $storageConfiguration = $this->convertFlexFormDataToConfigurationArray($storageRecord['configuration']);
+               }
+
+               $driverType = $storageRecord['driver'];
+               $driverObject = $this->getDriverObject($driverType, $storageConfiguration);
+
+               /** @var $storage t3lib_file_Storage */
+               $storage = t3lib_div::makeInstance($className, $driverObject, $storageRecord);
+
+               // TODO handle publisher
+
+               return $storage;
+       }
+
+       /**
+        * Creates a folder to directly access (a part of) a storage.
+        *
+        * @param t3lib_file_Storage $storage The storage the folder belongs to
+        * @param string $identifier The path to the folder. Might also be a simple unique string, depending on the storage driver.
+        * @param string $name The name of the folder (e.g. the folder name)
+        * @return t3lib_file_Folder
+        */
+       public function createFolderObject(t3lib_file_Storage $storage, $identifier, $name) {
+               return t3lib_div::makeInstance('t3lib_file_Folder', $storage, $identifier, $name);
+       }
+
+       protected function createPublisherFromConfiguration(array $configuration) {
+               $publishingTarget = $this->getStorageObject($configuration['publisherConfiguration']['publishingTarget']);
+               $publisher = t3lib_div::makeInstance($configuration['publisher'], $publishingTarget, $configuration['publisherConfiguration']);
+               return $publisher;
+       }
+
+       /**
+        * Creates an instance of the file given UID. The $fileData can be supplied to increase performance.
+        *
+        * @param integer $uid The uid of the file to instantiate.
+        * @param array $fileData The record row from database.
+        * @return t3lib_file_File
+        */
+       public function getFileObject($uid, array $fileData = array()) {
+               if (!is_numeric($uid)) {
+                       throw new InvalidArgumentException('uid of file has to be numeric.', 1300096564);
+               }
+
+               if (!$this->fileInstances[$uid]) {
+                       // Fetches data in case $fileData is empty
+                       if (empty($fileData)) {
+                               /** @var $GLOBALS['TYPO3_DB'] t3lib_DB */
+                               $fileData = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow('*', 'sys_file', 'uid=' . intval($uid) . ' AND deleted=0');
+                               if (!is_array($fileData) || count($fileData) === 0) {
+                                       throw new InvalidArgumentException('No file found for given UID.', 1317178604);
+                               }
+                       }
+
+                       $this->fileInstances[$uid] = $this->createFileObject($fileData);
+               }
+
+               return $this->fileInstances[$uid];
+       }
+
+       /**
+        * Gets an file object from an identifier [storage]:[fileId]
+        *
+        * @param string $identifier
+        * @return t3lib_file_File
+        */
+       public function getFileObjectFromCombinedIdentifier($identifier) {
+               $parts = t3lib_div::trimExplode(':', $identifier);
+
+               if (count($parts) === 2) {
+                       $storageUid = $parts[0];
+                       $fileIdentifier = $parts[1];
+               } else {
+                       // We only got a path: Go into backwards compatibility mode and use virtual Storage (uid=0)
+                       $storageUid = 0;
+                       $fileIdentifier = $parts[0];
+               }
+
+               return $this->getStorageObject($storageUid)->getFile($fileIdentifier);
+       }
+
+       /**
+        * bulk function, can be used for anything to get a file or folder
+        *
+        * 1. it's a UID
+        * 2. it's a combined identifier
+        * 3. it's just a path/filename (coming from the oldstyle/backwards compatibility)
+        *
+        * files, previously laid on fileadmin/ or something, will be "mapped" to the storage the file is
+        * in now. Files like typo3temp/ or typo3conf/ will be moved to the first writable storage
+        * in its processing folder
+        *
+        * $input could be
+        *   - "2:myfolder/myfile.jpg" (combined identifier)
+        *   - "23" (file UID)
+        *   - "uploads/myfile.png" (backwards-compatibility, storage "0")
+        *   - "file:23"
+        * @param string $input
+        * @return t3lib_file_FileInterface|t3lib_file_Folder
+        */
+       public function retrieveFileOrFolderObject($input) {
+                       // easy function to deal with that, could be dropped in the future
+                       // if we know where to use this function
+               if (t3lib_div::isFirstPartOfStr($input, 'file:')) {
+                       $input = substr($input, 5);
+                       return $this->retrieveFileOrFolderObject($input);
+               } elseif (t3lib_utility_Math::canBeInterpretedAsInteger($input)) {
+                               //
+                       return $this->getFileObject($input);
+               } elseif (strpos($input, ':')) {
+                               // path or folder
+                       return $this->getObjectFromCombinedIdentifier($input);
+               } else {
+                               // only the path
+                       return $this->getFileObjectFromCombinedIdentifier($input);
+               }
+       }
+
+
+       /**
+        * Gets an file object from an identifier [storage]:[fileId]
+        *
+        * @TODO check naming, inserted by SteffenR while working on filelist
+        * @param string $identifier
+        * @return t3lib_file_Folder
+        */
+       public function getFolderObjectFromCombinedIdentifier($identifier) {
+               $parts = t3lib_div::trimExplode(':', $identifier);
+
+               if (count($parts) === 2) {
+                       $storageUid = $parts[0];
+                       $folderIdentifier = $parts[1];
+               } else {
+                       // We only got a path: Go into backwards compatibility mode and use virtual Storage (uid=0)
+                       $storageUid = 0;
+                       $folderIdentifier = $parts[0];
+               }
+
+               return $this->getStorageObject($storageUid)->getFolder($folderIdentifier);
+       }
+
+       /**
+        * Gets a file or folder object.
+        *
+        * @param string $identifier
+        * @return t3lib_file_FileInterface|t3lib_file_Folder
+        */
+       public function getObjectFromCombinedIdentifier($identifier) {
+               list($storageId, $objectIdentifier) = t3lib_div::trimExplode(':', $identifier);
+               $storage = $this->getStorageObject($storageId);
+
+               if ($storage->hasFile($objectIdentifier)) {
+                       return $storage->getFile($objectIdentifier);
+               } elseif ($storage->hasFolder($objectIdentifier)) {
+                       return $storage->getFolder($objectIdentifier);
+               } else {
+                       throw new RuntimeException(
+                               'Object with identifier "' . $identifier . '" does not exist in storage',
+                               1329647780
+                       );
+               }
+       }
+
+       /**
+        * Creates a file object from an array of file data. Requires a database row to be fetched.
+        *
+        * @param array $fileData
+        * @return t3lib_file_File
+        */
+       public function createFileObject(array $fileData) {
+               /** @var t3lib_file_File $fileObject */
+               $fileObject = t3lib_div::makeInstance('t3lib_file_File', $fileData);
+
+               if (is_numeric($fileData['storage'])) {
+                       $storageObject = $this->getStorageObject($fileData['storage']);
+                       $fileObject->setStorage($storageObject);
+               }
+
+               return $fileObject;
+       }
+
+       /**
+        * Creates an instance of a FileReference object. The $fileReferenceData can be supplied to increase performance.
+        *
+        * @param integer $uid The uid of the file usage (sys_file_reference) to instantiate.
+        * @param array $fileReferenceData The record row from database.
+        * @return t3lib_file_FileReference
+        */
+       public function getFileReferenceObject($uid, array $fileReferenceData = array()) {
+               if (!is_numeric($uid)) {
+                       throw new InvalidArgumentException('uid of fileusage (sys_file_reference) has to be numeric.', 1300086584);
+               }
+
+               if (!$this->fileReferenceInstances[$uid]) {
+                       // Fetches data in case $fileData is empty
+                       if (empty($fileReferenceData)) {
+                               /** @var $GLOBALS['TYPO3_DB'] t3lib_DB */
+                               $fileReferenceData = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow('*', 'sys_file_reference', 'uid=' . intval($uid) . ' AND deleted=0');
+                               if (!is_array($fileReferenceData) || count($fileReferenceData) === 0) {
+                                       throw new InvalidArgumentException('No fileusage (sys_file_reference) found for given UID.', 1317178794);
+                               }
+                       }
+
+                       $this->fileReferenceInstances[$uid] = $this->createFileReferenceObject($fileReferenceData);
+               }
+
+               return $this->fileReferenceInstances[$uid];
+       }
+
+       /**
+        * Creates a file usage object from an array of fileReference data (from sys_file_reference table).
+        * Requires a database row to be already fetched and present.
+        *
+        * @param array $fileReferenceData
+        * @return t3lib_file_FileReference
+        */
+       public function createFileReferenceObject(array $fileReferenceData) {
+               /** @var t3lib_file_FileReference $fileReferenceObject */
+               $fileReferenceObject = t3lib_div::makeInstance('t3lib_file_FileReference', $fileReferenceData);
+               return $fileReferenceObject;
+       }
+
+       /**
+        * Generates a new object of the type t3lib_file_ProcessedFile
+        * additionally checks if this processed file already exists in the DB
+        *
+        * @param t3lib_file_FileInterface $originalFileObject
+        * @param string $context The context the file is processed in
+        * @param array $configuration The processing configuration
+        * @return t3lib_file_ProcessedFile
+        */
+       public function getProcessedFileObject(t3lib_file_FileInterface $originalFileObject, $context, array $configuration) {
+               /** @var t3lib_file_ProcessedFile $processedFileObject */
+               $processedFileObject = t3lib_div::makeInstance(
+                       't3lib_file_ProcessedFile',
+                       $originalFileObject,
+                       $context,
+                       $configuration);
+
+               /* @var t3lib_file_Repository_ProcessedFileRepository $repository */
+               $repository = t3lib_div::makeInstance('t3lib_file_Repository_ProcessedFileRepository');
+
+                       // check if this file already exists in the DB
+               $repository->populateDataOfProcessedFileObject($processedFileObject);
+
+               return $processedFileObject;
+       }
+}
+
+if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/file/Factory.php'])) {
+       include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/file/Factory.php']);
+}
+
+?>
diff --git a/t3lib/file/File.php b/t3lib/file/File.php
new file mode 100644 (file)
index 0000000..cdb1f69
--- /dev/null
@@ -0,0 +1,367 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Ingo Renner <ingo@typo3.org>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *  A copy is found in the textfile GPL.txt and important notices to the license
+ *  from the author is found in LICENSE.txt distributed with these scripts.
+ *
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * File representation in the file abstraction layer.
+ *
+ * @author  Andreas Wolf <andreas.wolf@ikt-werk.de>
+ * @package  TYPO3
+ * @subpackage  t3lib
+ */
+class t3lib_file_File extends t3lib_file_AbstractFile {
+
+       /**
+        * File indexing status. True, if the file is indexed in the database; NULL is the default value, this means that the index status is unknown
+        *
+        * @var bool
+        */
+       protected $indexed = NULL;
+
+       /**
+        * Set to TRUE while this file is being indexed - used to prevent some endless loops
+        *
+        * @var bool
+        */
+       protected $indexingInProgress = FALSE;
+
+       /**
+        * Contains the names of all properties that have been update since the instantiation of this object
+        *
+        * @var array
+        */
+       protected $updatedProperties = array();
+
+
+       /*********************************************
+        * GENERIC FILE TYPES
+        * these are generic filetypes or -groups,
+        * don't mix it up with mime types
+        *********************************************/
+
+
+       /**
+        * Constructor for a file object. Should normally not be used directly, use the corresponding factory methods instead.
+        *
+        * @param array $fileData
+        * @param t3lib_file_Storage $storage
+        */
+       public function __construct(array $fileData, $storage = NULL) {
+               if (isset($fileData['uid']) && intval($fileData['uid']) > 0) {
+                       $this->indexed = TRUE;
+               }
+
+               $this->identifier = $fileData['identifier'];
+               $this->name = $fileData['name'];
+
+               $this->properties = $fileData;
+               if (is_object($storage)) {
+                       $this->storage = $storage;
+               } elseif (isset($fileData['storage']) && is_object($fileData['storage'])) {
+                       $this->storage = $fileData['storage'];
+               }
+       }
+
+
+       /*******************************
+        * VARIOUS FILE PROPERTY GETTERS
+        *******************************/
+
+
+       /**
+        * Returns a property value
+        *
+        * @param string $key
+        * @return mixed Property value
+        */
+       public function getProperty($key) {
+               if ($this->indexed === NULL) {
+                       $this->loadIndexRecord();
+               }
+
+               return parent::getProperty($key);
+       }
+
+       /**
+        * Returns the properties of this object.
+        *
+        * @return array
+        */
+       public function getProperties() {
+               if ($this->indexed === NULL) {
+                       $this->loadIndexRecord();
+               }
+
+               return parent::getProperties();
+       }
+
+
+
+
+
+
+       /******************
+        * CONTENTS RELATED
+        ******************/
+
+       /**
+        * Get the contents of this file
+        *
+        * @return string File contents
+        */
+       public function getContents() {
+               return $this->getStorage()->getFileContents($this);
+       }
+
+       /**
+        * Replace the current file contents with the given string
+        *
+        * @param string $contents The contents to write to the file.
+        * @return t3lib_file_File The file object (allows chaining).
+        */
+       public function setContents($contents) {
+               $this->getStorage()->setFileContents($this, $contents);
+               return $this;
+       }
+
+
+
+
+
+
+
+       /***********************
+        * INDEX RELATED METHODS
+        ***********************/
+
+       /**
+        * Returns TRUE if this file is indexed
+        *
+        * @return bool
+        */
+       public function isIndexed() {
+               if ($this->indexed === NULL && !$this->indexingInProgress) {
+                       $this->loadIndexRecord();
+               }
+
+               return $this->indexed;
+       }
+
+       /**
+        * @param bool $indexIfNotIndexed
+        * @return void
+        */
+       protected function loadIndexRecord($indexIfNotIndexed = TRUE) {
+               if ($this->indexed !== NULL) {
+                       return;
+               }
+
+               /** @var $repo t3lib_file_Repository_FileRepository */
+               $repo = t3lib_div::makeInstance('t3lib_file_Repository_FileRepository');
+               $indexRecord = $repo->getFileIndexRecord($this);
+               if ($indexRecord === FALSE && $indexIfNotIndexed) {
+                       $this->indexingInProgress = TRUE;
+                       $indexRecord = $repo->addToIndex($this);
+                       $this->mergeIndexRecord($indexRecord);
+                       $this->indexed = TRUE;
+                       $this->indexingInProgress = FALSE;
+               } elseif ($indexRecord !== FALSE) {
+                       $this->mergeIndexRecord($indexRecord);
+                       $this->indexed = TRUE;
+               } else {
+                       throw new RuntimeException('Could not load index record for ' . $this->getIdentifier(), 1321288316);
+               }
+       }
+
+       /**
+        * Merges the contents of this file's index record into the file properties.
+        *
+        * @param array $recordData The index record as fetched from the database
+        * @return void
+        */
+       protected function mergeIndexRecord(array $recordData) {
+               if ($this->properties['uid'] != 0) {
+                       throw new InvalidArgumentException("uid property is already set. Cannot merge index record.", 1321023156);
+               }
+
+               $this->properties = array_merge($this->properties, $recordData);
+               // TODO check for any properties that come from the driver and would change -- these might have to be updated in the index record
+       }
+
+       /**
+        * Updates the properties of this file, e.g. after re-indexing or moving it.
+        * By default, only properties that exist as a key in the $properties array are overwritten. If you want to
+        * explicitly unset a property, set the corresponding key to NULL in the array.
+        *
+        * NOTE: This method should not be called from outside the File Abstraction Layer (FAL)!
+        *
+        * @param array $properties
+        * @return void
+        * @internal
+        */
+       public function updateProperties(array $properties) {
+                       // setting identifier and name to update values; we have to do this here because we might need a new identifier
+                       // when loading (and thus possibly indexing) a file.
+               if (isset($properties['identifier'])) {
+                       $this->identifier = $properties['identifier'];
+               }
+               if (isset($properties['name'])) {
+                       $this->name = $properties['name'];
+               }
+
+               if ($this->indexed === NULL && !isset($properties['uid'])) {
+                       $this->loadIndexRecord();
+               }
+
+               if ($this->properties['uid'] != 0 && isset($properties['uid'])) {
+                       unset($properties['uid']);
+               }
+
+               foreach ($properties as $key => $value) {
+                       if ($this->properties[$key] !== $value) {
+                               if (!in_array($key, $this->updatedProperties)) {
+                                       $this->updatedProperties[] = $key;
+                               }
+                               // TODO check if we should completely remove properties that are set to NULL
+                               $this->properties[$key] = $value;
+                       }
+               }
+
+                       // updating indexing status
+               if (isset($properties['uid']) && intval($properties['uid']) > 0) {
+                       $this->indexed = TRUE;
+               }
+
+               if (isset($properties['storage'])) {
+                       $this->loadStorage();
+               }
+
+               // TODO notify Factory if identifier or storage changed
+               // TODO find some more clever notifications we could use here
+       }
+
+       /**
+        * Returns the names of all properties that have been updated in this record
+        *
+        * @return array
+        */
+       public function getUpdatedProperties() {
+               return $this->updatedProperties;
+       }
+
+
+
+
+
+       /****************************************
+        * STORAGE AND MANAGEMENT RELATED METHODS
+        ****************************************/
+
+       /**
+        * Check if a file operation (= action) is allowed for this file
+        *
+        * @param       string  $action, can be read, write, delete
+        * @return boolean
+        */
+       public function checkActionPermission($action) {
+               return $this->getStorage()->checkFileActionPermission($action, $this);
+       }
+
+
+
+
+       /*****************
+        * SPECIAL METHODS
+        *****************/
+
+       /**
+        * creates a MD5 hash checksum based on the combined identifier of the file,
+        * the files' mimetype and the systems' encryption key.
+        * used to generate a thumbnail, and this hash is checked if valid
+        *
+        * @static
+        * @param t3lib_file_File $file the file to create the checksum from
+        * @return string the MD5 hash
+        */
+       public function calculateChecksum() {
+               return md5($this->getCombinedIdentifier() . '|' . $this->getMimeType() . '|' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey']);
+       }
+
+
+       /**
+        * Returns a modified version of the file.
+        *
+        * @param string $context the context of the configuration (see above)
+        * @param array $configuration the processing configuration, see manual for that
+        * @return t3lib_file_ProcessedFile The processed file
+        */
+       public function process($context, array $configuration) {
+               return $this->getStorage()->processFile($this, $context, $configuration);
+       }
+
+
+       /**
+        * Returns an array representation of the file.
+        * (This is used by the generic listing module vidi when displaying file records.)
+        *
+        * @return array Array of main data of the file. Don't rely on all data to be present here, it's just a selection of the most relevant information.
+        */
+       public function toArray() {
+               $array = array(
+                       'id'            => $this->getCombinedIdentifier(),
+                       'name'          => $this->getName(),
+                       'extension'     => $this->getExtension(),
+                       'type'          => $this->getType(),
+                       'mimetype'      => $this->getMimeType(),
+                       'size'          => $this->getSize(),
+                       'url'           => $this->getPublicUrl(),
+                       'indexed'       => $this->indexed,
+                       'uid'           => $this->getUid(),
+                       'permissions'=> array(
+                               'read'  => $this->checkActionPermission('read'),
+                               'write' => $this->checkActionPermission('write'),
+                               'delete'=> $this->checkActionPermission('delete'),
+                       ),
+                       'checksum' => $this->calculateChecksum()
+               );
+               foreach ($this->properties AS $key => $value) {
+                       $array[$key] = $value;
+               }
+               $stat = $this->storage->getFileInfo($this);
+               foreach ($stat AS $key => $value) {
+                       $array[$key] = $value;
+               }
+               return $array;
+       }
+}
+
+
+if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/vfs/class.t3lib_file_file.php'])) {
+       include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/vfs/class.t3lib_file_file.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/file/FileInterface.php b/t3lib/file/FileInterface.php
new file mode 100644 (file)
index 0000000..698dfc2
--- /dev/null
@@ -0,0 +1,193 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Ingmar Schlecht <ingmar@typo3.org>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *  A copy is found in the textfile GPL.txt and important notices to the license
+ *  from the author is found in LICENSE.txt distributed with these scripts.
+ *
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * File Interface
+ *
+ * @author  Ingmar Schlecht <ingmar@typo3.org>
+ * @package  TYPO3
+ * @subpackage  t3lib
+ */
+interface t3lib_file_FileInterface extends t3lib_file_ResourceInterface {
+
+       /*******************************
+        * VARIOUS FILE PROPERTY GETTERS
+        *******************************/
+
+       /**
+        * Returns true if the given key exists for this file.
+        *
+        * @param string $key
+        * @return boolean
+        */
+       public function hasProperty($key);
+
+       /**
+        * Get the value of the $key property.
+        *
+        * @param string $key
+        * @return string
+        */
+       public function getProperty($key);
+
+       /**
+        * Returns the size of this file
+        *
+        * @return integer
+        */
+       public function getSize();
+
+       /**
+        * Returns the Sha1 of this file
+        *
+        * @return string
+        */
+       public function getSha1();
+
+       /**
+        * Get the file extension
+        *
+        * @return string The file extension
+        */
+       public function getExtension();
+
+       /**
+        * Get the MIME type of this file
+        *
+        * @return array file information
+        */
+       public function getMimeType();
+
+       /**
+        * Returns the modification time of the file as Unix timestamp
+        *
+        * @return integer
+        */
+       public function getModificationTime();
+
+       /**
+        * Returns the creation time of the file as Unix timestamp
+        *
+        * @return integer
+        */
+       public function getCreationTime();
+
+
+
+
+
+       /******************
+        * CONTENTS RELATED
+        ******************/
+
+       /**
+        * Get the contents of this file
+        *
+        * @return string File contents
+        */
+       public function getContents();
+
+       /**
+        * Replace the current file contents with the given string.
+        * @TODO: Consider to remove this function from the interface, as its implementation in FileInUse could cause unforseen side-effects by setting contents on the original file instead of just on the Usage of the file.
+        * @TODO: At the same time, it could be considered whether to make the whole interface a read-only FileInterface, so that all file management and modification functions are removed...
+        *
+        * @param string $contents The contents to write to the file.
+        * @return t3lib_file_File The file object (allows chaining).
+        */
+       public function setContents($contents);
+
+
+       /****************************************
+        * STORAGE AND MANAGEMENT RELATED METHDOS
+        ****************************************/
+
+       /**
+        * Deletes this file from its storage. This also means that this object becomes useless.
+        *
+        * @return boolean TRUE if deletion succeeded
+        */
+       public function delete();
+
+       /**
+        * Renames this file.
+        *
+        * @param string $newName The new file name
+        * @return t3lib_file_File
+        */
+       public function rename($newName);
+
+
+       /*****************
+        * SPECIAL METHODS
+        *****************/
+
+       /**
+        * Returns a publicly accessible URL for this file
+        *
+        * WARNING: Access to the file may be restricted by further means, e.g. some web-based authentication. You have to take care of this
+        * yourself.
+        *
+        * @param bool  $relativeToCurrentScript   Determines whether the URL returned should be relative to the current script, in case it is relative at all (only for the LocalDriver)
+        *
+        * @return string
+        */
+       public function getPublicUrl($relativeToCurrentScript = FALSE);
+
+       /**
+        * Returns TRUE if this file is indexed
+        *
+        * @return boolean
+        */
+       public function isIndexed();
+
+       /**
+        * Returns a path to a local version of this file to process it locally (e.g. with some system tool).
+        * If the file is normally located on a remote storages, this creates a local copy.
+        * If the file is already on the local system, this only makes a new copy if $writable is set to TRUE.
+        *
+        * @param bool $writable Set this to FALSE if you only want to do read operations on the file.
+        * @return string
+        */
+       public function getForLocalProcessing($writable = TRUE);
+
+       /**
+        * Returns an array representation of the file.
+        * (This is used by the generic listing module vidi when displaying file records.)
+        *
+        * @return array Array of main data of the file. Don't rely on all data to be present here, it's just a selection of the most relevant information.
+        */
+       public function toArray();
+}
+
+
+if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/file/FileInterface.php'])) {
+       include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/file/FileInterface.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/file/FileReference.php b/t3lib/file/FileReference.php
new file mode 100644 (file)
index 0000000..6dda97e
--- /dev/null
@@ -0,0 +1,437 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Ingmar Schlecht <ingmar@typo3.org>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *  A copy is found in the textfile GPL.txt and important notices to the license
+ *  from the author is found in LICENSE.txt distributed with these scripts.
+ *
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * Representation of a specific usage of a file with possibilities to override certain
+ * properties of the original file just for this usage of the file.
+ *
+ * It acts as a decorator over the original file in the way that most method calls are
+ * directly passed along to the original file object.
+ *
+ * All file related methods are directly passed along; only meta data functionality is adopted
+ * in this decorator class to priorities possible overrides for the metadata for this specific usage
+ * of the file.
+ *
+ * @author Ingmar Schlecht <ingmar@typo3.org>
+ * @package TYPO3
+ * @subpackage t3lib
+ */
+class t3lib_file_FileReference implements t3lib_file_FileInterface {
+
+       /**
+        * Various properties of the FileReference. Note that these information can be different
+        * to the ones found in the originalFile.
+        *
+        * @var array
+        */
+       protected $propertiesOfFileReference;
+
+       /**
+        * The identifier of this file to identify it on the storage.
+        * On some drivers, this is the path to the file, but drivers could also just
+        * provide any other unique identifier for this file on the specific storage.
+        *
+        * @var string
+        */
+       protected $uidOfFileReference;
+
+       /**
+        * The file name of this file. It's either the fileName of the original underlying file,
+        * or the overlay file name supplied by the user for this particular usage (FileReference) of the file.
+        *
+        * @var string
+        */
+       protected $name;
+
+       /**
+        * The FileRepository object. Is needed e.g. for the delete() method to delete the usage record
+        * (sys_file_reference record) of this file usage.
+        *
+        * @var t3lib_file_Repository_FileRepository
+        */
+       protected $fileRepository;
+
+       /**
+        * Reference to the original File object underlying this FileReference.
+        *
+        * @var t3lib_file_File
+        */
+       protected $originalFile;
+
+       /**
+        * Constructor for a file in use object. Should normally not be used directly, use the corresponding factory methods instead.
+        *
+        * @param array $fileReferenceData
+        * @param t3lib_file_Factory $factory
+        */
+       public function __construct(array $fileReferenceData, $factory = NULL) {
+               $this->propertiesOfFileReference = $fileReferenceData;
+
+               if (!$fileReferenceData['uid_local']) {
+                       throw new Exception('Incorrect reference to original file given for FileReference.', 1300098528);
+               }
+
+               if (!$factory) {
+                       /** @var $factory t3lib_file_Factory */
+                       $factory = t3lib_div::makeInstance('t3lib_file_Factory');
+               }
+
+               $this->originalFile = $factory->getFileObject($fileReferenceData['uid_local']);
+
+               $this->fileRepository = t3lib_div::makeInstance('t3lib_file_Repository_FileRepository');
+
+               if (!is_object($this->originalFile)) {
+                       throw new Exception('Original File not found for FileReference.', 1300098529);
+               }
+
+               $this->name = $fileReferenceData['name'] !== '' ? $fileReferenceData['name'] : $this->originalFile->getName();
+       }
+
+
+       /*******************************
+        * VARIOUS FILE PROPERTY GETTERS
+        *******************************/
+
+
+       /**
+        * Returns true if the given key exists for this file.
+        *
+        * @param string $key The property to be looked up
+        * @return boolean
+        */
+       public function hasProperty($key) {
+               return array_key_exists($key, $this->propertiesOfFileReference);
+       }
+
+       /**
+        * Gets a property.
+        *
+        * @param string $key The property to be looked up
+        * @return mixed
+        * @throws InvalidArgumentException
+        */
+       public function getProperty($key) {
+               if (!$this->hasProperty($key)) {
+                       throw new InvalidArgumentException('Property "' . $key . '" was not found.', 1314226805);
+               }
+
+               return $this->propertiesOfFileReference[$key];
+       }
+
+       /**
+        * Gets all properties.
+        *
+        * @return array
+        */
+       public function getProperties() {
+               return t3lib_div::array_merge_recursive_overrule(
+                       $this->originalFile->getProperties(),
+                       $this->propertiesOfFileReference
+               );
+       }
+
+       /**
+        * Returns the name of this file
+        *
+        * @return string
+        */
+       public function getName() {
+               return $this->originalFile->getName();
+       }
+
+       /**
+        * Returns the title text to this image
+        *
+        * TODO: Possibly move this to the image domain object instead
+        *
+        * @return string
+        */
+       public function getTitle() {
+               return $this->propertiesOfFileReference['title'] ? $this->propertiesOfFileReference['title'] : $this->originalFile->getName();
+       }
+
+       /**
+        * Returns the alternative text to this image
+        *
+        * TODO: Possibly move this to the image domain object instead
+        *
+        * @return string
+        */
+       public function getAlternative() {
+               return $this->propertiesOfFileReference['alternative'] ? $this->propertiesOfFileReference['alternative'] : $this->originalFile->getName();
+       }
+
+       /**
+        * Returns the description text to this file
+        *
+        * TODO: Possibly move this to the image domain object instead
+        *
+        * @return string
+        */
+       public function getDescription() {
+               return $this->propertiesOfFileReference['description'];
+       }
+
+       /**
+        * Returns the link that should be active when clicking on this image
+        *
+        * TODO: Move this to the image domain object instead
+        *
+        * @return string
+        */
+       public function getLink() {
+               return $this->propertiesOfFileReference['link'];
+       }
+
+       /**
+        * Returns the uid of this File In Use
+        *
+        * @return integer
+        */
+       public function getUid() {
+               return $this->propertiesOfFileReference['uid'];
+       }
+
+       /**
+        * Returns the size of this file
+        *
+        * @return integer
+        */
+       public function getSize() {
+               return $this->originalFile->getSize();
+       }
+
+       /**
+        * Returns the Sha1 of this file
+        *
+        * @return string
+        */
+       public function getSha1() {
+               return $this->originalFile->getSha1();
+       }
+
+
+       /**
+        * Get the file extension of this file
+        *
+        * @return string The file extension
+        */
+       public function getExtension() {
+               return $this->originalFile->getExtension();
+       }
+
+       /**
+        * Get the MIME type of this file
+        *
+        * @return array file information
+        */
+       public function getMimeType() {
+               return $this->originalFile->getMimeType();
+       }
+
+       /**
+        * Returns the modification time of the file as Unix timestamp
+        *
+        * @return integer
+        */
+       public function getModificationTime() {
+               $this->originalFile->getModificationTime();
+       }
+
+       /**
+        * Returns the creation time of the file as Unix timestamp
+        *
+        * @return integer
+        */
+       public function getCreationTime() {
+               $this->originalFile->getCreationTime();
+       }
+
+       /**
+        * Returns the fileType of this file
+        *
+        * @return integer $fileType
+        */
+       public function getType() {
+               return $this->originalFile->getType();
+       }
+
+
+       /******************
+        * CONTENTS RELATED
+        ******************/
+
+       /**
+        * Get the contents of this file
+        *
+        * @return string File contents
+        */
+       public function getContents() {
+               return $this->originalFile->getContents();
+       }
+
+       /**
+        * Replace the current file contents with the given string
+        *
+        * @param string $contents The contents to write to the file.
+        * @return t3lib_file_File The file object (allows chaining).
+        */
+       public function setContents($contents) {
+               return $this->originalFile->setContents($contents);
+       }
+
+
+       /****************************************
+        * STORAGE AND MANAGEMENT RELATED METHDOS
+        ****************************************/
+
+
+       /**
+        * Get the storage the original file is located in
+        *
+        * @return t3lib_file_Storage
+        */
+       public function getStorage() {
+               return $this->originalFile->getStorage();
+       }
+
+       /**
+        * Returns the identifier of the underlying original file
+        *
+        * @return string
+        */
+       public function getIdentifier() {
+               return $this->originalFile->getIdentifier();
+       }
+
+
+       /**
+        * Returns a combined identifier of the underlying original file
+        *
+        * @return string Combined storage and file identifier, e.g. StorageUID:path/and/fileName.png
+        */
+       public function getCombinedIdentifier() {
+               return $this->originalFile->getCombinedIdentifier();
+       }
+
+       /**
+        * Deletes only this particular FileReference from the persistence layer (database table sys_file_reference)
+        * but leaves the original file untouched.
+        *
+        * @return boolean TRUE if deletion succeeded
+        */
+       public function delete() {
+               // TODO: Implement this function. This should only delete the FileReference (sys_file_reference) record, not the file itself.
+               throw new Exception('Function not implemented FileReference::delete().');
+               return $this->fileRepository->removeUsageRecord($this);
+       }
+
+       /**
+        * Renames the fileName in this particular usage.
+        *
+        * @param string $newName The new name
+        * @return t3lib_file_FileReference
+        */
+       public function rename($newName) {
+               // TODO: Implement this function. This should only rename the FileReference (sys_file_reference) record, not the file itself.
+               throw new Exception('Function not implemented FileReference::rename().');
+               return $this->fileRepository->renameUsageRecord($this, $newName);
+       }
+
+
+       /*****************
+        * SPECIAL METHODS
+        *****************/
+
+       /**
+        * Returns a publicly accessible URL for this file
+        *
+        * WARNING: Access to the file may be restricted by further means, e.g. some web-based authentication. You have to take care of this
+        * yourself.
+        *
+        * @param bool  $relativeToCurrentScript   Determines whether the URL returned should be relative to the current script, in case it is relative at all (only for the LocalDriver)
+        *
+        * @return string
+        */
+       public function getPublicUrl($relativeToCurrentScript = FALSE) {
+               return $this->originalFile->getPublicUrl($relativeToCurrentScript);
+       }
+
+       /**
+        * Returns TRUE if this file is indexed.
+        * This is always true for FileReference objects, as they rely on a sys_file_reference record to be present,
+        * which in turn can only exist if the original file is indexed.
+        *
+        * @return boolean
+        */
+       public function isIndexed() {
+               return TRUE;
+       }
+
+       /**
+        * Returns a path to a local version of this file to process it locally (e.g. with some system tool).
+        * If the file is normally located on a remote storages, this creates a local copy.
+        * If the file is already on the local system, this only makes a new copy if $writable is set to TRUE.
+        *
+        * @param boolean $writable Set this to FALSE if you only want to do read operations on the file.
+        * @return string
+        */
+       public function getForLocalProcessing($writable = TRUE) {
+               return $this->originalFile->getForLocalProcessing($writable);
+       }
+
+       /**
+        * Returns an array representation of the file.
+        * (This is used by the generic listing module vidi when displaying file records.)
+        *
+        * @return array Array of main data of the file. Don't rely on all data to be present here, it's just a selection of the most relevant information.
+        */
+       public function toArray() {
+               $array = array_merge(
+                       $this->originalFile->toArray(),
+                       $this->propertiesOfFileReference
+               );
+               return $array;
+       }
+
+       /**
+        * Gets the original file being referenced.
+        *
+        * @return t3lib_file_File
+        */
+       public function getOriginalFile() {
+               return $this->originalFile;
+       }
+}
+
+
+if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/file/FileReference.php'])) {
+       include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/file/FileReference.php']);
+}
+
+?>
diff --git a/t3lib/file/Folder.php b/t3lib/file/Folder.php
new file mode 100644 (file)
index 0000000..55c6992
--- /dev/null
@@ -0,0 +1,360 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Andreas Wolf <andreas.wolf@ikt-werk.de>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *  A copy is found in the textfile GPL.txt and important notices to the license
+ *  from the author is found in LICENSE.txt distributed with these scripts.
+ *
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * A folder that groups files in a storage. This may be a folder on the local disk, a bucket in Amazon S3
+ * or a user or a tag in Flickr.
+ *
+ * This object is not persisted in TYPO3 locally, but created on the fly by storage drivers for the folders they "offer".
+ *
+ * Some folders serve as a physical container for files (e.g. folders on the local disk, S3 buckets or Flickr users).
+ * Other folders just group files by a certain criterion, e.g. a tag.
+ * The way this is implemented depends on the storage driver.
+ *
+ * @author Andreas Wolf <andreas.wolf@ikt-werk.de>
+ * @author Ingmar Schlecht <ingmar@typo3.org>
+ * @package TYPO3
+ * @subpackage t3lib
+ */
+class t3lib_file_Folder implements t3lib_file_ResourceInterface {
+
+       /**
+        * The storage this folder belongs to.
+        *
+        * @var t3lib_file_Storage
+        */
+       protected $storage;
+
+       /**
+        * The identifier of this folder to identify it on the storage.
+        * On some drivers, this is the path to the folder, but drivers could also just
+        * provide any other unique identifier for this folder on the specific storage.
+        *
+        * @var string
+        */
+       protected $identifier;
+
+       /**
+        * The name of this folder
+        *
+        * @var string
+        */
+       protected $name;
+
+       /**
+        * Initialization of the folder
+        *
+        * @param t3lib_file_Storage $storage
+        * @param $identifier
+        * @param $name
+        */
+       public function __construct(t3lib_file_Storage $storage, $identifier, $name) {
+               $this->storage = $storage;
+               $this->identifier = rtrim($identifier, '/') . '/';
+               $this->name = $name;
+       }
+
+       /**
+        * Returns the name of this folder.
+        *
+        * @return string
+        */
+       public function getName() {
+               return $this->name;
+       }
+
+       /**
+        * Sets a new name of the folder
+        * currently this does not trigger the "renaming process"
+        * as the name is more seen as a label
+        *
+        * @param $name the new name
+        * @return void
+        */
+       public function setName($name) {
+               $this->name = $name;
+       }
+
+       /**
+        * Returns the storage this folder belongs to.
+        *
+        * @return t3lib_file_Storage
+        */
+       public function getStorage() {
+               return $this->storage;
+       }
+
+       /**
+        * Returns the path of this folder inside the storage. It depends on the type of storage whether this is a real
+        * path or just some unique identifier.
+        *
+        * @return string
+        */
+       public function getIdentifier() {
+               return $this->identifier;
+       }
+
+       /**
+        * Returns a combined identifier of this folder, i.e. the storage UID and the folder identifier
+        * separated by a colon ":".
+        *
+        * @return string Combined storage and folder identifier, e.g. StorageUID:folder/path/
+        */
+       public function getCombinedIdentifier() {
+               // @todo $this->properties is never defined nor used here
+
+               if (is_array($this->properties) && t3lib_utility_Math::canBeInterpretedAsInteger($this->properties['storage'])) {
+                       $combinedIdentifier = $this->properties['storage'].':'.$this->getIdentifier();
+               } else {
+                       $combinedIdentifier = $this->getStorage()->getUid().':'.$this->getIdentifier();
+               }
+
+               return $combinedIdentifier;
+       }
+
+       /**
+        * Returns a list of files in this folder, optionally filtered by the given pattern.
+        * For performance reasons the returned items can be limited to a given range
+        *
+        * @param string $pattern
+        * @param int $start The item to start at
+        * @param int $numberOfItems The number of items to return
+        * @return t3lib_file_File[]
+        */
+       public function getFiles($pattern = '', $start = 0, $numberOfItems = 0) {
+               // TODO fetch
+               /** @var $factory t3lib_file_Factory */
+               $factory = t3lib_div::makeInstance('t3lib_file_Factory');
+               $fileArray = $this->storage->getFileList($this->identifier, $pattern, $start, $numberOfItems);
+               $fileObjects = array();
+
+               foreach ($fileArray as $fileInfo) {
+                       $fileObjects[] = $factory->createFileObject($fileInfo);
+               }
+               return $fileObjects;
+       }
+
+       /**
+        * Returns amount of all files within this folder, optionally filtered by the given pattern
+        *
+        * @param string $pattern
+        * @return int
+        */
+       public function getFileCount($pattern = '') {
+               return count($this->storage->getFileList($this->identifier, $pattern));
+       }
+
+       /**
+        * Returns the object for a subfolder of the current folder, if it exists.
+        *
+        * @param  $name
+        * @return t3lib_file_Folder
+        */
+       public function getSubfolder($name) {
+               if (!$this->storage->hasFolderInFolder($name, $this)) {
+                       throw new InvalidArgumentException('Folder "' . $name . '" does not exist in "'. $this->identifier . '"', 1329836110);
+               }
+
+                       // TODO this will not work with non-hierarchical storages -> the identifier for subfolders is not composed of
+                       // the current item's identifier for these
+               /** @var $factory t3lib_file_Factory */
+               $factory = t3lib_file_Factory::getInstance();
+               $folderObject = $factory->createFolderObject($this->storage, $this->identifier . $name . '/', $name);
+
+               return $folderObject;
+       }
+
+       /**
+        * Returns a list of all subfolders
+        *
+        * @return t3lib_file_Folder[]
+        */
+       public function getSubfolders() {
+               $folderObjects = array();
+
+               $folderArray = $this->storage->getFolderList($this->identifier);
+
+               if (count($folderArray) > 0) {
+                       /** @var $factory t3lib_file_Factory */
+                       $factory = t3lib_div::makeInstance('t3lib_file_Factory');
+
+                               // TODO this will not work with non-hierarchical storages -> the identifier for subfolders is not composed of
+                               // the current item's identifier for these
+                       foreach ($folderArray as $folder) {
+                               $folderObjects[] = $factory->createFolderObject($this->storage, $this->identifier . $folder['name'] . '/', $folder['name']);
+                       }
+               }
+
+               return $folderObjects;
+       }
+
+       /**
+        * Adds a file from the local server disk. If the file already exists and overwriting is disabled,
+        *
+        * @param string $localFilePath
+        * @param string $fileName
+        * @param string $conflictMode possible value are 'cancel', 'replace'
+        * @return t3lib_file_File The file object
+        */
+       public function addFile($localFilePath, $fileName = NULL, $conflictMode = 'cancel') {
+               $fileName = $fileName ? $fileName : basename($localFilePath);
+               return $this->storage->addFile($localFilePath, $this, $fileName, $conflictMode);
+       }
+
+       /**
+        * Adds an uploaded file into the Storage.
+        *
+        * @param array $uploadedFileData contains information about the uploaded file given by $_FILES['file1']
+        * @param string $conflictMode possible value are 'cancel', 'replace'
+        * @return t3lib_file_File The file object
+        */
+       public function addUploadedFile(array $uploadedFileData, $conflictMode = 'cancel') {
+               return $this->storage->addUploadedFile($uploadedFileData, $this, $uploadedFileData['name'], $conflictMode);
+       }
+
+       /**
+        * Renames this folder.
+        *
+        * @param string $newName
+        * @return t3lib_file_Folder
+        */
+       public function rename($newName) {
+               return $this->storage->renameFolder($this, $newName);
+       }
+
+       /**
+        * Deletes this folder from its storage. This also means that this object becomes useless.
+        *
+        * @return boolean TRUE if deletion succeeded
+        * @param       boolean $deleteRecursively
+        *
+        * TODO mark folder internally as deleted, throw exceptions on all method calls afterwards
+        * TODO undelete mechanism? From Reycler Folder?
+        */
+       public function delete($deleteRecursively = TRUE) {
+               return $this->storage->deleteFolder($this, $deleteRecursively);
+       }
+
+
+       /**
+        * Creates a new blank file
+        *
+        * @param string $fileName
+        * @return t3lib_file_File The new file object
+        */
+       public function createFile($fileName) {
+               return $this->storage->createFile($fileName, $this);
+       }
+
+       /**
+        * Creates a new folder
+        *
+        * @param string $folderName
+        * @return t3lib_file_Folder The new folder object
+        */
+       public function createFolder($folderName) {
+               return $this->storage->createFolder($folderName, $this);
+       }
+
+       /**
+        * Copies folder to a target folder
+        *
+        * @param t3lib_file_Folder $targetFolder Target folder to copy to.
+        * @param string $targetFolderName an optional destination fileName
+        * @param string $conflictMode "overrideExistingFile", "renameNewFile" or "cancel"
+        *
+        * @return t3lib_file_Folder New (copied) folder object.
+        */
+       public function copyTo(t3lib_file_Folder $targetFolder, $targetFolderName = NULL, $conflictMode = 'renameNewFile') {
+               return $this->storage->copyFolder($this, $targetFolder, $targetFolderName, $conflictMode);
+       }
+
+       /**
+        * Movies folder to a target folder
+        *
+        * @param t3lib_file_Folder $targetFolder Target folder to move to.
+        * @param string $targetFolderName an optional destination fileName
+        * @param string $conflictMode "overrideExistingFile", "renameNewFile" or "cancel"
+        *
+        * @return t3lib_file_Folder New (copied) folder object.
+        */
+       public function moveTo(t3lib_file_Folder $targetFolder, $targetFolderName = NULL, $conflictMode = 'renameNewFile') {
+               return $this->storage->moveFolder($this, $targetFolder, $targetFolderName, $conflictMode);
+       }
+
+       /**
+        * Checks if a file exists in this folder
+        *
+        * @param $fileName
+        * @return boolean
+        */
+       public function hasFile($fileName) {
+               return $this->storage->hasFileInFolder($fileName, $this);
+       }
+
+       /**
+        * Checks if a folder exists in this folder.
+        *
+        * @param $name
+        * @return bool
+        */
+       public function hasFolder($name) {
+               return $this->storage->hasFolderInFolder($name, $this);
+       }
+
+       /**
+        * Check if a file operation (= action) is allowed on this folder
+        *
+        * @param       string  $action, can be read, write, delete
+        * @return boolean
+        */
+       public function checkActionPermission($action) {
+               return $this->getStorage()->checkFolderActionPermission($action, $this);
+       }
+
+       /**
+        * Updates the properties of this folder, e.g. after re-indexing or moving it.
+        *
+        * NOTE: This method should not be called from outside the File Abstraction Layer (FAL)!
+        *
+        * @param array $properties
+        * @return void
+        * @internal
+        */
+       public function updateProperties(array $properties) {
+                       // setting identifier and name to update values
+               if (isset($properties['identifier'])) {
+                       $this->identifier = $properties['identifier'];
+               }
+               if (isset($properties['name'])) {
+                       $this->name = $properties['name'];
+               }
+       }
+}
+
+?>
diff --git a/t3lib/file/ProcessedFile.php b/t3lib/file/ProcessedFile.php
new file mode 100644 (file)
index 0000000..c0751c5
--- /dev/null
@@ -0,0 +1,207 @@
+<?php
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2012 Benjamin Mack <benni@typo3.org>
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ * A copy is found in the textfile GPL.txt and important notices to the license
+ * from the author is found in LICENSE.txt distributed with these scripts.
+ *
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * Representation of a specific processing of a file.
+ *
+ * @author Benjamin Mack <benni@typo3.org>
+ * @package TYPO3
+ * @subpackage t3lib
+ */
+class t3lib_file_ProcessedFile extends t3lib_file_AbstractFile {
+       /*********************************************
+        * FILE PROCESSING CONTEXTS
+        *********************************************/
+
+       /**
+        * basic processing context to get a processed
+        * image with smaller width/height to render a preview
+        */
+       const CONTEXT_IMAGEPREVIEW = 'image.preview';
+
+       /**
+        * Processing context
+        *
+        * @var string
+        */
+       protected $context;
+
+       /**
+        * check if the file is processed
+        *
+        * @var boolean
+        */
+       protected $processed;
+
+       /**
+        * Processing configuration
+        *
+        * @var array
+        */
+       protected $processingConfiguration;
+
+       /**
+        * Reference to the original File object underlying this FileReference.
+        *
+        * @var t3lib_file_File
+        */
+       protected $originalFile;
+
+
+
+       /**
+        * Constructor for a file processing object. Should normally not be used directly, use the corresponding factory methods instead.
+        *
+        * @param t3lib_file_File $originalFile
+        * @param string $context
+        * @param array $processingConfiguration
+        */
+       public function __construct(t3lib_file_File $originalFile, $context, array $processingConfiguration) {
+               $this->originalFile = $originalFile;
+               $this->context = $context;
+               $this->processingConfiguration = $processingConfiguration;
+       }
+
+       /*******************************
+        * VARIOUS FILE PROPERTY GETTERS
+        ************************
+
+       /**
+        * Returns the Sha1 of this file
+        *
+        * @return string
+        */
+       public function calculateChecksum() {
+               return t3lib_div::shortMD5($this->originalFile->getUid() . $this->context . serialize($this->processingConfiguration));
+       }
+
+       /******************
+        * CONTENTS RELATED
+        ******************/
+
+       /**
+        * Replace the current file contents with the given string
+        *
+        * @param string $contents The contents to write to the file.
+        * @return t3lib_file_File The file object (allows chaining).
+        */
+       public function setContents($contents) {
+               throw new Exception('Setting contents not possible for processed file.', 1305438528);
+       }
+
+       /****************************************
+        * STORAGE AND MANAGEMENT RELATED METHDOS
+        ****************************************/
+
+       /**
+        * Returns TRUE if this file is indexed
+        *
+        * @return boolean
+        */
+       public function isIndexed() {
+               return FALSE;
+       }
+
+       /*****************
+        * SPECIAL METHODS
+        *****************/
+       /**
+        * Returns TRUE if this file is already processed.
+        *
+        * @return boolean
+        */
+       public function isProcessed() {
+               return $this->processed;
+       }
+
+       /**
+        * Called when the processed file is processed
+        *
+        * @param boolean $isProcessed
+        * @return void
+        */
+       public function setProcessed($isProcessed) {
+               $this->processed = (boolean) $isProcessed;
+
+                       // DB-query to insert the info
+               /** @var $processedFileRepository t3lib_file_Repository_ProcessedFileRepository */
+               $processedFileRepository = t3lib_div::makeInstance('t3lib_file_Repository_ProcessedFileRepository');
+               $processedFileRepository->add($this);
+       }
+
+       /**
+        * @return \t3lib_file_File
+        */
+       public function getOriginalFile() {
+               return $this->originalFile;
+       }
+
+       /**
+        * Updates properties of this object.
+        * This method is used to reconstitute settings from the
+        * database into this object after being intantiated.
+        *
+        * @param array $properties
+        */
+       public function updateProperties(array $properties) {
+               if ($properties['name']) {
+                       $this->name = $properties['name'];
+               }
+               if ($properties['identifier']) {
+                       $this->identifier = $properties['identifier'];
+               }
+               if (t3lib_utility_Math::canBeInterpretedAsInteger($properties['storage'])) {
+                       $this->setStorage($properties['storage']);
+               }
+               $this->properties = array_merge($this->properties, $properties);
+       }
+
+       /**
+        * basic array function for the DB update
+        * @return array
+        */
+       public function toArray() {
+               // @todo: define what we need here
+               return array(
+                       'storage' => $this->getStorage()->getUid(),
+                       'identifier' => $this->getIdentifier(),
+                       'name' => $this->getName(),
+                       'is_processed' => intval($this->processed),
+                       'checksum' => $this->calculateChecksum(),
+                       'context' => $this->context,
+                       'configuration' => serialize($this->processingConfiguration),
+                       'original' => $this->originalFile->getUid(),
+               );
+       }
+}
+
+if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/file/ProcessedFile.php'])) {
+       include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/file/ProcessedFile.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/file/Repository/AbstractRepository.php b/t3lib/file/Repository/AbstractRepository.php
new file mode 100644 (file)
index 0000000..ffb9337
--- /dev/null
@@ -0,0 +1,246 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Andreas Wolf <andreas.wolf@ikt-werk.de>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *  A copy is found in the textfile GPL.txt and important notices to the license
+ *  from the author is found in LICENSE.txt distributed with these scripts.
+ *
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * Abstract repository implementing the basic repository methods
+ *
+ * @author  Andreas Wolf <andreas.wolf@ikt-werk.de>
+ * @author  Ingmar Schlecht <ingmar@typo3.org>
+ * @package TYPO3
+ * @subpackage t3lib
+ */
+abstract class t3lib_file_Repository_AbstractRepository implements Tx_Extbase_Persistence_RepositoryInterface, t3lib_Singleton {
+
+       /**
+        * @var string
+        */
+       protected $table = '';
+
+       /**
+        * @var t3lib_file_Factory
+        */
+       protected $factory;
+
+       /**
+        * @var string
+        */
+       protected $typeField = '';
+
+       /**
+        * @var string
+        */
+       protected $type = '';
+
+       /**
+        * Creates this object.
+        */
+       public function __construct() {
+               $this->factory = t3lib_div::makeInstance('t3lib_file_Factory');
+       }
+
+       /**
+        * Adds an object to this repository.
+        *
+        * @param object $object The object to add
+        * @return void
+        * @api
+        */
+       public function add($object) {
+
+       }
+
+       /**
+        * Removes an object from this repository.
+        *
+        * @param object $object The object to remove
+        * @return void
+        * @api
+        */
+       public function remove($object) {
+
+       }
+
+       /**
+        * Replaces an object by another.
+        *
+        * @param object $existingObject The existing object
+        * @param object $newObject The new object
+        * @return void
+        * @api
+        */
+       public function replace($existingObject, $newObject) {
+
+       }
+
+       /**
+        * Replaces an existing object with the same identifier by the given object
+        *
+        * @param object $modifiedObject The modified object
+        * @api
+        */
+       public function update($modifiedObject) {
+
+       }
+
+       /**
+        * Returns all objects of this repository add()ed but not yet persisted to
+        * the storage layer.
+        *
+        * @return array An array of objects
+        */
+       public function getAddedObjects() {
+
+       }
+
+       /**
+        * Returns an array with objects remove()d from the repository that
+        * had been persisted to the storage layer before.
+        *
+        * @return array
+        */
+       public function getRemovedObjects() {
+
+       }
+
+       /**
+        * Returns all objects of this repository.
+        *
+        * @return array An array of objects, empty if no objects found
+        * @api
+        */
+       public function findAll() {
+               $itemList = array();
+
+               $whereClause = 'deleted = 0';
+               if ($this->type != '') {
+                       $whereClause .= ' AND ' . $this->typeField . ' = ' . $GLOBALS['TYPO3_DB']->fullQuoteStr($this->type, $this->table);
+               }
+
+               $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', $this->table, $whereClause);
+
+               while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
+                       $itemList[] = $this->createDomainObject($row);
+               }
+
+               return $itemList;
+       }
+
+       /**
+        * Creates an object managed by this repository.
+        *
+        * @abstract
+        * @param array $databaseRow
+        * @return object
+        */
+       abstract protected function createDomainObject(array $databaseRow);
+
+       /**
+        * Returns the total number objects of this repository.
+        *
+        * @return integer The object count
+        * @api
+        */
+       public function countAll() {
+
+       }
+
+       /**
+        * Removes all objects of this repository as if remove() was called for
+        * all of them.
+        *
+        * @return void
+        * @api
+        */
+       public function removeAll() {
+
+       }
+
+       /**
+        * Finds an object matching the given identifier.
+        *
+        * @param int $uid The identifier of the object to find
+        * @return object The matching object if found, otherwise NULL
+        * @api
+        */
+       public function findByUid($uid) {
+               if (!is_numeric($uid)) {
+                       throw new InvalidArgumentException("uid has to be numeric.", 1316779798);
+               }
+
+               $row = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow('*', $this->table, 'uid=' . intval($uid) . ' AND deleted=0');
+
+               if (count($row) == 0) {
+                       throw new RuntimeException("Could not find row with uid $uid in table $this->table.", 1314354065);
+               }
+
+               return $this->createDomainObject($row);
+       }
+
+       /**
+        * Sets the property names to order the result by per default.
+        * Expected like this:
+        * array(
+        *  'foo' => Tx_Extbase_Persistence_QueryInterface::ORDER_ASCENDING,
+        *  'bar' => Tx_Extbase_Persistence_QueryInterface::ORDER_DESCENDING
+        * )
+        *
+        * @param array $defaultOrderings The property names to order by
+        * @return void
+        * @api
+        */
+       public function setDefaultOrderings(array $defaultOrderings) {
+               throw new BadMethodCallException('Repository does not support the setDefaultOrderings() method.', 1313185906);
+       }
+
+       /**
+        * Sets the default query settings to be used in this repository
+        *
+        * @param Tx_Extbase_Persistence_QuerySettingsInterface $defaultQuerySettings The query settings to be used by default
+        * @return void
+        * @api
+        */
+       public function setDefaultQuerySettings(Tx_Extbase_Persistence_QuerySettingsInterface $defaultQuerySettings) {
+               throw new BadMethodCallException('Repository does not support the setDefaultQuerySettings() method.', 1313185907);
+       }
+
+       /**
+        * Returns a query for objects of this repository
+        *
+        * @return Tx_Extbase_Persistence_QueryInterface
+        * @api
+        */
+       public function createQuery() {
+               throw new BadMethodCallException('Repository does not support the createQuery() method.', 1313185908);
+       }
+}
+
+if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/file/Repository/AbstractRepository.php'])) {
+       include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/file/Repository/AbstractRepository.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/file/Repository/FileCollectionRepository.php b/t3lib/file/Repository/FileCollectionRepository.php
new file mode 100644 (file)
index 0000000..fad1109
--- /dev/null
@@ -0,0 +1,101 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011-2012 Andreas Wolf <andreas.wolf@ikt-werk.de>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *  A copy is found in the textfile GPL.txt and important notices to the license
+ *  from the author is found in LICENSE.txt distributed with these scripts.
+ *
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * Repository for accessing the collections stored in the database
+ *
+ * @author Andreas Wolf <andreas.wolf@ikt-werk.de>
+ * @author Ingmar Schlecht <ingmar@typo3.org>
+ * @package TYPO3
+ * @subpackage t3lib
+ */
+class t3lib_file_Repository_FileCollectionRepository extends t3lib_collection_RecordCollectionRepository {
+       /**
+        * @var string
+        */
+       protected $table = 'sys_file_collection';
+
+       /**
+        * @var string
+        */
+       protected $typeField = 'type';
+
+       /**
+        * Finds a record collection by uid.
+        *
+        * @param integer $uid The uid to be looked up
+        * @return NULL|t3lib_file_Collection_AbstractFileCollection
+        */
+       public function findByUid($uid) {
+               $object = parent::findByUid($uid);
+
+               if ($object === NULL) {
+                       throw new RuntimeException(
+                               'Could not find row with uid ' . $uid . ' in table ' . $this->table,
+                               1314354065
+                       );
+               }
+
+               return $object;
+       }
+
+       /**
+        * Finds record collection by type.
+        *
+        * @param string $type The type to be looked up
+        * @return NULL|t3lib_file_Collection_AbstractFileCollection[]
+        */
+       public function findByType($type) {
+               return parent::findByType($type);
+       }
+
+       /**
+        * Creates a record collection domain object.
+        *
+        * @param $record Database record to be reconsituted
+        * @return t3lib_file_Collection_AbstractFileCollection
+        */
+       protected function createDomainObject(array $record) {
+               return $this->getFileFactory()->createCollectionObject($record);
+       }
+
+       /**
+        * Gets the file factory.
+        *
+        * @return t3lib_file_Factory
+        */
+       protected function getFileFactory() {
+               return t3lib_div::makeInstance('t3lib_file_Factory');
+       }
+}
+
+if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/file/Repository/FileCollectionRepository.php'])) {
+       include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/file/Repository/FileCollectionRepository.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/file/Repository/FileRepository.php b/t3lib/file/Repository/FileRepository.php
new file mode 100644 (file)
index 0000000..4b706d2
--- /dev/null
@@ -0,0 +1,300 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Andreas Wolf <andreas.wolf@ikt-werk.de>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *  A copy is found in the textfile GPL.txt and important notices to the license
+ *  from the author is found in LICENSE.txt distributed with these scripts.
+ *
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * Repository for accessing files
+ * it also serves as the public API for the indexing part of files in general
+ *
+ * @author  Andreas Wolf <andreas.wolf@ikt-werk.de>
+ * @author  Ingmar Schlecht <ingmar@typo3.org>
+ * @package    TYPO3
+ * @subpackage t3lib
+ */
+class t3lib_file_Repository_FileRepository extends t3lib_file_Repository_AbstractRepository {
+
+       /**
+        * The main object type of this class. In some cases (fileReference) this repository can also return
+        * FileReference objects, implementing the common FileInterface.
+        *
+        * @var string
+        */
+       protected $objectType = 't3lib_file_File';
+
+       /**
+        * Main File object storage table. Note that this repository also works on the sys_file_reference table
+        * when returning FileReference objects.
+        *
+        * @var string
+        */
+       protected $table = 'sys_file';
+
+       /**
+        * @var t3lib_file_Service_IndexerService
+        */
+       protected $indexerService = NULL;
+
+       /**
+        * Internal function to retrieve the indexer service,
+        * if it does not exist, an instance will be created
+        *
+        * @return t3lib_file_Service_IndexerService
+        */
+       protected function getIndexerService() {
+               if ($this->indexerService === NULL) {
+                       $this->indexerService = t3lib_div::makeInstance('t3lib_file_Service_IndexerService');
+               }
+
+               return $this->indexerService;
+       }
+
+       /**
+        * Creates an object managed by this repository.
+        *
+        * @param array $databaseRow
+        * @return t3lib_file_File
+        */
+       protected function createDomainObject(array $databaseRow) {
+               return $this->factory->getFileObject($databaseRow['uid'], $databaseRow);
+       }
+
+       /**
+        * Index a file object given as parameter
+        * @TODO: Check if the indexing functions really belong into the repository and shouldn't be part of an
+        * @TODO: indexing service, right now it's fine that way as this function will serve as the public API
+        *
+        * @param t3lib_file_File $fileObject
+        * @return array The indexed file data
+        */
+       public function addToIndex(t3lib_file_File $fileObject) {
+               return $this->getIndexerService()->indexFile($fileObject, FALSE);
+       }
+
+       /**
+        * Checks the index status of a file and returns FALSE if the file is not indexed, the uid otherwise.
+        * @TODO: Check if the indexing functions really belong into the repository and shouldn't be part of an
+        * @TODO: indexing service, right now it's fine that way as this function will serve as the public API
+        *
+        * @param t3lib_file_File $fileObject
+        * @return bool|int
+        */
+       public function getFileIndexStatus(t3lib_file_File $fileObject) {
+               $mount = $fileObject->getStorage()->getUid();
+               $identifier = $fileObject->getIdentifier();
+
+               $row = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow('uid,storage,identifier', $this->table,
+                       sprintf('storage=%u AND identifier=%s', $mount, $GLOBALS['TYPO3_DB']->fullQuoteStr($identifier, $this->table))
+               );
+
+               if (!$row) {
+                       return FALSE;
+               } else {
+                       return $row['uid'];
+               }
+       }
+
+       /**
+        * Returns an index record of a file, or FALSE if the file is not indexed.
+        *
+        * @param t3lib_file_File $fileObject
+        * @return bool|array
+        */
+       public function getFileIndexRecord(t3lib_file_File $fileObject) {
+               $mount = $fileObject->getStorage()->getUid();
+               $identifier = $fileObject->getIdentifier();
+
+               $row = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow('*', $this->table,
+                       sprintf('storage=%u AND identifier=%s', $mount, $GLOBALS['TYPO3_DB']->fullQuoteStr($identifier, $this->table))
+               );
+
+               if (!$row) {
+                       return FALSE;
+               } else {
+                       return $row;
+               }
+       }
+
+       /**
+        * Returns the index-data of all files within that folder
+        *
+        * @param t3lib_file_Folder $folder
+        * @return array
+        */
+       public function getFileIndexRecordsForFolder(t3lib_file_Folder $folder) {
+               $identifier = $folder->getIdentifier();
+               $storage = $folder->getStorage()->getUid();
+
+               $rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('*', $this->table,
+                       sprintf('storage=%u AND identifier LIKE "%s" AND NOT identifier LIKE "%s"',
+                               $storage,
+                               $GLOBALS['TYPO3_DB']->escapeStrForLike($identifier, $this->table) . '%',
+                               $GLOBALS['TYPO3_DB']->escapeStrForLike($identifier, $this->table) . '%/%'
+                       ),
+                       '', '', '', 'identifier'
+               );
+
+               return (array)$rows;
+       }
+
+       /**
+        * Returns all files with the corresponding SHA-1 hash. This is queried against the database, so only indexed files
+        * will be found
+        *
+        * @param string $hash A SHA1 hash of a file
+        * @return array
+        */
+       public function findBySha1Hash($hash) {
+               if (preg_match('/[^a-f0-9]*/i', $hash)) {
+                       // TODO does not validate -> throw exception; also check for hash length
+               }
+
+               $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', $this->table,
+                       'sha1=' . $GLOBALS['TYPO3_DB']->fullQuoteStr($hash, $this->table));
+
+               $objects = array();
+
+               if ($res) {
+                       while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
+                               $objects[] = $this->createDomainObject($row);
+                       }
+
+                       $GLOBALS['TYPO3_DB']->sql_free_result($res);
+               }
+
+               return $objects;
+       }
+
+
+       /**
+        * Find FileReference objects by relation to other records
+        *
+        * @param int $tableName Table name of the related record
+        * @param int $fieldName Field name of the related record
+        * @param int $uid The UID of the related record
+        * @return array An array of objects, empty if no objects found
+        * @api
+        */
+       public function findByRelation($tableName, $fieldName, $uid) {
+               $itemList = array();
+
+               if (!is_numeric($uid)) {
+                       throw new InvalidArgumentException("uid of related record has to be numeric.", 1316789798);
+               }
+
+               $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
+                       '*',
+                       'sys_file_reference',
+                       'tablenames=' . $GLOBALS['TYPO3_DB']->fullQuoteStr($tableName, 'sys_file_reference') .
+                               ' AND deleted=0' .
+                               ' AND hidden=0' .
+                               ' AND uid_foreign=' . intval($uid) .
+                               ' AND fieldname=' . $GLOBALS['TYPO3_DB']->fullQuoteStr($fieldName, 'sys_file_reference'),
+                       '',
+                       'sorting_foreign'
+               );
+
+               if ($res) {
+                       while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
+                               $itemList[] = $this->createFileReferenceObject($row);
+                       }
+
+                       $GLOBALS['TYPO3_DB']->sql_free_result($res);
+               }
+
+               return $itemList;
+       }
+
+       /**
+        * Find FileReference objects by uid
+        *
+        * @param integer $uid The UID of the sys_file_reference record
+        * @return t3lib_file_FileReference|boolean
+        * @api
+        */
+       public function findFileReferenceByUid($uid) {
+               $fileReferenceObject = FALSE;
+
+               if (!is_numeric($uid)) {
+                       throw new InvalidArgumentException("uid of record has to be numeric.", 1316889798);
+               }
+
+               $row = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow(
+                       '*',
+                       'sys_file_reference',
+                       'uid=' . $uid .
+                               ' AND deleted=0'.
+                               ' AND hidden=0'
+               );
+
+               if ($row !== NULL) {
+                       $fileReferenceObject = $this->createFileReferenceObject($row);
+               }
+
+               return $fileReferenceObject;
+       }
+
+       /**
+        * Updates an existing file object in the database
+        *
+        * @param t3lib_file_File $modifiedObject
+        * @return void
+        */
+       public function update($modifiedObject) {
+               // TODO check if $modifiedObject is an instance of t3lib_file_File
+               // TODO check if $modifiedObject is indexed
+
+               $changedProperties = $modifiedObject->getUpdatedProperties();
+               $properties = $modifiedObject->getProperties();
+
+               $updateFields = array();
+               foreach ($changedProperties as $propertyName) {
+                       $updateFields[$propertyName] = $properties[$propertyName];
+               }
+
+               $GLOBALS['TYPO3_DB']->exec_UPDATEquery('sys_file',
+                       'uid=' . $modifiedObject->getUid(),
+                       $updateFields
+               );
+       }
+
+       /**
+        * Creates a FileReference object
+        *
+        * @param array $databaseRow
+        * @return t3lib_file_FileReference
+        */
+       protected function createFileReferenceObject(array $databaseRow) {
+               return $this->factory->getFileReferenceObject($databaseRow['uid'], $databaseRow);
+       }
+
+}
+
+if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/file/Repository/FileRepository.php'])) {
+       include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/file/Repository/FileRepository.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/file/Repository/ProcessedFileRepository.php b/t3lib/file/Repository/ProcessedFileRepository.php
new file mode 100644 (file)
index 0000000..21a2adb
--- /dev/null
@@ -0,0 +1,111 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2012 Benjamin Mack <benni@typo3.org>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *  A copy is found in the textfile GPL.txt and important notices to the license
+ *  from the author is found in LICENSE.txt distributed with these scripts.
+ *
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * Repository for accessing files
+ * it also serves as the public API for the indexing part of files in general
+ *
+ * @author  Benjamin Mack <benni@typo3.org>
+ * @author  Ingmar Schlecht <ingmar@typo3.org>
+ * @package    TYPO3
+ * @subpackage t3lib
+ */
+class t3lib_file_Repository_ProcessedFileRepository extends t3lib_file_Repository_AbstractRepository {
+
+       /**
+        * The main object type of this class. In some cases (fileReference) this repository can also return
+        * FileReference objects, implementing the common FileInterface.
+        *
+        * @var string
+        */
+       protected $objectType = 't3lib_file_ProcessedFile';
+
+       /**
+        * Main File object storage table. Note that this repository also works on the sys_file_reference table
+        * when returning FileReference objects.
+        *
+        * @var string
+        */
+       protected $table = 'sys_file_processedfile';
+
+       /**
+        * Creates an object managed by this repository.
+        *
+        * @param array $databaseRow
+        * @return t3lib_file_File
+        */
+       protected function createDomainObject(array $databaseRow) {
+               return $this->factory->getFileObject($databaseRow['uid'], $databaseRow);
+       }
+
+       /**
+        * Loads index-data into processedFileObject
+        *
+        * @param t3lib_file_ProcessedFile $processedFileObject
+        * @return boolean
+        */
+       public function populateDataOfProcessedFileObject(t3lib_file_ProcessedFile $processedFileObject) {
+
+               /** @var $GLOBALS['TYPO3_DB'] t3lib_DB */
+               $recordData = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow(
+                       '*',
+                       $this->table,
+                       'original=' . intval($processedFileObject->getOriginalFile()->getUid())
+                               . ' AND checksum=' . $GLOBALS['TYPO3_DB']->fullQuoteStr($processedFileObject->calculateChecksum(), $this->table)
+                               . ' AND deleted=0');
+
+                       // update the properties if the data was found
+               if (is_array($recordData)) {
+                       $processedFileObject->updateProperties($recordData);
+                       return TRUE;
+               } else {
+                       return FALSE;
+               }
+       }
+
+       /**
+        * Updates an existing file object in the database
+        *
+        * @param t3lib_file_ProcessedFile $processedFile
+        * @return void
+        */
+       public function add($processedFile) {
+               $insertFields = $processedFile->toArray();
+               $insertFields['crdate'] = $insertFields['tstamp'] = time();
+
+               // @todo: make sure that the toArray method only contains fields that are in the table
+               $GLOBALS['TYPO3_DB']->exec_INSERTquery($this->table, $insertFields);
+       }
+}
+
+
+if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/file/Repository/ProcessedFileRepository.php'])) {
+       include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/file/Repository/ProcessedFileRepository.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/file/Repository/StorageRepository.php b/t3lib/file/Repository/StorageRepository.php
new file mode 100644 (file)
index 0000000..d03b287
--- /dev/null
@@ -0,0 +1,141 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Andreas Wolf <andreas.wolf@ikt-werk.de>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *  A copy is found in the textfile GPL.txt and important notices to the license
+ *  from the author is found in LICENSE.txt distributed with these scripts.
+ *
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * Repository for accessing the file mounts
+ *
+ * @author Andreas Wolf <andreas.wolf@ikt-werk.de>
+ * @author Ingmar Schlecht <ingmar@typo3.org>
+ * @package TYPO3
+ * @subpackage t3lib
+ */
+class t3lib_file_Repository_StorageRepository extends t3lib_file_Repository_AbstractRepository {
+
+       /**
+        * @var string
+        */
+       protected $objectType = 't3lib_file_Storage';
+
+       /**
+        * @var string
+        */
+       protected $table = 'sys_file_storage';
+
+       /**
+        * @var string
+        */
+       protected $typeField = 'type';
+
+       /**
+        * Finds storages by type.
+        *
+        * @param string $storageType
+        */
+       public function findByStorageType($storageType) {
+               // @todo Needs to be implemented
+       }
+
+       /**
+        * Returns a list of mountpoints that are available in the VFS.
+        * In case no storage exists this automatically created a storage for fileadmin/
+        *
+        * @return t3lib_file_Storage[]
+        */
+       public function findAll() {
+               $storageObjects = parent::findAll();
+
+               if (count($storageObjects) === 0) {
+                       $this->createLocalStorage(
+                               'fileadmin/ (auto-created)',
+                               $GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir'],
+                               'relative',
+                               'This is the local fileadmin/ directory. This storage mount has been created automatically by TYPO3.'
+                       );
+                       $storageObjects = parent::findAll();
+               }
+
+               return $storageObjects;
+       }
+
+       /**
+        * Used to create the initial local storage base e.g. for the fileadmin/ directory.
+        *
+        * @param string $name
+        * @param string $basePath
+        * @param string $pathType
+        * @param string $description
+        * @return mixed
+        */
+       public function createLocalStorage($name, $basePath, $pathType, $description = '') {
+               $field_values = array(
+                       'pid' => 0,
+                       'tstamp' => time(),
+                       'crdate' => time(),
+                       'name' => $name,
+                       'description' => $description,
+                       'driver' => 'Local',
+                       'configuration' => '<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+                               <T3FlexForms>
+                                       <data>
+                                               <sheet index="sDEF">
+                                                       <language index="lDEF">
+                                                               <field index="basePath">
+                                                                       <value index="vDEF">' . rtrim($basePath, '/') . '/</value>
+                                                               </field>
+                                                               <field index="pathType">
+                                                                       <value index="vDEF">' . $pathType . '</value>
+                                                               </field>
+                                                       </language>
+                                               </sheet>
+                                       </data>
+                               </T3FlexForms>',
+                       'is_browsable' => 1,
+                       'is_public' => 1,
+                       'is_writable' => 1
+               );
+
+               $GLOBALS['TYPO3_DB']->exec_INSERTquery('sys_file_storage', $field_values);
+               return $GLOBALS['TYPO3_DB']->sql_insert_id();
+       }
+
+       /**
+        * Creates an object managed by this repository.
+        *
+        * @param array $databaseRow
+        * @return t3lib_file_Storage
+        */
+       protected function createDomainObject(array $databaseRow) {
+               return $this->factory->getStorageObject($databaseRow['uid'], $databaseRow);
+       }
+}
+
+if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/file/Repository/StorageRepository.php'])) {
+       include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/file/Repository/StorageRepository.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/file/ResourceInterface.php b/t3lib/file/ResourceInterface.php
new file mode 100644 (file)
index 0000000..18b2d37
--- /dev/null
@@ -0,0 +1,61 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2012 Ingmar Schlecht <ingmar@typo3.org>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *  A copy is found in the textfile GPL.txt and important notices to the license
+ *  from the author is found in LICENSE.txt distributed with these scripts.
+ *
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * FileResourceInterface
+ *
+ * @author  Ingmar Schlecht <ingmar@typo3.org>
+ * @package  TYPO3
+ * @subpackage  t3lib
+ */
+interface t3lib_file_ResourceInterface {
+
+       /**
+        * Returns the identifier of this file
+        *
+        * @return string
+        */
+       public function getIdentifier();
+
+       /**
+        * Returns the name of this file
+        *
+        * @return string
+        */
+       public function getName();
+
+       /**
+        * Get the storage this file is located in
+        *
+        * @return t3lib_file_Storage
+        */
+       public function getStorage();
+
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/file/Service/BackwardsCompatibility/TslibContentAdapterService.php b/t3lib/file/Service/BackwardsCompatibility/TslibContentAdapterService.php
new file mode 100644 (file)
index 0000000..d5efbe3
--- /dev/null
@@ -0,0 +1,120 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Ingmar Schlecht <ingmar@typo3.org>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * Tslib content adapter to modify $row array ($cObj->data[]) for backwards compatibility
+ *
+ * @package     TYPO3
+ * @author Ingmar Schlecht <ingmar@typo3.org>
+ * @license     http://www.gnu.org/copyleft/gpl.html
+ */
+class t3lib_file_Service_BackwardsCompatibility_TslibContentAdapterService {
+
+       /**
+        * The name of the table
+        *
+        * @var string
+        */
+       protected static $migrateFields = array(
+               'tt_content' => array(
+                       'image' => array(
+                               'paths' => 'image',
+                               'titleTexts' => 'titleText',
+                               'captions' => 'imagecaption',
+                               'links' => 'image_link',
+                               'alternativeTexts' => 'altText',
+                               'sysFileUids' => 'sysFileUids', // additional fields for the UIDs
+                       ),
+                       'media' => array(
+                               'paths' => 'media',
+                               'captions' => 'imagecaption',
+                       ),
+               ),
+               'pages' => array(
+                       'media' => array(
+                               'paths' => 'media'
+                       ),
+               ),
+       );
+
+       /**
+        * Modifies the DB row in the CONTENT cObj of tslib_content for supplying backwards compatibility
+        * for some file fields which have switched to using the new File API instead of the old uploads/
+        * folder for storing files.
+        *
+        * This method is called by the render() method of tslib_content_Content.
+        *
+        * @param $row
+        * @param $table
+        *
+        * @return      void
+        */
+       public static function modifyDBRow(&$row, $table) {
+               if (array_key_exists($table, static::$migrateFields)) {
+                       foreach (static::$migrateFields[$table] as $migrateFieldName => $oldFieldNames) {
+                               if (isset($row[$migrateFieldName])) {
+                                       /** @var $fileRepository t3lib_file_Repository_FileRepository */
+                                       $fileRepository = t3lib_div::makeInstance('t3lib_file_Repository_FileRepository');
+                                       $files = $fileRepository->findByRelation($table, $migrateFieldName, $row['uid']);
+                                       $fileFieldContents = array(
+                                               'paths' => array(),
+                                               'titleTexts' => array(),
+                                               'captions' => array(),
+                                               'links' => array(),
+                                               'alternativeTexts' => array(),
+                                               'sysFileUids' => array()
+                                       );
+                                       foreach ($files as $file) {
+                                               /** @var $file t3lib_file_FileReference */
+                                               $fileFieldContents['paths'][] = '../../' . $file->getPublicUrl();
+                                               $fileFieldContents['titleTexts'][] = $file->getProperty('title');
+                                               $fileFieldContents['captions'][] = $file->getProperty('description');
+                                               $fileFieldContents['links'][] = $file->getProperty('link');
+                                               $fileFieldContents['alternativeTexts'][] = $file->getProperty('alternative');
+                                               $fileFieldContents['sysFileUids'][] = $file->getUid();
+                                       }
+                                       foreach ($oldFieldNames as $oldFieldType => $oldFieldName) {
+                                                       // For paths, make comma separated list
+                                               if ($oldFieldType === 'paths') {
+                                                       $fieldContents = implode(',', $fileFieldContents[$oldFieldType]);
+                                               } else {
+                                                       // For all other fields, separate by newline
+                                                       $fieldContents = implode(chr(10), $fileFieldContents[$oldFieldType]);
+                                               }
+                                               if($fieldContents) {
+                                                       $row[$oldFieldName] = $fieldContents;
+                                               }
+                                       }
+                                       if (count($files)>0) {
+                                       } elseif ($row['image'] > 0) {
+                                               throw new Exception('inconsistent count field in '.$table.'.'.$migrateFieldName);
+                                       }
+                               }
+                       }
+               }
+       }
+
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/file/Service/FileProcessingService.php b/t3lib/file/Service/FileProcessingService.php
new file mode 100644 (file)
index 0000000..5e8f40d
--- /dev/null
@@ -0,0 +1,242 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2012 Oliver Hader <oliver.hader@typo3.org>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *  A copy is found in the textfile GPL.txt and important notices to the license
+ *  from the author is found in LICENSE.txt distributed with these scripts.
+ *
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * File processing service
+ *
+ * @author Oliver Hader <oliver.hader@typo3.org>
+ * @package TYPO3
+ * @subpackage t3lib
+ */
+class t3lib_file_Service_FileProcessingService {
+
+       /**
+        * @var t3lib_file_Storage
+        */
+       protected $storage;
+
+       /**
+        * @var t3lib_file_Driver_AbstractDriver
+        */
+       protected $driver;
+
+       /**
+        * Creates this object.
+        *
+        * @param t3lib_file_Storage $storage
+        * @param t3lib_file_Driver_AbstractDriver $driver
+        */
+       public function __construct(t3lib_file_Storage $storage, t3lib_file_Driver_AbstractDriver $driver) {
+               $this->storage = $storage;
+               $this->driver = $driver;
+       }
+
+       /**
+        * Processes the file.
+        *
+        * @param t3lib_file_ProcessedFile $processedFile
+        * @param t3lib_file_FileInterface $file
+        * @param string $context
+        * @param array $configuration
+        * @return t3lib_file_ProcessedFile
+        */
+       public function process(t3lib_file_ProcessedFile $processedFile, t3lib_file_FileInterface $file, $context, array $configuration = array()) {
+               switch ($context) {
+                       case $processedFile::CONTEXT_IMAGEPREVIEW:
+                               $this->processImagePreview($processedFile, $file, $configuration);
+                               break;
+                       default:
+                               throw new RuntimeException('Unknown processing context ' . $context);
+               }
+               return $processedFile;
+       }
+
+
+       /**
+        * This method actually does the processing of files locally
+        *
+        * takes the original file (on remote storages this will be fetched from the remote server)
+        * does the IM magic on the local server by creating a temporary typo3temp/ file
+        * copies the typo3temp/ file to the processingfolder of the target storage
+        * removes the typo3temp/ file
+        *
+        * @param t3lib_file_ProcessedFile $processedFile
+        * @param t3lib_file_FileInterface $file
+        * @param array $configuration
+        * @return string
+        */
+       protected function processImagePreview(t3lib_file_ProcessedFile $processedFile, t3lib_file_FileInterface $file, array $configuration) {
+
+                       // merge custom configuration with default configuration
+               $configuration = array_merge(
+                       array('width' => 64, 'height' => 64),
+                       $configuration
+               );
+
+               $configuration['width'] = t3lib_utility_Math::forceIntegerInRange($configuration['width'], 1, 1000);
+               $configuration['height'] = t3lib_utility_Math::forceIntegerInRange($configuration['height'], 1, 1000);
+
+               $originalFileName = $file->getForLocalProcessing(FALSE);
+
+                       // create a temporary file in typo3temp/
+               if ($file->getExtension() == 'jpg') {
+                       $targetFileExtension = '.jpg';
+               } else {
+                       $targetFileExtension = '.png';
+               }
+
+               $targetFolder = $this->storage->getProcessingFolder();
+               $targetFileName = 'preview_' . $processedFile->calculateChecksum() . $targetFileExtension;
+
+                       // do the actual processing
+               if (!$targetFolder->hasFile($targetFileName)) {
+                               // create the thumb filename in typo3temp/preview_....jpg
+                       $temporaryFileName = t3lib_div::tempnam('preview_') . $targetFileExtension;
+
+                               // Check file extension
+                       if ($file->getType() != $file::FILETYPE_IMAGE && !t3lib_div::inList($GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'], $file->getExtension())) {
+                               // create a default image
+                               $this->getTemporaryImageWithText($temporaryFileName, 'Not imagefile!', 'No ext!', $file->getName());
+                       } else {
+                                       // create the temporary file
+                               if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['im']) {
+                                       $parameters = '-sample ' . $configuration['width'] . 'x' . $configuration['height'] .  ' ' . $this->wrapFileName($originalFileName) . '[0] ' . $this->wrapFileName($temporaryFileName);
+                                       $cmd = t3lib_div::imageMagickCommand('convert', $parameters);
+                                       t3lib_utility_Command::exec($cmd);
+                                       if (!file_exists($temporaryFileName)) {
+                                                       // create a error gif
+                                               $this->getTemporaryImageWithText($temporaryFileName, 'No thumb','generated!', $file->getName());
+                                       }
+                               }
+
+                       }
+
+                               // everything worked out fine
+                       if (file_exists($temporaryFileName)) {
+                               t3lib_div::fixPermissions($temporaryFileName);
+
+                                       // copy the temporary file to the processedFolder
+                                       // this is done here, as the driver can do this without worrying
+                                       // about existing ProcessedFile objects
+                                       // or permissions in the storage
+
+                                       // for "remote" storages this means "uploading" the file to the storage again
+                                       // for the virtual storage, it is merely a thing of "copying a file from typo3temp/ to typo3temp/_processed_"
+                               $this->driver->addFile($temporaryFileName, $targetFolder, $targetFileName, $processedFile);
+                               $processedFile->setProcessed(TRUE);
+
+                                       // remove the temporary file as it's not needed anymore
+                               t3lib_div::unlink_tempfile($temporaryFileName);
+                       }
+               }
+       }
+
+
+       protected function processFilePreview() {
+               // if jpg => image preview
+               // if font => font preview
+               // if other => icon
+       }
+
+
+
+       /**
+        * Escapes a file name so it can safely be used on the command line.
+        *
+        * @param string $inputName filename to safeguard, must not be empty
+        * @return string $inputName escaped as needed
+        */
+       protected function wrapFileName($inputName) {
+               if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['UTF8filesystem']) {
+                       $currentLocale = setlocale(LC_CTYPE, 0);
+                       setlocale(LC_CTYPE, $GLOBALS['TYPO3_CONF_VARS']['SYS']['systemLocale']);
+
+                       $escapedInputName = escapeshellarg($inputName);
+
+                       setlocale(LC_CTYPE, $currentLocale);
+               } else {
+                       $escapedInputName = escapeshellarg($inputName);
+               }
+               return $escapedInputName;
+       }
+
+       /**
+        * Creates error image based on gfx/notfound_thumb.png
+        * Requires GD lib enabled, otherwise it will exit with the three textstrings outputted as text.
+        * Outputs the image stream to browser and exits!
+        *
+        * @param       string          Text line 1
+        * @param       string          Text line 2
+        * @param       string          Text line 3
+        * @return      void
+        */
+       protected function getTemporaryImageWithText($filename, $textline1, $textline2, $textline3) {
+               if (!$GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib']) {
+                       throw new RuntimeException(
+                               'TYPO3 Fatal Error: No gdlib. ' . $textline1 . ' ' . $textline2 . ' ' . $textline3,
+                               1270853952
+                       );
+               }
+
+                       // Creates the basis for the error image
+               if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib_png']) {
+                       $im = imagecreatefrompng(PATH_typo3 . 'gfx/notfound_thumb.png');
+               } else {
+                       $im = imagecreatefromgif (PATH_typo3 . 'gfx/notfound_thumb.gif');
+               }
+
+                       // Sets background color and print color.
+               $white = imageColorAllocate($im, 255, 255, 255);
+               $black = imageColorAllocate($im, 0, 0, 0);
+
+                       // Prints the text strings with the build-in font functions of GD
+               $x=0;
+               $font=0;
+               if ($textline1) {
+                       imagefilledrectangle($im, $x, 9, 56, 16, $white);
+                       imageString($im, $font, $x, 9, $textline1, $black);
+               }
+               if ($textline2) {
+                       imagefilledrectangle($im, $x, 19, 56, 26, $white);
+                       imageString($im, $font, $x, 19, $textline2, $black);
+               }
+               if ($textline3) {
+                       imagefilledrectangle($im, $x, 29, 56, 36, $white);
+                       imageString($im, $font, $x, 29, substr($textline3, -14), $black);
+               }
+
+                       // Outputting the image stream and exit
+               if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib_png']) {
+                       imagePng($im, $filename);
+               } else {
+                       imageGif ($im, $filename);
+               }
+       }
+
+}
+?>
\ No newline at end of file
diff --git a/t3lib/file/Service/ImageProcessingService.php b/t3lib/file/Service/ImageProcessingService.php
new file mode 100644 (file)
index 0000000..c368b57
--- /dev/null
@@ -0,0 +1,313 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Andreas Wolf <andreas.wolf@ikt-werk.de>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *  A copy is found in the textfile GPL.txt and important notices to the license
+ *  from the author is found in LICENSE.txt distributed with these scripts.
+ *
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * Thumbnail service
+ *
+ * @author Andreas Wolf <andreas.wolf@ikt-werk.de>
+ * @package TYPO3
+ * @subpackage t3lib
+ */
+// TODO should this be a singleton?
+class t3lib_file_Service_ImageProcessingService {
+
+       /**
+        * Renders the actual image
+        *
+        * @param tslib_cObj $contentObject
+        * @param $file
+        * @param array $fileConfiguration
+        * @return array
+        */
+       public function getImgResource(tslib_cObj $contentObject, $file, array $fileConfiguration) {
+               if ($fileConfiguration['import.']) {
+                       $ifile = $contentObject->stdWrap('', $fileConfiguration['import.']);
+                       if ($ifile) {
+                               $file = $fileConfiguration['import'] . $ifile;
+                       }
+               }
+               if (t3lib_utility_Math::canBeInterpretedAsInteger($file)) {
+                       $file = t3lib_div::makeInstance('t3lib_file_Factory')->getFileObject($file);
+               }
+
+               if ($file instanceof t3lib_file_FileInterface) {
+                       $theImage = $file->getForLocalProcessing(FALSE);
+               } else {
+                       $file = t3lib_div::resolveBackPath($file); // clean ../ sections of the path and resolve to proper string. This is necessary for the t3lib_file_Service_BackwardsCompatibility_TslibContentAdapterService to work.
+
+                       $theImage = $GLOBALS['TSFE']->tmpl->getFileName($file);
+                       if (!$theImage) {
+                               return array();
+                       }
+               }
+
+               $fileConfiguration = $this->processFileConfiguration($fileConfiguration, $contentObject);
+
+               $maskArray = $fileConfiguration['m.'];
+               $maskImages = array();
+               if (is_array($maskArray)) { // Must render mask images and include in hash-calculating - else we cannot be sure the filename is unique for the setup!
+                       $maskImages['m_mask'] = $this->getImgResource($contentObject, $maskArray['mask'], $maskArray['mask.']);
+                       $maskImages['m_bgImg'] = $this->getImgResource($contentObject, $maskArray['bgImg'], $maskArray['bgImg.']);
+                       $maskImages['m_bottomImg'] = $this->getImgResource($contentObject, $maskArray['bottomImg'], $maskArray['bottomImg.']);
+                       $maskImages['m_bottomImg_mask'] = $this->getImgResource($contentObject, $maskArray['bottomImg_mask'], $maskArray['bottomImg_mask.']);
+               }
+
+                       // TODO use t3lib_file_FileInterface here
+               if ($file instanceof t3lib_file_FileReference) {
+                       $hash = $file->getOriginalFile()->calculateChecksum();
+               } else {
+                       $hash = t3lib_div::shortMD5($theImage . serialize($fileConfiguration) . serialize($maskImages));
+               }
+
+               if (isset($GLOBALS['TSFE']->tmpl->fileCache[$hash])) {
+                       return $GLOBALS['TSFE']->tmpl->fileCache[$hash];
+               }
+
+               /** @var $gifCreator tslib_gifbuilder */
+               $gifCreator = t3lib_div::makeInstance('tslib_gifbuilder');
+               $gifCreator->init();
+
+               if ($GLOBALS['TSFE']->config['config']['meaningfulTempFilePrefix']) {
+                       $filename = basename($theImage);
+                               // remove extension
+                       $filename = substr($filename, 0, strrpos($filename, '.'));
+                       $tempFilePrefixLength = intval($GLOBALS['TSFE']->config['config']['meaningfulTempFilePrefix']);
+                       if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['UTF8filesystem']) {
+                                       /** @var $t3libCsInstance t3lib_cs */
+                               $t3libCsInstance = t3lib_div::makeInstance('t3lib_cs');
+                               $filenamePrefix = $t3libCsInstance->substr('utf-8', $filename, 0, $tempFilePrefixLength);
+                       } else {
+                                       // strip everything non-ascii
+                               $filename = preg_replace('/[^A-Za-z0-9_-]/', '', trim($filename));
+                               $filenamePrefix = substr($filename, 0, $tempFilePrefixLength);
+                       }
+                       $gifCreator->filenamePrefix = $filenamePrefix . '_';
+                       unset($filename);
+               }
+
+               if ($fileConfiguration['sample']) {
+                       $gifCreator->scalecmd = '-sample'