mirror of
https://github.com/abraunegg/onedrive
synced 2024-06-02 14:02:21 +02:00
* Test if local file is readable based on user permissions before attempting to access file to determine the sync state or upload
This commit is contained in:
parent
5349340818
commit
9b44bb1e96
560
src/sync.d
560
src/sync.d
|
@ -188,6 +188,7 @@ private Item makeItem(const ref JSONValue driveItem)
|
||||||
|
|
||||||
private bool testFileHash(const(string) path, const ref Item item)
|
private bool testFileHash(const(string) path, const ref Item item)
|
||||||
{
|
{
|
||||||
|
// Try and compute the file hash
|
||||||
if (item.crc32Hash) {
|
if (item.crc32Hash) {
|
||||||
if (item.crc32Hash == computeCrc32(path)) return true;
|
if (item.crc32Hash == computeCrc32(path)) return true;
|
||||||
} else if (item.sha1Hash) {
|
} else if (item.sha1Hash) {
|
||||||
|
@ -2737,20 +2738,28 @@ final class SyncEngine
|
||||||
final switch (item.type) {
|
final switch (item.type) {
|
||||||
case ItemType.file:
|
case ItemType.file:
|
||||||
if (isFile(path)) {
|
if (isFile(path)) {
|
||||||
SysTime localModifiedTime = timeLastModified(path).toUTC();
|
// can we actually read the local file?
|
||||||
SysTime itemModifiedTime = item.mtime;
|
if (readLocalFile(path)){
|
||||||
// HACK: reduce time resolution to seconds before comparing
|
// local file is readable
|
||||||
localModifiedTime.fracSecs = Duration.zero;
|
SysTime localModifiedTime = timeLastModified(path).toUTC();
|
||||||
itemModifiedTime.fracSecs = Duration.zero;
|
SysTime itemModifiedTime = item.mtime;
|
||||||
if (localModifiedTime == itemModifiedTime) {
|
// HACK: reduce time resolution to seconds before comparing
|
||||||
return true;
|
localModifiedTime.fracSecs = Duration.zero;
|
||||||
|
itemModifiedTime.fracSecs = Duration.zero;
|
||||||
|
if (localModifiedTime == itemModifiedTime) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
log.vlog("The local item has a different modified time ", localModifiedTime, " when compared to ", itemSource, " modified time ", itemModifiedTime);
|
||||||
|
}
|
||||||
|
if (testFileHash(path, item)) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
log.vlog("The local item has a different hash when compared to ", itemSource, " item hash");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
log.vlog("The local item has a different modified time ", localModifiedTime, " when compared to ", itemSource, " modified time ", itemModifiedTime);
|
// Unable to read local file
|
||||||
}
|
log.log("Unable to determine the sync state of this file as it cannot be read (file permissions or file corruption): ", path);
|
||||||
if (testFileHash(path, item)) {
|
return false;
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
log.vlog("The local item has a different hash when compared to ", itemSource, " item hash");
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.vlog("The local item is a directory but should be a file");
|
log.vlog("The local item is a directory but should be a file");
|
||||||
|
@ -3295,133 +3304,198 @@ final class SyncEngine
|
||||||
assert(item.type == ItemType.file);
|
assert(item.type == ItemType.file);
|
||||||
if (exists(path)) {
|
if (exists(path)) {
|
||||||
if (isFile(path)) {
|
if (isFile(path)) {
|
||||||
SysTime localModifiedTime = timeLastModified(path).toUTC();
|
// can we actually read the local file?
|
||||||
SysTime itemModifiedTime = item.mtime;
|
if (readLocalFile(path)){
|
||||||
// HACK: reduce time resolution to seconds before comparing
|
// file is readable
|
||||||
itemModifiedTime.fracSecs = Duration.zero;
|
SysTime localModifiedTime = timeLastModified(path).toUTC();
|
||||||
localModifiedTime.fracSecs = Duration.zero;
|
SysTime itemModifiedTime = item.mtime;
|
||||||
|
// HACK: reduce time resolution to seconds before comparing
|
||||||
if (localModifiedTime != itemModifiedTime) {
|
itemModifiedTime.fracSecs = Duration.zero;
|
||||||
log.vlog("The file last modified time has changed");
|
localModifiedTime.fracSecs = Duration.zero;
|
||||||
string eTag = item.eTag;
|
|
||||||
if (!testFileHash(path, item)) {
|
if (localModifiedTime != itemModifiedTime) {
|
||||||
log.vlog("The file content has changed");
|
log.vlog("The file last modified time has changed");
|
||||||
write("Uploading modified file ", path, " ... ");
|
string eTag = item.eTag;
|
||||||
JSONValue response;
|
|
||||||
|
|
||||||
if (!dryRun) {
|
// perform file hash tests - has the content of the file changed?
|
||||||
// Get the file size
|
if (!testFileHash(path, item)) {
|
||||||
long thisFileSize = getSize(path);
|
log.vlog("The file content has changed");
|
||||||
// Are we using OneDrive Personal or OneDrive Business?
|
write("Uploading modified file ", path, " ... ");
|
||||||
// To solve 'Multiple versions of file shown on website after single upload' (https://github.com/abraunegg/onedrive/issues/2)
|
JSONValue response;
|
||||||
// check what 'account type' this is as this issue only affects OneDrive Business so we need some extra logic here
|
|
||||||
if (accountType == "personal"){
|
if (!dryRun) {
|
||||||
// Original file upload logic
|
// Get the file size
|
||||||
if (thisFileSize <= thresholdFileSize) {
|
long thisFileSize = getSize(path);
|
||||||
try {
|
// Are we using OneDrive Personal or OneDrive Business?
|
||||||
response = onedrive.simpleUploadReplace(path, item.driveId, item.id, item.eTag);
|
// To solve 'Multiple versions of file shown on website after single upload' (https://github.com/abraunegg/onedrive/issues/2)
|
||||||
} catch (OneDriveException e) {
|
// check what 'account type' this is as this issue only affects OneDrive Business so we need some extra logic here
|
||||||
if (e.httpStatusCode == 401) {
|
if (accountType == "personal"){
|
||||||
// OneDrive returned a 'HTTP/1.1 401 Unauthorized Error' - file failed to be uploaded
|
// Original file upload logic
|
||||||
|
if (thisFileSize <= thresholdFileSize) {
|
||||||
|
try {
|
||||||
|
response = onedrive.simpleUploadReplace(path, item.driveId, item.id, item.eTag);
|
||||||
|
} catch (OneDriveException e) {
|
||||||
|
if (e.httpStatusCode == 401) {
|
||||||
|
// OneDrive returned a 'HTTP/1.1 401 Unauthorized Error' - file failed to be uploaded
|
||||||
|
writeln("skipped.");
|
||||||
|
log.vlog("OneDrive returned a 'HTTP 401 - Unauthorized' - gracefully handling error");
|
||||||
|
uploadFailed = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (e.httpStatusCode == 404) {
|
||||||
|
// HTTP request returned status code 404 - the eTag provided does not exist
|
||||||
|
// Delete record from the local database - file will be uploaded as a new file
|
||||||
|
writeln("skipped.");
|
||||||
|
log.vlog("OneDrive returned a 'HTTP 404 - eTag Issue' - gracefully handling error");
|
||||||
|
itemdb.deleteById(item.driveId, item.id);
|
||||||
|
uploadFailed = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Resolve https://github.com/abraunegg/onedrive/issues/36
|
||||||
|
if ((e.httpStatusCode == 409) || (e.httpStatusCode == 423)) {
|
||||||
|
// The file is currently checked out or locked for editing by another user
|
||||||
|
// We cant upload this file at this time
|
||||||
|
writeln("skipped.");
|
||||||
|
log.fileOnly("Uploading modified file ", path, " ... skipped.");
|
||||||
|
write("", path, " is currently checked out or locked for editing by another user.");
|
||||||
|
log.fileOnly(path, " is currently checked out or locked for editing by another user.");
|
||||||
|
uploadFailed = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (e.httpStatusCode == 412) {
|
||||||
|
// HTTP request returned status code 412 - ETag does not match current item's value
|
||||||
|
// Delete record from the local database - file will be uploaded as a new file
|
||||||
|
writeln("skipped.");
|
||||||
|
log.vdebug("Simple Upload Replace Failed - OneDrive eTag / cTag match issue");
|
||||||
|
log.vlog("OneDrive returned a 'HTTP 412 - Precondition Failed' - gracefully handling error. Will upload as new file.");
|
||||||
|
itemdb.deleteById(item.driveId, item.id);
|
||||||
|
uploadFailed = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (e.httpStatusCode == 504) {
|
||||||
|
// HTTP request returned status code 504 (Gateway Timeout)
|
||||||
|
log.log("OneDrive returned a 'HTTP 504 - Gateway Timeout' - retrying upload request as a session");
|
||||||
|
// Try upload as a session
|
||||||
|
response = session.upload(path, item.driveId, item.parentId, baseName(path), item.eTag);
|
||||||
|
} else {
|
||||||
|
// display what the error is
|
||||||
|
writeln("skipped.");
|
||||||
|
displayOneDriveErrorMessage(e.msg, getFunctionName!({}));
|
||||||
|
uploadFailed = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (FileException e) {
|
||||||
|
// display the error message
|
||||||
writeln("skipped.");
|
writeln("skipped.");
|
||||||
log.vlog("OneDrive returned a 'HTTP 401 - Unauthorized' - gracefully handling error");
|
displayFileSystemErrorMessage(e.msg, getFunctionName!({}));
|
||||||
uploadFailed = true;
|
uploadFailed = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (e.httpStatusCode == 404) {
|
// upload done without error
|
||||||
// HTTP request returned status code 404 - the eTag provided does not exist
|
writeln("done.");
|
||||||
// Delete record from the local database - file will be uploaded as a new file
|
} else {
|
||||||
writeln("skipped.");
|
writeln("");
|
||||||
log.vlog("OneDrive returned a 'HTTP 404 - eTag Issue' - gracefully handling error");
|
try {
|
||||||
itemdb.deleteById(item.driveId, item.id);
|
|
||||||
uploadFailed = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Resolve https://github.com/abraunegg/onedrive/issues/36
|
|
||||||
if ((e.httpStatusCode == 409) || (e.httpStatusCode == 423)) {
|
|
||||||
// The file is currently checked out or locked for editing by another user
|
|
||||||
// We cant upload this file at this time
|
|
||||||
writeln("skipped.");
|
|
||||||
log.fileOnly("Uploading modified file ", path, " ... skipped.");
|
|
||||||
write("", path, " is currently checked out or locked for editing by another user.");
|
|
||||||
log.fileOnly(path, " is currently checked out or locked for editing by another user.");
|
|
||||||
uploadFailed = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (e.httpStatusCode == 412) {
|
|
||||||
// HTTP request returned status code 412 - ETag does not match current item's value
|
|
||||||
// Delete record from the local database - file will be uploaded as a new file
|
|
||||||
writeln("skipped.");
|
|
||||||
log.vdebug("Simple Upload Replace Failed - OneDrive eTag / cTag match issue");
|
|
||||||
log.vlog("OneDrive returned a 'HTTP 412 - Precondition Failed' - gracefully handling error. Will upload as new file.");
|
|
||||||
itemdb.deleteById(item.driveId, item.id);
|
|
||||||
uploadFailed = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (e.httpStatusCode == 504) {
|
|
||||||
// HTTP request returned status code 504 (Gateway Timeout)
|
|
||||||
log.log("OneDrive returned a 'HTTP 504 - Gateway Timeout' - retrying upload request as a session");
|
|
||||||
// Try upload as a session
|
|
||||||
response = session.upload(path, item.driveId, item.parentId, baseName(path), item.eTag);
|
response = session.upload(path, item.driveId, item.parentId, baseName(path), item.eTag);
|
||||||
} else {
|
} catch (OneDriveException e) {
|
||||||
// display what the error is
|
if (e.httpStatusCode == 401) {
|
||||||
|
// OneDrive returned a 'HTTP/1.1 401 Unauthorized Error' - file failed to be uploaded
|
||||||
|
writeln("skipped.");
|
||||||
|
log.vlog("OneDrive returned a 'HTTP 401 - Unauthorized' - gracefully handling error");
|
||||||
|
uploadFailed = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (e.httpStatusCode == 412) {
|
||||||
|
// HTTP request returned status code 412 - ETag does not match current item's value
|
||||||
|
// Delete record from the local database - file will be uploaded as a new file
|
||||||
|
writeln("skipped.");
|
||||||
|
log.vdebug("Simple Upload Replace Failed - OneDrive eTag / cTag match issue");
|
||||||
|
log.vlog("OneDrive returned a 'HTTP 412 - Precondition Failed' - gracefully handling error. Will upload as new file.");
|
||||||
|
itemdb.deleteById(item.driveId, item.id);
|
||||||
|
uploadFailed = true;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
// display what the error is
|
||||||
|
writeln("skipped.");
|
||||||
|
displayOneDriveErrorMessage(e.msg, getFunctionName!({}));
|
||||||
|
uploadFailed = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (FileException e) {
|
||||||
|
// display the error message
|
||||||
writeln("skipped.");
|
writeln("skipped.");
|
||||||
displayOneDriveErrorMessage(e.msg, getFunctionName!({}));
|
displayFileSystemErrorMessage(e.msg, getFunctionName!({}));
|
||||||
uploadFailed = true;
|
uploadFailed = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch (FileException e) {
|
// upload done without error
|
||||||
// display the error message
|
writeln("done.");
|
||||||
writeln("skipped.");
|
|
||||||
displayFileSystemErrorMessage(e.msg, getFunctionName!({}));
|
|
||||||
uploadFailed = true;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
// upload done without error
|
|
||||||
writeln("done.");
|
|
||||||
} else {
|
} else {
|
||||||
writeln("");
|
// OneDrive Business Account
|
||||||
try {
|
// We need to always use a session to upload, but handle the changed file correctly
|
||||||
response = session.upload(path, item.driveId, item.parentId, baseName(path), item.eTag);
|
if (accountType == "business"){
|
||||||
} catch (OneDriveException e) {
|
try {
|
||||||
if (e.httpStatusCode == 401) {
|
// is this a zero-byte file?
|
||||||
// OneDrive returned a 'HTTP/1.1 401 Unauthorized Error' - file failed to be uploaded
|
if (thisFileSize == 0) {
|
||||||
|
// the file we are trying to upload as a session is a zero byte file - we cant use a session to upload or replace the file
|
||||||
|
// as OneDrive technically does not support zero byte files
|
||||||
|
writeln("skipped.");
|
||||||
|
log.fileOnly("Uploading modified file ", path, " ... skipped.");
|
||||||
|
log.vlog("Skip Reason: Microsoft OneDrive does not support 'zero-byte' files as a modified upload. Will upload as new file.");
|
||||||
|
// delete file on OneDrive
|
||||||
|
onedrive.deleteById(item.driveId, item.id, item.eTag);
|
||||||
|
// delete file from local database
|
||||||
|
itemdb.deleteById(item.driveId, item.id);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
// For logging consistency
|
||||||
|
writeln("");
|
||||||
|
// normal session upload
|
||||||
|
response = session.upload(path, item.driveId, item.parentId, baseName(path), item.eTag);
|
||||||
|
}
|
||||||
|
} catch (OneDriveException e) {
|
||||||
|
if (e.httpStatusCode == 401) {
|
||||||
|
// OneDrive returned a 'HTTP/1.1 401 Unauthorized Error' - file failed to be uploaded
|
||||||
|
writeln("skipped.");
|
||||||
|
log.vlog("OneDrive returned a 'HTTP 401 - Unauthorized' - gracefully handling error");
|
||||||
|
uploadFailed = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Resolve https://github.com/abraunegg/onedrive/issues/36
|
||||||
|
if ((e.httpStatusCode == 409) || (e.httpStatusCode == 423)) {
|
||||||
|
// The file is currently checked out or locked for editing by another user
|
||||||
|
// We cant upload this file at this time
|
||||||
|
writeln("skipped.");
|
||||||
|
log.fileOnly("Uploading modified file ", path, " ... skipped.");
|
||||||
|
writeln("", path, " is currently checked out or locked for editing by another user.");
|
||||||
|
log.fileOnly(path, " is currently checked out or locked for editing by another user.");
|
||||||
|
uploadFailed = true;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
// display what the error is
|
||||||
|
writeln("skipped.");
|
||||||
|
displayOneDriveErrorMessage(e.msg, getFunctionName!({}));
|
||||||
|
uploadFailed = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (FileException e) {
|
||||||
|
// display the error message
|
||||||
writeln("skipped.");
|
writeln("skipped.");
|
||||||
log.vlog("OneDrive returned a 'HTTP 401 - Unauthorized' - gracefully handling error");
|
displayFileSystemErrorMessage(e.msg, getFunctionName!({}));
|
||||||
uploadFailed = true;
|
uploadFailed = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (e.httpStatusCode == 412) {
|
// upload done without error
|
||||||
// HTTP request returned status code 412 - ETag does not match current item's value
|
writeln("done.");
|
||||||
// Delete record from the local database - file will be uploaded as a new file
|
|
||||||
writeln("skipped.");
|
// As the session.upload includes the last modified time, save the response
|
||||||
log.vdebug("Simple Upload Replace Failed - OneDrive eTag / cTag match issue");
|
// Is the response a valid JSON object - validation checking done in saveItem
|
||||||
log.vlog("OneDrive returned a 'HTTP 412 - Precondition Failed' - gracefully handling error. Will upload as new file.");
|
saveItem(response);
|
||||||
itemdb.deleteById(item.driveId, item.id);
|
|
||||||
uploadFailed = true;
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
// display what the error is
|
|
||||||
writeln("skipped.");
|
|
||||||
displayOneDriveErrorMessage(e.msg, getFunctionName!({}));
|
|
||||||
uploadFailed = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} catch (FileException e) {
|
|
||||||
// display the error message
|
|
||||||
writeln("skipped.");
|
|
||||||
displayFileSystemErrorMessage(e.msg, getFunctionName!({}));
|
|
||||||
uploadFailed = true;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
// upload done without error
|
|
||||||
writeln("done.");
|
// OneDrive documentLibrary
|
||||||
}
|
if (accountType == "documentLibrary"){
|
||||||
} else {
|
|
||||||
// OneDrive Business Account
|
|
||||||
// We need to always use a session to upload, but handle the changed file correctly
|
|
||||||
if (accountType == "business"){
|
|
||||||
try {
|
|
||||||
// is this a zero-byte file?
|
// is this a zero-byte file?
|
||||||
if (thisFileSize == 0) {
|
if (thisFileSize == 0) {
|
||||||
// the file we are trying to upload as a session is a zero byte file - we cant use a session to upload or replace the file
|
// the file we are trying to upload as a session is a zero byte file - we cant use a session to upload or replace the file
|
||||||
|
@ -3435,168 +3509,113 @@ final class SyncEngine
|
||||||
itemdb.deleteById(item.driveId, item.id);
|
itemdb.deleteById(item.driveId, item.id);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
// For logging consistency
|
// Handle certain file types differently
|
||||||
writeln("");
|
if ((extension(path) == ".txt") || (extension(path) == ".csv")) {
|
||||||
// normal session upload
|
// .txt and .csv are unaffected by https://github.com/OneDrive/onedrive-api-docs/issues/935
|
||||||
response = session.upload(path, item.driveId, item.parentId, baseName(path), item.eTag);
|
// For logging consistency
|
||||||
}
|
writeln("");
|
||||||
} catch (OneDriveException e) {
|
try {
|
||||||
if (e.httpStatusCode == 401) {
|
response = session.upload(path, item.driveId, item.parentId, baseName(path), item.eTag);
|
||||||
// OneDrive returned a 'HTTP/1.1 401 Unauthorized Error' - file failed to be uploaded
|
} catch (OneDriveException e) {
|
||||||
writeln("skipped.");
|
if (e.httpStatusCode == 401) {
|
||||||
log.vlog("OneDrive returned a 'HTTP 401 - Unauthorized' - gracefully handling error");
|
// OneDrive returned a 'HTTP/1.1 401 Unauthorized Error' - file failed to be uploaded
|
||||||
uploadFailed = true;
|
writeln("skipped.");
|
||||||
return;
|
log.vlog("OneDrive returned a 'HTTP 401 - Unauthorized' - gracefully handling error");
|
||||||
}
|
uploadFailed = true;
|
||||||
// Resolve https://github.com/abraunegg/onedrive/issues/36
|
return;
|
||||||
if ((e.httpStatusCode == 409) || (e.httpStatusCode == 423)) {
|
}
|
||||||
// The file is currently checked out or locked for editing by another user
|
// Resolve https://github.com/abraunegg/onedrive/issues/36
|
||||||
// We cant upload this file at this time
|
if ((e.httpStatusCode == 409) || (e.httpStatusCode == 423)) {
|
||||||
writeln("skipped.");
|
// The file is currently checked out or locked for editing by another user
|
||||||
log.fileOnly("Uploading modified file ", path, " ... skipped.");
|
// We cant upload this file at this time
|
||||||
writeln("", path, " is currently checked out or locked for editing by another user.");
|
writeln("skipped.");
|
||||||
log.fileOnly(path, " is currently checked out or locked for editing by another user.");
|
log.fileOnly("Uploading modified file ", path, " ... skipped.");
|
||||||
uploadFailed = true;
|
writeln("", path, " is currently checked out or locked for editing by another user.");
|
||||||
return;
|
log.fileOnly(path, " is currently checked out or locked for editing by another user.");
|
||||||
} else {
|
uploadFailed = true;
|
||||||
// display what the error is
|
return;
|
||||||
writeln("skipped.");
|
} else {
|
||||||
displayOneDriveErrorMessage(e.msg, getFunctionName!({}));
|
// display what the error is
|
||||||
uploadFailed = true;
|
writeln("skipped.");
|
||||||
return;
|
displayOneDriveErrorMessage(e.msg, getFunctionName!({}));
|
||||||
}
|
uploadFailed = true;
|
||||||
} catch (FileException e) {
|
return;
|
||||||
// display the error message
|
}
|
||||||
writeln("skipped.");
|
} catch (FileException e) {
|
||||||
displayFileSystemErrorMessage(e.msg, getFunctionName!({}));
|
// display the error message
|
||||||
uploadFailed = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// upload done without error
|
|
||||||
writeln("done.");
|
|
||||||
|
|
||||||
// As the session.upload includes the last modified time, save the response
|
|
||||||
// Is the response a valid JSON object - validation checking done in saveItem
|
|
||||||
saveItem(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// OneDrive documentLibrary
|
|
||||||
if (accountType == "documentLibrary"){
|
|
||||||
// is this a zero-byte file?
|
|
||||||
if (thisFileSize == 0) {
|
|
||||||
// the file we are trying to upload as a session is a zero byte file - we cant use a session to upload or replace the file
|
|
||||||
// as OneDrive technically does not support zero byte files
|
|
||||||
writeln("skipped.");
|
|
||||||
log.fileOnly("Uploading modified file ", path, " ... skipped.");
|
|
||||||
log.vlog("Skip Reason: Microsoft OneDrive does not support 'zero-byte' files as a modified upload. Will upload as new file.");
|
|
||||||
// delete file on OneDrive
|
|
||||||
onedrive.deleteById(item.driveId, item.id, item.eTag);
|
|
||||||
// delete file from local database
|
|
||||||
itemdb.deleteById(item.driveId, item.id);
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
// Handle certain file types differently
|
|
||||||
if ((extension(path) == ".txt") || (extension(path) == ".csv")) {
|
|
||||||
// .txt and .csv are unaffected by https://github.com/OneDrive/onedrive-api-docs/issues/935
|
|
||||||
// For logging consistency
|
|
||||||
writeln("");
|
|
||||||
try {
|
|
||||||
response = session.upload(path, item.driveId, item.parentId, baseName(path), item.eTag);
|
|
||||||
} catch (OneDriveException e) {
|
|
||||||
if (e.httpStatusCode == 401) {
|
|
||||||
// OneDrive returned a 'HTTP/1.1 401 Unauthorized Error' - file failed to be uploaded
|
|
||||||
writeln("skipped.");
|
writeln("skipped.");
|
||||||
log.vlog("OneDrive returned a 'HTTP 401 - Unauthorized' - gracefully handling error");
|
displayFileSystemErrorMessage(e.msg, getFunctionName!({}));
|
||||||
uploadFailed = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Resolve https://github.com/abraunegg/onedrive/issues/36
|
|
||||||
if ((e.httpStatusCode == 409) || (e.httpStatusCode == 423)) {
|
|
||||||
// The file is currently checked out or locked for editing by another user
|
|
||||||
// We cant upload this file at this time
|
|
||||||
writeln("skipped.");
|
|
||||||
log.fileOnly("Uploading modified file ", path, " ... skipped.");
|
|
||||||
writeln("", path, " is currently checked out or locked for editing by another user.");
|
|
||||||
log.fileOnly(path, " is currently checked out or locked for editing by another user.");
|
|
||||||
uploadFailed = true;
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
// display what the error is
|
|
||||||
writeln("skipped.");
|
|
||||||
displayOneDriveErrorMessage(e.msg, getFunctionName!({}));
|
|
||||||
uploadFailed = true;
|
uploadFailed = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch (FileException e) {
|
// upload done without error
|
||||||
// display the error message
|
writeln("done.");
|
||||||
|
// As the session.upload includes the last modified time, save the response
|
||||||
|
// Is the response a valid JSON object - validation checking done in saveItem
|
||||||
|
saveItem(response);
|
||||||
|
} else {
|
||||||
|
// Due to https://github.com/OneDrive/onedrive-api-docs/issues/935 Microsoft modifies all PDF, MS Office & HTML files with added XML content. It is a 'feature' of SharePoint.
|
||||||
|
// This means, as a session upload, on 'completion' the file is 'moved' and generates a 404 ......
|
||||||
writeln("skipped.");
|
writeln("skipped.");
|
||||||
displayFileSystemErrorMessage(e.msg, getFunctionName!({}));
|
log.fileOnly("Uploading modified file ", path, " ... skipped.");
|
||||||
uploadFailed = true;
|
log.vlog("Skip Reason: Microsoft Sharepoint 'enrichment' after upload issue");
|
||||||
|
log.vlog("See: https://github.com/OneDrive/onedrive-api-docs/issues/935 for further details");
|
||||||
|
// Delete record from the local database - file will be uploaded as a new file
|
||||||
|
itemdb.deleteById(item.driveId, item.id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// upload done without error
|
|
||||||
writeln("done.");
|
|
||||||
// As the session.upload includes the last modified time, save the response
|
|
||||||
// Is the response a valid JSON object - validation checking done in saveItem
|
|
||||||
saveItem(response);
|
|
||||||
} else {
|
|
||||||
// Due to https://github.com/OneDrive/onedrive-api-docs/issues/935 Microsoft modifies all PDF, MS Office & HTML files with added XML content. It is a 'feature' of SharePoint.
|
|
||||||
// This means, as a session upload, on 'completion' the file is 'moved' and generates a 404 ......
|
|
||||||
writeln("skipped.");
|
|
||||||
log.fileOnly("Uploading modified file ", path, " ... skipped.");
|
|
||||||
log.vlog("Skip Reason: Microsoft Sharepoint 'enrichment' after upload issue");
|
|
||||||
log.vlog("See: https://github.com/OneDrive/onedrive-api-docs/issues/935 for further details");
|
|
||||||
// Delete record from the local database - file will be uploaded as a new file
|
|
||||||
itemdb.deleteById(item.driveId, item.id);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
// Update etag with ctag from response
|
||||||
// Update etag with ctag from response
|
if ("cTag" in response) {
|
||||||
if ("cTag" in response) {
|
// use the cTag instead of the eTag because OneDrive may update the metadata of files AFTER they have been uploaded via simple upload
|
||||||
// use the cTag instead of the eTag because OneDrive may update the metadata of files AFTER they have been uploaded via simple upload
|
eTag = response["cTag"].str;
|
||||||
eTag = response["cTag"].str;
|
|
||||||
} else {
|
|
||||||
// Is there an eTag in the response?
|
|
||||||
if ("eTag" in response) {
|
|
||||||
// use the eTag from the response as there was no cTag
|
|
||||||
eTag = response["eTag"].str;
|
|
||||||
} else {
|
} else {
|
||||||
// no tag available - set to nothing
|
// Is there an eTag in the response?
|
||||||
eTag = "";
|
if ("eTag" in response) {
|
||||||
|
// use the eTag from the response as there was no cTag
|
||||||
|
eTag = response["eTag"].str;
|
||||||
|
} else {
|
||||||
|
// no tag available - set to nothing
|
||||||
|
eTag = "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// log that the modified file was uploaded successfully
|
||||||
|
log.fileOnly("Uploading modified file ", path, " ... done.");
|
||||||
|
|
||||||
|
// update free space tracking if this is our drive id
|
||||||
|
if (item.driveId == defaultDriveId) {
|
||||||
|
// how much space is left on OneDrive after upload?
|
||||||
|
remainingFreeSpace = (remainingFreeSpace - thisFileSize);
|
||||||
|
log.vlog("Remaining free space on OneDrive: ", remainingFreeSpace);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// we are --dry-run - simulate the file upload
|
||||||
|
writeln("done.");
|
||||||
|
response = createFakeResponse(path);
|
||||||
|
// Log action to log file
|
||||||
|
log.fileOnly("Uploading modified file ", path, " ... done.");
|
||||||
|
// Is the response a valid JSON object - validation checking done in saveItem
|
||||||
|
saveItem(response);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// log that the modified file was uploaded successfully
|
if (accountType == "personal"){
|
||||||
log.fileOnly("Uploading modified file ", path, " ... done.");
|
// If Personal, call to update the modified time as stored on OneDrive
|
||||||
|
if (!dryRun) {
|
||||||
// update free space tracking if this is our drive id
|
uploadLastModifiedTime(item.driveId, item.id, eTag, localModifiedTime.toUTC());
|
||||||
if (item.driveId == defaultDriveId) {
|
|
||||||
// how much space is left on OneDrive after upload?
|
|
||||||
remainingFreeSpace = (remainingFreeSpace - thisFileSize);
|
|
||||||
log.vlog("Remaining free space on OneDrive: ", remainingFreeSpace);
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// we are --dry-run - simulate the file upload
|
|
||||||
writeln("done.");
|
|
||||||
response = createFakeResponse(path);
|
|
||||||
// Log action to log file
|
|
||||||
log.fileOnly("Uploading modified file ", path, " ... done.");
|
|
||||||
// Is the response a valid JSON object - validation checking done in saveItem
|
|
||||||
saveItem(response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (accountType == "personal"){
|
|
||||||
// If Personal, call to update the modified time as stored on OneDrive
|
|
||||||
if (!dryRun) {
|
|
||||||
uploadLastModifiedTime(item.driveId, item.id, eTag, localModifiedTime.toUTC());
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
log.vlog("The file has not changed");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.vlog("The file has not changed");
|
//The file is not readable - skipped
|
||||||
|
log.log("Skipping processing this file as it cannot be read (file permissions or file corruption): ", path);
|
||||||
|
uploadFailed = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.vlog("The item was a file but now is a directory");
|
log.vlog("The item was a file but now is a directory");
|
||||||
|
@ -4899,6 +4918,9 @@ final class SyncEngine
|
||||||
uploadFailed = true;
|
uploadFailed = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// unable to read local file
|
||||||
|
log.log("Skipping uploading this file as it cannot be read (file permissions or file corruption): ", path);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Upload of the new file did not occur .. why?
|
// Upload of the new file did not occur .. why?
|
||||||
|
@ -6141,4 +6163,4 @@ final class SyncEngine
|
||||||
log.error("ERROR: onedrive.getSharedWithMe call returned an invalid JSON Object");
|
log.error("ERROR: onedrive.getSharedWithMe call returned an invalid JSON Object");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -153,7 +153,7 @@ bool readLocalFile(string path)
|
||||||
read(path,1);
|
read(path,1);
|
||||||
} catch (std.file.FileException e) {
|
} catch (std.file.FileException e) {
|
||||||
// unable to read the new local file
|
// unable to read the new local file
|
||||||
log.log("Skipping uploading this file as it cannot be read (file permissions or file corruption): ", path);
|
displayFileSystemErrorMessage(e.msg, getFunctionName!({}));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -322,7 +322,7 @@ void displayOneDriveErrorMessage(string message, string callingFunction)
|
||||||
// Parse and display error message received from the local file system
|
// Parse and display error message received from the local file system
|
||||||
void displayFileSystemErrorMessage(string message, string callingFunction)
|
void displayFileSystemErrorMessage(string message, string callingFunction)
|
||||||
{
|
{
|
||||||
log.error("ERROR: The local file system returned an error with the following message:");
|
log.error("\nERROR: The local file system returned an error with the following message:");
|
||||||
auto errorArray = splitLines(message);
|
auto errorArray = splitLines(message);
|
||||||
// What was the error message
|
// What was the error message
|
||||||
log.error(" Error Message: ", errorArray[0]);
|
log.error(" Error Message: ", errorArray[0]);
|
||||||
|
|
Loading…
Reference in a new issue