Patches between 0.16 and 0.17
Lars Magne Ingebrigtsen <[email protected]> Mon, 31 Mar 2003 20:10:01 +0200
| Newsgroups | gmane.emacs.gnus.patches |
|---|---|
| Message-ID | <[email protected]> |
Index: gnus/ChangeLog diff -u gnus/ChangeLog:6.45 gnus/ChangeLog:6.48 --- gnus/ChangeLog:6.45 Wed Feb 19 20:22:40 2003 +++ gnus/ChangeLog Wed Mar 26 21:49:55 2003 @@ -1,3 +1,22 @@ +2003-03-23 Simon Josefsson <[email protected]> + + * GNUS-NEWS: Add IDNA. Add TLS. Fix USEFOR reference. + +2003-03-22 Frank Schmitt <[email protected]> + + * make.bat: Redone from scratch; supports both Emacs and XEmacs + now; correctly generate gnus-load.el; check for errors; use + makeinfo if available, infohack.el if it isn't; be less verbose + when copying files; copy files from etc/gnus and etc/smilies, too + +2003-03-22 Frank Schmitt <[email protected]> + + * make-x.bat: Removed, make.bat does its job now. + +2003-03-22 Frank Schmitt <[email protected]> + + * etc/gnus-tut.txt: Include Gnus FAQ from http://my.gnus.org. + 2003-02-19 Reiner Steib <[email protected]> * GNUS-NEWS: Renamed `gnus-unsightly-citation-regexp' to Index: gnus/GNUS-NEWS diff -u gnus/GNUS-NEWS:6.44 gnus/GNUS-NEWS:6.48 --- gnus/GNUS-NEWS:6.44 Wed Feb 19 20:22:40 2003 +++ gnus/GNUS-NEWS Sun Mar 23 16:33:03 2003 @@ -8,6 +8,38 @@ * Changes in Oort Gnus +** TLS wrapper shipped with Gnus + +TLS/SSL is now supported in IMAP and NNTP via tls.el and GNUTLS. The +old TLS/SSL support via (external third party) ssl.el and OpenSSL +still works. + +** New make.bat for compiling and installing Gnus under MS Windows + +Use make.bat if you want to install Gnus under MS Windows, the first +argument to the batch-program should be the directory where xemacs.exe +respectively emacs.exe is located, iff you want to install Gnus after +compiling it, give make.bat /copy as the second parameter. + +Make.bat has been rewritten from scratch, it now features automatic +recognition of XEmacs and GNU Emacs, generates gnus-load.el, checks if +errors occur while compilation and generation of info files and reports +them at the end of the build process. It now uses makeinfo if it is +available and falls back to infohack.el otherwise. Make.bat should now +install all files which are necessary to run Gnus and be generally a +complete replacement for the "configure; make; make install" cycle used +under Unix systems. + +The new make.bat makes make-x.bat superfluous, so it has been removed. + +** Support for non-ASCII domain names + +Message supports non-ASCII domain names in From:, To: and Cc: and will +query you whether to perform encoding when you try to send a message. +The variable `message-use-idna' controls this. Gnus will also decode +non-ASCII domain names in From:, To: and Cc: when you view a message. +The variable `gnus-use-idna' controls this. + ** Better handling of Microsoft citation styles Gnus now tries to recognize the mangled header block that some Microsoft @@ -268,7 +300,7 @@ ** Group names are treated as UTF-8 by default. -This is supposedly what USEFOR wants to migrate to. See +This is supposedly what USEFOR wanted to migrate to. See `gnus-group-name-charset-group-alist' and `gnus-group-name-charset-method-alist' for customization. Index: gnus/make-x.bat diff -u gnus/make-x.bat:6.7 gnus/make-x.bat:removed --- gnus/make-x.bat:6.7 Mon Jan 13 19:43:38 2003 +++ gnus/make-x.bat Mon Mar 31 20:09:58 2003 @@ -1,76 +0,0 @@ -@echo off - -rem Modified once more by Frank Schmitt ([email protected]) -rem Modified by ShengHuo Zhu ([email protected]) -rem Originally from make.bat by David Charlap ([email protected]) - -rem Clear PWD so emacs doesn't get confused -set GNUS_PWD_SAVE=%PWD% -set PWD= - -if "%1" == "" goto usage - -rem Directory where the info files are installed -set GNUS_INFO_DIR=%1\..\..\xemacs-packages\info - -set emacs=xemacs.exe -if "%2" == "" set copy="false" -if "%2" == "copy" set copy=true -if "%2" == "/copy" set copy=true - -set EMACSBATCH=call %1\%emacs% -batch -q -no-site-file - -cd lisp -%EMACSBATCH% -l ./dgnushack.el -f dgnushack-compile -if not %copy%==true goto info -attrib -r %1\..\..\xemacs-packages\lisp\gnus\*.* -copy *.el? %1\..\..\xemacs-packages\lisp\gnus - -:info -set EMACSINFO=%EMACSBATCH% -l infohack.el -f batch-makeinfo -cd ..\texi -%EMACSINFO% message.texi -%EMACSINFO% emacs-mime.texi -%EMACSINFO% gnus.texi -if not %copy%==true goto done -copy gnus %GNUS_INFO_DIR% -copy gnus-? %GNUS_INFO_DIR% -copy gnus-?? %GNUS_INFO_DIR% -copy message %GNUS_INFO_DIR% -copy message-? %GNUS_INFO_DIR% -copy emacs-mime %GNUS_INFO_DIR% -copy sieve %GNUS_INFO_DIR% -copy pgg %GNUS_INFO_DIR% -echo Maybe you should add the following line to %GNUS_INFO_DIR%\dir: -echo. -echo * PGG: (pgg). Emacs interface to various PGP implementations. -echo * Sieve: (sieve). Managing Sieve scripts in Emacs. -echo. - -:etc -cd ..\etc -copy gnus-tut.txt %1\..\..\xemacs-packages\etc - -:done -cd .. -goto end - -:usage -echo Usage: make-x.bat :xemacs-dir: [/copy] -echo. -echo where: :xemacs-dir: is the directory you installed xemacs in -echo (the directory where xemacs.exe is situated) -echo eg. C:\Programme\XEmacs\XEmacs-21.4.3\i586-pc-win32 -echo /copy indicates that the compiled files should be copied to your -echo emacs lisp, info, and etc directories -echo. -echo Note: If you have Emacs/w3 you should set the environment variable -echo W3DIR to the directory where w3 is installed eg. -echo set W3DIR=C:\Progra~1\XEmacs\xemacs-packages\lisp\w3 - -rem Restore PWD so whoever called this batch file doesn't get confused -set PWD=%GNUS_PWD_SAVE% -set GNUS_PWD_SAVE= -set EMACSBATCH= -set GNUS_INFO_DIR= -:end Index: gnus/make.bat diff -u gnus/make.bat:6.5 gnus/make.bat:6.6 --- gnus/make.bat:6.5 Mon Jan 13 19:43:38 2003 +++ gnus/make.bat Sat Mar 22 20:15:21 2003 @@ -1,92 +1,283 @@ @echo off -rem Written by David Charlap ([email protected]) -rem -rem There are two possible problems with this batch file. The emacs.bat batch -rem file may not exist in all distributions. It is part of the GNU build of -rem Emacs 20.4 (http://www.gnu.org/softare/emacs/windows.ntemacs.html) If you -rem install Gnus with some other build, you may have to replace calls to -rem %1\emacs.bat with something else. -rem -rem Also, the emacs.bat file that comes with Emacs does not accept more than 9 -rem parameters, so the attempts to compile the .texi files will fail. To -rem fix that (at least on NT. I don't know about Win95), the following -rem change should be made to emacs.bat: -rem -rem %emacs_dir%\bin\emacs.exe %1 %2 %3 %4 %5 %6 %7 %8 %9 -rem -rem should become -rem -rem %emacs_dir%\bin\emacs.exe %* -rem -rem which will allow the batch file to accept an unlimited number of -rem parameters. - +rem Written by Frank Schmitt <[email protected]> +rem based on the work by David Charlap ([email protected]) +rem . rem Clear PWD so emacs doesn't get confused set GNUS_PWD_SAVE=%PWD% set PWD= +set ERROR=: if "%1" == "" goto usage -rem Directory where the info files are installed -set GNUS_INFO_DIR=%1\info - rem Emacs 20.7 no longer includes emacs.bat. Use emacs.exe if the batch file is rem not present -- this also fixes the problem about too many parameters on Win9x. -set emacs=emacs.exe -if exist %1\bin\emacs.bat set emacs=emacs.bat -set EMACSBATCH=call %1\bin\%emacs% -no-site-file -batch -q +if exist %1\emacs.bat goto ebat +if exist %1\emacs.exe goto eexe +if exist %1\xemacs.exe goto xemacs +goto noemacs + +:ebat +set EMACS=emacs.bat +echo. +echo *************************************************************************** +echo * Using emacs.bat (If you've got en Emacs >= 20.3 please remove Emacs.bat, +echo * it isn't needed anymore. +echo *************************************************************************** +echo. +goto emacs + +:eexe +set EMACS=emacs.exe +echo. +echo *************************************************************************** +echo * Using emacs.exe +echo *************************************************************************** +echo. +goto emacs +:emacs +if not "%2" == "/copy" goto emacsnocopy +if not exist %1\..\site-lisp mkdir %1\..\site-lisp +if not exist %1\..\site-lisp\gnus mkdir %1\..\site-lisp\gnus +if not exist %1\..\site-lisp\subdirs.el set subdirwarning=yes +:emacsnocopy +set GNUS_INFO_DIR=%1\..\info +set GNUS_LISP_DIR=%1\..\site-lisp\gnus\lisp +set GNUS_ETC_DIR=%1\..\site-lisp\gnus\etc +goto lisp + +:xemacs +set EMACS=xemacs.exe +if not "%2" == "/copy" goto xemacsnocopy +if not exist %1\..\..\site-packages\ mkdir %1\..\..\site-packages\ +if not exist %1\..\..\site-packages\info mkdir %1\..\..\site-packages\info +if not exist %1\..\..\site-packages\lisp mkdir %1\..\..\site-packages\lisp +if not exist %1\..\..\site-packages\etc mkdir %1\..\..\site-packages\etc +:xemacsnocopy +set GNUS_INFO_DIR=%1\..\..\site-packages\info +set GNUS_LISP_DIR=%1\..\..\site-packages\lisp\gnus +set GNUS_ETC_DIR=%1\..\..\site-packages\etc +echo. +echo *************************************************************************** +echo * Using xemacs.exe +echo *************************************************************************** +echo. +goto lisp + +:lisp +set EMACSBATCH=call %1\%EMACS% -no-site-file -batch -q cd lisp +if exist gnus-load.el del gnus-load.el +echo. +echo Stand by while generating autoloads. +echo. +%EMACSBATCH% -l ./dgnushack.el -f dgnushack-make-cus-load . +if ErrorLevel 1 set ERROR=make-cus-load +%EMACSBATCH% -l ./dgnushack.el -f dgnushack-make-auto-load . +if ErrorLevel 1 set ERROR=%ERROR%,make-auto-load +%EMACSBATCH% -l ./dgnushack.el -f dgnushack-make-load +if ErrorLevel 1 set ERROR=%ERROR%,make-load +echo. +echo Stand by while compiling lisp files. +echo. %EMACSBATCH% -l ./dgnushack.el -f dgnushack-compile -if not "%2" == "/copy" goto info -attrib -r %1\lisp\gnus\* -copy *.el* %1\lisp\gnus +if ErrorLevel 1 set ERROR=%ERROR%,compile -:info -set EMACSINFO=%EMACSBATCH% -l infohack.el -f batch-makeinfo +if not "%2" == "/copy" goto infotest +echo. +echo Stand by while copying lisp files. +echo. +if not exist %GNUS_LISP_DIR% mkdir %GNUS_LISP_DIR% +xcopy /R /Q /Y *.el* %GNUS_LISP_DIR% +if ErrorLevel 1 set ERROR=%ERROR%,copy-lisp +goto infotest + +:infotest cd ..\texi -%EMACSINFO% message.texi +if exist sieve del sieve +makeinfo sieve.texi +if exist sieve goto minfo +REM It seems that makeinfo isn't available +set EMACSINFO=%EMACSBATCH% -l infohack.el -f batch-makeinfo +echo. +echo *************************************************************************** +echo * Using infohack.el, if you've got makeinfo.exe put it in PATH. +echo *************************************************************************** +echo. +goto info + +:minfo +set EMACSINFO=makeinfo +echo. +echo *************************************************************************** +echo * Using makeinfo +echo *************************************************************************** +echo. +goto info + +:info +echo. +echo Stand by while generating info files. +echo. %EMACSINFO% emacs-mime.texi +if ErrorLevel 1 set ERROR=%ERROR%,emacs-mime.texi %EMACSINFO% gnus.texi -if not "%2" == "/copy" goto done -copy gnus %GNUS_INFO_DIR% -copy gnus-? %GNUS_INFO_DIR% -copy gnus-?? %GNUS_INFO_DIR% -copy message %GNUS_INFO_DIR% -copy message-? %GNUS_INFO_DIR% -copy emacs-mime %GNUS_INFO_DIR% -copy sieve %GNUS_INFO_DIR% -copy pgg %GNUS_INFO_DIR% -echo Maybe you should add the following line to %GNUS_INFO_DIR%\dir: +if ErrorLevel 1 set ERROR=%ERROR%,gnus.texi +%EMACSINFO% sieve.texi +if ErrorLevel 1 set ERROR=%ERROR%,sieve.texi +%EMACSINFO% pgg.texi +if ErrorLevel 1 set ERROR=%ERROR%,pgg.texi +%EMACSINFO% message.texi +if ErrorLevel 1 set ERROR=%ERROR%,message.texi + +if not "%2" == "/copy" goto nocopy +if not exist %GNUS_INFO_DIR% mkdir %GNUS_INFO_DIR% + +echo. +echo Stand by while copying info files. +echo. +xcopy /R /Q /Y gnus %GNUS_INFO_DIR% +if ErrorLevel 1 set ERROR=%ERROR%,copy-gnus-info +xcopy /R /Q /Y gnus-? %GNUS_INFO_DIR% +if ErrorLevel 1 set ERROR=%ERROR%,copy-gnus-x-info +xcopy /R /Q /Y gnus-?? %GNUS_INFO_DIR% +if ErrorLevel 1 set ERROR=%ERROR%,copy-gnus-xx-info +xcopy /R /Q /Y message %GNUS_INFO_DIR% +if ErrorLevel 1 set ERROR=%ERROR%,copy-message-info +if exist message-1 xcopy /R /Q /Y message-? %GNUS_INFO_DIR% +if ErrorLevel 1 set ERROR=%ERROR%,copy-message-x-info +xcopy /R /Q /Y emacs-mime %GNUS_INFO_DIR% +if ErrorLevel 1 set ERROR=%ERROR%,copy-emacs-mime-info +xcopy /R /Q /Y sieve %GNUS_INFO_DIR% +if ErrorLevel 1 set ERROR=%ERROR%,copy-sieve-info +xcopy /R /Q /Y pgg %GNUS_INFO_DIR% +if ErrorLevel 1 set ERROR=%ERROR%,copy-pgg-info + echo. -echo * PGG: (pgg). Emacs interface to various PGP implementations. -echo * Sieve: (sieve). Managing Sieve scripts in Emacs. +echo *************************************************************************** +echo * You should add the following lines to +echo * %GNUS_INFO_DIR%\dir +echo * if they aren't already there: +echo * +echo * * PGG: (pgg). Emacs interface to various PGP implementations. +echo * * Sieve: (sieve). Managing Sieve scripts in Emacs. +echo *************************************************************************** echo. :etc cd ..\etc -copy gnus-tut.txt %1\etc +echo. +echo Stand by while copying etc files. +echo. +if not exist %GNUS_ETC_DIR% mkdir %GNUS_ETC_DIR% +xcopy /R /Q /Y gnus-tut.txt %GNUS_ETC_DIR% +if ErrorLevel 1 set ERROR=%ERROR%,copy-etc-gnus-tut-txt +if not exist %GNUS_ETC_DIR%\gnus mkdir %GNUS_ETC_DIR%\gnus +xcopy /R /Q /Y .\gnus\* %GNUS_ETC_DIR%\gnus\ +if ErrorLevel 1 set ERROR=%ERROR%,copy-etc-gnus-* +if not exist %GNUS_ETC_DIR%\smilies mkdir %GNUS_ETC_DIR%\smilies +xcopy /R /Q /Y .\smilies\* %GNUS_ETC_DIR%\smilies\ +if ErrorLevel 1 set ERROR=%ERROR%,copy-etc-smilies-* +goto warnings + +:nocopy +echo. +echo *************************************************************************** +echo * You chose not to copy the files, therefore you should add the +echo * following lines to the TOP of your [X]emacs customization file: +echo * +echo * (add-to-list 'load-path "/Path/to/gnus/lisp") +echo * (if (featurep 'xemacs) +echo * (add-to-list 'Info-directory-list "c:/Path/to/gnus/texi/") +echo * (add-to-list 'Info-default-directory-list "c:/Path/to/gnus/texi/") +echo * (require 'gnus-load) +echo * +echo * Replace c:/Path/to/gnus with the Path where your new Gnus is (that's here +echo * and yes, you've got to use forward slashes). +echo *************************************************************************** +echo. + +:warnings +if not "%subdirwarning%" == "yes" goto warngnusload +echo. +echo *************************************************************************** +echo * There's no subdirs.el file in your site-lisp directory, you should +echo * therefor add the following line to the TOP of your Emacs +echo * customization file: +echo * +echo * (add-to-list 'load-path "/Path/to/emacs-site-lisp-directory/gnus/lisp") +echo * (require 'gnus-load) +echo * Yes, it must be forward slashes. +echo *************************************************************************** +echo. +goto warnerrors + +:warngnusload +echo. +echo *************************************************************************** +echo * You should add the following line to the TOP of your Emacs +echo * customization file: +echo * +echo * (require 'gnus-load) +echo *************************************************************************** +echo. + +:warnerrors +if "%ERROR%"==":" goto noerrors +set errorlevel=1 +echo. +echo *************************************************************************** +echo * WARNING ERRORS OCCURRED! +echo * You should look for error messages in the output of the called programs +echo * and try to find out what exactly went wrong. +echo * Errors occured in the following modules: +echo * %ERROR% +echo *************************************************************************** +echo. +goto done + +:noerrors +set errorlevel=0 :done cd .. goto end +:noemacs +echo. +echo *************************************************************************** +echo * Unable to find emacs.exe or xemacs.exe on the path you specified! +echo * STOP! +echo *************************************************************************** +echo. +goto usage + :usage -echo Usage: make :emacs-dir: [/copy] echo. -echo where: :emacs-dir: is the directory you installed emacs in -echo eg. d:\emacs\20.4 -echo /copy indicates that the compiled files should be copied to your -echo emacs lisp, info, and etc directories -echo. -echo Note: If you have Emacs/w3 you should set the environment variable -echo W3DIR to the directory where w3 is installed eg. -echo set W3DIR=d:\lisp\w3-4.0pre46\lisp +echo *************************************************************************** +echo * Usage: make.bat :[X]Emacs-exe-dir: [/copy] +echo * +echo * where: :[X]Emacs-exe-dir: is the directory your +echo * emacs.exe respectively xemacs.exe resides in, +echo * e.g. G:\Programme\XEmacs\XEmacs-21.4.11\i586-pc-win32\ +echo * or G:\Emacs\bin +echo * /copy indicates that the compiled files should be copied to your +echo * emacs lisp, info, and etc site directories. +echo * +echo * Note: If you have Emacs/w3 you should set the environment variable +echo * W3DIR to the directory where w3 is installed eg. +echo * set W3DIR=d:\lisp\w3-4.0pre46\lisp +echo *************************************************************************** +echo. -rem Restore PWD so whoever called this batch file doesn't get confused +:end +rem Restore environment variables set PWD=%GNUS_PWD_SAVE% set GNUS_PWD_SAVE= set EMACSBATCH= +set GNUS_LISP_DIR= set GNUS_INFO_DIR= -:end +set GNUS_ETC_DIR= +set subdirwarning= +set ERROR= Index: gnus/contrib/ChangeLog diff -u gnus/contrib/ChangeLog:1.76 gnus/contrib/ChangeLog:1.77 --- gnus/contrib/ChangeLog:1.76 Tue Mar 11 22:20:06 2003 +++ gnus/contrib/ChangeLog Wed Mar 19 23:23:50 2003 @@ -1,3 +1,7 @@ +2003-03-19 Simon Josefsson <[email protected]> + + * gnus-idna.el: Update. + 2003-03-11 Teodor Zlatanov <[email protected]> * hashcash.el (hashcash-version, hashcash-insert-payment): patch Index: gnus/contrib/gnus-idna.el diff -u gnus/contrib/gnus-idna.el:1.2 gnus/contrib/gnus-idna.el:1.3 --- gnus/contrib/gnus-idna.el:1.2 Fri Mar 7 20:29:25 2003 +++ gnus/contrib/gnus-idna.el Wed Mar 19 23:23:50 2003 @@ -24,9 +24,8 @@ ;;; Commentary: -;; This package implement crude support for internationalized -;; (non-ASCII) domain names in Gnus. It is meant as a proof of -;; concept. +;; This package implement crude support for internationalized domain +;; names in Gnus. ;; Theory of Operation: @@ -34,82 +33,121 @@ ;; using IDNA ToASCII() when you send mail using Message. The hook ;; used is message-send-hook. ;; -;; For incoming articles, when QP in headers are decoded, it searches -;; for "xn--" prefixes and decode them using IDNA ToUnicode(). The -;; hook used is gnus-article-decode-hook. +;; For incoming articles, when QP in headers are decoded (i.e., when +;; gnus-article-decode-hook is invoked), it searches for "xn--" +;; prefixes and decode them if they are found inside (heuristically +;; determined) RHS in From:, To: and Cc:, using IDNA ToUnicode(). ;; Usage: -;; Simply put (require 'gnus-idna) in your ~/.gnus or ~/.emacs and it -;; should work. You need to install GNU Libidn (0.1.11 or later) and -;; make sure the idna.el installed by it is found by emacs. +;; You need to install GNU Libidn (0.1.11 or later) and make sure the +;; idna.el installed by it is found by emacs. + +;; If you use an older Gnus, you may need to put the following in your +;; init scripts too, but keep in mind that most older Gnuses either +;; doesn't have these hooks or are buggy in other regards so it +;; doesn't work anyway. (The window of Gnus versions that this works +;; on is a few weeks during the Oort CVS in winter 2003.) Update to a +;; recent Gnus instead, then you don't have to do anything. + +;; (add-hook 'message-send-hook 'message-idna-to-ascii-rhs) +;; (add-hook 'gnus-article-decode-hook 'gnus-idna-to-unicode-rhs 'append) + +;; Revision history: + +;; 2003-02-26 Initial release +;; +;; 2003-03-19 Cleanup. Fixes a bug that may corrupt outgoing mail if +;; it contains From:, To: or Cc: headers in the body. ;;; Code: (require 'gnus) +(require 'gnus-util) (require 'rfc822) -(require 'idna) +(autoload 'idna-to-ascii "idna") +(autoload 'idna-to-unicode "idna") -(eval-and-compile - (cond - ((fboundp 'replace-in-string) - (defalias 'gnus-replace-in-string 'replace-in-string)) - ((fboundp 'replace-regexp-in-string) - (defun gnus-replace-in-string (string regexp newtext &optional literal) - (replace-regexp-in-string regexp newtext string nil literal))) - (t - (defun gnus-replace-in-string (string regexp newtext &optional literal) - (let ((start 0) tail) - (while (string-match regexp string start) - (setq tail (- (length string) (match-end 0))) - (setq string (replace-match newtext nil literal string)) - (setq start (- (length string) tail)))) - string)))) - -(defun gnus-idna-to-ascii-rhs-1 (header) - (save-excursion - (save-restriction - (let (address header-data new-header-data rhs ace) +(defcustom message-use-idna 'ask + "Whether to encode non-ASCII in domain names into ASCII according to IDNA." + :type '(choice (const :tag "Ask" ask) + (const :tag "Never" nil) + (const :tag "Always" t))) + +(defun message-idna-inside-rhs-p () + "Return t iff point is inside a RHS (heuristically). +Only works properly if header contains mailbox-list or address-list. +I.e., calling it on a Subject: header is useless." + (if (re-search-backward + "[\\\n\r\t ]" (save-excursion (search-backward "@" nil t)) t) + ;; whitespace between @ and point + nil + (let ((dquote 1) (paren 1)) + (while (save-excursion (re-search-backward "[^\\]\"" nil t dquote)) + (incf dquote)) + (while (save-excursion (re-search-backward "[^\\]\(" nil t paren)) + (incf paren)) + (and (= (% dquote 2) 1) (= (% paren 2) 1))))) + +(defun message-idna-to-ascii-rhs-1 (header) + "Interactively potentially IDNA encode domain names in HEADER." + (let (rhs ace start end startpos endpos) + (goto-char (point-min)) + (setq start (re-search-forward (concat "^" header) nil t) + end (or (save-excursion (re-search-forward "^[ \t]" nil t)) + (point-max))) + (when (and start end) + (while (re-search-forward "@\\([^ \t\r\n>]+\\)" end t) + (setq rhs (match-string-no-properties 1) + startpos (match-beginning 1) + endpos (match-end 1)) + (when (save-match-data + (and (message-idna-inside-rhs-p) + (setq ace (idna-to-ascii rhs)) + (not (string= rhs ace)) + (if (eq message-use-idna 'ask) + (unwind-protect + (progn + (replace-highlight startpos endpos) + (y-or-n-p + (format "Replace with `%s'? " ace))) + (message "") + (replace-dehighlight)) + message-use-idna))) + (replace-match (concat "@" ace))))))) + +;;;###autoload +(defun message-idna-to-ascii-rhs () + "Possibly IDNA encode non-ASCII domain names in From:, To: and Cc: headers. +See `message-idna-encode'." + (interactive) + (when (condition-case nil (require 'idna) (file-error)) + (save-excursion + (save-restriction (message-narrow-to-head) - (setq header-data (message-fetch-field header)) - (when header-data - (dolist (element (message-tokenize-header header-data)) - (setq address (car (rfc822-addresses element))) - (when (string-match "\\(.*\\)@\\([^@]+\\)" address) - (setq ace (if (setq rhs (match-string 2 address)) - (idna-to-ascii rhs))) - (push (if (string= rhs ace) - element - (gnus-replace-in-string - element (regexp-quote rhs) ace t)) - new-header-data))) - (message-remove-header header) - (message-position-on-field header) - (dolist (addr (reverse new-header-data)) - (insert addr ", ")) - (when new-header-data - (delete-backward-char 2))))))) - -(defun gnus-idna-to-ascii-rhs () - (gnus-idna-to-ascii-rhs-1 "From") - (gnus-idna-to-ascii-rhs-1 "To") - (gnus-idna-to-ascii-rhs-1 "Cc")) - -(add-hook 'message-send-hook 'gnus-idna-to-ascii-rhs) + (message-idna-to-ascii-rhs-1 "From") + (message-idna-to-ascii-rhs-1 "To") + (message-idna-to-ascii-rhs-1 "Cc"))))) +;;;###autoload (defun gnus-idna-to-unicode-rhs () - (let ((inhibit-point-motion-hooks t) - buffer-read-only) - (goto-char (point-min)) - (while (re-search-forward "xn--.*[ \t\n\r.,<>()@!]" nil t) - ;(or (eobp) (forward-char)) - (let (ace unicode) - (when (setq ace (match-string 0)) - (setq unicode (idna-to-unicode ace)) - (unless (string= ace unicode) - (replace-match unicode))))))) - -(add-hook 'gnus-article-decode-hook 'gnus-idna-to-unicode-rhs 'append) + "Decode IDNA strings in RHS in From:, To: and Cc: headers in current buffer." + (when (condition-case nil (require 'idna) (file-error)) + (let ((inhibit-point-motion-hooks t) + buffer-read-only) + (article-narrow-to-head) + (goto-char (point-min)) + (while (re-search-forward "\\(xn--.*\\)[ \t\n\r,>]" nil t) + (let (ace unicode) + (when (save-match-data + (and (setq ace (match-string 1)) + (save-excursion (and (re-search-backward "^[^ \t]" nil t) + (looking-at "From\\|To\\|Cc"))) + (save-excursion (backward-char) + (message-idna-inside-rhs-p)) + (setq unicode (idna-to-unicode ace)))) + (unless (string= ace unicode) + (replace-match unicode nil nil nil 1)))))))) (provide 'gnus-idna) Index: gnus/etc/gnus-tut.txt diff -u gnus/etc/gnus-tut.txt:6.3 gnus/etc/gnus-tut.txt:6.4 --- gnus/etc/gnus-tut.txt:6.3 Fri Jan 24 04:12:22 2003 +++ gnus/etc/gnus-tut.txt Sat Mar 22 20:15:21 2003 @@ -293,3 +293,1483 @@ is where to post the questions. +From fschmitt Sat Mar 22 18:13:00 2003 +From: [email protected] (Gnus FAQ team) +Date: Sat Mar 22 18:13:00 2003 +Subject: Gnus FAQ +Message-ID: <[email protected]> + +This is the text version of the Gnus FAQ, see http://my.gnus.org for +the up to date version of this document, there you can also find a +html version and various other formats. + +Frequently Asked Questions + +Table of Contents + +Introduction +Frequently Asked Questions with Answers +Glossary + +Abstract + +This is the new Gnus Frequently Asked Questions list. If you have a +Web browser, the official hypertext version is at http:// +my.gnus.org/FAQ/ [http://my.gnus.org/FAQ/], the Docbook source is +available from http://sourceforge.net [http://sourceforge.net/ +projects/gnus/]. + +Please submit features and suggestions to the FAQ discussion list +[mailto:[email protected]]. The list is protected against +junk mail with qconfirm [http://smarden.org/qconfirm/index.html]. +As a subscriber, your submissions will automatically pass. You can +also subscribe to the list by sending a blank email to [email protected] +[mailto:[email protected]] and browse the archive. + +Introduction + +This is the Gnus Frequently Asked Questions list. + +Gnus is a Usenet Newsreader and Electronic Mail User Agent +implemented as a part of Emacs. It's been around in some form for +almost a decade now, and has been distributed as a standard part of +Emacs for much of that time. Gnus 5 is the latest (and greatest) +incarnation. The original version was called GNUS, and was written +by Masanobu UMEDA. When autumn crept up in '94, Lars Magne +Ingebrigtsen grew bored and decided to rewrite Gnus. + +Its biggest strength is the fact that it is extremely customizable. +It is somewhat intimidating at first glance, but most of the +complexity can be ignored until you're ready to take advantage of +it. If you receive a reasonable volume of e-mail (you're on various +mailing lists), or you would like to read high-volume mailing lists +but cannot keep up with them, or read high volume newsgroups or are +just bored, then Gnus is what you want. + +This FAQ was maintained by Justin Sheehy until March 2002. He would +like to thank Steve Baur and Per Abrahamsen for doing a wonderful +job with this FAQ before him. We would like to do the same - +thanks, Justin! + +If you have a Web browser, the official hypertext version is at: +http://my.gnus.org/FAQ/ [http://my.gnus.org/FAQ/]. This version is +much nicer than the unofficial hypertext versions that are archived +at Utrecht, Oxford, Smart Pages, Ohio State, and other FAQ +archives. See the resources question below if you want information +on obtaining it in another format. + +The information contained here was compiled with the assistance of +the Gnus development mailing list, and any errors or misprints are +the my.gnus.org team's fault, sorry. + +Frequently Asked Questions with Answers + +1. Installation FAQ + + 1.1. What is the latest version of Gnus? + 1.2. Where and how to get Gnus? + 1.3. What to do with the tarball now? + 1.4. Which version of Emacs do I need? + 1.5. How do I run Gnus on both Emacs and XEmacs? + +2. Startup / Group buffer + + 2.1. Every time I start Gnus I get a message "Gnus auto-save + file exists. Do you want to read it?", what does this mean + and how to prevent it? + 2.2. Gnus doesn't remember which groups I'm subscribed to, + what's this? + 2.3. How to change the format of the lines in Group buffer? + 2.4. My group buffer becomes a bit crowded, is there a way to + sort my groups into categories so I can easier browse + through them? + 2.5. How to manually sort the groups in Group buffer? How to + sort the groups in a topic? + +3. Getting Messages + + 3.1. I just installed Gnus, started it via M-x gnus but it only + says "nntp (news) open error", what to do? + 3.2. I'm working under Windows and have no idea what ~/.gnus + means. + 3.3. My news server requires authentication, how to store user + name and password on disk? + 3.4. Gnus seems to start up OK, but I can't find out how to + subscribe to a group. + 3.5. Gnus doesn't show all groups / Gnus says I'm not allowed + to post on this server as well as I am, what's that? + 3.6. I want Gnus to fetch news from several servers, is this + possible? + 3.7. And how about local spool files? + 3.8. OK, reading news works now, but I want to be able to read + my mail with Gnus, too. How to do it? + 3.9. And what about IMAP? + 3.10. At the office we use one of those MS Exchange servers, + can I use Gnus to read my mail from it? + 3.11. Can I tell Gnus not to delete the mails on the server it + retrieves via POP3? + +4. Reading messages + + 4.1. When I enter a group, all read messages are gone. How to + view them again? + 4.2. How to tell Gnus to show an important message every time I + enter a group, even when it's read? + 4.3. How to view the headers of a message? + 4.4. How to view the raw unformatted message? + 4.5. How can I change the headers Gnus displays by default at + the top of the article buffer? + 4.6. I'd like Gnus NOT to render HTML-mails but show me the + text part if it's available. How to do it? + 4.7. Can I use some other browser than w3 to render my + HTML-mails? + 4.8. Is there anything I can do to make poorly formatted mails + more readable? + 4.9. Is there a way to automatically ignore posts by specific + authors or with specific words in the subject? And can I + highlight more interesting ones in some way? + 4.10. How can I disable threading in some (e.g. mail-) groups, + or set other variables specific for some groups? + 4.11. Can I highlight messages written by me and follow-ups to + those? + 4.12. The number of total messages in a group which Gnus + displays in group buffer is by far to high, especially in + mail groups. Is this a bug? + 4.13. I don't like the layout of summary and article buffer, + how to change it? Perhaps even a three pane display? + 4.14. I don't like the way the Summary buffer looks, how to + tweak it? + 4.15. How to split incoming mails in several groups? + +5. Composing messages + + 5.1. What are the basic commands I need to know for sending + mail and postings? + 5.2. How to enable automatic word-wrap when composing messages? + 5.3. How to set stuff like From, Organization, Reply-To, + signature...? + 5.4. Can I set things like From, Signature etc group based on + the group I post too? + 5.5. Is there a spell-checker? Perhaps even on-the-fly + spell-checking? + 5.6. Can I set the dictionary based on the group I'm posting + to? + 5.7. Is there some kind of address-book, so I needn't remember + all those email addresses? + 5.8. Sometimes I see little images at the top of article + buffer. What's that and how can I send one with my + postings, too? + 5.9. Sometimes I accidentally hit r instead of f in newsgroups. + Can Gnus warn me, when I'm replying by mail in newsgroups? + 5.10. How to tell Gnus not to generate a sender header? + 5.11. I want gnus to locally store copies of my send mail and + news, how to do it? + 5.12. People tell me my Message-IDs are not correct, why aren't + they and how to fix it? + +6. Old messages + + 6.1. How to import my old mail into Gnus? + 6.2. How to archive interesting messages? + 6.3. How to search for a specific message? + 6.4. How to get rid of old unwanted mail? + 6.5. I want that all read messages are expired (at least in + some groups). How to do it? + 6.6. I don't want expiration to delete my mails but to move + them to another group. + +7. Getting help + + 7.1. How to find information and help inside Emacs? + 7.2. I can't find anything in the Gnus manual about X (e.g. + attachments, PGP, MIME...), is it not documented? + 7.3. Which websites should I know? + 7.4. Which mailing lists and newsgroups are there? + 7.5. Where to report bugs? + 7.6. I need real-time help, where to find it? + +8. Tuning Gnus + + 8.1. Starting Gnus is really slow, how to speed it up? + 8.2. How to speed up the process of entering a group? + 8.3. Sending mail becomes slower and slower, what's up? + +1. Installation FAQ + +1.1. What is the latest version of Gnus? + + As of this posting, the latest Gnus version is 5.8.8(which is + basically the same as Gnus 5.9 which is shipped with GNU Emacs). + This version is very stable and should be the choice for all + beginners. However 5.8.8 is quite old, so many people today use the + BETA version from CVS called Oort Gnus, which contains a huge + amount of new features. If you want to do this too, be aware that + it's beta and might have bugs and at worst case might eat your + mail. + +1.2. Where and how to get Gnus? + + The latest released version of Gnus is included in Emacs 21 and + available through the package system of XEmacs 21.4, so the easiest + way is getting one of those. If you don't want or can't do this, + get the Gnus tarball from http://www.gnus.org/dist/gnus.tar.gz + [http://www.gnus.org/dist/gnus.tar.gz] or via anonymous FTP from + ftp://ftp.gnus.org/pub/gnus/gnus.tar.gz [ftp://ftp.gnus.org/pub/ + gnus/gnus.tar.gz]. + +1.3. What to do with the tarball now? + + Untar it via tar xvzf gnus.tar.gz and do the common ./configure; + make; make install circle. (under MS-Windows either get the Cygwin + environment from http://www.cygwin.com [http://www.cygwin.com] + which allows you to do what's described above or unpack the tarball + with some packer (e.g. Winace from http://www.winace.com [http:// + www.winace.com]) and use the batch-file make.bat included in the + tarball to install Gnus. If you don't want to (or aren't allowed + to) install Gnus system-wide, you can install it in your home + directory and add the following lines to your ~/.xemacs/init.el or + ~/.emacs: + + (add-to-list 'load-path "/path/to/gnus/lisp") + (if (featurep 'xemacs) + (add-to-list 'Info-directory-list "/path/to/gnus/texi/") + (add-to-list 'Info-default-directory-list "/path/to/gnus/texi/")) + + + Make sure that you don't have any gnus related stuff before this + line, on MS Windows use something like "C:/path/to/lisp" (yes, "/ + "). + +1.4. Which version of Emacs do I need? + + Gnus 5.8.8 requires an emacs version that is greater than or equal + to Emacs 20.3 or XEmacs 20.1. + +1.5. How do I run Gnus on both Emacs and XEmacs? + + You can't use the same copy of Gnus in both as the Lisp files are + byte-compiled to a format which is different depending on which + Emacs did the compilation. Get one copy of Gnus for Emacs and one + for XEmacs. + +2. Startup / Group buffer + +2.1. Every time I start Gnus I get a message "Gnus auto-save file + exists. Do you want to read it?", what does this mean and how to + prevent it? + + This message means that the last time you used Gnus, it wasn't + properly exited and therefor couldn't write its informations to + disk (e.g. which messages you read), you are now asked if you want + to restore those informations from the auto-save file. + + To prevent this message make sure you exit Gnus via q in group + buffer instead of just killing Emacs. + +2.2. Gnus doesn't remember which groups I'm subscribed to, what's this? + + You get the message described in the q/a pair above while starting + Gnus, right? It's an other symptom for the same problem, so read + the answer above. + +2.3. How to change the format of the lines in Group buffer? + + You've got to tweak the value of the variable + gnus-group-line-format. See the manual node "Group Line + Specification" for information on how to do this. An example for + this (guess from whose .gnus :-)): + + (setq gnus-group-line-format "%P%M%S[%5t]%5y : %(%g%)\n") + + +2.4. My group buffer becomes a bit crowded, is there a way to sort my + groups into categories so I can easier browse through them? + + Gnus offers the topic mode, it allows you to sort your groups in, + well, topics, e.g. all groups dealing with Linux under the topic + linux, all dealing with music under the topic music and all dealing + with scottish music under the topic scottish which is a subtopic of + music. + + To enter topic mode, just hit t while in Group buffer. Now you can + use T n to create a topic at point and T m to move a group to a + specific topic. For more commands see the manual or the menu. You + might want to include the %P specifier at the beginning of your + gnus-group-line-format variable to have the groups nicely indented. + +2.5. How to manually sort the groups in Group buffer? How to sort the + groups in a topic? + + Move point over the group you want to move and hit C-k, now move + point to the place where you want the group to be and hit C-y. + +3. Getting Messages + +3.1. I just installed Gnus, started it via M-x gnus but it only says + "nntp (news) open error", what to do? + + You've got to tell Gnus where to fetch the news from. Read the + documentation for information on how to do this. As a first start, + put those lines in ~/.gnus: + + (setq gnus-select-method '(nntp "news.yourprovider.net")) + (setq user-mail-address "[email protected]") + (setq user-full-name "Your Name") + + +3.2. I'm working under Windows and have no idea what ~/.gnus means. + + The ~/ means the home directory where Gnus and Emacs look for the + configuration files. However, you don't really need to know what + this means, it suffices that Emacs knows what it means :-) You can + type C-x C-f ~/.gnus RET (yes, with the forward slash, even on + Windows), and Emacs will open the right file for you. (It will most + likely be new, and thus empty.) However, I'd discourage you from + doing so, since the directory Emacs chooses will most certainly not + be what you want, so let's do it the correct way. The first thing + you've got to do is to create a suitable directory (no blanks in + directory name please) e.g. c:\myhome. Then you must set the + environment variable HOME to this directory. To do this under Win9x + or Me include the line + + SET HOME=C:\myhome + + + in your autoexec.bat and reboot. Under NT, 2000 and XP, hit + Winkey+Pause/Break to enter system options (if it doesn't work, go + to Control Panel -> System). There you'll find the possibility to + set environment variables, create a new one with name HOME and + value C:\myhome, a reboot is not necessary. + + Now to create ~/.gnus, say C-x C-f ~/.gnus RET C-x C-s. in Emacs. + +3.3. My news server requires authentication, how to store user name and + password on disk? + + Create a file ~/.authinfo which includes for each server a line + like this + + machine news.yourprovider.net login YourUserName password YourPassword + + . Make sure that the file isn't readable to others if you work on a + OS which is capable of doing so. (Under Unix say + + chmod 600 ~/.authinfo + + in a shell.) + +3.4. Gnus seems to start up OK, but I can't find out how to subscribe to + a group. + + If you know the name of the group say U name.of.group RET in group + buffer (use the tab-completion Luke). Otherwise hit ^ in group + buffer, this brings you to the server buffer. Now place point (the + cursor) over the server which carries the group you want, hit RET, + move point to the group you want to subscribe to and say u to + subscribe to it. + +3.5. Gnus doesn't show all groups / Gnus says I'm not allowed to post on + this server as well as I am, what's that? + + Some providers allow restricted anonymous access and full access + only after authorization. To make Gnus send authinfo to those + servers append + + force yes + + to the line for those servers in ~/.authinfo. + +3.6. I want Gnus to fetch news from several servers, is this possible? + + Of course. You can specify more sources for articles in the + variable gnus-secondary-select-methods. Add something like this in + ~/.gnus: + + (add-to-list 'gnus-secondary-select-methods '(nntp "news.yourSecondProvider.net")) + (add-to-list 'gnus-secondary-select-methods '(nntp "news.yourThirdProvider.net")) + + +3.7. And how about local spool files? + + No problem, this is just one more select method called nnspool, so + you want this: + + (add-to-list 'gnus-secondary-select-methods '(nnspool "")) + + + Or this if you don't want an NNTP Server as primary news source: + + (setq gnus-select-method '(nnspool "")) + + + Gnus will look for the spool file in /usr/spool/news, if you want + something different, change the line above to something like this: + + (add-to-list 'gnus-secondary-select-methods + '(nnspool "" (nnspool-directory "/usr/local/myspoolddir"))) + + + This sets the spool directory for this server only. You might have + to specify more stuff like the program used to post articles, see + the Gnus manual on how to do this. + +3.8. OK, reading news works now, but I want to be able to read my mail + with Gnus, too. How to do it? + + That's a bit harder since there are many possible sources for mail, + many possible ways for storing mail and many different ways for + sending mail. The most common cases are these: 1: You want to read + your mail from a pop3 server and send them directly to a SMTP + Server 2: Some program like fetchmail retrieves your mail and + stores it on disk from where Gnus shall read it. Outgoing mail is + sent by Sendmail, Postfix or some other MTA. Sometimes, you even + need a combination of the above cases. + + However, the first thing to do is to tell Gnus in which way it + should store the mail, in Gnus terminology which back end to use. + Gnus supports many different back ends, the most commonly used one + is nnml. It stores every mail in one file and is therefor quite + fast. However you might prefer a one file per group approach if + your file system has problems with many small files, the nnfolder + back end is then probably the choice for you. To use nnml add the + following to ~/.gnus: + + (add-to-list 'gnus-secondary-select-methods '(nnml "")) + + + As you might have guessed, if you want nnfolder, it's + + (add-to-list 'gnus-secondary-select-methods '(nnfolder "")) + + + Now we need to tell Gnus, where to get it's mail from. If it's a + POP3 server, then you need something like this: + + (eval-after-load "mail-source" + '(add-to-list 'mail-sources '(pop :server "pop.YourProvider.net" + :user "yourUserName" + :password "yourPassword")) + + + Make sure ~/.gnus isn't readable to others if you store your + password there. If you want to read your mail from a traditional + spool file on your local machine, it's + + (eval-after-load "mail-source" + '(add-to-list 'mail-sources '(file :path "/path/to/spool/file")) + + + If it's a Maildir, with one file per message as used by postfix, + Qmail and (optionally) fetchmail it's + + (eval-after-load "mail-source" + '(add-to-list 'mail-sources '(maildir :path "/path/to/Maildir/" + :subdirs ("cur" "new"))) + + + And finally if you want to read your mail from several files in one + directory, for example because procmail already split your mail, + it's + + (eval-after-load "mail-source" + '(add-to-list 'mail-sources '(directory :path "/path/to/procmail-dir/" + :suffix ".prcml")) + + + Where :suffix ".prcml" tells Gnus only to use files with the suffix + .prcml. + + OK, now you only need to tell Gnus how to send mail. If you want to + send mail via sendmail (or whichever MTA is playing the role of + sendmail on your system), you don't need to do anything. However, + if you want to send your mail to an SMTP Server you need the + following in your ~/.gnus + + (setq send-mail-function 'smtpmail-send-it) + (setq message-send-mail-function 'smtpmail-send-it) + (setq smtpmail-default-smtp-server "smtp.yourProvider.net") + + +3.9. And what about IMAP? + + There are two ways of using IMAP with Gnus. The first one is to use + IMAP like POP3, that means Gnus fetches the mail from the IMAP + server and stores it on disk. If you want to do this (you don't + really want to do this) add the following to ~/.gnus + + (add-to-list 'mail-sources '(imap :server "mail.mycorp.com" + :user "username" + :pass "password" + :stream network + :authentication login + :mailbox "INBOX" + :fetchflag "\\Seen")) + + + You might have to tweak the values for stream and/or + authentification, see the Gnus manual node "Mail Source Specifiers" + for possible values. + + If you want to use IMAP the way it's intended, you've got to follow + a different approach. You've got to add the nnimap back end to your + select method and give the information about the server there. + + (add-to-list 'gnus-secondary-select-methods + '(nnimap "Give the baby a name" + (nnimap-address "imap.yourProvider.net") + (nnimap-port 143) + (nnimap-list-pattern "archive.*"))) + + + Again, you might have to specify how to authenticate to the server + if Gnus can't guess the correct way, see the Manual Node "IMAP" for + detailed information. + +3.10. At the office we use one of those MS Exchange servers, can I use + Gnus to read my mail from it? + + Offer your administrator a pair of new running shoes for activating + IMAP on the server and follow the instructions above. + +3.11. Can I tell Gnus not to delete the mails on the server it retrieves + via POP3? + + First of all, that's not the way POP3 is intended to work, if you + have the possibility, you should use the IMAP Protocol if you want + your messages to stay on the server. Nevertheless there might be + situations where you need the feature, but sadly Gnus itself has no + predefined functionality to do so. + + However this is Gnus county so there are possibilities to achieve + what you want. The easiest way is to get an external program which + retrieves copies of the mail and stores them on disk, so Gnus can + read it from there. On Unix systems you could use e.g. fetchmail + for this, on MS Windows you can use Hamster, an excellent local + news and mail server. + + The other solution would be, to replace the method Gnus uses to get + mail from POP3 servers by one which is capable of leaving the mail + on the server. If you use XEmacs, get the package mail-lib, it + includes an enhanced pop3.el, look in the file, there's + documentation on how to tell Gnus to use it and not to delete the + retrieved mail. For GNU Emacs look for the file epop3.el which can + do the same (If you know the home of this file, please send me an + e-mail). You can also tell Gnus to use an external program (e.g. + fetchmail) to fetch your mail, see the info node "Mail Source + Specifiers" in the Gnus manual on how to do it. + +4. Reading messages + +4.1. When I enter a group, all read messages are gone. How to view them + again? + + If you enter the group by saying RET in summary buffer with point + over the group, only unread and ticked messages are loaded. Say C-u + RET instead to load all available messages. If you want only the + e.g. 300 newest say C-u 300 RET + + Loading only unread messages can be annoying if you have threaded + view enabled, say + + (setq gnus-fetch-old-headers 'some) + + + in ~/.gnus to load enough old articles to prevent teared threads, + replace 'some with t to load all articles (Warning: Both settings + enlarge the amount of data which is fetched when you enter a group + and slow down the process of entering a group). + + If you use Oort Gnus, you can say /o N In summary buffer to load + the last N messages, this feature is not available in 5.8.8 + + If you don't want all old messages, but the parent of the message + you're just reading, you can say ^, if you want to retrieve the + whole thread the message you're just reading belongs to, A T is + your friend. + +4.2. How to tell Gnus to show an important message every time I enter a + group, even when it's read? + + You can tick important messages. To do this hit u while point is in + summary buffer over the message. When you want to remove the mark, + hit either d (this deletes the tick mark and set's unread mark) or + M c (which deletes all marks for the message). + +4.3. How to view the headers of a message? + + Say t to show all headers, one more t hides them again. + +4.4. How to view the raw unformatted message? + + Say C-u g to show the raw message g returns to normal view. + +4.5. How can I change the headers Gnus displays by default at the top of + the article buffer? + + The variable gnus-visible-headers controls which headers are shown, + its value is a regular expression, header lines which match it are + shown. So if you want author, subject, date, and if the header + exists, Followup-To and MUA / NUA say this in ~/.gnus: + + (setq gnus-visible-headers + "^\\(From:\\|Subject:\\|Date:\\|Followup-To:\\|X-Newsreader:\\|User-Agent:\\|X-Mailer:\\)") + + +4.6. I'd like Gnus NOT to render HTML-mails but show me the text part if + it's available. How to do it? + + Say + + (eval-after-load "mm-decode" + '(progn + (add-to-list 'mm-discouraged-alternatives "text/html") + (add-to-list 'mm-discouraged-alternatives "text/richtext"))) + + + in ~/.gnus. If you don't want HTML rendered, even if there's no + text alternative add + + (setq mm-automatic-display (remove "text/html" mm-automatic-display)) + + + too. + +4.7. Can I use some other browser than w3 to render my HTML-mails? + + Only if you use Oort Gnus. In this case you've got the choice + between w3, w3m, links, lynx and html2text, which one is used can + be specified in the variable mm-text-html-renderer, so if you want + links to render your mail say + + (setq mm-text-html-renderer 'links) + + +4.8. Is there anything I can do to make poorly formatted mails more + readable? + + Gnus offers you several functions to "wash" incoming mail, you can + find them if you browse through the menu, item Article->Washing. + The most interesting ones are probably "Wrap long lines" ( W w ), + "Decode ROT13" ( W r ) and "Outlook Deuglify" which repairs the + dumb quoting used by many users of Microsoft products ( W k ) sadly + the last one is only available in Oort Gnus. + +4.9. Is there a way to automatically ignore posts by specific authors or + with specific words in the subject? And can I highlight more + interesting ones in some way? + + You want Scoring. Scoring means, that you define rules which assign + each message an integer value. Depending on the value the message + is highlighted in summary buffer (if it's high, say +2000) or + automatically marked read (if the value is low, say -800) or some + other action happens. + + There are basically three ways of setting up rules which assign the + scoring-value to messages. The first and easiest way is to set up + rules based on the article you are just reading. Say you're reading + a message by a guy who always writes nonsense and you want to + ignore his messages in the future. Hit L, to set up a rule which + lowers the score. Now Gnus asks you which the criteria for lowering + the Score shall be. Hit ? twice to see all possibilities, we want a + which means the author (the from header). Now Gnus wants to know + which kind of matching we want. Hit either e for an exact match or + s for substring-match and delete afterwards everything but the name + to score down all authors with the given name no matter which email + address is used. Now you need to tell Gnus when to apply the rule + and how long it should last, hit e.g. p to apply the rule now and + let it last forever. If you want to raise the score instead of + lowering it say I instead of L. + + You can also set up rules by hand. To do this say V f in summary + buffer. Then you are asked for the name of the score file, it's + name.of.group.SCORE for rules valid in only one group or all.Score + for rules valid in all groups. See the Gnus manual for the exact + syntax, basically it's one big list whose elements are lists again. + the first element of those lists is the header to score on, then + one more list with what to match, which score to assign, when to + expire the rule and how to do the matching. If you find me very + interesting, you could e.g. add the following to your all.Score: + + (("references" ("hschmi22.userfqdn.rz-online.de" 500 nil s)) + ("message-id" ("hschmi22.userfqdn.rz-online.de" 999 nil s))) + + + This would add 999 to the score of messages written by me and 500 + to the score of messages which are a (possibly indirect) answer to + a message written by me. Of course nobody with a sane mind would do + this :-) + + The third alternative is adaptive scoring. This means Gnus watches + you and tries to find out what you find interesting and what + annoying and sets up rules which reflect this. Adaptive scoring can + be a huge help when reading high traffic groups. If you want to + activate adaptive scoring say + + (setq gnus-use-adaptive-scoring t) + + + in ~/.gnus. + +4.10. How can I disable threading in some (e.g. mail-) groups, or set + other variables specific for some groups? + + While in group buffer move point over the group and hit G c, this + opens a buffer where you can set options for the group. At the + bottom of the buffer you'll find an item that allows you to set + variables locally for the group. To disable threading enter + gnus-show-threads as name of variable and nil as value. Hit button + done at the top of the buffer when you're ready. + +4.11. Can I highlight messages written by me and follow-ups to those? + + Stop those "Can I ..." questions, the answer is always yes in Gnus + Country :-). It's a three step process: First we make faces + (specifications of how summary-line shall look like) for those + postings, then we'll give them some special score and finally we'll + tell Gnus to use the new faces. You can find detailed instructions + on how to do it on my.gnus.org [http://my.gnus.org/Members/dzimmerm + /HowTo%2C2002-07-25%2C1027619165012198456/view] + +4.12. The number of total messages in a group which Gnus displays in + group buffer is by far to high, especially in mail groups. Is this + a bug? + + No, that's a matter of design of Gnus, fixing this would mean + reimplementation of major parts of Gnus' back ends. Gnus thinks + "highest-article-number - lowest-article-number = + total-number-of-articles". This works OK for Usenet groups, but if + you delete and move many messages in mail groups, this fails. To + cure the symptom, enter the group via C-u RET (this makes Gnus get + all messages), then hit M P b to mark all messages and then say B m + name.of.group to move all messages to the group they have been in + before, they get new message numbers in this process and the count + is right again (until you delete and move your mail to other groups + again). + +4.13. I don't like the layout of summary and article buffer, how to + change it? Perhaps even a three pane display? + + You can control the windows configuration by calling the function + gnus-add-configuration. The syntax is a bit complicated but + explained very well in the manual node "Window Layout". Some + popular examples: + + Instead 25% summary 75% article buffer 35% summary and 65% article + (the 1.0 for article means "take the remaining space"): + + (gnus-add-configuration '(article (vertical 1.0 (summary .35 point) (article 1.0)))) + + + A three pane layout, Group buffer on the left, summary buffer + top-right, article buffer bottom-right: + + (gnus-add-configuration + '(article + (horizontal 1.0 + (vertical 25 + (group 1.0)) + (vertical 1.0 + (summary 0.25 point) + (article 1.0))))) + (gnus-add-configuration + '(summary + (horizontal 1.0 + (vertical 25 + (group 1.0)) + (vertical 1.0 + (summary 1.0 point))))) + + +4.14. I don't like the way the Summary buffer looks, how to tweak it? + + You've got to play around with the variable + gnus-summary-line-format. It's value is a string of symbols which + stand for things like author, date, subject etc. A list of the + available specifiers can be found in the manual node "Summary + Buffer Lines" and the often forgotten node "Formatting Variables" + and it's sub-nodes. There you'll find useful things like + positioning the cursor and tabulators which allow you a summary in + table form, but sadly hard tabulators are broken in 5.8.8. + + Oort Gnus offers you some very nice new specifiers, e.g. %B which + draws a thread-tree and %&user-date which gives you a date where + the details are dependent of the articles age. Here's an example + which uses both, DON'T TRY TO USE IT WITH 5.8.8! + + (setq gnus-summary-line-format ":%U%R %B %s %-60=|%4L |%-20,20f |%&user-date; \n") + + + resulting in: + + :O Re: [Richard Stallman] rfc2047.el | 13 |Lars Magne Ingebrigt |Sat 23:06 + :O Re: Revival of the ding-patches list | 13 |Lars Magne Ingebrigt |Sat 23:12 + :R > Re: Find correct list of articles for a gro| 25 |Lars Magne Ingebrigt |Sat 23:16 + :O \-> ... | 21 |Kai Grossjohann | 0:01 + :R > Re: Cry for help: deuglify.el - moving stuf| 28 |Lars Magne Ingebrigt |Sat 23:34 + :O \-> ... | 115 |Raymond Scholz | 1:24 + :O \-> ... | 19 |Lars Magne Ingebrigt |15:33 + :O Slow mailing list | 13 |Lars Magne Ingebrigt |Sat 23:49 + :O Re: `@' mark not documented | 13 |Lars Magne Ingebrigt |Sat 23:50 + :R > Re: Gnus still doesn't count messages prope| 23 |Lars Magne Ingebrigt |Sat 23:57 + :O \-> ... | 18 |Kai Grossjohann | 0:35 + :O \-> ... | 13 |Lars Magne Ingebrigt | 0:56 + + +4.15. How to split incoming mails in several groups? + + Gnus offers two possibilities for splitting mail, the easy + nnmail-split-methods and the more powerful Fancy Mail Splitting. + I'll only talk about the first one, refer to the manual, node + "Fancy Mail Splitting" for the latter. + + The value of nnmail-split-methods is a list, each element is a list + which stands for a splitting rule. Each rule has the form "group + where matching articles should go to", "regular expression which + has to be matched", the first rule which matches wins. The last + rule must always be a general rule (regular expression .*) which + denotes where articles should go which don't match any other rule. + If the folder doesn't exist yet, it will be created as soon as an + article lands there. By default the mail will be send to all groups + whose rules match. If you don't want that (you probably don't + want), say + + (setq nnmail-crosspost nil) + + + in ~/.gnus. + + An example might be better than thousand words, so here's my + nnmail-split-methods. Note that I send duplicates in a special + group and that the default group is spam, since I filter all mails + out which are from some list I'm subscribed to or which are + addressed directly to me before. Those rules kill about 80% of the + Spam which reaches me (Email addresses are changed to prevent + spammers from using them): + + (setq nnmail-split-methods + '(("duplicates" "^Gnus-Warning:.*duplicate") + ("XEmacs-NT" "^\\(To:\\|CC:\\).*[email protected].*") + ("Gnus-Tut" "^\\(To:\\|CC:\\).*[email protected].*") + ("tcsh" "^\\(To:\\|CC:\\).*[email protected].*") + ("BAfH" "^\\(To:\\|CC:\\).*localpart@.*uni-muenchen.bla.*") + ("Hamster-src" "^\\(CC:\\|To:\\).*hamster-sourcen@yahoogroups.\\(de\\|com\\).*") + ("Tagesschau" "^From: tagesschau <[email protected]>$") + ("Replies" "^\\(CC:\\|To:\\).*[email protected].*") + ("EK" "^From:.*\\([email protected]\\|[email protected]\\).*") + ("Spam" "^Content-Type:.*\\(ks_c_5601-1987\\|EUC-KR\\|big5\\|iso-2022-jp\\).*") + ("Spam" "^Subject:.*\\(This really work\\|XINGA\\|ADV:\\|XXX\\|adult\\|sex\\).*") + ("Spam" "^Subject:.*\\(\=\?ks_c_5601-1987\?\\|\=\?euc-kr\?\\|\=\?big5\?\\).*") + ("Spam" "^X-Mailer:\\(.*BulkMailer.*\\|.*MIME::Lite.*\\|\\)") + ("Spam" "^X-Mailer:\\(.*CyberCreek Avalanche\\|.*http\:\/\/GetResponse\.com\\)") + ("Spam" "^From:.*\\(verizon\.net\\|prontomail\.com\\|money\\|ConsumerDirect\\).*") + ("Spam" "^Delivered-To: GMX delivery to [email protected]$") + ("Spam" "^Received: from link2buy.com") + ("Spam" "^CC: .*[email protected]") + ("Spam" "^X-Mailer-Version: 1.50 BETA") + ("Uni" "^\\(CC:\\|To:\\).*[email protected].*") + ("Inbox" "^\\(CC:\\|To:\\).*\\(my\ name\\|[email protected]\\|[email protected]\\)") + ("Spam" ""))) + + +5. Composing messages + +5.1. What are the basic commands I need to know for sending mail and + postings? + + To start composing a new mail hit m either in Group or Summary + buffer, for a posting, it's either a in Group buffer and filling + the Newsgroups header manually or a in the Summary buffer of the + group where the posting shall be send to. Replying by mail is r if + you don't want to cite the author, or import the cited text + manually and R to cite the text of the original message. For a + follow up to a newsgroup, it's f and F (analog to r and R. + + Enter new headers above the line saying "--text follows this + line--", enter the text below the line. When ready hit C-c C-c, to + send the message, if you want to finish it later hit C-c C-d to + save it in the drafts group, where you can start editing it again + by saying D e. + +5.2. How to enable automatic word-wrap when composing messages? + + Say + + (add-hook 'message-mode-hook + (lambda () + (setq fill-column 72) + (turn-on-auto-fill))) + + + in ~/.gnus. You can reformat a paragraph by hitting M-q (as usual) + +5.3. How to set stuff like From, Organization, Reply-To, signature...? + + There are other ways, but you should use posting styles for this. + (See below why). This example should make the syntax clear: + + (setq gnus-posting-styles + '((".*" + (name "Frank Schmitt") + (address "[email protected]") + (organization "Hamme net, kren mer och nimmi") + (signature-file "~/.signature") + ("X-SampleHeader" "foobar") + (eval (setq some-variable "Foo bar"))))) + + + The ".*" means that this settings are the default ones (see below), + valid values for the first element of the following lists are + signature, signature-file, organization, address, name or body. The + attribute name can also be a string. In that case, this will be + used as a header name, and the value will be inserted in the + headers of the article; if the value is `nil', the header name will + be removed. You can also say (eval (foo bar)), then the function + foo will be evaluated with argument bar and the result will be + thrown away. + +5.4. Can I set things like From, Signature etc group based on the group + I post too? + + That's the strength of posting styles. Before, we used ".*" to set + the default for all groups. You can use a regexp like "^gmane" and + the following settings are only applied to postings you send to the + gmane hierarchy, use ".*binaries" instead and they will be applied + to postings send to groups containing the string binaries in their + name etc. + + You can instead of specifying a regexp specify a function which is + evaluated, only if it returns true, the corresponding settings take + effect. Two interesting candidates for this are message-news-p + which returns t if the current Group is a newsgroup and the + corresponding message-mail-p. + + Note that all forms that match are applied, that means in the + example below, when I post to gmane.mail.spam.spamassassin.general, + the settings under ".*" are applied and the settings under + message-news-p and those under "^gmane" and those under "^gmane\ + \.mail\\.spam\\.spamassassin\\.general$". Because of this put + general settings at the top and specific ones at the bottom. + + (setq gnus-posting-styles + '((".*" ;;default + (name "Frank Schmitt") + (organization "Hamme net, kren mer och nimmi") + (signature-file "~/.signature") ) + ((message-news-p) ;;Usenet news? + (address "[email protected]") + ("Reply-To" "[email protected]") ) + ((message-mail-p) ;;mail? + (address "[email protected]") ) + ("^gmane" ;;this is mail, too in fact + (address "[email protected]") + ("Reply-To" nil) ) + ("^gmane.mail.spam.spamassassin.general$" + (eval (setq mail-envelope-from "[email protected]")) + (address "[email protected]")) )) + + +5.5. Is there a spell-checker? Perhaps even on-the-fly spell-checking? + + You can use ispell.el to spell-check stuff in Emacs. So the first + thing to do is to make sure that you've got either ispell [http:// + fmg-www.cs.ucla.edu/fmg-members/geoff/ispell.html] or aspell [http: + //aspell.sourceforge.net/] installed and in your Path. Then you + need ispell.el [http://www.kdstevens.com/~stevens/ispell-page.html] + and for on-the-fly spell-checking flyspell.el [http:// + www-sop.inria.fr/mimosa/personnel/Manuel.Serrano/flyspell/ + flyspell.html]. Ispell.el is shipped with Gnus Emacs and available + through the Emacs package system, flyspell.el is shipped with Emacs + and part of XEmacs text-modes package which is available through + the package system, so there should be no need to install them + manually. + + Ispell.el assumes you use ispell, if you choose aspell say + + (setq ispell-program-name "aspell") + + in your Emacs configuration file. + + If you want your outgoing messages to be spell-checked, say + + (add-hook 'message-send-hook 'ispell-message) + + In your ~/.gnus, if you prefer on-the-fly spell-checking say + + (add-hook 'message-mode-hook (lambda () (flyspell-mode 1))) + +5.6. Can I set the dictionary based on the group I'm posting to? + + Yes, say something like + + (add-hook 'gnus-select-group-hook + (lambda () + (cond + ((string-match + "^de\\." (gnus-group-real-name gnus-newsgroup-name)) + (ispell-change-dictionary "deutsch8")) + (t + (ispell-change-dictionary "english"))))) + + + in ~/.gnus. Change "^de\\." and "deutsch8" to something that suits + your needs. + +5.7. Is there some kind of address-book, so I needn't remember all those + email addresses? + + There's an very basic solution for this, mail aliases. You can + store your mail addresses in a ~/.mailrc file using a simple alias + syntax: + + alias al "Al <[email protected]>" + + + Then typing your alias (followed by a space or punctuation + character) on a To: or Cc: line in the message buffer will cause + gnus to insert the full address for you. See the node "Mail + Aliases" in Message (not Gnus) manual for details. + + However, what you really want is the Insidious Big Brother Database + bbdb. Get it through the XEmacs package system or from bbdb's + homepage [http://bbdb.sourceforge.net/]. Now place the following in + ~/.gnus, to activate bbdb for Gnus: + + (require 'bbdb) + (bbdb-initialize 'gnus 'message) + + + Now you probably want some general bbdb configuration, place them + in ~/.emacs: + + (require 'bbdb) + ;;If you don't live in Northern America, you should disable the + ;;syntax check for telephone numbers by saying + (setq bbdb-north-american-phone-numbers-p nil) + ;;Tell bbdb about your email address: + (setq bbdb-user-mail-names + (regexp-opt '("[email protected]" + "[email protected]"))) + ;;cycling while completing email addresses + (setq bbdb-complete-name-allow-cycling t) + ;;No popup-buffers + (setq bbdb-use-pop-up nil) + + + Now you should be ready to go. Say M-x bbdb RET RET to open a bbdb + buffer showing all entries. Say c to create a new entry, b to + search your BBDB and C-o to add a new field to an entry. If you + want to add a sender to the BBDB you can also just hit `:' on the + posting in the summary buffer and you are done. When you now + compose a new mail, hit TAB to cycle through know recipients. + +5.8. Sometimes I see little images at the top of article buffer. What's + that and how can I send one with my postings, too? + + Those images are called X-Faces. They are 48*48 pixel b/w pictures, + encoded in a header line. If you want to include one in your posts, + you've got to convert some image to a X-Face. So fire up some image + manipulation program (say Gimp), open the image you want to + include, cut out the relevant part, reduce color depth to 1 bit, + resize to 48*48 and save as bitmap. Now you should get the compface + package from this site [ftp://ftp.cs.indiana.edu:/pub/faces/]. and + create the actual X-face by saying + + cat file.xbm | xbm2ikon |compface > file.face + cat ./file.face | sed 's/\\/\\\\/g' | sed 's/\"/\\\"/g' > ./file.face.quoted + + + if you can't use compface, there's an online X-face converter at + http://www.dairiki.org/xface/ [http://www.dairiki.org/xface/]. If + you use MS Windows, you could also use the WinFace program from + http://www.xs4all.nl/~walterln/winface/ [http://www.xs4all.nl/ + ~walterln/winface/]. Now you only have to tell Gnus to include the + X-face in your postings by saying + + (setq message-default-headers + (with-temp-buffer + (insert "X-Face: ") + (insert-file-contents "~/.xemacs/xface") + (buffer-string))) + + + in ~/.gnus. + +5.9. Sometimes I accidentally hit r instead of f in newsgroups. Can Gnus + warn me, when I'm replying by mail in newsgroups? + + Put this in ~/.gnus: + + (defadvice gnus-summary-reply (around reply-in-news activate) + (interactive) + (when (or (not (gnus-news-group-p gnus-newsgroup-name)) + (y-or-n-p "Really reply? ")) + ad-do-it)) + + + In Oort you can use + + (setq gnus-confirm-mail-reply-to-news t) + + + instead to achieve the same result. + +5.10. How to tell Gnus not to generate a sender header? + + Say + + (eval-after-load "message" + '(add-to-list 'message-syntax-checks '(sender . disabled))) + + + in ~/.gnus. (This is the default behaviour in Oort Gnus.) + +5.11. I want gnus to locally store copies of my send mail and news, how + to do it? + + You must set the variable gnus-message-archive-group to do this. + You can set it to a string giving the name of the group where the + copies shall go or like in the example below use a function which + is evaluated and which returns the group to use. + + (setq gnus-message-archive-group + '((if (message-news-p) + "nnml:Send-News" + "nnml:Send-Mail"))) + + +5.12. People tell me my Message-IDs are not correct, why aren't they and + how to fix it? + + The message-ID is an unique identifier for messages you send. To + make it unique, Gnus need to know which machine name to put after + the "@". If the name of the machine where Gnus is running isn't + suitable (it probably isn't at most private machines) you can tell + Gnus what to use by saying: + + (defun message-make-message-id() + (concat "<"(message-unique-id)"@yourmachine.yourdomain.tld>")) + + + in ~/.gnus. If you have no idea what to insert for + "yourmachine.yourdomain.tld", you've got several choices. You can + either ask your provider if he allows you to use something like + yourUserName.userfqdn.provider.net, or you can use + somethingUnique.yourdomain.tld if you own the domain + yourdomain.tld, or you can register at a service which gives + private users a FQDN for free, e.g. http://www.stura.tu-freiberg.de + /~dlx/addfqdn.html [http://www.stura.tu-freiberg.de/~dlx/ + addfqdn.html]. (Sorry but this website is in German, if you know of + an English one offering the same, drop me a note). + + Finally you can tell Gnus not to generate a Message-ID for News at + all (and letting the server do the job) by saying + + (setq message-required-news-headers + (remove' Message-ID message-required-news-headers)) + + + you can also tell Gnus not to generate Message-IDs for mail by + saying + + (setq message-required-mail-headers + (remove' Message-ID message-required-mail-headers)) + + + , however some mail servers don't generate proper Message-IDs, too, + so test if your Mail Server behaves correctly by sending yourself a + Mail and looking at the Message-ID. + +6. Old messages + +6.1. How to import my old mail into Gnus? + + The easiest way is to tell your old mail program to export the + messages in mbox format. Most Unix mailers are able to do this, if + you come from the MS Windows world, you may find tools at http:// + mbx2mbox.sourceforge.net/ [http://mbx2mbox.sourceforge.net/]. + + Now you've got to import this mbox file into Gnus. To do this, + create a nndoc group based on the mbox file by saying G f /path/ + file.mbox RET in Group buffer. You now have read-only access to + your mail. If you want to import the messages to your normal Gnus + mail groups hierarchy, enter the nndoc group you've just created by + saying C-u RET (thus making sure all messages are retrieved), mark + all messages by saying M P b and either copy them to the desired + group by saying B c name.of.group RET or send them through + nnmail-split-methods (respool them) by saying B r. + +6.2. How to archive interesting messages? + + If you stumble across an interesting message, say in gnu.emacs.gnus + and want to archive it there are several solutions. The first and + easiest is to save it to a file by saying O f. However, wouldn't it + be much more convenient to have more direct access to the archived + message from Gnus? If you say yes, put this snippet by Frank Haun + <[email protected]> in ~/.gnus: + + (defun my-archive-article (&optional n) + "Copies one or more article(s) to a corresponding `nnml:' group, e.g. + `gnus.ding' goes to `nnml:1.gnus.ding'. And `nnml:List-gnus.ding' goes + to `nnml:1.List-gnus-ding'. + + Use process marks or mark a region in the summary buffer to archive + more then one article." + (interactive "P") + (let ((archive-name + (format + "nnml:1.%s" + (if (featurep 'xemacs) + (replace-in-string gnus-newsgroup-name "^.*:" "") + (replace-regexp-in-string "^.*:" "" gnus-newsgroup-name))))) + (gnus-summary-copy-article n archive-name))) + + + You can now say M-x my-archive-article in summary buffer to archive + the article under the cursor in a nnml group. (Change nnml to your + preferred back end) + + Of course you can also make sure the cache is enabled by saying + + (setq gnus-use-cache t) + + + then you only have to set either the tick or the dormant mark for + articles you want to keep, setting the read mark will remove them + from cache. + +6.3. How to search for a specific message? + + There are several ways for this, too. For a posting from a Usenet + group the easiest solution is probably to ask groups.google.com + [http://groups.google.com] (in Oort Gnus you can search + groups.google.com with G W), if you found the posting there, tell + Google to display the raw message, look for the message-id, and say + M-^ [email protected] RET in a summary buffer. + + Another idea which works for both mail and news groups is to enter + the group where the message you are searching is and use the + standard Emacs search C-s, it's smart enough to look at articles in + collapsed threads, too. If you want to search bodies, too try M-s + instead. Further on there are the gnus-summary-limit-to-foo + functions, which can help you, too. + + Of course you can also use grep to search through your local mail, + but this is both slow for big archives and inconvenient since you + are not displaying the found mail in Gnus. Here comes nnir into + action. Nnir is a front end to search engines like swish-e or + swish++ and others. You index your mail with one of those search + engines and with the help of nnir you can search trough the indexed + mail and generate a temporary group with all messages which met + your search criteria. If this sound cool to you get nnir.el from + ftp://ls6-ftp.cs.uni-dortmund.de/pub/src/emacs/ [ftp:// + ls6-ftp.cs.uni-dortmund.de/pub/src/emacs/] or ftp:// + ftp.is.informatik.uni-duisburg.de/pub/src/emacs/ [ftp:// + ftp.is.informatik.uni-duisburg.de/pub/src/emacs/]. Instructions on + how to use it are at the top of the file. + +6.4. How to get rid of old unwanted mail? + + You can of course just mark the mail you don't need anymore by + saying # with point over the mail and then say B DEL to get rid of + them forever. You could also instead of actually deleting them, + send them to a junk-group by saying B m nnml:trash-bin which you + clear from time to time, but both are not the intended way in Gnus. + + In Gnus, we let mail expire like news expires on a news server. + That means you tell Gnus the message is expirable (you tell Gnus "I + don't need this mail anymore") by saying E with point over the mail + in summary buffer. Now when you leave the group, Gnus looks at all + messages which you marked as expirable before and if they are old + enough (default is older than a week) they are deleted. + +6.5. I want that all read messages are expired (at least in some + groups). How to do it? + + If you want all read messages to be expired (e.g. in mailing lists + where there's an online archive), you've got two choices: + auto-expire and total-expire. Auto-expire means, that every article + which has no marks set and is selected for reading is marked as + expirable, Gnus hits E for you every time you read a message. + Total-expire follows a slightly different approach, here all + article where the read mark is set are expirable. + + To activate auto-expire, include auto-expire in the Group + parameters for the group. (Hit G c in summary buffer with point + over the group to change group parameters). For total-expire add + total-expire to the group-parameters. + + Which method you choose is merely a matter of taste: Auto-expire is + faster, but it doesn't play together with Adaptive Scoring, so if + you want to use this feature, you should use total-expire. + + If you want a message to be excluded from expiration in a group + where total or auto expire is active, set either tick (hit u) or + dormant mark (hit u), when you use auto-expire, you can also set + the read mark (hit d). + +6.6. I don't want expiration to delete my mails but to move them to + another group. + + Say something like this in ~/.gnus: + + (setq nnmail-expiry-target "nnml:expired") + + + (If you want to change the value of nnmail-expiry-target on a per + group basis see the question "How can I disable threading in some + (e.g. mail-) groups, or set other variables specific for some + groups?") + +7. Getting help + +7.1. How to find information and help inside Emacs? + + The first stop should be the Gnus manual (Say C-h i d m Gnus RET to + start the Gnus manual, then walk through the menus or do a + full-text search with s). Then there are the general Emacs help + commands starting with C-h, type C-h ? ? to get a list of all + available help commands and their meaning. Finally M-x + apropos-command lets you search through all available functions and + M-x apropos searches the bound variables. + +7.2. I can't find anything in the Gnus manual about X (e.g. attachments, + PGP, MIME...), is it not documented? + + There's not only the Gnus manual but also the manuals for message, + emacs-mime, sieve and (only in Oort Gnus) pgg. Those packages are + distributed with Gnus and used by Gnus but aren't really part of + core Gnus, so they are documented in different info files, you + should have a look in those manuals, too. + +7.3. Which websites should I know? + + The two most important ones are the official Gnus website [http:// + www.gnus.org]. and it's sister site my.gnus.org (MGO) [http:// + my.gnus.org], hosting an archive of lisp snippets, howtos, a (not + really finished) tutorial and this FAQ. + + Tell me about other sites which are interesting. + +7.4. Which mailing lists and newsgroups are there? + + There's the newsgroup gnu.emacs.gnus (pull it from e.g. + news.gnus.org) which deals with general questions and the ding + mailing list ([email protected]) dealing with development of Gnus. You + can read the ding list via NNTP, too under the name gnus.ding from + news.gnus.org. + + If you want to stay in the big8, news.software.newssreaders is also + read by some Gnus users (but chances for qualified help are much + better in the above groups) and if you speak German, there's + de.comm.software.gnus. + +7.5. Where to report bugs? + + Say M-x gnus-bug, this will start a message to the gnus bug mailing + list [mailto:[email protected]] including information about your + environment which make it easier to help you. + +7.6. I need real-time help, where to find it? + + Point your IRC client to irc.my.gnus.org channel #mygnus. Don't be + afraid if people there speak German, they are willing and capable + of switching to English when people from outside Germany enter. + +8. Tuning Gnus + +8.1. Starting Gnus is really slow, how to speed it up? + + The reason for this could be the way Gnus reads it's active file, + see the node "The Active File" in the Gnus manual for things you + might try to speed the process up. An other idea would be to byte + compile your ~/.gnus (say M-x byte-compile-file RET ~/.gnus RET to + do it). Finally, if you have require statements in your .gnus, you + could replace them with eval-after-load, which loads the stuff not + at startup time, but when it's needed. Say you've got this in your + ~/.gnus: + + (require 'message) + (add-to-list 'message-syntax-checks '(sender . disabled)) + + + then as soon as you start Gnus, message.el is loaded. If you + replace it with + + (eval-after-load "message" + '(add-to-list 'message-syntax-checks '(sender . disabled))) + + + it's loaded when it's needed. + +8.2. How to speed up the process of entering a group? + + A speed killer is setting the variable gnus-fetch-old-headers to + anything different from nil, so don't do this if speed is an issue. + To speed up building of summary say + + (gnus-compile) + + + at the bottom of your ~/.gnus, this will make gnus byte-compile + things like gnus-summary-line-format. then you could increase the + value of gc-cons-threshold by saying something like + + (setq gc-cons-threshold 3500000) + + + in ~/.emacs. If you don't care about width of CJK characters or use + Oort Gnus together with a recent GNU Emacs, you should say + + (setq gnus-use-correct-string-widths nil) + + + in ~/.gnus (thanks to Jesper harder for the last two suggestions). + Finally if this also doesn't help, you might want to jump in the + cold water and try Oort Gnus, there some work has been done to + speed up summary generation. Read and remember the warnings about + Oort at the top of this FAQ. + +8.3. Sending mail becomes slower and slower, what's up? + + The reason could be that you told Gnus to archive the messages you + wrote by setting gnus-message-archive-group. Try to use a nnml + group instead of an archive group, this should bring you back to + normal speed. + +Glossary + +~/.gnus + + When the term ~/.gnus is used it just means your Gnus + configuration file. You might as well call it ~/.gnus.el or + specify another name. + +Back End + + In Gnus terminology a back end is a virtual server, a layer + between core Gnus and the real NNTP-, POP3-, IMAP- or + whatever-server which offers Gnus a standardized interface to + functions like "get message", "get Headers" etc. + +Emacs + + When the term Emacs is used in this FAQ, it means either GNU + Emacs or XEmacs. + +Message + + In this FAQ message means a either a mail or a posting to a + Usenet Newsgroup or to some other fancy back end, no matter of + which kind it is. + +MUA + + MUA is an acronym for Mail User Agent, it's the program you use + to read and write e-mails. + +NUA + + NUA is an acronym for News User Agent, it's the program you use + to read and write Usenet news. + Index: gnus/lisp/ChangeLog diff -u gnus/lisp/ChangeLog:6.2114 gnus/lisp/ChangeLog:6.2171 --- gnus/lisp/ChangeLog:6.2114 Tue Mar 18 00:38:33 2003 +++ gnus/lisp/ChangeLog Mon Mar 31 20:08:31 2003 @@ -1,3 +1,373 @@ +2003-03-31 20:08:19 Lars Magne Ingebrigtsen <[email protected]> + + * gnus.el: Oort Gnus v0.17 is released. + +2003-03-31 Lars Magne Ingebrigtsen <[email protected]> + + * gnus-start.el (gnus-unload): Removed. + + * pop3.el (pop3-read-response): Use + nnheader-accept-process-output. + (pop3-retr): Ditto. + + * mm-view.el (mm-text-html-renderer-alist): Add -nolist to Lynx. + (mm-text-html-washer-alist): Ditto. + +2003-03-31 Simon Josefsson <[email protected]> + + * imap.el (imap-gssapi-program): Also try GNU SASL. + (imap-gssapi-open): Accept GNU SASL greeting. + (imap-read-timeout): New. + (imap-wait-for-tag): Use it. + +2003-03-31 Lars Magne Ingebrigtsen <[email protected]> + + * nntp.el (nntp-accept-process-output): Use new function. + + * nnheader.el (nnheader-read-timeout): New variable. + (nnheader-accept-process-output): New function. + + * nntp.el (nntp-read-timeout): Removed. + + * gnus-sum.el (gnus-summary-prepare-threads): Add comment. + +2003-03-30 Katsumi Yamaoka <[email protected]> + + * gnus-cache.el (gnus-cache-braid-nov): Revoke last change. + +2003-03-30 Simon Josefsson <[email protected]> + + * message.el (message-idna-inside-rhs-p): Narrow to header before + searching. + + * gnus-art.el (article-decode-idna-rhs): More restrictive regexp. + +2003-03-30 Lars Magne Ingebrigtsen <[email protected]> + + * nnmail.el (nnmail-process-mmdf-mail-format): Indent. + +2003-03-28 Vasily Korytov <[email protected]> + + * message.el (message-make-in-reply-to): Use + mail-extract-address-components to dentermine sender's + name/address. + +2003-03-30 Lars Magne Ingebrigtsen <[email protected]> + + * nndoc.el (nndoc-type-alist): Move mime-parts further ahead. + + * gnus-registry.el (gnus-registry-translate-to-alist): Make a + valid lambda. + (gnus-registry-translate-from-alist): Ditto. + + * gnus-start.el (gnus-gnus-to-quick-newsrc-format): Bind + print-length to nil. + + * gnus-sum.el (gnus-summary-highlight-line-0): Indent. + + * gnus-fun.el (gnus-fun-ppm-change-string): New function. + (gnus-grab-cam-face): Use it. + +2003-03-28 Paul Jarc <[email protected]> + + * nnmaildir.el (nnmaildir-request-set-mark, + nnmaildir-close-group): Allow each mark directory in a group to + have its own inode for mark files, to accommodate AFS. + +2003-03-28 Teodor Zlatanov <[email protected]> + + * gnus-start.el (gnus-read-newsrc-el-hook): new hook called by gnus-read-newsrc-el-file + (gnus-read-newsrc-el-file): call the gnus-read-newsrc-el-hook + + * gnus-registry.el (gnus-registry-translate-to-alist) + (gnus-registry-translate-from-alist, alist-to-hashtable) + (hashtable-to-alist): new functions + (gnus-register-spool-action): add a spool item to the registry + + * gnus.el (gnus-variable-list): added gnus-registry-alist to the + list of saved variables + (gnus-registry-alist): new variable + +2003-03-27 Simon Josefsson <[email protected]> + + * gnus-art.el (article-decode-group-name): Be correct instead of + smart. + +2003-03-27 Katsumi Yamaoka <[email protected]> + + * lpath.el: Bind url-current-object for FSF Emacs; bind + gnus-agent-expire-current-dirs for XEmacs; fbind open-ssl-stream + for both Emacsen. + +2003-03-27 Jesper Harder <[email protected]> + + * gnus-sum.el (gnus-article-loose-mime) + (gnus-article-emulate-mime): Move to gnus-article-mime customize + group. + + * gnus-msg.el (gnus-mailing-list-groups): Fix customize type and + doc string. + +2003-03-26 Kevin Ryde <[email protected]> + + * gnus-sum.el (gnus-summary-find-for-reselect): Renamed from + gnus-summary-find-uncancelled, skip temporary articles inserted by + "refer" functions. + +2003-03-26 Vasily Korytov <[email protected]> + + * smiley.el (smiley-buffer): New function. + +2003-03-26 Kevin Greiner <[email protected]> + + * gnus-agent.el (gnus-agent-fetch-selected-article): Replaced + gnus-summary-update-line (which updated the article's face) with + gnus-summary-update-download-mark (which updates the article's + face by calling gnus-summary-update-line AND updates the download + mark to show that the article was fetched). + +2003-03-23 Kevin Greiner <[email protected]> + + * gnus-agent.el (gnus-agent-expire-unagentized-dirs): Provides + option of deleting agent directories for groups/servers that are + not currently agentized. + (gnus-agent-expire): Use gnus-agent-expire-unagentized-dirs. + + * gnus-int.el (gnus-open-server): Report backend errors in + condition handler. + +2003-03-23 Simon Josefsson <[email protected]> + + * message.el (message-idna-to-ascii-rhs-1): Don't continue outside + header. + + * rfc2047.el (rfc2047-header-encoding-alist): Make Followup-To + same as Newsgroups. + + * nntp.el (nntp-open-connection-function): Mention + nntp-open-tls-stream. + (nntp-open-tls-stream): New function. + + * tls.el: New file. + + * nnimap.el (nnimap-server-port, nnimap-stream): Say TLS/SSL + instead of SSL. + (nnimap-stream): Add other streams, link to imap variables. + (nnimap-authenticator): Add other authenticator, link to imap + variables. + + * imap.el: Autoload open-tls-stream. + (imap-streams): Add tls in front of ssl. + (imap-stream-alist): Add tls. + (imap-default-tls-port): New variable. + (imap-tls-p, imap-tls-open): New functions. + +2003-03-22 ShengHuo ZHU <[email protected]> + + * mm-url.el (mm-url-insert-file-contents): parse url only if + results is a list. + +2003-03-22 Lars Magne Ingebrigtsen <[email protected]> + + * mail-source.el (mail-source-fetch-imap): Revert. + +2003-03-22 Svend Tollak Munkejord <[email protected]> + + * deuglify.el (gnus-outlook-repair-attribution-outlook): Use a + less strict regexp. + +2003-03-22 Lars Magne Ingebrigtsen <[email protected]> + + * mail-source.el (mail-source-fetch-imap): Use buffer name for + more imap function. + +2003-03-21 Simon Josefsson <[email protected]> + + * gnus-art.el (article-decode-group-name): Replace Newsgroups and + Followup-To data inline. + +2003-03-21 Jesper Harder <[email protected]> + + * gnus-art.el (gnus-treat-display-xface): Don't enable if + icontopbm isn't available. + +2003-03-21 Kevin Greiner <[email protected]> + + * gnus-int.el (gnus-open-server): Catch errors in backend's + open-server method. Returns nil rather than crashing startup. + + * gnus-sum.el (eval-when-compile): Modified to resolve + compile-time warnings. + + * gnus-uu.el (gnus-uu-mark-series): Added informative msg. + Reports length of series so that the user can compare N with a + subject that should, if the entire series is present, contain + '(.../N)'. + (gnus-uu-delete-work-dir): Avoid hanging when O/S forbids deletion + of temp file (Win-XP may leave the temp file locked when the + uudecode process fails). + +2003-03-20 ShengHuo ZHU <[email protected]> + + * message.el (message-split-line): Ignore error. + + * lpath.el (split-line): Avoid split-line warning message. + +2003-03-20 Kim F. Storm <[email protected]> + + * message.el (message-split-line): New function. + (message-mode-map): Remap split-line to message-split-line. + +2003-03-20 Katsumi Yamaoka <[email protected]> + + * message.el (message-make-overlay): Defalias it to make-overlay. + (message-delete-overlay): Defalias it to delete-overlay. + (message-overlay-put): Defalias it to overlay-put. + (message-idna-to-ascii-rhs-1): Use them. + + * messagexmas.el (message-xmas-redefine): Defalias some overlay + functions to extent functions. + +2003-03-20 Reiner Steib <[email protected]> + + * message.el (message-check-news-header-syntax): Fixed regexp. + +2003-03-20 ShengHuo ZHU <[email protected]> + + * rfc2231.el (rfc2231-decode-encoded-string): Downcase charset. + + * mm-url.el (mm-url-insert): Move url-current-object stuff into + mm-url-insert-file-contents. + + * nnrss.el (nnrss-fetch): Fetch the local stuff. + (nnrss-check-group): Use it. + +2003-03-20 Mark A. Hershberger <[email protected]> + + * nnrss.el: Primitive XML Name-space support. This means that RSS + feeds like Kevin Burton's[1] can now be read in Gnus. + + Implemented support for Mark Pilgrim's RSS Autodiscovery.[2] This + means that if you want to read the RSS feed for example.com, all + you have to do is hit "G R http://www.example.com/ RET" and + nnrss.el will find and the feed listed on the site or (if you have + loaded xml-rpc.el) look it up on syndic8.com. + + Marked the message as HTML (by adding a Content-Type header) so + that Gnus will render it as html if the user wants that. + + Implemented the ability to save nnrss-group-alist so that any new + feeds the you subscribe to will be found the next time you start + up. + + Implemented support for RSS 2.0 elements (author, pubDate). + + Prefer for <content:encoded> over <description> where both + elements exist. + + * mm-url.el (mm-url-insert): Set url-current-object. + + * gnus-group.el (gnus-group-make-rss-group): New function. + +2003-03-20 Katsumi Yamaoka <[email protected]> + + * message.el (message-idna-to-ascii-rhs-1): Don't use replace-* + for highlight overlays. + +2003-03-20 Katsumi Yamaoka <[email protected]> + + * gnus-cache.el (gnus-cache-braid-nov): Test if a line looks like + a NOV. + +2003-03-20 Simon Josefsson <[email protected]> + + * message.el (message-use-idna): Disable if UTF-8 unavailable. + (message-idna-to-ascii-rhs): Use it. + + * gnus-art.el (gnus-use-idna): Disable if UTF-8 unavailable. + +2003-03-19 Teodor Zlatanov <[email protected]> + + * spam.el (spam-group-ham-mark-p, spam-group-spam-mark-p) + (spam-group-ham-marks, spam-group-spam-marks): new functions + (spam-spam-marks, spam-ham-marks): removed in favor of the + spam-marks and ham-marks parameters + (spam-generic-register-routine, spam-ham-move-routine): use the + new spam-group-{spam,ham}-mark-p functions + + * gnus.el (spam-marks, ham-marks): new group parameters with + default values same as the old spam-spam-marks and spam-ham-marks + +2003-03-19 Simon Josefsson <[email protected]> + + * gnus-art.el (gnus-article-decode-hook): Add IDNA. + (gnus-use-idna): New variable. + (article-decode-idna-rhs): New function. + + * message.el (message-use-idna): New variable. + (message-mode-field-menu): Add entry for IDNA. + (message-idna-inside-rhs-p, message-idna-to-ascii-rhs-1) + (message-idna-to-ascii-rhs): New function. + (message-generate-headers): Invoke IDNA code. + +2003-03-19 Paul Jarc <[email protected]> + + * nnmaildir.el (nnmaildir--system-name): New function. + (nnmaildir-request-accept-article): Use it. + +2003-03-19 Katsumi Yamaoka <[email protected]> + + * gnus-util.el (gnus-byte-compile): Make it work silently as the + gnus-compile function does. + + * gnus-sum.el (gnus-summary-highlight-line-0): Revoke the last + bogus change. + +2003-03-19 Jesper Harder <[email protected]> + + * mm-util.el (mm-mule-charset-to-mime-charset): Test if + sort-coding-systems is defined. + +2003-03-18 Paul Jarc <[email protected]> + + * nnmaildir.el (nnmaildir-open-server, + nnmaildir-request-scan, + nnmaildir-request-create-group, + nnmaildir-request-delete-group): Replace create-directory with + target-prefix. + +2003-03-18 Jesper Harder <[email protected]> + + * mm-bodies.el (mm-decode-coding-region-safely): Don't use + find-charset-region which is slooow in XEmacs. + +2003-03-18 Katsumi Yamaoka <[email protected]> + + * gnus-sum.el (gnus-summary-highlight-line-0): Silence the byte- + compiler under XEmacs. + +2003-03-18 Jesper Harder <[email protected]> + + * gnus-art.el (gnus-treat-highlight-signature): Make the default + work for multipart/signed where the message text isn't `last'. + +2003-03-18 Katsumi Yamaoka <[email protected]> + + * mm-view.el (mm-setup-w3m): Set w3m-display-inline-images to + the value of mm-inline-text-html-with-images. + (mm-inline-text-html-render-with-w3m): Don't bind + w3m-display-inline-images. + + * gnus-art.el (gnus-article-wash-html-with-w3m): Don't bind + w3m-display-inline-images. + + * lpath.el: Bind w3m-display-inline-images; bind mm-w3m-mode-map + regardless of an Emacs flavor. + +2003-03-18 Lars Magne Ingebrigtsen <[email protected]> + + * gnus.el (gnus-version-number): Bump. + 2003-03-18 00:38:22 Lars Magne Ingebrigtsen <[email protected]> * gnus.el: Oort Gnus v0.16 is released. @@ -6,7 +376,7 @@ * lpath.el (featurep): Bind mm-w3m-mode-map. -2003-03-12 Paul Jarc <[email protected]> +2003-03-17 Paul Jarc <[email protected]> * nnmail.el (nnmail-cache-primary-mail-backend): Not all 'respool-able backends define a global nnchoke-get-new-mail Index: gnus/lisp/deuglify.el diff -u gnus/lisp/deuglify.el:6.10 gnus/lisp/deuglify.el:6.11 --- gnus/lisp/deuglify.el:6.10 Sat Feb 8 22:20:53 2003 +++ gnus/lisp/deuglify.el Sat Mar 22 19:33:23 2003 @@ -388,7 +388,7 @@ (gnus-with-article-buffer (article-goto-body) (if (re-search-forward - (concat "^[" cite-marks " \t]*----* ?[^-]+ [^-]+ ?----*\n" + (concat "^[" cite-marks " \t]*--* ?[^-]+ [^-]+ ?--*\\s *\n" "[^\n:]+:[ \t]*\\([^\n]+\\)\n" "\\([^\n:]+:[ \t]*[^\n]+\n\\)+") nil t) Index: gnus/lisp/gnus-agent.el diff -u gnus/lisp/gnus-agent.el:6.158 gnus/lisp/gnus-agent.el:6.160 --- gnus/lisp/gnus-agent.el:6.158 Mon Mar 10 01:08:24 2003 +++ gnus/lisp/gnus-agent.el Wed Mar 26 20:33:27 2003 @@ -1017,7 +1017,7 @@ (list gnus-current-article)) (setq gnus-newsgroup-undownloaded (delq gnus-current-article gnus-newsgroup-undownloaded)) - (gnus-summary-update-line gnus-current-article))))) + (gnus-summary-update-download-mark gnus-current-article))))) ;;; ;;; Internal functions @@ -2430,309 +2430,316 @@ ;; gnus-command-method, initialized overview buffer, and to have ;; provided a non-nil active - (if (eq 'DISABLE (gnus-agent-find-parameter group 'agent-enable-expiration)) - (gnus-message 5 "Expiry skipping over %s" group) - (gnus-message 5 "Expiring articles in %s" group) - (gnus-agent-load-alist group) - (let* ((info (gnus-get-info group)) - (alist gnus-agent-article-alist) - (dir (concat - (gnus-agent-directory) - (gnus-agent-group-path group) - "/")) - (day (- (time-to-days (current-time)) - (gnus-agent-find-parameter group 'agent-days-until-old))) - (specials (if (and alist - (not force)) - ;; This could be a bit of a problem. I need to - ;; keep the last article to avoid refetching - ;; headers when using nntp in the backend. At - ;; the same time, if someone uses a backend - ;; that supports article moving then I may have - ;; to remove the last article to complete the - ;; move. Right now, I'm going to assume that - ;; FORCE overrides specials. - (list (caar (last alist))))) - (unreads ;; Articles that are excluded from the - ;; expiration process - (cond (gnus-agent-expire-all - ;; All articles are marked read by global decree - nil) - ((eq articles t) - ;; All articles are marked read by function - ;; parameter - nil) - ((not articles) - ;; Unread articles are marked protected from - ;; expiration Don't call - ;; gnus-list-of-unread-articles as it returns - ;; articles that have not been fetched into the - ;; agent. - (ignore-errors - (gnus-agent-unread-articles group))) - (t - ;; All articles EXCEPT those named by the caller - ;; are protected from expiration - (gnus-sorted-difference - (gnus-uncompress-range - (cons (caar alist) - (caar (last alist)))) - (sort articles '<))))) - (marked ;; More articles that are exluded from the - ;; expiration process - (cond (gnus-agent-expire-all - ;; All articles are unmarked by global decree - nil) - ((eq articles t) - ;; All articles are unmarked by function - ;; parameter - nil) - (articles - ;; All articles may as well be unmarked as the - ;; unreads list already names the articles we are - ;; going to keep - nil) - (t - ;; Ticked and/or dormant articles are excluded - ;; from expiration - (nconc - (gnus-uncompress-range - (cdr (assq 'tick (gnus-info-marks info)))) - (gnus-uncompress-range - (cdr (assq 'dormant - (gnus-info-marks info)))))))) - (nov-file (concat dir ".overview")) - (cnt 0) - (completed -1) - dlist - type) - - ;; The normal article alist contains elements that look like - ;; (article# . fetch_date) I need to combine other - ;; information with this list. For example, a flag indicating - ;; that a particular article MUST BE KEPT. To do this, I'm - ;; going to transform the elements to look like (article# - ;; fetch_date keep_flag NOV_entry_marker) Later, I'll reverse - ;; the process to generate the expired article alist. - - ;; Convert the alist elements to (article# fetch_date nil - ;; nil). - (setq dlist (mapcar (lambda (e) - (list (car e) (cdr e) nil nil)) alist)) - - ;; Convert the keep lists to elements that look like (article# - ;; nil keep_flag nil) then append it to the expanded dlist - ;; These statements are sorted by ascending precidence of the - ;; keep_flag. - (setq dlist (nconc dlist - (mapcar (lambda (e) - (list e nil 'unread nil)) - unreads))) - (setq dlist (nconc dlist - (mapcar (lambda (e) - (list e nil 'marked nil)) - marked))) - (setq dlist (nconc dlist - (mapcar (lambda (e) - (list e nil 'special nil)) - specials))) - - (set-buffer overview) - (erase-buffer) - (buffer-disable-undo) - (when (file-exists-p nov-file) - (gnus-message 7 "gnus-agent-expire: Loading overview...") - (nnheader-insert-file-contents nov-file) - (goto-char (point-min)) - - (let (p) - (while (< (setq p (point)) (point-max)) - (condition-case nil - ;; If I successfully read an integer (the plus zero - ;; ensures a numeric type), prepend a marker entry - ;; to the list - (push (list (+ 0 (read (current-buffer))) nil nil - (set-marker (make-marker) p)) - dlist) - (error - (gnus-message 1 "gnus-agent-expire: read error \ + (let ((dir (concat + (gnus-agent-directory) + (gnus-agent-group-path group) + "/"))) + (when (boundp 'gnus-agent-expire-current-dirs) + (set 'gnus-agent-expire-current-dirs + (cons dir + (symbol-value 'gnus-agent-expire-current-dirs)))) + + (if (eq 'DISABLE (gnus-agent-find-parameter group + 'agent-enable-expiration)) + (gnus-message 5 "Expiry skipping over %s" group) + (gnus-message 5 "Expiring articles in %s" group) + (gnus-agent-load-alist group) + (let* ((info (gnus-get-info group)) + (alist gnus-agent-article-alist) + (day (- (time-to-days (current-time)) + (gnus-agent-find-parameter group 'agent-days-until-old))) + (specials (if (and alist + (not force)) + ;; This could be a bit of a problem. I need to + ;; keep the last article to avoid refetching + ;; headers when using nntp in the backend. At + ;; the same time, if someone uses a backend + ;; that supports article moving then I may have + ;; to remove the last article to complete the + ;; move. Right now, I'm going to assume that + ;; FORCE overrides specials. + (list (caar (last alist))))) + (unreads ;; Articles that are excluded from the + ;; expiration process + (cond (gnus-agent-expire-all + ;; All articles are marked read by global decree + nil) + ((eq articles t) + ;; All articles are marked read by function + ;; parameter + nil) + ((not articles) + ;; Unread articles are marked protected from + ;; expiration Don't call + ;; gnus-list-of-unread-articles as it returns + ;; articles that have not been fetched into the + ;; agent. + (ignore-errors + (gnus-agent-unread-articles group))) + (t + ;; All articles EXCEPT those named by the caller + ;; are protected from expiration + (gnus-sorted-difference + (gnus-uncompress-range + (cons (caar alist) + (caar (last alist)))) + (sort articles '<))))) + (marked ;; More articles that are exluded from the + ;; expiration process + (cond (gnus-agent-expire-all + ;; All articles are unmarked by global decree + nil) + ((eq articles t) + ;; All articles are unmarked by function + ;; parameter + nil) + (articles + ;; All articles may as well be unmarked as the + ;; unreads list already names the articles we are + ;; going to keep + nil) + (t + ;; Ticked and/or dormant articles are excluded + ;; from expiration + (nconc + (gnus-uncompress-range + (cdr (assq 'tick (gnus-info-marks info)))) + (gnus-uncompress-range + (cdr (assq 'dormant + (gnus-info-marks info)))))))) + (nov-file (concat dir ".overview")) + (cnt 0) + (completed -1) + dlist + type) + + ;; The normal article alist contains elements that look like + ;; (article# . fetch_date) I need to combine other + ;; information with this list. For example, a flag indicating + ;; that a particular article MUST BE KEPT. To do this, I'm + ;; going to transform the elements to look like (article# + ;; fetch_date keep_flag NOV_entry_marker) Later, I'll reverse + ;; the process to generate the expired article alist. + + ;; Convert the alist elements to (article# fetch_date nil + ;; nil). + (setq dlist (mapcar (lambda (e) + (list (car e) (cdr e) nil nil)) alist)) + + ;; Convert the keep lists to elements that look like (article# + ;; nil keep_flag nil) then append it to the expanded dlist + ;; These statements are sorted by ascending precidence of the + ;; keep_flag. + (setq dlist (nconc dlist + (mapcar (lambda (e) + (list e nil 'unread nil)) + unreads))) + (setq dlist (nconc dlist + (mapcar (lambda (e) + (list e nil 'marked nil)) + marked))) + (setq dlist (nconc dlist + (mapcar (lambda (e) + (list e nil 'special nil)) + specials))) + + (set-buffer overview) + (erase-buffer) + (buffer-disable-undo) + (when (file-exists-p nov-file) + (gnus-message 7 "gnus-agent-expire: Loading overview...") + (nnheader-insert-file-contents nov-file) + (goto-char (point-min)) + + (let (p) + (while (< (setq p (point)) (point-max)) + (condition-case nil + ;; If I successfully read an integer (the plus zero + ;; ensures a numeric type), prepend a marker entry + ;; to the list + (push (list (+ 0 (read (current-buffer))) nil nil + (set-marker (make-marker) p)) + dlist) + (error + (gnus-message 1 "gnus-agent-expire: read error \ occurred when reading expression at %s in %s. Skipping to next \ line." (point) nov-file))) - ;; Whether I succeeded, or failed, it doesn't matter. - ;; Move to the next line then try again. - (forward-line 1))) - (gnus-message - 7 "gnus-agent-expire: Loading overview... Done")) - (set-buffer-modified-p nil) - - ;; At this point, all of the information is in dlist. The - ;; only problem is that much of it is spread across multiple - ;; entries. Sort then MERGE!! - (gnus-message 7 "gnus-agent-expire: Sorting entries... ") - ;; If two entries have the same article-number then sort by - ;; ascending keep_flag. - (let ((special 0) - (marked 1) - (unread 2)) - (setq dlist - (sort dlist - (lambda (a b) - (cond ((< (nth 0 a) (nth 0 b)) - t) - ((> (nth 0 a) (nth 0 b)) - nil) - (t - (let ((a (or (symbol-value (nth 2 a)) - 3)) - (b (or (symbol-value (nth 2 b)) - 3))) - (<= a b)))))))) - (gnus-message 7 "gnus-agent-expire: Sorting entries... Done") - (gnus-message 7 "gnus-agent-expire: Merging entries... ") - (let ((dlist dlist)) - (while (cdr dlist) ; I'm not at the end-of-list - (if (eq (caar dlist) (caadr dlist)) - (let ((first (cdr (car dlist))) - (secnd (cdr (cadr dlist)))) - (setcar first (or (car first) - (car secnd))) ; fetch_date - (setq first (cdr first) - secnd (cdr secnd)) - (setcar first (or (car first) - (car secnd))) ; Keep_flag - (setq first (cdr first) - secnd (cdr secnd)) - (setcar first (or (car first) - (car secnd))) ; NOV_entry_marker - - (setcdr dlist (cddr dlist))) - (setq dlist (cdr dlist))))) - (gnus-message 7 "gnus-agent-expire: Merging entries... Done") - - (let* ((len (float (length dlist))) - (alist (list nil)) - (tail-alist alist)) - (while dlist - (let ((new-completed (truncate (* 100.0 - (/ (setq cnt (1+ cnt)) - len))))) - (when (> new-completed completed) - (setq completed new-completed) - (gnus-message 7 "%3d%% completed..." completed))) - (let* ((entry (car dlist)) - (article-number (nth 0 entry)) - (fetch-date (nth 1 entry)) - (keep (nth 2 entry)) - (marker (nth 3 entry))) - - (cond - ;; Kept articles are unread, marked, or special. - (keep - (gnus-agent-message 10 - "gnus-agent-expire: Article %d: Kept %s article." - article-number keep) - (when fetch-date - (unless (file-exists-p - (concat dir (number-to-string - article-number))) - (setf (nth 1 entry) nil) - (gnus-agent-message 3 "gnus-agent-expire cleared \ + ;; Whether I succeeded, or failed, it doesn't matter. + ;; Move to the next line then try again. + (forward-line 1))) + + (gnus-message + 7 "gnus-agent-expire: Loading overview... Done")) + (set-buffer-modified-p nil) + + ;; At this point, all of the information is in dlist. The + ;; only problem is that much of it is spread across multiple + ;; entries. Sort then MERGE!! + (gnus-message 7 "gnus-agent-expire: Sorting entries... ") + ;; If two entries have the same article-number then sort by + ;; ascending keep_flag. + (let ((special 0) + (marked 1) + (unread 2)) + (setq dlist + (sort dlist + (lambda (a b) + (cond ((< (nth 0 a) (nth 0 b)) + t) + ((> (nth 0 a) (nth 0 b)) + nil) + (t + (let ((a (or (symbol-value (nth 2 a)) + 3)) + (b (or (symbol-value (nth 2 b)) + 3))) + (<= a b)))))))) + (gnus-message 7 "gnus-agent-expire: Sorting entries... Done") + (gnus-message 7 "gnus-agent-expire: Merging entries... ") + (let ((dlist dlist)) + (while (cdr dlist) ; I'm not at the end-of-list + (if (eq (caar dlist) (caadr dlist)) + (let ((first (cdr (car dlist))) + (secnd (cdr (cadr dlist)))) + (setcar first (or (car first) + (car secnd))) ; fetch_date + (setq first (cdr first) + secnd (cdr secnd)) + (setcar first (or (car first) + (car secnd))) ; Keep_flag + (setq first (cdr first) + secnd (cdr secnd)) + (setcar first (or (car first) + (car secnd))) ; NOV_entry_marker + + (setcdr dlist (cddr dlist))) + (setq dlist (cdr dlist))))) + (gnus-message 7 "gnus-agent-expire: Merging entries... Done") + + (let* ((len (float (length dlist))) + (alist (list nil)) + (tail-alist alist)) + (while dlist + (let ((new-completed (truncate (* 100.0 + (/ (setq cnt (1+ cnt)) + len))))) + (when (> new-completed completed) + (setq completed new-completed) + (gnus-message 7 "%3d%% completed..." completed))) + (let* ((entry (car dlist)) + (article-number (nth 0 entry)) + (fetch-date (nth 1 entry)) + (keep (nth 2 entry)) + (marker (nth 3 entry))) + + (cond + ;; Kept articles are unread, marked, or special. + (keep + (gnus-agent-message 10 + "gnus-agent-expire: Article %d: Kept %s article." + article-number keep) + (when fetch-date + (unless (file-exists-p + (concat dir (number-to-string + article-number))) + (setf (nth 1 entry) nil) + (gnus-agent-message 3 "gnus-agent-expire cleared \ download flag on article %d as the cached article file is missing." - (caar dlist))) - (unless marker - (gnus-message 1 "gnus-agent-expire detected a \ + (caar dlist))) + (unless marker + (gnus-message 1 "gnus-agent-expire detected a \ missing NOV entry. Run gnus-agent-regenerate-group to restore it."))) - (gnus-agent-append-to-list - tail-alist - (cons article-number fetch-date))) - - ;; The following articles are READ, UNMARKED, and - ;; ORDINARY. See if they can be EXPIRED!!! - ((setq type - (cond - ((not (integerp fetch-date)) - 'read) ;; never fetched article (may expire - ;; right now) - ((not (file-exists-p - (concat dir (number-to-string - article-number)))) - (setf (nth 1 entry) nil) - 'externally-expired) ;; Can't find the cached - ;; article. Handle case - ;; as though this article - ;; was never fetched. - - ;; We now have the arrival day, so we see - ;; whether it's old enough to be expired. - ((< fetch-date day) - 'expired) - (force - 'forced))) - - ;; I found some reason to expire this entry. - - (let ((actions nil)) - (when (memq type '(forced expired)) - (ignore-errors ; Just being paranoid. - (delete-file (concat dir (number-to-string - article-number))) - (push "expired cached article" actions)) - (setf (nth 1 entry) nil) - ) - - (when marker - (push "NOV entry removed" actions) - (goto-char marker) - (gnus-delete-line)) - - ;; If considering all articles is set, I can only - ;; expire article IDs that are no longer in the - ;; active range. - (if (and gnus-agent-consider-all-articles - (>= article-number (car active))) - ;; I have to keep this ID in the alist - (gnus-agent-append-to-list - tail-alist (cons article-number fetch-date)) - (push (format "Removed %s article number from \ + (gnus-agent-append-to-list + tail-alist + (cons article-number fetch-date))) + + ;; The following articles are READ, UNMARKED, and + ;; ORDINARY. See if they can be EXPIRED!!! + ((setq type + (cond + ((not (integerp fetch-date)) + 'read) ;; never fetched article (may expire + ;; right now) + ((not (file-exists-p + (concat dir (number-to-string + article-number)))) + (setf (nth 1 entry) nil) + 'externally-expired) ;; Can't find the cached + ;; article. Handle case + ;; as though this article + ;; was never fetched. + + ;; We now have the arrival day, so we see + ;; whether it's old enough to be expired. + ((< fetch-date day) + 'expired) + (force + 'forced))) + + ;; I found some reason to expire this entry. + + (let ((actions nil)) + (when (memq type '(forced expired)) + (ignore-errors ; Just being paranoid. + (delete-file (concat dir (number-to-string + article-number))) + (push "expired cached article" actions)) + (setf (nth 1 entry) nil) + ) + + (when marker + (push "NOV entry removed" actions) + (goto-char marker) + (gnus-delete-line)) + + ;; If considering all articles is set, I can only + ;; expire article IDs that are no longer in the + ;; active range. + (if (and gnus-agent-consider-all-articles + (>= article-number (car active))) + ;; I have to keep this ID in the alist + (gnus-agent-append-to-list + tail-alist (cons article-number fetch-date)) + (push (format "Removed %s article number from \ article alist" type) actions)) - (gnus-agent-message 8 "gnus-agent-expire: Article %d: %s" - article-number - (mapconcat 'identity actions ", ")))) - (t - (gnus-agent-message - 10 "gnus-agent-expire: Article %d: Article kept as \ + (gnus-agent-message 8 "gnus-agent-expire: Article %d: %s" + article-number + (mapconcat 'identity actions ", ")))) + (t + (gnus-agent-message + 10 "gnus-agent-expire: Article %d: Article kept as \ expiration tests failed." article-number) - (gnus-agent-append-to-list - tail-alist (cons article-number fetch-date))) - ) - - ;; Clean up markers as I want to recycle this buffer - ;; over several groups. - (when marker - (set-marker marker nil)) - - (setq dlist (cdr dlist)))) - - (setq alist (cdr alist)) - - (let ((inhibit-quit t)) - (unless (equal alist gnus-agent-article-alist) - (setq gnus-agent-article-alist alist) - (gnus-agent-save-alist group)) - - (when (buffer-modified-p) - (let ((coding-system-for-write - gnus-agent-file-coding-system)) - (gnus-make-directory dir) - (write-region (point-min) (point-max) nov-file nil - 'silent) - ;; clear the modified flag as that I'm not confused by - ;; its status on the next pass through this routine. - (set-buffer-modified-p nil))) + (gnus-agent-append-to-list + tail-alist (cons article-number fetch-date))) + ) - (when (eq articles t) - (gnus-summary-update-info))))))) + ;; Clean up markers as I want to recycle this buffer + ;; over several groups. + (when marker + (set-marker marker nil)) + + (setq dlist (cdr dlist)))) + + (setq alist (cdr alist)) + + (let ((inhibit-quit t)) + (unless (equal alist gnus-agent-article-alist) + (setq gnus-agent-article-alist alist) + (gnus-agent-save-alist group)) + + (when (buffer-modified-p) + (let ((coding-system-for-write + gnus-agent-file-coding-system)) + (gnus-make-directory dir) + (write-region (point-min) (point-max) nov-file nil + 'silent) + ;; clear the modified flag as that I'm not confused by + ;; its status on the next pass through this routine. + (set-buffer-modified-p nil))) + + (when (eq articles t) + (gnus-summary-update-info)))))))) (defun gnus-agent-expire (&optional articles group force) "Expire all old articles. @@ -2753,6 +2760,9 @@ (yes-or-no-p "Are you sure that you want to expire all \ articles in every agentized group.")) (let ((methods gnus-agent-covered-methods) + ;; Bind gnus-agent-expire-current-dirs to enable tracking + ;; of agent directories. + (gnus-agent-expire-current-dirs nil) gnus-command-method overview orig) (setq overview (gnus-get-buffer-create " *expire overview*")) (unwind-protect @@ -2775,7 +2785,78 @@ (gnus-agent-expire-group-1 expiring-group overview active articles force))))))) (kill-buffer overview)) + (gnus-agent-expire-unagentized-dirs) (gnus-message 4 "Expiry...done"))))) + +(defun gnus-agent-expire-unagentized-dirs () + (when (boundp 'gnus-agent-expire-current-dirs) + (let* ((keep (gnus-make-hashtable)) + ;; Formally bind gnus-agent-expire-current-dirs so that the + ;; compiler will not complain about free references. + (gnus-agent-expire-current-dirs + (symbol-value 'gnus-agent-expire-current-dirs)) + dir) + + (gnus-sethash gnus-agent-directory t keep) + (while gnus-agent-expire-current-dirs + (setq dir (pop gnus-agent-expire-current-dirs)) + (when (and (stringp dir) + (file-directory-p dir)) + (while (not (gnus-gethash dir keep)) + (gnus-sethash dir t keep) + (setq dir (file-name-directory (directory-file-name dir)))))) + + (let* (to-remove + checker + (checker + (function + (lambda (d) + (let ((files (directory-files d)) + file) + (while (setq file (pop files)) + (cond ((equal file ".") + nil) + ((equal file "..") + nil) + ((equal file ".overview") + (let ((d (file-name-as-directory d)) + r) + (while (not (gnus-gethash + (setq d (file-name-directory d)) keep)) + (setq r d + d (directory-file-name d))) + (if r + (push r to-remove)))) + ((file-directory-p (setq file (nnheader-concat d file))) + (funcall checker file))))))))) + (funcall checker gnus-agent-directory) + + (when (and to-remove + (gnus-y-or-n-p + "gnus-agent-expire has identified local directories that are\ + not currently required by any agentized group. Do you wish to consider\ + deleting them?")) + (while to-remove + (let ((dir (pop to-remove))) + (if (gnus-y-or-n-p (format "Delete %s?" dir)) + (let* (delete-recursive + (delete-recursive + (function + (lambda (f-or-d) + (ignore-errors + (if (file-directory-p f-or-d) + (condition-case nil + (delete-directory f-or-d) + (file-error + (mapcar (lambda (f) + (or (member f '("." "..")) + (funcall delete-recursive + (nnheader-concat + f-or-d f)))) + (directory-files f-or-d)) + (delete-directory f-or-d))) + (delete-file f-or-d))))))) + (funcall delete-recursive dir)))))))))) ;;;###autoload (defun gnus-agent-batch () Index: gnus/lisp/gnus-art.el diff -u gnus/lisp/gnus-art.el:6.314 gnus/lisp/gnus-art.el:6.324 --- gnus/lisp/gnus-art.el:6.314 Mon Mar 17 17:07:31 2003 +++ gnus/lisp/gnus-art.el Sun Mar 30 14:51:13 2003 @@ -683,7 +683,7 @@ (defcustom gnus-article-decode-hook '(article-decode-charset article-decode-encoded-words - article-decode-group-name) + article-decode-group-name article-decode-idna-rhs) "*Hook run to decode charsets in articles." :group 'gnus-article-headers :type 'hook) @@ -858,7 +858,7 @@ (defvar gnus-inhibit-treatment nil "Whether to inhibit treatment.") -(defcustom gnus-treat-highlight-signature '(or last (typep "text/x-vcard")) +(defcustom gnus-treat-highlight-signature '(or t (typep "text/x-vcard")) "Highlight the signature. Valid values are nil, t, `head', `last', an integer or a predicate. See Info node `(gnus)Customizing Articles'." @@ -1145,7 +1145,8 @@ (and (not noninteractive) (or (and (fboundp 'image-type-available-p) (image-type-available-p 'xbm) - (string-match "^0x" (shell-command-to-string "uncompface"))) + (string-match "^0x" (shell-command-to-string "uncompface")) + (executable-find "icontopbm")) (and (featurep 'xemacs) (featurep 'xface))) 'head) @@ -1320,6 +1321,14 @@ (defvar gnus-article-wash-function nil "Function used for converting HTML into text.") +(defcustom gnus-use-idna (and (condition-case nil (require 'idna) (file-error)) + (fboundp 'coding-system-p) + (coding-system-p 'utf-8)) + "Whether IDNA decoding of headers is used when viewing messages. +This requires GNU Libidn, and by default only enabled if it is found." + :group 'gnus-article-headers + :type 'boolean) + ;;; Internal variables (defvar gnus-english-month-names @@ -2113,20 +2122,60 @@ (when (and (or gnus-group-name-charset-method-alist gnus-group-name-charset-group-alist) (gnus-buffer-live-p gnus-original-article-buffer)) - (when (nnmail-fetch-field "Newsgroups") - (nnheader-replace-header "Newsgroups" - (gnus-decode-newsgroups - (with-current-buffer - gnus-original-article-buffer - (nnmail-fetch-field "Newsgroups")) - gnus-newsgroup-name method))) - (when (nnmail-fetch-field "Followup-To") - (nnheader-replace-header "Followup-To" - (gnus-decode-newsgroups - (with-current-buffer - gnus-original-article-buffer - (nnmail-fetch-field "Followup-To")) - gnus-newsgroup-name method)))))) + (save-restriction + (article-narrow-to-head) + (with-current-buffer gnus-original-article-buffer + (goto-char (point-min))) + (while (re-search-forward "^Newsgroups:\\(\\(.\\|\n[\t ]\\)*\\)\n[^\t ]" + nil t) + (replace-match (save-match-data + (gnus-decode-newsgroups + ;; XXX how to use data in article buffer? + (with-current-buffer gnus-original-article-buffer + (re-search-forward + "^Newsgroups:\\(\\(.\\|\n[\t ]\\)*\\)\n[^\t ]" + nil t) + (match-string 1)) + gnus-newsgroup-name method)) + t t nil 1)) + (goto-char (point-min)) + (with-current-buffer gnus-original-article-buffer + (goto-char (point-min))) + (while (re-search-forward "^Followup-To:\\(\\(.\\|\n[\t ]\\)*\\)\n[^\t ]" + nil t) + (replace-match (save-match-data + (gnus-decode-newsgroups + ;; XXX how to use data in article buffer? + (with-current-buffer gnus-original-article-buffer + (re-search-forward + "^Followup-To:\\(\\(.\\|\n[\t ]\\)*\\)\n[^\t ]" + nil t) + (match-string 1)) + gnus-newsgroup-name method)) + t t nil 1)))))) + +(autoload 'idna-to-unicode "idna") + +(defun article-decode-idna-rhs () + "Decode IDNA strings in RHS in From:, To: and Cc: headers in current buffer." + (when gnus-use-idna + (save-restriction + (let ((inhibit-point-motion-hooks t) + buffer-read-only) + (article-narrow-to-head) + (goto-char (point-min)) + (while (re-search-forward "\\(xn--[-A-Za-z0-9.]*\\)[ \t\n\r,>]" nil t) + (let (ace unicode) + (when (save-match-data + (and (setq ace (match-string 1)) + (save-excursion + (and (re-search-backward "^[^ \t]" nil t) + (looking-at "From\\|To\\|Cc"))) + (save-excursion (backward-char) + (message-idna-inside-rhs-p)) + (setq unicode (idna-to-unicode ace)))) + (unless (string= ace unicode) + (replace-match unicode nil nil nil 1))))))))) (defun article-de-quoted-unreadable (&optional force read-charset) "Translate a quoted-printable-encoded article. @@ -2270,7 +2319,6 @@ (let ((w3m-safe-url-regexp (if mm-inline-text-html-with-images nil "\\`cid:")) - (w3m-display-inline-images mm-inline-text-html-with-images) w3m-force-redisplay) (w3m-region (point-min) (point-max))) (when mm-inline-text-html-with-w3m-keymap Index: gnus/lisp/gnus-fun.el diff -u gnus/lisp/gnus-fun.el:6.38 gnus/lisp/gnus-fun.el:6.42 --- gnus/lisp/gnus-fun.el:6.38 Sat Feb 8 22:20:53 2003 +++ gnus/lisp/gnus-fun.el Mon Mar 31 19:49:14 2003 @@ -219,14 +219,27 @@ (sleep-for 1)) (setq file (car file)) (shell-command - (format "pnmcut -left 110 -top 30 -width 144 -height 144 '%s' | ppmnorm 2>/dev/null | ppmnorm | ppmtopgm | pnmscale -width 48 -height 48 > /tmp/gnus.face.ppm" + (format "pnmcut -left 110 -top 30 -width 144 -height 144 '%s' | pnmscale -width 48 -height 48 | ppmtopgm > /tmp/gnus.face.ppm" file)) (let ((gnus-convert-image-to-face-command - "cat '%s' | ppmquant %d | pnmtopng")) + (format "cat '%%s' | ppmquant %%d | ppmchange %s | pnmtopng" + (gnus-fun-ppm-change-string)))) (setq result (gnus-face-from-file "/tmp/gnus.face.ppm"))) (delete-file file) ;;(delete-file "/tmp/gnus.face.ppm") result)) + +(defun gnus-fun-ppm-change-string () + (let* ((possibilites '("%02x0000" "00%02x00" "0000%02x" + "%02x%02x00" "00%02x%02x" "%02x00%02x")) + (format (concat "'#%02x%02x%02x' '#" + (nth (random 6) possibilites) + "'")) + (values nil)) + (dotimes (i 255) + (push (format format i i i i i i) + values)) + (mapconcat 'identity values " "))) (provide 'gnus-fun) Index: gnus/lisp/gnus-group.el diff -u gnus/lisp/gnus-group.el:6.107 gnus/lisp/gnus-group.el:6.108 --- gnus/lisp/gnus-group.el:6.107 Thu Mar 6 16:58:40 2003 +++ gnus/lisp/gnus-group.el Thu Mar 20 13:29:59 2003 @@ -625,6 +625,7 @@ "f" gnus-group-make-doc-group "w" gnus-group-make-web-group "r" gnus-group-rename-group + "R" gnus-group-make-rss-group "c" gnus-group-customize "x" gnus-group-nnimap-expunge "\177" gnus-group-delete-group @@ -2523,6 +2524,32 @@ group method t (cons (current-buffer) (if (eq major-mode 'gnus-summary-mode) 'summary 'group)))))) + +(eval-when-compile (defvar nnrss-group-alist) + (defun nnrss-discover-feed (arg)) + (defun nnrss-save-server-data (arg))) +(defun gnus-group-make-rss-group (&optional url) + "Given a URL, discover if there is an RSS feed. If there is, +use Gnus' to create an nnrss group" + (interactive) + (require 'nnrss) + (if (not url) + (setq url (read-from-minibuffer "URL to Search for RSS: "))) + (let ((feedinfo (nnrss-discover-feed url))) + (if feedinfo + (let ((title (read-from-minibuffer "Title: " + (cdr (assoc 'title + feedinfo)))) + (desc (read-from-minibuffer "Description: " + (cdr (assoc 'description + feedinfo)))) + (href (cdr (assoc 'href feedinfo)))) + (push (list title href desc) + nnrss-group-alist) + (gnus-group-unsubscribe-group + (concat "nnrss:" title)) + (nnrss-save-server-data nil)) + (error "No feeds found for %s" url)))) (defvar nnwarchive-type-definition) (defvar gnus-group-warchive-type-history nil) Index: gnus/lisp/gnus-int.el diff -u gnus/lisp/gnus-int.el:6.27 gnus/lisp/gnus-int.el:6.29 --- gnus/lisp/gnus-int.el:6.27 Mon Mar 3 02:10:44 2003 +++ gnus/lisp/gnus-int.el Mon Mar 24 04:02:37 2003 @@ -49,7 +49,7 @@ :group 'gnus-start :type '(choice (const :tag "Ask" nil) (const :tag "Deny server" denied) - (const :tag "Unplugg Agent" offline))) + (const :tag "Unplug Agent" offline))) (defvar gnus-internal-registry-spool-current-method nil "The current method, for the registry.") @@ -202,12 +202,17 @@ nil) ;; Open the server. (let ((result - (condition-case () + (condition-case err (funcall (gnus-get-function gnus-command-method 'open-server) (nth 1 gnus-command-method) (nthcdr 2 gnus-command-method)) + (error + (gnus-message 1 (format + "Unable to open server due to: %s" + (error-message-string err))) + nil) (quit - (message "Quit trying to open server") + (gnus-message 1 "Quit trying to open server") nil)))) ;; If this hasn't been opened before, we add it to the list. (unless elem Index: gnus/lisp/gnus-msg.el diff -u gnus/lisp/gnus-msg.el:6.126 gnus/lisp/gnus-msg.el:6.127 --- gnus/lisp/gnus-msg.el:6.126 Mon Mar 17 17:14:09 2003 +++ gnus/lisp/gnus-msg.el Thu Mar 27 05:58:02 2003 @@ -70,12 +70,13 @@ (function))) (defcustom gnus-mailing-list-groups nil - "*Regexp matching groups that are really mailing lists. + "*If non-nil a regexp matching groups that are really mailing lists. This is useful when you're reading a mailing list that has been gatewayed to a newsgroup, and you want to followup to an article in the group." :group 'gnus-message - :type 'regexp) + :type '(choice (regexp) + (const nil))) (defcustom gnus-add-to-list nil "*If non-nil, add a `to-list' parameter automatically." Index: gnus/lisp/gnus-registry.el diff -u gnus/lisp/gnus-registry.el:6.4 gnus/lisp/gnus-registry.el:6.6 --- gnus/lisp/gnus-registry.el:6.4 Mon Feb 24 04:09:10 2003 +++ gnus/lisp/gnus-registry.el Sun Mar 30 04:30:21 2003 @@ -52,6 +52,31 @@ ;; alias puthash is missing from Emacs 20 cl-extra.el (defalias 'puthash 'cl-puthash))) +(defun gnus-registry-translate-to-alist () + (setq gnus-registry-alist (hashtable-to-alist gnus-registry-hashtb))) + +(defun gnus-registry-translate-from-alist () + (setq gnus-registry-hashtb (alist-to-hashtable gnus-registry-alist))) + +(defun alist-to-hashtable (alist) + "Build a hashtable from the values in ALIST." + (let ((ht (make-hash-table + :size 4096 + :test 'equal))) + (mapc + (lambda (kv-pair) + (puthash (car kv-pair) (cdr kv-pair) ht)) + alist) + ht)) + +(defun hashtable-to-alist (hash) + "Build an alist from the values in HASH." + (let ((list nil)) + (maphash + (lambda (key value) + (setq list (cons (cons key value) list))) + hash))) + (defun gnus-register-action (action data-header from &optional to method) (let* ((id (mail-header-id data-header)) (hash-entry (gethash id gnus-registry-hashtb))) @@ -71,15 +96,19 @@ (gnus-group-prefixed-name group gnus-internal-registry-spool-current-method - t))) + t)) + (puthash id (cons (list 'spool nil group nil) + (gethash id gnus-registry-hashtb)) gnus-registry-hashtb)) (add-hook 'gnus-summary-article-move-hook 'gnus-register-action) ; also does copy, respool, and crosspost (add-hook 'gnus-summary-article-delete-hook 'gnus-register-action) (add-hook 'gnus-summary-article-expire-hook 'gnus-register-action) (add-hook 'nnmail-spool-hook 'gnus-register-spool-action) +(add-hook 'gnus-save-newsrc-hook 'gnus-registry-translate-to-alist) +(add-hook 'gnus-read-newsrc-el-hook 'gnus-registry-translate-from-alist) + ;; TODO: a lot of things -;; TODO: we have to load and save the registry through gnus-save-newsrc-file (provide 'gnus-registry) Index: gnus/lisp/gnus-start.el diff -u gnus/lisp/gnus-start.el:6.65 gnus/lisp/gnus-start.el:6.69 --- gnus/lisp/gnus-start.el:6.65 Thu Mar 6 16:58:40 2003 +++ gnus/lisp/gnus-start.el Mon Mar 31 19:49:14 2003 @@ -404,6 +404,11 @@ :group 'gnus-group-new :type 'hook) +(defcustom gnus-read-newsrc-el-hook nil + "A hook called after reading the newsrc.eld? file." + :group 'gnus-newsrc + :type 'hook) + (defcustom gnus-save-newsrc-hook nil "A hook called before saving any of the newsrc files." :group 'gnus-newsrc @@ -782,17 +787,6 @@ (gnus-group-set-parameter "nndraft:drafts" 'gnus-dummy '((gnus-draft-mode))))) -;;;###autoload -(defun gnus-unload () - "Unload all Gnus features. -\(For some value of `all' or `Gnus'.) Currently, features whose names -have prefixes `gnus-', `nn', `mm-' or `rfc' are unloaded. Use -cautiously -- unloading may cause trouble." - (interactive) - (dolist (feature features) - (if (string-match "^\\(gnus-\\|nn\\|mm-\\|rfc\\)" (symbol-name feature)) - (unload-feature feature 'force)))) - ;;; ;;; Dribble file @@ -2231,7 +2225,8 @@ (gnus-message 5 "Reading %s..." file) ;; The .el file is newer than the .eld file, so we read that one ;; as well. - (gnus-read-old-newsrc-el-file file)))) + (gnus-read-old-newsrc-el-file file))) + (gnus-run-hooks 'gnus-read-newsrc-el-hook)) ;; Parse the old-style quick startup file (defun gnus-read-old-newsrc-el-file (file) @@ -2609,10 +2604,9 @@ (unwind-protect (progn - (gnus-with-output-to-file - working-file - (gnus-gnus-to-quick-newsrc-format) - (gnus-run-hooks 'gnus-save-quick-newsrc-hook)) + (gnus-with-output-to-file working-file + (gnus-gnus-to-quick-newsrc-format) + (gnus-run-hooks 'gnus-save-quick-newsrc-hook)) ;; These bindings will mislead the current buffer ;; into thinking that it is visiting the startup @@ -2647,7 +2641,8 @@ (princ "(setq gnus-newsrc-file-version ") (princ (gnus-prin1-to-string gnus-version)) (princ ")\n") - (let* ((gnus-killed-list + (let* ((print-length nil) + (gnus-killed-list (if (and gnus-save-killed-list (stringp gnus-save-killed-list)) (gnus-strip-killed-list) Index: gnus/lisp/gnus-sum.el diff -u gnus/lisp/gnus-sum.el:6.319 gnus/lisp/gnus-sum.el:6.326 --- gnus/lisp/gnus-sum.el:6.319 Mon Mar 17 16:14:43 2003 +++ gnus/lisp/gnus-sum.el Mon Mar 31 18:48:35 2003 @@ -1080,7 +1080,7 @@ the MIME-Version header is missed." :version "21.3" :type 'boolean - :group 'gnus-article) + :group 'gnus-article-mime) (defcustom gnus-article-emulate-mime t "If non-nil, use MIME emulation for uuencode and the like. @@ -1088,7 +1088,7 @@ like uuencoded bits, yEncoded bits, and so on, and present that using the normal Gnus MIME machinery." :type 'boolean - :group 'gnus-article) + :group 'gnus-article-mime) ;;; Internal variables @@ -1382,9 +1382,18 @@ ") ;; Byte-compiler warning. -;(eval-when-compile (defvar gnus-article-mode-map)) (eval-when-compile + ;; Bind features so that require will believe that gnus-sum has + ;; already been loaded (avoids infinite recursion) (let ((features (cons 'gnus-sum features))) + ;; Several of the declarations in gnus-sum are needed to load the + ;; following files. Right now, these definitions have been + ;; compiled but not defined (evaluated). We could either do a + ;; eval-and-compile about all of the declarations or evaluate the + ;; source file. + (if (boundp 'gnus-newsgroup-variables) + nil + (load "gnus-sum.el" t t t t)) (require 'gnus) (require 'gnus-agent) (require 'gnus-art))) @@ -4810,6 +4819,8 @@ (substring gnus-tmp-from (1+ (match-beginning 0)) (1- (match-end 0)))) (t gnus-tmp-from)) + + ;; Do the %B string gnus-tmp-thread-tree-header-string (cond ((not gnus-show-threads) "") @@ -6308,17 +6319,19 @@ (> (prefix-numeric-value arg) 0))) (redraw-display)) -(defun gnus-summary-find-uncancelled () - "Return the number of an uncancelled article. +(defun gnus-summary-find-for-reselect () + "Return the number of an article to stay on across a reselect. The current article is considered, then following articles, then previous -articles. If all articles are cancelled then return a dummy 0." +articles. An article is sought which is not cancelled and isn't a temporary +insertion from another group. If there's no such then return a dummy 0." (let (found) (dolist (rev '(nil t)) (unless found ; don't demand the reverse list if we don't need it (let ((data (gnus-data-find-list (gnus-summary-article-number) (gnus-data-list rev)))) (while (and data (not found)) - (if (not (eq gnus-canceled-mark (gnus-data-mark (car data)))) + (if (and (< 0 (gnus-data-number (car data))) + (not (eq gnus-canceled-mark (gnus-data-mark (car data))))) (setq found (gnus-data-number (car data)))) (setq data (cdr data)))))) (or found 0))) @@ -6329,7 +6342,7 @@ (interactive "P") (when (gnus-ephemeral-group-p gnus-newsgroup-name) (error "Ephemeral groups can't be reselected")) - (let ((current-subject (gnus-summary-find-uncancelled)) + (let ((current-subject (gnus-summary-find-for-reselect)) (group gnus-newsgroup-name)) (setq gnus-newsgroup-begin nil) (gnus-summary-exit) @@ -11126,7 +11139,8 @@ (c cond) (list gnus-summary-highlight)) (while list - (setcdr c (cons (list (caar list) (list 'quote (cdar list))) nil)) + (setcdr c (cons (list (caar list) (list 'quote (cdar list))) + nil)) (setq c (cdr c) list (cdr list))) (gnus-byte-compile (list 'lambda nil cond)))))) Index: gnus/lisp/gnus-util.el diff -u gnus/lisp/gnus-util.el:6.77 gnus/lisp/gnus-util.el:6.79 --- gnus/lisp/gnus-util.el:6.77 Thu Mar 6 08:19:47 2003 +++ gnus/lisp/gnus-util.el Sun Mar 30 04:22:03 2003 @@ -1038,15 +1038,17 @@ (,buffer (make-string ,size 0)) (,leng 0) (append nil) - (standard-output (lambda (c) - (aset ,buffer ,leng c) - (if (= ,size (setq ,leng (1+ ,leng))) - (progn (write-region ,buffer nil ,file append 'no-msg) - (setq ,leng 0 - append t)))))) + (standard-output + (lambda (c) + (aset ,buffer ,leng c) + (if (= ,size (setq ,leng (1+ ,leng))) + (progn (write-region ,buffer nil ,file append 'no-msg) + (setq ,leng 0 + append t)))))) ,@body - (if (> ,leng 0) - (write-region (substring ,buffer 0 ,leng) nil ,file append 'no-msg))))) + (when (> ,leng 0) + (write-region (substring ,buffer 0 ,leng) nil ,file + append 'no-msg))))) (put 'gnus-with-output-to-file 'lisp-indent-function 1) (put 'gnus-with-output-to-file 'edebug-form-spec '(form body)) @@ -1115,8 +1117,11 @@ (require 'byte-optimize) (error)) (require 'bytecomp) - (defalias 'gnus-byte-compile 'byte-compile) - (byte-compile form)) + (defalias 'gnus-byte-compile + (lambda (form) + (let ((byte-compile-warnings '(unresolved callargs redefine))) + (byte-compile form)))) + (gnus-byte-compile form)) form)) (defun gnus-remassoc (key alist) Index: gnus/lisp/gnus-uu.el diff -u gnus/lisp/gnus-uu.el:6.22 gnus/lisp/gnus-uu.el:6.24 --- gnus/lisp/gnus-uu.el:6.22 Mon Mar 3 18:52:32 2003 +++ gnus/lisp/gnus-uu.el Fri Mar 21 08:30:45 2003 @@ -572,11 +572,12 @@ (defun gnus-uu-mark-series () "Mark the current series with the process mark." (interactive) - (let ((articles (gnus-uu-find-articles-matching))) + (let* ((articles (gnus-uu-find-articles-matching)) + (l (length articles))) (while articles (gnus-summary-set-process-mark (car articles)) (setq articles (cdr articles))) - (message "")) + (message "Marked %d articles" l)) (gnus-summary-position-point)) (defun gnus-uu-mark-region (beg end &optional unmark) @@ -1794,9 +1795,13 @@ (if (file-directory-p file) (gnus-uu-delete-work-dir file) (gnus-message 9 "Deleting file %s..." file) - (delete-file file)))) - (delete-directory dir))) - (gnus-message 7 "")) + (condition-case err + (delete-file file) + (error (gnus-message 3 "Deleting file %s failed... %s" file err)))))) + (condition-case err + (delete-directory dir) + (error (gnus-message 3 "Deleting directory %s failed... %s" file err)))) + (gnus-message 7 ""))) ;; Initializing Index: gnus/lisp/gnus.el diff -u gnus/lisp/gnus.el:6.163 gnus/lisp/gnus.el:6.166 --- gnus/lisp/gnus.el:6.163 Mon Mar 3 02:12:06 2003 +++ gnus/lisp/gnus.el Fri Mar 28 10:41:18 2003 @@ -286,7 +286,7 @@ :link '(custom-manual "(gnus)Exiting Gnus") :group 'gnus) -(defconst gnus-version-number "0.16" +(defconst gnus-version-number "0.17" "Version number for this version of Gnus.") (defconst gnus-version (format "Oort Gnus v%s" gnus-version-number) @@ -1949,7 +1949,50 @@ (string :tag "Move to a group") (const :tag "Expire" nil)))) :parameter-document - "Where ham articles will go at summary exit from a spam group.")) + "Where ham articles will go at summary exit from a spam group.") + + (gnus-define-group-parameter + ham-marks + :type 'list + :parameter-type '(list :tag "Ham mark choices" + (set + (variable-item gnus-del-mark) + (variable-item gnus-read-mark) + (variable-item gnus-killed-mark) + (variable-item gnus-kill-file-mark) + (variable-item gnus-low-score-mark))) + + :parameter-document + "Marks considered ham (positively not spam). Such articles will be +processed as ham (non-spam) on group exit. When nil, the global +spam-ham-marks variable takes precedence." + :variable-default '((".*" ((gnus-del-mark + gnus-read-mark + gnus-killed-mark + gnus-kill-file-mark + gnus-low-score-mark)))) + :variable-group spam + :variable-document + "*Groups in which to explicitly set the ham marks to some value.") + + (gnus-define-group-parameter + spam-marks + :type 'list + :parameter-type '(list :tag "Spam mark choices" + (set + (variable-item gnus-spam-mark) + (variable-item gnus-killed-mark) + (variable-item gnus-kill-file-mark) + (variable-item gnus-low-score-mark))) + + :parameter-document + "Marks considered spam. +Such articles will be processed as spam on group exit. When nil, the global +spam-spam-marks variable takes precedence." + :variable-default '((".*" ((gnus-spam-mark)))) + :variable-group spam + :variable-document + "*Groups in which to explicitly set the spam marks to some value.")) (defcustom gnus-group-uncollapsed-levels 1 "Number of group name elements to leave alone when making a short group name." @@ -2243,6 +2286,7 @@ '(gnus-newsrc-options gnus-newsrc-options-n gnus-newsrc-last-checked-date gnus-newsrc-alist gnus-server-alist + gnus-registry-alist gnus-killed-list gnus-zombie-list gnus-topic-topology gnus-topic-alist gnus-agent-covered-methods gnus-format-specs) @@ -2251,6 +2295,10 @@ (defvar gnus-newsrc-alist nil "Assoc list of read articles. gnus-newsrc-hashtb should be kept so that both hold the same information.") + +(defvar gnus-registry-alist nil + "Assoc list of registry data. +gnus-registry.el will populate this if it's loaded.") (defvar gnus-newsrc-hashtb nil "Hashtable of gnus-newsrc-alist.") Index: gnus/lisp/imap.el diff -u gnus/lisp/imap.el:6.48 gnus/lisp/imap.el:6.51 --- gnus/lisp/imap.el:6.48 Tue Mar 4 02:59:15 2003 +++ gnus/lisp/imap.el Mon Mar 31 19:23:59 2003 @@ -152,6 +152,7 @@ (autoload 'utf7-decode "utf7") (autoload 'format-spec "format-spec") (autoload 'format-spec-make "format-spec") + (autoload 'open-tls-stream "tls") ;; Avoid use gnus-point-at-eol so we're independent of Gnus. These ;; days we have point-at-eol anyhow. (if (fboundp 'point-at-eol) @@ -178,7 +179,12 @@ :group 'imap :type '(repeat string)) -(defcustom imap-gssapi-program '("imtest -m gssapi -u %l -p %p %s") +(defcustom imap-gssapi-program (list + (concat "gsasl --client --connect %s:%p " + "--imap --application-data " + "--mechanism GSSAPI " + "--authentication-id %l") + "imtest -m gssapi -u %l -p %p %s") "List of strings containing commands for GSSAPI (krb5) authentication. %s is replaced with server hostname, %p with port to connect to, and %l with the value of `imap-default-user'. The program should accept @@ -246,17 +252,28 @@ :group 'imap :type 'string) +(defcustom imap-read-timeout (if (string-match + "windows-nt\\|os/2\\|emx\\|cygwin" + (symbol-name system-type)) + 1.0 + 0.1) + "*How long to wait between checking for the end of output. +Shorter values mean quicker response, but is more CPU intensive." + :type 'number + :group 'imap) + ;; Various variables. (defvar imap-fetch-data-hook nil "Hooks called after receiving each FETCH response.") -(defvar imap-streams '(gssapi kerberos4 starttls ssl network shell) +(defvar imap-streams '(gssapi kerberos4 starttls tls ssl network shell) "Priority of streams to consider when opening connection to server.") (defvar imap-stream-alist '((gssapi imap-gssapi-stream-p imap-gssapi-open) (kerberos4 imap-kerberos4-stream-p imap-kerberos4-open) + (tls imap-tls-p imap-tls-open) (ssl imap-ssl-p imap-ssl-open) (network imap-network-p imap-network-open) (shell imap-shell-p imap-shell-open) @@ -299,6 +316,7 @@ (defconst imap-default-port 143) (defconst imap-default-ssl-port 993) +(defconst imap-default-tls-port 993) (defconst imap-default-stream 'network) (defconst imap-coding-system-for-read 'binary) (defconst imap-coding-system-for-write 'binary) @@ -545,7 +563,7 @@ (set-buffer buffer) ;; XXX "blue moon" nntp.el bug (goto-char (point-min)) ;; cyrus 1.6.x (13? < x <= 22) queries capabilities - (or (while (looking-at "^C:") + (or (while (looking-at "^C:") (forward-line)) t) ;; cyrus 1.6 imtest print "S: " before server greeting @@ -555,7 +573,10 @@ (not (and (imap-parse-greeting) ;; success in imtest 1.6: (re-search-forward - "^\\(Authenticat.*\\)" nil t) + (concat "^\\(\\(Authenticat.*\\)\\|\\(" + "Client authentication " + "finished.*\\)\\)") + nil t) (setq response (match-string 1))))) (accept-process-output process 1) (sit-for 1)) @@ -626,6 +647,31 @@ (message "imap: Opening SSL connection with `%s'...failed" cmd) nil))) +(defun imap-tls-p (buffer) + nil) + +(defun imap-tls-open (name buffer server port) + (let* ((port (or port imap-default-tls-port)) + (coding-system-for-read imap-coding-system-for-read) + (coding-system-for-write imap-coding-system-for-write) + (process (open-tls-stream name buffer server port))) + (when process + (while (and (memq (process-status process) '(open run)) + (set-buffer buffer) ;; XXX "blue moon" nntp.el bug + (goto-char (point-max)) + (forward-line -1) + (not (imap-parse-greeting))) + (accept-process-output process 1) + (sit-for 1)) + (and imap-log + (with-current-buffer (get-buffer-create imap-log-buffer) + (imap-disable-multibyte) + (buffer-disable-undo) + (goto-char (point-max)) + (insert-buffer-substring buffer))) + (when (memq (process-status process) '(open run)) + process)))) + (defun imap-network-p (buffer) t) @@ -1701,7 +1747,11 @@ (unless (< len 10) (setq imap-have-messaged t) (message "imap read: %dk" len)) - (accept-process-output imap-process 1))) + (accept-process-output imap-process + (truncate imap-read-timeout) + (truncate (* (- imap-read-timeout + (truncate imap-read-timeout)) + 1000))))) (when imap-have-messaged (message "")) (and (memq (process-status imap-process) '(open run)) Index: gnus/lisp/lpath.el diff -u gnus/lisp/lpath.el:6.58 gnus/lisp/lpath.el:6.61 --- gnus/lisp/lpath.el:6.58 Tue Mar 18 01:01:23 2003 +++ gnus/lisp/lpath.el Thu Mar 27 07:24:37 2003 @@ -13,19 +13,20 @@ create-image display-graphic-p display-time-event-handler find-image image-size image-type-available-p insert-image - make-mode-line-mouse-map make-temp-file propertize - put-image replace-regexp-in-string rmail-msg-is-pruned - rmail-msg-restore-non-pruned-header sort-coding-systems - spam-BBDB-register-routine spam-enter-ham-BBDB - tool-bar-add-item tool-bar-add-item-from-menu - tool-bar-local-item-from-menu url-http-file-exists-p - vcard-pretty-print w32-focus-frame + make-mode-line-mouse-map make-temp-file open-ssl-stream + propertize put-image replace-regexp-in-string + rmail-msg-is-pruned rmail-msg-restore-non-pruned-header + sort-coding-systems spam-BBDB-register-routine + spam-enter-ham-BBDB tool-bar-add-item + tool-bar-add-item-from-menu tool-bar-local-item-from-menu + url-http-file-exists-p vcard-pretty-print w32-focus-frame w3m-charset-to-coding-system x-focus-frame)) (maybe-bind '(filladapt-mode - mc-pgp-always-sign rmail-enable-mime-composing + mc-pgp-always-sign mm-w3m-mode-map rmail-enable-mime-composing rmail-insert-mime-forwarded-message-function w3m-cid-retrieve-function-alist w3m-current-buffer - w3m-meta-content-type-charset-regexp w3m-minor-mode-map)) + w3m-display-inline-images w3m-meta-content-type-charset-regexp + w3m-minor-mode-map)) (if (featurep 'xemacs) (progn @@ -47,11 +48,10 @@ buffer-display-table buffer-file-coding-system current-language-environment default-enable-multibyte-characters - enable-multibyte-characters language-info-alist - mark-active mouse-selection-click-count + enable-multibyte-characters gnus-agent-expire-current-dirs + language-info-alist mark-active mouse-selection-click-count mouse-selection-click-count-buffer pgg-parse-crc24 - temporary-file-directory transient-mark-mode - mm-w3m-mode-map))) + temporary-file-directory transient-mark-mode))) (maybe-fbind '(bbdb-complete-name delete-annotation device-connection dfw-device events-to-keys font-lock-set-defaults frame-device @@ -64,11 +64,15 @@ w3-prepare-buffer w3-region w3m-region window-pixel-height window-pixel-width)) (maybe-bind '(help-echo-owns-message - mail-mode-hook url-package-name url-package-version + mail-mode-hook + url-current-object url-package-name url-package-version w3-meta-charset-content-type-regexp - w3-meta-content-type-charset-regexp mm-w3m-mode-map))) + w3-meta-content-type-charset-regexp))) (defun nnkiboze-score-file (a) + ) + +(defun split-line (&optional arg) ) (provide 'lpath) Index: gnus/lisp/message.el diff -u gnus/lisp/message.el:6.311 gnus/lisp/message.el:6.322 --- gnus/lisp/message.el:6.311 Mon Mar 17 17:14:09 2003 +++ gnus/lisp/message.el Sun Mar 30 16:21:56 2003 @@ -1288,6 +1288,17 @@ :link '(custom-manual "(message)News Headers") :type 'string) +(defcustom message-use-idna (and (condition-case nil (require 'idna) + (file-error)) + (fboundp 'coding-system-p) + (coding-system-p 'utf-8) + 'ask) + "Whether to encode non-ASCII in domain names into ASCII according to IDNA." + :group 'message-headers + :type '(choice (const :tag "Ask" ask) + (const :tag "Never" nil) + (const :tag "Always" t))) + ;;; Internal variables. (defvar message-sending-message "Sending...") @@ -2080,6 +2091,7 @@ (define-key message-mode-map "\C-c\C-z" 'message-kill-to-signature) (define-key message-mode-map "\M-\r" 'message-newline-and-reformat) ;;(define-key message-mode-map "\M-q" 'message-fill-paragraph) + (define-key message-mode-map [remap split-line] 'message-split-line) (define-key message-mode-map "\C-c\C-a" 'mml-attach-file) @@ -2172,6 +2184,7 @@ ["Reduce To: to Cc:" message-reduce-to-to-cc t] "----" ["Sort Headers" message-sort-headers t] + ["Encode non-ASCII domain names" message-idna-to-ascii-rhs t] ["Goto Body" message-goto-body t] ["Goto Signature" message-goto-signature t])) @@ -3899,7 +3912,7 @@ ;; Check "Shoot me". (message-check 'shoot (if (re-search-forward - "Message-ID.*.i-did-not-set--mail-host-address--so-shoot-me" nil t) + "Message-ID.*.i-did-not-set--mail-host-address--so-tickle-me" nil t) (y-or-n-p "You appear to have a misconfigured system. Really post? ") t)) ;; Check for Approved. @@ -4412,12 +4425,10 @@ (date (mail-header-date message-reply-headers)) (msg-id (mail-header-message-id message-reply-headers))) (when from - (let ((stop-pos - (string-match " *at \\| *@ \\| *(\\| *<" from))) + (let ((name (mail-extract-address-components from))) (concat msg-id (if msg-id " (") - (if (and stop-pos - (not (zerop stop-pos))) - (substring from 0 stop-pos) from) + (or (car name) + (nth 1 name)) "'s message of \"" (if (or (not date) (string= date "")) "(unknown date)" date) @@ -4629,6 +4640,70 @@ list msg-recipients)))))) +(defun message-idna-inside-rhs-p () + "Return t iff point is inside a RHS (heuristically). +Only works properly if header contains mailbox-list or address-list. +I.e., calling it on a Subject: header is useless." + (save-restriction + (narrow-to-region (save-excursion (or (re-search-backward "^[^ \t]" nil t) + (point-min))) + (save-excursion (or (re-search-forward "^[^ \t]" nil t) + (point-max)))) + (if (re-search-backward "[\\\n\r\t ]" + (save-excursion (search-backward "@" nil t)) t) + ;; whitespace between @ and point + nil + (let ((dquote 1) (paren 1)) + (while (save-excursion (re-search-backward "[^\\]\"" nil t dquote)) + (incf dquote)) + (while (save-excursion (re-search-backward "[^\\]\(" nil t paren)) + (incf paren)) + (and (= (% dquote 2) 1) (= (% paren 2) 1)))))) + +(autoload 'idna-to-ascii "idna") + +(defun message-idna-to-ascii-rhs-1 (header) + "Interactively potentially IDNA encode domain names in HEADER." + (let (rhs ace start startpos endpos ovl) + (goto-char (point-min)) + (while (re-search-forward (concat "^" header) nil t) + (while (re-search-forward "@\\([^ \t\r\n>]+\\)" + (or (save-excursion + (re-search-forward "^[^ \t]" nil t)) + (point-max)) + t) + (setq rhs (match-string-no-properties 1) + startpos (match-beginning 1) + endpos (match-end 1)) + (when (save-match-data + (and (message-idna-inside-rhs-p) + (setq ace (idna-to-ascii rhs)) + (not (string= rhs ace)) + (if (eq message-use-idna 'ask) + (unwind-protect + (progn + (setq ovl (message-make-overlay startpos + endpos)) + (message-overlay-put ovl 'face 'highlight) + (y-or-n-p + (format "Replace with `%s'? " ace))) + (message "") + (message-delete-overlay ovl)) + message-use-idna))) + (replace-match (concat "@" ace))))))) + +(defun message-idna-to-ascii-rhs () + "Possibly IDNA encode non-ASCII domain names in From:, To: and Cc: headers. +See `message-idna-encode'." + (interactive) + (when message-use-idna + (save-excursion + (save-restriction + (message-narrow-to-head) + (message-idna-to-ascii-rhs-1 "From") + (message-idna-to-ascii-rhs-1 "To") + (message-idna-to-ascii-rhs-1 "Cc"))))) + (defun message-generate-headers (headers) "Prepare article HEADERS. Headers already prepared in the buffer are not modified." @@ -4780,7 +4855,9 @@ (beginning-of-line)) (when (or (message-news-p) (string-match "@.+\\.." secure-sender)) - (insert "Sender: " secure-sender "\n"))))))) + (insert "Sender: " secure-sender "\n")))) + ;; Check for IDNA + (message-idna-to-ascii-rhs)))) (defun message-insert-courtesy-copy () "Insert a courtesy message in mail copies of combined messages." @@ -4833,6 +4910,16 @@ (widen) (forward-line 1))) +(defun message-split-line () + "Split current line, moving portion beyond point vertically down. +If the current line has `message-yank-prefix', insert it on the new line." + (interactive "*") + (condition-case nil + (split-line message-yank-prefix) ;; Emacs 21.3.50+ supports arg. + (error + (split-line)))) + + (defun message-fill-header (header value) (let ((begin (point)) (fill-column 78) @@ -6066,6 +6153,9 @@ (delete-char -2)))))) (defalias 'message-exchange-point-and-mark 'exchange-point-and-mark) +(defalias 'message-make-overlay 'make-overlay) +(defalias 'message-delete-overlay 'delete-overlay) +(defalias 'message-overlay-put 'overlay-put) ;; Support for toolbar (eval-when-compile Index: gnus/lisp/messagexmas.el diff -u gnus/lisp/messagexmas.el:6.4 gnus/lisp/messagexmas.el:6.5 --- gnus/lisp/messagexmas.el:6.4 Thu Jan 16 01:53:34 2003 +++ gnus/lisp/messagexmas.el Thu Mar 20 17:11:28 2003 @@ -124,7 +124,10 @@ 'region-exists-p) (when (>= emacs-major-version 20) (defalias 'message-make-caesar-translation-table - 'message-xmas-make-caesar-translation-table))) + 'message-xmas-make-caesar-translation-table)) + (defalias 'message-make-overlay 'make-extent) + (defalias 'message-delete-overlay 'delete-extent) + (defalias 'message-overlay-put 'set-extent-property)) (message-xmas-redefine) Index: gnus/lisp/mm-bodies.el diff -u gnus/lisp/mm-bodies.el:6.16 gnus/lisp/mm-bodies.el:6.17 --- gnus/lisp/mm-bodies.el:6.16 Sat Mar 15 23:59:22 2003 +++ gnus/lisp/mm-bodies.el Tue Mar 18 18:22:05 2003 @@ -282,14 +282,17 @@ "Decode region between START and END with CODING-SYSTEM. If CODING-SYSTEM is not a valid coding system for the text, let Emacs decide which coding system to use." - (let* ((decoded (mm-decode-coding-string (buffer-substring start end) - coding-system)) - (charsets (find-charset-string decoded))) - (if (or (memq 'eight-bit-control charsets) - (memq 'eight-bit-graphic charsets)) - (mm-decode-coding-region start end 'undecided) - (delete-region start end) - (insert decoded)))) + (let* ((orig (buffer-substring start end)) + charsets) + (save-restriction + (narrow-to-region start end) + (mm-decode-coding-region (point-min) (point-max) coding-system) + (setq charsets (find-charset-region (point-min) (point-max))) + (when (or (memq 'eight-bit-control charsets) + (memq 'eight-bit-graphic charsets)) + (delete-region (point-min) (point-max)) + (insert orig) + (mm-decode-coding-region (point-min) (point-max) 'undecided))))) (defun mm-decode-string (string charset) "Decode STRING with CHARSET." Index: gnus/lisp/mm-url.el diff -u gnus/lisp/mm-url.el:6.19 gnus/lisp/mm-url.el:6.22 --- gnus/lisp/mm-url.el:6.19 Mon Mar 3 18:52:32 2003 +++ gnus/lisp/mm-url.el Sun Mar 23 04:47:15 2003 @@ -279,17 +279,23 @@ (list url (buffer-size))) (mm-url-load-url) (let ((name buffer-file-name) + (url-request-extra-headers (list (cons "Connection" "Close"))) (url-package-name (or mm-url-package-name url-package-name)) (url-package-version (or mm-url-package-version - url-package-version))) - (prog1 - (url-insert-file-contents url) - (save-excursion - (goto-char (point-min)) - (while (re-search-forward "\r 1000\r ?" nil t) - (replace-match ""))) - (setq buffer-file-name name))))) + url-package-version)) + result) + (setq result (url-insert-file-contents url)) + (save-excursion + (goto-char (point-min)) + (while (re-search-forward "\r 1000\r ?" nil t) + (replace-match ""))) + (setq buffer-file-name name) + (if (and (fboundp 'url-generic-parse-url) + (listp result)) + (setq url-current-object (url-generic-parse-url + (car result)))) + result))) (defun mm-url-insert-file-contents-external (url) (let (program args) Index: gnus/lisp/mm-util.el diff -u gnus/lisp/mm-util.el:6.56 gnus/lisp/mm-util.el:6.57 --- gnus/lisp/mm-util.el:6.56 Mon Feb 10 01:42:16 2003 +++ gnus/lisp/mm-util.el Wed Mar 19 04:34:35 2003 @@ -298,7 +298,8 @@ (defun mm-mule-charset-to-mime-charset (charset) "Return the MIME charset corresponding to the given Mule CHARSET." - (if (fboundp 'find-coding-systems-for-charsets) + (if (and (fboundp 'find-coding-systems-for-charsets) + (fboundp 'sort-coding-systems)) (let (mime) (dolist (cs (sort-coding-systems (copy-sequence Index: gnus/lisp/mm-view.el diff -u gnus/lisp/mm-view.el:6.51 gnus/lisp/mm-view.el:6.53 --- gnus/lisp/mm-view.el:6.51 Thu Mar 13 02:59:30 2003 +++ gnus/lisp/mm-view.el Mon Mar 31 19:14:38 2003 @@ -47,7 +47,7 @@ mm-links-remove-leading-blank "links" "-dump" file) (lynx mm-inline-render-with-stdin nil - "lynx" "-dump" "-force_html" "-stdin") + "lynx" "-dump" "-force_html" "-stdin" "-nolist") (html2text mm-inline-render-with-function html2text)) "The attributes of renderer types for text/html.") @@ -60,7 +60,7 @@ mm-links-remove-leading-blank "links" "-dump" file) (lynx mm-inline-wash-with-stdin nil - "lynx" "-dump" "-force_html" "-stdin") + "lynx" "-dump" "-force_html" "-stdin" "-nolist") (html2text html2text)) "The attributes of washer types for text/html.") @@ -194,7 +194,8 @@ (unless (assq 'gnus-article-mode w3m-cid-retrieve-function-alist) (push (cons 'gnus-article-mode 'mm-w3m-cid-retrieve) w3m-cid-retrieve-function-alist)) - (setq mm-w3m-setup t))) + (setq mm-w3m-setup t)) + (setq w3m-display-inline-images mm-inline-text-html-with-images)) (defun mm-w3m-cid-retrieve (url &rest args) "Insert a content pointed by URL if it has the cid: scheme." @@ -248,7 +249,6 @@ (delete-region (point-min) (point-max)) (insert (mm-decode-string text charset))) (let ((w3m-safe-url-regexp mm-w3m-safe-url-regexp) - (w3m-display-inline-images mm-inline-text-html-with-images) w3m-force-redisplay) (w3m-region (point-min) (point-max))) (when mm-inline-text-html-with-w3m-keymap Index: gnus/lisp/nndoc.el diff -u gnus/lisp/nndoc.el:6.18 gnus/lisp/nndoc.el:6.19 --- gnus/lisp/nndoc.el:6.18 Mon Mar 17 17:14:09 2003 +++ gnus/lisp/nndoc.el Sun Mar 30 16:21:56 2003 @@ -58,6 +58,9 @@ `((mmdf (article-begin . "^\^A\^A\^A\^A\n") (body-end . "^\^A\^A\^A\^A\n")) + (mime-parts + (generate-head-function . nndoc-generate-mime-parts-head) + (article-transform-function . nndoc-transform-mime-parts)) (nsmail (article-begin . "^From - ")) (news @@ -98,9 +101,6 @@ (body-end . "") (file-end . "") (subtype digest guess)) - (mime-parts - (generate-head-function . nndoc-generate-mime-parts-head) - (article-transform-function . nndoc-transform-mime-parts)) (standard-digest (first-article . ,(concat "^" (make-string 70 ?-) "\n *\n+")) (article-begin . ,(concat "^\n" (make-string 30 ?-) "\n *\n+")) Index: gnus/lisp/nnheader.el diff -u gnus/lisp/nnheader.el:6.39 gnus/lisp/nnheader.el:6.40 --- gnus/lisp/nnheader.el:6.39 Mon Mar 17 17:14:09 2003 +++ gnus/lisp/nnheader.el Mon Mar 31 19:07:30 2003 @@ -70,6 +70,14 @@ (defvar nnheader-head-chop-length 2048 "*Length of each read operation when trying to fetch HEAD headers.") +(defvar nnheader-read-timeout + (if (string-match "windows-nt\\|os/2\\|emx\\|cygwin" + (symbol-name system-type)) + 1.0 + 0.1) + "How long nntp should wait between checking for the end of output. +Shorter values mean quicker response, but is more CPU intensive.") + (defvar nnheader-file-name-translation-alist (let ((case-fold-search t)) (cond @@ -999,6 +1007,14 @@ (defalias 'nnheader-cancel-timer 'cancel-timer) (defalias 'nnheader-cancel-function-timers 'cancel-function-timers) (defalias 'nnheader-string-as-multibyte 'string-as-multibyte) + +(defun nnheader-accept-process-output (process) + (accept-process-output + process + (truncate nnheader-read-timeout) + (truncate (* (- nnheader-read-timeout + (truncate nnheader-read-timeout)) + 1000)))) (when (featurep 'xemacs) (require 'nnheaderxm)) Index: gnus/lisp/nnimap.el diff -u gnus/lisp/nnimap.el:6.63 gnus/lisp/nnimap.el:6.64 --- gnus/lisp/nnimap.el:6.63 Fri Mar 7 19:22:00 2003 +++ gnus/lisp/nnimap.el Sun Mar 23 14:57:08 2003 @@ -83,7 +83,7 @@ (defvoo nnimap-server-port nil "Port number on physical IMAP server. -If nil, defaults to 993 for SSL connections and 143 otherwise.") +If nil, defaults to 993 for TLS/SSL connections and 143 otherwise.") ;; Splitting variables @@ -260,14 +260,16 @@ Change this if -1) you want to connect with SSL. The SSL integration with IMAP is - brain-dead so you'll have to tell it specifically. +1) you want to connect with TLS/SSL. The TLS/SSL integration + with IMAP is suboptimal so you'll have to tell it + specifically. 2) your server is more capable than your environment -- i.e. your server accept Kerberos login's but you haven't installed the `imtest' program or your machine isn't configured for Kerberos. -Possible choices: kerberos4, ssl, network") +Possible choices: gssapi, kerberos4, starttls, tls, ssl, network, shell. +See also `imap-streams' and `imap-stream-alist'.") (defvoo nnimap-authenticator nil "How nnimap authenticate itself to the server. @@ -281,7 +283,8 @@ installed the `imtest' program or your machine isn't configured for Kerberos. -Possible choices: kerberos4, cram-md5, login, anonymous.") +Possible choices: gssapi, kerberos4, digest-md5, cram-md5, login, anonymous. +See also `imap-authenticators' and `imap-authenticator-alist'") (defvoo nnimap-directory (nnheader-concat gnus-directory "overview/") "Directory to keep NOV cache files for nnimap groups. Index: gnus/lisp/nnmail.el diff -u gnus/lisp/nnmail.el:6.70 gnus/lisp/nnmail.el:6.72 --- gnus/lisp/nnmail.el:6.70 Mon Mar 17 20:13:24 2003 +++ gnus/lisp/nnmail.el Sun Mar 30 16:22:52 2003 @@ -889,8 +889,8 @@ start (if (search-forward "\n\n" nil t) (1- (point)) - ;; This will never happen, but just to be on the safe side -- - ;; if there is no head-body delimiter, we search a bit manually. + ;; This will never happen, but just to be on the safe side -- + ;; if there is no head-body delimiter, we search a bit manually. (while (and (looking-at "From \\|[^ \t]+:") (not (eobp))) (forward-line 1)) @@ -936,7 +936,7 @@ (if (search-forward "\n\n" nil t) (1- (point)) ;; This will never happen, but just to be on the safe side -- - ;; if there is no head-body delimiter, we search a bit manually. + ;; if there is no head-body delimiter, we search a bit manually. (while (and (looking-at "From \\|[^ \t]+:") (not (eobp))) (forward-line 1)) @@ -1186,7 +1186,8 @@ nil t) (delete-region (match-beginning 2) (match-end 0)) (beginning-of-line)) - (when (re-search-forward "^Subject: +\\(\\(R[Ee]: +\\)+\\)R[Ee]: +" nil t) + (when (re-search-forward "^Subject: +\\(\\(R[Ee]: +\\)+\\)R[Ee]: +" + nil t) (delete-region (match-beginning 1) (match-end 1)) (beginning-of-line))))) Index: gnus/lisp/nnmaildir.el diff -u gnus/lisp/nnmaildir.el:6.26 gnus/lisp/nnmaildir.el:6.29 --- gnus/lisp/nnmaildir.el:6.26 Thu Mar 13 20:47:00 2003 +++ gnus/lisp/nnmaildir.el Fri Mar 28 18:12:31 2003 @@ -41,12 +41,8 @@ ;; copying, restoring, etc. ;; ;; Todo: -;; * Replace create-directory with target-prefix, so the maildirs can be in -;; the same directory as the symlinks, starting with, e.g., ".". ;; * Add a hook for when moving messages from new/ to cur/, to support ;; nnmail's duplicate detection. -;; * Allow each mark directory in a group to have its own inode for mark -;; files, to accommodate AFS. ;; * Improve generated Xrefs, so crossposts are detectable. ;; * Improve code readability. @@ -138,17 +134,17 @@ ; ("Mark Mod Time Hash") (defstruct nnmaildir--srv - (address nil :type string) ;; server address string - (method nil :type list) ;; (nnmaildir "address" ...) - (prefix nil :type string) ;; "nnmaildir+address:" - (dir nil :type string) ;; "/expanded/path/to/server/dir/" - (ls nil :type function) ;; directory-files function - (groups nil :type vector) ;; obarray mapping group names->groups - (curgrp nil :type nnmaildir--grp) ;; current group, or nil - (error nil :type string) ;; last error message, or nil - (mtime nil :type list) ;; modtime of dir - (gnm nil) ;; flag: split from mail-sources? - (create-dir nil :type string)) ;; group creation directory + (address nil :type string) ;; server address string + (method nil :type list) ;; (nnmaildir "address" ...) + (prefix nil :type string) ;; "nnmaildir+address:" + (dir nil :type string) ;; "/expanded/path/to/server/dir/" + (ls nil :type function) ;; directory-files function + (groups nil :type vector) ;; obarray mapping group name->group + (curgrp nil :type nnmaildir--grp) ;; current group, or nil + (error nil :type string) ;; last error message, or nil + (mtime nil :type list) ;; modtime of dir + (gnm nil) ;; flag: split from mail-sources? + (target-prefix nil :type string)) ;; symlink target prefix (defun nnmaildir--expired-article (group article) (setf (nnmaildir--art-nov article) nil) @@ -242,8 +238,9 @@ (or (file-exists-p (file-name-as-directory dir)) (make-directory-internal (directory-file-name dir)))) (defun nnmaildir--delete-dir-files (dir ls) - (mapcar 'delete-file (funcall ls dir 'full "\\`[^.]" 'nosort)) - (delete-directory dir)) + (when (file-attributes dir) + (mapcar 'delete-file (funcall ls dir 'full "\\`[^.]" 'nosort)) + (delete-directory dir))) (defun nnmaildir--group-maxnum (server group) (if (zerop (nnmaildir--grp-count group)) 0 @@ -548,6 +545,15 @@ (defun nnmaildir--up2-1 (n) (if (zerop n) 1 (1- (lsh 1 (1+ (logb n)))))) +(defun nnmaildir--system-name () + (gnus-replace-in-string + (gnus-replace-in-string + (gnus-replace-in-string + (system-name) + "\\\\" "\\134" 'literal) + "/" "\\057" 'literal) + ":" "\\072" 'literal)) + (defun nnmaildir-request-type (group &optional article) 'mail) @@ -606,11 +612,20 @@ (car x) (setf (nnmaildir--srv-gnm server) t) (require 'nnmail)) - (setq x (assq 'create-directory defs)) - (when x - (setq x (cadr x) - x (eval x)) - (setf (nnmaildir--srv-create-dir server) x)) + (setq x (assq 'target-prefix defs)) + (if x + (progn + (setq x (cadr x) + x (eval x)) + (setf (nnmaildir--srv-target-prefix server) x)) + (setq x (assq 'create-directory defs)) + (if x + (progn + (setq x (cadr x) + x (eval x) + x (file-name-as-directory x)) + (setf (nnmaildir--srv-target-prefix server) x)) + (setf (nnmaildir--srv-target-prefix server) ""))) (setf (nnmaildir--srv-groups server) (make-vector size 0)) (setq nnmaildir--cur-server server) t))) @@ -758,12 +773,14 @@ (nnmaildir-get-new-mail t) (nnmaildir-group-alist nil) (nnmaildir-active-file nil) - x srv-ls srv-dir method groups group dirs grp-dir seen deactivate-mark) + x srv-ls srv-dir method groups target-prefix group dirs grp-dir seen + deactivate-mark) (nnmaildir--prepare server nil) (setq srv-ls (nnmaildir--srv-ls nnmaildir--cur-server) srv-dir (nnmaildir--srv-dir nnmaildir--cur-server) method (nnmaildir--srv-method nnmaildir--cur-server) - groups (nnmaildir--srv-groups nnmaildir--cur-server)) + groups (nnmaildir--srv-groups nnmaildir--cur-server) + target-prefix (nnmaildir--srv-target-prefix nnmaildir--cur-server)) (nnmaildir--with-work-buffer (save-match-data (if (stringp scan-group) @@ -780,6 +797,13 @@ method srv-dir srv-ls)) groups)) (setq dirs (funcall srv-ls srv-dir nil "\\`[^.]" 'nosort) + dirs (if (zerop (length target-prefix)) + dirs + (remove-if (lambda (dir) + (and (>= (length dir) (length target-prefix)) + (string= (substring dir 0 (length target-prefix)) + target-prefix))) + dirs)) seen (nnmaildir--up2-1 (length dirs)) seen (make-vector seen 0)) (mapcar @@ -940,7 +964,7 @@ (defun nnmaildir-request-create-group (gname &optional server args) (nnmaildir--prepare server nil) (catch 'return - (let ((create-dir (nnmaildir--srv-create-dir nnmaildir--cur-server)) + (let ((target-prefix (nnmaildir--srv-target-prefix nnmaildir--cur-server)) srv-dir dir groups) (when (zerop (length gname)) (setf (nnmaildir--srv-error nnmaildir--cur-server) @@ -961,18 +985,19 @@ (concat "Group already exists: " gname)) (throw 'return nil)) (setq srv-dir (nnmaildir--srv-dir nnmaildir--cur-server)) - (if (file-name-absolute-p create-dir) - (setq dir (expand-file-name create-dir)) + (if (file-name-absolute-p target-prefix) + (setq dir (expand-file-name target-prefix)) (setq dir srv-dir dir (file-truename dir) - dir (concat dir create-dir))) - (setq dir (nnmaildir--subdir (file-name-as-directory dir) gname)) + dir (concat dir target-prefix))) + (setq dir (nnmaildir--subdir dir gname)) (nnmaildir--mkdir dir) (nnmaildir--mkdir (nnmaildir--tmp dir)) (nnmaildir--mkdir (nnmaildir--new dir)) (nnmaildir--mkdir (nnmaildir--cur dir)) - (setq create-dir (file-name-as-directory create-dir)) - (make-symbolic-link (concat create-dir gname) (concat srv-dir gname)) + (unless (string= target-prefix "") + (make-symbolic-link (concat target-prefix gname) + (concat srv-dir gname))) (nnmaildir-request-scan 'find-new-groups)))) (defun nnmaildir-request-rename-group (gname new-name &optional server) @@ -1028,20 +1053,28 @@ (defun nnmaildir-request-delete-group (gname force &optional server) (let ((group (nnmaildir--prepare server gname)) - pgname grp-dir dir ls deactivate-mark) + pgname grp-dir target dir ls deactivate-mark) (catch 'return (unless group (setf (nnmaildir--srv-error nnmaildir--cur-server) (concat "No such group: " gname)) (throw 'return nil)) + (setq gname (nnmaildir--grp-name group) + pgname (nnmaildir--pgname nnmaildir--cur-server gname) + grp-dir (nnmaildir--srv-dir nnmaildir--cur-server) + target (car (file-attributes (concat grp-dir gname))) + grp-dir (nnmaildir--srvgrp-dir grp-dir gname)) + (unless (or force (stringp target)) + (setf (nnmaildir--srv-error nnmaildir--cur-server) + (concat "Not a symlink: " gname)) + (throw 'return nil)) (if (eq group (nnmaildir--srv-curgrp nnmaildir--cur-server)) (setf (nnmaildir--srv-curgrp nnmaildir--cur-server) nil)) - (setq gname (nnmaildir--grp-name group) - pgname (nnmaildir--pgname nnmaildir--cur-server gname)) (unintern gname (nnmaildir--srv-groups nnmaildir--cur-server)) - (setq grp-dir (nnmaildir--srv-dir nnmaildir--cur-server) - grp-dir (nnmaildir--srvgrp-dir grp-dir gname)) - (if (not force) (setq grp-dir (directory-file-name grp-dir)) + (if (not force) + (progn + (setq grp-dir (directory-file-name grp-dir)) + (nnmaildir--unlink grp-dir)) (setq ls (nnmaildir--group-ls nnmaildir--cur-server pgname)) (if (nnmaildir--param pgname 'read-only) (progn (delete-directory (nnmaildir--tmp grp-dir)) @@ -1060,14 +1093,16 @@ (nnmaildir--unlink (concat dir "markfile{new}")) (delete-directory (nnmaildir--marks-dir dir)) (delete-directory dir) - (setq grp-dir (directory-file-name grp-dir) - dir (car (file-attributes grp-dir))) - (unless (eq (aref "/" 0) (aref dir 0)) - (setq dir (concat (file-truename - (nnmaildir--srv-dir nnmaildir--cur-server)) - dir))) - (delete-directory dir)) - (nnmaildir--unlink grp-dir) + (if (not (stringp target)) + (delete-directory grp-dir) + (setq grp-dir (directory-file-name grp-dir) + dir target) + (unless (eq (aref "/" 0) (aref dir 0)) + (setq dir (concat (file-truename + (nnmaildir--srv-dir nnmaildir--cur-server)) + dir))) + (delete-directory dir) + (nnmaildir--unlink grp-dir))) t))) (defun nnmaildir-retrieve-headers (articles &optional gname server fetch-old) @@ -1282,7 +1317,7 @@ (setq file (concat file "M" (number-to-string (caddr time))))) (setq file (concat file nnmaildir--delivery-pid) file (concat file "Q" (number-to-string nnmaildir--delivery-count)) - file (concat file "." (system-name)) ;;;; FIXME: encode / and : + file (concat file "." (nnmaildir--system-name)) tmpfile (concat (nnmaildir--tmp dir) file) curfile (concat (nnmaildir--cur dir) file ":2,")) (when (file-exists-p tmpfile) @@ -1448,7 +1483,7 @@ (file-coding-system-alist nil) del-mark del-action add-action set-action marksdir markfile nlist ranges begin end article all-marks todo-marks did-marks mdir mfile - pgname ls markfilenew deactivate-mark) + pgname ls permarkfile deactivate-mark) (setq del-mark (lambda (mark) (setq mfile (nnmaildir--subdir marksdir (symbol-name mark)) @@ -1460,20 +1495,19 @@ (mapcar (lambda (mark) (setq mdir (nnmaildir--subdir marksdir (symbol-name mark)) + permarkfile (concat mdir ":") mfile (concat mdir (nnmaildir--art-prefix article))) (unless (memq mark did-marks) + (setq did-marks (cons mark did-marks)) (nnmaildir--mkdir mdir) - (setq did-marks (cons mark did-marks))) + (unless (file-attributes permarkfile) + (condition-case nil + (add-name-to-file markfile permarkfile) + (file-error + ;; AFS can't make hard links in separate directories + (write-region "" nil permarkfile nil 'no-message))))) (unless (file-exists-p mfile) - (condition-case nil - (add-name-to-file markfile mfile) - (file-error - (unless (file-exists-p mfile) - ;; too many links, maybe - (write-region "" nil markfilenew nil 'no-message) - (add-name-to-file markfilenew mfile - 'ok-if-already-exists) - (rename-file markfilenew markfile 'replace)))))) + (add-name-to-file permarkfile mfile))) todo-marks)) set-action (lambda (article) (funcall add-action) @@ -1494,7 +1528,6 @@ marksdir (nnmaildir--srvgrp-dir marksdir gname) marksdir (nnmaildir--nndir marksdir) markfile (concat marksdir "markfile") - markfilenew (concat markfile "{new}") marksdir (nnmaildir--marks-dir marksdir) gname (nnmaildir--grp-name group) pgname (nnmaildir--pgname nnmaildir--cur-server gname) @@ -1551,7 +1584,7 @@ dir (file-name-as-directory (car dir))) (mapcar (lambda (file) - (unless (intern-soft file flist) + (unless (or (intern-soft file flist) (string= file ":")) (setq file (concat dir file)) (delete-file file))) files)) Index: gnus/lisp/nnrss.el diff -u gnus/lisp/nnrss.el:6.35 gnus/lisp/nnrss.el:6.37 --- gnus/lisp/nnrss.el:6.35 Mon Mar 3 18:52:32 2003 +++ gnus/lisp/nnrss.el Thu Mar 20 13:47:04 2003 @@ -59,106 +59,7 @@ (defconst nnrss-version "nnrss 1.0") -(defvar nnrss-group-alist - '(("MacWeek" - "http://macweek.zdnet.com/macweek.xml" - "The Macintosh news authority.") - ("Linux.Weekly.News" - "http://lwn.net/headlines/rss") - ("Motley.Fool" - "http://www.fool.com/About/headlines/rss_headlines.asp") - ("NewsForge.rdf" - "http://www.newsforge.com/newsforge.rdf") - ("Slashdot" - "http://www.slashdot.com/slashdot.rdf") - ("CNN" - "http://www.cnn.com/cnn.rss" - "The world's news leader.") - ("FreshMeat" - "http://freshmeat.net/backend/fm-releases.rdf" - "The one-stop-shop for all your Linux software needs.") - ("The.Guardian.newspaper" - "http://www.guardianunlimited.co.uk/rss/1,,,00.xml" - "Intelligent news and comment throughout the day from The Guardian newspaper.") - ("MonkeyFist.rdf" - "http://monkeyfist.com/rdf.php3" - "News and opinion on politics, technology, and eclectic miscellany.") - ("NewsForge" - "http://www.newsforge.com/newsforge.rss") - ("Reuters.Health" - "http://www.reutershealth.com/eline.rss" - "Consumer-oriented health-related news stories.") - ("Salon" - "http://www.salon.com/feed/RDF/salon_use.rdf") - ("Wired" - "http://www.wired.com/news_drop/netcenter/netcenter.rdf") - ("ITN" - "http://www.itn.co.uk/itn.rdf") - ("Meerkat" - "http://www.oreillynet.com/meerkat/?_fl=rss10" - "An Open Wire Service") - ("MonkeyFist" - "http://monkeyfist.com/rss1.php3" - "News and opinion on politics, technology, and eclectic miscellany.") - ("Reuters.Health.rdf" - "http://www.reutershealth.com/eline.rdf" - "Consumer-oriented health-related news stories.") - ("Aaronland" "http://aaronland.net/xml/abhb.rdf" "A boy and his basement.") - ("Art of the Mix" "http://www.artofthemix.org/xml/rss.asp" "A website devoted to the art of making mixed tapes and cds.") - ("Dave Beckett's RDF Resource Guide" "http://www.ilrt.bristol.ac.uk/discovery/rdf/resources/rss.rdf" "A comprehensive guide to resources about RDF.") - ("David Chess" "http://www.davidchess.com/words/log.rss" "Mostly-daily musings on philosophy, children, culture, technology, the emergence of life from matter, chocolate, Nomic, and all that sort of thing.") - ("Figby Articles" "http://www.figby.com/index-rss.php" "A weblog with daily stories about technology, books and publishing, privacy, science, and occasional humor.") - ("Figby Quickies" "http://www.figby.com/quickies-rss.php" "Quick commented links to other sites from Figby.com.") - ("Flutterby!" "http://www.flutterby.com/main.rdf" "News and views from Dan Lyke.") - ("Groovelog" - "http://groovelog.agora.co.uk/groove+log/groovelog.nsf/today.rss.xml" - "The open-access groove users' weblog.") - ("Hit or Miss" "http://hit-or-miss.org/rss/" "Daily weblog and journal.") - ("Larkfarm News" "http://www.larkfarm.com/Larkfarm.rdf" "Mike Gunderloy's web site.") - ("Latest RFCs" "http://x42.com/rss/rfc.rss") - ("Linux Today" "http://linuxtoday.com/backend/biglt.rss") - ("Linux Today.rdf" "http://linuxtoday.com/backend/my-netscape10.rdf") - ("More Like This WebLog" "http://www.whump.com/moreLikeThis/RSS" "Because the more you know, the more jokes you get.") - ("Motivational Quotes of the Day" "http://www.quotationspage.com/data/mqotd.rss" "Four motivational quotations each day from the Quotations Page.") - ("Network World Fusion NetFlash" "http://www.nwfusion.com/netflash.rss" "Daily breaking news about networking products, technologies and services.") - ("News Is Free" "http://www.newsisfree.com/news.rdf.php3") - ("O'Reilly Network Articles" "http://www.oreillynet.com/cs/rss/query/q/260?x-ver=1.0") - ("Quotes of the Day" "http://www.quotationspage.com/data/qotd.rss" "Four humorous quotations each day from the Quotations Page.") - ("RDF Interest Group" "http://ilrt.org/discovery/rdf-dev/roads/cgi-bin/desire/ig2rss?list=www-rdf-interest" "An experimental channel scraped from the RDF Interest Group mail archives.") - ("RDF Logic List" "http://ilrt.org/discovery/rdf-dev/roads/cgi-bin/desire/ig2rss?list=www-rdf-logic" "An experimental channel scraped from the RDF Logic mail archives.") - ("RSS Info" "http://www.blogspace.com/rss/rss10" "News and information on the RSS format") - ("Semantic Web List" - "http://ilrt.org/discovery/rdf-dev/roads/cgi-bin/desire/ig2rss?list=semantic-web" - "An experimental channel scraped from the W3C's Semantic Web mail archives.") - ("W3C" - "http://www.w3.org/2000/08/w3c-synd/home.rss" - "The latest news at the World Wide Web Consortium.") - ("|fr| XMLfr" "http://xmlfr.org/actualites/general.rss10" - "French speaking portal site dedicated to XML.") - ("XMLhack" "http://xmlhack.com/rss10.php" - "Developer news from the XML community.") - ("The Register" - "http://www.theregister.co.uk/tonys/slashdot.rdf" - "The Register -- Biting the hand that feeds IT.") - ("|de| Heise-Ticker" - "http://www.heise.de/newsticker/heise.rdf" - "German news ticker about technology.") - ("|de| Telepolis News" - "http://www.heise.de/tp/news.rdf" - "German background news about technology.") - ("Kuro5hin" - "http://www.kuro5hin.org/backend.rdf" - "Technology and culture, from the trenches.") - ("Jabber Software Foundation News" - "http://www.jabber.org/news/rss.xml" - "News and announcements from the Jabber Software Foundation.") - ("MacRumors" - "http://www.macrumors.com/macrumors.xml" - "The mac news you care about.") - ("Mac OS X Hints" - "http://www.macosxhints.com/backend/geeklog.rdf" - "Mac OS X Hits.") - ) +(defvar nnrss-group-alist '() "List of RSS addresses.") (defvar nnrss-use-local nil) @@ -248,6 +149,7 @@ (with-current-buffer nntp-server-buffer (erase-buffer) (goto-char (point-min)) + (insert "Mime-Version: 1.0\nContent-Type: text/html\n") (if group (insert "Newsgroups: " group "\n")) (if (nth 3 e) @@ -262,23 +164,23 @@ (let ((point (point))) (insert (nnrss-string-as-multibyte (nth 6 e))) (goto-char point) - (while (search-forward "\n" nil t) - (delete-char -1)) + (while (re-search-forward "\n" nil t) + (replace-match " ")) (goto-char (point-max)) (insert "\n\n") (fill-region point (point)))) (if (nth 2 e) - (insert (nth 2 e) "\n")) + (insert "<p><a href='" (nth 2 e) "'>link</a></p>\n")) (if nnrss-content-function (funcall nnrss-content-function e group article))))) (cond (err (nnheader-report 'nnrss err)) ((not e) - (nnheader-report 'nnrss "No such id: %d" article)) + (nnheader-report 'nnrss "no such id: %d" article)) (t - (nnheader-report 'nnrss "Article %s retrieved" (car e)) - ;; We return the article number. + (nnheader-report 'nnrss "article %s retrieved" (car e)) + ;; we return the article number. (cons nnrss-group (car e)))))) (deffoo nnrss-request-list (&optional server) @@ -337,6 +239,35 @@ (nnoo-define-skeleton nnrss) ;;; Internal functions +(eval-when-compile (defun xml-rpc-method-call (&rest args))) +(defun nnrss-fetch (url &optional local) + "Fetch the url and put it in a the expected lisp structure." + (with-temp-buffer + ;some CVS versions of url.el need this to close the connection quickly + (let* (xmlform htmlform) + ;; bit o' work necessary for w3 pre-cvs and post-cvs + (if local + (let ((coding-system-for-read 'binary)) + (insert-file-contents url)) + (mm-url-insert url)) + +;; Because xml-parse-region can't deal with anything that isn't +;; xml and w3-parse-buffer can't deal with some xml, we have to +;; parse with xml-parse-region first and, if that fails, parse +;; with w3-parse-buffer. Yuck. Eventually, someone should find out +;; why w3-parse-buffer fails to parse some well-formed xml and +;; fix it. + + (condition-case err + (setq xmlform (xml-parse-region (point-min) (point-max))) + (error (if (fboundp 'w3-parse-buffer) + (setq htmlform (caddar (w3-parse-buffer + (current-buffer)))) + (message "nnrss: Not valid XML and w3 parse not available (%s)" + url)))) + (if htmlform + htmlform + xmlform)))) (defun nnrss-possibly-change-group (&optional group server) (when (and server @@ -349,7 +280,7 @@ (defvar nnrss-extra-categories '(nnrss-snarf-moreover-categories)) (defun nnrss-generate-active () - (if (y-or-n-p "Fetch extra categories? ") + (if (y-or-n-p "fetch extra categories? ") (dolist (func nnrss-extra-categories) (funcall func))) (save-excursion @@ -361,7 +292,7 @@ (unless (assoc (car elem) nnrss-group-alist) (insert (prin1-to-string (car elem)) " 0 1 y\n"))))) -;;; Data functions +;;; data functions (defun nnrss-read-server-data (server) (setq nnrss-server-data nil) @@ -455,10 +386,11 @@ (mm-url-insert url))) (defun nnrss-decode-entities-unibyte-string (string) - (mm-with-unibyte-buffer - (insert string) - (mm-url-decode-entities-nbsp) - (buffer-string))) + (if string + (mm-with-unibyte-buffer + (insert string) + (mm-url-decode-entities-nbsp) + (buffer-string)))) (defalias 'nnrss-insert 'nnrss-insert-w3) @@ -469,50 +401,44 @@ ;;; Snarf functions (defun nnrss-check-group (group server) - (let (file xml subject url extra changed author date) - (condition-case err - (mm-with-unibyte-buffer - (if (and nnrss-use-local - (file-exists-p (setq file (expand-file-name - (nnrss-translate-file-chars - (concat group ".xml")) - nnrss-directory)))) - (insert-file-contents file) - (setq url (or (nth 2 (assoc group nnrss-server-data)) - (second (assoc group nnrss-group-alist)))) - (unless url - (setq url - (read-string (format "RSS url of %s: " group "http://"))) - (let ((pair (assoc group nnrss-server-data))) - (if pair - (setcdr (cdr pair) (list url)) - (push (list group nnrss-group-max url) nnrss-server-data))) - (setq changed t)) - (nnrss-insert url)) - (goto-char (point-min)) - (while (re-search-forward "\r\n?" nil t) - (replace-match "\n")) - (goto-char (point-min)) - (if (re-search-forward "<rdf\\|<rss" nil t) - (goto-char (match-beginning 0))) - (setq xml (xml-parse-region (point) (point-max)))) - (error - (nnheader-message 1 "Error in group %s: %s" group (cadr err)))) - (while (and xml (not (assq 'item xml))) - (setq xml (cddar xml)) - (while (not (listp (car xml))) - (setq xml (cdr xml)))) - (dolist (item (nreverse xml)) + (let (file xml subject url extra changed author date rss-ns rdf-ns content-ns dc-ns) + (if (and nnrss-use-local + (file-exists-p (setq file (expand-file-name + (nnrss-translate-file-chars + (concat group ".xml")) + nnrss-directory)))) + (nnrss-fetch file t) + (setq url (or (nth 2 (assoc group nnrss-server-data)) + (second (assoc group nnrss-group-alist)))) + (unless url + (setq url + (nnrss-discover-feed (read-string (format "URL to search for %s: " group) "http://"))) + (let ((pair (assoc group nnrss-server-data))) + (if pair + (setcdr (cdr pair) (list url)) + (push (list group nnrss-group-max url) nnrss-server-data))) + (setq changed t)) + (setq xml (nnrss-fetch url))) + ;; See + ;; http://feeds.archive.org/validator/docs/howto/declare_namespaces.html + ;; for more RSS namespaces. + (setq dc-ns (nnrss-get-namespace-prefix xml "http://purl.org/dc/elements/1.1/") + rdf-ns (nnrss-get-namespace-prefix xml "http://www.w3.org/1999/02/22-rdf-syntax-ns#") + rss-ns (nnrss-get-namespace-prefix xml "http://purl.org/rss/1.0/") + content-ns (nnrss-get-namespace-prefix xml "http://purl.org/rss/1.0/modules/content/")) + (dolist (item (nreverse (nnrss-find-el (intern (concat rss-ns "item")) xml))) (when (and (listp item) - (eq 'item (car item)) - (setq url (nnrss-node-text (assq 'link (cddr item)))) - (setq url (nnrss-decode-entities-unibyte-string url)) + (eq (intern (concat rss-ns "item")) (car item)) + (setq url (nnrss-decode-entities-unibyte-string + (nnrss-node-text rss-ns 'link (cddr item)))) (not (gnus-gethash url nnrss-group-hashtb))) - (setq subject (nnrss-node-text (assq 'title (cddr item)))) - (setq extra (or (nnrss-node-text (assq 'description (cddr item))) - (nnrss-node-text (assq 'dc:description (cddr item))))) - (setq author (nnrss-node-text (assq 'dc:creator (cddr item)))) - (setq date (or (nnrss-node-text (assq 'dc:date (cddr item))) + (setq subject (nnrss-node-text rss-ns 'title item)) + (setq extra (or (nnrss-node-text content-ns 'encoded item) + (nnrss-node-text rss-ns 'description item))) + (setq author (or (nnrss-node-text rss-ns 'author item) + (nnrss-node-text dc-ns 'creator item))) + (setq date (or (nnrss-node-text dc-ns 'date item) + (nnrss-node-text rss-ns 'pubDate item) (message-make-date))) (push (list @@ -565,7 +491,7 @@ (nnrss-insert nnrss-moreover-url) (goto-char (point-min)) (while (re-search-forward - "<A NAME=\"\\([^\"]+\\)\">\\|<A HREF=\"\\(http://[^\"]*moreover\\.com[^\"]+page\\?c=\\([^\"&]+\\)&o=rss\\)" nil t) + "<a name=\"\\([^\"]+\\)\">\\|<a href=\"\\(http://[^\"]*moreover\\.com[^\"]+page\\?c=\\([^\"&]+\\)&o=rss\\)" nil t) (if (match-string 1) (setq category (match-string 1)) (setq url (match-string 2) @@ -583,11 +509,240 @@ (defun nnrss-format-string (string) (gnus-replace-in-string (nnrss-string-as-multibyte string) " *\n *" " ")) -(defun nnrss-node-text (node) +(defun nnrss-node-text (namespace local-name element) + (let* ((node (assq (intern (concat namespace (symbol-name local-name))) element)) + (text (if (and node (listp node)) + (nnrss-node-just-text node) + node)) + (cleaned-text (if text + (replace-regexp-in-string + " *$" "" (replace-regexp-in-string + "^ *" "" (replace-regexp-in-string + "^[[:cntrl:]]+" "" text)))))) + (if (string-equal "" cleaned-text) + nil + cleaned-text))) + +(defun nnrss-node-just-text (node) (if (and node (listp node)) - (mapconcat 'nnrss-node-text (cddr node) "") + (mapconcat 'nnrss-node-just-text (cddr node) " ") node)) +(defun nnrss-find-el (tag data &optional found-list) + "Find the all matching elements in the data. Careful with this on +large documents!" + (if (listp data) + (mapcar (lambda (bit) + (if (car-safe bit) + (progn (if (equal tag (car bit)) + (setq found-list + (append found-list + (list bit)))) + (if (and (listp (car-safe (caddr bit))) + (not (stringp (caddr bit)))) + (setq found-list + (append found-list + (nnrss-find-el + tag (caddr bit)))) + (setq found-list + (append found-list + (nnrss-find-el + tag (cddr bit)))))))) + data)) + found-list) + +(defun nnrss-rsslink-p (el) + "Test if the element we are handed is an RSS autodiscovery link." + (and (eq (car-safe el) 'link) + (string-equal (cdr (assoc 'rel (cadr el))) "alternate") + (or (string-equal (cdr (assoc 'type (cadr el))) + "application/rss+xml") + (string-equal (cdr (assoc 'type (cadr el))) "text/xml")))) + +(defun nnrss-get-rsslinks (data) + "Extract the <link> elements that are links to RSS from the parsed data." + (delq nil (mapcar + (lambda (el) + (if (nnrss-rsslink-p el) el)) + (nnrss-find-el 'link data)))) + +(defun nnrss-extract-hrefs (data) + "Recursively extract hrefs from a page's source. DATA should be +the output of xml-parse-region or w3-parse-buffer." + (mapcar (lambda (ahref) + (cdr (assoc 'href (cadr ahref)))) + (nnrss-find-el 'a data))) + +(defmacro nnrss-match-macro (base-uri item + onsite-list offsite-list) + `(cond ((or (string-match (concat "^" ,base-uri) ,item) + (not (string-match "://" ,item))) + (setq ,onsite-list (append ,onsite-list (list ,item)))) + (t (setq ,offsite-list (append ,offsite-list (list ,item)))))) + +(defun nnrss-order-hrefs (base-uri hrefs) + "Given a list of hrefs, sort them using the following priorities: + 1. links ending in .rss + 2. links ending in .rdf + 3. links ending in .xml + 4. links containing the above + 5. offsite links + +BASE-URI is used to determine the location of the links and +whether they are `offsite' or `onsite'." + (let (rss-onsite-end rdf-onsite-end xml-onsite-end + rss-onsite-in rdf-onsite-in xml-onsite-in + rss-offsite-end rdf-offsite-end xml-offsite-end + rss-offsite-in rdf-offsite-in xml-offsite-in) + (mapcar (lambda (href) + (if (not (null href)) + (cond ((string-match "\\.rss$" href) + (nnrss-match-macro + base-uri href rss-onsite-end rss-offsite-end)) + ((string-match "\\.rdf$" href) + (nnrss-match-macro + base-uri href rdf-onsite-end rdf-offsite-end)) + ((string-match "\\.xml$" href) + (nnrss-match-macro + base-uri href xml-onsite-end xml-offsite-end)) + ((string-match "rss" href) + (nnrss-match-macro + base-uri href rss-onsite-in rss-offsite-in)) + ((string-match "rdf" href) + (nnrss-match-macro + base-uri href rdf-onsite-in rdf-offsite-in)) + ((string-match "xml" href) + (nnrss-match-macro + base-uri href xml-onsite-in xml-offsite-in))))) + hrefs) + (append + rss-onsite-end rdf-onsite-end xml-onsite-end + rss-onsite-in rdf-onsite-in xml-onsite-in + rss-offsite-end rdf-offsite-end xml-offsite-end + rss-offsite-in rdf-offsite-in xml-offsite-in))) + +(defun nnrss-discover-feed (url) + "Given a page, find an RSS feed using Mark Pilgrim's +`ultra-liberal rss locator' (http://diveintomark.org/2002/08/15.html)." + + (let ((parsed-page (nnrss-fetch url))) + +;; 1. if this url is the rss, use it. + (if (nnrss-rss-p parsed-page) + (let ((rss-ns (nnrss-get-namespace-prefix parsed-page "http://purl.org/rss/1.0/"))) + (nnrss-rss-title-description rss-ns parsed-page url)) + +;; 2. look for the <link rel="alternate" +;; type="application/rss+xml" and use that if it is there. + (let ((links (nnrss-get-rsslinks parsed-page))) + (if links + (let* ((xml (nnrss-fetch + (cdr (assoc 'href (cadar links))))) + (rss-ns (nnrss-get-namespace-prefix xml "http://purl.org/rss/1.0/"))) + (nnrss-rss-title-description rss-ns xml (cdr (assoc 'href (cadar links))))) + +;; 3. look for links on the site in the following order: +;; - onsite links ending in .rss, .rdf, or .xml +;; - onsite links containing any of the above +;; - offsite links ending in .rss, .rdf, or .xml +;; - offsite links containing any of the above + (let* ((base-uri (progn (string-match ".*://[^/]+/?" url) + (match-string 0 url))) + (hrefs (nnrss-order-hrefs + base-uri (nnrss-extract-hrefs parsed-page))) + (rss-link nil)) + (while (and (eq rss-link nil) (not (eq hrefs nil))) + (let ((href-data (nnrss-fetch (car hrefs)))) + (if (nnrss-rss-p href-data) + (let* ((rss-ns (nnrss-get-namespace-prefix href-data "http://purl.org/rss/1.0/"))) + (setq rss-link (nnrss-rss-title-description + rss-ns href-data (car hrefs)))) + (setq hrefs (cdr hrefs))))) + (if rss-link rss-link + +;; 4. check syndic8 + (nnrss-find-rss-via-syndic8 url)))))))) + +(defun nnrss-find-rss-via-syndic8 (url) + "query syndic8 for the rss feeds it has for the url." + (condition-case nil + (progn (require 'xml-rpc) + (let ((feedid (xml-rpc-method-call + "http://www.syndic8.com/xmlrpc.php" + 'syndic8.FindSites + url))) + (if feedid + (let* ((feedinfo (xml-rpc-method-call + "http://www.syndic8.com/xmlrpc.php" + 'syndic8.GetFeedInfo + feedid)) + (urllist + (delq nil + (mapcar + (lambda (listinfo) + (if (string-equal + (cdr (assoc "status" listinfo)) + "Syndicated") + (cons + (cdr (assoc "sitename" listinfo)) + (list + (cons 'title + (cdr (assoc + "sitename" listinfo))) + (cons 'href + (cdr (assoc + "dataurl" listinfo))))))) + feedinfo)))) + (if (> (length urllist) 1) + (let ((completion-ignore-case t) + (selection + (mapcar (lambda (listinfo) + (cons (cdr (assoc "sitename" listinfo)) + (string-to-int + (cdr (assoc "feedid" listinfo))))) + feedinfo))) + (cdr (assoc + (completing-read + "Multiple feeds found. Select one: " + selection nil t) urllist))) + (cdar urllist)))))) + (message "XML-RPC is not available... not checking Syndic8."))) + +(defun nnrss-rss-p (data) + "Test if data is an RSS feed. Simply ensures that the first +element is rss or rdf." + (or (eq (caar data) 'rss) + (eq (caar data) 'rdf:RDF))) + +(defun nnrss-rss-title-description (rss-namespace data url) + "Return the title of an RSS feed." + (if (nnrss-rss-p data) + (let ((description (intern (concat rss-namespace "description"))) + (title (intern (concat rss-namespace "title"))) + (channel (nnrss-find-el (intern (concat rss-namespace "channel")) + data))) + (list + (cons 'description (caddr (nth 0 (nnrss-find-el description channel)))) + (cons 'title (caddr (nth 0 (nnrss-find-el title channel)))) + (cons 'href url))))) + +(defun nnrss-get-namespace-prefix (el uri) + "Given EL (containing a parsed element) and URI (containing a string +that gives the URI for which you want to retrieve the namespace +prefix), return the prefix." + (let* ((prefix (car (rassoc uri (cadar el)))) + (nslist (if prefix + (split-string (symbol-name prefix) ":"))) + (ns (cond ((eq (length nslist) 1) ; no prefix given + "") + ((eq (length nslist) 2) ; extract prefix + (cadr nslist))))) + (if (and ns (not (eq ns ""))) + (concat ns ":") + ns))) + (provide 'nnrss) + ;;; nnrss.el ends here + Index: gnus/lisp/nntp.el diff -u gnus/lisp/nntp.el:6.53 gnus/lisp/nntp.el:6.55 --- gnus/lisp/nntp.el:6.53 Tue Mar 4 02:59:15 2003 +++ gnus/lisp/nntp.el Mon Mar 31 19:07:31 2003 @@ -75,6 +75,7 @@ Direct connections: - `nntp-open-network-stream' (the default), - `nntp-open-ssl-stream', +- `nntp-open-tls-stream', - `nntp-open-telnet-stream'. Indirect connections: @@ -207,13 +208,6 @@ "*Hook run just before posting an article. It is supposed to be used to insert Cancel-Lock headers.") -(defvoo nntp-read-timeout (if (string-match "windows-nt\\|os/2\\|emx\\|cygwin" - (symbol-name system-type)) - 1.0 - 0.1) - "How long nntp should wait between checking for the end of output. -Shorter values mean quicker response, but is more CPU intensive.") - ;;; Internal variables. (defvar nntp-record-commands nil @@ -1161,7 +1155,19 @@ (process-kill-without-query proc) (save-excursion (set-buffer buffer) - (nntp-wait-for-string "^\r*20[01]") + (let ((nntp-connection-alist (list proc buffer nil))) + (nntp-wait-for-string "^\r*20[01]")) + (beginning-of-line) + (delete-region (point-min) (point)) + proc))) + +(defun nntp-open-tls-stream (buffer) + (let ((proc (open-tls-stream "nntpd" buffer nntp-address nntp-port-number))) + (process-kill-without-query proc) + (save-excursion + (set-buffer buffer) + (let ((nntp-connection-alist (list proc buffer nil))) + (nntp-wait-for-string "^\r*20[01]")) (beginning-of-line) (delete-region (point-min) (point)) proc))) @@ -1295,12 +1301,7 @@ (unless (< len 10) (setq nntp-have-messaged t) (nnheader-message 7 "nntp read: %dk" len))) - (accept-process-output - process - (truncate nntp-read-timeout) - (truncate (* (- nntp-read-timeout - (truncate nntp-read-timeout)) - 1000))) + (nnheader-accept-process-output process) ;; accept-process-output may update status of process to indicate ;; that the server has closed the connection. This MUST be ;; handled here as the buffer restored by the save-excursion may Index: gnus/lisp/pop3.el diff -u gnus/lisp/pop3.el:6.19 gnus/lisp/pop3.el:6.20 --- gnus/lisp/pop3.el:6.19 Thu Mar 6 05:46:23 2003 +++ gnus/lisp/pop3.el Mon Mar 31 19:19:37 2003 @@ -174,7 +174,7 @@ (set-buffer (process-buffer process)) (goto-char pop3-read-point) (while (not (search-forward "\r\n" nil t)) - (accept-process-output process 0 500) + (nnheader-accept-process-output process) (goto-char pop3-read-point)) (setq match-end (point)) (goto-char pop3-read-point) @@ -348,7 +348,7 @@ (save-excursion (set-buffer (process-buffer process)) (while (not (re-search-forward "^\\.\r\n" nil t)) - (accept-process-output process 0 500) + (nnheader-accept-process-output process) ;; [email protected] ... to save wear and tear on the heap ;; uncommented because the condensed version below is a problem for ;; some. Index: gnus/lisp/rfc2047.el diff -u gnus/lisp/rfc2047.el:6.38 gnus/lisp/rfc2047.el:6.39 --- gnus/lisp/rfc2047.el:6.38 Fri Mar 14 23:33:59 2003 +++ gnus/lisp/rfc2047.el Sun Mar 23 15:43:08 2003 @@ -42,6 +42,7 @@ (defvar rfc2047-header-encoding-alist '(("Newsgroups" . nil) + ("Followup-To" . nil) ("Message-ID" . nil) ("\\(Resent-\\)?\\(From\\|Cc\\|To\\|Bcc\\|Reply-To\\|Sender\\)" . "-A-Za-z0-9!*+/=_") Index: gnus/lisp/rfc2231.el diff -u gnus/lisp/rfc2231.el:6.7 gnus/lisp/rfc2231.el:6.8 --- gnus/lisp/rfc2231.el:6.7 Tue Feb 19 18:13:13 2002 +++ gnus/lisp/rfc2231.el Thu Mar 20 23:55:39 2003 @@ -151,9 +151,9 @@ ;; Encode using the charset, if any. (when (and (mm-multibyte-p) (> (length elems) 1) - (not (equal (intern (car elems)) 'us-ascii))) + (not (equal (intern (downcase (car elems))) 'us-ascii))) (mm-decode-coding-region (point-min) (point-max) - (intern (car elems)))) + (intern (downcase (car elems))))) (buffer-string)))) (defun rfc2231-encode-string (param value) Index: gnus/lisp/smiley.el diff -u gnus/lisp/smiley.el:6.12 gnus/lisp/smiley.el:6.13 --- gnus/lisp/smiley.el:6.12 Sat Feb 8 22:20:53 2003 +++ gnus/lisp/smiley.el Wed Mar 26 21:48:26 2003 @@ -135,6 +135,16 @@ (gnus-put-image image string)))) images)))) +;;;###autoload +(defun smiley-buffer (&optional buffer) + "Run `smiley-region' at the buffer, specified in the argument or +interactively. If there's no argument, do it at the current buffer" + (interactive "bBuffer to run smiley-region: ") + (save-excursion + (if buffer + (set-buffer (get-buffer buffer))) + (smiley-region (point-min) (point-max)))) + (defun smiley-toggle-buffer (&optional arg) "Toggle displaying smiley faces in article buffer. With arg, turn displaying on if and only if arg is positive." Index: gnus/lisp/spam.el diff -u gnus/lisp/spam.el:6.85 gnus/lisp/spam.el:6.87 --- gnus/lisp/spam.el:6.85 Sat Mar 8 18:47:18 2003 +++ gnus/lisp/spam.el Thu Mar 20 00:05:57 2003 @@ -190,29 +190,6 @@ :type 'regexp :group 'spam) -(defcustom spam-ham-marks (list 'gnus-del-mark 'gnus-read-mark - 'gnus-killed-mark 'gnus-kill-file-mark - 'gnus-low-score-mark) - "Marks considered as being ham (positively not spam). -Such articles will be processed as ham (non-spam) on group exit." - :type '(set - (variable-item gnus-del-mark) - (variable-item gnus-read-mark) - (variable-item gnus-killed-mark) - (variable-item gnus-kill-file-mark) - (variable-item gnus-low-score-mark)) - :group 'spam) - -(defcustom spam-spam-marks (list 'gnus-spam-mark) - "Marks considered as being spam (positively spam). -Such articles will be transmitted to `bogofilter -s' on group exit." - :type '(set - (variable-item gnus-spam-mark) - (variable-item gnus-killed-mark) - (variable-item gnus-kill-file-mark) - (variable-item gnus-low-score-mark)) - :group 'spam) - (defcustom spam-face 'gnus-splash-face "Face for spam-marked articles" :type 'face @@ -316,6 +293,29 @@ gnus-summary-highlight) ;; convenience functions +(defun spam-group-ham-mark-p (group mark &optional spam) + (when (stringp group) + (let* ((marks (spam-group-ham-marks group spam)) + (marks (if (symbolp mark) + marks + (mapcar 'symbol-value marks)))) + (memq mark marks)))) + +(defun spam-group-spam-mark-p (group mark) + (spam-group-ham-mark-p group mark t)) + +(defun spam-group-ham-marks (group &optional spam) + (when (stringp group) + (let* ((marks (if spam + (gnus-parameter-spam-marks group) + (gnus-parameter-ham-marks group))) + (marks (car marks)) + (marks (if (listp (car marks)) (car marks) marks))) + marks))) + +(defun spam-group-spam-marks (group) + (spam-group-ham-marks group t)) + (defun spam-group-spam-contents-p (group) (if (stringp group) (or (member group spam-junk-mailgroups) @@ -469,13 +469,12 @@ (defun spam-ham-move-routine (&optional group copy) (gnus-summary-kill-process-mark) (let ((articles gnus-newsgroup-articles) - article ham-mark-values mark tomove) + article mark tomove) (when (stringp group) ; this routine will do nothing ; without a valid group - (dolist (mark spam-ham-marks) - (push (symbol-value mark) ham-mark-values)) (dolist (article articles) - (when (memq (gnus-summary-article-mark article) ham-mark-values) + (when (spam-group-spam-mark-p gnus-newsgroup-name + (gnus-summary-article-mark article)) (push article tomove))) ;; now do the actual move @@ -491,24 +490,17 @@ (defun spam-generic-register-routine (spam-func ham-func) (let ((articles gnus-newsgroup-articles) - article mark ham-articles spam-articles spam-mark-values - ham-mark-values) - - ;; marks are stored as symbolic values, so we have to dereference - ;; them for memq to work. we wouldn't have to do this if - ;; gnus-summary-article-mark returned a symbol. - (dolist (mark spam-ham-marks) - (push (symbol-value mark) ham-mark-values)) - - (dolist (mark spam-spam-marks) - (push (symbol-value mark) spam-mark-values)) + article mark ham-articles spam-articles) (while articles (setq article (pop articles) mark (gnus-summary-article-mark article)) - (cond ((memq mark spam-mark-values) (push article spam-articles)) + (cond ((spam-group-spam-mark-p gnus-newsgroup-name mark) + (push article spam-articles)) ((memq article gnus-newsgroup-saved)) - ((memq mark ham-mark-values) (push article ham-articles)))) + ((spam-group-ham-mark-p gnus-newsgroup-name mark) + (push article ham-articles)))) + (when (and ham-articles ham-func) (mapc ham-func ham-articles)) ; we use mapc because unlike ; mapcar it discards the Index: gnus/lisp/tls.el diff -u /dev/null gnus/lisp/tls.el:6.1 --- /dev/null Mon Mar 31 20:10:00 2003 +++ gnus/lisp/tls.el Sun Mar 23 14:57:08 2003 @@ -0,0 +1,127 @@ +;;; tls.el --- TLS/SSL support via wrapper around GnuTLS + +;; Copyright (C) 2003 Free Software Foundation, Inc. + +;; Author: Simon Josefsson <[email protected]> +;; Keywords: comm, tls, gnutls, ssl + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; This package implements a simple wrapper around "gnutls-cli" to +;; make Emacs support TLS/SSL. +;; +;; Usage is the same as `open-network-stream', i.e.: +;; +;; (setq tmp (open-tls-stream "test" (current-buffer) "news.mozilla.org" 563)) +;; ... +;; #<process test> +;; (process-send-string tmp "mode reader\n") +;; 200 secnews.netscape.com Netscape-Collabra/3.52 03615 NNRP ready ... +;; nil +;; (process-send-string tmp "quit\n") +;; 205 +;; nil + +;; To use this package as a replacement for ssl.el by William M. Perry +;; <[email protected]>, you need to evaluate the following: +;; +;; (defalias 'open-ssl-stream 'open-tls-stream) + +;;; Code: + +(eval-and-compile + (autoload 'format-spec "format-spec") + (autoload 'format-spec-make "format-spec")) + +(defgroup tls nil + "Transport Layer Security (TLS) parameters." + :group 'comm) + +(defcustom tls-program '("gnutls-cli -p %p %h" + "gnutls-cli -p %p %h --protocols ssl3") + "List of strings containing commands to start TLS stream to a host. +Each entry in the list is tried until a connection is successful. +%s is replaced with server hostname, %p with port to connect to. +The program should read input on stdin and write output to +stdout. Also see `tls-success' for what the program should output +after successful negotiation." + :type '(repeat string) + :group 'tls) + +(defcustom tls-process-connection-type nil + "*Value for `process-connection-type' to use when starting process." + :type 'boolean + :group 'tls) + +(defcustom tls-success "- Handshake was completed" + "*Regular expression indicating completed TLS handshakes. +The default is what GNUTLS's \"gnutls-cli\" outputs." + :type 'regexp + :group 'tls) + +(defun open-tls-stream (name buffer host service) + "Open a TLS connection for a service to a host. +Returns a subprocess-object to represent the connection. +Input and output work as for subprocesses; `delete-process' closes it. +Args are NAME BUFFER HOST SERVICE. +NAME is name for process. It is modified if necessary to make it unique. +BUFFER is the buffer (or buffer-name) to associate with the process. + Process output goes at end of that buffer, unless you specify + an output stream or filter function to handle the output. + BUFFER may be also nil, meaning that this process is not associated + with any buffer +Third arg is name of the host to connect to, or its IP address. +Fourth arg SERVICE is name of the service desired, or an integer +specifying a port number to connect to." + (let ((cmds tls-program) cmd done) + (message "Opening TLS connection to `%s'..." host) + (while (and (not done) (setq cmd (pop cmds))) + (message "Opening TLS connection with `%s'..." cmd) + (let* ((process-connection-type tls-process-connection-type) + (process (start-process + name buffer shell-file-name shell-command-switch + (format-spec + cmd + (format-spec-make + ?h host + ?p (if (integerp service) + (int-to-string service) + service))))) + response) + (while (and process + (memq (process-status process) '(open run)) + (save-excursion + (set-buffer buffer) ;; XXX "blue moon" nntp.el bug + (goto-char (point-min)) + (not (setq done (re-search-forward tls-success nil t))))) + (accept-process-output process 1) + (sit-for 1)) + (message "Opening TLS connection with `%s'...%s" cmd + (if done "done" "failed")) + (if done + (setq done process) + (delete-process process)))) + (message "Opening TLS connection to `%s'...%s" + host (if done "done" "failed")) + done)) + +(provide 'tls) + +;;; tls.el ends here Index: gnus/texi/ChangeLog diff -u gnus/texi/ChangeLog:6.481 gnus/texi/ChangeLog:6.497 --- gnus/texi/ChangeLog:6.481 Mon Mar 17 17:09:30 2003 +++ gnus/texi/ChangeLog Mon Mar 31 19:49:45 2003 @@ -1,3 +1,80 @@ +2003-03-31 Lars Magne Ingebrigtsen <[email protected]> + + * gnus.texi (Exiting Gnus): Removed gnus-unload. + +2003-03-31 Simon Josefsson <[email protected]> + + * gnus.texi (IMAP): Add. + +2003-03-27 Paul Jarc <[email protected]> + + * gnus.texi (Comparing Mail Back Ends): Note nnmaildir's + incompatibilities more prominently. + +2003-03-27 Paul Jarc <[email protected]> + + * gnus.texi (Maildir): Note nnmail-expiry-target incompatibility. + +2003-03-27 Jesper Harder <[email protected]> + + * gnus.texi (Adaptive Scoring): Fix. + +2003-03-23 Simon Josefsson <[email protected]> + + * gnus.texi (Direct Functions, Common Variables) + (Mail Source Specifiers, IMAP): Add TLS wherever SSL is mentioned + now. + +2003-03-23 Jesper Harder <[email protected]> + + * gnus.texi (Group Information, Article Washing) + (Formatting Fonts, Group Parameters): Fix external xrefs. + + * message.texi (Mailing Lists): do. + +2003-03-22 Simon Josefsson <[email protected]> + + * gnus.texi (Troubleshooting): Fix typo. + (Drafts): Mention how to restore special property, suggested by + Florian Weimer <[email protected]>. + +2003-03-19 Simon Josefsson <[email protected]> + + * gnus.texi (Misc Article): Add. + (Agent Basics): Fix makeinfo warnings. + + * message.texi (IDNA): New. + +2003-03-18 Kevin Greiner <[email protected]> + + * gnus.texi (Gnus Unplugged): Refer to new agent Group/Topic + parameters. + (Category Syntax): New description. + (Category Buffer): New command. + (Category Variables): New variables. + (Agent as Cache): Expanded description. + (Agent Expiry): Expanded description. + (Agent Variables): Fixed and new descriptions. + + * infohack.el (batch-makeinfo): Provide local implementation of + subst-char-in-region as the built-in implementation is unreliable + on Windows XP (Intermittent failure results in build looping + forever). + +2003-03-18 Paul Jarc <[email protected]> + + * gnus.texi (Maildir): Replace create-directory with + target-prefix. + +2003-03-18 Paul Jarc <[email protected]> + + * gnus.texi (Maildir): More info for expire-group; add + distrust-Lines:. + +2003-03-17 Paul Jarc <[email protected]> + + * gnus.texi (Comparing Mail Back Ends): nnmaildir fixes. + 2003-03-17 Reiner Steib <[email protected]> * gnus.texi (Using MIME): Added gnus-mime-delete-part. @@ -157,7 +234,7 @@ (Mail Group Commands): do. * gnus.texi: Mark-up fixes. - + 2003-01-27 Teodor Zlatanov <[email protected]> * gnus.texi: replace `H' mark with `$' mark @@ -215,7 +292,7 @@ (gnus-agent-mark-unread-after-downloaded): New variable. (gnus-agent-consider-all-articles): New variable. (gnus-agent-max-fetch-size): New variable. - + 2003-01-22 Jesper Harder <[email protected]> * gnusref.tex (subsection*{Notes}): do. @@ -236,11 +313,11 @@ * gnus.texi: Markup fixes: use @code for nil and t, use @file for files. - + * message.texi: do. * emacs-mime.texi: do. - + 2003-01-19 Jesper Harder <[email protected]> * dir (File): Add pgg. @@ -265,9 +342,9 @@ 2003-01-15 ShengHuo ZHU <[email protected]> - * gnus.texi: Don't use `path' in some cases. + * gnus.texi: Don't use `path' in some cases. From the GNU coding standards: - + Please do not use the term ``pathname'' that is used in Unix documentation; use ``file name'' (two words) instead. We use the term ``path'' only for search paths, which are lists of @@ -342,7 +419,7 @@ 2003-01-09 Teodor Zlatanov <[email protected]> - * gnus.texi (Filtering Spam Using spam.el, ifile spam filtering) + * gnus.texi (Filtering Spam Using spam.el, ifile spam filtering) (spam-stat spam filtering): added new functionality and explained old functionality better, especially where it has changed in ham/spam/unclassified group exit processing. @@ -394,8 +471,8 @@ 2003-01-05 Teodor Zlatanov <[email protected]> - * gnus.texi (Filtering Spam Using spam.el) - (Blacklists and Whitelists, BBDB Whitelists, Blackholes) + * gnus.texi (Filtering Spam Using spam.el) + (Blacklists and Whitelists, BBDB Whitelists, Blackholes) (Bogofilter, Ifile spam filtering, Extending spam.el): updated documentation for the new spam.el functionality @@ -458,7 +535,7 @@ 2002-12-29 Lars Magne Ingebrigtsen <[email protected]> * gnus.texi (Loose Threads): add - gnus-summary-make-false-root-always. + gnus-summary-make-false-root-always. (Finding the Parent): Change name of nnweb server. 2002-12-22 Jesper Harder <[email protected]> @@ -476,7 +553,7 @@ * gnus.texi (Optional Back End Functions): nnchoke-request-update-info need not return the info object. - + 2002-12-15 Jesper Harder <[email protected]> * gnusref.tex: Additions. Index: gnus/texi/gnus.texi diff -u gnus/texi/gnus.texi:6.442 gnus/texi/gnus.texi:6.460 --- gnus/texi/gnus.texi:6.442 Tue Mar 18 00:38:34 2003 +++ gnus/texi/gnus.texi Mon Mar 31 20:08:32 2003 @@ -33,7 +33,7 @@ \makeindex \begin{document} -\newcommand{\gnusversionname}{Oort Gnus v0.16} +\newcommand{\gnusversionname}{Oort Gnus v0.17} \newcommand{\gnuschaptername}{} \newcommand{\gnussectionname}{} @@ -387,7 +387,7 @@ spool or your mbox file. All at the same time, if you want to push your luck. -This manual corresponds to Oort Gnus v0.16. +This manual corresponds to Oort Gnus v0.17. @end ifinfo @@ -2725,8 +2725,9 @@ to-address and to-list parameters for this group as addresses of mailing lists you are subscribed to. Giving Gnus this information is (only) a first step in getting it to generate correct Mail-Followup-To -headers for your posts to these lists. Look here @pxref{(message)Mailing -Lists} for a complete treatment of available MFT support. +headers for your posts to these lists. Look here @pxref{Mailing +Lists, , Mailing Lists, message, The Message Manual} for a complete +treatment of available MFT support. See also @code{gnus-find-subscribed-addresses}, the function that directly uses this group parameter. @@ -3432,12 +3433,6 @@ @code{gnus-after-exiting-gnus-hook} is called as the final item when exiting Gnus. -@findex gnus-unload -@cindex unloading -If you wish to completely unload Gnus and all its adherents, you can use -the @code{gnus-unload} command. This command is also very handy when -trying to customize meta-variables. - Note: @quotation @@ -4157,8 +4152,8 @@ and displayed in an ephemeral group. Note that the control messages are compressed. To use this command -you need to turn on @code{auto-compression-mode} -(@pxref{(emacs)Compressed Files}). +you need to turn on @code{auto-compression-mode} (@pxref{Compressed +Files, ,Compressed Files, emacs, The Emacs Manual}). @item H d @itemx C-c C-d @@ -8465,10 +8460,11 @@ @vindex gnus-article-wash-function The default is to use the function specified by -@code{mm-text-html-renderer} (@pxref{(emacs-mime)Display -Customization}) to convert the @sc{html}, but this is controlled by -the @code{gnus-article-wash-function} variable. Pre-defined functions -you can use include: +@code{mm-text-html-renderer} (@pxref{Display Customization, ,Display +Customization, emacs-mime, The Emacs MIME Manual}) to convert the +@sc{html}, but this is controlled by the +@code{gnus-article-wash-function} variable. Pre-defined functions you +can use include: @table @code @item w3 @@ -11043,6 +11039,17 @@ @vindex gnus-page-delimiter This is the delimiter mentioned above. By default, it is @samp{^L} (formfeed). + +@cindex IDNA +@cindex internationalized domain names +@vindex gnus-use-idna +@item gnus-use-idna +This variable controls whether Gnus performs IDNA decoding of +internationalized domain names inside @sc{From:}, @sc{To:} and +@sc{Cc:} headers. This requires GNU Libidn +(@url{http://www.gnu.org/software/libidn/}, and this variable is only +enabled if you have installed it. + @end table @@ -11550,7 +11557,13 @@ If the group doesn't exist, it will be created and you'll be subscribed to it. The only way to make it disappear from the Group buffer is to -unsubscribe it. +unsubscribe it. The special properties of the draft group comes from +a group property (@pxref{Group Parameters}), and if lost the group +behaves like any other group. This means the commands below will not +be available. To restore the special properties of the group, the +simplest way is to kill the group, using @kbd{C-k}, and restart +Gnus. The group is automatically created again with the +correct parameters. The content of the group is not lost. @c @findex gnus-dissociate-buffer-from-draft @c @kindex C-c M-d (Mail) @@ -12399,6 +12412,23 @@ This is the default, and simply connects to some port or other on the remote system. +@findex nntp-open-tls-stream +@item nntp-open-tls-stream +Opens a connection to a server over a @dfn{secure} channel. To use +this you must have GNUTLS installed (see +@uref{http://www.gnu.org/software/gnutls/}). You then define a server +as follows: + +@lisp +;; "nntps" is port 563 and is predefined in our /etc/services +;; however, gnutls-cli -p doesn't like named ports. +;; +(nntp "snews.bar.com" + (nntp-open-connection-function nntp-open-tls-stream) + (nntp-port-number ) + (nntp-address "snews.bar.com")) +@end lisp + @findex nntp-open-ssl-stream @item nntp-open-ssl-stream Opens a connection to a server over a @dfn{secure} channel. To use this @@ -12407,10 +12437,8 @@ define a server as follows: @lisp -;; Type `C-c C-c' after you've finished editing. -;; ;; "snews" is port 563 and is predefined in our /etc/services -;; however, openssl s_client -port doesn't like named ports +;; however, openssl s_client -port doesn't like named ports. ;; (nntp "snews.bar.com" (nntp-open-connection-function nntp-open-ssl-stream) @@ -12540,10 +12568,10 @@ @item nntp-pre-command @vindex nntp-pre-command -A command wrapper to use when connecting through a non native connection -function (all except @code{nntp-open-network-stream} and -@code{nntp-open-ssl-stream}. This is where you would put a @samp{SOCKS} -wrapper for instance. +A command wrapper to use when connecting through a non native +connection function (all except @code{nntp-open-network-stream}, +@code{nntp-open-tls-stream}, and @code{nntp-open-ssl-stream}. This is +where you would put a @samp{SOCKS} wrapper for instance. @item nntp-address @vindex nntp-address @@ -12551,10 +12579,11 @@ @item nntp-port-number @vindex nntp-port-number -Port number to connect to the @sc{nntp} server. The default is @samp{nntp}. -If you use @sc{nntp} over @sc{ssl}, you may want to use integer ports rather -than named ports (i.e, use @samp{563} instead of @samp{snews}), because -external SSL tools may not work with named ports. +Port number to connect to the @sc{nntp} server. The default is +@samp{nntp}. If you use @sc{nntp} over @sc{tls}/@sc{ssl}, you may +want to use integer ports rather than named ports (i.e, use @samp{563} +instead of @samp{snews} or @samp{nntps}), because external TLS/SSL +tools may not work with named ports. @item nntp-end-of-line @vindex nntp-end-of-line @@ -13171,7 +13200,7 @@ and fetches articles from a given @sc{imap} mailbox. @xref{IMAP}, for more information. -Note that for the Kerberos, GSSAPI, SSL/TLS and STARTTLS support you +Note that for the Kerberos, GSSAPI, TLS/SSL and STARTTLS support you may need external programs and libraries, @xref{IMAP}. Keywords: @@ -13183,7 +13212,7 @@ @item :port The port number of the @sc{imap} server. The default is @samp{143}, or -@samp{993} for SSL/TLS connections. +@samp{993} for TLS/SSL connections. @item :user The user name to give to the @sc{imap} server. The default is the login @@ -13196,8 +13225,8 @@ @item :stream What stream to use for connecting to the server, this is one of the symbols in @code{imap-stream-alist}. Right now, this means -@samp{gssapi}, @samp{kerberos4}, @samp{starttls}, @samp{ssl}, -@samp{shell} or the default @samp{network}. +@samp{gssapi}, @samp{kerberos4}, @samp{starttls}, @samp{tls}, +@samp{ssl}, @samp{shell} or the default @samp{network}. @item :authentication Which authenticator to use for authenticating to the server, this is @@ -14543,18 +14572,14 @@ @item directory For each of your nnmaildir servers (it's very unlikely that you'd need more than one), you need to create a directory and populate it with -symlinks to maildirs (and nothing else; do not choose a directory -already used for other purposes). You could also put maildirs -themselves (instead of symlinks to them) directly in the server -directory, but that would break @code{nnmaildir-request-delete-group}, -so you wouldn't be able to delete those groups from within Gnus. (You -could still delete them from your shell with @code{rm -r foo}.) Each -maildir will be represented in Gnus as a newsgroup on that server; the -filename of the symlink will be the name of the group. Any filenames -in the directory starting with `.' are ignored. The directory is -scanned when you first start Gnus, and each time you type @kbd{g} in -the group buffer; if any maildirs have been removed or added, -nnmaildir notices at these times. +maildirs or symlinks to maildirs (and nothing else; do not choose a +directory already used for other purposes). Each maildir will be +represented in Gnus as a newsgroup on that server; the filename of the +symlink will be the name of the group. Any filenames in the directory +starting with `.' are ignored. The directory is scanned when you +first start Gnus, and each time you type @kbd{g} in the group buffer; +if any maildirs have been removed or added, nnmaildir notices at these +times. The value of the @code{directory} parameter should be a Lisp form which is processed by @code{eval} and @code{expand-file-name} to get @@ -14562,23 +14587,38 @@ only when the server is opened; the resulting string is used until the server is closed. (If you don't know about forms and @code{eval}, don't worry - a simple string will work.) This parameter is not -optional; you must specify it. I don't recommend using @file{~/Mail} -or a subdirectory of it; several other parts of Gnus use that -directory by default for various things, and may get confused if -nnmaildir uses it too. @file{~/.nnmaildir} is a typical value. +optional; you must specify it. I don't recommend using +@code{"~/Mail"} or a subdirectory of it; several other parts of Gnus +use that directory by default for various things, and may get confused +if nnmaildir uses it too. @code{"~/.nnmaildir"} is a typical value. -@item create-directory +@item target-prefix This should be a Lisp form which is processed by @code{eval} and -@code{expand-file-name} to get the name of the directory where new -maildirs are created. The form is @code{eval}ed only when the server -is opened; the resulting string is used until the server is closed. -This parameter is optional, but if you do not supply it, you cannot -create new groups from within Gnus. (You could still create them from -your shell with @code{mkdir -m 0700 foo foo/tmp foo/new foo/cur}.) A -relative path is interpreted as relative to the @code{directory} path. -@code{create-directory} and @code{directory} must be different; -otherwise, group creation and deletion will break. (If you don't need -those features, you can omit @code{create-directory} entirely.) +@code{expand-file-name}. The form is @code{eval}ed only when the +server is opened; the resulting string is used until the server is +closed. + +When you create a group on an nnmaildir server, the maildir is created +with @code{target-prefix} prepended to its name, and a symlink +pointing to that maildir is created, named with the plain group name. +So if @code{directory} is @code{"~/.nnmaildir"} and +@code{target-prefix} is @code{"../maildirs/"}, then when you create +the group @code{foo}, nnmaildir will create +@file{~/.nnmaildir/../maildirs/foo} as a maildir, and will create +@file{~/.nnmaildir/foo} as a symlink pointing to +@file{../maildirs/foo}. + +You can set @code{target-prefix} to a string without any slashes to +create both maildirs and symlinks in the same @code{directory}; in +this case, any maildirs found in @code{directory} whose names start +with @code{target-prefix} will not be listed as groups (but the +symlinks pointing to them will be). + +As a special case, if @code{target-prefix} is @code{""} (the default), +then when you create a group, the maildir will be created in +@code{directory} without a corresponding symlink. Beware that you +cannot use @code{gnus-group-delete-group} on such groups without the +@code{force} argument. @item directory-files This should be a function with the same interface as @@ -14647,8 +14687,15 @@ articles will be moved to the specified group during expiry before being deleted. @emph{If this is set to an nnmaildir group, the article will be just as old in the destination group as it was in the -source group.} So be careful with @code{expire-age} in the destination -group. +source group.} So be careful with @code{expire-age} in the +destination group. If this is set to the name of the same group that +the parameter belongs to, then the article is not expired at all. If +you use the vector form, the first element is evaluated once for each +article. So that form can refer to +@code{nnmaildir-article-file-name}, etc., to decide where to put the +article. @emph{If this parameter is not set, nnmaildir does not fall +back to the @code{expiry-target} group parameter or the +@code{nnmail-expiry-target} variable.} @item read-only If this is set to @code{t}, nnmaildir will treat the articles in this @@ -14669,6 +14716,11 @@ group to find articles. The default is the function specified by the server's @code{directory-files} parameter. +@item distrust-Lines: +If non-@code{nil}, nnmaildir will always count the lines of an +article, rather than use the @code{Lines:} header field. If +@code{nil}, the header field will be used if present. + @item always-marks A list of mark symbols, such as @code{['(read expire)]}. Whenever Gnus asks nnmaildir for @@ -14972,6 +15024,10 @@ @item nnmaildir +For configuring expiry and other things, @code{nnmaildir} uses +incompatible group parameters, slightly different from those of other +mail back ends. + @code{nnmaildir} is largely similar to @code{nnml}, with some notable differences. Each message is stored in a separate file, but the filename is unrelated to the article number in Gnus. @code{nnmaildir} @@ -14991,16 +15047,8 @@ thus damaging message bodies), and another set to be used as groups (in whatever format you like). A maildir has a built-in spool, in the @code{new/} subdirectory. Beware that currently, mail moved from -@code{new/} to @code{cur/} instead of via mail splitting will undergo -treatment such as duplicate checking. - -An article will not necessarily keep the same number across Gnus -sessions; articles are renumbered starting from 1 for each Gnus session -(more precisely, each time you open the @code{nnmaildir} server). This -way, you don't get gaps in your article number ranges, and when entering -large groups, Gnus is likely to give a more accurate article count. The -price is that @code{nnmaildir} doesn't work with the cache or agent. -This will probably be changed in the future. +@code{new/} to @code{cur/} instead of via mail splitting will not +undergo treatment such as duplicate checking. @code{nnmaildir} stores article marks for a given group in the corresponding maildir, in a way designed so that it's easy to manipulate @@ -15009,19 +15057,17 @@ it's not as easy to work with them from outside Gnus as with @code{nnmaildir}. -For configuring expiry and other things, @code{nnmaildir} uses group -parameters slightly different from those of other mail back ends. - @code{nnmaildir} uses a significant amount of memory to speed things up. (It keeps in memory some of the things that @code{nnml} stores in files and that @code{nnmh} repeatedly parses out of message files.) If this is a problem for you, you can set the @code{nov-cache-size} group parameter to something small (0 would probably not work, but 1 probably -would) to make it use less memory. +would) to make it use less memory. This caching will probably be +removed in the future. -Startup and shutdown are likely to be slower with @code{nnmaildir} than -with other back ends. Everything in between is likely to be faster, -depending in part on your file system. +Startup is likely to be slower with @code{nnmaildir} than with other +back ends. Everything else is likely to be faster, depending in part +on your file system. @code{nnmaildir} does not use @code{nnoo}, so you cannot use @code{nnoo} to write an @code{nnmaildir}-derived back end. @@ -15476,7 +15522,7 @@ usage explained in this section. A server configuration in @file{~/.gnus} with a few @sc{imap} servers -might look something like the following. (Note that for SSL/TLS, you +might look something like the following. (Note that for TLS/SSL, you need external programs and libraries, see below.) @lisp @@ -15521,7 +15567,7 @@ @item nnimap-server-port @vindex nnimap-server-port -Port on server to contact. Defaults to port 143, or 993 for SSL. +Port on server to contact. Defaults to port 143, or 993 for TLS/SSL. Note that this should be an integer, example server specification: @@ -15555,7 +15601,7 @@ @vindex nnimap-stream The type of stream used to connect to your server. By default, nnimap will detect and automatically use all of the below, with the exception -of SSL/TLS. (@sc{imap} over SSL/TLS is being replaced by STARTTLS, which +of TLS/SSL. (@sc{imap} over TLS/SSL is being replaced by STARTTLS, which can be automatically detected, but it's not widely deployed yet.) Example server specification: @@ -15570,14 +15616,17 @@ @itemize @bullet @item @dfn{gssapi:} Connect with GSSAPI (usually Kerberos 5). Requires the -@samp{imtest} program. +@samp{gsasl} or @samp{imtest} program. @item @dfn{kerberos4:} Connect with Kerberos 4. Requires the @samp{imtest} program. @item @dfn{starttls:} Connect via the STARTTLS extension (similar to -SSL). Requires the external library @samp{starttls.el} and program +TLS/SSL). Requires the external library @samp{starttls.el} and program @samp{starttls}. @item +@dfn{tls:} Connect through TLS. Requires GNUTLS (the program +@samp{gnutls-cli}). +@item @dfn{ssl:} Connect through SSL. Requires OpenSSL (the program @samp{openssl}) or SSLeay (@samp{s_client}). @item @@ -15597,6 +15646,19 @@ @code{imap-kerberos4-program} contain parameters to pass to the imtest program. +For TLS connection, the @code{gnutls-cli} program from GNUTLS is +needed. It is available from +@uref{http://www.gnu.org/software/gnutls/}. + +@vindex imap-gssapi-program +This parameter specifies a list of command lines that invoke a GSSAPI +authenticated IMAP stream in a subshell. They are tried sequentially +until a connection is made, or the list has been exhausted. By +default, @samp{gsasl} from GNU SASL, available from +@uref{http://www.gnu.org/software/gsasl/}, and the @samp{imtest} +program from Cyrus IMAPD (see @code{imap-kerberos4-program}), are +tried. + @vindex imap-ssl-program For SSL connections, the OpenSSL program is available from @uref{http://www.openssl.org/}. OpenSSL was formerly known as SSLeay, @@ -15629,7 +15691,7 @@ @itemize @bullet @item @dfn{gssapi:} GSSAPI (usually kerberos 5) authentication. Requires -external program @code{imtest}. +external program @code{gsasl} or @code{imtest}. @item @dfn{kerberos4:} Kerberos 4 authentication. Requires external program @code{imtest}. @@ -17010,7 +17072,19 @@ @code{gnus-secondary-select-methods} are agentized. @item -Decide on download policy. @xref{Agent Categories}. + +Decide on download policy. It's fairly simple once you decide whether +you are going to use agent categories, topic parameters, and/or group +parameters to implement your policy. If you're new to gnus, it +is probably best to start with a category @xref{Agent Categories}. + +Both topic parameters (@pxref{Topic Parameters}) and agent categories +(@pxref{Agent Categories}) provide for setting a policy that applies +to multiple groups. Which you use is entirely up to you. Topic +parameters do override categories so, if you mix the two, you'll have +to take that into account. If you have a few groups that deviate from +your policy, you can use grou parameters (@pxref{Group Parameters}) to +configure them. @item Uhm@dots{} that's it. @@ -17028,11 +17102,26 @@ mark the articles for downloading manually if it should turn out that you're interested in the articles anyway. -The main way to control what is to be downloaded is to create a -@dfn{category} and then assign some (or all) groups to this category. -Groups that do not belong in any other category belong to the -@code{default} category. Gnus has its own buffer for creating and -managing categories. +One of the more effective methods for controlling what is to be +downloaded is to create a @dfn{category} and then assign some (or all) +groups to this category. Groups that do not belong in any other +category belong to the @code{default} category. Gnus has its own +buffer for creating and managing categories. + +If you prefer, you can also use group parameters (@pxref{Group +Parameters}) and topic parameters (@pxref{Topic Parameters}) for an +alternative approach to controlling the agent. The only real +difference is that categories are specific to the agent (so there is +less to learn) while group and topic parameters include the kitchen +sink. + +Since you can set agent parameters in several different places we have +a rule to decide which source to believe. This rule specifies that +the parameter sources are checked in the following order: group +parameters, topic parameters, agent category, and finally customizable +variables. So you can mix all of these sources to produce a wide range +of behavior, just don't blame me if you don't remember where you put +your settings. @menu * Category Syntax:: What a category looks like. @@ -17044,18 +17133,58 @@ @node Category Syntax @subsubsection Category Syntax -A category consists of two things. +A category consists of a name, the list of groups belonging to the +category, and a number of optional parameters that override the +customizable variables. The complete list of agent parameters are +listed below. -@enumerate -@item +@table @code +@item gnus-agent-cat-name +The name of the category. + +@item gnus-agent-cat-groups +The list of groups that are in this category. + +@item gnus-agent-cat-predicate A predicate which (generally) gives a rough outline of which articles are eligible for downloading; and -@item +@item gnus-agent-cat-score-file a score rule which (generally) gives you a finer granularity when deciding what articles to download. (Note that this @dfn{download score} is not necessarily related to normal scores.) -@end enumerate + +@item gnus-agent-cat-enable-expiration +a boolean indicating whether the agent should expire old articles in +this group. Most groups should be expired to conserve disk space. In +fact, its probably safe to say that the gnus.* hierarchy contains the +only groups that should not be expired. + +@item gnus-agent-cat-days-until-old +an integer indicating the number of days that the agent should wait +before deciding that a read article is safe to expire. + +@item gnus-agent-cat-low-score +an integer that overrides the value of @code{gnus-agent-low-score}. + +@item gnus-agent-cat-high-score +an integer that overrides the value of @code{gnus-agent-high-score}. + +@item gnus-agent-cat-length-when-short +an integer that overrides the value of +@code{gnus-agent-short-article}. + +@item gnus-agent-cat-length-when-long +an integer that overrides the value of @code{gnus-agent-long-article}. +@end table + +The name of a category can not be changed once the category has been +created. + +Each category maintains a list of groups that are exclusive members of +that category. The exclusivity rule is automatically enforced, add a +group to a new category and it is automatically removed from its old +category. A predicate in its simplest form can be a single predicate such as @code{true} or @code{false}. These two will download every available @@ -17102,6 +17231,14 @@ The following predicates are pre-defined, but if none of these fit what you want to do, you can write your own. +When evaluating each of these predicates, the named constant will be +bound to the value determined by calling +@code{gnus-agent-find-parameter} on the appropriate parameter. For +example, gnus-agent-short-article will be bound to +@code{(gnus-agent-find-parameter group 'agent-short-article)}. This +means that you can specify a predicate in your category then tune that +predicate to individual groups. + @table @code @item short True iff the article is shorter than @code{gnus-agent-short-article} @@ -17186,7 +17323,7 @@ (agent-predicate . short) @end lisp -This is the group parameter equivalent of the agent category default. +This is the group/topic parameter equivalent of the agent category default. Note that when specifying a single word predicate like this, the @code{agent-predicate} specification must be in dotted pair notation. @@ -17237,7 +17374,7 @@ @end lisp @item -Group Parameter specification +Group/Topic Parameter specification @lisp (agent-score ("from" @@ -17327,6 +17464,12 @@ @findex gnus-category-exit Return to the group buffer (@code{gnus-category-exit}). +@item e +@kindex e (Category) +@findex gnus-category-customize-category +Use a customization buffer to set all of the selected category's +parameters at one time (@code{gnus-category-customize-category}). + @item k @kindex k (Category) @findex gnus-category-kill @@ -17410,6 +17553,25 @@ Articles that have a score higher than this have a high score. Default 0. +@item gnus-agent-expire-days +@vindex gnus-agent-expire-days +The number of days that a @samp{read} article must stay in the agent's +local disk before becoming eligible for expiration (While the name is +the same, this doesn't mean expiring the article on the server. It +just means deleting the local copy of the article). What is also +important to understand is that the counter starts with the time the +article was written to the local disk and not the time the article was +read. +Default 7. + +@item gnus-agent-enable-expiration +@vindex gnus-agent-enable-expiration +Determines whether articles in a group are, by default, expired or +retained indefinitely. The default is @code{ENABLE} which means that +you'll have to disable expiration when desired. On the other hand, +you could set this to @code{DISABLE}. In that case, you would then +have to enable expiration in selected groups. + @end table @@ -17563,8 +17725,11 @@ article into the Agent, Gnus will not download the article from the server again but use the locally stored copy instead. -This behaviour can be controlled by @code{gnus-agent-cache} -(@pxref{Agent Variables}). +If you so desire, you can configure the agent (see @code{gnus-agent-cache} +@pxref{Agent Variables}) to always download headers and articles while +plugged. Gnus will almost certainly be slower, but it will be kept +synchronized with the server. That last point probably won't make any +sense if you are using a nntp or nnimap backend. @node Agent Expiry @subsection Agent Expiry @@ -17572,45 +17737,39 @@ @vindex gnus-agent-expire-days @findex gnus-agent-expire @kindex M-x gnus-agent-expire +@kindex M-x gnus-agent-expire-group +@findex gnus-agent-expire-group @cindex Agent expiry @cindex Gnus Agent expiry @cindex expiry -@code{nnagent} doesn't handle expiry. Instead, there's a special -@code{gnus-agent-expire} command that will expire all read articles that -are older than @code{gnus-agent-expire-days} days. It can be run -whenever you feel that you're running out of space. It's not -particularly fast or efficient, and it's not a particularly good idea to -interrupt it (with @kbd{C-g} or anything else) once you've started it. +The Agent backend, @code{nnagent}, doesn't handle expiry. Well, at +least it doesn't handle it like other backends. Instead, there are +special @code{gnus-agent-expire} and @code{gnus-agent-expire-group} +commands that will expire all read articles that are older than +@code{gnus-agent-expire-days} days. They can be run whenever you feel +that you're running out of space. Neither are particularly fast or +efficient, and it's not a particularly good idea to interrupt them (with +@kbd{C-g} or anything else) once you've started one of them. Note that other functions, e.g. @code{gnus-request-expire-articles}, might run @code{gnus-agent-expire} for you to keep the agent synchronized with the group. -@code{gnus-agent-expire-days} can also be a list of regexp/day pairs. -The regexps will be matched against group names to allow differing -expiry in different groups. - -@lisp -(setq gnus-agent-expire-days - '(("alt\\." 7) - (".*binary" 1) - ("." 21))) -@end lisp - -If you use the list form, the last element must always be the default -method---it must always match all groups. Also, for a regexp to match, -it must match from the beginning of the group's name. +The agent parameter @code{agent-enable-expiration} may be used to +prevent expiration in selected groups. @vindex gnus-agent-expire-all -If @code{gnus-agent-expire-all} is non-@code{nil}, this command will -expire all articles---unread, read, ticked and dormant. If @code{nil} -(which is the default), only read articles are eligible for expiry, and -unread, ticked and dormant articles will be kept indefinitely. +If @code{gnus-agent-expire-all} is non-@code{nil}, the agent +expiration commands will expire all articles---unread, read, ticked +and dormant. If @code{nil} (which is the default), only read articles +are eligible for expiry, and unread, ticked and dormant articles will +be kept indefinitely. If you find that some articles eligible for expiry are never expired, -perhaps some Gnus Agent files are corrupted. There's a special -@code{gnus-agent-regenerate} command to fix possible problems. +perhaps some Gnus Agent files are corrupted. There's are special +commands, @code{gnus-agent-regenerate} and +@code{gnus-agent-regenerate-group}, to fix possible problems. @node Agent Regeneration @subsection Agent Regeneration @@ -17627,8 +17786,8 @@ For example, if your connection to your server is lost while downloaded articles into the agent, the local data structures will not -know about articles downloaded prior to the connection failure. -Running @code{gnus-agent-regenerate} or +know about articles successfully downloaded prior to the connection +failure. Running @code{gnus-agent-regenerate} or @code{gnus-agent-regenerate-group} will update the data structures such that you don't need to download these articles a second time. @@ -17740,7 +17899,7 @@ @item gnus-agent-fetched-hook @vindex gnus-agent-fetched-hook -Hook run when after finishing fetching articles. +Hook run when finished fetching articles. @item gnus-agent-cache @vindex gnus-agent-cache @@ -17760,7 +17919,9 @@ @item gnus-agent-mark-unread-after-downloaded @vindex gnus-agent-mark-unread-after-downloaded If @code{gnus-agent-mark-unread-after-downloaded} is non-@code{nil}, -mark articles as unread after downloading. The default is t. +mark articles as unread after downloading. This is usually a safe +thing to do as the newly downloaded article has obviously not been +read. The default is t. @item gnus-agent-consider-all-articles @vindex gnus-agent-consider-all-articles @@ -17779,7 +17940,8 @@ connection be lost while fetching (You may need to run @code{gnus-agent-regenerate-group} to update the group's state. However, all articles parsed prior to loosing the connection will be -available while unplugged). +available while unplugged). The default is 10M so it is unusual to +see any cycling. @item gnus-server-unopen-status @vindex gnus-server-unopen-status @@ -17791,6 +17953,19 @@ for this variable include @code{denied} and @code{offline} the latter is only valid if the Agent is used. +@item gnus-auto-goto-ignores +@vindex gnus-auto-goto-ignores +Another variable that isn't a Agent variable, yet so closely related +that most will look for it here, this variable tells the summary +buffer how to maneuver around undownloaded (only headers stored in the +agent) and unfetched (neither article nor headers stored) articles. + +The legal values are @code{nil} (maneuver to any article), +@code{undownloaded} (maneuvering while unplugged ignores articles that +have not been fetched), @code{always-undownloaded} (maneuvering always +ignores articles that have not been fetched), @code{unfetched} +(maneuvering ignores articles whose headers have not been fetched). + @end table @@ -17871,7 +18046,8 @@ @code{gnus-agent-fetch-selected-article} to @code{gnus-select-article-hook}. -@item If I read an article while plugged, and the article already exists in the Agent, will it get downloaded once more? +@item If I read an article while plugged, and the article already exists in +the Agent, will it get downloaded once more? @strong{No}, unless @code{gnus-agent-cache} is @code{nil}. @@ -18756,7 +18932,7 @@ will be applied to each article. To take @code{gnus-del-mark} as an example---this alist says that all -articles that have that mark (i.e., are marked with @samp{D}) will have a +articles that have that mark (i.e., are marked with @samp{e}) will have a score entry added to lower based on the @code{From} header by -4, and lowered by @code{Subject} by -1. Change this to fit your prejudices. @@ -20096,15 +20272,17 @@ @samp{hello} mouse-highlighted with @code{gnus-mouse-face-3}. Text inside the @samp{%<<} and @samp{%>>} specifiers will get the -special @code{balloon-help} property set to @code{gnus-balloon-face-0}. -If you say @samp{%1<<}, you'll get @code{gnus-balloon-face-1} and so on. -The @code{gnus-balloon-face-*} variables should be either strings or -symbols naming functions that return a string. When the mouse passes -over text with this property set, a balloon window will appear and -display the string. Please refer to @ref{(emacs)Help Echo} (in GNU -Emacs) or the doc string of @code{balloon-help-mode} (in XEmacs) for -more information on this. (For technical reasons, the guillemets have -been approximated as @samp{<<} and @samp{>>} in this paragraph.) +special @code{balloon-help} property set to +@code{gnus-balloon-face-0}. If you say @samp{%1<<}, you'll get +@code{gnus-balloon-face-1} and so on. The @code{gnus-balloon-face-*} +variables should be either strings or symbols naming functions that +return a string. When the mouse passes over text with this property +set, a balloon window will appear and display the string. Please +refer to @ref{Tooltips, ,Tooltips, emacs, The Emacs Manual}, +(in GNU Emacs) or the doc string of @code{balloon-help-mode} (in +XEmacs) for more information on this. (For technical reasons, the +guillemets have been approximated as @samp{<<} and @samp{>>} in this +paragraph.) Here's an alternative recipe for the group buffer: @@ -24641,7 +24819,7 @@ @cindex slow Sometimes, a problem do not directly generate a elisp error but manifests itself by causing Gnus to be very slow. In these cases, you -can use @kbd{M-x toggle-debug-on-quit} and press @kbd{C-j} when things are +can use @kbd{M-x toggle-debug-on-quit} and press @kbd{C-g} when things are slow, and then try to analyze the backtrace (repeating the procedure helps isolating the real problem areas). A fancier approach is to use the elisp profiler, ELP. The profiler is (or should be) fully Index: gnus/texi/infohack.el diff -u gnus/texi/infohack.el:6.7 gnus/texi/infohack.el:6.8 --- gnus/texi/infohack.el:6.7 Mon Dec 3 16:42:49 2001 +++ gnus/texi/infohack.el Wed Mar 19 08:01:09 2003 @@ -55,6 +55,27 @@ (Info-split)) (save-buffer))) +(eval-and-compile + (when (string-match "windows-nt\\|os/2\\|emx\\|cygwin" + (symbol-name system-type)) + (defun subst-char-in-region (START END FROMCHAR TOCHAR &optional NOUNDO) + "From START to END, replace FROMCHAR with TOCHAR each time it occurs. +If optional arg NOUNDO is non-nil, don't record this change for undo +and don't mark the buffer as really changed. +Both characters must have the same length of multi-byte form." + (let ((original-buffer-undo-list buffer-undo-list) + (modified (buffer-modified-p))) + (if NOUNDO + (setq buffer-undo-list t)) + (goto-char START) + (let ((from (char-to-string FROMCHAR)) + (to (char-to-string TOCHAR))) + (while (search-forward from END t) + (replace-match to t t))) + (if NOUNDO + (progn (setq buffer-undo-list original-buffer-undo-list) + (set-buffer-modidifed-p modified))))))) + (defun batch-makeinfo () "Emacs makeinfo in batch mode." (infohack (car command-line-args-left)) Index: gnus/texi/message.texi diff -u gnus/texi/message.texi:6.69 gnus/texi/message.texi:6.71 --- gnus/texi/message.texi:6.69 Wed Feb 26 03:37:03 2003 +++ gnus/texi/message.texi Sun Mar 23 02:22:32 2003 @@ -423,8 +423,9 @@ There is a pre-defined function in Gnus that is a good candidate for this variable. @code{gnus-find-subscribed-addresses} is a function that returns a list of addresses corresponding to the groups that have -the @code{subscribed} (@pxref{(gnus)subscribed}) -group parameter set to a non-nil value. This is how you would do it. +the @code{subscribed} (@pxref{Group Parameters, ,Group Parameters, +gnus, The Gnus Manual}) group parameter set to a non-nil value. This +is how you would do it. @lisp (setq message-subscribed-address-functions @@ -502,6 +503,7 @@ * Movement:: Moving around in message buffers. * Insertion:: Inserting things into message buffers. * MIME:: @sc{mime} considerations. +* IDNA:: Non-ASCII domain name considerations. * Security:: Signing and encrypting messages. * Various Commands:: Various things. * Sending:: Actually sending the message. @@ -830,6 +832,37 @@ You can also create arbitrarily complex multiparts using the MML language (@pxref{Composing, , Composing, emacs-mime, The Emacs MIME Manual}). + +@node IDNA +@section IDNA +@cindex IDNA +@cindex internationalized domain names +@cindex non-ascii domain names + +Message is a @sc{idna}-compliant posting agent. The user generally +doesn't have to do anything to make the @sc{idna} happen---Message +will encode non-ASCII domain names in @code{From}, @code{To}, and +@code{Cc} headers automatically. + +Until IDNA becomes more well known, Message queries you whether IDNA +encoding of the domain name really should occur. Some users might not +be aware that domain names can contain non-ASCII now, so this gives +them a safety net if they accidently typed a non-ASCII domain name. + +@vindex message-use-idna +The @code{message-use-idna} variable control whether @sc{idna} is +used. If the variable is @sc{nil} no IDNA encoding will ever happen, +if it is set to the symbol @sc{ask} the user will be queried (the +default), and if set to @sc{t} IDNA encoding happens automatically. + +@findex message-idna-to-ascii-rhs +If you want to experiment with the IDNA encoding, you can invoke +@kbd{M-x message-idna-to-ascii-rhs RET} in the message buffer to have +the non-ASCII domain names encoded while you edit the message. + +Note that you must have GNU Libidn +(@url{http://www.gnu.org/software/libidn/} installed in order to use +this functionality. @node Security @section Security