Mercurial > hg > xemacs-beta
comparison lisp/gnus/nntp.el @ 30:ec9a17fef872 r19-15b98
Import from CVS: tag r19-15b98
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:52:29 +0200 |
parents | 441bb1e64a06 |
children | e04119814345 |
comparison
equal
deleted
inserted
replaced
29:7976500f47f9 | 30:ec9a17fef872 |
---|---|
41 | 41 |
42 (defvoo nntp-port-number "nntp" | 42 (defvoo nntp-port-number "nntp" |
43 "Port number on the physical nntp server.") | 43 "Port number on the physical nntp server.") |
44 | 44 |
45 (defvoo nntp-server-opened-hook '(nntp-send-mode-reader) | 45 (defvoo nntp-server-opened-hook '(nntp-send-mode-reader) |
46 "*Hook used for sending commands to the server at startup. | 46 "*Hook used for sending commands to the server at startup. |
47 The default value is `nntp-send-mode-reader', which makes an innd | 47 The default value is `nntp-send-mode-reader', which makes an innd |
48 server spawn an nnrpd server. Another useful function to put in this | 48 server spawn an nnrpd server. Another useful function to put in this |
49 hook might be `nntp-send-authinfo', which will prompt for a password | 49 hook might be `nntp-send-authinfo', which will prompt for a password |
50 to allow posting from the server. Note that this is only necessary to | 50 to allow posting from the server. Note that this is only necessary to |
51 do on servers that use strict access control.") | 51 do on servers that use strict access control.") |
52 | 52 |
53 (defvoo nntp-authinfo-function 'nntp-send-authinfo | 53 (defvoo nntp-authinfo-function 'nntp-send-authinfo |
54 "Function used to send AUTHINFO to the server.") | 54 "Function used to send AUTHINFO to the server.") |
55 | 55 |
56 (defvoo nntp-server-action-alist | 56 (defvoo nntp-server-action-alist |
57 '(("nntpd 1\\.5\\.11t" | 57 '(("nntpd 1\\.5\\.11t" |
58 (remove-hook 'nntp-server-opened-hook 'nntp-send-mode-reader)) | 58 (remove-hook 'nntp-server-opened-hook 'nntp-send-mode-reader)) |
59 ("NNRP server Netscape" | 59 ("NNRP server Netscape" |
60 (setq nntp-server-list-active-group nil))) | 60 (setq nntp-server-list-active-group nil))) |
61 "Alist of regexps to match on server types and actions to be taken. | 61 "Alist of regexps to match on server types and actions to be taken. |
62 For instance, if you want Gnus to beep every time you connect | 62 For instance, if you want Gnus to beep every time you connect |
63 to innd, you could say something like: | 63 to innd, you could say something like: |
64 | 64 |
186 (not nntp-nov-is-evil) | 186 (not nntp-nov-is-evil) |
187 (nntp-retrieve-headers-with-xover articles fetch-old)) | 187 (nntp-retrieve-headers-with-xover articles fetch-old)) |
188 ;; We successfully retrieved the headers via XOVER. | 188 ;; We successfully retrieved the headers via XOVER. |
189 'nov | 189 'nov |
190 ;; XOVER didn't work, so we do it the hard, slow and inefficient | 190 ;; XOVER didn't work, so we do it the hard, slow and inefficient |
191 ;; way. | 191 ;; way. |
192 (let ((number (length articles)) | 192 (let ((number (length articles)) |
193 (count 0) | 193 (count 0) |
194 (received 0) | 194 (received 0) |
195 (last-point (point-min)) | 195 (last-point (point-min)) |
196 (buf (nntp-find-connection-buffer nntp-server-buffer)) | 196 (buf (nntp-find-connection-buffer nntp-server-buffer)) |
197 (nntp-inhibit-erase t)) | 197 (nntp-inhibit-erase t)) |
198 ;; Send HEAD command. | 198 ;; Send HEAD command. |
199 (while articles | 199 (while articles |
200 (nntp-send-command | 200 (nntp-send-command |
201 nil | 201 nil |
202 "HEAD" (if (numberp (car articles)) | 202 "HEAD" (if (numberp (car articles)) |
203 (int-to-string (car articles)) | 203 (int-to-string (car articles)) |
204 ;; `articles' is either a list of article numbers | 204 ;; `articles' is either a list of article numbers |
205 ;; or a list of article IDs. | 205 ;; or a list of article IDs. |
252 "Retrieve group info on GROUPS." | 252 "Retrieve group info on GROUPS." |
253 (nntp-possibly-change-group nil server) | 253 (nntp-possibly-change-group nil server) |
254 (save-excursion | 254 (save-excursion |
255 (set-buffer (nntp-find-connection-buffer nntp-server-buffer)) | 255 (set-buffer (nntp-find-connection-buffer nntp-server-buffer)) |
256 ;; The first time this is run, this variable is `try'. So we | 256 ;; The first time this is run, this variable is `try'. So we |
257 ;; try. | 257 ;; try. |
258 (when (eq nntp-server-list-active-group 'try) | 258 (when (eq nntp-server-list-active-group 'try) |
259 (nntp-try-list-active (car groups))) | 259 (nntp-try-list-active (car groups))) |
260 (erase-buffer) | 260 (erase-buffer) |
261 (let ((count 0) | 261 (let ((count 0) |
262 (received 0) | 262 (received 0) |
324 article alist) | 324 article alist) |
325 (set-buffer buf) | 325 (set-buffer buf) |
326 (erase-buffer) | 326 (erase-buffer) |
327 ;; Send HEAD command. | 327 ;; Send HEAD command. |
328 (while (setq article (pop articles)) | 328 (while (setq article (pop articles)) |
329 (nntp-send-command | 329 (nntp-send-command |
330 nil | 330 nil |
331 "ARTICLE" (if (numberp article) | 331 "ARTICLE" (if (numberp article) |
332 (int-to-string article) | 332 (int-to-string article) |
333 ;; `articles' is either a list of article numbers | 333 ;; `articles' is either a list of article numbers |
334 ;; or a list of article IDs. | 334 ;; or a list of article IDs. |
377 (cons (car entry) point)) | 377 (cons (car entry) point)) |
378 map)))) | 378 map)))) |
379 | 379 |
380 (defun nntp-next-result-arrived-p () | 380 (defun nntp-next-result-arrived-p () |
381 (let ((point (point))) | 381 (let ((point (point))) |
382 (cond | 382 (cond |
383 ((looking-at "2") | 383 ((looking-at "2") |
384 (if (re-search-forward "\n.\r?\n" nil t) | 384 (if (re-search-forward "\n.\r?\n" nil t) |
385 t | 385 t |
386 (goto-char point) | 386 (goto-char point) |
387 nil)) | 387 nil)) |
499 (let* ((date (timezone-parse-date date)) | 499 (let* ((date (timezone-parse-date date)) |
500 (time-string | 500 (time-string |
501 (format "%s%02d%02d %s%s%s" | 501 (format "%s%02d%02d %s%s%s" |
502 (substring (aref date 0) 2) (string-to-int (aref date 1)) | 502 (substring (aref date 0) 2) (string-to-int (aref date 1)) |
503 (string-to-int (aref date 2)) (substring (aref date 3) 0 2) | 503 (string-to-int (aref date 2)) (substring (aref date 3) 0 2) |
504 (substring | 504 (substring |
505 (aref date 3) 3 5) (substring (aref date 3) 6 8)))) | 505 (aref date 3) 3 5) (substring (aref date 3) 6 8)))) |
506 (prog1 | 506 (prog1 |
507 (nntp-send-command "^\\.\r?\n" "NEWGROUPS" time-string) | 507 (nntp-send-command "^\\.\r?\n" "NEWGROUPS" time-string) |
508 (nntp-decode-text))))) | 508 (nntp-decode-text))))) |
509 | 509 |
512 (when (nntp-send-command "^[23].*\r?\n" "POST") | 512 (when (nntp-send-command "^[23].*\r?\n" "POST") |
513 (nntp-send-buffer "^[23].*\n"))) | 513 (nntp-send-buffer "^[23].*\n"))) |
514 | 514 |
515 (deffoo nntp-request-type (group article) | 515 (deffoo nntp-request-type (group article) |
516 'news) | 516 'news) |
517 | 517 |
518 (deffoo nntp-asynchronous-p () | 518 (deffoo nntp-asynchronous-p () |
519 t) | 519 t) |
520 | 520 |
521 ;;; Hooky functions. | 521 ;;; Hooky functions. |
522 | 522 |
529 | 529 |
530 (defun nntp-send-nosy-authinfo () | 530 (defun nntp-send-nosy-authinfo () |
531 "Send the AUTHINFO to the nntp server. | 531 "Send the AUTHINFO to the nntp server. |
532 This function is supposed to be called from `nntp-server-opened-hook'. | 532 This function is supposed to be called from `nntp-server-opened-hook'. |
533 It will prompt for a password." | 533 It will prompt for a password." |
534 (nntp-send-command | 534 (nntp-send-command |
535 "^.*\r?\n" "AUTHINFO USER" | 535 "^.*\r?\n" "AUTHINFO USER" |
536 (read-string (format "NNTP (%s) user name: " nntp-address))) | 536 (read-string (format "NNTP (%s) user name: " nntp-address))) |
537 (nntp-send-command | 537 (nntp-send-command |
538 "^.*\r?\n" "AUTHINFO PASS" | 538 "^.*\r?\n" "AUTHINFO PASS" |
539 (nnmail-read-passwd "NNTP (%s) password: " nntp-address))) | 539 (nnmail-read-passwd "NNTP (%s) password: " nntp-address))) |
540 | 540 |
541 (defun nntp-send-authinfo () | 541 (defun nntp-send-authinfo () |
542 "Send the AUTHINFO to the nntp server. | 542 "Send the AUTHINFO to the nntp server. |
543 This function is supposed to be called from `nntp-server-opened-hook'. | 543 This function is supposed to be called from `nntp-server-opened-hook'. |
544 It will prompt for a password." | 544 It will prompt for a password." |
545 (nntp-send-command "^.*\r?\n" "AUTHINFO USER" (user-login-name)) | 545 (nntp-send-command "^.*\r?\n" "AUTHINFO USER" (user-login-name)) |
546 (nntp-send-command | 546 (nntp-send-command |
547 "^.*\r?\n" "AUTHINFO PASS" | 547 "^.*\r?\n" "AUTHINFO PASS" |
548 (nnmail-read-passwd (format "NNTP (%s) password: " nntp-address)))) | 548 (nnmail-read-passwd (format "NNTP (%s) password: " nntp-address)))) |
549 | 549 |
550 (defun nntp-send-authinfo-from-file () | 550 (defun nntp-send-authinfo-from-file () |
551 "Send the AUTHINFO to the nntp server. | 551 "Send the AUTHINFO to the nntp server. |
552 This function is supposed to be called from `nntp-server-opened-hook'." | 552 This function is supposed to be called from `nntp-server-opened-hook'." |
553 (when (file-exists-p "~/.nntp-authinfo") | 553 (when (file-exists-p "~/.nntp-authinfo") |
554 (nnheader-temp-write nil | 554 (nnheader-temp-write nil |
555 (insert-file-contents "~/.nntp-authinfo") | 555 (insert-file-contents "~/.nntp-authinfo") |
556 (goto-char (point-min)) | 556 (goto-char (point-min)) |
557 (nntp-send-command "^.*\r?\n" "AUTHINFO USER" (user-login-name)) | 557 (nntp-send-command "^.*\r?\n" "AUTHINFO USER" (user-login-name)) |
558 (nntp-send-command | 558 (nntp-send-command |
559 "^.*\r?\n" "AUTHINFO PASS" | 559 "^.*\r?\n" "AUTHINFO PASS" |
560 (buffer-substring (point) (progn (end-of-line) (point))))))) | 560 (buffer-substring (point) (progn (end-of-line) (point))))))) |
561 | 561 |
562 ;;; Internal functions. | 562 ;;; Internal functions. |
563 | 563 |
564 (defun nntp-send-command (wait-for &rest strings) | 564 (defun nntp-send-command (wait-for &rest strings) |
634 (process-buffer process)))) | 634 (process-buffer process)))) |
635 | 635 |
636 (defun nntp-make-process-buffer (buffer) | 636 (defun nntp-make-process-buffer (buffer) |
637 "Create a new, fresh buffer usable for nntp process connections." | 637 "Create a new, fresh buffer usable for nntp process connections." |
638 (save-excursion | 638 (save-excursion |
639 (set-buffer | 639 (set-buffer |
640 (generate-new-buffer | 640 (generate-new-buffer |
641 (format " *server %s %s %s*" | 641 (format " *server %s %s %s*" |
642 nntp-address nntp-port-number | 642 nntp-address nntp-port-number |
643 (buffer-name (get-buffer buffer))))) | 643 (buffer-name (get-buffer buffer))))) |
644 (buffer-disable-undo (current-buffer)) | 644 (buffer-disable-undo (current-buffer)) |
742 (save-excursion | 742 (save-excursion |
743 (set-buffer (process-buffer process)) | 743 (set-buffer (process-buffer process)) |
744 (erase-buffer))) | 744 (erase-buffer))) |
745 (when command | 745 (when command |
746 (nntp-send-string process command)) | 746 (nntp-send-string process command)) |
747 (cond | 747 (cond |
748 ((eq callback 'ignore) | 748 ((eq callback 'ignore) |
749 t) | 749 t) |
750 ((and callback wait-for) | 750 ((and callback wait-for) |
751 (save-excursion | 751 (save-excursion |
752 (set-buffer (process-buffer process)) | 752 (set-buffer (process-buffer process)) |
753 (unless nntp-inside-change-function | 753 (unless nntp-inside-change-function |
754 (erase-buffer)) | 754 (erase-buffer)) |
755 (setq nntp-process-decode decode | 755 (setq nntp-process-decode decode |
756 nntp-process-to-buffer buffer | 756 nntp-process-to-buffer buffer |
757 nntp-process-wait-for wait-for | 757 nntp-process-wait-for wait-for |
758 nntp-process-callback callback | 758 nntp-process-callback callback |
759 nntp-process-start-point (point-max) | 759 nntp-process-start-point (point-max) |
760 after-change-functions | 760 after-change-functions |
761 (list 'nntp-after-change-function-callback))) | 761 (list 'nntp-after-change-function-callback))) |
762 t) | 762 t) |
763 (wait-for | 763 (wait-for |
764 (nntp-wait-for process wait-for buffer decode)) | 764 (nntp-wait-for process wait-for buffer decode)) |
765 (t t))))) | 765 (t t))))) |
766 | 766 |
767 (defun nntp-send-string (process string) | 767 (defun nntp-send-string (process string) |
768 "Send STRING to PROCESS." | 768 "Send STRING to PROCESS." |
786 (nntp-snarf-error-message) | 786 (nntp-snarf-error-message) |
787 nil) | 787 nil) |
788 (goto-char (point-max)) | 788 (goto-char (point-max)) |
789 (let ((limit (point-min))) | 789 (let ((limit (point-min))) |
790 (while (not (re-search-backward wait-for limit t)) | 790 (while (not (re-search-backward wait-for limit t)) |
791 ;; We assume that whatever we wait for is less than 1000 | 791 ;; We assume that whatever we wait for is less than 1000 |
792 ;; characters long. | 792 ;; characters long. |
793 (setq limit (max (- (point-max) 1000) (point-min))) | 793 (setq limit (max (- (point-max) 1000) (point-min))) |
794 (nntp-accept-process-output process) | 794 (nntp-accept-process-output process) |
795 (goto-char (point-max)))) | 795 (goto-char (point-max)))) |
796 (nntp-decode-text (not decode)) | 796 (nntp-decode-text (not decode)) |
818 (defun nntp-accept-process-output (process) | 818 (defun nntp-accept-process-output (process) |
819 "Wait for output from PROCESS and message some dots." | 819 "Wait for output from PROCESS and message some dots." |
820 (save-excursion | 820 (save-excursion |
821 (set-buffer (or (nntp-find-connection-buffer nntp-server-buffer) | 821 (set-buffer (or (nntp-find-connection-buffer nntp-server-buffer) |
822 nntp-server-buffer)) | 822 nntp-server-buffer)) |
823 (let ((len (/ (point-max) 1024))) | 823 (let ((len (/ (point-max) 1024)) |
824 message-log-max) | |
824 (unless (< len 10) | 825 (unless (< len 10) |
825 (setq nntp-have-messaged t) | 826 (setq nntp-have-messaged t) |
826 (nnheader-message 7 "nntp read: %dk" len))) | 827 (nnheader-message 7 "nntp read: %dk" len))) |
827 (accept-process-output process 1))) | 828 (accept-process-output process 1))) |
828 | 829 |
885 (insert "." nntp-end-of-line))) | 886 (insert "." nntp-end-of-line))) |
886 | 887 |
887 (defun nntp-retrieve-headers-with-xover (articles &optional fetch-old) | 888 (defun nntp-retrieve-headers-with-xover (articles &optional fetch-old) |
888 (set-buffer nntp-server-buffer) | 889 (set-buffer nntp-server-buffer) |
889 (erase-buffer) | 890 (erase-buffer) |
890 (cond | 891 (cond |
891 | 892 |
892 ;; This server does not talk NOV. | 893 ;; This server does not talk NOV. |
893 ((not nntp-server-xover) | 894 ((not nntp-server-xover) |
894 nil) | 895 nil) |
895 | 896 |
896 ;; We don't care about gaps. | 897 ;; We don't care about gaps. |
897 ((or (not nntp-nov-gap) | 898 ((or (not nntp-nov-gap) |
898 fetch-old) | 899 fetch-old) |
899 (nntp-send-xover-command | 900 (nntp-send-xover-command |
900 (if fetch-old | 901 (if fetch-old |
901 (if (numberp fetch-old) | 902 (if (numberp fetch-old) |
902 (max 1 (- (car articles) fetch-old)) | 903 (max 1 (- (car articles) fetch-old)) |
903 1) | 904 1) |
904 (car articles)) | 905 (car articles)) |
930 ;; that means that the server does not understand XOVER, but we | 931 ;; that means that the server does not understand XOVER, but we |
931 ;; won't know that until we try. | 932 ;; won't know that until we try. |
932 (while (and nntp-server-xover articles) | 933 (while (and nntp-server-xover articles) |
933 (setq first (car articles)) | 934 (setq first (car articles)) |
934 ;; Search forward until we find a gap, or until we run out of | 935 ;; Search forward until we find a gap, or until we run out of |
935 ;; articles. | 936 ;; articles. |
936 (while (and (cdr articles) | 937 (while (and (cdr articles) |
937 (< (- (nth 1 articles) (car articles)) nntp-nov-gap)) | 938 (< (- (nth 1 articles) (car articles)) nntp-nov-gap)) |
938 (setq articles (cdr articles))) | 939 (setq articles (cdr articles))) |
939 | 940 |
940 (when (nntp-send-xover-command first (car articles)) | 941 (when (nntp-send-xover-command first (car articles)) |
947 (zerop (% count nntp-maximum-request))) | 948 (zerop (% count nntp-maximum-request))) |
948 (accept-process-output) | 949 (accept-process-output) |
949 ;; On some Emacs versions the preceding function has | 950 ;; On some Emacs versions the preceding function has |
950 ;; a tendency to change the buffer. Perhaps. It's | 951 ;; a tendency to change the buffer. Perhaps. It's |
951 ;; quite difficult to reproduce, because it only | 952 ;; quite difficult to reproduce, because it only |
952 ;; seems to happen once in a blue moon. | 953 ;; seems to happen once in a blue moon. |
953 (set-buffer buf) | 954 (set-buffer buf) |
954 (while (progn | 955 (while (progn |
955 (goto-char last-point) | 956 (goto-char last-point) |
956 ;; Count replies. | 957 ;; Count replies. |
957 (while (re-search-forward "^[0-9][0-9][0-9] " nil t) | 958 (while (re-search-forward "^[0-9][0-9][0-9] " nil t) |
969 (while (progn | 970 (while (progn |
970 (goto-char (point-max)) | 971 (goto-char (point-max)) |
971 (forward-line -1) | 972 (forward-line -1) |
972 (not (looking-at "^\\.\r?\n"))) | 973 (not (looking-at "^\\.\r?\n"))) |
973 (nntp-accept-response))) | 974 (nntp-accept-response))) |
974 | 975 |
975 ;; We remove any "." lines and status lines. | 976 ;; We remove any "." lines and status lines. |
976 (goto-char (point-min)) | 977 (goto-char (point-min)) |
977 (while (search-forward "\r" nil t) | 978 (while (search-forward "\r" nil t) |
978 (delete-char -1)) | 979 (delete-char -1)) |
979 (goto-char (point-min)) | 980 (goto-char (point-min)) |
989 (nntp-inhibit-erase t)) | 990 (nntp-inhibit-erase t)) |
990 (if (stringp nntp-server-xover) | 991 (if (stringp nntp-server-xover) |
991 ;; If `nntp-server-xover' is a string, then we just send this | 992 ;; If `nntp-server-xover' is a string, then we just send this |
992 ;; command. | 993 ;; command. |
993 (if wait-for-reply | 994 (if wait-for-reply |
994 (nntp-send-command-nodelete | 995 (nntp-send-command-nodelete |
995 "\r?\n\\.\r?\n" nntp-server-xover range) | 996 "\r?\n\\.\r?\n" nntp-server-xover range) |
996 ;; We do not wait for the reply. | 997 ;; We do not wait for the reply. |
997 (nntp-send-command-nodelete "\r?\n\\.\r?\n" nntp-server-xover range)) | 998 (nntp-send-command-nodelete "\r?\n\\.\r?\n" nntp-server-xover range)) |
998 (let ((commands nntp-xover-commands)) | 999 (let ((commands nntp-xover-commands)) |
999 ;; `nntp-xover-commands' is a list of possible XOVER commands. | 1000 ;; `nntp-xover-commands' is a list of possible XOVER commands. |
1000 ;; We try them all until we get at positive response. | 1001 ;; We try them all until we get at positive response. |
1001 (while (and commands (eq nntp-server-xover 'try)) | 1002 (while (and commands (eq nntp-server-xover 'try)) |
1002 (nntp-send-command-nodelete "\r?\n\\.\r?\n" (car commands) range) | 1003 (nntp-send-command-nodelete "\r?\n\\.\r?\n" (car commands) range) |
1003 (save-excursion | 1004 (save-excursion |
1004 (set-buffer nntp-server-buffer) | 1005 (set-buffer nntp-server-buffer) |
1005 (goto-char (point-min)) | 1006 (goto-char (point-min)) |
1103 (match-end 1))))) | 1104 (match-end 1))))) |
1104 group newsgroups xref) | 1105 group newsgroups xref) |
1105 (and number (zerop number) (setq number nil)) | 1106 (and number (zerop number) (setq number nil)) |
1106 ;; Then we find the group name. | 1107 ;; Then we find the group name. |
1107 (setq group | 1108 (setq group |
1108 (cond | 1109 (cond |
1109 ;; If there is only one group in the Newsgroups header, | 1110 ;; If there is only one group in the Newsgroups header, |
1110 ;; then it seems quite likely that this article comes | 1111 ;; then it seems quite likely that this article comes |
1111 ;; from that group, I'd say. | 1112 ;; from that group, I'd say. |
1112 ((and (setq newsgroups (mail-fetch-field "newsgroups")) | 1113 ((and (setq newsgroups (mail-fetch-field "newsgroups")) |
1113 (not (string-match "," newsgroups))) | 1114 (not (string-match "," newsgroups))) |
1116 ;; header, then the Xref header should be filled out. | 1117 ;; header, then the Xref header should be filled out. |
1117 ;; We hazard a guess that the group that has this | 1118 ;; We hazard a guess that the group that has this |
1118 ;; article number in the Xref header is the one we are | 1119 ;; article number in the Xref header is the one we are |
1119 ;; looking for. This might very well be wrong if this | 1120 ;; looking for. This might very well be wrong if this |
1120 ;; article happens to have the same number in several | 1121 ;; article happens to have the same number in several |
1121 ;; groups, but that's life. | 1122 ;; groups, but that's life. |
1122 ((and (setq xref (mail-fetch-field "xref")) | 1123 ((and (setq xref (mail-fetch-field "xref")) |
1123 number | 1124 number |
1124 (string-match (format "\\([^ :]+\\):%d" number) xref)) | 1125 (string-match (format "\\([^ :]+\\):%d" number) xref)) |
1125 (substring xref (match-beginning 1) (match-end 1))) | 1126 (substring xref (match-beginning 1) (match-end 1))) |
1126 (t ""))) | 1127 (t ""))) |