Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Fix update detection for Dropbox #6069

Closed
wants to merge 2 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 58 additions & 5 deletions apps/files_external/lib/dropbox.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,17 +63,26 @@ private function deleteMetaData($path) {
* @brief Returns the path's metadata
* @param $path path for which to return the metadata
* @param $list if true, also return the directory's contents
* @param $hash previously known hash, used to detect changes
* @return directory contents if $list is true, file metadata if $list is
* false, null if the file doesn't exist or "false" if the operation failed
* false, null if the file doesn't exist, "false" if the operation failed.
* If a hash is passed, "true" might be returned if the metadata didn't change
*/
private function getMetaData($path, $list = false) {
private function getMetaData($path, $list = false, $hash = null) {
$path = $this->root.$path;
if ( ! $list && isset($this->metaData[$path])) {
if ( ! $list && ! $hash && isset($this->metaData[$path])) {
return $this->metaData[$path];
} else {
if ($list) {
try {
$response = $this->dropbox->getMetaData($path);
$response = $this->dropbox->getMetaData($path, 'true');
// FIXME: why does Dropbox rerturn 401 unauthorized when passing a hash !?
//$response = $this->dropbox->getMetaData($path, 'true', $hash);
// FIXME: HACK, checking the hash here
if ($hash && $hash === $response['hash']) {
// no changes
return true;
}
} catch (\Exception $exception) {
\OCP\Util::writeLog('files_external', $exception->getMessage(), \OCP\Util::ERROR);
return false;
Expand All @@ -96,7 +105,7 @@ private function getMetaData($path, $list = false) {
return $contents;
} else {
try {
$response = $this->dropbox->getMetaData($path, 'false');
$response = $this->dropbox->getMetaData($path, 'false', $hash);
if (!isset($response['is_deleted']) || !$response['is_deleted']) {
$this->metaData[$path] = $response;
return $response;
Expand Down Expand Up @@ -308,4 +317,48 @@ public function touch($path, $mtime = null) {
return true;
}

public function hasUpdated($path, $time) {
// Dropbox doesn't have directory mtime, so need to use the Dropbox hash
// we stored as etag
$data = $this->getCache()->get($path);
// FIXME: might break if someone replaced a dir with a file with
// the same name before we got the update
if ($data['mimetype'] === 'httpd/unix-directory') {
$hash = $data['etag'];
$newData = $this->getMetaData($path, true, $hash);
return $newData !== true;
}
// use mtime for files
return parent::hasUpdated($path, $time);
}

public function getETag($path) {
// then retrieve the cached entry
$data = $this->getCache()->get($path);
// FIXME: might break if someone replaced a dir with a file with
// the same name before we got the update
if ($data && $data['mimetype'] === 'httpd/unix-directory' && isset($data['etag'])) {
// only check for changes
$metaData = $this->getMetaData($path, true, $data['etag']);
// no changes ?
if ($metaData === true) {
// return old etag
return $data['etag'];
}
}
else {
// FIXME: ouch, we need to get the directory contents to
// get the hash value, maybe there is a more efficient way to do this ?
$metaData = $this->getMetaData($path, true);
}

// this will get the cached entry for the directory
$metaData = $this->getMetaData($path);
if ($metaData && isset($metaData['is_dir']) && $metaData['is_dir'] && isset($metaData['hash'])) {
// for directories
return $metaData['hash'];
}
// files need to use the regular etag algo (no hash)
return parent::getEtag($path);
}
}