diff --git a/onedrive.1.in b/onedrive.1.in index 1d442135..8a6180c5 100644 --- a/onedrive.1.in +++ b/onedrive.1.in @@ -18,6 +18,11 @@ A complete tool to interact with OneDrive on Linux. .SH OPTIONS Without any option given, no sync is done and the program exits. .TP +\fB\-\-auth\-files\fP ARG +Perform authorization via two files passed in as \fBARG\fP in the format \fBauthUrl:responseUrl\fP. +The authorization URL is written to the \fBauthUrl\fP, then \fBonedrive\fP waits for +the file \fBresponseUrl\fP to be present, and reads the response from that file. +.TP \fB\-\-check\-for\-nomount\fP Check for the presence of .nosync in the syncdir root. If found, do not perform sync. .br diff --git a/src/config.d b/src/config.d index a01e640c..cf6709c7 100644 --- a/src/config.d +++ b/src/config.d @@ -151,6 +151,7 @@ final class Config stringValues["remove_directory"] = ""; stringValues["single_directory"] = ""; stringValues["source_directory"] = ""; + stringValues["auth_files"] = ""; boolValues["display_config"] = false; boolValues["display_sync_status"] = false; boolValues["resync"] = false; @@ -169,6 +170,9 @@ final class Config args, std.getopt.config.bundling, std.getopt.config.caseSensitive, + "auth-files", + "Perform authentication not via interactive dialog but via files read/writes to these files.", + &stringValues["auth_files"], "check-for-nomount", "Check for the presence of .nosync in the syncdir root. If found, do not perform sync.", &boolValues["check_nomount"], diff --git a/src/onedrive.d b/src/onedrive.d index 4a773528..5655e8fc 100644 --- a/src/onedrive.d +++ b/src/onedrive.d @@ -1,7 +1,8 @@ import std.net.curl; import etc.c.curl: CurlOption; import std.datetime, std.exception, std.file, std.json, std.path; -import std.stdio, std.string, std.uni, std.uri; +import std.stdio, std.string, std.uni, std.uri, std.file; +import std.array: split; import core.stdc.stdlib; import core.thread, std.conv, std.math; import progress; @@ -161,9 +162,29 @@ final class OneDriveApi import std.stdio, std.regex; char[] response; string url = authUrl ~ "?client_id=" ~ clientId ~ "&scope=files.readwrite%20files.readwrite.all%20offline_access&response_type=code&redirect_uri=" ~ redirectUrl; - log.log("Authorize this app visiting:\n"); - write(url, "\n\n", "Enter the response uri: "); - readln(response); + string authFilesString = cfg.getValueString("auth_files"); + if (authFilesString == "") { + log.log("Authorize this app visiting:\n"); + write(url, "\n\n", "Enter the response uri: "); + readln(response); + } else { + string[] authFiles = authFilesString.split(":"); + string authUrl = authFiles[0]; + string responseUrl = authFiles[1]; + auto authUrlFile = File(authUrl, "w"); + authUrlFile.write(url); + authUrlFile.close(); + while (!exists(responseUrl)) { + Thread.sleep(dur!("msecs")(100)); + } + response = cast(char[]) read(responseUrl); + try { + std.file.remove(authUrl); + std.file.remove(responseUrl); + } catch (FileException e) { + log.error("Cannot remove files ", authUrl, " ", responseUrl); + } + } // match the authorization code auto c = matchFirst(response, r"(?:[\?&]code=)([\w\d-]+)"); if (c.empty) {