[TASK] Switch to PSR-2
authorAndreas Wolf <andreas.wolf@typo3.org>
Thu, 5 Nov 2015 14:37:59 +0000 (15:37 +0100)
committerAndreas Wolf <andreas.wolf@typo3.org>
Thu, 5 Nov 2015 14:38:45 +0000 (15:38 +0100)
14 files changed:
Classes/Backend/StatusReport.php
Classes/Backend/TceMainHook.php
Classes/Dav/CachingWebDavFrontend.php
Classes/Dav/WebDavClient.php
Classes/Dav/WebDavFrontend.php
Classes/Driver/WebDavDriver.php
Classes/Utility/EncryptionUtility.php
Classes/Utility/UrlTools.php
Tests/Backend/TceMainHookTest.php
Tests/Driver/WebDavDriverTest.php
Tests/Utility/EncryptionTest.php
Tests/Utility/UrlToolsTest.php
ext_emconf.php
ext_localconf.php

index 6ea715d..f0250a6 100644 (file)
@@ -27,24 +27,28 @@ namespace TYPO3\FalWebdav\Backend;
  *  This copyright notice MUST APPEAR in all copies of the script!
  ***************************************************************/
 
-class StatusReport implements \TYPO3\CMS\Reports\StatusProviderInterface {
-       /**
-        * Returns the status of an extension or (sub)system
-        *
-        * @return array An array of tx_reports_reports_status_Status objects
-        */
-       public function getStatus() {
-               return array(
-                       'mcryptAvailability' => $this->getMcryptAvailability()
-               );
-       }
+class StatusReport implements \TYPO3\CMS\Reports\StatusProviderInterface
+{
+    /**
+     * Returns the status of an extension or (sub)system
+     *
+     * @return array An array of tx_reports_reports_status_Status objects
+     */
+    public function getStatus()
+    {
+        return array(
+            'mcryptAvailability' => $this->getMcryptAvailability()
+        );
+    }
 
-       protected function getMcryptAvailability() {
-               $mcryptAvailable = \TYPO3\FalWebdav\Utility\EncryptionUtility::isMcryptAvailable();
-               $severity = $mcryptAvailable === TRUE ? \TYPO3\CMS\Reports\Status::OK : \TYPO3\CMS\Reports\Status::ERROR;
-               $status = ($mcryptAvailable ? '' : 'Not ') . 'Available';
+    protected function getMcryptAvailability()
+    {
+        $mcryptAvailable = \TYPO3\FalWebdav\Utility\EncryptionUtility::isMcryptAvailable();
+        $severity = $mcryptAvailable === true ? \TYPO3\CMS\Reports\Status::OK : \TYPO3\CMS\Reports\Status::ERROR;
+        $status = ($mcryptAvailable ? '' : 'Not ') . 'Available';
 
-               return \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Reports\\Status', 'PHP extension mcrypt', $status, '', $severity);
-       }
+        return \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Reports\\Status',
+            'PHP extension mcrypt', $status, '', $severity);
+    }
 
 }
\ No newline at end of file
index 884db88..92dc649 100644 (file)
@@ -6,42 +6,48 @@ namespace TYPO3\FalWebdav\Backend;
  *
  * @author Andreas Wolf <andreas.wolf@ikt-werk.de>
  */
