Thunderbird passwordcommand fixed
This commit is contained in:
parent
d1dd741f05
commit
ac21c9885e
274
packages/add_passwordcommand_imap.patch
Normal file
274
packages/add_passwordcommand_imap.patch
Normal file
@ -0,0 +1,274 @@
|
|||||||
|
diff -x __pycache__ -ru thunderbird-128.10.1/comm/mailnews/base/src/nsMsgIncomingServer.cpp thunderbird/thunderbird-128.10.1/comm/mailnews/base/src/nsMsgIncomingServer.cpp
|
||||||
|
--- thunderbird-128.10.1/comm/mailnews/base/src/nsMsgIncomingServer.cpp 2025-05-13 15:22:25.000000000 +0200
|
||||||
|
+++ thunderbird/thunderbird-128.10.1/comm/mailnews/base/src/nsMsgIncomingServer.cpp 2025-08-21 03:49:50.217872643 +0200
|
||||||
|
@@ -41,6 +41,15 @@
|
||||||
|
#include "mozilla/Unused.h"
|
||||||
|
#include "nsIUUIDGenerator.h"
|
||||||
|
#include "nsIArray.h"
|
||||||
|
+#include "mozilla/SpinEventLoopUntil.h"
|
||||||
|
+#include "nsIProcess.h"
|
||||||
|
+#include "mozilla/RandomNum.h"
|
||||||
|
+#include "nsIServerSocket.h"
|
||||||
|
+#include "nsIAsyncInputStream.h"
|
||||||
|
+#include "nsISocketTransport.h"
|
||||||
|
+#include "nsIBinaryInputStream.h"
|
||||||
|
+#include "nsIObjectInputStream.h"
|
||||||
|
+#include "nsDirectoryServiceDefs.h"
|
||||||
|
|
||||||
|
#define PORT_NOT_SET -1
|
||||||
|
|
||||||
|
@@ -707,12 +716,241 @@
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
+nsresult
|
||||||
|
+nsMsgIncomingServer::GetPasswordCommand(nsTArray<nsString> &passwordCommand) {
|
||||||
|
+ nsString serializedCommand;
|
||||||
|
+
|
||||||
|
+ nsresult rv = GetUnicharValue("passwordCommand", serializedCommand);
|
||||||
|
+ NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
+
|
||||||
|
+ if (serializedCommand.Length() == 0)
|
||||||
|
+ return NS_OK;
|
||||||
|
+
|
||||||
|
+ // Serialization is achieved by joining the arguments with a comma.
|
||||||
|
+ // Commas are themselves allowed to be backslash-espaced.
|
||||||
|
+
|
||||||
|
+ nsString currentArgument;
|
||||||
|
+ bool nextShouldBeEscaped = false;
|
||||||
|
+
|
||||||
|
+ for (unsigned int i = 0; i < serializedCommand.Length(); i++) {
|
||||||
|
+ char c = serializedCommand[i];
|
||||||
|
+
|
||||||
|
+ switch (c) {
|
||||||
|
+ case ',':
|
||||||
|
+ if (nextShouldBeEscaped) {
|
||||||
|
+ currentArgument.Append(',');
|
||||||
|
+ nextShouldBeEscaped = false;
|
||||||
|
+ } else {
|
||||||
|
+ passwordCommand.AppendElement(currentArgument);
|
||||||
|
+ currentArgument.Truncate();
|
||||||
|
+ }
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ case '\\':
|
||||||
|
+ if (nextShouldBeEscaped)
|
||||||
|
+ currentArgument.Append(',');
|
||||||
|
+
|
||||||
|
+ nextShouldBeEscaped = !nextShouldBeEscaped;
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ default:
|
||||||
|
+ currentArgument.Append(c);
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (nextShouldBeEscaped)
|
||||||
|
+ currentArgument.Append('\\');
|
||||||
|
+ passwordCommand.AppendElement(currentArgument);
|
||||||
|
+
|
||||||
|
+ return NS_OK;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+class PasswordCommandObserver final
|
||||||
|
+ : public nsIObserver,
|
||||||
|
+ public nsIServerSocketListener,
|
||||||
|
+ public nsIInputStreamCallback {
|
||||||
|
+ public:
|
||||||
|
+ NS_DECL_ISUPPORTS
|
||||||
|
+ NS_DECL_NSIOBSERVER
|
||||||
|
+ NS_DECL_NSISERVERSOCKETLISTENER
|
||||||
|
+ NS_DECL_NSIINPUTSTREAMCALLBACK
|
||||||
|
+
|
||||||
|
+ private:
|
||||||
|
+ bool isCommandDone;
|
||||||
|
+ bool passwordReceived;
|
||||||
|
+ nsAString& password;
|
||||||
|
+ nsTArray<uint8_t> received;
|
||||||
|
+
|
||||||
|
+ public:
|
||||||
|
+ PasswordCommandObserver(nsAString& password);
|
||||||
|
+ bool IsDone();
|
||||||
|
+ private:
|
||||||
|
+ ~PasswordCommandObserver();
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+NS_IMPL_ISUPPORTS(PasswordCommandObserver, nsIObserver, nsIServerSocketListener, nsIInputStreamCallback)
|
||||||
|
+
|
||||||
|
+PasswordCommandObserver::PasswordCommandObserver(nsAString& password) : password(password) {
|
||||||
|
+ isCommandDone = false;
|
||||||
|
+ passwordReceived = false;
|
||||||
|
+}
|
||||||
|
+PasswordCommandObserver::~PasswordCommandObserver() {}
|
||||||
|
+
|
||||||
|
+bool
|
||||||
|
+PasswordCommandObserver::IsDone() {
|
||||||
|
+ return isCommandDone && passwordReceived;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+NS_IMETHODIMP
|
||||||
|
+PasswordCommandObserver::Observe(nsISupports* aSubject, const char* aTopic,
|
||||||
|
+ const char16_t* aData) {
|
||||||
|
+ isCommandDone = true;
|
||||||
|
+
|
||||||
|
+ return strcmp(aTopic, "process-failed") == 0 ? NS_ERROR_FAILURE : NS_OK;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+NS_IMETHODIMP
|
||||||
|
+PasswordCommandObserver::OnSocketAccepted(nsIServerSocket *aServ, nsISocketTransport *aTransport) {
|
||||||
|
+ nsresult rv;
|
||||||
|
+
|
||||||
|
+ // The socket can be closed. This does not close the existing connection.
|
||||||
|
+ rv = aServ->Close();
|
||||||
|
+ NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
+
|
||||||
|
+ nsCOMPtr<nsIInputStream> stream;
|
||||||
|
+ rv = aTransport->OpenInputStream(0, 0, 0, getter_AddRefs(stream));
|
||||||
|
+ NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
+
|
||||||
|
+ nsCOMPtr<nsIAsyncInputStream> astream;
|
||||||
|
+ astream = do_QueryInterface(stream);
|
||||||
|
+ rv = astream->AsyncWait(this, 0, 0, NS_GetCurrentThread());
|
||||||
|
+ NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
+
|
||||||
|
+ return NS_OK;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+NS_IMETHODIMP
|
||||||
|
+PasswordCommandObserver::OnStopListening(nsIServerSocket *aServ, nsresult aStatus) {
|
||||||
|
+ return NS_OK;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+NS_IMETHODIMP
|
||||||
|
+PasswordCommandObserver::OnInputStreamReady(nsIAsyncInputStream *aStream) {
|
||||||
|
+ nsresult rv;
|
||||||
|
+
|
||||||
|
+ int64_t len;
|
||||||
|
+ rv = aStream->Available((uint64_t*)&len);
|
||||||
|
+ if (NS_FAILED(rv))
|
||||||
|
+ // note: aStream->Available() can also return -1.
|
||||||
|
+ len = -1;
|
||||||
|
+
|
||||||
|
+ if (len == -1) {
|
||||||
|
+ password.Assign(NS_ConvertUTF8toUTF16((char*)received.Elements(), received.Length()));
|
||||||
|
+ passwordReceived = true;
|
||||||
|
+ } else {
|
||||||
|
+ if (len > 0) {
|
||||||
|
+ nsCOMPtr<nsIBinaryInputStream> bin = NS_NewObjectInputStream(aStream);
|
||||||
|
+ nsTArray<uint8_t> data;
|
||||||
|
+ rv = bin->ReadByteArray(len, data);
|
||||||
|
+ NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
+ received.AppendElements(data);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ rv = aStream->AsyncWait(this, 0, 0, NS_GetCurrentThread());
|
||||||
|
+ NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return NS_OK;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+nsresult
|
||||||
|
+nsMsgIncomingServer::RunPasswordCommand(nsTArray<nsString> &passwordCommand, nsAString& password) {
|
||||||
|
+ nsresult rv;
|
||||||
|
+
|
||||||
|
+ nsCOMPtr<nsIFile> socketFile;
|
||||||
|
+ rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(socketFile));
|
||||||
|
+ NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
+ nsAutoString tempSocketName;
|
||||||
|
+ uint64_t randomSocketName = mozilla::RandomUint64().valueOrFrom([] {
|
||||||
|
+ return 0;
|
||||||
|
+ });
|
||||||
|
+ const char* alphabet = "abcdefghijklmnopqrstuvwxyz0123456789";
|
||||||
|
+ tempSocketName.AppendPrintf(
|
||||||
|
+ "tmp-%c%c%c.sock",
|
||||||
|
+ alphabet[randomSocketName % 36],
|
||||||
|
+ alphabet[(randomSocketName / 36) % 36],
|
||||||
|
+ alphabet[(randomSocketName / (36*36)) % 36]
|
||||||
|
+ );
|
||||||
|
+ socketFile->AppendRelativePath(tempSocketName);
|
||||||
|
+
|
||||||
|
+ nsCOMPtr<nsIServerSocket> socket =
|
||||||
|
+ do_CreateInstance(NS_SERVERSOCKET_CONTRACTID);
|
||||||
|
+ socket->InitWithFilename(socketFile, 0600, -1);
|
||||||
|
+
|
||||||
|
+ auto executable = passwordCommand[0];
|
||||||
|
+ nsCOMPtr<nsIFile> executableFile =
|
||||||
|
+ do_CreateInstance("@mozilla.org/file/local;1", &rv);
|
||||||
|
+ NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
+ executableFile->InitWithPath(executable);
|
||||||
|
+
|
||||||
|
+ nsCOMPtr<nsIProcess> process =
|
||||||
|
+ do_CreateInstance("@mozilla.org/process/util;1", &rv);
|
||||||
|
+ NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
+ rv = process->Init(executableFile);
|
||||||
|
+ NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
+
|
||||||
|
+ auto observer = new PasswordCommandObserver(password);
|
||||||
|
+
|
||||||
|
+ socket->AsyncListen(observer);
|
||||||
|
+
|
||||||
|
+ auto argsCount = passwordCommand.Length();
|
||||||
|
+ const char** args = new const char*[argsCount];
|
||||||
|
+ for (unsigned int i = 0; i < argsCount - 1; i++) {
|
||||||
|
+ NS_ConvertUTF16toUTF8 argUtf8(passwordCommand[i + 1]);
|
||||||
|
+ args[i] = strdup(argUtf8.get());
|
||||||
|
+ }
|
||||||
|
+ nsString socketPath;
|
||||||
|
+ rv = socketFile->GetPath(socketPath);
|
||||||
|
+ NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
+ NS_ConvertUTF16toUTF8 socketPathUtf8(socketPath);
|
||||||
|
+ args[argsCount - 1] = strdup(socketPathUtf8.get());
|
||||||
|
+
|
||||||
|
+ rv = process->RunAsync(args, argsCount, observer, false);
|
||||||
|
+ if (NS_FAILED(rv))
|
||||||
|
+ return rv;
|
||||||
|
+
|
||||||
|
+ mozilla::SpinEventLoopUntil("nsMsgIncomingServer::RunPasswordCommand"_ns, [&]() {
|
||||||
|
+ return observer->IsDone();
|
||||||
|
+ });
|
||||||
|
+
|
||||||
|
+ for (unsigned int i = 0; i < argsCount; i++)
|
||||||
|
+ free((void*)args[i]);
|
||||||
|
+ delete[] args;
|
||||||
|
+
|
||||||
|
+ return NS_OK;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsMsgIncomingServer::GetPasswordWithUI(const nsAString& aPromptMessage,
|
||||||
|
const nsAString& aPromptTitle,
|
||||||
|
nsAString& aPassword) {
|
||||||
|
nsresult rv = NS_OK;
|
||||||
|
|
||||||
|
+ nsTArray<nsString> passwordCommand;
|
||||||
|
+ rv = GetPasswordCommand(passwordCommand);
|
||||||
|
+ NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
+
|
||||||
|
+ if (passwordCommand.Length() > 0) {
|
||||||
|
+ rv = RunPasswordCommand(passwordCommand, aPassword);
|
||||||
|
+ NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
+
|
||||||
|
+ rv = SetPassword(aPassword);
|
||||||
|
+ NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
+
|
||||||
|
+ return NS_OK;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (m_password.IsEmpty()) {
|
||||||
|
// let's see if we have the password in the password manager and
|
||||||
|
// can avoid this prompting thing. This makes it easier to get embedders
|
||||||
|
diff -x __pycache__ -ru thunderbird-128.10.1/comm/mailnews/base/src/nsMsgIncomingServer.h thunderbird/thunderbird-128.10.1/comm/mailnews/base/src/nsMsgIncomingServer.h
|
||||||
|
--- thunderbird-128.10.1/comm/mailnews/base/src/nsMsgIncomingServer.h 2025-05-13 15:22:25.000000000 +0200
|
||||||
|
+++ thunderbird/thunderbird-128.10.1/comm/mailnews/base/src/nsMsgIncomingServer.h 2025-08-19 12:39:19.236805257 +0200
|
||||||
|
@@ -48,6 +48,9 @@
|
||||||
|
nsCString m_serverKey;
|
||||||
|
bool m_hasShutDown;
|
||||||
|
|
||||||
|
+ nsresult GetPasswordCommand(nsTArray<nsString> &passwordCommand);
|
||||||
|
+ nsresult RunPasswordCommand(nsTArray<nsString> &passwordCommand, nsAString& password);
|
||||||
|
+
|
||||||
|
// Sets m_password, if password found. Can return NS_ERROR_ABORT if the
|
||||||
|
// user cancels the master password dialog.
|
||||||
|
nsresult GetPasswordWithoutUI();
|
298
packages/add_passwordcommand_smtp.patch
Normal file
298
packages/add_passwordcommand_smtp.patch
Normal file
@ -0,0 +1,298 @@
|
|||||||
|
--- a/comm/mailnews/base/src/MailAuthenticator.sys.mjs
|
||||||
|
+++ b/comm/mailnews/base/src/MailAuthenticator.sys.mjs
|
||||||
|
@@ -229,7 +229,7 @@
|
||||||
|
this._server.forgetPassword();
|
||||||
|
}
|
||||||
|
|
||||||
|
- getPassword() {
|
||||||
|
+ async getPassword() {
|
||||||
|
if (this._server.password) {
|
||||||
|
return this._server.password;
|
||||||
|
}
|
||||||
|
@@ -261,8 +261,8 @@
|
||||||
|
*
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
- getByteStringPassword() {
|
||||||
|
- return MailStringUtils.stringToByteString(this.getPassword());
|
||||||
|
+ async getByteStringPassword() {
|
||||||
|
+ return MailStringUtils.stringToByteString(await this.getPassword());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@@ -270,10 +270,12 @@
|
||||||
|
*
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
- getPlainToken() {
|
||||||
|
+ async getPlainToken() {
|
||||||
|
// According to rfc4616#section-2, password should be UTF-8 BinaryString
|
||||||
|
// before base64 encoded.
|
||||||
|
- return btoa("\0" + this.username + "\0" + this.getByteStringPassword());
|
||||||
|
+ return btoa(
|
||||||
|
+ "\0" + this.username + "\0" + (await this.getByteStringPassword())
|
||||||
|
+ );
|
||||||
|
}
|
||||||
|
|
||||||
|
async getOAuthToken() {
|
||||||
|
--- a/comm/mailnews/compose/src/SmtpServer.sys.mjs
|
||||||
|
+++ b/comm/mailnews/compose/src/SmtpServer.sys.mjs
|
||||||
|
@@ -7,9 +7,22 @@
|
||||||
|
|
||||||
|
const lazy = {};
|
||||||
|
ChromeUtils.defineESModuleGetters(lazy, {
|
||||||
|
+ FileUtils: "resource:///modules/FileUtils.sys.mjs",
|
||||||
|
SmtpClient: "resource:///modules/SmtpClient.sys.mjs",
|
||||||
|
});
|
||||||
|
|
||||||
|
+const UnixServerSocket = Components.Constructor(
|
||||||
|
+ "@mozilla.org/network/server-socket;1",
|
||||||
|
+ "nsIServerSocket",
|
||||||
|
+ "initWithFilename"
|
||||||
|
+);
|
||||||
|
+const currentThread = Cc["@mozilla.org/thread-manager;1"].getService().currentThread;
|
||||||
|
+const BinaryInputStream = Components.Constructor(
|
||||||
|
+ "@mozilla.org/binaryinputstream;1",
|
||||||
|
+ "nsIBinaryInputStream",
|
||||||
|
+ "setInputStream"
|
||||||
|
+);
|
||||||
|
+
|
||||||
|
/**
|
||||||
|
* This class represents a single SMTP server.
|
||||||
|
*
|
||||||
|
@@ -318,7 +331,161 @@
|
||||||
|
this._password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
- getPasswordWithUI(promptMessage, promptTitle) {
|
||||||
|
+ getPasswordCommand() {
|
||||||
|
+ let serializedCommand = this._getCharPrefWithDefault("passwordCommand");
|
||||||
|
+ if (serializedCommand === "")
|
||||||
|
+ return null;
|
||||||
|
+
|
||||||
|
+ // Serialization is achieved by joining the arguments with a comma.
|
||||||
|
+ // Comma are themselves allowed to be backslash-espaced.
|
||||||
|
+
|
||||||
|
+ let currentArgument = "";
|
||||||
|
+ let nextShouldBeEscaped = false;
|
||||||
|
+ let commandArguments = [];
|
||||||
|
+
|
||||||
|
+ for (let i = 0; i < serializedCommand.length; i++) {
|
||||||
|
+ let c = serializedCommand[i];
|
||||||
|
+
|
||||||
|
+ switch (c) {
|
||||||
|
+ case ',':
|
||||||
|
+ if (nextShouldBeEscaped) {
|
||||||
|
+ currentArgument += ',';
|
||||||
|
+ nextShouldBeEscaped = false;
|
||||||
|
+ } else {
|
||||||
|
+ commandArguments.push(currentArgument);
|
||||||
|
+ currentArgument = '';
|
||||||
|
+ }
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ case '\\':
|
||||||
|
+ if (nextShouldBeEscaped)
|
||||||
|
+ currentArgument += '\\';
|
||||||
|
+
|
||||||
|
+ nextShouldBeEscaped = !nextShouldBeEscaped;
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ default:
|
||||||
|
+ currentArgument += c;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (nextShouldBeEscaped)
|
||||||
|
+ currentArgument += '\\';
|
||||||
|
+ commandArguments.push(currentArgument);
|
||||||
|
+
|
||||||
|
+ return commandArguments;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ async runPasswordCommand(passwordCommand) {
|
||||||
|
+ let executable = passwordCommand[0];
|
||||||
|
+ let args = passwordCommand.splice(1);
|
||||||
|
+
|
||||||
|
+ let executableFile = new lazy.FileUtils.File(executable);
|
||||||
|
+
|
||||||
|
+ function genSocketFile() {
|
||||||
|
+ let tmpDir = lazy.FileUtils.getDir("TmpD", [], false);
|
||||||
|
+ let random = Math.round(Math.random() * 36 ** 3).toString(36);
|
||||||
|
+ return new lazy.FileUtils.File(
|
||||||
|
+ PathUtils.join(tmpDir.path, `tmp-${random}.sock`)
|
||||||
|
+ );
|
||||||
|
+ }
|
||||||
|
+ let socketFile = genSocketFile();
|
||||||
|
+
|
||||||
|
+ let socket = new UnixServerSocket(
|
||||||
|
+ socketFile,
|
||||||
|
+ parseInt("600", 8),
|
||||||
|
+ -1
|
||||||
|
+ );
|
||||||
|
+
|
||||||
|
+ var process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess);
|
||||||
|
+ process.init(executableFile);
|
||||||
|
+ let processPromise = new Promise((resolve, reject) => {
|
||||||
|
+ process.runAsync(
|
||||||
|
+ args.concat(socketFile.path),
|
||||||
|
+ args.length + 1,
|
||||||
|
+ {
|
||||||
|
+ observe(subject, topic, data) {
|
||||||
|
+ switch (topic) {
|
||||||
|
+ case "process-finished":
|
||||||
|
+ resolve();
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ case "process-failed":
|
||||||
|
+ reject();
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ },
|
||||||
|
+ false
|
||||||
|
+ );
|
||||||
|
+ });
|
||||||
|
+
|
||||||
|
+ let passwordPromise = new Promise((resolve, reject) => {
|
||||||
|
+ socket.asyncListen({
|
||||||
|
+ "onSocketAccepted": (server, transport) => {
|
||||||
|
+ // The socket can be closed. This does not close the existing connection.
|
||||||
|
+ socket.close();
|
||||||
|
+
|
||||||
|
+ var stream = transport.openInputStream(0, 0, 0);
|
||||||
|
+
|
||||||
|
+ let received = [];
|
||||||
|
+ let observer = {
|
||||||
|
+ onInputStreamReady(stream) {
|
||||||
|
+ let len = 0;
|
||||||
|
+ try {
|
||||||
|
+ len = stream.available();
|
||||||
|
+ } catch (e) {
|
||||||
|
+ // note: stream.available() can also return -1.
|
||||||
|
+ len = -1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (len == -1) {
|
||||||
|
+ let decoder = new TextDecoder();
|
||||||
|
+ let result = decoder.decode(new Uint8Array(received));
|
||||||
|
+
|
||||||
|
+ resolve(result);
|
||||||
|
+ } else {
|
||||||
|
+ if (len > 0) {
|
||||||
|
+ let bin = new BinaryInputStream(stream);
|
||||||
|
+ let data = Array.from(bin.readByteArray(len));
|
||||||
|
+ received = received.concat(data);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ stream.asyncWait(observer, 0, 0, currentThread);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ };
|
||||||
|
+ stream.asyncWait(observer, 0, 0, currentThread);
|
||||||
|
+ }
|
||||||
|
+ });
|
||||||
|
+ });
|
||||||
|
+
|
||||||
|
+ let [_, result] = await Promise.allSettled([
|
||||||
|
+ processPromise,
|
||||||
|
+ passwordPromise,
|
||||||
|
+ ]);
|
||||||
|
+
|
||||||
|
+ socketFile.remove(false);
|
||||||
|
+
|
||||||
|
+ if (result.status == "fulfilled")
|
||||||
|
+ return result.value;
|
||||||
|
+ else
|
||||||
|
+ return Promise.reject(result.reason);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ async getPasswordWithUI(promptMessage, promptTitle) {
|
||||||
|
+ let passwordCommand = this.getPasswordCommand();
|
||||||
|
+ if (passwordCommand !== null) {
|
||||||
|
+ let password = await this.runPasswordCommand(passwordCommand);
|
||||||
|
+
|
||||||
|
+ if (password === null)
|
||||||
|
+ throw Components.Exception("Password command failure", Cr.NS_ERROR_ABORT);
|
||||||
|
+
|
||||||
|
+ this.password = password;
|
||||||
|
+ return this.password;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
// This prompt has a checkbox for saving password.
|
||||||
|
const authPrompt = Cc["@mozilla.org/messenger/msgAuthPrompt;1"].getService(
|
||||||
|
Ci.nsIAuthPrompt
|
||||||
|
--- a/comm/mailnews/compose/src/SmtpClient.sys.mjs
|
||||||
|
+++ b/comm/mailnews/compose/src/SmtpClient.sys.mjs
|
||||||
|
@@ -362,7 +362,7 @@
|
||||||
|
*
|
||||||
|
* @param {string} chunk Chunk of data received from the server
|
||||||
|
*/
|
||||||
|
- _parse(chunk) {
|
||||||
|
+ async _parse(chunk) {
|
||||||
|
// Lines should always end with <CR><LF> but you never know, might be only <LF> as well
|
||||||
|
var lines = (this._parseRemainder + (chunk || "")).split(/\r?\n/);
|
||||||
|
this._parseRemainder = lines.pop(); // not sure if the line has completely arrived yet
|
||||||
|
@@ -399,14 +399,14 @@
|
||||||
|
success: statusCode >= 200 && statusCode < 300,
|
||||||
|
};
|
||||||
|
|
||||||
|
- this._onCommand(response);
|
||||||
|
+ await this._onCommand(response);
|
||||||
|
this._parseBlock = {
|
||||||
|
data: [],
|
||||||
|
statusCode: null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
- this._onCommand({
|
||||||
|
+ await this._onCommand({
|
||||||
|
success: false,
|
||||||
|
statusCode: this._parseBlock.statusCode || null,
|
||||||
|
data: [lines[i]].join("\n"),
|
||||||
|
@@ -456,7 +456,7 @@
|
||||||
|
// rejects AUTH PLAIN then closes the connection, the client then sends AUTH
|
||||||
|
// LOGIN. This line guarantees onclose is called before sending AUTH LOGIN.
|
||||||
|
await new Promise(resolve => setTimeout(resolve));
|
||||||
|
- this._parse(stringPayload);
|
||||||
|
+ await this._parse(stringPayload);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
@@ -732,7 +732,7 @@
|
||||||
|
this.logger.debug("Authentication via AUTH PLAIN");
|
||||||
|
this._currentAction = this._actionAUTHComplete;
|
||||||
|
this._sendCommand(
|
||||||
|
- "AUTH PLAIN " + this._authenticator.getPlainToken(),
|
||||||
|
+ "AUTH PLAIN " + (await this._authenticator.getPlainToken()),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
@@ -1065,7 +1065,7 @@
|
||||||
|
* @param {{statusCode: number, data: string}} command - Parsed command from
|
||||||
|
* the server.
|
||||||
|
*/
|
||||||
|
- _actionAUTH_LOGIN_PASS(command) {
|
||||||
|
+ async _actionAUTH_LOGIN_PASS(command) {
|
||||||
|
if (
|
||||||
|
command.statusCode !== 334 ||
|
||||||
|
(command.data !== btoa("Password:") && command.data !== btoa("password:"))
|
||||||
|
@@ -1075,7 +1075,7 @@
|
||||||
|
}
|
||||||
|
this.logger.debug("AUTH LOGIN PASS");
|
||||||
|
this._currentAction = this._actionAUTHComplete;
|
||||||
|
- let password = this._getPassword();
|
||||||
|
+ let password = await this._getPassword();
|
||||||
|
if (
|
||||||
|
!Services.prefs.getBoolPref(
|
||||||
|
"mail.smtp_login_pop3_user_pass_auth_is_latin1",
|
||||||
|
@@ -1104,7 +1104,7 @@
|
||||||
|
}
|
||||||
|
this._currentAction = this._actionAUTHComplete;
|
||||||
|
this._sendCommand(
|
||||||
|
- this._authenticator.getCramMd5Token(this._getPassword(), command.data),
|
||||||
|
+ this._authenticator.getCramMd5Token(await this._getPassword(), command.data),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
@ -13,6 +13,7 @@
|
|||||||
./locale.nix
|
./locale.nix
|
||||||
./ssh.nix
|
./ssh.nix
|
||||||
./email.nix
|
./email.nix
|
||||||
|
./git.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
nix.settings.experimental-features = [
|
nix.settings.experimental-features = [
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
};
|
};
|
||||||
smtp = {
|
smtp = {
|
||||||
host = "smtp.hadoly.fr";
|
host = "smtp.hadoly.fr";
|
||||||
port = 443;
|
port = 465;
|
||||||
tls.enable = true;
|
tls.enable = true;
|
||||||
};
|
};
|
||||||
primary = true;
|
primary = true;
|
||||||
@ -34,7 +34,7 @@
|
|||||||
};
|
};
|
||||||
smtp = {
|
smtp = {
|
||||||
host = "mail.mailo.com";
|
host = "mail.mailo.com";
|
||||||
port = 443;
|
port = 465;
|
||||||
tls.enable = true;
|
tls.enable = true;
|
||||||
};
|
};
|
||||||
userName = "samyavrillon@netcourrier.com";
|
userName = "samyavrillon@netcourrier.com";
|
||||||
|
15
profiles/basic/git.nix
Normal file
15
profiles/basic/git.nix
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{config, lib, pkgs, ...}: {
|
||||||
|
|
||||||
|
home-manager.users.mysaa.programs.git = {
|
||||||
|
enable = true;
|
||||||
|
userEmail = "mysaa@hadoly.fr";
|
||||||
|
userName = "Mysaa Java";
|
||||||
|
|
||||||
|
signing.key = "880352F5FD83DF24F41413CC4E77725580DA73CE";
|
||||||
|
|
||||||
|
aliases = {
|
||||||
|
l = "log --oneline --graph";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
@ -1,12 +1,16 @@
|
|||||||
{config, lib, pkgs, ...}: {
|
{config, lib, pkgs, ...}: {
|
||||||
|
|
||||||
programs.ssh = {
|
programs.ssh = {
|
||||||
extraConfig = "
|
extraConfig = ''
|
||||||
Host git-ssh.hadoly.fr
|
Host git-ssh.hadoly.fr
|
||||||
Hostname git-ssh.hadoly.fr
|
Hostname git-ssh.hadoly.fr
|
||||||
IdentityFile /run/secrets/ssh/mysaa@git.hadoly.fr
|
IdentityFile /run/secrets/ssh/mysaa@git.hadoly.fr
|
||||||
Port 6900
|
Port 6900
|
||||||
";
|
|
||||||
|
Host github.com
|
||||||
|
HostName github.com
|
||||||
|
IdentityFile /run/secrets/ssh/MysaaJava@github.com
|
||||||
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,10 @@
|
|||||||
discord
|
discord
|
||||||
];
|
];
|
||||||
|
|
||||||
|
environment.plasma6.excludePackages = with pkgs.kdePackages; [
|
||||||
|
elisa
|
||||||
|
];
|
||||||
|
|
||||||
home-manager.users.mysaa.home.packages = with pkgs; [
|
home-manager.users.mysaa.home.packages = with pkgs; [
|
||||||
firefox
|
firefox
|
||||||
vlc
|
vlc
|
||||||
@ -23,14 +27,57 @@
|
|||||||
edwinkofler.vscode-hyperupcall-pack-java
|
edwinkofler.vscode-hyperupcall-pack-java
|
||||||
];
|
];
|
||||||
})
|
})
|
||||||
|
keepassxc
|
||||||
|
libreoffice
|
||||||
|
#hyphenDicts.fr_FR
|
||||||
|
hyphenDicts.en_US
|
||||||
|
hyphenDicts.de_DE
|
||||||
|
steam
|
||||||
];
|
];
|
||||||
|
|
||||||
|
home-manager.users.mysaa.services.kdeconnect.enable = true;
|
||||||
|
# We open kdeconnect ports
|
||||||
|
networking.firewall = rec {
|
||||||
|
allowedTCPPortRanges = [ { from = 1714; to = 1764; } ];
|
||||||
|
allowedUDPPortRanges = allowedTCPPortRanges;
|
||||||
|
};
|
||||||
|
|
||||||
home-manager.users.mysaa.accounts.email.accounts."hadoly".thunderbird.enable = true;
|
home-manager.users.mysaa.accounts.email.accounts."hadoly".thunderbird.enable = true;
|
||||||
home-manager.users.mysaa.accounts.email.accounts."personal".thunderbird.enable = true;
|
home-manager.users.mysaa.accounts.email.accounts."personal".thunderbird.enable = true;
|
||||||
home-manager.users.mysaa.programs.thunderbird = {
|
home-manager.users.mysaa.programs.thunderbird = {
|
||||||
enable = true;
|
enable = true;
|
||||||
profiles.default = {
|
profiles.default = {
|
||||||
isDefault = true;
|
isDefault = true;
|
||||||
};
|
settings = {}
|
||||||
};
|
// lib.attrsets.concatMapAttrs (
|
||||||
|
_: account:
|
||||||
|
lib.optionalAttrs (account.passwordCommand != null) (
|
||||||
|
let
|
||||||
|
id = builtins.hashString "sha256" account.name;
|
||||||
|
command = lib.concatStringsSep " " account.passwordCommand;
|
||||||
|
passwordScript = pkgs.writeShellScript "get-password.sh" ''
|
||||||
|
${command} | tr -d $'\n' | ${pkgs.netcat}/bin/nc -w 0 -U $1
|
||||||
|
'';
|
||||||
|
in
|
||||||
|
lib.optionalAttrs (account.smtp != null) {
|
||||||
|
"mail.smtpserver.smtp_${id}.passwordCommand" = toString passwordScript;
|
||||||
|
}
|
||||||
|
// lib.optionalAttrs (account.imap != null) {
|
||||||
|
"mail.server.server_${id}.passwordCommand" = toString passwordScript;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
) config.home-manager.users.mysaa.accounts.email.accounts;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
home-manager.users.mysaa.nixpkgs.overlays = [
|
||||||
|
(final: prev: {
|
||||||
|
thunderbird-unwrapped = prev.thunderbird-unwrapped.overrideAttrs {
|
||||||
|
patches = (prev.thunderbird-unwrapped.patches or [ ]) ++ [
|
||||||
|
../../packages/add_passwordcommand_smtp.patch
|
||||||
|
../../packages/add_passwordcommand_imap.patch
|
||||||
|
];
|
||||||
|
};
|
||||||
|
})
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user