diff --git a/apps/files_external/tests/env/start-webdav-apache.sh b/apps/files_external/tests/env/start-webdav-apache.sh new file mode 100755 index 0000000000..48acb8572d --- /dev/null +++ b/apps/files_external/tests/env/start-webdav-apache.sh @@ -0,0 +1,90 @@ +#!/bin/bash +# +# ownCloud +# +# This script start a docker container to test the files_external tests +# against. It will also change the files_external config to use the docker +# container as testing environment. This is reverted in the stop step. +# +# If the environment variable RUN_DOCKER_MYSQL is set the ownCloud will +# be set up using MySQL instead of SQLite. +# +# Set environment variable DEBUG to print config file +# +# @author Morris Jobke +# @copyright 2014 Morris Jobke +# @copyright 2016 Vincent Petry +# + +if ! command -v docker >/dev/null 2>&1; then + echo "No docker executable found - skipped docker setup" + exit 0; +fi + +echo "Docker executable found - setup docker" + +echo "Fetch recent morrisjobke/webdav docker image" +docker pull morrisjobke/webdav + +# retrieve current folder to place the config in the parent folder +thisFolder=`echo $0 | sed 's#env/start-webdav-apache\.sh##'` + +if [ -z "$thisFolder" ]; then + thisFolder="." +fi; + +if [ -n "$RUN_DOCKER_MYSQL" ]; then + echo "Fetch recent mysql docker image" + docker pull mysql + + echo "Setup MySQL ..." + # user/password will be read by ENV variables in owncloud container (they are generated by docker) + databaseContainer=`docker run -e MYSQL_ROOT_PASSWORD=mysupersecretpassword -d mysql` + containerName=`docker inspect $databaseContainer | grep Name | grep _ | cut -d \" -f 4 | cut -d / -f 2` + + parameter="--link $containerName:db" +fi + +container=`docker run -P $parameter -d -e USERNAME=test -e PASSWORD=test morrisjobke/webdav` +host=`docker inspect --format="{{.NetworkSettings.IPAddress}}" $container` + +echo -n "Waiting for Apache initialization on ${host}:${port}" +if ! "$thisFolder"/env/wait-for-connection ${host} 80 60; then + echo "[ERROR] Waited 60 seconds, no response" >&2 + exit 1 +fi + +# wait at least 5 more seconds - sometimes the webserver still needs some additional time +sleep 5 + +cat > $thisFolder/config.webdav.php <true, + 'host'=>'${host}:80/webdav/', + 'user'=>'test', + 'password'=>'test', + 'root'=>'', + // wait delay in seconds after write operations + // (only in tests) + // set to higher value for lighttpd webdav + 'wait'=> 0 +); + +DELIM + +echo "ownCloud container: $container" + +# put container IDs into a file to drop them after the test run (keep in mind that multiple tests run in parallel on the same host) +echo $container >> $thisFolder/dockerContainerWebdav.$EXECUTOR_NUMBER.webdav + +if [ -n "$databaseContainer" ]; then + echo "Database container: $databaseContainer" + echo $databaseContainer >> $thisFolder/dockerContainerWebdav.$EXECUTOR_NUMBER.webdav +fi + +if [ -n "$DEBUG" ]; then + cat $thisFolder/config.webdav.php + cat $thisFolder/dockerContainerWebdav.$EXECUTOR_NUMBER.webdav +fi diff --git a/apps/files_external/tests/env/stop-webdav-apache.sh b/apps/files_external/tests/env/stop-webdav-apache.sh new file mode 100755 index 0000000000..e898a65cc3 --- /dev/null +++ b/apps/files_external/tests/env/stop-webdav-apache.sh @@ -0,0 +1,37 @@ +#!/bin/bash +# +# ownCloud +# +# This script stops the docker container the files_external tests were run +# against. It will also revert the config changes done in start step. +# +# @author Morris Jobke +# @copyright 2014 Morris Jobke +# @copyright 2016 Vincent Petry +# + +if ! command -v docker >/dev/null 2>&1; then + echo "No docker executable found - skipped docker stop" + exit 0; +fi + +echo "Docker executable found - stop and remove docker containers" + +# retrieve current folder to remove the config from the parent folder +thisFolder=`echo $0 | sed 's#env/stop-webdav-apache\.sh##'` + +if [ -z "$thisFolder" ]; then + thisFolder="." +fi; + +# stopping and removing docker containers +for container in `cat $thisFolder/dockerContainerWebdav.$EXECUTOR_NUMBER.webdav`; do + echo "Stopping and removing docker container $container" + # kills running container and removes it + docker rm -f $container +done; + +# cleanup +rm $thisFolder/config.webdav.php +rm $thisFolder/dockerContainerWebdav.$EXECUTOR_NUMBER.webdav + diff --git a/lib/private/Files/Storage/DAV.php b/lib/private/Files/Storage/DAV.php index 04910ece68..0d41b3bab0 100644 --- a/lib/private/Files/Storage/DAV.php +++ b/lib/private/Files/Storage/DAV.php @@ -449,7 +449,16 @@ class DAV extends Common { if ($this->file_exists($path)) { try { $this->statCache->remove($path); - $this->client->proppatch($this->encodePath($path), array('{DAV:}lastmodified' => $mtime)); + $this->client->proppatch($this->encodePath($path), ['{DAV:}lastmodified' => $mtime]); + // non-owncloud clients might not have accepted the property, need to recheck it + $response = $this->client->propfind($this->encodePath($path), ['{DAV:}getlastmodified'], 0); + if (isset($response['{DAV:}getlastmodified'])) { + $remoteMtime = strtotime($response['{DAV:}getlastmodified']); + if ($remoteMtime !== $mtime) { + // server has not accepted the mtime + return false; + } + } } catch (ClientHttpException $e) { if ($e->getHttpStatus() === 501) { return false; @@ -506,13 +515,18 @@ class DAV extends Common { $path1 = $this->cleanPath($path1); $path2 = $this->cleanPath($path2); try { + // overwrite directory ? + if ($this->is_dir($path2)) { + // needs trailing slash in destination + $path2 = rtrim($path2, '/') . '/'; + } $this->client->request( 'MOVE', $this->encodePath($path1), null, - array( - 'Destination' => $this->createBaseUri() . $this->encodePath($path2) - ) + [ + 'Destination' => $this->createBaseUri() . $this->encodePath($path2), + ] ); $this->statCache->clear($path1 . '/'); $this->statCache->clear($path2 . '/'); @@ -530,10 +544,22 @@ class DAV extends Common { /** {@inheritdoc} */ public function copy($path1, $path2) { $this->init(); - $path1 = $this->encodePath($this->cleanPath($path1)); - $path2 = $this->createBaseUri() . $this->encodePath($this->cleanPath($path2)); + $path1 = $this->cleanPath($path1); + $path2 = $this->cleanPath($path2); try { - $this->client->request('COPY', $path1, null, array('Destination' => $path2)); + // overwrite directory ? + if ($this->is_dir($path2)) { + // needs trailing slash in destination + $path2 = rtrim($path2, '/') . '/'; + } + $this->client->request( + 'COPY', + $this->encodePath($path1), + null, + [ + 'Destination' => $this->createBaseUri() . $this->encodePath($path2), + ] + ); $this->statCache->clear($path2 . '/'); $this->statCache->set($path2, true); $this->removeCachedFile($path2);