diff --git a/src/config.d b/src/config.d index 1675fa72..cf988800 100644 --- a/src/config.d +++ b/src/config.d @@ -1132,6 +1132,7 @@ class ApplicationConfig { stringValues["auth_files"] = ""; stringValues["auth_response"] = ""; stringValues["share_password"] = ""; + stringValues["download_single_file"] = ""; boolValues["display_config"] = false; boolValues["display_sync_status"] = false; boolValues["display_quota"] = false; @@ -1214,6 +1215,9 @@ class ApplicationConfig { "download-only", "Replicate the OneDrive online state locally, by only downloading changes from OneDrive. Do not upload local changes to OneDrive", &boolValues["download_only"], + "download-file", + "Download a single file from Microsoft OneDrive", + &stringValues["download_single_file"], "dry-run", "Perform a trial sync with no changes made", &boolValues["dry_run"], @@ -2641,6 +2645,7 @@ class ApplicationConfig { // - Are we just deleting a directory online, without any sync being performed? // - Are we renaming or moving a directory? // - Are we displaying the quota information? + // - Are we downloading a single file? bool noSyncOperation = false; // Return a true|false if any of these have been set, so that we use the 'dry-run' DB copy, to execute these tasks, in case the client is currently operational @@ -2718,6 +2723,12 @@ class ApplicationConfig { noSyncOperation = true; } + // Are we downloading a single file? + if ((getValueString("download_single_file") != "")) { + // flag that a no sync operation has been requested + noSyncOperation = true; + } + // Return result return noSyncOperation; } @@ -2801,6 +2812,7 @@ void outputLongHelp(Option[] opt) { "--classify-as-big-delete", "--create-share-link", "--destination-directory", + "--download-file", "--get-file-link", "--get-O365-drive-id", "--get-sharepoint-drive-id", @@ -2842,7 +2854,9 @@ void outputLongHelp(Option[] opt) { writefln(" %s%s%s%s\n %s", it.optLong, it.optShort == "" ? "" : " " ~ it.optShort, - argsNeedingOptions.canFind(it.optLong) ? " ARG" : "", + argsNeedingOptions.canFind(it.optLong) ? " ''" : "", it.required ? " (required)" : "", it.help); } + // end with a blank line + writeln(); } diff --git a/src/main.d b/src/main.d index 36179306..c424fee6 100644 --- a/src/main.d +++ b/src/main.d @@ -745,6 +745,15 @@ int main(string[] cliArgs) { return EXIT_SUCCESS; } + // --download-file - Are we downloading a single file from Microsoft OneDrive + if ((appConfig.getValueString("download_single_file") != "")) { + // Handle downloading the single file + syncEngineInstance.downloadSingleFile(appConfig.getValueString("download_single_file")); + // Exit application + // Use exit scopes to shutdown API + return EXIT_SUCCESS; + } + // If we get to this point, we have not performed a 'no-sync' task .. // Did we just authorise the client? diff --git a/src/sync.d b/src/sync.d index 91b26bb2..3b727a00 100644 --- a/src/sync.d +++ b/src/sync.d @@ -14753,4 +14753,89 @@ class SyncEngine { // Return sanitised JSON string for logging output return sanitisedJSONString; } + + // Download a single file via --download-file + void downloadSingleFile(string pathToQuery) { + // Function Start Time + SysTime functionStartTime; + string logKey; + string thisFunctionName = format("%s.%s", strip(__MODULE__) , strip(getFunctionName!({}))); + // Only set this if we are generating performance processing times + if (appConfig.getValueBool("display_processing_time") && debugLogging) { + functionStartTime = Clock.currTime(); + logKey = generateAlphanumericString(); + displayFunctionProcessingStart(thisFunctionName, logKey); + } + + OneDriveApi queryPathDetailsOnline; + JSONValue onlinePathData; + + // Was a path to query passed in? + if (pathToQuery.empty) { + // Nothing to query + addLogEntry("No path to query"); + return; + } + + // Create new OneDrive API Instance + queryPathDetailsOnline = new OneDriveApi(appConfig); + queryPathDetailsOnline.initialise(); + + try { + // Query the OneDrive API, using the path, which will query 'our' OneDrive Account + onlinePathData = queryPathDetailsOnline.getPathDetails(pathToQuery); + + + } catch (OneDriveException exception) { + + if (exception.httpStatusCode == 404) { + // Path does not exist online ... + addLogEntry("ERROR: The requested path does not exist online. Please check for your file online."); + } else { + // Display error message + displayOneDriveErrorMessage(exception.msg, thisFunctionName); + } + + // OneDrive API Instance Cleanup - Shutdown API, free curl object and memory + queryPathDetailsOnline.releaseCurlEngine(); + queryPathDetailsOnline = null; + // Perform Garbage Collection + GC.collect(); + + // Return .. nothing to do + return; + } + + // Was a valid JSON response provided? + if (onlinePathData.type() == JSONType.object) { + // Valid JSON item was returned + // Is the item a file ? + if (isFileItem(onlinePathData)) { + // JSON item is a file + // Download the file based on the data returned + downloadFileItem(onlinePathData); + } else { + // The provided path is not a file + addLogEntry(); + addLogEntry("ERROR: The requested path to download is not a file. Please correct this error and try again."); + addLogEntry(); + } + } else { + addLogEntry(); + addLogEntry("ERROR: The requested file to download has generated an error. Please correct this error and try again."); + addLogEntry(); + } + + // OneDrive API Instance Cleanup - Shutdown API, free curl object and memory + queryPathDetailsOnline.releaseCurlEngine(); + queryPathDetailsOnline = null; + // Perform Garbage Collection + GC.collect(); + + // Display function processing time if configured to do so + if (appConfig.getValueBool("display_processing_time") && debugLogging) { + // Combine module name & running Function + displayFunctionProcessingTime(thisFunctionName, functionStartTime, Clock.currTime(), logKey); + } + } }