-class TceMainHook {
-       /**
-        * @param array $incomingFieldArray
-        * @param string $table
-        * @param integer|string $id
-        * @param \TYPO3\CMS\Core\DataHandling\DataHandler $tceMainObject
-        * @return mixed
-        */
-       public function processDatamap_preProcessFieldArray(&$incomingFieldArray, $table, $id, \TYPO3\CMS\Core\DataHandling\DataHandler $tceMainObject) {
-               if ($table !== 'sys_file_storage') {
-                       return;
-               }
-               if ($incomingFieldArray['driver'] !== 'WebDav') {
-                       return;
-               }
+class TceMainHook
+{
+    /**
+     * @param array $incomingFieldArray
+     * @param string $table
+     * @param integer|string $id
+     * @param \TYPO3\CMS\Core\DataHandling\DataHandler $tceMainObject
+     * @return mixed
+     */
+    public function processDatamap_preProcessFieldArray(
+        &$incomingFieldArray,
+        $table,
+        $id,
+        \TYPO3\CMS\Core\DataHandling\DataHandler $tceMainObject
+    ) {
+        if ($table !== 'sys_file_storage') {
+            return;
+        }
+        if ($incomingFieldArray['driver'] !== 'WebDav') {
+            return;
+        }
 
-               $url = &$incomingFieldArray['configuration']['data']['sDEF']['lDEF']['baseUrl']['vDEF'];
-               $username = &$incomingFieldArray['configuration']['data']['sDEF']['lDEF']['username']['vDEF'];
-               $password = &$incomingFieldArray['configuration']['data']['sDEF']['lDEF']['password']['vDEF'];
+        $url = &$incomingFieldArray['configuration']['data']['sDEF']['lDEF']['baseUrl']['vDEF'];
+        $username = &$incomingFieldArray['configuration']['data']['sDEF']['lDEF']['username']['vDEF'];
+        $password = &$incomingFieldArray['configuration']['data']['sDEF']['lDEF']['password']['vDEF'];
 
-               list($cleanedUrl, $extractedUsername, $extractedPassword) = \TYPO3\FalWebdav\Utility\UrlTools::extractUsernameAndPasswordFromUrl($url);
-               if ($cleanedUrl != $url) {
-                       $url = $cleanedUrl;
-               }
-                       // if we found authentication information in the URL, use it instead of the information currently stored
-               if ($extractedUsername !== '') {
-                       $username = $extractedUsername;
-                       $password = $extractedPassword;
-               }
+        list($cleanedUrl, $extractedUsername, $extractedPassword) = \TYPO3\FalWebdav\Utility\UrlTools::extractUsernameAndPasswordFromUrl($url);
+        if ($cleanedUrl != $url) {
+            $url = $cleanedUrl;
+        }
+        // if we found authentication information in the URL, use it instead of the information currently stored
+        if ($extractedUsername !== '') {
+            $username = $extractedUsername;
+            $password = $extractedPassword;
+        }
 
-                       // skip encryption if we have no password set or the password is already encrypted
-               if ($password === '' || substr($password, 0, 1) === '$') {
-                       return;
-               }
+        // skip encryption if we have no password set or the password is already encrypted
+        if ($password === '' || substr($password, 0, 1) === '$') {
+            return;
+        }
 
-               $password = \TYPO3\FalWebdav\Utility\EncryptionUtility::encryptPassword($password);
-       }
+        $password = \TYPO3\FalWebdav\Utility\EncryptionUtility::encryptPassword($password);
+    }
 
 }
index 1e89530..2bf5d18 100644 (file)
@@ -6,182 +6,196 @@ use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 
-class CachingWebDavFrontend extends WebDavFrontend {
-
-       /**
-        * @var FrontendInterface
-        */
-       protected $cache;
-
-       protected $cacheHits = array(
-               'propFind' => 0,
-               'listFiles' => 0,
-               'listFolders' => 0,
-               'getFileInfo' => 0,
-       );
-
-       protected $cacheMisses = array(
-               'propFind' => 0,
-               'listFiles' => 0,
-               'listFolders' => 0,
-               'getFileInfo' => 0,
-       );
-
-
-       public function __construct(WebDavClient $client, $baseUrl, $storageUid, FrontendInterface $cache) {
-               parent::__construct($client, $baseUrl, $storageUid);
-
-               $this->cache = $cache;
-       }
-
-       /**
-        * @return FrontendInterface
-        */
-       protected function getCache() {
-               if (!$this->cache) {
-                       /** @var CacheManager $cacheManager */
-                       $cacheManager = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Cache\\CacheManager');
-                       $this->cache = $cacheManager->getCache('tx_falwebdav_directorylisting');
-               }
-
-               return $this->cache;
-       }
-
-       public function propFind($path) {
-               $cacheKey = $this->getCacheIdentifierForResponse($path);
-
-               if (!$this->getCache()->has($cacheKey)) {
-                       ++$this->cacheMisses[__FUNCTION__];
-                       $this->logger->debug('propFind(): cache miss for ' . $path);
-
-                       $propFindResult = parent::propFind($path);
-
-                       $this->getCache()->set($cacheKey, $propFindResult);
-
-                       if (substr($path, -1) == '/' || strlen($path) == 0) {
-                               $this->extractFileInformationFromPropfindResult($propFindResult);
-                       }
-               } else {
-                       $this->logger->debug('propFind(): cache hit for ' . $path);
-                       ++$this->cacheHits[__FUNCTION__];
-               }
-
-               return $this->getCache()->get($cacheKey);
-       }
-
-       public function listFiles($path) {
-               $cacheKey = $this->getCacheIdentifierForFileList($path);
-               if (!$this->getCache()->has($cacheKey)) {
-                       ++$this->cacheMisses[__FUNCTION__];
-                       $this->getCache()->set($cacheKey, parent::listFiles($path));
-               } else {
-                       ++$this->cacheHits[__FUNCTION__];
-               }
-
-               return $this->getCache()->get($cacheKey);
-       }
-
-       public function listFolders($path) {
-               $cacheKey = $this->getCacheIdentifierForFolderList($path);
-               if (!$this->getCache()->has($cacheKey)) {
-                       ++$this->cacheMisses[__FUNCTION__];
-                       $this->getCache()->set($cacheKey, parent::listFolders($path));
-               } else {
-                       ++$this->cacheHits[__FUNCTION__];
-               }
-
-               return $this->getCache()->get($cacheKey);
-       }
-
-       public function getFileInfo($path) {
-               // the leading slash is already included in baseURL/basePath
-               $path = ltrim($path, '/');
-
-               $cacheKey = $this->getCacheIdentifierForFileInfo($path);
-               if (!$this->getCache()->has($cacheKey)) {
-                       ++$this->cacheMisses[__FUNCTION__];
-                       $this->getCache()->set($cacheKey, parent::getFileInfo($path));
-               } else {
-                       ++$this->cacheHits[__FUNCTION__];
-               }
-
-               return $this->getCache()->get($cacheKey);
-       }
-
-       public function logCacheStatistics() {
-               if ($GLOBALS['TYPO3_AJAX'] === TRUE) {
-                       return;
-               }
-               sprintf('WebDAV frontend cache stats (hits/misses): '
-                       .'propFind %d/%d, listFiles %d/%d, listFolders %d/%d, getFileInfo %d/%d',
-                       $this->cacheHits['propFind'], $this->cacheMisses['propFind'],
-                       $this->cacheHits['listFiles'], $this->cacheMisses['listFiles'],
-                       $this->cacheHits['listFolders'], $this->cacheMisses['listFolders'],
-                       $this->cacheHits['getFileInfo'], $this->cacheMisses['getFileInfo']
-               );
-       }
-
-       /**
-        * Returns the cache identifier for the raw response for a given path
-        *
-        * @param string $path
-        * @return string
-        */
-       protected function getCacheIdentifierForResponse($path) {
-               return 'davResponse-' . $this->storageUid . '-' . sha1($path);
-       }
-
-       /**
-        * Returns the cache identifier for the file list of a given path.
-        *
-        * @param string $path
-        * @return string
-        */
-       protected function getCacheIdentifierForFileList($path) {
-               return 'filelist-' . $this->storageUid . '-' . sha1($this->baseUrl . ':' . trim($path, '/') . '/');
-       }
-
-       /**
-        * Returns the cache identifier for the folder list of a given path.
-        *
-        * @param string $path
-        * @return string
-        */
-       protected function getCacheIdentifierForFolderList($path) {
-               return 'folderlist-' . $this->storageUid . '-' . sha1($this->baseUrl . ':' . trim($path, '/') . '/');
-       }
-
-       /**
-        * Returns the cache identifier for the file list of a given path.
-        *
-        * @param string $path
-        * @return string
-        */
-       protected function getCacheIdentifierForFileInfo($path) {
-               return 'fileinfo-' . $this->storageUid . '-' . sha1($this->baseUrl . ':' . $path);
-       }
-
-       function __destruct() {
-               $this->logCacheStatistics();
-       }
-
-       /**
-        * @param $propFindResult
-        */
-       protected function extractFileInformationFromPropfindResult($propFindResult) {
-               $this->logger->debug('Extracting file information from request');
-               foreach ($propFindResult as $filePath => $entry) {
-                       if (substr($filePath, -1) == '/') {
-                               continue;
-                       }
-
-                       $filePath = rawurldecode($filePath);
-                       $filePath = substr($filePath, strlen($this->basePath));
-                       $cacheKey = $this->getCacheIdentifierForFileInfo($filePath);
-                       if (!$this->getCache()->has($cacheKey)) {
-                               $this->getCache()->set($cacheKey, $this->extractFileInfo($filePath, $entry));
-                       }
-               }
-       }
+class CachingWebDavFrontend extends WebDavFrontend
+{
+
+    /**
+     * @var FrontendInterface
+     */
+    protected $cache;
+
+    protected $cacheHits = array(
+        'propFind' => 0,
+        'listFiles' => 0,
+        'listFolders' => 0,
+        'getFileInfo' => 0,
+    );
+
+    protected $cacheMisses = array(
+        'propFind' => 0,
+        'listFiles' => 0,
+        'listFolders' => 0,
+        'getFileInfo' => 0,
+    );
+
+
+    public function __construct(WebDavClient $client, $baseUrl, $storageUid, FrontendInterface $cache)
+    {
+        parent::__construct($client, $baseUrl, $storageUid);
+
+        $this->cache = $cache;
+    }
+
+    /**
+     * @return FrontendInterface
+     */
+    protected function getCache()
+    {
+        if (!$this->cache) {
+            /** @var CacheManager $cacheManager */
+            $cacheManager = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Cache\\CacheManager');
+            $this->cache = $cacheManager->getCache('tx_falwebdav_directorylisting');
+        }
+
+        return $this->cache;
+    }
+
+    public function propFind($path)
+    {
+        $cacheKey = $this->getCacheIdentifierForResponse($path);
+
+        if (!$this->getCache()->has($cacheKey)) {
+            ++$this->cacheMisses[__FUNCTION__];
+            $this->logger->debug('propFind(): cache miss for ' . $path);
+
+            $propFindResult = parent::propFind($path);
+
+            $this->getCache()->set($cacheKey, $propFindResult);
+
+            if (substr($path, -1) == '/' || strlen($path) == 0) {
+                $this->extractFileInformationFromPropfindResult($propFindResult);
+            }
+        } else {
+            $this->logger->debug('propFind(): cache hit for ' . $path);
+            ++$this->cacheHits[__FUNCTION__];
+        }
+
+        return $this->getCache()->get($cacheKey);
+    }
+
+    public function listFiles($path)
+    {
+        $cacheKey = $this->getCacheIdentifierForFileList($path);
+        if (!$this->getCache()->has($cacheKey)) {
+            ++$this->cacheMisses[__FUNCTION__];
+            $this->getCache()->set($cacheKey, parent::listFiles($path));
+        } else {
+            ++$this->cacheHits[__FUNCTION__];
+        }
+
+        return $this->getCache()->get($cacheKey);
+    }
+
+    public function listFolders($path)
+    {
+        $cacheKey = $this->getCacheIdentifierForFolderList($path);
+        if (!$this->getCache()->has($cacheKey)) {
+            ++$this->cacheMisses[__FUNCTION__];
+            $this->getCache()->set($cacheKey, parent::listFolders($path));
+        } else {
+            ++$this->cacheHits[__FUNCTION__];
+        }
+
+        return $this->getCache()->get($cacheKey);
+    }
+
+    public function getFileInfo($path)
+    {
+        // the leading slash is already included in baseURL/basePath
+        $path = ltrim($path, '/');
+
+        $cacheKey = $this->getCacheIdentifierForFileInfo($path);
+        if (!$this->getCache()->has($cacheKey)) {
+            ++$this->cacheMisses[__FUNCTION__];
+            $this->getCache()->set($cacheKey, parent::getFileInfo($path));
+        } else {
+            ++$this->cacheHits[__FUNCTION__];
+        }
+
+        return $this->getCache()->get($cacheKey);
+    }
+
+    public function logCacheStatistics()
+    {
+        if ($GLOBALS['TYPO3_AJAX'] === true) {
+            return;
+        }
+        sprintf('WebDAV frontend cache stats (hits/misses): '
+            . 'propFind %d/%d, listFiles %d/%d, listFolders %d/%d, getFileInfo %d/%d',
+            $this->cacheHits['propFind'], $this->cacheMisses['propFind'],
+            $this->cacheHits['listFiles'], $this->cacheMisses['listFiles'],
+            $this->cacheHits['listFolders'], $this->cacheMisses['listFolders'],
+            $this->cacheHits['getFileInfo'], $this->cacheMisses['getFileInfo']
+        );
+    }
+
+    /**
+     * Returns the cache identifier for the raw response for a given path
+     *
+     * @param string $path
+     * @return string
+     */
+    protected function getCacheIdentifierForResponse($path)
+    {
+        return 'davResponse-' . $this->storageUid . '-' . sha1($path);
+    }
+
+    /**
+     * Returns the cache identifier for the file list of a given path.
+     *
+     * @param string $path
+     * @return string
+     */
+    protected function getCacheIdentifierForFileList($path)
+    {
+        return 'filelist-' . $this->storageUid . '-' . sha1($this->baseUrl . ':' . trim($path, '/') . '/');
+    }
+
+    /**
+     * Returns the cache identifier for the folder list of a given path.
+     *
+     * @param string $path
+     * @return string
+     */
+    protected function getCacheIdentifierForFolderList($path)
+    {
+        return 'folderlist-' . $this->storageUid . '-' . sha1($this->baseUrl . ':' . trim($path, '/') . '/');
+    }
+
+    /**
+     * Returns the cache identifier for the file list of a given path.
+     *
+     * @param string $path
+     * @return string
+     */
+    protected function getCacheIdentifierForFileInfo($path)
+    {
+        return 'fileinfo-' . $this->storageUid . '-' . sha1($this->baseUrl . ':' . $path);
+    }
+
+    function __destruct()
+    {
+        $this->logCacheStatistics();
+    }
+
+    /**
+     * @param $propFindResult
+     */
+    protected function extractFileInformationFromPropfindResult($propFindResult)
+    {
+        $this->logger->debug('Extracting file information from request');
+        foreach ($propFindResult as $filePath => $entry) {
+            if (substr($filePath, -1) == '/') {
+                continue;
+            }
+
+            $filePath = rawurldecode($filePath);
+            $filePath = substr($filePath, strlen($this->basePath));
+            $cacheKey = $this->getCacheIdentifierForFileInfo($filePath);
+            if (!$this->getCache()->has($cacheKey)) {
+                $this->getCache()->set($cacheKey, $this->extractFileInfo($filePath, $entry));
+            }
+        }
+    }
 
 }
index 9583c60..b956a81 100644 (file)
@@ -23,95 +23,101 @@ use Sabre\HTTP;
 /**
  * Helper class to circumvent limitations in SabreDAV's support for cURL's certificate verification options.
  */
-class WebDavClient extends Client {
-
-       /**
-        * Trigger to enable/disable peer certificate verification
-        *
-        * @var boolean
-        */
-       protected $verifyCertificates = TRUE;
-
-       /**
-        * The file to write the data to.
-        *
-        * @var resource
-        */
-       protected $outputFile = NULL;
-
-
-       /**
-        * @param boolean $peerVerification
-        */
-       public function setCertificateVerification($peerVerification) {
-               $this->verifyCertificates = $peerVerification;
-       }
-
-       /**
-        * Wrapper for all cUrl functions.
-        *
-        * @param resource $curlHandle
-        *
-        * @return array
-        */
-       protected function curlExec($curlHandle) {
-               if ($this->verifyCertificates === FALSE) {
-                       curl_setopt($curlHandle, CURLOPT_SSL_VERIFYPEER, FALSE);
-               }
-               if ($this->outputFile !== NULL) {
-                       // make sure the file is never returned into the default output stream
-                       curl_setopt($curlHandle, CURLOPT_RETURNTRANSFER, FALSE);
-                       // don’t return the headers
-                       curl_setopt($curlHandle, CURLOPT_HEADER, FALSE);
-                       curl_setopt($curlHandle, CURLOPT_FILE, $this->outputFile);
-                       curl_setopt($curlHandle, CURLOPT_FOLLOWLOCATION, TRUE);
-                       $this->outputFile = NULL;
-               } else {
-                       // set back to default as the cURL handle is not always reset; the file is not used anyways, but cURL
-                       // still complains about the handle being gone away if we closed the file that was used in an earlier
-                       // request
-                       curl_setopt($curlHandle, CURLOPT_FILE, fopen('php://stdout','w'));
-
-                       // we must use a different order here; setting RETURNTRANSFER before resetting the file handle will let
-                       // cURL still use the file.
-                       curl_setopt($curlHandle, CURLOPT_RETURNTRANSFER, TRUE);
-               }
-
-               return parent::curlExec($curlHandle);
-       }
-
-       function propFind($url, array $properties = NULL, $depth = 0) {
-               if ($properties === NULL) {
-                       $properties = array(
-                               '{DAV:}resourcetype',
-                               '{DAV:}creationdate',
-                               '{DAV:}getcontentlength',
-                               '{DAV:}getlastmodified'
-                       );
-               }
-               return parent::propFind($url, $properties, $depth); // TODO: Change the autogenerated stub
-       }
-
-       /**
-        * Reads the given URL’s contents to the given file handle. The handle must be writable, the disk must have enough
-        * free space and
-        *
-        * @param string $url
-        * @param resource $fileHandle
-        * @param array $headers
-        * @return HTTP\ResponseInterface
-        */
-       public function readUrlToHandle($url, $fileHandle, array $headers = []) {
-               if (!is_resource($fileHandle)) {
-                       throw new \InvalidArgumentException('The file handle must be a valid resource');
-               }
-               $request = new HTTP\Request('GET', $url, $headers);
-
-               // The actual option is set in curlExec(), as we don’t have access to the cURL handle here
-               $this->outputFile = $fileHandle;
-
-               return $this->send($request);
-       }
+class WebDavClient extends Client
+{
+
+    /**
+     * Trigger to enable/disable peer certificate verification
+     *
+     * @var boolean
+     */
+    protected $verifyCertificates = true;
+
+    /**
+     * The file to write the data to.
+     *
+     * @var resource
+     */
+    protected $outputFile = null;
+
+
+    /**
+     * @param boolean $peerVerification
+     */
+    public function setCertificateVerification($peerVerification)
+    {
+        $this->verifyCertificates = $peerVerification;
+    }
+
+    /**
+     * Wrapper for all cUrl functions.
+     *
+     * @param resource $curlHandle
+     *
+     * @return array
+     */
+    protected function curlExec($curlHandle)
+    {
+        if ($this->verifyCertificates === false) {
+            curl_setopt($curlHandle, CURLOPT_SSL_VERIFYPEER, false);
+        }
+        if ($this->outputFile !== null) {
+            // make sure the file is never returned into the default output stream
+            curl_setopt($curlHandle, CURLOPT_RETURNTRANSFER, false);
+            // don’t return the headers
+            curl_setopt($curlHandle, CURLOPT_HEADER, false);
+            curl_setopt($curlHandle, CURLOPT_FILE, $this->outputFile);
+            curl_setopt($curlHandle, CURLOPT_FOLLOWLOCATION, true);
+            $this->outputFile = null;
+        } else {
+            // set back to default as the cURL handle is not always reset; the file is not used anyways, but cURL
+            // still complains about the handle being gone away if we closed the file that was used in an earlier
+            // request
+            curl_setopt($curlHandle, CURLOPT_FILE, fopen('php://stdout', 'w'));
+
+            // we must use a different order here; setting RETURNTRANSFER before resetting the file handle will let
+            // cURL still use the file.
+            curl_setopt($curlHandle, CURLOPT_RETURNTRANSFER, true);
+        }
+
+        return parent::curlExec($curlHandle);
+    }
+
+    function propFind($url, array $properties = null, $depth = 0)
+    {
+        if ($properties === null) {
+            $properties = array(
+                '{DAV:}resourcetype',
+                '{DAV:}creationdate',
+                '{DAV:}getcontentlength',
+                '{DAV:}getlastmodified'
+            );
+        }
+
+        return parent::propFind($url, $properties, $depth); // TODO: Change the autogenerated stub
+    }
+
+    /**
+     * Reads the given URL’s contents to the given file handle. The handle must be writable, the disk must have enough
+     * free space and
+     *
+     * @param string $url
+     * @param resource $fileHandle
+     * @param array $headers
+     * @return HTTP\ResponseInterface
+     */
+    public function readUrlToHandle($url, $fileHandle, array $headers = [])
+    {
+        if (!is_resource($fileHandle)) {
+            throw new \InvalidArgumentException('The file handle must be a valid resource');
+        }
+        $request = new HTTP\Request('GET', $url, $headers);
+
+        // The actual option is set in curlExec(), as we don’t have access to the cURL handle here
+        $this->outputFile = $fileHandle;
+
+        return $this->send($request);
+    }
 
 }
 
index 425c085..65b06ce 100644 (file)
@@ -17,7 +17,6 @@ namespace TYPO3\FalWebdav\Dav;
 use Sabre\DAV;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\HttpUtility;
-use TYPO3\FalWebdav\Utility\UrlTools;
 
 
 /**
@@ -26,206 +25,221 @@ use TYPO3\FalWebdav\Utility\UrlTools;
  * All identifiers within this class are relative to the DAV storage’s base path and thus have no slash at the
  * beginning (unlike FAL identifiers, which are always prepended with a slash).
  */
-class WebDavFrontend {
-
-       /**
-        * @var WebDavClient
-        */
-       protected $davClient;
-
-       /**
-        * The storage base URL, has to be already URL-encoded
-        *
-        * @var string
-        */
-       protected $baseUrl;
-
-       /**
-        * @var string
-        */
-       protected $basePath;
-
-       /**
-        * @var \TYPO3\CMS\Core\Log\Logger
-        */
-       protected $logger;
-
-       /**
-        * @var int
-        */
-       protected $storageUid;
-
-
-       public function __construct(WebDavClient $client, $baseUrl, $storageUid) {
-               $this->logger = GeneralUtility::makeInstance('TYPO3\CMS\Core\Log\LogManager')->getLogger(__CLASS__);
-
-               $this->davClient = $client;
-               $this->baseUrl = rtrim($baseUrl, '/') . '/';
-               $urlParts = parse_url($this->baseUrl);
-               $this->basePath = $urlParts['path'];
-               $this->storageUid = $storageUid;
-       }
-
-       /**
-        * @param string $url
-        * @return string
-        */
-       protected function encodeUrl($url) {
-               $urlParts = parse_url($url);
-               $urlParts['path'] = $this->urlEncodePath($urlParts['path']);
-
-               return HttpUtility::buildUrl($urlParts);
-       }
-
-       /**
-        * Wrapper around the PROPFIND method of the WebDAV client to get proper local error handling.
-        *
-        * @param string $path
-        * @return array
-        * @throws DAV\Exception\NotFound if the given URL does not hold a resource
-        *
-        * TODO define proper error handling for other cases
-        */
-       public function propFind($path) {
-               $url = $this->baseUrl . $path;
-               $encodedUrl = $this->encodeUrl($url);
-
-               try {
-                       // propfind() already decodes the XML, so we get back an array
-                       $propfindResultArray = $this->davClient->propfind($encodedUrl, NULL, 1);
-
-                       // the returned items are indexed by their key, so sort them here to return the correct items.
-                       // At least Apache does not sort them before returning
-                       uksort($propfindResultArray, 'strnatcasecmp');
-
-                       return $propfindResultArray;
-               } catch (DAV\Exception\NotFound $exception) {
-                       $this->logger->warning('URL not found: ' . $url);
-                       // If a file is not found, we have to deal with that on a higher level, so throw the exception again
-                       throw $exception;
-               } catch (DAV\Exception $exception) {
-                       // log all other exceptions
-                       $this->logger->error(sprintf(
-                               'Error while executing DAV PROPFIND request. Original message: "%s" (Exception %s, id: %u)',
-                               $exception->getMessage(), get_class($exception), $exception->getCode()
-                       ));
-                       // TODO check how we can let this propagate to the driver
-                       return array();
-               }
-       }
-
-       /**
-        *
-        * @param string $path
-        * @return array A list of file names in the path
-        */
-       public function listFiles($path) {
-               $files = $this->listItems($path, function ($currentItem) {
-                       if (substr($currentItem, -1) == '/') {
-                               return FALSE;
-                       }
-                       return TRUE;
-               });
-
-               return $files;
-       }
-
-       /**
-        * @param string $path
-        * @return array A list of folder names in the path
-        */
-       public function listFolders($path) {
-               $folders = $this->listItems($path, function ($currentItem) {
-                       if (substr($currentItem, -1) != '/') {
-                               return FALSE;
-                       }
-                       return TRUE;
-               });
-
-               return $folders;
-       }
-
-       protected function listItems($path, $itemFilterCallback) {
-               $path = trim($path, '/');
-               if (strlen($path) > 0) {
-                       $path .= '/';
-               }
-               $urlParts = parse_url($this->baseUrl . $path);
-               $unencodedBasePath = $urlParts['path'];
-
-               $result = $this->propFind($path);
-
-               // remove first entry, as it is the folder itself
-               array_shift($result);
-
-               $files = array();
-               // $filePath contains the path part of the URL, no server name and protocol!
-               foreach ($result as $filePath => $fileInfo) {
-                       $decodedFilePath = urldecode($filePath);
-                       $decodedFilePath = substr($decodedFilePath, strlen($unencodedBasePath));
-                       // ignore folder entries
-                       if (!$itemFilterCallback($decodedFilePath)) {
-                               continue;
-                       }
-
-                       // TODO if depth is > 1, we will also include deeper entries here, which we should not
-
-                       $files[] = basename($decodedFilePath);
-               }
-
-               return $files;
-       }
-
-       /**
-        * Returns information about the given file.
-        *
-        * TODO define what to return
-        *
-        * @param string $path
-        * @return array
-        */
-       public function getFileInfo($path) {
-               // the leading slash is already included in baseURL/basePath
-               $path = ltrim($path, '/');
-
-               $result = $this->propFind($path);
-
-               return $this->extractFileInfo($path, $result[$this->basePath . $this->urlEncodePath($path)]);
-       }
-
-       protected function extractFileInfo($path, $propFindArray) {
-               $fileInfo = array(
-                       'mtime' => (int)strtotime($propFindArray['{DAV:}getlastmodified']),
-                       'ctime' => (int)strtotime($propFindArray['{DAV:}creationdate']),
-                       'mimetype' => (string)$propFindArray['{DAV:}getcontenttype'],
-                       'name' => basename($path),
-                       'size' => (int)$propFindArray['{DAV:}getcontentlength'],
-                       'identifier' => '/' . $path,
-                       'storage' => $this->storageUid,
-                       'identifier_hash' => sha1('/' . $path),
-                       'folder_hash' => sha1('/' . $this->getFolderPathFromIdentifier($path)),
-               );
-
-               return $fileInfo;
-       }
-
-       /**
-        * @param string $path The identifier, without a leading slash!
-        * @return string The folder path, without a trailing slash. If the file is on root level, an empty string is returned
-        */
-       protected function getFolderPathFromIdentifier($path) {
-               $dirPath = dirname($path);
-
-               return $dirPath . ($dirPath !== '') ? '/' : '';
-       }
-
-       /**
-        * @param $path
-        * @return string
-        */
-       protected function urlEncodePath($path) {
-               // using urlencode() does not work because it encodes a space as "+" and not as "%20".
-               return implode('/', array_map('rawurlencode', explode('/', $path)));
-       }
+class WebDavFrontend
+{
+
+    /**
+     * @var WebDavClient
+     */
+    protected $davClient;
+
+    /**
+     * The storage base URL, has to be already URL-encoded
+     *
+     * @var string
+     */
+    protected $baseUrl;
+
+    /**
+     * @var string
+     */
+    protected $basePath;
+
+    /**
+     * @var \TYPO3\CMS\Core\Log\Logger
+     */
+    protected $logger;
+
+    /**
+     * @var int
+     */
+    protected $storageUid;
+
+
+    public function __construct(WebDavClient $client, $baseUrl, $storageUid)
+    {
+        $this->logger = GeneralUtility::makeInstance('TYPO3\CMS\Core\Log\LogManager')->getLogger(__CLASS__);
+
+        $this->davClient = $client;
+        $this->baseUrl = rtrim($baseUrl, '/') . '/';
+        $urlParts = parse_url($this->baseUrl);
+        $this->basePath = $urlParts['path'];
+        $this->storageUid = $storageUid;
+    }
+
+    /**
+     * @param string $url
+     * @return string
+     */
+    protected function encodeUrl($url)
+    {
+        $urlParts = parse_url($url);
+        $urlParts['path'] = $this->urlEncodePath($urlParts['path']);
+
+        return HttpUtility::buildUrl($urlParts);
+    }
+
+    /**
+     * Wrapper around the PROPFIND method of the WebDAV client to get proper local error handling.
+     *
+     * @param string $path
+     * @return array
+     * @throws DAV\Exception\NotFound if the given URL does not hold a resource
+     *
+     * TODO define proper error handling for other cases
+     */
+    public function propFind($path)
+    {
+        $url = $this->baseUrl . $path;
+        $encodedUrl = $this->encodeUrl($url);
+
+        try {
+            // propfind() already decodes the XML, so we get back an array
+            $propfindResultArray = $this->davClient->propfind($encodedUrl, null, 1);
+
+            // the returned items are indexed by their key, so sort them here to return the correct items.
+            // At least Apache does not sort them before returning
+            uksort($propfindResultArray, 'strnatcasecmp');
+
+            return $propfindResultArray;
+        } catch (DAV\Exception\NotFound $exception) {
+            $this->logger->warning('URL not found: ' . $url);
+            // If a file is not found, we have to deal with that on a higher level, so throw the exception again
+            throw $exception;
+        } catch (DAV\Exception $exception) {
+            // log all other exceptions
+            $this->logger->error(sprintf(
+                'Error while executing DAV PROPFIND request. Original message: "%s" (Exception %s, id: %u)',
+                $exception->getMessage(), get_class($exception), $exception->getCode()
+            ));
+
+            // TODO check how we can let this propagate to the driver
+            return array();
+        }
+    }
+
+    /**
+     *
+     * @param string $path
+     * @return array A list of file names in the path
+     */
+    public function listFiles($path)
+    {
+        $files = $this->listItems($path, function ($currentItem) {
+            if (substr($currentItem, -1) == '/') {
+                return false;
+            }
+
+            return true;
+        });
+
+        return $files;
+    }
+
+    /**
+     * @param string $path
+     * @return array A list of folder names in the path
+     */
+    public function listFolders($path)
+    {
+        $folders = $this->listItems($path, function ($currentItem) {
+            if (substr($currentItem, -1) != '/') {
+                return false;
+            }
+
+            return true;
+        });
+
+        return $folders;
+    }
+
+    protected function listItems($path, $itemFilterCallback)
+    {
+        $path = trim($path, '/');
+        if (strlen($path) > 0) {
+            $path .= '/';
+        }
+        $urlParts = parse_url($this->baseUrl . $path);
+        $unencodedBasePath = $urlParts['path'];
+
+        $result = $this->propFind($path);
+
+        // remove first entry, as it is the folder itself
+        array_shift($result);
+
+        $files = array();
+        // $filePath contains the path part of the URL, no server name and protocol!
+        foreach ($result as $filePath => $fileInfo) {
+            $decodedFilePath = urldecode($filePath);
+            $decodedFilePath = substr($decodedFilePath, strlen($unencodedBasePath));
+            // ignore folder entries
+            if (!$itemFilterCallback($decodedFilePath)) {
+                continue;
+            }
+
+            // TODO if depth is > 1, we will also include deeper entries here, which we should not
+
+            $files[] = basename($decodedFilePath);
+        }
+
+        return $files;
+    }
+
+    /**
+     * Returns information about the given file.
+     *
+     * TODO define what to return
+     *
+     * @param string $path
+     * @return array
+     */
+    public function getFileInfo($path)
+    {
+        // the leading slash is already included in baseURL/basePath
+        $path = ltrim($path, '/');
+
+        $result = $this->propFind($path);
+
+        return $this->extractFileInfo($path, $result[$this->basePath . $this->urlEncodePath($path)]);
+    }
+
+    protected function extractFileInfo($path, $propFindArray)
+    {
+        $fileInfo = array(
+            'mtime' => (int)strtotime($propFindArray['{DAV:}getlastmodified']),
+            'ctime' => (int)strtotime($propFindArray['{DAV:}creationdate']),
+            'mimetype' => (string)$propFindArray['{DAV:}getcontenttype'],
+            'name' => basename($path),
+            'size' => (int)$propFindArray['{DAV:}getcontentlength'],
+            'identifier' => '/' . $path,
+            'storage' => $this->storageUid,
+            'identifier_hash' => sha1('/' . $path),
+            'folder_hash' => sha1('/' . $this->getFolderPathFromIdentifier($path)),
+        );
+
+        return $fileInfo;
+    }
+
+    /**
+     * @param string $path The identifier, without a leading slash!
+     * @return string The folder path, without a trailing slash. If the file is on root level, an empty string is
+     *     returned
+     */
+    protected function getFolderPathFromIdentifier($path)
+    {
+        $dirPath = dirname($path);
+
+        return $dirPath . ($dirPath !== '') ? '/' : '';
+    }
+
+    /**
+     * @param $path
+     * @return string
+     */
+    protected function urlEncodePath($path)
+    {
+        // using urlencode() does not work because it encodes a space as "+" and not as "%20".
+        return implode('/', array_map('rawurlencode', explode('/', $path)));
+    }
 
 }
index 1fb1c01..de29336 100644 (file)
@@ -19,7 +19,6 @@ include_once __DIR__ . '/../../Resources/Composer/vendor/autoload.php';
 use Sabre\DAV;
 use TYPO3\CMS\Core\Cache\CacheManager;
 use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
-use TYPO3\CMS\Core\Resource\Driver\AbstractDriver;
 use TYPO3\CMS\Core\Resource\Driver\AbstractHierarchicalFilesystemDriver;
 use TYPO3\CMS\Core\Resource\Exception\FileOperationErrorException;
 use TYPO3\CMS\Core\Resource\Exception\FolderDoesNotExistException;
@@ -27,973 +26,1057 @@ use TYPO3\CMS\Core\Resource\ResourceStorage;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\HttpUtility;
 use TYPO3\FalWebdav\Dav\CachingWebDavFrontend;
-use TYPO3\FalWebdav\Dav\WebDavFrontend;
 use TYPO3\FalWebdav\Dav\WebDavClient;
+use TYPO3\FalWebdav\Dav\WebDavFrontend;
 use TYPO3\FalWebdav\Utility\EncryptionUtility;
 
 
 /**
  * The driver class for WebDAV storages.
  */
-class WebDavDriver extends AbstractHierarchicalFilesystemDriver {
-
-       /**
-        * The base URL of the WebDAV share. Always ends with a trailing slash.
-        *
-        * @var string
-        */
-       protected $baseUrl = '';
-
-       /**
-        * The base URL to fetch resources. Includes authentication information if authentication is enabled, so this must
-        * never be published!
-        *
-        * @var string
-        */
-       protected $resourceBaseUrl = '';
-
-       /**
-        * The base path of the WebDAV store. This is the URL without protocol, host and port (i.e., only the path on the host).
-        * Always ends with a trailing slash.
-        *
-        * @var string
-        */
-       protected $basePath = '';
-
-       /**
-        * @var WebDavClient
-        */
-       protected $davClient;
-
-       /**
-        * The username to use for connecting to the storage.
-        *
-        * @var string
-        */
-       protected $username = '';
-
-       /**
-        * The password to use for connecting to the storage.
-        *
-        * @var string
-        */
-       protected $password = '';
-
-       /**
-        * @var \TYPO3\CMS\Core\Cache\Frontend\AbstractFrontend
-        */
-       protected $directoryListingCache;
-
-       /**
-        * @var WebDavFrontend
-        */
-       protected $frontend;
-
-       /**
-        * @var \TYPO3\CMS\Core\Log\Logger
-        */
-       protected $logger;
-
-       public function __construct(array $configuration = array()) {
-               $this->logger = GeneralUtility::makeInstance('TYPO3\CMS\Core\Log\LogManager')->getLogger(__CLASS__);
-
-               parent::__construct($configuration);
-       }
-
-       /**
-        * Initializes this object. This is called by the storage after the driver has been attached.
-        *
-        * @return void
-        */
-       public function initialize() {
-               $this->capabilities = ResourceStorage::CAPABILITY_BROWSABLE
-                       + ResourceStorage::CAPABILITY_PUBLIC
-                       + ResourceStorage::CAPABILITY_WRITABLE;
-       }
-
-       /**
-        * Inject method for the DAV client. Mostly useful for unit tests.
-        *
-        * @param WebDavClient $client
-        */
-       public function injectDavClient(WebDavClient $client) {
-               $this->davClient = $client;
-       }
-
-       /**
-        * Only used in tests.
-        *
-        * @param FrontendInterface $cache
-        */
-       public function injectDirectoryListingCache(FrontendInterface $cache) {
-               $this->directoryListingCache = $cache;
-       }
-
-       public function injectFrontend(WebDavFrontend $frontend) {
-               $this->frontend = $frontend;
-       }
-
-       protected function getFrontend() {
-               if (!$this->frontend) {
-                       $this->frontend = new CachingWebDavFrontend($this->davClient, $this->baseUrl, $this->storageUid, $this->getCache());
-               }
-               return $this->frontend;
-       }
-
-       /**
-        * @return FrontendInterface
-        */
-       protected function getCache() {
-               if (!$this->directoryListingCache) {
-                       /** @var CacheManager $cacheManager */
-                       $cacheManager = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Cache\\CacheManager');
-                       $this->directoryListingCache = $cacheManager->getCache('tx_falwebdav_directorylisting');
-               }
-
-               return $this->directoryListingCache;
-       }
-
-       /**
-        * Processes the configuration coming from the storage record and prepares the SabreDAV object.
-        *
-        * @return void
-        * @throws \InvalidArgumentException
-        */
-       public function processConfiguration() {
-               foreach ($this->configuration as $key => $value) {
-                       $this->configuration[$key] = trim($value);
-               }
-
-               $baseUrl = $this->configuration['baseUrl'];
-
-               $urlInfo = parse_url($baseUrl);
-               if ($urlInfo === FALSE) {
-                       throw new \InvalidArgumentException('Invalid base URL configured for WebDAV driver: ' . $this->configuration['baseUrl'], 1325771040);
-               }
-               $this->basePath = rtrim($urlInfo['path'], '/') . '/';
-
-               $extConf = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['fal_webdav']);
-               $configuration['enableZeroByteFilesIndexing'] = (boolean)$extConf['enableZeroByteFilesIndexing'];
-
-               // Use authentication only if enabled
-               $settings = array();
-               if ($this->configuration['useAuthentication']) {
-                       $this->username = $urlInfo['user'] ? $urlInfo['user'] : $this->configuration['username'];
-                       $this->password = $urlInfo['pass'] ? $urlInfo['pass'] : EncryptionUtility::decryptPassword($this->configuration['password']);
-                       $settings = array(
-                               'userName' => $this->username,
-                               'password' => $this->password
-                       );
-               }
-
-               // make sure the URL contains authentication data and build the resource URL for directly fetching data
-               $urlInfo['user'] = $this->username;
-               $urlInfo['pass'] = $this->password;
-               $this->resourceBaseUrl = rtrim(HttpUtility::buildUrl($urlInfo), '/') . '/';
-               // create cleaned URL without credentials
-               unset($urlInfo['user']);
-               unset($urlInfo['pass']);
-               $this->baseUrl = rtrim(HttpUtility::buildUrl($urlInfo), '/') . '/';
-               $settings['baseUri'] = $this->baseUrl;
-
-               $this->davClient = new WebDavClient($settings);
-               $this->davClient->setThrowExceptions(TRUE);
-
-               $this->davClient->setCertificateVerification($this->configuration['disableCertificateVerification'] != 1);
-       }
-
-       /**
-        * Checks if a configuration is valid for this driver.
-        *
-        * Throws an exception if a configuration will not work.
-        *
-        * @param array $configuration
-        * @return void
-        */
-       public static function verifyConfiguration(array $configuration) {
-               // TODO: Implement verifyConfiguration() method.
-       }
-
-       /**
-        * Executes a MOVE request from $oldPath to $newPath.
-        *
-        * @param string $oldPath
-        * @param string $newPath
-        * @return array The result as returned by SabreDAV
-        */
-       public function executeMoveRequest($oldPath, $newPath) {
-               $oldUrl = $this->baseUrl . ltrim($oldPath, '/');
-               $newUrl = $this->baseUrl . ltrim($newPath, '/');
-
-                       // force overwriting the file (header Overwrite: T) because the Storage already handled possible conflicts
-                       // for us
-               return $this->executeDavRequest('MOVE', $oldUrl, NULL, array('Destination' => $newUrl, 'Overwrite' => 'T'));
-       }
-
-       protected function encodeUrl($url) {
-               $urlParts = parse_url($url);
-               $urlParts['path'] = implode('/', array_map('rawurlencode', explode('/', $urlParts['path'])));
-
-               return HttpUtility::buildUrl($urlParts);
-       }
-
-       /**
-        * Executes a request on the DAV driver.
-        *
-        * @param string $method
-        * @param string $url
-        * @param string $body
-        * @param array $headers
-        * @return array
-        * @throws \Exception If anything goes wrong
-        */
-       protected function executeDavRequest($method, $url, $body = NULL, array $headers = array()) {
-               try {
-                       $url = $this->encodeUrl($url);
-                       return $this->davClient->request($method, $url, $body, $headers);
-               } catch (\Sabre\DAV\Exception\NotFound $exception) {
-                       // If a file is not found, we have to deal with that on a higher level, so throw the exception again
-                       throw $exception;
-               } catch (DAV\Exception $exception) {
-                       // log all other exceptions
-                       $this->logger->error(sprintf(
-                               'Error while executing DAV request. Original message: "%s" (Exception %s, id: %u)',
-                               $exception->getMessage(), get_class($exception), $exception->getCode()
-                       ));
-                       // TODO check how we can let this propagate to the driver
-                       return array();
-               }
-       }
-
-
-
-       /**
-        * Checks if a given resource exists in this DAV share.
-        *
-        * @param string $resourcePath The path to the resource, i.e. a regular identifier as used everywhere else here.
-        * @return bool
-        * @throws \InvalidArgumentException
-        */
-       public function resourceExists($resourcePath) {
-               if ($resourcePath == '') {
-                       throw new \InvalidArgumentException('Resource path cannot be empty');
-               }
-               $url = $this->baseUrl . ltrim($resourcePath, '/');
-               try {
-                       $result = $this->executeDavRequest('HEAD', $url);
-               } catch (\Sabre\Http\HttpException $exception) {
-                       return $exception->getHttpStatus() != 404;
-               }
-               // TODO check if other status codes may also indicate that the file is not present
-               return $result['statusCode'] < 400;
-       }
-
-
-       /**
-        * Returns the complete URL to a file. This is not necessarily the publicly available URL!
-        *
-        * @param string $file The file object or its identifier
-        * @return string
-        */
-       protected function getResourceUrl($file) {
-               return $this->resourceBaseUrl . ltrim($file, '/');
-       }
-
-       /**
-        * Returns the public URL to a file. This does not contain a username or password, even if this is
-        * necessary to display the file.
-        *
-        * TODO make it optional to include the username/password
-        *
-        * @param string $identifier
-        * @return string
-        */
-       public function getPublicUrl($identifier) {
-                       // as the storage is marked as public, we can simply use the public URL here.
-               return $this->baseUrl . ltrim($identifier, '/');
-       }
-
-       /**
-        * Creates a (cryptographic) hash for a file.
-        *
-        * @param string $identifier The file identifier
-        * @param string $hashAlgorithm The hash algorithm to use
-        * @return string
-        * TODO switch parameter order?
-        */
-       public function hash($identifier, $hashAlgorithm) {
-               // TODO add unit test
-               $fileCopy = $this->copyFileToTemporaryPath($identifier);
-
-               switch ($hashAlgorithm) {
-                       case 'sha1':
-                               $hash = sha1_file($fileCopy);
-                               break;
-
-                       default:
-                               throw new \InvalidArgumentException('Unsupported hash algorithm ' . $hashAlgorithm);
-               }
-
-               unlink($fileCopy);
-
-               return $hash;
-       }
-
-       /**
-        * Creates a new file and returns its identifier.
-        *
-        * @param string $fileName
-        * @param string $parentFolderIdentifier
-        * @return \TYPO3\CMS\Core\Resource\FileInterface
-        */
-       public function createFile($fileName, $parentFolderIdentifier) {
-               $fileIdentifier = $parentFolderIdentifier . $fileName;
-               $fileUrl = $this->baseUrl . ltrim($fileIdentifier, '/');
-
-               $this->executeDavRequest('PUT', $fileUrl, '');
-
-               $this->removeCacheForPath($parentFolderIdentifier);
-
-               return $fileIdentifier;
-       }
-
-       /**
-        * 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 \TYPO3\CMS\Core\Resource\FileInterface $fileIdentifier
-        * @return string The file contents
-        */
-       public function getFileContents($fileIdentifier) {
-               $fileUrl = $this->baseUrl . ltrim($fileIdentifier, '/');
-
-               $result = $this->executeDavRequest('GET', $fileUrl);
-
-               return $result['body'];
-       }
-
-       /**
-        * Sets the contents of a file to the specified value.
-        *
-        * @param string $fileIdentifier
-        * @param string $contents
-        * @return bool TRUE if setting the contents succeeded
-        * @throws \RuntimeException if the operation failed
-        */
-       public function setFileContents($fileIdentifier, $contents) {
-               // Apache returns a "204 no content" status after a successful put operation
-
-               $fileUrl = $this->getResourceUrl($fileIdentifier);
-               $result = $this->executeDavRequest('PUT', $fileUrl, $contents);
-
-               $this->removeCacheForPath(dirname($fileIdentifier));
-
-               // TODO check result
-       }
-
-       /**
-        * 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 (within PATH_site)
-        * @param string $targetFolderIdentifier
-        * @param string $newFileName optional, if not given original name is used
-        * @param boolean $removeOriginal if set the original file will be removed
-        *                                after successful operation
-        * @return string the identifier of the new file
-        */
-       public function addFile($localFilePath, $targetFolderIdentifier, $newFileName = '', $removeOriginal = TRUE) {
-               $fileIdentifier = $targetFolderIdentifier . $newFileName;
-               $fileUrl = $this->baseUrl . ltrim($fileIdentifier);
-
-               $fileHandle = fopen($localFilePath, 'r');
-               if (!is_resource($fileHandle)) {
-                       throw new \RuntimeException('Could not open handle for ' . $localFilePath, 1325959310);
-               }
-               $result = $this->executeDavRequest('PUT', $fileUrl, $fileHandle);
-
-               // TODO check result
-
-               $this->removeCacheForPath($targetFolderIdentifier);
-
-               return $fileIdentifier;
-       }
-
-       /**
-        * Checks if a file exists.
-        *
-        * @param string $identifier
-        * @return bool
-        */
-       public function fileExists($identifier) {
-               return substr($identifier, -1) !== '/' && $this->resourceExists($identifier);
-       }
-
-       /**
-        * Checks if a file inside a storage folder exists.
-        *
-        * @param string $fileName
-        * @param string $folderIdentifier
-        * @return boolean
-        */
-       public function fileExistsInFolder($fileName, $folderIdentifier) {
-               // TODO add unit test
-               $fileIdentifier = $folderIdentifier . $fileName;
-
-               return $this->fileExists($fileIdentifier);
-       }
-
-       /**
-        * 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!
-        *
-        * @param string $fileIdentifier
-        * @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
-        */
-       public function getFileForLocalProcessing($fileIdentifier, $writable = TRUE) {
-               return $this->copyFileToTemporaryPath($fileIdentifier);
-       }
-
-       /**
-        * Renames a file
-        *
-        * @param \TYPO3\CMS\Core\Resource\FileInterface $file
-        * @param string $newName
-        * @return string The new identifier of the file
-        */
-       public function renameFile($fileIdentifier, $newName) {
-               // TODO add unit test
-               // Renaming works by invoking the MOVE method on the source URL and providing the new destination in the
-               // "Destination:" HTTP header.
-               $sourcePath = $fileIdentifier;
-               $targetPath = dirname($fileIdentifier) . '/' . $newName;
-
-               $this->executeMoveRequest($sourcePath, $targetPath);
-
-               $this->removeCacheForPath(dirname($fileIdentifier));
-
-               return $targetPath;
-       }
-
-       /**
-        * Replaces the contents (and file-specific metadata) of a file object with a local file.
-        *
-        * @param string $fileIdentifier
-        * @param string $localFilePath
-        * @return bool
-        * @throws \RuntimeException
-        */
-       public function replaceFile($fileIdentifier, $localFilePath) {
-               $fileUrl = $this->getResourceUrl($fileIdentifier);
-               $fileHandle = fopen($localFilePath, 'r');
-               if (!is_resource($fileHandle)) {
-                       throw new \RuntimeException('Could not open handle for ' . $localFilePath, 1325959311);
-               }
-
-               $this->removeCacheForPath(dirname($fileIdentifier));
-
-               $this->executeDavRequest('PUT', $fileUrl, $fileHandle);
-       }
-
-       /**
-        * Returns information about a file for a given file identifier.
-        *
-        * @param string $identifier The (relative) path to the file.
-        * @param array $propertiesToExtract The properties to get
-        * @return array
-        */
-       public function getFileInfoByIdentifier($identifier, array $propertiesToExtract = array()) {
-               assert($identifier[0] === '/', 'Identifier must start with a slash, got ' . $identifier);
-
-               return $this->getFrontend()->getFileInfo($identifier);
-       }
-
-       /**
-        * Returns the cache identifier for a given path.
-        *
-        * @param string $path
-        * @return string
-        */
-       protected function getCacheIdentifierForPath($path) {
-               return sha1($this->storageUid . ':' . trim($path, '/') . '/');
-       }
-
-       /**
-        * Flushes the cache for a given path inside this storage.
-        *
-        * @param $path
-        * @return void
-        * @deprecated this should be moved to WebDavFrontend
-        */
-       protected function removeCacheForPath($path) {
-               $this->getCache()->remove($this->getCacheIdentifierForPath($path));
-       }
-
-       /**
-        * Copies a file to a temporary path and returns that path. You have to take care of removing the temporary file yourself!
-        *
-        * @param string $fileIdentifier
-        * @return string The temporary path
-        */
-       public function copyFileToTemporaryPath($fileIdentifier) {
-               $temporaryPath = GeneralUtility::tempnam('vfs-tempfile-');
-               $fileUrl = $this->getResourceUrl($fileIdentifier);
-
-               $fileHandle = fopen($temporaryPath, 'w');
-               $fileUrl = $this->encodeUrl($fileUrl);
-               $this->davClient->readUrlToHandle($fileUrl, $fileHandle);
-
-               // the handle is not closed by readUrlToHandle()!
-               fclose($fileHandle);
-
-               return $temporaryPath;
-       }
-
-       /**
-        * 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 string $fileIdentifier
-        * @param string $targetFolderIdentifier
-        * @param string $newFileName
-        *
-        * @return string
-        * @throws FileOperationErrorException
-        */
-       public function moveFileWithinStorage($fileIdentifier, $targetFolderIdentifier, $newFileName) {
-               $newPath = $targetFolderIdentifier . $newFileName;
-
-               try {
-                       $result = $this->executeMoveRequest($fileIdentifier, $newPath);
-               } catch (DAV\Exception $e) {
-                       // TODO insert correct exception here
-                       throw new FileOperationErrorException('Moving file ' . $fileIdentifier
-                               . ' to ' . $newPath . ' failed.', 1325848030);
-               }
-               // TODO check if there are some return codes that signalize an error, but do not throw an exception
-               // status codes: 204: file was overwritten; 201: file was created;
-
-               return $newPath;
-       }
-
-       /**
-        * 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 string $fileIdentifier
-        * @param string $targetFolderIdentifier
-        * @param string $fileName
-        *
-        * @return string the Identifier of the new file
-        * @throws FileOperationErrorException
-        */
-       public function copyFileWithinStorage($fileIdentifier, $targetFolderIdentifier, $fileName) {
-               $oldFileUrl = $this->getResourceUrl($fileIdentifier);
-               $newFileUrl = $this->getResourceUrl($targetFolderIdentifier) . $fileName;
-               $newFileIdentifier = $targetFolderIdentifier . $fileName;
-
-               try {
-                               // force overwriting the file (header Overwrite: T) because the Storage already handled possible conflicts
-                               // for us
-                       $result = $this->executeDavRequest('COPY', $oldFileUrl, NULL, array('Destination' => $newFileUrl, 'Overwrite' => 'T'));
-               } catch (DAV\Exception $e) {
-                       // TODO insert correct exception here
-                       throw new FileOperationErrorException('Copying file ' . $fileIdentifier . ' to '
-                               . $newFileIdentifier . ' failed.', 1325848030);
-               }
-               // TODO check if there are some return codes that signalize an error, but do not throw an exception
-               // status codes: 204: file was overwritten; 201: file was created;
-
-               return $newFileIdentifier;
-       }
-
-       /**
-        * Folder equivalent to moveFileWithinStorage().
-        *
-        * @param string $sourceFolderIdentifier
-        * @param string $targetFolderIdentifier
-        * @param string $newFolderName
-        *
-        * @return array All files which are affected, map of old => new file identifiers
-        * @throws FileOperationErrorException
-        */
-       public function moveFolderWithinStorage($sourceFolderIdentifier, $targetFolderIdentifier, $newFolderName) {
-               $newFolderIdentifier = $targetFolderIdentifier . $newFolderName . '/';
-
-               try {
-                       $result = $this->executeMoveRequest($sourceFolderIdentifier, $newFolderIdentifier);
-               } catch (DAV\Exception $e) {
-                       // TODO insert correct exception here
-                       throw new FileOperationErrorException('Moving folder ' . $sourceFolderIdentifier
-                               . ' to ' . $newFolderIdentifier . ' failed: ' . $e->getMessage(), 1326135944);
-               }
-               // TODO check if there are some return codes that signalize an error, but do not throw an exception
-               // status codes: 204: file was overwritten; 201: file was created;
-
-               // TODO extract mapping of old to new identifiers from server response
-       }
-
-       /**
-        * Folder equivalent to copyFileWithinStorage().
-        *
-        * @param string $sourceFolderIdentifier
-        * @param string $targetFolderIdentifier
-        * @param string $newFolderName
-        *
-        * @return boolean
-        * @throws FileOperationErrorException
-        */
-       public function copyFolderWithinStorage($sourceFolderIdentifier, $targetFolderIdentifier, $newFolderName) {
-               $oldFolderUrl = $this->getResourceUrl($sourceFolderIdentifier);
-               $newFolderUrl = $this->getResourceUrl($targetFolderIdentifier) . $newFolderName . '/';
-               $newFolderIdentifier = $targetFolderIdentifier . $newFolderName . '/';
-
-               try {
-                       $result = $this->executeDavRequest('COPY', $oldFolderUrl, NULL, array('Destination' => $newFolderUrl, 'Overwrite' => 'T'));
-               } catch (DAV\Exception $e) {
-                       // TODO insert correct exception here
-                       throw new FileOperationErrorException('Moving folder ' . $sourceFolderIdentifier
-                               . ' to ' . $newFolderIdentifier . ' failed.', 1326135944);
-               }
-               // TODO check if there are some return codes that signalize an error, but do not throw an exception
-               // status codes: 204: file was overwritten; 201: file was created;
-
-               return $newFolderIdentifier;
-       }
-
-       /**
-        * 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)!
-        *
-        * @param string $fileIdentifier
-        * @return boolean TRUE if the operation succeeded
-        */
-       public function deleteFile($fileIdentifier) {
-               // TODO add unit tests
-               $fileUrl = $this->baseUrl . ltrim($fileIdentifier, '/');
-
-               $result = $this->executeDavRequest('DELETE', $fileUrl);
-
-               // 204 is derived from the answer Apache gives - there might be other status codes that indicate success
-               return ($result['statusCode'] == 204);
-       }
-
-       /**
-        * Returns the root level folder of the storage.
-        *
-        * @return \TYPO3\CMS\Core\Resource\Folder
-        */
-       public function getRootLevelFolder() {
-               return '/';
-       }
-
-       /**
-        * Returns the default folder new files should be put into.
-        *
-        * @return \TYPO3\CMS\Core\Resource\Folder
-        */
-       public function getDefaultFolder() {
-               return '/';
-       }
-
-       /**
-        * Creates a folder, within a parent folder.
-        * If no parent folder is given, a root level folder will be created
-        *
-        * @param string $newFolderName
-        * @param string $parentFolderIdentifier
-        * @param boolean $recursive If set, parent folders will be created if they don’t exist
-        * @return string The new folder’s identifier
-        */
-       public function createFolder($newFolderName, $parentFolderIdentifier = '', $recursive = FALSE) {
-               // TODO test if recursive creation works
-               // We add a slash to the path as some actions require a trailing slash on some servers.
-               // Apache's mod_dav e.g. does not do it for this action, but it does not do harm either, so we add it anyways
-               $folderPath = $parentFolderIdentifier . $newFolderName . '/';
-               $folderUrl = $this->baseUrl . ltrim($folderPath, '/');
-
-               $this->executeDavRequest('MKCOL', $folderUrl);
-
-               $this->removeCacheForPath($parentFolderIdentifier);
-
-               return $folderPath;
-       }
-
-       /**
-        * Checks if a folder exists
-        *
-        * @param string $identifier
-        * @return bool
-        */
-       public function folderExists($identifier) {
-               // TODO add unit test
-               // TODO check if this test suffices to find out if the resource really is a folder - it might not do with some implementations
-               $identifier = '/' . trim($identifier, '/') . '/';
-               return $this->resourceExists($identifier);
-       }
-
-       /**
-        * Checks if a file inside a storage folder exists.
-        *
-        * @param string $folderName
-        * @param string $folderIdentifier
-        * @return bool
-        */
-       public function folderExistsInFolder($folderName, $folderIdentifier) {
-               $folderIdentifier = $folderIdentifier . $folderName . '/';
-               return $this->resourceExists($folderIdentifier);
-       }
-
-       /**
-        * Checks if a given identifier is within a container, e.g. if a file or folder is within another folder.
-        * This can be used to check for webmounts.
-        *
-        * @param string $containerIdentifier
-        * @param string $content
-        * @return bool
-        */
-       public function isWithin($containerIdentifier, $content) {
-               $content = '/' . ltrim($content, '/');
-
-               return GeneralUtility::isFirstPartOfStr($content, $containerIdentifier);
-       }
-
-       /**
-        * Removes a folder from this storage.
-        *
-        * @param string $folderIdentifier
-        * @param bool $deleteRecursively
-        * @return boolean
-        */
-       public function deleteFolder($folderIdentifier, $deleteRecursively = FALSE) {
-               $folderUrl = $this->getResourceUrl($folderIdentifier);
-
-               $this->removeCacheForPath(dirname($folderIdentifier));
-
-                       // We don't need to specify a depth header when deleting (see sect. 9.6.1 of RFC #4718)
-               $this->executeDavRequest('DELETE', $folderUrl, '', array());
-       }
-
-       /**
-        * Renames a folder in this storage.
-        *
-        * @param string $folderIdentifier
-        * @param string $newName The new folder name
-        * @return string The new identifier of the folder if the operation succeeds
-        * @throws \RuntimeException if renaming the folder failed
-        * @throws FileOperationErrorException
-        */
-       public function renameFolder($folderIdentifier, $newName) {
-               $targetPath = dirname($folderIdentifier) . '/' . $newName . '/';
-
-               try {
-                       $result = $this->executeMoveRequest($folderIdentifier, $targetPath);
-               } catch (DAV\Exception $e) {
-                       // TODO insert correct exception here
-                       throw new FileOperationErrorException('Renaming ' . $folderIdentifier . ' to '
-                               . $targetPath . ' failed.', 1325848030);
-               }
-
-               $this->removeCacheForPath(dirname($folderIdentifier));
-
-               return $targetPath;
-       }
-
-       /**
-        * Checks if a folder contains files and (if supported) other folders.
-        *
-        * @param string $folderIdentifier
-        * @return bool TRUE if there are no files and folders within $folder
-        */
-       public function isFolderEmpty($folderIdentifier) {
-               $folderContents = $this->frontend->propFind($folderIdentifier);
-
-               return (count($folderContents) == 1);
-       }
-
-       /**
-        * Merges the capabilites set by the administrator in the storage configuration with the actual capabilities of
-        * this driver and returns the result.
-        *
-        * @param integer $capabilities
-        *
-        * @return integer
-        */
-       public function mergeConfigurationCapabilities($capabilities) {
-               $this->capabilities &= $capabilities;
-               return $this->capabilities;
-       }
-
-       /**
-        * Returns the identifier of the folder the file resides in
-        *
-        * @param string $fileIdentifier
-        *
-        * @return string
-        */
-       public function getParentFolderIdentifierOfIdentifier($fileIdentifier) {
-               return dirname($fileIdentifier);
-       }
-
-       /**
-        * Returns the permissions of a file/folder as an array
-        * (keys r, w) of boolean flags
-        *
-        * @param string $identifier
-        * @return array
-        */
-       public function getPermissions($identifier) {
-               // TODO check this again
-               return array('r' => TRUE, 'w' => TRUE);
-       }
-
-       /**
-        * Directly output the contents of the file to the output
-        * buffer. Should not take care of header files or flushing
-        * buffer before. Will be taken care of by the Storage.
-        *
-        * @param string $identifier
-        * @return void
-        */
-       public function dumpFileContents($identifier) {
-               // TODO: Implement dumpFileContents() method.
-       }
-
-       /**
-        * Returns information about a file.
-        *
-        * @param string $folderIdentifier
-        *
-        * @return array
-        * @throws FolderDoesNotExistException
-        */
-       public function getFolderInfoByIdentifier($folderIdentifier) {
-               if (!$this->folderExists($folderIdentifier)) {
-                       throw new FolderDoesNotExistException(
-                               'Folder ' . $folderIdentifier . ' does not exist.',
-                               1314516810
-                       );
-               }
-               return array(
-                       'identifier' => $folderIdentifier,
-                       'name' => basename($folderIdentifier),
-                       'storage' => $this->storageUid
-               );
-       }
-
-       /**
-        * Returns the identifier of a file inside the folder.
-        *
-        * @param string $fileName
-        * @param string $folderIdentifier
-        * @return string file identifier
-        */
-       public function getFileInFolder($fileName, $folderIdentifier) {
-               return $this->canonicalizeAndCheckFileIdentifier($folderIdentifier . '/' . $fileName);
-       }
-
-       /**
-        * Returns a list of files inside the specified path
-        *
-        * @param string $folderIdentifier
-        * @param integer $start
-        * @param integer $numberOfItems
-        * @param boolean $recursive
-        * @param array $filenameFilterCallbacks callbacks for filtering the items
-        * @param string $sort Property name used to sort the items.
-        *                     Among them may be: '' (empty, no sorting), name,
-        *                     fileext, size, tstamp and rw.
-        *                     If a driver does not support the given property, it
-        *                     should fall back to "name".
-        * @param bool $sortRev TRUE to indicate reverse sorting (last to first)
-        *
-        * @return array of FileIdentifiers
-        */
-       public function getFilesInFolder($folderIdentifier, $start = 0, $numberOfItems = 0, $recursive = FALSE,
-                                        array $filenameFilterCallbacks = array(), $sort = '', $sortRev = FALSE) {
-               $files = $this->getFrontend()->listFiles($folderIdentifier);
-
-               // TODO implement sorting
-
-               $items = array();
-               foreach ($files as $filename) {
-                       $items[$filename] = $folderIdentifier . $filename;
-               }
-
-               return $items;
-       }
-
-       /**
-        * Returns the number of files inside the specified path
-        *
-        * @param string $folderIdentifier
-        * @param boolean $recursive
-        * @param array $filenameFilterCallbacks callbacks for filtering the items
-        * @return integer Number of files in folder
-        */
-       public function countFilesInFolder($folderIdentifier, $recursive = FALSE,
-                                          array $filenameFilterCallbacks = array()) {
-               return count($this->getFrontend()->listFiles($folderIdentifier));
-       }
-
-       /**
-        * Returns the identifier of a folder inside the folder.
-        *
-        * @param string $folderName The name of the target folder
-        * @param string $folderIdentifier
-        * @return string folder identifier
-        */
-       public function getFolderInFolder($folderName, $folderIdentifier) {
-               return $this->canonicalizeAndCheckFolderIdentifier($folderIdentifier . '/' . $folderName);
-       }
-
-       /**
-        * Returns a list of folders inside the specified path
-        *
-        * @param string $folderIdentifier
-        * @param integer $start
-        * @param integer $numberOfItems
-        * @param boolean $recursive
-        * @param array $folderNameFilterCallbacks callbacks for filtering the items
-        * @param string $sort Property name used to sort the items.
-        *                     Among them may be: '' (empty, no sorting), name,
-        *                     fileext, size, tstamp and rw.
-        *                     If a driver does not support the given property, it
-        *                     should fall back to "name".
-        * @param bool $sortRev TRUE to indicate reverse sorting (last to first)
-        *
-        * @return array of folder identifiers
-        */
-       public function getFoldersInFolder($folderIdentifier, $start = 0, $numberOfItems = 0, $recursive = FALSE,
-                                          array $folderNameFilterCallbacks = array(), $sort = '', $sortRev = FALSE) {
-               $folders = $this->getFrontend()->listFolders($folderIdentifier);
-
-               // TODO implement sorting
-
-               $items = array();
-               foreach ($folders as $name) {
-                       $items[$name] = $folderIdentifier . $name . '/';
-               }
-
-               return $items;
-       }
-
-       /**
-        * Returns the number of folders inside the specified path
-        *
-        * @param string $folderIdentifier
-        * @param boolean $recursive
-        * @param array $folderNameFilterCallbacks callbacks for filtering the items
-        * @return integer Number of folders in folder
-        */
-       public function countFoldersInFolder($folderIdentifier, $recursive = FALSE,
-                                            array $folderNameFilterCallbacks = array()) {
-               return count($this->getFrontend()->listFolders($folderIdentifier));
-       }
+class WebDavDriver extends AbstractHierarchicalFilesystemDriver
+{
+
+    /**
+     * The base URL of the WebDAV share. Always ends with a trailing slash.
+     *
+     * @var string
+     */
+    protected $baseUrl = '';
+
+    /**
+     * The base URL to fetch resources. Includes authentication information if authentication is enabled, so this must
+     * never be published!
+     *
+     * @var string
+     */
+    protected $resourceBaseUrl = '';
+
+    /**
+     * The base path of the WebDAV store. This is the URL without protocol, host and port (i.e., only the path on the
+     * host). Always ends with a trailing slash.
+     *
+     * @var string
+     */
+    protected $basePath = '';
+
+    /**
+     * @var WebDavClient
+     */
+    protected $davClient;
+
+    /**
+     * The username to use for connecting to the storage.
+     *
+     * @var string
+     */
+    protected $username = '';
+
+    /**
+     * The password to use for connecting to the storage.
+     *
+     * @var string
+     */
+    protected $password = '';
+
+    /**
+     * @var \TYPO3\CMS\Core\Cache\Frontend\AbstractFrontend
+     */
+    protected $directoryListingCache;
+
+    /**
+     * @var WebDavFrontend
+     */
+    protected $frontend;
+
+    /**
+     * @var \TYPO3\CMS\Core\Log\Logger
+     */
+    protected $logger;
+
+    public function __construct(array $configuration = array())
+    {
+        $this->logger = GeneralUtility::makeInstance('TYPO3\CMS\Core\Log\LogManager')->getLogger(__CLASS__);
+
+        parent::__construct($configuration);
+    }
+
+    /**
+     * Initializes this object. This is called by the storage after the driver has been attached.
+     *
+     * @return void
+     */
+    public function initialize()
+    {
+        $this->capabilities = ResourceStorage::CAPABILITY_BROWSABLE
+            + ResourceStorage::CAPABILITY_PUBLIC
+            + ResourceStorage::CAPABILITY_WRITABLE;
+    }
+
+    /**
+     * Inject method for the DAV client. Mostly useful for unit tests.
+     *
+     * @param WebDavClient $client
+     */
+    public function injectDavClient(WebDavClient $client)
+    {
+        $this->davClient = $client;
+    }
+
+    /**
+     * Only used in tests.
+     *
+     * @param FrontendInterface $cache
+     */
+    public function injectDirectoryListingCache(FrontendInterface $cache)
+    {
+        $this->directoryListingCache = $cache;
+    }
+
+    public function injectFrontend(WebDavFrontend $frontend)
+    {
+        $this->frontend = $frontend;
+    }
+
+    protected function getFrontend()
+    {
+        if (!$this->frontend) {
+            $this->frontend = new CachingWebDavFrontend($this->davClient, $this->baseUrl, $this->storageUid,
+                $this->getCache());
+        }
+
+        return $this->frontend;
+    }
+
+    /**
+     * @return FrontendInterface
+     */
+    protected function getCache()
+    {
+        if (!$this->directoryListingCache) {
+            /** @var CacheManager $cacheManager */
+            $cacheManager = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Cache\\CacheManager');
+            $this->directoryListingCache = $cacheManager->getCache('tx_falwebdav_directorylisting');
+        }
+
+        return $this->directoryListingCache;
+    }
+
+    /**
+     * Processes the configuration coming from the storage record and prepares the SabreDAV object.
+     *
+     * @return void
+     * @throws \InvalidArgumentException
+     */
+    public function processConfiguration()
+    {
+        foreach ($this->configuration as $key => $value) {
+            $this->configuration[$key] = trim($value);
+        }
+
+        $baseUrl = $this->configuration['baseUrl'];
+
+        $urlInfo = parse_url($baseUrl);
+        if ($urlInfo === false) {
+            throw new \InvalidArgumentException('Invalid base URL configured for WebDAV driver: ' . $this->configuration['baseUrl'],
+                1325771040);
+        }
+        $this->basePath = rtrim($urlInfo['path'], '/') . '/';
+
+        $extConf = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['fal_webdav']);
+        $configuration['enableZeroByteFilesIndexing'] = (boolean)$extConf['enableZeroByteFilesIndexing'];
+
+        // Use authentication only if enabled
+        $settings = array();
+        if ($this->configuration['useAuthentication']) {
+            $this->username = $urlInfo['user'] ? $urlInfo['user'] : $this->configuration['username'];
+            $this->password = $urlInfo['pass'] ? $urlInfo['pass'] : EncryptionUtility::decryptPassword($this->configuration['password']);
+            $settings = array(
+                'userName' => $this->username,
+                'password' => $this->password
+            );
+        }
+
+        // make sure the URL contains authentication data and build the resource URL for directly fetching data
+        $urlInfo['user'] = $this->username;
+        $urlInfo['pass'] = $this->password;
+        $this->resourceBaseUrl = rtrim(HttpUtility::buildUrl($urlInfo), '/') . '/';
+        // create cleaned URL without credentials
+        unset($urlInfo['user']);
+        unset($urlInfo['pass']);
+        $this->baseUrl = rtrim(HttpUtility::buildUrl($urlInfo), '/') . '/';
+        $settings['baseUri'] = $this->baseUrl;
+
+        $this->davClient = new WebDavClient($settings);
+        $this->davClient->setThrowExceptions(true);
+
+        $this->davClient->setCertificateVerification($this->configuration['disableCertificateVerification'] != 1);
+    }
+
+    /**
+     * Checks if a configuration is valid for this driver.
+     *
+     * Throws an exception if a configuration will not work.
+     *
+     * @param array $configuration
+     * @return void
+     */
+    public static function verifyConfiguration(array $configuration)
+    {
+        // TODO: Implement verifyConfiguration() method.
+    }
+
+    /**
+     * Executes a MOVE request from $oldPath to $newPath.
+     *
+     * @param string $oldPath
+     * @param string $newPath
+     * @return array The result as returned by SabreDAV
+     */
+    public function executeMoveRequest($oldPath, $newPath)
+    {
+        $oldUrl = $this->baseUrl . ltrim($oldPath, '/');
+        $newUrl = $this->baseUrl . ltrim($newPath, '/');
+
+        // force overwriting the file (header Overwrite: T) because the Storage already handled possible conflicts
+        // for us
+        return $this->executeDavRequest('MOVE', $oldUrl, null, array('Destination' => $newUrl, 'Overwrite' => 'T'));
+    }
+
+    protected function encodeUrl($url)
+    {
+        $urlParts = parse_url($url);
+        $urlParts['path'] = implode('/', array_map('rawurlencode', explode('/', $urlParts['path'])));
+
+        return HttpUtility::buildUrl($urlParts);
+    }
+
+    /**
+     * Executes a request on the DAV driver.
+     *
+     * @param string $method
+     * @param string $url
+     * @param string $body
+     * @param array $headers
+     * @return array
+     * @throws \Exception If anything goes wrong
+     */
+    protected function executeDavRequest($method, $url, $body = null, array $headers = array())
+    {
+        try {
+            $url = $this->encodeUrl($url);
+
+            return $this->davClient->request($method, $url, $body, $headers);
+        } catch (\Sabre\DAV\Exception\NotFound $exception) {
+            // If a file is not found, we have to deal with that on a higher level, so throw the exception again
+            throw $exception;
+        } catch (DAV\Exception $exception) {
+            // log all other exceptions
+            $this->logger->error(sprintf(
+                'Error while executing DAV request. Original message: "%s" (Exception %s, id: %u)',
+                $exception->getMessage(), get_class($exception), $exception->getCode()
+            ));
+
+            // TODO check how we can let this propagate to the driver
+            return array();
+        }
+    }
+
+
+    /**
+     * Checks if a given resource exists in this DAV share.
+     *
+     * @param string $resourcePath The path to the resource, i.e. a regular identifier as used everywhere else here.
+     * @return bool
+     * @throws \InvalidArgumentException
+     */
+    public function resourceExists($resourcePath)
+    {
+        if ($resourcePath == '') {
+            throw new \InvalidArgumentException('Resource path cannot be empty');
+        }
+        $url = $this->baseUrl . ltrim($resourcePath, '/');
+        try {
+            $result = $this->executeDavRequest('HEAD', $url);
+        } catch (\Sabre\Http\HttpException $exception) {
+            return $exception->getHttpStatus() != 404;
+        }
+
+        // TODO check if other status codes may also indicate that the file is not present
+        return $result['statusCode'] < 400;
+    }
+
+
+    /**
+     * Returns the complete URL to a file. This is not necessarily the publicly available URL!
+     *
+     * @param string $file The file object or its identifier
+     * @return string
+     */
+    protected function getResourceUrl($file)
+    {
+        return $this->resourceBaseUrl . ltrim($file, '/');
+    }
+
+    /**
+     * Returns the public URL to a file. This does not contain a username or password, even if this is
+     * necessary to display the file.
+     *
+     * TODO make it optional to include the username/password
+     *
+     * @param string $identifier
+     * @return string
+     */
+    public function getPublicUrl($identifier)
+    {
+        // as the storage is marked as public, we can simply use the public URL here.
+        return $this->baseUrl . ltrim($identifier, '/');
+    }
+
+    /**
+     * Creates a (cryptographic) hash for a file.
+     *
+     * @param string $identifier The file identifier
+     * @param string $hashAlgorithm The hash algorithm to use
+     * @return string
+     * TODO switch parameter order?
+     */
+    public function hash($identifier, $hashAlgorithm)
+    {
+        // TODO add unit test
+        $fileCopy = $this->copyFileToTemporaryPath($identifier);
+
+        switch ($hashAlgorithm) {
+            case 'sha1':
+                $hash = sha1_file($fileCopy);
+                break;
+
+            default:
+                throw new \InvalidArgumentException('Unsupported hash algorithm ' . $hashAlgorithm);
+        }
+
+        unlink($fileCopy);
+
+        return $hash;
+    }
+
+    /**
+     * Creates a new file and returns its identifier.
+     *
+     * @param string $fileName
+     * @param string $parentFolderIdentifier
+     * @return \TYPO3\CMS\Core\Resource\FileInterface
+     */
+    public function createFile($fileName, $parentFolderIdentifier)
+    {
+        $fileIdentifier = $parentFolderIdentifier . $fileName;
+        $fileUrl = $this->baseUrl . ltrim($fileIdentifier, '/');
+
+        $this->executeDavRequest('PUT', $fileUrl, '');
+
+        $this->removeCacheForPath($parentFolderIdentifier);
+
+        return $fileIdentifier;
+    }
+
+    /**
+     * 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 \TYPO3\CMS\Core\Resource\FileInterface $fileIdentifier
+     * @return string The file contents
+     */
+    public function getFileContents($fileIdentifier)
+    {
+        $fileUrl = $this->baseUrl . ltrim($fileIdentifier, '/');
+
+        $result = $this->executeDavRequest('GET', $fileUrl);
+
+        return $result['body'];
+    }
+
+    /**
+     * Sets the contents of a file to the specified value.
+     *
+     * @param string $fileIdentifier
+     * @param string $contents
+     * @return bool TRUE if setting the contents succeeded
+     * @throws \RuntimeException if the operation failed
+     */
+    public function setFileContents($fileIdentifier, $contents)
+    {
+        // Apache returns a "204 no content" status after a successful put operation
+
+        $fileUrl = $this->getResourceUrl($fileIdentifier);
+        $result = $this->executeDavRequest('PUT', $fileUrl, $contents);
+
+        $this->removeCacheForPath(dirname($fileIdentifier));
+
+        // TODO check result
+    }
+
+    /**
+     * 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 (within PATH_site)
+     * @param string $targetFolderIdentifier
+     * @param string $newFileName optional, if not given original name is used
+     * @param boolean $removeOriginal if set the original file will be removed
+     *                                after successful operation
+     * @return string the identifier of the new file
+     */
+    public function addFile($localFilePath, $targetFolderIdentifier, $newFileName = '', $removeOriginal = true)
+    {
+        $fileIdentifier = $targetFolderIdentifier . $newFileName;
+        $fileUrl = $this->baseUrl . ltrim($fileIdentifier);
+
+        $fileHandle = fopen($localFilePath, 'r');
+        if (!is_resource($fileHandle)) {
+            throw new \RuntimeException('Could not open handle for ' . $localFilePath, 1325959310);
+        }
+        $result = $this->executeDavRequest('PUT', $fileUrl, $fileHandle);
+
+        // TODO check result
+
+        $this->removeCacheForPath($targetFolderIdentifier);
+
+        return $fileIdentifier;
+    }
+
+    /**
+     * Checks if a file exists.
+     *
+     * @param string $identifier
+     * @return bool
+     */
+    public function fileExists($identifier)
+    {
+        return substr($identifier, -1) !== '/' && $this->resourceExists($identifier);
+    }
+
+    /**
+     * Checks if a file inside a storage folder exists.
+     *
+     * @param string $fileName
+     * @param string $folderIdentifier
+     * @return boolean
+     */
+    public function fileExistsInFolder($fileName, $folderIdentifier)
+    {
+        // TODO add unit test
+        $fileIdentifier = $folderIdentifier . $fileName;
+
+        return $this->fileExists($fileIdentifier);
+    }
+
+    /**
+     * 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!
+     *
+     * @param string $fileIdentifier
+     * @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
+     */
+    public function getFileForLocalProcessing($fileIdentifier, $writable = true)
+    {
+        return $this->copyFileToTemporaryPath($fileIdentifier);
+    }
+
+    /**
+     * Renames a file
+     *
+     * @param \TYPO3\CMS\Core\Resource\FileInterface $file
+     * @param string $newName
+     * @return string The new identifier of the file
+     */
+    public function renameFile($fileIdentifier, $newName)
+    {
+        // TODO add unit test
+        // Renaming works by invoking the MOVE method on the source URL and providing the new destination in the
+        // "Destination:" HTTP header.
+        $sourcePath = $fileIdentifier;
+        $targetPath = dirname($fileIdentifier) . '/' . $newName;
+
+        $this->executeMoveRequest($sourcePath, $targetPath);
+
+        $this->removeCacheForPath(dirname($fileIdentifier));
+
+        return $targetPath;
+    }
+
+    /**
+     * Replaces the contents (and file-specific metadata) of a file object with a local file.
+     *
+     * @param string $fileIdentifier
+     * @param string $localFilePath
+     * @return bool
+     * @throws \RuntimeException
+     */
+    public function replaceFile($fileIdentifier, $localFilePath)
+    {
+        $fileUrl = $this->getResourceUrl($fileIdentifier);
+        $fileHandle = fopen($localFilePath, 'r');
+        if (!is_resource($fileHandle)) {
+            throw new \RuntimeException('Could not open handle for ' . $localFilePath, 1325959311);
+        }
+
+        $this->removeCacheForPath(dirname($fileIdentifier));
+
+        $this->executeDavRequest('PUT', $fileUrl, $fileHandle);
+    }
+
+    /**
+     * Returns information about a file for a given file identifier.
+     *
+     * @param string $identifier The (relative) path to the file.
+     * @param array $propertiesToExtract The properties to get
+     * @return array
+     */
+    public function getFileInfoByIdentifier($identifier, array $propertiesToExtract = array())
+    {
+        assert($identifier[0] === '/', 'Identifier must start with a slash, got ' . $identifier);
+
+        return $this->getFrontend()->getFileInfo($identifier);
+    }
+
+    /**
+     * Returns the cache identifier for a given path.
+     *
+     * @param string $path
+     * @return string
+     */
+    protected function getCacheIdentifierForPath($path)
+    {
+        return sha1($this->storageUid . ':' . trim($path, '/') . '/');
+    }
+
+    /**
+     * Flushes the cache for a given path inside this storage.
+     *
+     * @param $path
+     * @return void
+     * @deprecated this should be moved to WebDavFrontend
+     */
+    protected function removeCacheForPath($path)
+    {
+        $this->getCache()->remove($this->getCacheIdentifierForPath($path));
+    }
+
+    /**
+     * Copies a file to a temporary path and returns that path. You have to take care of removing the temporary file
+     * yourself!
+     *
+     * @param string $fileIdentifier
+     * @return string The temporary path
+     */
+    public function copyFileToTemporaryPath($fileIdentifier)
+    {
+        $temporaryPath = GeneralUtility::tempnam('vfs-tempfile-');
+        $fileUrl = $this->getResourceUrl($fileIdentifier);
+
+        $fileHandle = fopen($temporaryPath, 'w');
+        $fileUrl = $this->encodeUrl($fileUrl);
+        $this->davClient->readUrlToHandle($fileUrl, $fileHandle);
+
+        // the handle is not closed by readUrlToHandle()!
+        fclose($fileHandle);
+
+        return $temporaryPath;
+    }
+
+    /**
+     * 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 string $fileIdentifier
+     * @param string $targetFolderIdentifier
+     * @param string $newFileName
+     *
+     * @return string
+     * @throws FileOperationErrorException
+     */
+    public function moveFileWithinStorage($fileIdentifier, $targetFolderIdentifier, $newFileName)
+    {
+        $newPath = $targetFolderIdentifier . $newFileName;
+
+        try {
+            $result = $this->executeMoveRequest($fileIdentifier, $newPath);
+        } catch (DAV\Exception $e) {
+            // TODO insert correct exception here
+            throw new FileOperationErrorException('Moving file ' . $fileIdentifier
+                . ' to ' . $newPath . ' failed.', 1325848030);
+        }
+        // TODO check if there are some return codes that signalize an error, but do not throw an exception
+        // status codes: 204: file was overwritten; 201: file was created;
+
+        return $newPath;
+    }
+
+    /**
+     * 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 string $fileIdentifier
+     * @param string $targetFolderIdentifier
+     * @param string $fileName
+     *
+     * @return string the Identifier of the new file
+     * @throws FileOperationErrorException
+     */
+    public function copyFileWithinStorage($fileIdentifier, $targetFolderIdentifier, $fileName)
+    {
+        $oldFileUrl = $this->getResourceUrl($fileIdentifier);
+        $newFileUrl = $this->getResourceUrl($targetFolderIdentifier) . $fileName;
+        $newFileIdentifier = $targetFolderIdentifier . $fileName;
+
+        try {
+            // force overwriting the file (header Overwrite: T) because the Storage already handled possible conflicts
+            // for us
+            $result = $this->executeDavRequest('COPY', $oldFileUrl, null,
+                array('Destination' => $newFileUrl, 'Overwrite' => 'T'));
+        } catch (DAV\Exception $e) {
+            // TODO insert correct exception here
+            throw new FileOperationErrorException('Copying file ' . $fileIdentifier . ' to '
+                . $newFileIdentifier . ' failed.', 1325848030);
+        }
+        // TODO check if there are some return codes that signalize an error, but do not throw an exception
+        // status codes: 204: file was overwritten; 201: file was created;
+
+        return $newFileIdentifier;
+    }
+
+    /**
+     * Folder equivalent to moveFileWithinStorage().
+     *
+     * @param string $sourceFolderIdentifier
+     * @param string $targetFolderIdentifier
+     * @param string $newFolderName
+     *
+     * @return array All files which are affected, map of old => new file identifiers
+     * @throws FileOperationErrorException
+     */
+    public function moveFolderWithinStorage($sourceFolderIdentifier, $targetFolderIdentifier, $newFolderName)
+    {
+        $newFolderIdentifier = $targetFolderIdentifier . $newFolderName . '/';
+
+        try {
+            $result = $this->executeMoveRequest($sourceFolderIdentifier, $newFolderIdentifier);
+        } catch (DAV\Exception $e) {
+            // TODO insert correct exception here
+            throw new FileOperationErrorException('Moving folder ' . $sourceFolderIdentifier
+                . ' to ' . $newFolderIdentifier . ' failed: ' . $e->getMessage(), 1326135944);
+        }
+        // TODO check if there are some return codes that signalize an error, but do not throw an exception
+        // status codes: 204: file was overwritten; 201: file was created;
+
+        // TODO extract mapping of old to new identifiers from server response
+    }
+
+    /**
+     * Folder equivalent to copyFileWithinStorage().
+     *
+     * @param string $sourceFolderIdentifier
+     * @param string $targetFolderIdentifier
+     * @param string $newFolderName
+     *
+     * @return boolean
+     * @throws FileOperationErrorException
+     */
+    public function copyFolderWithinStorage($sourceFolderIdentifier, $targetFolderIdentifier, $newFolderName)
+    {
+        $oldFolderUrl = $this->getResourceUrl($sourceFolderIdentifier);
+        $newFolderUrl = $this->getResourceUrl($targetFolderIdentifier) . $newFolderName . '/';
+        $newFolderIdentifier = $targetFolderIdentifier . $newFolderName . '/';
+
+        try {
+            $result = $this->executeDavRequest('COPY', $oldFolderUrl, null,
+                array('Destination' => $newFolderUrl, 'Overwrite' => 'T'));
+        } catch (DAV\Exception $e) {
+            // TODO insert correct exception here
+            throw new FileOperationErrorException('Moving folder ' . $sourceFolderIdentifier
+                . ' to ' . $newFolderIdentifier . ' failed.', 1326135944);
+        }
+        // TODO check if there are some return codes that signalize an error, but do not throw an exception
+        // status codes: 204: file was overwritten; 201: file was created;
+
+        return $newFolderIdentifier;
+    }
+
+    /**
+     * 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)!
+     *
+     * @param string $fileIdentifier
+     * @return boolean TRUE if the operation succeeded
+     */
+    public function deleteFile($fileIdentifier)
+    {
+        // TODO add unit tests
+        $fileUrl = $this->baseUrl . ltrim($fileIdentifier, '/');
+
+        $result = $this->executeDavRequest('DELETE', $fileUrl);
+
+        // 204 is derived from the answer Apache gives - there might be other status codes that indicate success
+        return ($result['statusCode'] == 204);
+    }
+
+    /**
+     * Returns the root level folder of the storage.
+     *
+     * @return \TYPO3\CMS\Core\Resource\Folder
+     */
+    public function getRootLevelFolder()
+    {
+        return '/';
+    }
+
+    /**
+     * Returns the default folder new files should be put into.
+     *
+     * @return \TYPO3\CMS\Core\Resource\Folder
+     */
+    public function getDefaultFolder()
+    {
+        return '/';
+    }
+
+    /**
+     * Creates a folder, within a parent folder.
+     * If no parent folder is given, a root level folder will be created
+     *
+     * @param string $newFolderName
+     * @param string $parentFolderIdentifier
+     * @param boolean $recursive If set, parent folders will be created if they don’t exist
+     * @return string The new folder’s identifier
+     */
+    public function createFolder($newFolderName, $parentFolderIdentifier = '', $recursive = false)
+    {
+        // TODO test if recursive creation works
+        // We add a slash to the path as some actions require a trailing slash on some servers.
+        // Apache's mod_dav e.g. does not do it for this action, but it does not do harm either, so we add it anyways
+        $folderPath = $parentFolderIdentifier . $newFolderName . '/';
+        $folderUrl = $this->baseUrl . ltrim($folderPath, '/');
+
+        $this->executeDavRequest('MKCOL', $folderUrl);
+
+        $this->removeCacheForPath($parentFolderIdentifier);
+
+        return $folderPath;
+    }
+
+    /**
+     * Checks if a folder exists
+     *
+     * @param string $identifier
+     * @return bool
+     */
+    public function folderExists($identifier)
+    {
+        // TODO add unit test
+        // TODO check if this test suffices to find out if the resource really is a folder - it might not do with some implementations
+        $identifier = '/' . trim($identifier, '/') . '/';
+
+        return $this->resourceExists($identifier);
+    }
+
+    /**
+     * Checks if a file inside a storage folder exists.
+     *
+     * @param string $folderName
+     * @param string $folderIdentifier
+     * @return bool
+     */
+    public function folderExistsInFolder($folderName, $folderIdentifier)
+    {
+        $folderIdentifier = $folderIdentifier . $folderName . '/';
+
+        return $this->resourceExists($folderIdentifier);
+    }
+
+    /**
+     * Checks if a given identifier is within a container, e.g. if a file or folder is within another folder.
+     * This can be used to check for webmounts.
+     *
+     * @param string $containerIdentifier
+     * @param string $content
+     * @return bool
+     */
+    public function isWithin($containerIdentifier, $content)
+    {
+        $content = '/' . ltrim($content, '/');
+
+        return GeneralUtility::isFirstPartOfStr($content, $containerIdentifier);
+    }
+
+    /**
+     * Removes a folder from this storage.
+     *
+     * @param string $folderIdentifier
+     * @param bool $deleteRecursively
+     * @return boolean
+     */
+    public function deleteFolder($folderIdentifier, $deleteRecursively = false)
+    {
+        $folderUrl = $this->getResourceUrl($folderIdentifier);
+
+        $this->removeCacheForPath(dirname($folderIdentifier));
+
+        // We don't need to specify a depth header when deleting (see sect. 9.6.1 of RFC #4718)
+        $this->executeDavRequest('DELETE', $folderUrl, '', array());
+    }
+
+    /**
+     * Renames a folder in this storage.
+     *
+     * @param string $folderIdentifier
+     * @param string $newName The new folder name
+     * @return string The new identifier of the folder if the operation succeeds
+     * @throws \RuntimeException if renaming the folder failed
+     * @throws FileOperationErrorException
+     */
+    public function renameFolder($folderIdentifier, $newName)
+    {
+        $targetPath = dirname($folderIdentifier) . '/' . $newName . '/';
+
+        try {
+            $result = $this->executeMoveRequest($folderIdentifier, $targetPath);
+        } catch (DAV\Exception $e) {
+            // TODO insert correct exception here
+            throw new FileOperationErrorException('Renaming ' . $folderIdentifier . ' to '
+                . $targetPath . ' failed.', 1325848030);
+        }
+
+        $this->removeCacheForPath(dirname($folderIdentifier));
+
+        return $targetPath;
+    }
+
+    /**
+     * Checks if a folder contains files and (if supported) other folders.
+     *
+     * @param string $folderIdentifier
+     * @return bool TRUE if there are no files and folders within $folder
+     */
+    public function isFolderEmpty($folderIdentifier)
+    {
+        $folderContents = $this->frontend->propFind($folderIdentifier);
+
+        return (count($folderContents) == 1);
+    }
+
+    /**
+     * Merges the capabilites set by the administrator in the storage configuration with the actual capabilities of
+     * this driver and returns the result.
+     *
+     * @param integer $capabilities
+     *
+     * @return integer
+     */
+    public function mergeConfigurationCapabilities($capabilities)
+    {
+        $this->capabilities &= $capabilities;
+
+        return $this->capabilities;
+    }
+
+    /**
+     * Returns the identifier of the folder the file resides in
+     *
+     * @param string $fileIdentifier
+     *
+     * @return string
+     */
+    public function getParentFolderIdentifierOfIdentifier($fileIdentifier)
+    {
+        return dirname($fileIdentifier);
+    }
+
+    /**
+     * Returns the permissions of a file/folder as an array
+     * (keys r, w) of boolean flags
+     *
+     * @param string $identifier
+     * @return array
+     */
+    public function getPermissions($identifier)
+    {
+        // TODO check this again
+        return array('r' => true, 'w' => true);
+    }
+
+    /**
+     * Directly output the contents of the file to the output
+     * buffer. Should not take care of header files or flushing
+     * buffer before. Will be taken care of by the Storage.
+     *
+     * @param string $identifier
+     * @return void
+     */
+    public function dumpFileContents($identifier)
+    {
+        // TODO: Implement dumpFileContents() method.
+    }
+
+    /**
+     * Returns information about a file.
+     *
+     * @param string $folderIdentifier
+     *
+     * @return array
+     * @throws FolderDoesNotExistException
+     */
+    public function getFolderInfoByIdentifier($folderIdentifier)
+    {
+        if (!$this->folderExists($folderIdentifier)) {
+            throw new FolderDoesNotExistException(
+                'Folder ' . $folderIdentifier . ' does not exist.',
+                1314516810
+            );
+        }
+
+        return array(
+            'identifier' => $folderIdentifier,
+            'name' => basename($folderIdentifier),
+            'storage' => $this->storageUid
+        );
+    }
+
+    /**
+     * Returns the identifier of a file inside the folder.
+     *
+     * @param string $fileName
+     * @param string $folderIdentifier
+     * @return string file identifier
+     */
+    public function getFileInFolder($fileName, $folderIdentifier)
+    {
+        return $this->canonicalizeAndCheckFileIdentifier($folderIdentifier . '/' . $fileName);
+    }
+
+    /**
+     * Returns a list of files inside the specified path
+     *
+     * @param string $folderIdentifier
+     * @param integer $start
+     * @param integer $numberOfItems
+     * @param boolean $recursive
+     * @param array $filenameFilterCallbacks callbacks for filtering the items
+     * @param string $sort Property name used to sort the items.
+     *                     Among them may be: '' (empty, no sorting), name,
+     *                     fileext, size, tstamp and rw.
+     *                     If a driver does not support the given property, it
+     *                     should fall back to "name".
+     * @param bool $sortRev TRUE to indicate reverse sorting (last to first)
+     *
+     * @return array of FileIdentifiers
+     */
+    public function getFilesInFolder(
+        $folderIdentifier,
+        $start = 0,
+        $numberOfItems = 0,
+        $recursive = false,
+        array $filenameFilterCallbacks = array(),
+        $sort = '',
+        $sortRev = false
+    ) {
+        $files = $this->getFrontend()->listFiles($folderIdentifier);
+
+        // TODO implement sorting
+
+        $items = array();
+        foreach ($files as $filename) {
+            $items[$filename] = $folderIdentifier . $filename;
+        }
+
+        return $items;
+    }
+
+    /**
+     * Returns the number of files inside the specified path
+     *
+     * @param string $folderIdentifier
+     * @param boolean $recursive
+     * @param array $filenameFilterCallbacks callbacks for filtering the items
+     * @return integer Number of files in folder
+     */
+    public function countFilesInFolder(
+        $folderIdentifier,
+        $recursive = false,
+        array $filenameFilterCallbacks = array()
+    ) {
+        return count($this->getFrontend()->listFiles($folderIdentifier));
+    }
+
+    /**
+     * Returns the identifier of a folder inside the folder.
+     *
+     * @param string $folderName The name of the target folder
+     * @param string $folderIdentifier
+     * @return string folder identifier
+     */
+    public function getFolderInFolder($folderName, $folderIdentifier)
+    {
+        return $this->canonicalizeAndCheckFolderIdentifier($folderIdentifier . '/' . $folderName);
+    }
+
+    /**
+     * Returns a list of folders inside the specified path
+     *
+     * @param string $folderIdentifier
+     * @param integer $start
+     * @param integer $numberOfItems
+     * @param boolean $recursive
+     * @param array $folderNameFilterCallbacks callbacks for filtering the items
+     * @param string $sort Property name used to sort the items.
+     *                     Among them may be: '' (empty, no sorting), name,
+     *                     fileext, size, tstamp and rw.
+     *                     If a driver does not support the given property, it
+     *                     should fall back to "name".
+     * @param bool $sortRev TRUE to indicate reverse sorting (last to first)
+     *
+     * @return array of folder identifiers
+     */
+    public function getFoldersInFolder(
+        $folderIdentifier,
+        $start = 0,
+        $numberOfItems = 0,
+        $recursive = false,
+        array $folderNameFilterCallbacks = array(),
+        $sort = '',
+        $sortRev = false
+    ) {
+        $folders = $this->getFrontend()->listFolders($folderIdentifier);
+
+        // TODO implement sorting
+
+        $items = array();
+        foreach ($folders as $name) {
+            $items[$name] = $folderIdentifier . $name . '/';
+        }
+
+        return $items;
+    }
+
+    /**
+     * Returns the number of folders inside the specified path
+     *
+     * @param string $folderIdentifier
+     * @param boolean $recursive
+     * @param array $folderNameFilterCallbacks callbacks for filtering the items
+     * @return integer Number of folders in folder
+     */
+    public function countFoldersInFolder(
+        $folderIdentifier,
+        $recursive = false,
+        array $folderNameFilterCallbacks = array()
+    ) {
+        return count($this->getFrontend()->listFolders($folderIdentifier));
+    }
 
 }
index 6b6e299..ebb3682 100644 (file)
@@ -1,7 +1,8 @@
 <?php
 namespace TYPO3\FalWebdav\Utility;
 
-use \TYPO3\CMS\Core\Utility;
+use TYPO3\CMS\Core\Utility;
+
 
 /**
  * Utility methods for encrypting/decrypting data. Currently only supports Blowfish encryption in CBC mode,
@@ -10,176 +11,191 @@ use \TYPO3\CMS\Core\Utility;
  *
  * @author Andreas Wolf <andreas.wolf@ikt-werk.de>
  */
-class EncryptionUtility {
-
-       protected static $encryptionMethod = MCRYPT_BLOWFISH;
-
-       protected static $encryptionMode = MCRYPT_MODE_CBC;
-
-       /**
-        * @var \TYPO3\CMS\Core\Log\Logger
-        */
-       protected static $logger;
-
-       public static function getEncryptionMethod() {
-               return self::$encryptionMethod;
-       }
-
-       public static function getEncryptionMode() {
-               return self::$encryptionMode;
-       }
-
-       /**
-        * Returns TRUE if the mcrypt extension is available.
-        *
-        * @return bool
-        */
-       public static function isMcryptAvailable() {
-               return extension_loaded('mcrypt');
-       }
-
-       /**
-        * @return \TYPO3\CMS\Core\Log\Logger
-        */
-       protected static function getLogger() {
-               if (self::$logger === NULL) {
-                       /** @var $logManager \TYPO3\CMS\Core\Log\LogManager */
-                       $logManager = Utility\GeneralUtility::makeInstance('TYPO3\CMS\Core\Log\LogManager');
-
-                       self::$logger = $logManager->getLogger(__CLASS__);
-               }
-
-               return self::$logger;
-       }
-
-       /**
-        * Returns an initialization vector suitable for the chosen encryption method.
-        *
-        * @param string $encryptionMethod
-        * @param string $encryptionMode
-        * @return string
-        */
-       protected static function getInitializationVector($encryptionMethod = NULL, $encryptionMode = NULL) {
-               if (!$encryptionMethod) {
-                       $encryptionMethod = self::$encryptionMethod;
-               }
-               if (!$encryptionMode) {
-                       $encryptionMode = self::$encryptionMode;
-               }
-
-               $iv_size = mcrypt_get_iv_size($encryptionMethod, $encryptionMode);
-               $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
-               return $iv;
-       }
-
-       /**
-        * Creates and returns a resource pointer for the encryption method. This is required for e.g. retrieving an
-        * encryption key.
-        *
-        * @param string $encryptionMethod
-        * @param string $encryptionMode
-        * @return resource
-        */
-       protected static function createEncryptionContext($encryptionMethod = NULL, $encryptionMode = NULL) {
-               if (!$encryptionMethod) {
-                       $encryptionMethod = self::$encryptionMethod;
-               }
-               if (!$encryptionMode) {
-                       $encryptionMode = self::$encryptionMode;
-               }
-
-               $td = mcrypt_module_open($encryptionMethod, '', $encryptionMode, '');
-               return $td;
-       }
-
-       /**
-        * @param $td
-        * @return string
-        */
-       protected static function getEncryptionKey($td) {
-               $ks = mcrypt_enc_get_key_size($td);
-               $key = substr(md5($GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey']), 0, $ks);
-               return $key;
-       }
-
-       /**
-        * Encrypts a password. The algorithm used and - if necessary - the initialization vector are stored within the
-        * password string. The encrypted password itself is stored base64 encoded to make it possible to store this password
-        * in an XML structure.
-        *
-        * @param $value
-        * @return string
-        * @see decryptPassword()
-        */
-       public static function encryptPassword($value) {
-               if ($value == '') {
-                       return '';
-               }
-               if (!self::isMcryptAvailable()) {
-                       self::getLogger()->error('Encryption utility is not available. See reports module for more information.');
-                       return '';
-               }
-
-               $td = self::createEncryptionContext();
-               $iv = self::getInitializationVector();
-               $key = self::getEncryptionKey($td);
-               mcrypt_generic_init($td, $key, $iv);
-
-               $encryptedPassword = mcrypt_generic($td, $value);
-               mcrypt_generic_deinit($td);
-
-               $encryptedText = sprintf('$%s$%s$%s$%s',
-                       self::$encryptionMethod,
-                       self::$encryptionMode,
-                       base64_encode($iv),
-                       base64_encode($encryptedPassword)
-               );
-
-                       // close the module opened for encrypting
-               mcrypt_module_close($td);
-
-               return $encryptedText;
-       }
-
-       /**
-        * Decrypts a password. The necessary initialization vector is extracted from the password.
-        *
-        * @param string $encryptedPassword
-        * @return string
-        * @see encryptPassword()
-        */
-       public static function decryptPassword($encryptedPassword) {
-               if ($encryptedPassword == '') {
-                       return '';
-               }
-               if (!self::isMcryptAvailable()) {
-                       self::getLogger()->error('Encryption utility is not available. See reports module for more information.');
-                       return '';
-               }
-
-               if (substr_count($encryptedPassword, '$') > 0) {
-                       $passwordParts = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode('$', $encryptedPassword, TRUE);
-                               // Base64 decoding the password is done below
-                       $encryptedPassword = $passwordParts[3];
-
-                       $encryptionMethod = $passwordParts[0];
-                       $mode = $passwordParts[1];
-                       $td = self::createEncryptionContext($encryptionMethod, $mode);
-
-                       $iv = base64_decode($passwordParts[2]);
-               } else {
-                       $td = self::createEncryptionContext(self::$encryptionMethod, self::$encryptionMode);
-                       $iv = self::getInitializationVector();
-               }
-               $key = self::getEncryptionKey($td);
-
-               mcrypt_generic_init($td, $key, $iv);
-               $decryptedPassword = trim(mdecrypt_generic($td, base64_decode($encryptedPassword)));
-               mcrypt_generic_deinit($td);
-
-                       // close the module opened for decrypting
-               mcrypt_module_close($td);
-
-               return $decryptedPassword;
-       }
+class EncryptionUtility
+{
+
+    protected static $encryptionMethod = MCRYPT_BLOWFISH;
+
+    protected static $encryptionMode = MCRYPT_MODE_CBC;
+
+    /**
+     * @var \TYPO3\CMS\Core\Log\Logger
+     */
+    protected static $logger;
+
+    public static function getEncryptionMethod()
+    {
+        return self::$encryptionMethod;
+    }
+
+    public static function getEncryptionMode()
+    {
+        return self::$encryptionMode;
+    }
+
+    /**
+     * Returns TRUE if the mcrypt extension is available.
+     *
+     * @return bool
+     */
+    public static function isMcryptAvailable()
+    {
+        return extension_loaded('mcrypt');
+    }
+
+    /**
+     * @return \TYPO3\CMS\Core\Log\Logger
+     */
+    protected static function getLogger()
+    {
+        if (self::$logger === null) {
+            /** @var $logManager \TYPO3\CMS\Core\Log\LogManager */
+            $logManager = Utility\GeneralUtility::makeInstance('TYPO3\CMS\Core\Log\LogManager');
+
+            self::$logger = $logManager->getLogger(__CLASS__);
+        }
+
+        return self::$logger;
+    }
+
+    /**
+     * Returns an initialization vector suitable for the chosen encryption method.
+     *
+     * @param string $encryptionMethod
+     * @param string $encryptionMode
+     * @return string
+     */
+    protected static function getInitializationVector($encryptionMethod = null, $encryptionMode = null)
+    {
+        if (!$encryptionMethod) {
+            $encryptionMethod = self::$encryptionMethod;
+        }
+        if (!$encryptionMode) {
+            $encryptionMode = self::$encryptionMode;
+        }
+
+        $iv_size = mcrypt_get_iv_size($encryptionMethod, $encryptionMode);
+        $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
+
+        return $iv;
+    }
+
+    /**
+     * Creates and returns a resource pointer for the encryption method. This is required for e.g. retrieving an
+     * encryption key.
+     *
+     * @param string $encryptionMethod
+     * @param string $encryptionMode
+     * @return resource
+     */
+    protected static function createEncryptionContext($encryptionMethod = null, $encryptionMode = null)
+    {
+        if (!$encryptionMethod) {
+            $encryptionMethod = self::$encryptionMethod;
+        }
+        if (!$encryptionMode) {
+            $encryptionMode = self::$encryptionMode;
+        }
+
+        $td = mcrypt_module_open($encryptionMethod, '', $encryptionMode, '');
+
+        return $td;
+    }
+
+    /**
+     * @param $td
+     * @return string
+     */
+    protected static function getEncryptionKey($td)
+    {
+        $ks = mcrypt_enc_get_key_size($td);
+        $key = substr(md5($GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey']), 0, $ks);
+
+        return $key;
+    }
+
+    /**
+     * Encrypts a password. The algorithm used and - if necessary - the initialization vector are stored within the
+     * password string. The encrypted password itself is stored base64 encoded to make it possible to store this
+     * password in an XML structure.
+     *
+     * @param $value
+     * @return string
+     * @see decryptPassword()
+     */
+    public static function encryptPassword($value)
+    {
+        if ($value == '') {
+            return '';
+        }
+        if (!self::isMcryptAvailable()) {
+            self::getLogger()->error('Encryption utility is not available. See reports module for more information.');
+
+            return '';
+        }
+
+        $td = self::createEncryptionContext();
+        $iv = self::getInitializationVector();
+        $key = self::getEncryptionKey($td);
+        mcrypt_generic_init($td, $key, $iv);
+
+        $encryptedPassword = mcrypt_generic($td, $value);
+        mcrypt_generic_deinit($td);
+
+        $encryptedText = sprintf('$%s$%s$%s$%s',
+            self::$encryptionMethod,
+            self::$encryptionMode,
+            base64_encode($iv),
+            base64_encode($encryptedPassword)
+        );
+
+        // close the module opened for encrypting
+        mcrypt_module_close($td);
+
+        return $encryptedText;
+    }
+
+    /**
+     * Decrypts a password. The necessary initialization vector is extracted from the password.
+     *
+     * @param string $encryptedPassword
+     * @return string
+     * @see encryptPassword()
+     */
+    public static function decryptPassword($encryptedPassword)
+    {
+        if ($encryptedPassword == '') {
+            return '';
+        }
+        if (!self::isMcryptAvailable()) {
+            self::getLogger()->error('Encryption utility is not available. See reports module for more information.');
+
+            return '';
+        }
+
+        if (substr_count($encryptedPassword, '$') > 0) {
+            $passwordParts = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode('$', $encryptedPassword, true);
+            // Base64 decoding the password is done below
+            $encryptedPassword = $passwordParts[3];
+
+            $encryptionMethod = $passwordParts[0];
+            $mode = $passwordParts[1];
+            $td = self::createEncryptionContext($encryptionMethod, $mode);
+
+            $iv = base64_decode($passwordParts[2]);
+        } else {
+            $td = self::createEncryptionContext(self::$encryptionMethod, self::$encryptionMode);
+            $iv = self::getInitializationVector();
+        }
+        $key = self::getEncryptionKey($td);
+
+        mcrypt_generic_init($td, $key, $iv);
+        $decryptedPassword = trim(mdecrypt_generic($td, base64_decode($encryptedPassword)));
+        mcrypt_generic_deinit($td);
+
+        // close the module opened for decrypting
+        mcrypt_module_close($td);
+
+        return $decryptedPassword;
+    }
 }
\ No newline at end of file
index 41bd102..430ae65 100644 (file)
@@ -6,26 +6,29 @@ namespace TYPO3\FalWebdav\Utility;
  *
  * @author Andreas Wolf <andreas.wolf@ikt-werk.de>
  */
-class UrlTools {
-       /**
-        * Helper method to extract the username and password from a url. Returns username, password and the url without
-        * authentication info.
-        *
-        * @param string
-        * @return array An array with the cleaned url, the username and the password as entries
-        */
-       public static function extractUsernameAndPasswordFromUrl($url) {
-               $urlInfo = parse_url($url);
+class UrlTools
+{
+    /**
+     * Helper method to extract the username and password from a url. Returns username, password and the url without
+     * authentication info.
+     *
+     * @param string
+     * @return array An array with the cleaned url, the username and the password as entries
+     */
+    public static function extractUsernameAndPasswordFromUrl($url)
+    {
+        $urlInfo = parse_url($url);
 
-               $user = $pass = '';
-               if (isset($urlInfo['user'])) {
-                       $user = $urlInfo['user'];
-                       unset($urlInfo['user']);
-               }
-               if (isset($urlInfo['pass'])) {
-                       $pass = $urlInfo['pass'];
-                       unset($urlInfo['pass']);
-               }
-               return array(\TYPO3\CMS\Core\Utility\HttpUtility::buildUrl($urlInfo), $user, $pass);
-       }
+        $user = $pass = '';
+        if (isset($urlInfo['user'])) {
+            $user = $urlInfo['user'];
+            unset($urlInfo['user']);
+        }
+        if (isset($urlInfo['pass'])) {
+            $pass = $urlInfo['pass'];
+            unset($urlInfo['pass']);
+        }
+
+        return array(\TYPO3\CMS\Core\Utility\HttpUtility::buildUrl($urlInfo), $user, $pass);
+    }
 }
index ec8e486..7dda0d7 100644 (file)
@@ -1,25 +1,25 @@
 <?php
 namespace TYPO3\FalWebdav\Tests\Backend;
 
-/*                                                                        *
- * This script belongs to the TYPO3 project.                              *
- *                                                                        *
- * It 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.                                             *
- *                                                                        *
- * This script is distributed in the hope that it will be useful, but     *
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN-    *
- * TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General      *
- * Public License for more details.                                       *
- *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with the script.                                                 *
- * If not, see http://www.gnu.org/licenses/gpl.html                       *
- *                                                                        *
- * The TYPO3 project - inspiring people to share!                         *
- *                                                                        */
+    /*                                                                        *
    * This script belongs to the TYPO3 project.                              *
    *                                                                        *
    * It 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.                                             *
    *                                                                        *
    * This script is distributed in the hope that it will be useful, but     *
    * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN-    *
    * TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General      *
    * Public License for more details.                                       *
    *                                                                        *
    * You should have received a copy of the GNU General Public License      *
    * along with the script.                                                 *
    * If not, see http://www.gnu.org/licenses/gpl.html                       *
    *                                                                        *
    * The TYPO3 project - inspiring people to share!                         *
    *                                                                        */
 
 /**
  * Testcase for the WebDAV driver configuration TCEmain hook.
@@ -28,71 +28,80 @@ namespace TYPO3\FalWebdav\Tests\Backend;
  * @package TYPO3
  * @subpackage fal_webdav
  */
-class TceMainHookTest extends \Tx_Phpunit_TestCase {
+class TceMainHookTest extends \Tx_Phpunit_TestCase
+{
 
-       /**
-        * @var \TYPO3\FalWebdav\Backend\TceMainHook
-        */
-       protected $fixture;
+    /**
+     * @var \TYPO3\FalWebdav\Backend\TceMainHook
+     */
+    protected $fixture;
 
-       public function setUp() {
-               $this->fixture = new \TYPO3\FalWebdav\Backend\TceMainHook();
-       }
+    public function setUp()
+    {
+        $this->fixture = new \TYPO3\FalWebdav\Backend\TceMainHook();
+    }
 
-       protected function prepareFieldArrayFixture(array $fieldValues) {
-               $fieldArray = array(
-                       'configuration' => array(
-                               'data' => array(
-                                       'sDEF' => array(
-                                               'lDEF' => array(
-                                                               // preset the driver as the TCEmain hook checks this
-                                                       'driver' => array(
-                                                               'vDEF' => 'WebDav'
-                                                       )
-                                               )
-                                       )
-                               )
-                       )
-               );
+    protected function prepareFieldArrayFixture(array $fieldValues)
+    {
+        $fieldArray = array(
+            'configuration' => array(
+                'data' => array(
+                    'sDEF' => array(
+                        'lDEF' => array(
+                            // preset the driver as the TCEmain hook checks this
+                            'driver' => array(
+                                'vDEF' => 'WebDav'
+                            )
+                        )
+                    )
+                )
+            )
+        );
 
-               foreach ($fieldValues as $field => $value) {
-                       $fieldArray['configuration']['data']['sDEF']['lDEF'][$field] = array(
-                               'vDEF' => $value
-                       );
-               }
-               return $fieldArray;
-       }
+        foreach ($fieldValues as $field => $value) {
+            $fieldArray['configuration']['data']['sDEF']['lDEF'][$field] = array(
+                'vDEF' => $value
+            );
+        }
 
-       /**
-        * @test
-        */
-       public function usernameAndPasswordFromUrlOverrideSetValuesInConfigurationFields() {
-               $fieldArray = $this->prepareFieldArrayFixture(array(
-                       'baseUrl' => 'http://newUser:newPass@localhost/some/storage/',
-                       'username' => 'oldUser',
-                       'password' => 'oldPassword'
-               ));
+        return $fieldArray;
+    }
 
-               $this->fixture->processDatamap_preProcessFieldArray($fieldArray, 'sys_file_storage', -1, new \StdClass());
+    /**
+     * @test
+     */
+    public function usernameAndPasswordFromUrlOverrideSetValuesInConfigurationFields()
+    {
+        $fieldArray = $this->prepareFieldArrayFixture(array(
+            'baseUrl' => 'http://newUser:newPass@localhost/some/storage/',
+            'username' => 'oldUser',
+            'password' => 'oldPassword'
+        ));
 
-               $this->assertEquals('newUser', $fieldArray['configuration']['data']['sDEF']['lDEF']['username']['vDEF']);
-               $this->assertEquals('newPass', \TYPO3\FalWebdav\Utility\Encryption::decryptPassword($fieldArray['configuration']['data']['sDEF']['lDEF']['password']['vDEF']));
-               $this->assertEquals('http://localhost/some/storage/', $fieldArray['configuration']['data']['sDEF']['lDEF']['baseUrl']['vDEF']);
-       }
+        $this->fixture->processDatamap_preProcessFieldArray($fieldArray, 'sys_file_storage', -1, new \StdClass());
 
-       /**
-        * @test
-        */
-       public function usernameAndPasswordInConfigurationFieldsAreLeftUnchangedIfNoAuthenticationInfoIsGivenInUrl() {
-               $fieldArray = $this->prepareFieldArrayFixture(array(
-                       'baseUrl' => 'http://localhost/some/storage/',
-                       'username' => 'oldUser',
-                       'password' => 'oldPassword'
-               ));
+        $this->assertEquals('newUser', $fieldArray['configuration']['data']['sDEF']['lDEF']['username']['vDEF']);
+        $this->assertEquals('newPass',
+            \TYPO3\FalWebdav\Utility\Encryption::decryptPassword($fieldArray['configuration']['data']['sDEF']['lDEF']['password']['vDEF']));
+        $this->assertEquals('http://localhost/some/storage/',
+            $fieldArray['configuration']['data']['sDEF']['lDEF']['baseUrl']['vDEF']);
+    }
 
-               $this->fixture->processDatamap_preProcessFieldArray($fieldArray, 'sys_file_storage', -1, new \StdClass());
+    /**
+     * @test
+     */
+    public function usernameAndPasswordInConfigurationFieldsAreLeftUnchangedIfNoAuthenticationInfoIsGivenInUrl()
+    {
+        $fieldArray = $this->prepareFieldArrayFixture(array(
+            'baseUrl' => 'http://localhost/some/storage/',
+            'username' => 'oldUser',
+            'password' => 'oldPassword'
+        ));
 
-               $this->assertEquals('oldUser', $fieldArray['configuration']['data']['sDEF']['lDEF']['username']['vDEF']);
-               $this->assertEquals('oldPassword', \TYPO3\FalWebdav\Utility\Encryption::decryptPassword($fieldArray['configuration']['data']['sDEF']['lDEF']['password']['vDEF']));
-       }
+        $this->fixture->processDatamap_preProcessFieldArray($fieldArray, 'sys_file_storage', -1, new \StdClass());
+
+        $this->assertEquals('oldUser', $fieldArray['configuration']['data']['sDEF']['lDEF']['username']['vDEF']);
+        $this->assertEquals('oldPassword',
+            \TYPO3\FalWebdav\Utility\Encryption::decryptPassword($fieldArray['configuration']['data']['sDEF']['lDEF']['password']['vDEF']));
+    }
 }
index bad1bbe..454492d 100644 (file)
@@ -33,200 +33,221 @@ use TYPO3\FalWebdav\Dav\WebDavClient;
  * @package TYPO3
  * @subpackage fal_webdav
  */
-class WebDavDriverTest extends \TYPO3\CMS\Core\Tests\Unit\Resource\BaseTestCase {
-
-       /**
-        * @var \TYPO3\FalWebdav\Driver\WebDavDriver
-        */
-       protected $fixture;
-
-       /**
-        * @var string
-        */
-       protected $baseUrl;
-
-       public function setUp() {
-               $this->baseUrl = 'http://example.org/webdav-root/';
-       }
-
-       protected function mockDavClient() {
-               return $this->getMock('TYPO3\FalWebdav\Dav\WebDavClient', array(), array(), '', FALSE);
-       }
-
-       protected function prepareFixture(WebDavClient $client = NULL, $storageUid = NULL) {
-               if ($client === NULL) {
-                       $client = $this->mockDavClient();
-               }
-               if ($storageUid === NULL) {
-                       $storageUid = 1;
-               }
-
-               $this->fixture = new \TYPO3\FalWebdav\Driver\WebDavDriver(array('baseUrl' => $this->baseUrl));
-               $this->fixture->setStorageUid($storageUid);
-               $this->fixture->injectDirectoryListingCache($this->getMock('TYPO3\CMS\Core\Cache\Frontend\FrontendInterface'));
-               $this->fixture->processConfiguration();
-               $this->fixture->injectDavClient($client);
-               $this->fixture->initialize();
-       }
-
-       /**
-        * @test
-        */
-       public function createFileIssuesCorrectCommandOnServer() {
-               /** @var $clientMock WebDavClient */
-               $clientMock = $this->mockDavClient();
-               $clientMock->expects($this->once())->method('request')->with($this->equalTo('PUT'), $this->stringEndsWith('/someFile'));
-               $this->prepareFixture($clientMock);
-               $mockedFolder = '/';
-
-               $this->fixture->createFile('someFile', $mockedFolder);
-       }
-
-       /**
-        * @test
-        * @return \TYPO3\CMS\Core\Resource\Folder
-        */
-       public function createFolderIssuesCorrectCreateCommandOnServer() {
-               /** @var $clientMock WebDavClient */
-               $clientMock = $this->mockDavClient();
-               $clientMock->expects($this->at(0))->method('request')->with($this->equalTo('MKCOL'), $this->stringEndsWith('/mainFolder/subFolder/'));
-               $this->prepareFixture($clientMock);
-               $mockedFolder = '/mainFolder/';
-
-               return $this->fixture->createFolder('subFolder', $mockedFolder);
-       }
-
-       /**
-        * @test
-        * @depends createFolderIssuesCorrectCreateCommandOnServer
-        * @param string $folderIdentifier
-        */
-       public function createFolderReturnsObjectWithCorrectIdentifier($folderIdentifier) {
-               $this->assertEquals('/mainFolder/subFolder/', $folderIdentifier);
-       }
-
-       /**
-        * @test
-        */
-       public function copyFileToTemporaryPathCreatesLocalCopyOfFile() {
-               $fileContents = uniqid();
-
-               /** @var $clientMock WebDavClient */
-               $clientMock = $this->mockDavClient();
-               $clientMock->expects($this->once())->method('request')->with($this->equalTo('GET'), $this->stringEndsWith('/mainFolder/file.txt'))
-                       ->will($this->returnValue(array('body' => $fileContents)));
-               $this->prepareFixture($clientMock);
-               $mockedFile = '/mainFolder/file.txt';
-
-               $temporaryPath = $this->fixture->copyFileToTemporaryPath($mockedFile);
-               $this->assertEquals($fileContents, file_get_contents($temporaryPath));
-
-               unlink($temporaryPath);
-       }
-
-       /**
-        * @test
-        */
-       public function moveFileWithinStorageIssuesCorrectCommand() {
-               $mockedFile = '/someFile';
-               $mockedFolder = '/targetFolder/';
-
-               /** @var $clientMock WebDavClient */
-               $clientMock = $this->mockDavClient();
-                       // TODO make the parameter matching here more special as soon as PHPUnit supports doing so
-               $clientMock->expects($this->once())->method('request')->with($this->equalTo('MOVE'), $this->stringEndsWith('/someFile'),
-                       NULL, $this->logicalAnd($this->contains($this->baseUrl . 'targetFolder/movedFile'), $this->contains('T')));
-               $this->prepareFixture($clientMock);
-
-               $newFileIdentifier = $this->fixture->moveFileWithinStorage($mockedFile, $mockedFolder, 'movedFile');
-
-               $this->assertEquals('/targetFolder/movedFile', $newFileIdentifier);
-       }
-
-       /**
-        * @return array
-        */
-       public function isWithin_dataProvider() {
-               return array(
-                       'file in folder' => array(
-                               '/someFolder',
-                               '/someFolder/file',
-                               TRUE
-                       ),
-                       'file within subfolder' => array(
-                               '/someFolder',
-                               '/someFolder/someOtherFolder/file',
-                               TRUE
-                       ),
-                       'file in root folder' => array(
-                               '/',
-                               '/file',
-                               TRUE
-                       )
-               );
-       }
-
-       /**
-        * @test
-        * @dataProvider isWithin_dataProvider
-        */
-       public function isWithinCorrectlyDetectsPaths($containerPath, $contentPath, $expectedResult) {
-               $mockedFolder = $containerPath;
-               $this->prepareFixture();
-
-               $actualResult = $this->fixture->isWithin($mockedFolder, $contentPath);
-
-               $this->assertEquals($expectedResult, $actualResult);
-       }
-
-       /**
-        * @test
-        */
-       public function setFileContentsIssuesCorrectCommandOnServer() {
-               $fileContents = uniqid();
-               /** @var $clientMock WebDavClient */
-               $clientMock = $this->mockDavClient();
-               $clientMock->expects($this->once())->method('request')->with($this->equalTo('PUT'), $this->stringEndsWith('/someFile'), $fileContents);
-               $this->prepareFixture($clientMock);
-               $mockedFile = '/someFile';
-
-               $this->fixture->setFileContents($mockedFile, $fileContents);
-       }
-
-       /**
-        * @test
-        */
-       public function getPublicUrlReturnsCorrectUrlIfStorageIsPublic() {
-               $mockedStorage = $this->getMock(ResourceStorage::class, array(), array(), '', FALSE);
-               $mockedStorage->expects($this->any())->method('isPublic')->will($this->returnValue(TRUE));
-               $this->prepareFixture();
-
-               $this->fixture->getPublicUrl('/someFolder/someFile.jpg');
-       }
-
-       /**
-        * @test
-        */
-       public function deleteFolderIssuesCorrectCommandOnServer() {
-               /** @var $clientMock WebDavClient */
-               $clientMock = $this->mockDavClient();
-               $clientMock->expects($this->once())->method('request')->with($this->equalTo('DELETE'), $this->stringEndsWith('/someFolder/'));
-               $this->prepareFixture($clientMock);
-
-               $this->fixture->deleteFolder('/someFolder/');
-       }
-
-       /**
-        * @test
-        */
-       public function timeoutOnRequestThrowsException() {
-               $this->markTestSkipped('This test needs to be adjusted (timeout configuration, exception class)');
-               $this->setExpectedException('Sabre_DAV_Exception_Timeout');
-
-                       // 192.0.2.0/24 is a network that should be used in documentation and for tests, but not in the wild;
-                       // see http://tools.ietf.org/html/rfc5737
-               $client = new WebDavClient(array('baseUri' => 'http://192.0.2.1/', 'timeout' => 5));
-
-               print_r($client->request('GET', '/something'));
-       }
+class WebDavDriverTest extends \TYPO3\CMS\Core\Tests\Unit\Resource\BaseTestCase
+{
+
+    /**
+     * @var \TYPO3\FalWebdav\Driver\WebDavDriver
+     */
+    protected $fixture;
+
+    /**
+     * @var string
+     */
+    protected $baseUrl;
+
+    public function setUp()
+    {
+        $this->baseUrl = 'http://example.org/webdav-root/';
+    }
+
+    protected function mockDavClient()
+    {
+        return $this->getMock('TYPO3\FalWebdav\Dav\WebDavClient', array(), array(), '', false);
+    }
+
+    protected function prepareFixture(WebDavClient $client = null, $storageUid = null)
+    {
+        if ($client === null) {
+            $client = $this->mockDavClient();
+        }
+        if ($storageUid === null) {
+            $storageUid = 1;
+        }
+
+        $this->fixture = new \TYPO3\FalWebdav\Driver\WebDavDriver(array('baseUrl' => $this->baseUrl));
+        $this->fixture->setStorageUid($storageUid);
+        $this->fixture->injectDirectoryListingCache($this->getMock('TYPO3\CMS\Core\Cache\Frontend\FrontendInterface'));
+        $this->fixture->processConfiguration();
+        $this->fixture->injectDavClient($client);
+        $this->fixture->initialize();
+    }
+
+    /**
+     * @test
+     */
+    public function createFileIssuesCorrectCommandOnServer()
+    {
+        /** @var $clientMock WebDavClient */
+        $clientMock = $this->mockDavClient();
+        $clientMock->expects($this->once())->method('request')->with($this->equalTo('PUT'),
+            $this->stringEndsWith('/someFile'));
+        $this->prepareFixture($clientMock);
+        $mockedFolder = '/';
+
+        $this->fixture->createFile('someFile', $mockedFolder);
+    }
+
+    /**
+     * @test
+     * @return \TYPO3\CMS\Core\Resource\Folder
+     */
+    public function createFolderIssuesCorrectCreateCommandOnServer()
+    {
+        /** @var $clientMock WebDavClient */
+        $clientMock = $this->mockDavClient();
+        $clientMock->expects($this->at(0))->method('request')->with($this->equalTo('MKCOL'),
+            $this->stringEndsWith('/mainFolder/subFolder/'));
+        $this->prepareFixture($clientMock);
+        $mockedFolder = '/mainFolder/';
+
+        return $this->fixture->createFolder('subFolder', $mockedFolder);
+    }
+
+    /**
+     * @test
+     * @depends createFolderIssuesCorrectCreateCommandOnServer
+     * @param string $folderIdentifier
+     */
+    public function createFolderReturnsObjectWithCorrectIdentifier($folderIdentifier)
+    {
+        $this->assertEquals('/mainFolder/subFolder/', $folderIdentifier);
+    }
+
+    /**
+     * @test
+     */
+    public function copyFileToTemporaryPathCreatesLocalCopyOfFile()
+    {
+        $fileContents = uniqid();
+
+        /** @var $clientMock WebDavClient */
+        $clientMock = $this->mockDavClient();
+        $clientMock->expects($this->once())->method('request')->with($this->equalTo('GET'),
+            $this->stringEndsWith('/mainFolder/file.txt'))
+            ->will($this->returnValue(array('body' => $fileContents)));
+        $this->prepareFixture($clientMock);
+        $mockedFile = '/mainFolder/file.txt';
+
+        $temporaryPath = $this->fixture->copyFileToTemporaryPath($mockedFile);
+        $this->assertEquals($fileContents, file_get_contents($temporaryPath));
+
+        unlink($temporaryPath);
+    }
+
+    /**
+     * @test
+     */
+    public function moveFileWithinStorageIssuesCorrectCommand()
+    {
+        $mockedFile = '/someFile';
+        $mockedFolder = '/targetFolder/';
+
+        /** @var $clientMock WebDavClient */
+        $clientMock = $this->mockDavClient();
+        // TODO make the parameter matching here more special as soon as PHPUnit supports doing so
+        $clientMock->expects($this->once())->method('request')->with($this->equalTo('MOVE'),
+            $this->stringEndsWith('/someFile'),
+            null, $this->logicalAnd($this->contains($this->baseUrl . 'targetFolder/movedFile'), $this->contains('T')));
+        $this->prepareFixture($clientMock);
+
+        $newFileIdentifier = $this->fixture->moveFileWithinStorage($mockedFile, $mockedFolder, 'movedFile');
+
+        $this->assertEquals('/targetFolder/movedFile', $newFileIdentifier);
+    }
+
+    /**
+     * @return array
+     */
+    public function isWithin_dataProvider()
+    {
+        return array(
+            'file in folder' => array(
+                '/someFolder',
+                '/someFolder/file',
+                true
+            ),
+            'file within subfolder' => array(
+                '/someFolder',
+                '/someFolder/someOtherFolder/file',
+                true
+            ),
+            'file in root folder' => array(
+                '/',
+                '/file',
+                true
+            )
+        );
+    }
+
+    /**
+     * @test
+     * @dataProvider isWithin_dataProvider
+     */
+    public function isWithinCorrectlyDetectsPaths($containerPath, $contentPath, $expectedResult)
+    {
+        $mockedFolder = $containerPath;
+        $this->prepareFixture();
+
+        $actualResult = $this->fixture->isWithin($mockedFolder, $contentPath);
+
+        $this->assertEquals($expectedResult, $actualResult);
+    }
+
+    /**
+     * @test
+     */
+    public function setFileContentsIssuesCorrectCommandOnServer()
+    {
+        $fileContents = uniqid();
+        /** @var $clientMock WebDavClient */
+        $clientMock = $this->mockDavClient();
+        $clientMock->expects($this->once())->method('request')->with($this->equalTo('PUT'),
+            $this->stringEndsWith('/someFile'), $fileContents);
+        $this->prepareFixture($clientMock);
+        $mockedFile = '/someFile';
+
+        $this->fixture->setFileContents($mockedFile, $fileContents);
+    }
+
+    /**
+     * @test
+     */
+    public function getPublicUrlReturnsCorrectUrlIfStorageIsPublic()
+    {
+        $mockedStorage = $this->getMock(ResourceStorage::class, array(), array(), '', false);
+        $mockedStorage->expects($this->any())->method('isPublic')->will($this->returnValue(true));
+        $this->prepareFixture();
+
+        $this->fixture->getPublicUrl('/someFolder/someFile.jpg');
+    }
+
+    /**
+     * @test
+     */
+    public function deleteFolderIssuesCorrectCommandOnServer()
+    {
+        /** @var $clientMock WebDavClient */
+        $clientMock = $this->mockDavClient();
+        $clientMock->expects($this->once())->method('request')->with($this->equalTo('DELETE'),
+            $this->stringEndsWith('/someFolder/'));
+        $this->prepareFixture($clientMock);
+
+        $this->fixture->deleteFolder('/someFolder/');
+    }
+
+    /**
+     * @test
+     */
+    public function timeoutOnRequestThrowsException()
+    {
+        $this->markTestSkipped('This test needs to be adjusted (timeout configuration, exception class)');
+        $this->setExpectedException('Sabre_DAV_Exception_Timeout');
+
+        // 192.0.2.0/24 is a network that should be used in documentation and for tests, but not in the wild;
+        // see http://tools.ietf.org/html/rfc5737
+        $client = new WebDavClient(array('baseUri' => 'http://192.0.2.1/', 'timeout' => 5));
+
+        print_r($client->request('GET', '/something'));
+    }
 }
index 509742e..a9d4f6c 100644 (file)
@@ -1,25 +1,25 @@
 <?php
 namespace TYPO3\FalWebdav\Tests\Utility;
 
-/*                                                                        *
- * This script belongs to the TYPO3 project.                              *
- *                                                                        *
- * It 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.                                             *
- *                                                                        *
- * This script is distributed in the hope that it will be useful, but     *
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN-    *
- * TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General      *
- * Public License for more details.                                       *
- *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with the script.                                                 *
- * If not, see http://www.gnu.org/licenses/gpl.html                       *
- *                                                                        *
- * The TYPO3 project - inspiring people to share!                         *
- *                                                                        */
+    /*                                                                        *
    * This script belongs to the TYPO3 project.                              *
    *                                                                        *
    * It 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.                                             *
    *                                                                        *
    * This script is distributed in the hope that it will be useful, but     *
    * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN-    *
    * TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General      *
    * Public License for more details.                                       *
    *                                                                        *
    * You should have received a copy of the GNU General Public License      *
    * along with the script.                                                 *
    * If not, see http://www.gnu.org/licenses/gpl.html                       *
    *                                                                        *
    * The TYPO3 project - inspiring people to share!                         *
    *                                                                        */
 
 /**
  * Testcase for the WebDAV driver encryption tools
@@ -28,49 +28,54 @@ namespace TYPO3\FalWebdav\Tests\Utility;
  * @package TYPO3
  * @subpackage fal_webdav
  */
-class EncryptionTest extends \Tx_Phpunit_TestCase {
-       /**
-        * @test
-        */
-       public function passwordsCanBeEncryptedAndDecrypted() {
-               $password = uniqid();
+class EncryptionTest extends \Tx_Phpunit_TestCase
+{
+    /**
+     * @test
+     */
+    public function passwordsCanBeEncryptedAndDecrypted()
+    {
+        $password = uniqid();
 
-               $encryptedPassword = \TYPO3\FalWebdav\Utility\Encryption::encryptPassword($password);
-               $decryptedPassword = \TYPO3\FalWebdav\Utility\Encryption::decryptPassword($encryptedPassword);
+        $encryptedPassword = \TYPO3\FalWebdav\Utility\Encryption::encryptPassword($password);
+        $decryptedPassword = \TYPO3\FalWebdav\Utility\Encryption::decryptPassword($encryptedPassword);
 
-               $this->assertEquals($password, $decryptedPassword);
-       }
+        $this->assertEquals($password, $decryptedPassword);
+    }
 
-       /**
-        * @test
-        */
-       public function encryptedPasswordContainsAlgorithm() {
-               $password = uniqid();
+    /**
+     * @test
+     */
+    public function encryptedPasswordContainsAlgorithm()
+    {
+        $password = uniqid();
 
-               $encryptedPassword = \TYPO3\FalWebdav\Utility\Encryption::encryptPassword($password);
+        $encryptedPassword = \TYPO3\FalWebdav\Utility\Encryption::encryptPassword($password);
 
-               $this->assertStringStartsWith(
-                       sprintf('$%s$%s$',
-                               \TYPO3\FalWebdav\Utility\Encryption::getEncryptionMethod(),
-                               \TYPO3\FalWebdav\Utility\Encryption::getEncryptionMode()
-                       ),
-                       $encryptedPassword
-               );
-       }
+        $this->assertStringStartsWith(
+            sprintf('$%s$%s$',
+                \TYPO3\FalWebdav\Utility\Encryption::getEncryptionMethod(),
+                \TYPO3\FalWebdav\Utility\Encryption::getEncryptionMode()
+            ),
+            $encryptedPassword
+        );
+    }
 
-       /**
-        * @test
-        */
-       public function encryptingEmptyStringReturnsEmptyString() {
-               $encryptedPassword = \TYPO3\FalWebdav\Utility\Encryption::encryptPassword('');
+    /**
+     * @test
+     */
+    public function encryptingEmptyStringReturnsEmptyString()
+    {
+        $encryptedPassword = \TYPO3\FalWebdav\Utility\Encryption::encryptPassword('');
 
-               $this->assertEmpty($encryptedPassword);
-       }
+        $this->assertEmpty($encryptedPassword);
+    }
 
-       /**
-        * @test
-        */
-       public function decryptingEmptyStringReturnsEmptyString() {
-               $this->assertEquals('', \TYPO3\FalWebdav\Utility\Encryption::decryptPassword(''));
-       }
+    /**
+     * @test
+     */
+    public function decryptingEmptyStringReturnsEmptyString()
+    {
+        $this->assertEquals('', \TYPO3\FalWebdav\Utility\Encryption::decryptPassword(''));
+    }
 }
\ No newline at end of file
index 28b8832..fd8dab8 100644 (file)
@@ -6,36 +6,39 @@ namespace TYPO3\FalWebdav\Tests\Utility;
  *
  * @author Andreas Wolf <andreas.wolf@ikt-werk.de>
  */
-class UrlToolsTest extends \Tx_Phpunit_TestCase {
+class UrlToolsTest extends \Tx_Phpunit_TestCase
+{
 
-       public function urlDataProvider() {
-               return array(
-                       'regular URL with username and password' => array(
-                               'http://someuser:somepass@localhost/test.php',
-                               array('http://localhost/test.php', 'someuser', 'somepass')
-                       ),
-                       'URL with just user' => array(
-                               'http://someuser@localhost/test.php',
-                               array('http://localhost/test.php', 'someuser', '')
-                       ),
-                       'HTTPS URL with username and password' => array(
-                               'https://someuser:somepass@localhost/test.php',
-                               array('https://localhost/test.php', 'someuser', 'somepass')
-                       ),
-                       'URL without authentication' => array(
-                               'http://localhost/test.php',
-                               array('http://localhost/test.php', '', '')
-                       )
-               );
-       }
+    public function urlDataProvider()
+    {
+        return array(
+            'regular URL with username and password' => array(
+                'http://someuser:somepass@localhost/test.php',
+                array('http://localhost/test.php', 'someuser', 'somepass')
+            ),
+            'URL with just user' => array(
+                'http://someuser@localhost/test.php',
+                array('http://localhost/test.php', 'someuser', '')
+            ),
+            'HTTPS URL with username and password' => array(
+                'https://someuser:somepass@localhost/test.php',
+                array('https://localhost/test.php', 'someuser', 'somepass')
+            ),
+            'URL without authentication' => array(
+                'http://localhost/test.php',
+                array('http://localhost/test.php', '', '')
+            )
+        );
+    }
 
-       /**
-        * @test
-        * @dataProvider urlDataProvider
-        */
-       public function usernameAndPasswordAreProperlyExtractedFromUrl($url, $expectedOutput) {
-               $output = \TYPO3\FalWebdav\Utility\UrlTools::extractUsernameAndPasswordFromUrl($url);
+    /**
+     * @test
+     * @dataProvider urlDataProvider
+     */
+    public function usernameAndPasswordAreProperlyExtractedFromUrl($url, $expectedOutput)
+    {
+        $output = \TYPO3\FalWebdav\Utility\UrlTools::extractUsernameAndPasswordFromUrl($url);
 
-               $this->assertEquals($expectedOutput, $output);
-       }
+        $this->assertEquals($expectedOutput, $output);
+    }
 }
index ee82505..38d50c7 100644 (file)
 ########################################################################
 
 $EM_CONF[$_EXTKEY] = array(
-       'title' => 'WebDAV driver for FAL',
-       'description' => 'Provides a WebDAV driver for the TYPO3 File Abstraction Layer.',
-       'category' => 'be',
-       'author' => 'Andreas Wolf',
-       'author_email' => 'andreas.wolf@typo3.org',
-       'shy' => '',
-       'dependencies' => '',
-       'conflicts' => '',
-       'priority' => '',
-       'module' => '',
-       'state' => 'beta',
-       'internal' => '',
-       'uploadfolder' => 0,
-       'createDirs' => '',
-       'modify_tables' => '',
-       'clearCacheOnLoad' => 0,
-       'lockType' => '',
-       'author_company' => '',
-       'version' => '1.0.0-dev',
-       'constraints' => array(
-               'depends' => array(
-                       'typo3' => '6.0.0-'
-               ),
-               'conflicts' => array(
-               ),
-               'suggests' => array(
-               ),
-       ),
-       '_md5_values_when_last_written' => 'a:5:{s:9:"ChangeLog";s:4:"6f31";s:10:"README.txt";s:4:"ee2d";s:12:"ext_icon.gif";s:4:"1bdc";s:19:"doc/wizard_form.dat";s:4:"c0c7";s:20:"doc/wizard_form.html";s:4:"4670";}',
+    'title' => 'WebDAV driver for FAL',
+    'description' => 'Provides a WebDAV driver for the TYPO3 File Abstraction Layer.',
+    'category' => 'be',
+    'author' => 'Andreas Wolf',
+    'author_email' => 'andreas.wolf@typo3.org',
+    'shy' => '',
+    'dependencies' => '',
+    'conflicts' => '',
+    'priority' => '',
+    'module' => '',
+    'state' => 'beta',
+    'internal' => '',
+    'uploadfolder' => 0,
+    'createDirs' => '',
+    'modify_tables' => '',
+    'clearCacheOnLoad' => 0,
+    'lockType' => '',
+    'author_company' => '',
+    'version' => '1.0.0-dev',
+    'constraints' => array(
+        'depends' => array(
+            'typo3' => '6.0.0-'
+        ),
+        'conflicts' => array(),
+        'suggests' => array(),
+    ),
+    '_md5_values_when_last_written' => 'a:5:{s:9:"ChangeLog";s:4:"6f31";s:10:"README.txt";s:4:"ee2d";s:12:"ext_icon.gif";s:4:"1bdc";s:19:"doc/wizard_form.dat";s:4:"c0c7";s:20:"doc/wizard_form.html";s:4:"4670";}',
 );
 
 ?>
\ No newline at end of file
index 1c2206d..05e4315 100644 (file)
@@ -1,25 +1,26 @@
 <?php
 
 if (!defined('TYPO3_MODE')) {
-       die('Access denied.');
+    die('Access denied.');
 }
 
 include_once \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath('fal_webdav')
-       . 'Resources/Composer/vendor/autoload.php';
+    . 'Resources/Composer/vendor/autoload.php';
 
 /** @var \TYPO3\CMS\Core\Resource\Driver\DriverRegistry $registry */
 $registry = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\CMS\Core\Resource\Driver\DriverRegistry');
-$registry->registerDriverClass('TYPO3\FalWebdav\Driver\WebDavDriver', 'WebDav', 'WebDAV', 'FILE:EXT:fal_webdav/Configuration/FlexForm/WebDavDriverFlexForm.xml');
+$registry->registerDriverClass('TYPO3\FalWebdav\Driver\WebDavDriver', 'WebDav', 'WebDAV',
+    'FILE:EXT:fal_webdav/Configuration/FlexForm/WebDavDriverFlexForm.xml');
 
 $TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processDatamapClass']['fal_webdav'] = 'TYPO3\\FalWebdav\\Backend\\TceMainHook';
 
 
-       // Cache configuration, see http://wiki.typo3.org/Caching_Framework
+// Cache configuration, see http://wiki.typo3.org/Caching_Framework
 if (!is_array($TYPO3_CONF_VARS['SYS']['caching']['cacheConfigurations']['tx_falwebdav_directorylisting'])) {
-       $TYPO3_CONF_VARS['SYS']['caching']['cacheConfigurations']['tx_falwebdav_directorylisting'] = array(
-               'frontend' => 'TYPO3\CMS\Core\Cache\Frontend\VariableFrontend',
-               'backend' => 'TYPO3\CMS\Core\Cache\Backend\TransientMemoryBackend',
-               'options' => array(),
-               'groups' => array()
+    $TYPO3_CONF_VARS['SYS']['caching']['cacheConfigurations']['tx_falwebdav_directorylisting'] = array(
+        'frontend' => 'TYPO3\CMS\Core\Cache\Frontend\VariableFrontend',
+        'backend' => 'TYPO3\CMS\Core\Cache\Backend\TransientMemoryBackend',
+        'options' => array(),
+        'groups' => array()
     );
 }