diff options
| -rw-r--r-- | lisp/gnus/ChangeLog | 18 | ||||
| -rw-r--r-- | lisp/gnus/sieve-manage.el | 248 |
2 files changed, 103 insertions, 163 deletions
diff --git a/lisp/gnus/ChangeLog b/lisp/gnus/ChangeLog index 9809f5a7432..744e1871b65 100644 --- a/lisp/gnus/ChangeLog +++ b/lisp/gnus/ChangeLog | |||
| @@ -1,3 +1,21 @@ | |||
| 1 | 2013-06-10 Albert Krewinkel <krewinkel@moltkeplatz.de> | ||
| 2 | |||
| 3 | * sieve-manage.el (sieve-manage-open): work with STARTTLS: shorten | ||
| 4 | stream managing functions by using open-protocol-stream to do most of | ||
| 5 | the work. Has the nice benefit of enabling STARTTLS. | ||
| 6 | Wait for capabilities after STARTTLS: following RFC5804, the server | ||
| 7 | sends new capabilities after successfully establishing a TLS connection | ||
| 8 | with the client. The client should update the cached list of | ||
| 9 | capabilities, but we just ignore the answer for now. | ||
| 10 | (sieve-manage-network-p, sieve-manage-network-open) | ||
| 11 | (sieve-manage-starttls-p, sieve-manage-starttls-open) | ||
| 12 | (sieve-manage-forward, sieve-manage-streams) | ||
| 13 | (sieve-manage-stream-alist): Remove unneeded functions neither in the | ||
| 14 | API, nor called by any other function. | ||
| 15 | Enable Multibyte for SieveManage buffers: The parser won't properly | ||
| 16 | handle umlauts and line endings unless multibyte is turned on in the | ||
| 17 | process buffer. | ||
| 18 | |||
| 1 | 2013-06-11 Lars Magne Ingebrigtsen <larsi@gnus.org> | 19 | 2013-06-11 Lars Magne Ingebrigtsen <larsi@gnus.org> |
| 2 | 20 | ||
| 3 | * eww.el (eww-tag-input): Support password fields. | 21 | * eww.el (eww-tag-input): Support password fields. |
diff --git a/lisp/gnus/sieve-manage.el b/lisp/gnus/sieve-manage.el index b96261764e5..23ab24152d9 100644 --- a/lisp/gnus/sieve-manage.el +++ b/lisp/gnus/sieve-manage.el | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | ;; Copyright (C) 2001-2013 Free Software Foundation, Inc. | 3 | ;; Copyright (C) 2001-2013 Free Software Foundation, Inc. |
| 4 | 4 | ||
| 5 | ;; Author: Simon Josefsson <simon@josefsson.org> | 5 | ;; Author: Simon Josefsson <simon@josefsson.org> |
| 6 | ;; Albert Krewinkel <tarleb@moltkeplatz.de> | ||
| 6 | 7 | ||
| 7 | ;; This file is part of GNU Emacs. | 8 | ;; This file is part of GNU Emacs. |
| 8 | 9 | ||
| @@ -66,6 +67,7 @@ | |||
| 66 | ;; 2001-10-31 Committed to Oort Gnus. | 67 | ;; 2001-10-31 Committed to Oort Gnus. |
| 67 | ;; 2002-07-27 Added DELETESCRIPT. Suggested by Ned Ludd. | 68 | ;; 2002-07-27 Added DELETESCRIPT. Suggested by Ned Ludd. |
| 68 | ;; 2002-08-03 Use SASL library. | 69 | ;; 2002-08-03 Use SASL library. |
| 70 | ;; 2013-06-05 Enabled STARTTLS support, fixed bit rot. | ||
| 69 | 71 | ||
| 70 | ;;; Code: | 72 | ;;; Code: |
| 71 | 73 | ||
| @@ -82,7 +84,6 @@ | |||
| 82 | (require 'sasl) | 84 | (require 'sasl) |
| 83 | (require 'starttls)) | 85 | (require 'starttls)) |
| 84 | (autoload 'sasl-find-mechanism "sasl") | 86 | (autoload 'sasl-find-mechanism "sasl") |
| 85 | (autoload 'starttls-open-stream "starttls") | ||
| 86 | (autoload 'auth-source-search "auth-source") | 87 | (autoload 'auth-source-search "auth-source") |
| 87 | 88 | ||
| 88 | ;; User customizable variables: | 89 | ;; User customizable variables: |
| @@ -107,23 +108,6 @@ | |||
| 107 | :type 'string | 108 | :type 'string |
| 108 | :group 'sieve-manage) | 109 | :group 'sieve-manage) |
| 109 | 110 | ||
| 110 | (defcustom sieve-manage-streams '(network starttls shell) | ||
| 111 | "Priority of streams to consider when opening connection to server." | ||
| 112 | :group 'sieve-manage) | ||
| 113 | |||
| 114 | (defcustom sieve-manage-stream-alist | ||
| 115 | '((network sieve-manage-network-p sieve-manage-network-open) | ||
| 116 | (shell sieve-manage-shell-p sieve-manage-shell-open) | ||
| 117 | (starttls sieve-manage-starttls-p sieve-manage-starttls-open)) | ||
| 118 | "Definition of network streams. | ||
| 119 | |||
| 120 | \(NAME CHECK OPEN) | ||
| 121 | |||
| 122 | NAME names the stream, CHECK is a function returning non-nil if the | ||
| 123 | server support the stream and OPEN is a function for opening the | ||
| 124 | stream." | ||
| 125 | :group 'sieve-manage) | ||
| 126 | |||
| 127 | (defcustom sieve-manage-authenticators '(digest-md5 | 111 | (defcustom sieve-manage-authenticators '(digest-md5 |
| 128 | cram-md5 | 112 | cram-md5 |
| 129 | scram-md5 | 113 | scram-md5 |
| @@ -156,8 +140,7 @@ for doing the actual authentication." | |||
| 156 | :group 'sieve-manage) | 140 | :group 'sieve-manage) |
| 157 | 141 | ||
| 158 | (defcustom sieve-manage-default-stream 'network | 142 | (defcustom sieve-manage-default-stream 'network |
| 159 | "Default stream type to use for `sieve-manage'. | 143 | "Default stream type to use for `sieve-manage'." |
| 160 | Must be a name of a stream in `sieve-manage-stream-alist'." | ||
| 161 | :version "24.1" | 144 | :version "24.1" |
| 162 | :type 'symbol | 145 | :type 'symbol |
| 163 | :group 'sieve-manage) | 146 | :group 'sieve-manage) |
| @@ -185,17 +168,21 @@ Valid states are `closed', `initial', `nonauth', and `auth'.") | |||
| 185 | (defvar sieve-manage-capability nil) | 168 | (defvar sieve-manage-capability nil) |
| 186 | 169 | ||
| 187 | ;; Internal utility functions | 170 | ;; Internal utility functions |
| 188 | 171 | (defun sieve-manage-make-process-buffer () | |
| 189 | (defmacro sieve-manage-disable-multibyte () | 172 | (with-current-buffer |
| 190 | "Enable multibyte in the current buffer." | 173 | (generate-new-buffer (format " *sieve %s:%s*" |
| 191 | (unless (featurep 'xemacs) | 174 | sieve-manage-server |
| 192 | '(set-buffer-multibyte nil))) | 175 | sieve-manage-port)) |
| 176 | (mapc 'make-local-variable sieve-manage-local-variables) | ||
| 177 | (mm-enable-multibyte) | ||
| 178 | (buffer-disable-undo) | ||
| 179 | (current-buffer))) | ||
| 193 | 180 | ||
| 194 | (defun sieve-manage-erase (&optional p buffer) | 181 | (defun sieve-manage-erase (&optional p buffer) |
| 195 | (let ((buffer (or buffer (current-buffer)))) | 182 | (let ((buffer (or buffer (current-buffer)))) |
| 196 | (and sieve-manage-log | 183 | (and sieve-manage-log |
| 197 | (with-current-buffer (get-buffer-create sieve-manage-log) | 184 | (with-current-buffer (get-buffer-create sieve-manage-log) |
| 198 | (sieve-manage-disable-multibyte) | 185 | (mm-enable-multibyte) |
| 199 | (buffer-disable-undo) | 186 | (buffer-disable-undo) |
| 200 | (goto-char (point-max)) | 187 | (goto-char (point-max)) |
| 201 | (insert-buffer-substring buffer (with-current-buffer buffer | 188 | (insert-buffer-substring buffer (with-current-buffer buffer |
| @@ -204,71 +191,32 @@ Valid states are `closed', `initial', `nonauth', and `auth'.") | |||
| 204 | (point-max))))))) | 191 | (point-max))))))) |
| 205 | (delete-region (point-min) (or p (point-max)))) | 192 | (delete-region (point-min) (or p (point-max)))) |
| 206 | 193 | ||
| 207 | (defun sieve-manage-open-1 (buffer) | 194 | (defun sieve-manage-open-server (server port &optional stream buffer) |
| 195 | "Open network connection to SERVER on PORT. | ||
| 196 | Return the buffer associated with the connection." | ||
| 208 | (with-current-buffer buffer | 197 | (with-current-buffer buffer |
| 209 | (sieve-manage-erase) | 198 | (sieve-manage-erase) |
| 210 | (setq sieve-manage-state 'initial | 199 | (setq sieve-manage-state 'initial) |
| 211 | sieve-manage-process | 200 | (destructuring-bind (proc . props) |
| 212 | (condition-case () | 201 | (open-protocol-stream |
| 213 | (funcall (nth 2 (assq sieve-manage-stream | 202 | "SIEVE" buffer server port |
| 214 | sieve-manage-stream-alist)) | 203 | :type stream |
| 215 | "sieve" buffer sieve-manage-server sieve-manage-port) | 204 | :capability-command "CAPABILITY\r\n" |
| 216 | ((error quit) nil))) | 205 | :end-of-command "^\\(OK\\|NO\\).*\n" |
| 217 | (when sieve-manage-process | 206 | :success "^OK.*\n" |
| 218 | (while (and (eq sieve-manage-state 'initial) | 207 | :return-list t |
| 219 | (memq (process-status sieve-manage-process) '(open run))) | 208 | :starttls-function |
| 220 | (message "Waiting for response from %s..." sieve-manage-server) | 209 | '(lambda (capabilities) |
| 221 | (accept-process-output sieve-manage-process 1)) | 210 | (when (string-match "\\bSTARTTLS\\b" capabilities) |
| 222 | (message "Waiting for response from %s...done" sieve-manage-server) | 211 | "STARTTLS\r\n"))) |
| 223 | (and (memq (process-status sieve-manage-process) '(open run)) | 212 | (setq sieve-manage-process proc) |
| 224 | sieve-manage-process)))) | 213 | (setq sieve-manage-capability |
| 225 | 214 | (sieve-manage-parse-capability (getf props :capabilities))) | |
| 226 | ;; Streams | 215 | ;; Ignore new capabilities issues after successful STARTTLS |
| 227 | 216 | (when (and (memq stream '(nil network starttls)) | |
| 228 | (defun sieve-manage-network-p (buffer) | 217 | (eq (getf props :type) 'tls)) |
| 229 | t) | 218 | (sieve-manage-drop-next-answer)) |
| 230 | 219 | (current-buffer)))) | |
| 231 | (defun sieve-manage-network-open (name buffer server port) | ||
| 232 | (let* ((port (or port sieve-manage-default-port)) | ||
| 233 | (coding-system-for-read sieve-manage-coding-system-for-read) | ||
| 234 | (coding-system-for-write sieve-manage-coding-system-for-write) | ||
| 235 | (process (open-network-stream name buffer server port))) | ||
| 236 | (when process | ||
| 237 | (while (and (memq (process-status process) '(open run)) | ||
| 238 | (set-buffer buffer) ;; XXX "blue moon" nntp.el bug | ||
| 239 | (goto-char (point-min)) | ||
| 240 | (not (sieve-manage-parse-greeting-1))) | ||
| 241 | (accept-process-output process 1) | ||
| 242 | (sit-for 1)) | ||
| 243 | (sieve-manage-erase nil buffer) | ||
| 244 | (when (memq (process-status process) '(open run)) | ||
| 245 | process)))) | ||
| 246 | |||
| 247 | (defun sieve-manage-starttls-p (buffer) | ||
| 248 | (condition-case () | ||
| 249 | (progn | ||
| 250 | (require 'starttls) | ||
| 251 | (call-process "starttls")) | ||
| 252 | (error nil))) | ||
| 253 | |||
| 254 | (defun sieve-manage-starttls-open (name buffer server port) | ||
| 255 | (let* ((port (or port sieve-manage-default-port)) | ||
| 256 | (coding-system-for-read sieve-manage-coding-system-for-read) | ||
| 257 | (coding-system-for-write sieve-manage-coding-system-for-write) | ||
| 258 | (process (starttls-open-stream name buffer server port)) | ||
| 259 | done) | ||
| 260 | (when process | ||
| 261 | (while (and (memq (process-status process) '(open run)) | ||
| 262 | (set-buffer buffer) ;; XXX "blue moon" nntp.el bug | ||
| 263 | (goto-char (point-min)) | ||
| 264 | (not (sieve-manage-parse-greeting-1))) | ||
| 265 | (accept-process-output process 1) | ||
| 266 | (sit-for 1)) | ||
| 267 | (sieve-manage-erase nil buffer) | ||
| 268 | (sieve-manage-send "STARTTLS") | ||
| 269 | (starttls-negotiate process)) | ||
| 270 | (when (memq (process-status process) '(open run)) | ||
| 271 | process))) | ||
| 272 | 220 | ||
| 273 | ;; Authenticators | 221 | ;; Authenticators |
| 274 | (defun sieve-sasl-auth (buffer mech) | 222 | (defun sieve-sasl-auth (buffer mech) |
| @@ -396,63 +344,33 @@ Optional argument AUTH indicates authenticator to use, see | |||
| 396 | If nil, chooses the best stream the server is capable of. | 344 | If nil, chooses the best stream the server is capable of. |
| 397 | Optional argument BUFFER is buffer (buffer, or string naming buffer) | 345 | Optional argument BUFFER is buffer (buffer, or string naming buffer) |
| 398 | to work in." | 346 | to work in." |
| 399 | (or port (setq port sieve-manage-default-port)) | 347 | (setq sieve-manage-port (or port sieve-manage-default-port)) |
| 400 | (setq buffer (or buffer (format " *sieve* %s:%s" server port))) | 348 | (with-current-buffer (or buffer (sieve-manage-make-process-buffer)) |
| 401 | (with-current-buffer (get-buffer-create buffer) | 349 | (setq sieve-manage-server (or server |
| 402 | (mapc 'make-local-variable sieve-manage-local-variables) | 350 | sieve-manage-server) |
| 403 | (sieve-manage-disable-multibyte) | 351 | sieve-manage-stream (or stream |
| 404 | (buffer-disable-undo) | 352 | sieve-manage-stream |
| 405 | (setq sieve-manage-server (or server sieve-manage-server)) | 353 | sieve-manage-default-stream) |
| 406 | (setq sieve-manage-port port) | 354 | sieve-manage-auth (or auth |
| 407 | (setq sieve-manage-stream (or stream sieve-manage-stream)) | 355 | sieve-manage-auth)) |
| 408 | (message "sieve: Connecting to %s..." sieve-manage-server) | 356 | (message "sieve: Connecting to %s..." sieve-manage-server) |
| 409 | (if (let ((sieve-manage-stream | 357 | (sieve-manage-open-server sieve-manage-server |
| 410 | (or sieve-manage-stream sieve-manage-default-stream))) | 358 | sieve-manage-port |
| 411 | (sieve-manage-open-1 buffer)) | 359 | sieve-manage-stream |
| 412 | ;; Choose stream. | 360 | (current-buffer)) |
| 413 | (let (stream-changed) | 361 | (when (sieve-manage-opened (current-buffer)) |
| 414 | (message "sieve: Connecting to %s...done" sieve-manage-server) | 362 | ;; Choose authenticator |
| 415 | (when (null sieve-manage-stream) | 363 | (when (and (null sieve-manage-auth) |
| 416 | (let ((streams sieve-manage-streams)) | 364 | (not (eq sieve-manage-state 'auth))) |
| 417 | (while (setq stream (pop streams)) | 365 | (dolist (auth sieve-manage-authenticators) |
| 418 | (if (funcall (nth 1 (assq stream | 366 | (when (funcall (nth 1 (assq auth sieve-manage-authenticator-alist)) |
| 419 | sieve-manage-stream-alist)) buffer) | 367 | buffer) |
| 420 | (setq stream-changed | 368 | (setq sieve-manage-auth auth) |
| 421 | (not (eq (or sieve-manage-stream | 369 | (return))) |
| 422 | sieve-manage-default-stream) | 370 | (unless sieve-manage-auth |
| 423 | stream)) | 371 | (error "Couldn't figure out authenticator for server"))) |
| 424 | sieve-manage-stream stream | ||
| 425 | streams nil))) | ||
| 426 | (unless sieve-manage-stream | ||
| 427 | (error "Couldn't figure out a stream for server")))) | ||
| 428 | (when stream-changed | ||
| 429 | (message "sieve: Reconnecting with stream `%s'..." | ||
| 430 | sieve-manage-stream) | ||
| 431 | (sieve-manage-close buffer) | ||
| 432 | (if (sieve-manage-open-1 buffer) | ||
| 433 | (message "sieve: Reconnecting with stream `%s'...done" | ||
| 434 | sieve-manage-stream) | ||
| 435 | (message "sieve: Reconnecting with stream `%s'...failed" | ||
| 436 | sieve-manage-stream)) | ||
| 437 | (setq sieve-manage-capability nil)) | ||
| 438 | (if (sieve-manage-opened buffer) | ||
| 439 | ;; Choose authenticator | ||
| 440 | (when (and (null sieve-manage-auth) | ||
| 441 | (not (eq sieve-manage-state 'auth))) | ||
| 442 | (let ((auths sieve-manage-authenticators)) | ||
| 443 | (while (setq auth (pop auths)) | ||
| 444 | (if (funcall (nth 1 (assq | ||
| 445 | auth | ||
| 446 | sieve-manage-authenticator-alist)) | ||
| 447 | buffer) | ||
| 448 | (setq sieve-manage-auth auth | ||
| 449 | auths nil))) | ||
| 450 | (unless sieve-manage-auth | ||
| 451 | (error "Couldn't figure out authenticator for server")))))) | ||
| 452 | (message "sieve: Connecting to %s...failed" sieve-manage-server)) | ||
| 453 | (when (sieve-manage-opened buffer) | ||
| 454 | (sieve-manage-erase) | 372 | (sieve-manage-erase) |
| 455 | buffer))) | 373 | (current-buffer)))) |
| 456 | 374 | ||
| 457 | (defun sieve-manage-authenticate (&optional buffer) | 375 | (defun sieve-manage-authenticate (&optional buffer) |
| 458 | "Authenticate on server in BUFFER. | 376 | "Authenticate on server in BUFFER. |
| @@ -544,12 +462,22 @@ If NAME is nil, return the full server list of capabilities." | |||
| 544 | 462 | ||
| 545 | ;; Protocol parsing routines | 463 | ;; Protocol parsing routines |
| 546 | 464 | ||
| 465 | (defun sieve-manage-wait-for-answer () | ||
| 466 | (let ((pattern "^\\(OK\\|NO\\).*\n") | ||
| 467 | pos) | ||
| 468 | (while (not pos) | ||
| 469 | (setq pos (search-forward-regexp pattern nil t)) | ||
| 470 | (goto-char (point-min)) | ||
| 471 | (sleep-for 0 50)) | ||
| 472 | pos)) | ||
| 473 | |||
| 474 | (defun sieve-manage-drop-next-answer () | ||
| 475 | (sieve-manage-wait-for-answer) | ||
| 476 | (sieve-manage-erase)) | ||
| 477 | |||
| 547 | (defun sieve-manage-ok-p (rsp) | 478 | (defun sieve-manage-ok-p (rsp) |
| 548 | (string= (downcase (or (car-safe rsp) "")) "ok")) | 479 | (string= (downcase (or (car-safe rsp) "")) "ok")) |
| 549 | 480 | ||
| 550 | (defsubst sieve-manage-forward () | ||
| 551 | (or (eobp) (forward-char))) | ||
| 552 | |||
| 553 | (defun sieve-manage-is-okno () | 481 | (defun sieve-manage-is-okno () |
| 554 | (when (looking-at (concat | 482 | (when (looking-at (concat |
| 555 | "^\\(OK\\|NO\\)\\( (\\([^)]+\\))\\)?\\( \\(.*\\)\\)?" | 483 | "^\\(OK\\|NO\\)\\( (\\([^)]+\\))\\)?\\( \\(.*\\)\\)?" |
| @@ -571,21 +499,15 @@ If NAME is nil, return the full server list of capabilities." | |||
| 571 | (sieve-manage-erase) | 499 | (sieve-manage-erase) |
| 572 | rsp)) | 500 | rsp)) |
| 573 | 501 | ||
| 574 | (defun sieve-manage-parse-capability-1 () | 502 | (defun sieve-manage-parse-capability (str) |
| 575 | "Accept a managesieve greeting." | 503 | "Parse managesieve capability string `STR'. |
| 576 | (let (str) | 504 | Set variable `sieve-manage-capability' to " |
| 577 | (while (setq str (sieve-manage-is-string)) | 505 | (let ((capas (remove-if #'null |
| 578 | (if (eq (char-after) ? ) | 506 | (mapcar #'split-string-and-unquote |
| 579 | (progn | 507 | (split-string str "\n"))))) |
| 580 | (sieve-manage-forward) | 508 | (when (string= "OK" (caar (last capas))) |
| 581 | (push (list str (sieve-manage-is-string)) | 509 | (setq sieve-manage-state 'nonauth)) |
| 582 | sieve-manage-capability)) | 510 | capas)) |
| 583 | (push (list str) sieve-manage-capability)) | ||
| 584 | (forward-line))) | ||
| 585 | (when (re-search-forward (concat "^OK.*" sieve-manage-server-eol) nil t) | ||
| 586 | (setq sieve-manage-state 'nonauth))) | ||
| 587 | |||
| 588 | (defalias 'sieve-manage-parse-greeting-1 'sieve-manage-parse-capability-1) | ||
| 589 | 511 | ||
| 590 | (defun sieve-manage-is-string () | 512 | (defun sieve-manage-is-string () |
| 591 | (cond ((looking-at "\"\\([^\"]+\\)\"") | 513 | (cond ((looking-at "\"\\([^\"]+\\)\"") |
| @@ -639,7 +561,7 @@ If NAME is nil, return the full server list of capabilities." | |||
| 639 | (setq cmdstr (concat cmdstr sieve-manage-client-eol)) | 561 | (setq cmdstr (concat cmdstr sieve-manage-client-eol)) |
| 640 | (and sieve-manage-log | 562 | (and sieve-manage-log |
| 641 | (with-current-buffer (get-buffer-create sieve-manage-log) | 563 | (with-current-buffer (get-buffer-create sieve-manage-log) |
| 642 | (sieve-manage-disable-multibyte) | 564 | (mm-enable-multibyte) |
| 643 | (buffer-disable-undo) | 565 | (buffer-disable-undo) |
| 644 | (goto-char (point-max)) | 566 | (goto-char (point-max)) |
| 645 | (insert cmdstr))) | 567 | (insert cmdstr))) |