From 9e951848ba068d29138c9663e76bb4fa114660be Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Sat, 19 Nov 2022 05:49:40 -0800 Subject: [PATCH 0/7] *** NOT A PATCH *** *** BLURB HERE *** F. Jason Park (7): Add GS2 authorization to sasl-scram-rfc Don't set erc-networks--id until network is known Make erc--server-reconnecting non-buffer-local Support local ERC modules in erc-mode buffers Call erc-login indirectly via new generic wrapper Add non-IRCv3 SASL module to ERC Accept functions in place of passwords in ERC doc/misc/erc.texi | 162 ++++++- etc/ERC-NEWS | 13 +- lisp/erc/erc-backend.el | 35 +- lisp/erc/erc-common.el | 56 ++- lisp/erc/erc-compat.el | 104 +++++ lisp/erc/erc-goodies.el | 1 + lisp/erc/erc-networks.el | 39 +- lisp/erc/erc-sasl.el | 429 ++++++++++++++++++ lisp/erc/erc-services.el | 5 +- lisp/erc/erc.el | 135 ++++-- lisp/net/sasl-scram-rfc.el | 21 +- test/lisp/erc/erc-sasl-tests.el | 344 ++++++++++++++ test/lisp/erc/erc-scenarios-sasl.el | 202 +++++++++ test/lisp/erc/erc-services-tests.el | 16 +- test/lisp/erc/erc-tests.el | 87 ++++ test/lisp/erc/resources/sasl/external.eld | 33 ++ test/lisp/erc/resources/sasl/plain-failed.eld | 16 + test/lisp/erc/resources/sasl/plain.eld | 39 ++ test/lisp/erc/resources/sasl/scram-sha-1.eld | 47 ++ .../lisp/erc/resources/sasl/scram-sha-256.eld | 47 ++ 20 files changed, 1724 insertions(+), 107 deletions(-) create mode 100644 lisp/erc/erc-sasl.el create mode 100644 test/lisp/erc/erc-sasl-tests.el create mode 100644 test/lisp/erc/erc-scenarios-sasl.el create mode 100644 test/lisp/erc/resources/sasl/external.eld create mode 100644 test/lisp/erc/resources/sasl/plain-failed.eld create mode 100644 test/lisp/erc/resources/sasl/plain.eld create mode 100644 test/lisp/erc/resources/sasl/scram-sha-1.eld create mode 100644 test/lisp/erc/resources/sasl/scram-sha-256.eld Interdiff: diff --git a/doc/misc/erc.texi b/doc/misc/erc.texi index 790db1135e..834f1cbf2c 100644 --- a/doc/misc/erc.texi +++ b/doc/misc/erc.texi @@ -1067,12 +1067,13 @@ SASL NickServ password. If you're still having trouble, please contact us (@pxref{Getting Help and Reporting Bugs}). -And if, for whatever reason, you do find yourself trying out -non-default SASL settings, keep in mind that every change requires a -fresh session, so you'll want to call @code{erc-tls} from scratch -again rather than rely on @samp{/reconnect} or the auto-reconnect -facility. In fact, it's best to temporarily set -@code{erc-server-auto-reconnect} to @code{nil} while experimenting. +As you try out different settings, keep in mind that it's best to +create a fresh session for every change, for example, by calling +@code{erc-tls} from scratch. More experienced users may be able to +get away with cycling @code{erc-sasl-mode} and issuing a +@samp{/reconnect}, but that's generally not recommended. Whatever the +case, you'll probably want to temporarily disable +@code{erc-server-auto-reconnect} while experimenting. @node Sample Configuration @section Sample Configuration diff --git a/etc/ERC-NEWS b/etc/ERC-NEWS index 829ef25a47..3e1b7bca95 100644 --- a/etc/ERC-NEWS +++ b/etc/ERC-NEWS @@ -103,14 +103,6 @@ messages during periods of heavy traffic no longer disappear. Although rare, server passwords containing white space are now handled correctly. -** ERC-mode hooks are more useful. -The function 'erc-update-modules' now supports an optional argument to -defer enabling of local modules and instead return their mode -commands. 'erc-open' relies on this to delay their activation, as -well as that of all 'erc-mode-hook' members, until most local session -variables have been initialized (minus those "server"- and -process-focused ones in erc-backend). - ** Miscellaneous behavioral changes in the library API. A number of core macros and other definitions have been moved to a new file called erc-common.el. This was done to further lessen the @@ -132,6 +124,12 @@ The function 'erc-auto-query' was deemed too difficult to reason through and has thus been deprecated with no public replacement; it has also been removed from the client code path. +The function 'erc-open' now delays running 'erc-mode-hook' members +until most local session variables have been initialized (minus those +connection-related ones in erc-backend). 'erc-open' also no longer +calls 'erc-update-modules', although modules are still activated +in an identical fashion. + A few internal variables have been introduced that could just as well have been made public, possibly as user options. Likewise for some internal functions. As always, users needing such functionality diff --git a/lisp/erc/erc-backend.el b/lisp/erc/erc-backend.el index 7bf21087c6..ed1a92867b 100644 --- a/lisp/erc/erc-backend.el +++ b/lisp/erc/erc-backend.el @@ -312,8 +312,13 @@ erc-server-reconnecting (make-obsolete-variable 'erc-server-reconnecting "see `erc--server-reconnecting'" "29.1") -(defvar-local erc--server-reconnecting nil - "Non-nil when reconnecting.") +(defvar erc--server-reconnecting nil + "An alist of buffer-local vars and their values when reconnecting. +This is for the benefit of local modules and `erc-mode-hook' +members so they can access buffer-local data from the previous +session when reconnecting. Once `erc-reuse-buffers' is retired +and fully removed, modules can switch to leveraging the +`permanent-local' property instead.") (defvar-local erc-server-timed-out nil "Non-nil if the IRC server failed to respond to a ping.") @@ -669,7 +674,6 @@ erc-server-connect (setq erc-server-process process) (setq erc-server-quitting nil) (setq erc-server-reconnecting nil - erc--server-reconnecting nil erc--server-reconnect-timer nil) (setq erc-server-timed-out nil) (setq erc-server-banned nil) @@ -711,11 +715,11 @@ erc-server-reconnect (with-current-buffer buffer (erc-update-mode-line) (erc-set-active-buffer (current-buffer)) - (setq erc--server-reconnecting t) (setq erc-server-last-sent-time 0) (setq erc-server-lines-sent 0) (let ((erc-server-connect-function (or erc-session-connector - #'erc-open-network-stream))) + #'erc-open-network-stream)) + (erc--server-reconnecting (buffer-local-variables))) (erc-open erc-session-server erc-session-port erc-server-current-nick erc-session-user-full-name t erc-session-password nil nil nil erc-session-client-certificate @@ -829,8 +833,7 @@ erc-process-sentinel-2 (if (not reconnect-p) ;; terminate, do not reconnect (progn - (setq erc--server-reconnecting nil - erc--server-reconnect-timer nil) + (setq erc--server-reconnect-timer nil) (erc-display-message nil 'error (current-buffer) 'terminated ?e event) (set-buffer-modified-p nil)) diff --git a/lisp/erc/erc-compat.el b/lisp/erc/erc-compat.el index 47299ee3cc..8b95f8ac81 100644 --- a/lisp/erc/erc-compat.el +++ b/lisp/erc/erc-compat.el @@ -417,18 +417,6 @@ erc-compat--29-browse-url-irc (cons '("\\`irc6?s?://" . erc-compat--29-browse-url-irc) existing)))))) -(defun erc-compat--local-module-modes () - (delq nil - (if (boundp 'local-minor-modes) - (mapcar (lambda (m) - (and (string-prefix-p "erc-" (symbol-name m)) m)) - local-minor-modes) - (mapcar (pcase-lambda (`(,k . _)) - (and (string-prefix-p "erc-" (symbol-name k)) - (string-suffix-p "-mode" (symbol-name k)) - k)) - (buffer-local-variables))))) - (provide 'erc-compat) ;;; erc-compat.el ends here diff --git a/lisp/erc/erc-sasl.el b/lisp/erc/erc-sasl.el index aabb6c8a51..16fe93f50d 100644 --- a/lisp/erc/erc-sasl.el +++ b/lisp/erc/erc-sasl.el @@ -288,7 +288,7 @@ erc-sasl--init ;; non-nil and contain erroneous values, but how can we detect that? ;; What if the server dropped the connection for some other reason? (setq erc-sasl--options - (or (and (consp erc--server-reconnecting) + (or (and erc--server-reconnecting (alist-get 'erc-sasl--options erc--server-reconnecting)) `((user . ,erc-sasl-user) (password . ,erc-sasl-password) diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index 60bfb909e0..0b1f44e560 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -1870,23 +1870,24 @@ erc-modules (repeat :tag "Others" :inline t symbol)) :group 'erc) -(defun erc-update-modules (&optional defer-locals) - "Enable global minor mode for all global modules in `erc-modules'. -With DEFER-LOCALS, return minor-mode commands for all local -modules, possibly for deferred invocation, as done by `erc-open' -whenever a new ERC buffer is created. Local modules were -introduced in ERC 5.5." +(defun erc-update-modules () + "Enable minor mode for every module in `erc-modules'. +Except ignore all local modules, which were introduced in ERC 5.5." + (erc--update-modules) + nil) + +(defun erc--update-modules () (let (local-modes) - (dolist (module erc-modules (and defer-locals local-modes)) + (dolist (module erc-modules local-modes) (require (or (alist-get module erc--modules-to-features) (intern (concat "erc-" (symbol-name module)))) nil 'noerror) ; some modules don't have a corresponding feature (let ((mode (intern-soft (concat "erc-" (symbol-name module) "-mode")))) (unless (and mode (fboundp mode)) (error "`%s' is not a known ERC module" module)) - (if (and defer-locals (not (custom-variable-p mode))) - (push mode local-modes) - (funcall mode 1)))))) + (if (custom-variable-p mode) + (funcall mode 1) + (push mode local-modes)))))) (defun erc-setup-buffer (buffer) "Consults `erc-join-buffer' to find out how to display `BUFFER'." @@ -1917,6 +1918,17 @@ erc-setup-buffer (display-buffer buffer) (switch-to-buffer buffer))))) +(defun erc--local-module-modes (old-vars new) + ;; Emacs 27 doesnt' have `local-minor-modes' + (if-let* ((old-vars) + (fn (pcase-lambda (`(,k . ,v)) + (and (string-prefix-p "erc-" (symbol-name k)) + (string-suffix-p "-mode" (symbol-name k)) + v + k)))) + (delete-dups (append (delq nil (mapcar fn old-vars)) new nil)) + new)) + (defun erc-open (&optional server port nick full-name connect passwd tgt-list channel process client-certificate user id) @@ -1950,20 +1962,16 @@ erc-open (continued-session (and erc--server-reconnecting (with-suppressed-warnings ((obsolete erc-reuse-buffers)) - erc-reuse-buffers) - (buffer-local-variables)))) + erc-reuse-buffers)))) (when connect (run-hook-with-args 'erc-before-connect server port nick)) (set-buffer buffer) (setq old-point (point)) - (setq delayed-modules - (delete-dups (append (when continued-session - (erc-compat--local-module-modes)) - (erc-update-modules 'defer-locals)))) + (setq delayed-modules (erc--local-module-modes erc--server-reconnecting + (erc--update-modules))) (delay-mode-hooks (erc-mode)) - (setq erc-server-reconnect-count old-recon-count - erc--server-reconnecting continued-session) + (setq erc-server-reconnect-count old-recon-count) (when (setq erc-server-connected (not connect)) (setq erc-server-announced-name @@ -3859,10 +3867,8 @@ erc--cmd-reconnect (with-suppressed-warnings ((obsolete erc-server-reconnecting) (obsolete erc-reuse-buffers)) (if erc-reuse-buffers - (progn (cl-assert (not erc--server-reconnecting)) - (cl-assert (not erc-server-reconnecting))) - (setq erc--server-reconnecting nil - erc-server-reconnecting nil))))) + (cl-assert (not erc-server-reconnecting)) + (setq erc-server-reconnecting nil))))) t) (defun erc-cmd-RECONNECT (&rest args) diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el index 3617548f3b..4e646a775b 100644 --- a/test/lisp/erc/erc-tests.el +++ b/test/lisp/erc/erc-tests.el @@ -1206,7 +1206,7 @@ erc-migrate-modules ;; Default unchanged (should (equal (erc-migrate-modules erc-modules) erc-modules))) -(ert-deftest erc-update-modules () +(ert-deftest erc--update-modules () (let (calls erc-modules erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook) @@ -1233,7 +1233,7 @@ erc-update-modules (ert-info ("Local modules") (setq erc-modules '(fake-foo fake-bar)) - (should (equal (erc-update-modules t) '(erc-fake-bar-mode))) + (should (equal (erc--update-modules) '(erc-fake-bar-mode))) ;; Bar the feature is still required but the mode is not activated (should (equal (nreverse calls) '(erc-fake-foo (fake-foo . 1) erc-fake-bar))) @@ -1241,21 +1241,28 @@ erc-update-modules (ert-info ("Module name overrides") (setq erc-modules '(completion autojoin networks)) - (should-not (erc-update-modules t)) ; no locals + (should-not (erc--update-modules)) ; no locals (should (equal (nreverse calls) '( erc-pcomplete (completion . 1) erc-join (autojoin . 1) erc-networks (networks . 1)))) (setq calls nil))))) -(ert-deftest erc-compat--local-module-modes () - (with-temp-buffer - (if (< 27 emacs-major-version) - (let ((local-minor-modes '(font-lock-mode erc-fake-bar-mode))) - (should (equal (erc-compat--local-module-modes) - '(erc-fake-bar-mode)))) - (cl-letf (((symbol-function 'buffer-local-variables) - (lambda (&rest _) '((font-lock-mode) (erc-fake-bar-mode))))) - (should (equal (erc-compat--local-module-modes) - '(erc-fake-bar-mode))))))) +(ert-deftest erc--local-module-modes () + + (should (equal (erc--local-module-modes nil '(erc-a-mode erc-b-mode)) + '(erc-a-mode erc-b-mode))) + + (should (equal (erc--local-module-modes + '((a) (b . t)) '(erc-c-mode erc-d-mode)) + '(erc-c-mode erc-d-mode))) + + (should (equal (erc--local-module-modes + '((a) (erc-b-mode) (c . t) (erc-d-mode . t) (erc-e-mode . t)) + '(erc-b-mode erc-d-mode)) + '(erc-d-mode erc-e-mode erc-b-mode))) + + (should (equal (erc--local-module-modes + '((a) (b . t) (erc-e-mode . t)) nil) + '(erc-e-mode)))) ;;; erc-tests.el ends here -- 2.38.1