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 "")))