comparison lisp/gnus/gnus-uu.el @ 16:0293115a14e9 r19-15b91

Import from CVS: tag r19-15b91
author cvs
date Mon, 13 Aug 2007 08:49:20 +0200
parents ac2d302a0011
children d95e72db5c07
comparison
equal deleted inserted replaced
15:ad457d5f7d04 16:0293115a14e9
1 ;;; gnus-uu.el --- extract (uu)encoded files in Gnus 1 ;;; gnus-uu.el --- extract (uu)encoded files in Gnus
2 ;; Copyright (C) 1985,86,87,93,94,95,96 Free Software Foundation, Inc. 2 ;; Copyright (C) 1985,86,87,93,94,95,96,97 Free Software Foundation, Inc.
3 3
4 ;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no> 4 ;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
5 ;; Created: 2 Oct 1993 5 ;; Created: 2 Oct 1993
6 ;; Keyword: news 6 ;; Keyword: news
7 7
25 ;;; Commentary: 25 ;;; Commentary:
26 26
27 ;;; Code: 27 ;;; Code:
28 28
29 (require 'gnus) 29 (require 'gnus)
30 (require 'gnus-art)
31 (require 'message)
30 (require 'gnus-msg) 32 (require 'gnus-msg)
31 (eval-when-compile (require 'cl)) 33
34 (defgroup gnus-extract nil
35 "Extracting encoded files."
36 :prefix "gnus-uu-"
37 :group 'gnus)
38
39 (defgroup gnus-extract-view nil
40 "Viewwing extracted files."
41 :group 'gnus-extract)
42
43 (defgroup gnus-extract-archive nil
44 "Extracting encoded archives."
45 :group 'gnus-extract)
46
47 (defgroup gnus-extract-post nil
48 "Extracting encoded archives."
49 :prefix "gnus-uu-post"
50 :group 'gnus-extract)
32 51
33 ;; Default viewing action rules 52 ;; Default viewing action rules
34 53
35 (defvar gnus-uu-default-view-rules 54 (defcustom gnus-uu-default-view-rules
36 '(("\\.te?xt$\\|\\.doc$\\|read.*me\\|\\.c?$\\|\\.h$\\|\\.bat$\\|\\.asm$\\|makefile" "cat %s | sed s/\r//g") 55 '(("\\.te?xt$\\|\\.doc$\\|read.*me\\|\\.c?$\\|\\.h$\\|\\.bat$\\|\\.asm$\\|makefile" "cat %s | sed s/\r//g")
37 ("\\.pas$" "cat %s | sed s/\r//g") 56 ("\\.pas$" "cat %s | sed s/\r//g")
38 ("\\.[1-9]$" "groff -mandoc -Tascii %s | sed s/\b.//g") 57 ("\\.[1-9]$" "groff -mandoc -Tascii %s | sed s/\b.//g")
39 ("\\.\\(jpe?g\\|gif\\|tiff?\\|p[pgb]m\\|xwd\\|xbm\\|pcx\\)$" "xv") 58 ("\\.\\(jpe?g\\|gif\\|tiff?\\|p[pgb]m\\|xwd\\|xbm\\|pcx\\)$" "xv")
40 ("\\.tga$" "tgatoppm %s | xv -") 59 ("\\.tga$" "tgatoppm %s | xv -")
48 ("\\.html$" "xmosaic") 67 ("\\.html$" "xmosaic")
49 ("\\.mpe?g$" "mpeg_play") 68 ("\\.mpe?g$" "mpeg_play")
50 ("\\.\\(flc\\|fli\\|rle\\|iff\\|pfx\\|avi\\|sme\\|rpza\\|dl\\|qt\\|rsrc\\|mov\\)$" "xanim") 69 ("\\.\\(flc\\|fli\\|rle\\|iff\\|pfx\\|avi\\|sme\\|rpza\\|dl\\|qt\\|rsrc\\|mov\\)$" "xanim")
51 ("\\.\\(tar\\|arj\\|zip\\|zoo\\|arc\\|gz\\|Z\\|lzh\\|ar\\|lha\\)$" 70 ("\\.\\(tar\\|arj\\|zip\\|zoo\\|arc\\|gz\\|Z\\|lzh\\|ar\\|lha\\)$"
52 "gnus-uu-archive")) 71 "gnus-uu-archive"))
53 "*Default actions to be taken when the user asks to view a file. 72 "Default actions to be taken when the user asks to view a file.
54 To change the behaviour, you can either edit this variable or set 73 To change the behaviour, you can either edit this variable or set
55 `gnus-uu-user-view-rules' to something useful. 74 `gnus-uu-user-view-rules' to something useful.
56 75
57 For example: 76 For example:
58 77
59 To make gnus-uu use 'xli' to display JPEG and GIF files, put the 78 To make gnus-uu use 'xli' to display JPEG and GIF files, put the
60 following in your .emacs file: 79 following in your .emacs file:
61 80
62 (setq gnus-uu-user-view-rules '((\"jpg$\\\\|gif$\" \"xli\"))) 81 (setq gnus-uu-user-view-rules '((\"jpg$\\\\|gif$\" \"xli\")))
63 82
64 Both these variables are lists of lists with two string elements. The 83 Both these variables are lists of lists with two string elements. The
65 first string is a regular expression. If the file name matches this 84 first string is a regular expression. If the file name matches this
66 regular expression, the command in the second string is executed with 85 regular expression, the command in the second string is executed with
67 the file as an argument. 86 the file as an argument.
68 87
69 If the command string contains \"%s\", the file name will be inserted 88 If the command string contains \"%s\", the file name will be inserted
70 at that point in the command string. If there's no \"%s\" in the 89 at that point in the command string. If there's no \"%s\" in the
71 command string, the file name will be appended to the command string 90 command string, the file name will be appended to the command string
72 before executing. 91 before executing.
73 92
74 There are several user variables to tailor the behaviour of gnus-uu to 93 There are several user variables to tailor the behaviour of gnus-uu to
75 your needs. First we have `gnus-uu-user-view-rules', which is the 94 your needs. First we have `gnus-uu-user-view-rules', which is the
76 variable gnus-uu first consults when trying to decide how to view a 95 variable gnus-uu first consults when trying to decide how to view a
77 file. If this variable contains no matches, gnus-uu examines the 96 file. If this variable contains no matches, gnus-uu examines the
78 default rule variable provided in this package. If gnus-uu finds no 97 default rule variable provided in this package. If gnus-uu finds no
79 match here, it uses `gnus-uu-user-view-rules-end' to try to make a 98 match here, it uses `gnus-uu-user-view-rules-end' to try to make a
80 match.") 99 match."
81 100 :group 'gnus-extract-view
82 (defvar gnus-uu-user-view-rules nil 101 :type '(repeat (group regexp (string :tag "Command"))))
83 "*Variable detailing what actions are to be taken to view a file. 102
103 (defcustom gnus-uu-user-view-rules nil
104 "What actions are to be taken to view a file.
84 See the documentation on the `gnus-uu-default-view-rules' variable for 105 See the documentation on the `gnus-uu-default-view-rules' variable for
85 details.") 106 details."
86 107 :group 'gnus-extract-view
87 (defvar gnus-uu-user-view-rules-end 108 :type '(repeat (group regexp (string :tag "Command"))))
109
110 (defcustom gnus-uu-user-view-rules-end
88 '(("" "file")) 111 '(("" "file"))
89 "*Variable saying what actions are to be taken if no rule matched the file name. 112 "What actions are to be taken if no rule matched the file name.
90 See the documentation on the `gnus-uu-default-view-rules' variable for 113 See the documentation on the `gnus-uu-default-view-rules' variable for
91 details.") 114 details."
115 :group 'gnus-extract-view
116 :type '(repeat (group regexp (string :tag "Command"))))
92 117
93 ;; Default unpacking commands 118 ;; Default unpacking commands
94 119
95 (defvar gnus-uu-default-archive-rules 120 (defcustom gnus-uu-default-archive-rules
96 '(("\\.tar$" "tar xf") 121 '(("\\.tar$" "tar xf")
97 ("\\.zip$" "unzip -o") 122 ("\\.zip$" "unzip -o")
98 ("\\.ar$" "ar x") 123 ("\\.ar$" "ar x")
99 ("\\.arj$" "unarj x") 124 ("\\.arj$" "unarj x")
100 ("\\.zoo$" "zoo -e") 125 ("\\.zoo$" "zoo -e")
101 ("\\.\\(lzh\\|lha\\)$" "lha x") 126 ("\\.\\(lzh\\|lha\\)$" "lha x")
102 ("\\.Z$" "uncompress") 127 ("\\.Z$" "uncompress")
103 ("\\.gz$" "gunzip") 128 ("\\.gz$" "gunzip")
104 ("\\.arc$" "arc -x"))) 129 ("\\.arc$" "arc -x"))
130 "See `gnus-uu-user-archive-rules'."
131 :group 'gnus-extract-archive
132 :type '(repeat (group regexp (string :tag "Command"))))
105 133
106 (defvar gnus-uu-destructive-archivers 134 (defvar gnus-uu-destructive-archivers
107 (list "uncompress" "gunzip")) 135 (list "uncompress" "gunzip"))
108 136
109 (defvar gnus-uu-user-archive-rules nil 137 (defcustom gnus-uu-user-archive-rules nil
110 "*A list that can be set to override the default archive unpacking commands. 138 "A list that can be set to override the default archive unpacking commands.
111 To use, for instance, 'untar' to unpack tar files and 'zip -x' to 139 To use, for instance, 'untar' to unpack tar files and 'zip -x' to
112 unpack zip files, say the following: 140 unpack zip files, say the following:
113 (setq gnus-uu-user-archive-rules 141 (setq gnus-uu-user-archive-rules
114 '((\"\\\\.tar$\" \"untar\") 142 '((\"\\\\.tar$\" \"untar\")
115 (\"\\\\.zip$\" \"zip -x\")))") 143 (\"\\\\.zip$\" \"zip -x\")))"
116 144 :group 'gnus-extract-archive
117 (defvar gnus-uu-ignore-files-by-name nil 145 :type '(repeat (group regexp (string :tag "Command"))))
146
147 (defcustom gnus-uu-ignore-files-by-name nil
118 "*A regular expression saying what files should not be viewed based on name. 148 "*A regular expression saying what files should not be viewed based on name.
119 If, for instance, you want gnus-uu to ignore all .au and .wav files, 149 If, for instance, you want gnus-uu to ignore all .au and .wav files,
120 you could say something like 150 you could say something like
121 151
122 (setq gnus-uu-ignore-files-by-name \"\\\\.au$\\\\|\\\\.wav$\") 152 (setq gnus-uu-ignore-files-by-name \"\\\\.au$\\\\|\\\\.wav$\")
123 153
124 Note that this variable can be used in conjunction with the 154 Note that this variable can be used in conjunction with the
125 `gnus-uu-ignore-files-by-type' variable.") 155 `gnus-uu-ignore-files-by-type' variable."
126 156 :group 'gnus-extract
127 (defvar gnus-uu-ignore-files-by-type nil 157 :type '(choice (const :tag "off" nil)
158 (regexp :format "%v")))
159
160 (defcustom gnus-uu-ignore-files-by-type nil
128 "*A regular expression saying what files that shouldn't be viewed, based on MIME file type. 161 "*A regular expression saying what files that shouldn't be viewed, based on MIME file type.
129 If, for instance, you want gnus-uu to ignore all audio files and all mpegs, 162 If, for instance, you want gnus-uu to ignore all audio files and all mpegs,
130 you could say something like 163 you could say something like
131 164
132 (setq gnus-uu-ignore-files-by-type \"audio/\\\\|video/mpeg\") 165 (setq gnus-uu-ignore-files-by-type \"audio/\\\\|video/mpeg\")
133 166
134 Note that this variable can be used in conjunction with the 167 Note that this variable can be used in conjunction with the
135 `gnus-uu-ignore-files-by-name' variable.") 168 `gnus-uu-ignore-files-by-name' variable."
169 :group 'gnus-extract
170 :type '(choice (const :tag "off" nil)
171 (regexp :format "%v")))
136 172
137 ;; Pseudo-MIME support 173 ;; Pseudo-MIME support
138 174
139 (defconst gnus-uu-ext-to-mime-list 175 (defconst gnus-uu-ext-to-mime-list
140 '(("\\.gif$" "image/gif") 176 '(("\\.gif$" "image/gif")
175 ("\\.rsrc$" "video/rsrc") 211 ("\\.rsrc$" "video/rsrc")
176 ("\\..*$" "unknown/unknown"))) 212 ("\\..*$" "unknown/unknown")))
177 213
178 ;; Various variables users may set 214 ;; Various variables users may set
179 215
180 (defvar gnus-uu-tmp-dir "/tmp/" 216 (defcustom gnus-uu-tmp-dir "/tmp/"
181 "*Variable saying where gnus-uu is to do its work. 217 "*Variable saying where gnus-uu is to do its work.
182 Default is \"/tmp/\".") 218 Default is \"/tmp/\"."
183 219 :group 'gnus-extract
184 (defvar gnus-uu-do-not-unpack-archives nil 220 :type 'directory)
221
222 (defcustom gnus-uu-do-not-unpack-archives nil
185 "*Non-nil means that gnus-uu won't peek inside archives looking for files to display. 223 "*Non-nil means that gnus-uu won't peek inside archives looking for files to display.
186 Default is nil.") 224 Default is nil."
187 225 :group 'gnus-extract-archive
188 (defvar gnus-uu-ignore-default-view-rules nil 226 :type 'boolean)
227
228 (defcustom gnus-uu-ignore-default-view-rules nil
189 "*Non-nil means that gnus-uu will ignore the default viewing rules. 229 "*Non-nil means that gnus-uu will ignore the default viewing rules.
190 Only the user viewing rules will be consulted. Default is nil.") 230 Only the user viewing rules will be consulted. Default is nil."
191 231 :group 'gnus-extract-view
192 (defvar gnus-uu-grabbed-file-functions nil 232 :type 'boolean)
193 "*Functions run on each file after successful decoding. 233
234 (defcustom gnus-uu-grabbed-file-functions nil
235 "Functions run on each file after successful decoding.
194 They will be called with the name of the file as the argument. 236 They will be called with the name of the file as the argument.
195 Likely functions you can use in this list are `gnus-uu-grab-view' 237 Likely functions you can use in this list are `gnus-uu-grab-view'
196 and `gnus-uu-grab-move'.") 238 and `gnus-uu-grab-move'."
197 239 :group 'gnus-extract
198 (defvar gnus-uu-ignore-default-archive-rules nil 240 :options '(gnus-uu-grab-view gnus-uu-grab-move)
241 :type 'hook)
242
243 (defcustom gnus-uu-ignore-default-archive-rules nil
199 "*Non-nil means that gnus-uu will ignore the default archive unpacking commands. 244 "*Non-nil means that gnus-uu will ignore the default archive unpacking commands.
200 Only the user unpacking commands will be consulted. Default is nil.") 245 Only the user unpacking commands will be consulted. Default is nil."
201 246 :group 'gnus-extract-archive
202 (defvar gnus-uu-kill-carriage-return t 247 :type 'boolean)
248
249 (defcustom gnus-uu-kill-carriage-return t
203 "*Non-nil means that gnus-uu will strip all carriage returns from articles. 250 "*Non-nil means that gnus-uu will strip all carriage returns from articles.
204 Default is t.") 251 Default is t."
205 252 :group 'gnus-extract
206 (defvar gnus-uu-view-with-metamail nil 253 :type 'boolean)
254
255 (defcustom gnus-uu-view-with-metamail nil
207 "*Non-nil means that files will be viewed with metamail. 256 "*Non-nil means that files will be viewed with metamail.
208 The gnus-uu viewing functions will be ignored and gnus-uu will try 257 The gnus-uu viewing functions will be ignored and gnus-uu will try
209 to guess at a content-type based on file name suffixes. Default 258 to guess at a content-type based on file name suffixes. Default
210 it nil.") 259 it nil."
211 260 :group 'gnus-extract
212 (defvar gnus-uu-unmark-articles-not-decoded nil 261 :type 'boolean)
262
263 (defcustom gnus-uu-unmark-articles-not-decoded nil
213 "*Non-nil means that gnus-uu will mark articles that were unsuccessfully decoded as unread. 264 "*Non-nil means that gnus-uu will mark articles that were unsuccessfully decoded as unread.
214 Default is nil.") 265 Default is nil."
215 266 :group 'gnus-extract
216 (defvar gnus-uu-correct-stripped-uucode nil 267 :type 'boolean)
268
269 (defcustom gnus-uu-correct-stripped-uucode nil
217 "*Non-nil means that gnus-uu will *try* to fix uuencoded files that have had trailing spaces deleted. 270 "*Non-nil means that gnus-uu will *try* to fix uuencoded files that have had trailing spaces deleted.
218 Default is nil.") 271 Default is nil."
219 272 :group 'gnus-extract
220 (defvar gnus-uu-save-in-digest nil 273 :type 'boolean)
274
275 (defcustom gnus-uu-save-in-digest nil
221 "*Non-nil means that gnus-uu, when asked to save without decoding, will save in digests. 276 "*Non-nil means that gnus-uu, when asked to save without decoding, will save in digests.
222 If this variable is nil, gnus-uu will just save everything in a 277 If this variable is nil, gnus-uu will just save everything in a
223 file without any embellishments. The digesting almost conforms to RFC1153 - 278 file without any embellishments. The digesting almost conforms to RFC1153 -
224 no easy way to specify any meaningful volume and issue numbers were found, 279 no easy way to specify any meaningful volume and issue numbers were found,
225 so I simply dropped them.") 280 so I simply dropped them."
226 281 :group 'gnus-extract
227 (defvar gnus-uu-digest-headers 282 :type 'boolean)
283
284 (defcustom gnus-uu-digest-headers
228 '("^Date:" "^From:" "^To:" "^Cc:" "^Subject:" "^Message-ID:" "^Keywords:" 285 '("^Date:" "^From:" "^To:" "^Cc:" "^Subject:" "^Message-ID:" "^Keywords:"
229 "^Summary:" "^References:") 286 "^Summary:" "^References:")
230 "*List of regexps to match headers included in digested messages. 287 "List of regexps to match headers included in digested messages.
231 The headers will be included in the sequence they are matched.") 288 The headers will be included in the sequence they are matched."
232 289 :group 'gnus-extract
233 (defvar gnus-uu-save-separate-articles nil 290 :type '(repeat regexp))
234 "*Non-nil means that gnus-uu will save articles in separate files.") 291
292 (defcustom gnus-uu-save-separate-articles nil
293 "*Non-nil means that gnus-uu will save articles in separate files."
294 :group 'gnus-extract
295 :type 'boolean)
296
297 (defcustom gnus-uu-be-dangerous 'ask
298 "*Specifies what to do if unusual situations arise during decoding.
299 If nil, be as conservative as possible. If t, ignore things that
300 didn't work, and overwrite existing files. Otherwise, ask each time."
301 :group 'gnus-extract
302 :type '(choice (const :tag "conservative" nil)
303 (const :tag "ask" ask)
304 (const :tag "liberal" t)))
235 305
236 ;; Internal variables 306 ;; Internal variables
237 307
238 (defvar gnus-uu-saved-article-name nil) 308 (defvar gnus-uu-saved-article-name nil)
239 309
267 (defvar gnus-uu-default-dir gnus-article-save-directory) 337 (defvar gnus-uu-default-dir gnus-article-save-directory)
268 (defvar gnus-uu-digest-from-subject nil) 338 (defvar gnus-uu-digest-from-subject nil)
269 339
270 ;; Keymaps 340 ;; Keymaps
271 341
272 (gnus-define-keys 342 (gnus-define-keys (gnus-uu-mark-map "P" gnus-summary-mark-map)
273 (gnus-uu-mark-map "P" gnus-summary-mark-map) 343 "p" gnus-summary-mark-as-processable
274 "p" gnus-summary-mark-as-processable 344 "u" gnus-summary-unmark-as-processable
275 "u" gnus-summary-unmark-as-processable 345 "U" gnus-summary-unmark-all-processable
276 "U" gnus-summary-unmark-all-processable 346 "v" gnus-uu-mark-over
277 "v" gnus-uu-mark-over 347 "s" gnus-uu-mark-series
278 "s" gnus-uu-mark-series 348 "r" gnus-uu-mark-region
279 "r" gnus-uu-mark-region 349 "R" gnus-uu-mark-by-regexp
280 "R" gnus-uu-mark-by-regexp 350 "t" gnus-uu-mark-thread
281 "t" gnus-uu-mark-thread 351 "T" gnus-uu-unmark-thread
282 "T" gnus-uu-unmark-thread 352 "a" gnus-uu-mark-all
283 "a" gnus-uu-mark-all 353 "b" gnus-uu-mark-buffer
284 "b" gnus-uu-mark-buffer 354 "S" gnus-uu-mark-sparse
285 "S" gnus-uu-mark-sparse) 355 "k" gnus-summary-kill-process-mark
286 356 "y" gnus-summary-yank-process-mark
287 (gnus-define-keys 357 "w" gnus-summary-save-process-mark
288 (gnus-uu-extract-map "X" gnus-summary-mode-map) 358 "i" gnus-uu-invert-processable)
289 ;;"x" gnus-uu-extract-any 359
290 ;;"m" gnus-uu-extract-mime 360 (gnus-define-keys (gnus-uu-extract-map "X" gnus-summary-mode-map)
291 "u" gnus-uu-decode-uu 361 ;;"x" gnus-uu-extract-any
292 "U" gnus-uu-decode-uu-and-save 362 ;;"m" gnus-uu-extract-mime
293 "s" gnus-uu-decode-unshar 363 "u" gnus-uu-decode-uu
294 "S" gnus-uu-decode-unshar-and-save 364 "U" gnus-uu-decode-uu-and-save
295 "o" gnus-uu-decode-save 365 "s" gnus-uu-decode-unshar
296 "O" gnus-uu-decode-save 366 "S" gnus-uu-decode-unshar-and-save
297 "b" gnus-uu-decode-binhex 367 "o" gnus-uu-decode-save
298 "B" gnus-uu-decode-binhex 368 "O" gnus-uu-decode-save
299 "p" gnus-uu-decode-postscript 369 "b" gnus-uu-decode-binhex
300 "P" gnus-uu-decode-postscript-and-save) 370 "B" gnus-uu-decode-binhex
371 "p" gnus-uu-decode-postscript
372 "P" gnus-uu-decode-postscript-and-save)
301 373
302 (gnus-define-keys 374 (gnus-define-keys
303 (gnus-uu-extract-view-map "v" gnus-uu-extract-map) 375 (gnus-uu-extract-view-map "v" gnus-uu-extract-map)
304 "u" gnus-uu-decode-uu-view 376 "u" gnus-uu-decode-uu-view
305 "U" gnus-uu-decode-uu-and-save-view 377 "U" gnus-uu-decode-uu-and-save-view
315 387
316 ;; Commands. 388 ;; Commands.
317 389
318 (defun gnus-uu-decode-uu (&optional n) 390 (defun gnus-uu-decode-uu (&optional n)
319 "Uudecodes the current article." 391 "Uudecodes the current article."
320 (interactive "P") 392 (interactive "P")
321 (gnus-uu-decode-with-method 'gnus-uu-uustrip-article n)) 393 (gnus-uu-decode-with-method 'gnus-uu-uustrip-article n))
322 394
323 (defun gnus-uu-decode-uu-and-save (n dir) 395 (defun gnus-uu-decode-uu-and-save (n dir)
324 "Decodes and saves the resulting file." 396 "Decodes and saves the resulting file."
325 (interactive 397 (interactive
429 501
430 (defun gnus-uu-digest-mail-forward (&optional n post) 502 (defun gnus-uu-digest-mail-forward (&optional n post)
431 "Digests and forwards all articles in this series." 503 "Digests and forwards all articles in this series."
432 (interactive "P") 504 (interactive "P")
433 (let ((gnus-uu-save-in-digest t) 505 (let ((gnus-uu-save-in-digest t)
434 (file (make-temp-name (concat gnus-uu-tmp-dir "forward"))) 506 (file (make-temp-name (nnheader-concat gnus-uu-tmp-dir "forward")))
435 buf subject from) 507 buf subject from newsgroups)
436 (setq gnus-uu-digest-from-subject nil) 508 (setq gnus-uu-digest-from-subject nil)
437 (gnus-uu-decode-save n file) 509 (gnus-uu-decode-save n file)
438 (setq buf (switch-to-buffer (get-buffer-create " *gnus-uu-forward*"))) 510 (setq buf (switch-to-buffer (get-buffer-create " *gnus-uu-forward*")))
439 (gnus-add-current-to-buffer-list) 511 (gnus-add-current-to-buffer-list)
440 (erase-buffer) 512 (erase-buffer)
441 (delete-other-windows) 513 (delete-other-windows)
442 (insert-file file) 514 (insert-file file)
443 (let ((fs gnus-uu-digest-from-subject)) 515 (let ((fs gnus-uu-digest-from-subject))
444 (if (not fs) 516 (when fs
445 ()
446 (setq from (caar fs) 517 (setq from (caar fs)
447 subject (gnus-simplify-subject-fuzzy (cdar fs)) 518 subject (gnus-simplify-subject-fuzzy (cdar fs))
448 fs (cdr fs)) 519 fs (cdr fs))
449 (while (and fs (or from subject)) 520 (while (and fs (or from subject))
450 (and from 521 (when from
451 (or (string= from (caar fs)) 522 (unless (string= from (caar fs))
452 (setq from nil))) 523 (setq from nil)))
453 (and subject 524 (when subject
454 (or (string= (gnus-simplify-subject-fuzzy (cdar fs)) 525 (unless (string= (gnus-simplify-subject-fuzzy (cdar fs))
455 subject) 526 subject)
456 (setq subject nil))) 527 (setq subject nil)))
457 (setq fs (cdr fs)))) 528 (setq fs (cdr fs))))
458 (or subject (setq subject "Digested Articles")) 529 (unless subject
459 (or from (setq from "Various"))) 530 (setq subject "Digested Articles"))
531 (unless from
532 (setq from
533 (if (gnus-news-group-p gnus-newsgroup-name)
534 gnus-newsgroup-name
535 "Various"))))
460 (goto-char (point-min)) 536 (goto-char (point-min))
461 (and (re-search-forward "^Subject: ") 537 (when (re-search-forward "^Subject: ")
462 (progn 538 (delete-region (point) (point-at-eol))
463 (delete-region (point) (gnus-point-at-eol)) 539 (insert subject))
464 (insert subject)))
465 (goto-char (point-min)) 540 (goto-char (point-min))
466 (and (re-search-forward "^From: ") 541 (when (re-search-forward "^From: ")
467 (progn 542 (delete-region (point) (point-at-eol))
468 (delete-region (point) (gnus-point-at-eol)) 543 (insert from))
469 (insert from)))
470 (message-forward post) 544 (message-forward post)
471 (delete-file file) 545 (delete-file file)
472 (kill-buffer buf) 546 (kill-buffer buf)
473 (setq gnus-uu-digest-from-subject nil))) 547 (setq gnus-uu-digest-from-subject nil)))
474 548
554 (gnus-summary-article-number)) 628 (gnus-summary-article-number))
555 (zerop (gnus-summary-next-subject 1)) 629 (zerop (gnus-summary-next-subject 1))
556 (> (gnus-summary-thread-level) level)))) 630 (> (gnus-summary-thread-level) level))))
557 (gnus-summary-position-point)) 631 (gnus-summary-position-point))
558 632
633 (defun gnus-uu-invert-processable ()
634 "Invert the list of process-marked articles."
635 (let ((data gnus-newsgroup-data)
636 d number)
637 (save-excursion
638 (while data
639 (if (memq (setq number (gnus-data-number (pop data)))
640 gnus-newsgroup-processable)
641 (gnus-summary-remove-process-mark number)
642 (gnus-summary-set-process-mark number)))))
643 (gnus-summary-position-point))
644
559 (defun gnus-uu-mark-over (&optional score) 645 (defun gnus-uu-mark-over (&optional score)
560 "Mark all articles with a score over SCORE (the prefix.)" 646 "Mark all articles with a score over SCORE (the prefix.)"
561 (interactive "P") 647 (interactive "P")
562 (let ((score (gnus-score-default score)) 648 (let ((score (gnus-score-default score))
563 (data gnus-newsgroup-data)) 649 (data gnus-newsgroup-data))
575 "Mark all series that have some articles marked." 661 "Mark all series that have some articles marked."
576 (interactive) 662 (interactive)
577 (gnus-set-global-variables) 663 (gnus-set-global-variables)
578 (let ((marked (nreverse gnus-newsgroup-processable)) 664 (let ((marked (nreverse gnus-newsgroup-processable))
579 subject articles total headers) 665 subject articles total headers)
580 (or marked (error "No articles marked with the process mark")) 666 (unless marked
667 (error "No articles marked with the process mark"))
581 (setq gnus-newsgroup-processable nil) 668 (setq gnus-newsgroup-processable nil)
582 (save-excursion 669 (save-excursion
583 (while marked 670 (while marked
584 (and (vectorp (setq headers 671 (and (vectorp (setq headers
585 (gnus-summary-article-header (car marked)))) 672 (gnus-summary-article-header (car marked))))
650 ;; Internal functions. 737 ;; Internal functions.
651 738
652 (defun gnus-uu-decode-with-method (method n &optional save not-insert 739 (defun gnus-uu-decode-with-method (method n &optional save not-insert
653 scan cdir) 740 scan cdir)
654 (gnus-uu-initialize scan) 741 (gnus-uu-initialize scan)
655 (if save (setq gnus-uu-default-dir save)) 742 (when save
743 (setq gnus-uu-default-dir save))
656 ;; Create the directory we save to. 744 ;; Create the directory we save to.
657 (when (and scan cdir save 745 (when (and scan cdir save
658 (not (file-exists-p save))) 746 (not (file-exists-p save)))
659 (make-directory save t)) 747 (make-directory save t))
660 (let ((articles (gnus-uu-get-list-of-articles n)) 748 (let ((articles (gnus-uu-get-list-of-articles n))
661 files) 749 files)
662 (setq files (gnus-uu-grab-articles articles method t)) 750 (setq files (gnus-uu-grab-articles articles method t))
663 (let ((gnus-current-article (car articles))) 751 (let ((gnus-current-article (car articles)))
664 (and scan (setq files (gnus-uu-scan-directory gnus-uu-work-dir)))) 752 (when scan
665 (and save (gnus-uu-save-files files save)) 753 (setq files (gnus-uu-scan-directory gnus-uu-work-dir))))
666 (if (eq gnus-uu-do-not-unpack-archives nil) 754 (when save
755 (gnus-uu-save-files files save))
756 (when (eq gnus-uu-do-not-unpack-archives nil)
667 (setq files (gnus-uu-unpack-files files))) 757 (setq files (gnus-uu-unpack-files files)))
668 (setq files (nreverse (gnus-uu-get-actions files))) 758 (setq files (nreverse (gnus-uu-get-actions files)))
669 (or not-insert (not gnus-insert-pseudo-articles) 759 (or not-insert (not gnus-insert-pseudo-articles)
670 (gnus-summary-insert-pseudos files save)))) 760 (gnus-summary-insert-pseudos files save))))
671 761
692 (while (setq file (cdr (assq 'name (pop files)))) 782 (while (setq file (cdr (assq 'name (pop files))))
693 (when (file-exists-p file) 783 (when (file-exists-p file)
694 (string-match reg file) 784 (string-match reg file)
695 (setq fromdir (substring file (match-end 0))) 785 (setq fromdir (substring file (match-end 0)))
696 (if (file-directory-p file) 786 (if (file-directory-p file)
697 (unless (file-exists-p (concat dir fromdir)) 787 (gnus-make-directory (concat dir fromdir))
698 (make-directory (concat dir fromdir) t))
699 (setq to-file (concat dir fromdir)) 788 (setq to-file (concat dir fromdir))
700 (when (or (not (file-exists-p to-file)) 789 (when (or (not (file-exists-p to-file))
701 (gnus-y-or-n-p (format "%s exists; overwrite? " to-file))) 790 (eq gnus-uu-be-dangerous t)
791 (and gnus-uu-be-dangerous
792 (gnus-y-or-n-p (format "%s exists; overwrite? "
793 to-file))))
702 (copy-file file to-file t t))))) 794 (copy-file file to-file t t)))))
703 (gnus-message 5 "Saved %d file%s" len (if (= len 1) "" "s")))) 795 (gnus-message 5 "Saved %d file%s" len (if (= len 1) "" "s"))))
704 796
705 ;; Functions for saving and possibly digesting articles without 797 ;; Functions for saving and possibly digesting articles without
706 ;; any decoding. 798 ;; any decoding.
709 (defun gnus-uu-save-article (buffer in-state) 801 (defun gnus-uu-save-article (buffer in-state)
710 (cond 802 (cond
711 (gnus-uu-save-separate-articles 803 (gnus-uu-save-separate-articles
712 (save-excursion 804 (save-excursion
713 (set-buffer buffer) 805 (set-buffer buffer)
714 (write-region 1 (point-max) (concat gnus-uu-saved-article-name 806 (gnus-write-buffer
715 gnus-current-article)) 807 (concat gnus-uu-saved-article-name gnus-current-article))
716 (cond ((eq in-state 'first) (list gnus-uu-saved-article-name 'begin)) 808 (cond ((eq in-state 'first) (list gnus-uu-saved-article-name 'begin))
717 ((eq in-state 'first-and-last) (list gnus-uu-saved-article-name 809 ((eq in-state 'first-and-last) (list gnus-uu-saved-article-name
718 'begin 'end)) 810 'begin 'end))
719 ((eq in-state 'last) (list 'end)) 811 ((eq in-state 'last) (list 'end))
720 (t (list 'middle))))) 812 (t (list 'middle)))))
721 ((not gnus-uu-save-in-digest) 813 ((not gnus-uu-save-in-digest)
722 (save-excursion 814 (save-excursion
723 (set-buffer buffer) 815 (set-buffer buffer)
724 (write-region 1 (point-max) gnus-uu-saved-article-name t) 816 (write-region (point-min) (point-max) gnus-uu-saved-article-name t)
725 (cond ((eq in-state 'first) (list gnus-uu-saved-article-name 'begin)) 817 (cond ((eq in-state 'first) (list gnus-uu-saved-article-name 'begin))
726 ((eq in-state 'first-and-last) (list gnus-uu-saved-article-name 818 ((eq in-state 'first-and-last) (list gnus-uu-saved-article-name
727 'begin 'end)) 819 'begin 'end))
728 ((eq in-state 'last) (list 'end)) 820 ((eq in-state 'last) (list 'end))
729 (t (list 'middle))))) 821 (t (list 'middle)))))
730 (t 822 (t
731 (let ((header (gnus-summary-article-header))) 823 (let ((header (gnus-summary-article-header)))
732 (setq gnus-uu-digest-from-subject 824 (push (cons (mail-header-from header)
733 (cons (cons (mail-header-from header) 825 (mail-header-subject header))
734 (mail-header-subject header)) 826 gnus-uu-digest-from-subject))
735 gnus-uu-digest-from-subject)))
736 (let ((name (file-name-nondirectory gnus-uu-saved-article-name)) 827 (let ((name (file-name-nondirectory gnus-uu-saved-article-name))
737 (delim (concat "^" (make-string 30 ?-) "$")) 828 (delim (concat "^" (make-string 30 ?-) "$"))
738 beg subj headers headline sorthead body end-string state) 829 beg subj headers headline sorthead body end-string state)
739 (if (or (eq in-state 'first) 830 (if (or (eq in-state 'first)
740 (eq in-state 'first-and-last)) 831 (eq in-state 'first-and-last))
741 (progn 832 (progn
742 (setq state (list 'begin)) 833 (setq state (list 'begin))
743 (save-excursion (set-buffer (get-buffer-create "*gnus-uu-body*")) 834 (save-excursion (set-buffer (get-buffer-create "*gnus-uu-body*"))
744 (erase-buffer)) 835 (erase-buffer))
746 (set-buffer (get-buffer-create "*gnus-uu-pre*")) 837 (set-buffer (get-buffer-create "*gnus-uu-pre*"))
747 (erase-buffer) 838 (erase-buffer)
748 (insert (format 839 (insert (format
749 "Date: %s\nFrom: %s\nSubject: %s Digest\n\nTopics:\n" 840 "Date: %s\nFrom: %s\nSubject: %s Digest\n\nTopics:\n"
750 (current-time-string) name name)))) 841 (current-time-string) name name))))
751 (if (not (eq in-state 'end)) 842 (when (not (eq in-state 'end))
752 (setq state (list 'middle)))) 843 (setq state (list 'middle))))
753 (save-excursion 844 (save-excursion
754 (set-buffer (get-buffer "*gnus-uu-body*")) 845 (set-buffer (get-buffer "*gnus-uu-body*"))
755 (goto-char (setq beg (point-max))) 846 (goto-char (setq beg (point-max)))
756 (save-excursion 847 (save-excursion
757 (save-restriction 848 (save-restriction
788 (widen))) 879 (widen)))
789 (insert sorthead) (goto-char (point-max)) 880 (insert sorthead) (goto-char (point-max))
790 (insert body) (goto-char (point-max)) 881 (insert body) (goto-char (point-max))
791 (insert (concat "\n" (make-string 30 ?-) "\n\n")) 882 (insert (concat "\n" (make-string 30 ?-) "\n\n"))
792 (goto-char beg) 883 (goto-char beg)
793 (if (re-search-forward "^Subject: \\(.*\\)$" nil t) 884 (when (re-search-forward "^Subject: \\(.*\\)$" nil t)
794 (progn 885 (setq subj (buffer-substring (match-beginning 1) (match-end 1)))
795 (setq subj (buffer-substring (match-beginning 1) (match-end 1))) 886 (save-excursion
796 (save-excursion 887 (set-buffer (get-buffer "*gnus-uu-pre*"))
797 (set-buffer (get-buffer "*gnus-uu-pre*")) 888 (insert (format " %s\n" subj)))))
798 (insert (format " %s\n" subj)))))) 889 (when (or (eq in-state 'last)
799 (if (or (eq in-state 'last) 890 (eq in-state 'first-and-last))
800 (eq in-state 'first-and-last)) 891 (save-excursion
801 (progn 892 (set-buffer (get-buffer "*gnus-uu-pre*"))
802 (save-excursion 893 (insert (format "\n\n%s\n\n" (make-string 70 ?-)))
803 (set-buffer (get-buffer "*gnus-uu-pre*")) 894 (gnus-write-buffer gnus-uu-saved-article-name))
804 (insert (format "\n\n%s\n\n" (make-string 70 ?-))) 895 (save-excursion
805 (write-region 1 (point-max) gnus-uu-saved-article-name)) 896 (set-buffer (get-buffer "*gnus-uu-body*"))
806 (save-excursion 897 (goto-char (point-max))
807 (set-buffer (get-buffer "*gnus-uu-body*")) 898 (insert
808 (goto-char (point-max)) 899 (concat (setq end-string (format "End of %s Digest" name))
809 (insert 900 "\n"))
810 (concat (setq end-string (format "End of %s Digest" name)) 901 (insert (concat (make-string (length end-string) ?*) "\n"))
811 "\n")) 902 (write-region
812 (insert (concat (make-string (length end-string) ?*) "\n")) 903 (point-min) (point-max) gnus-uu-saved-article-name t))
813 (write-region 1 (point-max) gnus-uu-saved-article-name t)) 904 (kill-buffer (get-buffer "*gnus-uu-pre*"))
814 (kill-buffer (get-buffer "*gnus-uu-pre*")) 905 (kill-buffer (get-buffer "*gnus-uu-body*"))
815 (kill-buffer (get-buffer "*gnus-uu-body*")) 906 (push 'end state))
816 (setq state (cons 'end state))))
817 (if (memq 'begin state) 907 (if (memq 'begin state)
818 (cons gnus-uu-saved-article-name state) 908 (cons gnus-uu-saved-article-name state)
819 state))))) 909 state)))))
820 910
821 ;; Binhex treatment - not very advanced. 911 ;; Binhex treatment - not very advanced.
831 (let (state start-char) 921 (let (state start-char)
832 (save-excursion 922 (save-excursion
833 (set-buffer buffer) 923 (set-buffer buffer)
834 (widen) 924 (widen)
835 (goto-char (point-min)) 925 (goto-char (point-min))
836 (if (not (re-search-forward gnus-uu-binhex-begin-line nil t)) 926 (when (not (re-search-forward gnus-uu-binhex-begin-line nil t))
837 (if (not (re-search-forward gnus-uu-binhex-body-line nil t)) 927 (when (not (re-search-forward gnus-uu-binhex-body-line nil t))
838 (setq state (list 'wrong-type)))) 928 (setq state (list 'wrong-type))))
839 929
840 (if (memq 'wrong-type state) 930 (if (memq 'wrong-type state)
841 () 931 ()
842 (beginning-of-line) 932 (beginning-of-line)
843 (setq start-char (point)) 933 (setq start-char (point))
846 (setq state (list 'begin)) 936 (setq state (list 'begin))
847 (write-region 1 1 gnus-uu-binhex-article-name)) 937 (write-region 1 1 gnus-uu-binhex-article-name))
848 (setq state (list 'middle))) 938 (setq state (list 'middle)))
849 (goto-char (point-max)) 939 (goto-char (point-max))
850 (re-search-backward (concat gnus-uu-binhex-body-line "\\|" 940 (re-search-backward (concat gnus-uu-binhex-body-line "\\|"
851 gnus-uu-binhex-end-line) nil t) 941 gnus-uu-binhex-end-line)
852 (if (looking-at gnus-uu-binhex-end-line) 942 nil t)
853 (setq state (if (memq 'begin state) 943 (when (looking-at gnus-uu-binhex-end-line)
854 (cons 'end state) 944 (setq state (if (memq 'begin state)
855 (list 'end)))) 945 (cons 'end state)
946 (list 'end))))
856 (beginning-of-line) 947 (beginning-of-line)
857 (forward-line 1) 948 (forward-line 1)
858 (if (file-exists-p gnus-uu-binhex-article-name) 949 (when (file-exists-p gnus-uu-binhex-article-name)
859 (append-to-file start-char (point) gnus-uu-binhex-article-name)))) 950 (append-to-file start-char (point) gnus-uu-binhex-article-name))))
860 (if (memq 'begin state) 951 (if (memq 'begin state)
861 (cons gnus-uu-binhex-article-name state) 952 (cons gnus-uu-binhex-article-name state)
862 state))) 953 state)))
863 954
864 ;; PostScript 955 ;; PostScript
912 gnus-uu-user-view-rules 1003 gnus-uu-user-view-rules
913 (if gnus-uu-ignore-default-view-rules 1004 (if gnus-uu-ignore-default-view-rules
914 nil 1005 nil
915 gnus-uu-default-view-rules) 1006 gnus-uu-default-view-rules)
916 gnus-uu-user-view-rules-end))) 1007 gnus-uu-user-view-rules-end)))
917 (if (and (not (string= (or action "") "gnus-uu-archive")) 1008 (when (and (not (string= (or action "") "gnus-uu-archive"))
918 gnus-uu-view-with-metamail) 1009 gnus-uu-view-with-metamail)
919 (if (setq action 1010 (when (setq action
920 (gnus-uu-choose-action file-name gnus-uu-ext-to-mime-list)) 1011 (gnus-uu-choose-action file-name gnus-uu-ext-to-mime-list))
921 (setq action (format "metamail -d -b -c \"%s\"" action)))) 1012 (setq action (format "metamail -d -b -c \"%s\"" action))))
922 action)) 1013 action))
923 1014
924 1015
925 ;; Functions for treating subjects and collecting series. 1016 ;; Functions for treating subjects and collecting series.
926 1017
927 (defun gnus-uu-reginize-string (string) 1018 (defun gnus-uu-reginize-string (string)
928 ;; Takes a string and puts a \ in front of every special character; 1019 ;; Takes a string and puts a \ in front of every special character;
929 ;; ignores any leading "version numbers" thingies that they use in 1020 ;; ignores any leading "version numbers" thingies that they use in
930 ;; the comp.binaries groups, and either replaces anything that looks 1021 ;; the comp.binaries groups, and either replaces anything that looks
931 ;; like "2/3" with "[0-9]+/[0-9]+" or, if it can't find something 1022 ;; like "2/3" with "[0-9]+/[0-9]+" or, if it can't find something
932 ;; like that, replaces the last two numbers with "[0-9]+". This, in 1023 ;; like that, replaces the last two numbers with "[0-9]+". This, in
933 ;; my experience, should get most postings of a series. 1024 ;; my experience, should get most postings of a series.
934 (let ((count 2) 1025 (let ((count 2)
935 (vernum "v[0-9]+[a-z][0-9]+:") 1026 (vernum "v[0-9]+[a-z][0-9]+:")
936 beg) 1027 beg)
937 (save-excursion 1028 (save-excursion
941 (insert (regexp-quote string)) 1032 (insert (regexp-quote string))
942 (setq beg 1) 1033 (setq beg 1)
943 1034
944 (setq case-fold-search nil) 1035 (setq case-fold-search nil)
945 (goto-char (point-min)) 1036 (goto-char (point-min))
946 (if (looking-at vernum) 1037 (when (looking-at vernum)
947 (progn 1038 (replace-match vernum t t)
948 (replace-match vernum t t) 1039 (setq beg (length vernum)))
949 (setq beg (length vernum))))
950 1040
951 (goto-char beg) 1041 (goto-char beg)
952 (if (re-search-forward "[ \t]*[0-9]+/[0-9]+" nil t) 1042 (if (re-search-forward "[ \t]*[0-9]+/[0-9]+" nil t)
953 (replace-match " [0-9]+/[0-9]+") 1043 (replace-match " [0-9]+/[0-9]+")
954 1044
955 (goto-char beg) 1045 (goto-char beg)
956 (if (re-search-forward "[0-9]+[ \t]*of[ \t]*[0-9]+" nil t) 1046 (if (re-search-forward "[0-9]+[ \t]*of[ \t]*[0-9]+" nil t)
957 (replace-match "[0-9]+ of [0-9]+") 1047 (replace-match "[0-9]+ of [0-9]+")
958 1048
959 (end-of-line) 1049 (end-of-line)
960 (while (and (re-search-backward "[0-9]" nil t) (> count 0)) 1050 (if (re-search-backward "\\([^0-9]\\)[0-9]+\\([^0-9]+\\)[0-9]+"
961 (while (and 1051 nil t)
962 (looking-at "[0-9]") 1052 (replace-match "\\1[0-9]+\\2[0-9]+" t nil nil nil))))
963 (< 1 (goto-char (1- (point)))))) 1053
964 (re-search-forward "[0-9]+" nil t)
965 (replace-match "[0-9]+")
966 (backward-char 5)
967 (setq count (1- count)))))
968
969 (goto-char beg) 1054 (goto-char beg)
970 (while (re-search-forward "[ \t]+" nil t) 1055 (while (re-search-forward "[ \t]+" nil t)
971 (replace-match "[ \t]*" t t)) 1056 (replace-match "[ \t]*" t t))
972 1057
973 (buffer-substring 1 (point-max))))) 1058 (buffer-substring 1 (point-max)))))
980 ;; Failing that, articles that have subjects that are part of the 1065 ;; Failing that, articles that have subjects that are part of the
981 ;; same "series" as the current will be returned. 1066 ;; same "series" as the current will be returned.
982 (let (articles) 1067 (let (articles)
983 (cond 1068 (cond
984 (n 1069 (n
1070 (setq n (prefix-numeric-value n))
985 (let ((backward (< n 0)) 1071 (let ((backward (< n 0))
986 (n (abs n))) 1072 (n (abs n)))
987 (save-excursion 1073 (save-excursion
988 (while (and (> n 0) 1074 (while (and (> n 0)
989 (setq articles (cons (gnus-summary-article-number) 1075 (push (gnus-summary-article-number)
990 articles)) 1076 articles)
991 (gnus-summary-search-forward nil nil backward)) 1077 (gnus-summary-search-forward nil nil backward))
992 (setq n (1- n)))) 1078 (setq n (1- n))))
993 (nreverse articles))) 1079 (nreverse articles)))
994 (gnus-newsgroup-processable 1080 (gnus-newsgroup-processable
995 (reverse gnus-newsgroup-processable)) 1081 (reverse gnus-newsgroup-processable))
1000 (string< (car l1) (car l2))) 1086 (string< (car l1) (car l2)))
1001 1087
1002 (defun gnus-uu-find-articles-matching 1088 (defun gnus-uu-find-articles-matching
1003 (&optional subject only-unread do-not-translate) 1089 (&optional subject only-unread do-not-translate)
1004 ;; Finds all articles that matches the regexp SUBJECT. If it is 1090 ;; Finds all articles that matches the regexp SUBJECT. If it is
1005 ;; nil, the current article name will be used. If ONLY-UNREAD is 1091 ;; nil, the current article name will be used. If ONLY-UNREAD is
1006 ;; non-nil, only unread articles are chosen. If DO-NOT-TRANSLATE is 1092 ;; non-nil, only unread articles are chosen. If DO-NOT-TRANSLATE is
1007 ;; non-nil, article names are not equalized before sorting. 1093 ;; non-nil, article names are not equalized before sorting.
1008 (let ((subject (or subject 1094 (let ((subject (or subject
1009 (gnus-uu-reginize-string (gnus-summary-article-subject)))) 1095 (gnus-uu-reginize-string (gnus-summary-article-subject))))
1010 list-of-subjects) 1096 list-of-subjects)
1011 (save-excursion 1097 (save-excursion
1023 gnus-unread-mark) 1109 gnus-unread-mark)
1024 (= mark gnus-ticked-mark) 1110 (= mark gnus-ticked-mark)
1025 (= mark gnus-dormant-mark)) 1111 (= mark gnus-dormant-mark))
1026 (setq subj (mail-header-subject (gnus-data-header d))) 1112 (setq subj (mail-header-subject (gnus-data-header d)))
1027 (string-match subject subj) 1113 (string-match subject subj)
1028 (setq list-of-subjects 1114 (push (cons subj (gnus-data-number d))
1029 (cons (cons subj (gnus-data-number d)) 1115 list-of-subjects))))
1030 list-of-subjects)))))
1031 1116
1032 ;; Expand numbers, sort, and return the list of article 1117 ;; Expand numbers, sort, and return the list of article
1033 ;; numbers. 1118 ;; numbers.
1034 (mapcar (lambda (sub) (cdr sub)) 1119 (mapcar (lambda (sub) (cdr sub))
1035 (sort (gnus-uu-expand-numbers 1120 (sort (gnus-uu-expand-numbers
1036 list-of-subjects 1121 list-of-subjects
1037 (not do-not-translate)) 1122 (not do-not-translate))
1038 'gnus-uu-string<)))))) 1123 'gnus-uu-string<))))))
1039 1124
1040 (defun gnus-uu-expand-numbers (string-list &optional translate) 1125 (defun gnus-uu-expand-numbers (string-list &optional translate)
1041 ;; Takes a list of strings and "expands" all numbers in all the 1126 ;; Takes a list of strings and "expands" all numbers in all the
1042 ;; strings. That is, this function makes all numbers equal length by 1127 ;; strings. That is, this function makes all numbers equal length by
1043 ;; prepending lots of zeroes before each number. This is to ease later 1128 ;; prepending lots of zeroes before each number. This is to ease later
1044 ;; sorting to find out what sequence the articles are supposed to be 1129 ;; sorting to find out what sequence the articles are supposed to be
1045 ;; decoded in. Returns the list of expanded strings. 1130 ;; decoded in. Returns the list of expanded strings.
1046 (let ((out-list string-list) 1131 (let ((out-list string-list)
1047 string) 1132 string)
1048 (save-excursion 1133 (save-excursion
1049 (set-buffer (get-buffer-create gnus-uu-output-buffer-name)) 1134 (set-buffer (get-buffer-create gnus-uu-output-buffer-name))
1050 (buffer-disable-undo (current-buffer)) 1135 (buffer-disable-undo (current-buffer))
1055 (goto-char (point-min)) 1140 (goto-char (point-min))
1056 (while (re-search-forward "[ \t]+" nil t) 1141 (while (re-search-forward "[ \t]+" nil t)
1057 (replace-match " ")) 1142 (replace-match " "))
1058 ;; Translate all characters to "a". 1143 ;; Translate all characters to "a".
1059 (goto-char (point-min)) 1144 (goto-char (point-min))
1060 (if translate 1145 (when translate
1061 (while (re-search-forward "[A-Za-z]" nil t) 1146 (while (re-search-forward "[A-Za-z]" nil t)
1062 (replace-match "a" t t))) 1147 (replace-match "a" t t)))
1063 ;; Expand numbers. 1148 ;; Expand numbers.
1064 (goto-char (point-min)) 1149 (goto-char (point-min))
1065 (while (re-search-forward "[0-9]+" nil t) 1150 (while (re-search-forward "[0-9]+" nil t)
1066 (replace-match 1151 (replace-match
1067 (format "%06d" 1152 (format "%06d"
1076 ;; `gnus-uu-grab-articles' is the general multi-article treatment 1161 ;; `gnus-uu-grab-articles' is the general multi-article treatment
1077 ;; function. It takes a list of articles to be grabbed and a function 1162 ;; function. It takes a list of articles to be grabbed and a function
1078 ;; to apply to each article. 1163 ;; to apply to each article.
1079 ;; 1164 ;;
1080 ;; The function to be called should take two parameters. The first 1165 ;; The function to be called should take two parameters. The first
1081 ;; parameter is the article buffer. The function should leave the 1166 ;; parameter is the article buffer. The function should leave the
1082 ;; result, if any, in this buffer. Most treatment functions will just 1167 ;; result, if any, in this buffer. Most treatment functions will just
1083 ;; generate files... 1168 ;; generate files...
1084 ;; 1169 ;;
1085 ;; The second parameter is the state of the list of articles, and can 1170 ;; The second parameter is the state of the list of articles, and can
1086 ;; have four values: `first', `middle', `last' and `first-and-last'. 1171 ;; have four values: `first', `middle', `last' and `first-and-last'.
1087 ;; 1172 ;;
1088 ;; The function should return a list. The list may contain the 1173 ;; The function should return a list. The list may contain the
1089 ;; following symbols: 1174 ;; following symbols:
1090 ;; `error' if an error occurred 1175 ;; `error' if an error occurred
1091 ;; `begin' if the beginning of an encoded file has been received 1176 ;; `begin' if the beginning of an encoded file has been received
1092 ;; If the list returned contains a `begin', the first element of 1177 ;; If the list returned contains a `begin', the first element of
1093 ;; the list *must* be a string with the file name of the decoded 1178 ;; the list *must* be a string with the file name of the decoded
1102 (defun gnus-uu-unmark-list-of-grabbed (&optional dont-unmark-last-article) 1187 (defun gnus-uu-unmark-list-of-grabbed (&optional dont-unmark-last-article)
1103 (let (art) 1188 (let (art)
1104 (if (not (and gnus-uu-has-been-grabbed 1189 (if (not (and gnus-uu-has-been-grabbed
1105 gnus-uu-unmark-articles-not-decoded)) 1190 gnus-uu-unmark-articles-not-decoded))
1106 () 1191 ()
1107 (if dont-unmark-last-article 1192 (when dont-unmark-last-article
1108 (progn 1193 (setq art (car gnus-uu-has-been-grabbed))
1109 (setq art (car gnus-uu-has-been-grabbed)) 1194 (setq gnus-uu-has-been-grabbed (cdr gnus-uu-has-been-grabbed)))
1110 (setq gnus-uu-has-been-grabbed (cdr gnus-uu-has-been-grabbed))))
1111 (while gnus-uu-has-been-grabbed 1195 (while gnus-uu-has-been-grabbed
1112 (gnus-summary-tick-article (car gnus-uu-has-been-grabbed) t) 1196 (gnus-summary-tick-article (car gnus-uu-has-been-grabbed) t)
1113 (setq gnus-uu-has-been-grabbed (cdr gnus-uu-has-been-grabbed))) 1197 (setq gnus-uu-has-been-grabbed (cdr gnus-uu-has-been-grabbed)))
1114 (if dont-unmark-last-article 1198 (when dont-unmark-last-article
1115 (setq gnus-uu-has-been-grabbed (list art)))))) 1199 (setq gnus-uu-has-been-grabbed (list art))))))
1116 1200
1117 ;; This function takes a list of articles and a function to apply to 1201 ;; This function takes a list of articles and a function to apply to
1118 ;; each article grabbed. 1202 ;; each article grabbed.
1119 ;; 1203 ;;
1120 ;; This function returns a list of files decoded if the grabbing and 1204 ;; This function returns a list of files decoded if the grabbing and
1121 ;; the process-function has been successful and nil otherwise. 1205 ;; the process-function has been successful and nil otherwise.
1122 (defun gnus-uu-grab-articles (articles process-function 1206 (defun gnus-uu-grab-articles (articles process-function
1123 &optional sloppy limit no-errors) 1207 &optional sloppy limit no-errors)
1124 (let ((state 'first) 1208 (let ((state 'first)
1209 (gnus-asynchronous nil)
1125 has-been-begin article result-file result-files process-state 1210 has-been-begin article result-file result-files process-state
1126 gnus-summary-display-article-function 1211 gnus-summary-display-article-function
1127 gnus-article-display-hook gnus-article-prepare-hook 1212 gnus-article-display-hook gnus-article-prepare-hook
1128 article-series files) 1213 article-series files)
1129 1214
1158 (gnus-summary-remove-process-mark article) 1243 (gnus-summary-remove-process-mark article)
1159 1244
1160 ;; If this is the beginning of a decoded file, we push it 1245 ;; If this is the beginning of a decoded file, we push it
1161 ;; on to a list. 1246 ;; on to a list.
1162 (when (or (memq 'begin process-state) 1247 (when (or (memq 'begin process-state)
1163 (and (or (eq state 'first) 1248 (and (or (eq state 'first)
1164 (eq state 'first-and-last)) 1249 (eq state 'first-and-last))
1165 (memq 'ok process-state))) 1250 (memq 'ok process-state)))
1166 (if has-been-begin 1251 (when has-been-begin
1167 ;; If there is a `result-file' here, that means that the 1252 ;; If there is a `result-file' here, that means that the
1168 ;; file was unsuccessfully decoded, so we delete it. 1253 ;; file was unsuccessfully decoded, so we delete it.
1169 (when (and result-file 1254 (when (and result-file
1170 (file-exists-p result-file)) 1255 (file-exists-p result-file)
1171 (delete-file result-file))) 1256 (not gnus-uu-be-dangerous)
1257 (or (eq gnus-uu-be-dangerous t)
1258 (gnus-y-or-n-p
1259 (format "Delete unsuccessfully decoded file %s"
1260 result-file))))
1261 (delete-file result-file)))
1172 (when (memq 'begin process-state) 1262 (when (memq 'begin process-state)
1173 (setq result-file (car process-state))) 1263 (setq result-file (car process-state)))
1174 (setq has-been-begin t)) 1264 (setq has-been-begin t))
1175 1265
1176 ;; Check whether we have decoded one complete file. 1266 ;; Check whether we have decoded one complete file.
1190 (let ((funcs gnus-uu-grabbed-file-functions)) 1280 (let ((funcs gnus-uu-grabbed-file-functions))
1191 (unless (listp funcs) 1281 (unless (listp funcs)
1192 (setq funcs (list funcs))) 1282 (setq funcs (list funcs)))
1193 (while funcs 1283 (while funcs
1194 (funcall (pop funcs) result-file)))) 1284 (funcall (pop funcs) result-file))))
1285 (setq result-file nil)
1195 ;; Check whether we have decoded enough articles. 1286 ;; Check whether we have decoded enough articles.
1196 (and limit (= (length result-files) limit) 1287 (and limit (= (length result-files) limit)
1197 (setq articles nil))) 1288 (setq articles nil)))
1198 1289
1199 ;; If this is the last article to be decoded, and 1290 ;; If this is the last article to be decoded, and
1201 ;; the partially decoded file. 1292 ;; the partially decoded file.
1202 (and (or (eq state 'last) (eq state 'first-and-last)) 1293 (and (or (eq state 'last) (eq state 'first-and-last))
1203 (not (memq 'end process-state)) 1294 (not (memq 'end process-state))
1204 result-file 1295 result-file
1205 (file-exists-p result-file) 1296 (file-exists-p result-file)
1297 (not gnus-uu-be-dangerous)
1298 (or (eq gnus-uu-be-dangerous t)
1299 (gnus-y-or-n-p (format "Delete incomplete file %s? " result-file)))
1206 (delete-file result-file)) 1300 (delete-file result-file))
1207 1301
1208 ;; If this was a file of the wrong sort, then 1302 ;; If this was a file of the wrong sort, then
1209 (when (and (or (memq 'wrong-type process-state) 1303 (when (and (or (memq 'wrong-type process-state)
1210 (memq 'error process-state)) 1304 (memq 'error process-state))
1228 (cond 1322 (cond
1229 ((not has-been-begin) 1323 ((not has-been-begin)
1230 (gnus-message 2 "Wrong type file")) 1324 (gnus-message 2 "Wrong type file"))
1231 ((memq 'error process-state) 1325 ((memq 'error process-state)
1232 (gnus-message 2 "An error occurred during decoding")) 1326 (gnus-message 2 "An error occurred during decoding"))
1233 ((not (or (memq 'ok process-state) 1327 ((not (or (memq 'ok process-state)
1234 (memq 'end process-state))) 1328 (memq 'end process-state)))
1235 (gnus-message 2 "End of articles reached before end of file"))) 1329 (gnus-message 2 "End of articles reached before end of file")))
1236 ;; Make unsuccessfully decoded articles unread. 1330 ;; Make unsuccessfully decoded articles unread.
1237 (when gnus-uu-unmark-articles-not-decoded 1331 (when gnus-uu-unmark-articles-not-decoded
1238 (while article-series 1332 (while article-series
1297 ;; We replace certain characters that could make things messy. 1391 ;; We replace certain characters that could make things messy.
1298 (setq gnus-uu-file-name 1392 (setq gnus-uu-file-name
1299 (let ((nnheader-file-name-translation-alist 1393 (let ((nnheader-file-name-translation-alist
1300 '((?/ . ?,) (? . ?_) (?* . ?_) (?$ . ?_)))) 1394 '((?/ . ?,) (? . ?_) (?* . ?_) (?$ . ?_))))
1301 (nnheader-translate-file-chars (match-string 1)))) 1395 (nnheader-translate-file-chars (match-string 1))))
1396 (replace-match (concat "begin 644 " gnus-uu-file-name) t t)
1302 1397
1303 ;; Remove any non gnus-uu-body-line right after start. 1398 ;; Remove any non gnus-uu-body-line right after start.
1304 (forward-line 1) 1399 (forward-line 1)
1305 (while (and (not (eobp)) 1400 (while (and (not (eobp))
1306 (not (looking-at gnus-uu-body-line))) 1401 (not (looking-at gnus-uu-body-line)))
1307 (gnus-delete-line)) 1402 (gnus-delete-line))
1308 1403
1309 ;; If a process is running, we kill it. 1404 ;; If a process is running, we kill it.
1310 (when (and gnus-uu-uudecode-process 1405 (when (and gnus-uu-uudecode-process
1311 (memq (process-status gnus-uu-uudecode-process) 1406 (memq (process-status gnus-uu-uudecode-process)
1312 '(run stop))) 1407 '(run stop)))
1313 (delete-process gnus-uu-uudecode-process) 1408 (delete-process gnus-uu-uudecode-process)
1314 (gnus-uu-unmark-list-of-grabbed t)) 1409 (gnus-uu-unmark-list-of-grabbed t))
1315 1410
1316 ;; Start a new uudecoding process. 1411 ;; Start a new uudecoding process.
1331 (setq state (list 'begin)) 1426 (setq state (list 'begin))
1332 (push (concat gnus-uu-work-dir gnus-uu-file-name) files)) 1427 (push (concat gnus-uu-work-dir gnus-uu-file-name) files))
1333 1428
1334 ;; We look for the end of the thing to be decoded. 1429 ;; We look for the end of the thing to be decoded.
1335 (if (re-search-forward gnus-uu-end-string nil t) 1430 (if (re-search-forward gnus-uu-end-string nil t)
1336 (setq state (cons 'end state)) 1431 (push 'end state)
1337 (goto-char (point-max)) 1432 (goto-char (point-max))
1338 (re-search-backward gnus-uu-body-line nil t)) 1433 (re-search-backward gnus-uu-body-line nil t))
1339 1434
1340 (forward-line 1) 1435 (forward-line 1)
1341 1436
1356 (setq state (list 'wrong-type))))) 1451 (setq state (list 'wrong-type)))))
1357 1452
1358 (if (memq 'end state) 1453 (if (memq 'end state)
1359 (progn 1454 (progn
1360 ;; Send an EOF, just in case. 1455 ;; Send an EOF, just in case.
1361 (condition-case () 1456 (ignore-errors
1362 (process-send-eof gnus-uu-uudecode-process) 1457 (process-send-eof gnus-uu-uudecode-process))
1363 (error nil))
1364 (while (memq (process-status gnus-uu-uudecode-process) 1458 (while (memq (process-status gnus-uu-uudecode-process)
1365 '(open run)) 1459 '(open run))
1366 (accept-process-output gnus-uu-uudecode-process 1))) 1460 (accept-process-output gnus-uu-uudecode-process 1)))
1367 (when (or (not gnus-uu-uudecode-process) 1461 (when (or (not gnus-uu-uudecode-process)
1368 (not (memq (process-status gnus-uu-uudecode-process) 1462 (not (memq (process-status gnus-uu-uudecode-process)
1386 (beginning-of-line) 1480 (beginning-of-line)
1387 (setq start-char (point)) 1481 (setq start-char (point))
1388 (call-process-region 1482 (call-process-region
1389 start-char (point-max) shell-file-name nil 1483 start-char (point-max) shell-file-name nil
1390 (get-buffer-create gnus-uu-output-buffer-name) nil 1484 (get-buffer-create gnus-uu-output-buffer-name) nil
1391 shell-command-switch (concat "cd " gnus-uu-work-dir " ; sh")))) 1485 shell-command-switch
1486 (concat "cd " gnus-uu-work-dir " "
1487 gnus-shell-command-separator " sh"))))
1392 state)) 1488 state))
1393 1489
1394 ;; Returns the name of what the shar file is going to unpack. 1490 ;; Returns the name of what the shar file is going to unpack.
1395 (defun gnus-uu-find-name-in-shar () 1491 (defun gnus-uu-find-name-in-shar ()
1396 (let ((oldpoint (point)) 1492 (let ((oldpoint (point))
1397 res) 1493 res)
1398 (goto-char (point-min)) 1494 (goto-char (point-min))
1399 (if (re-search-forward gnus-uu-shar-name-marker nil t) 1495 (when (re-search-forward gnus-uu-shar-name-marker nil t)
1400 (setq res (buffer-substring (match-beginning 1) (match-end 1)))) 1496 (setq res (buffer-substring (match-beginning 1) (match-end 1))))
1401 (goto-char oldpoint) 1497 (goto-char oldpoint)
1402 res)) 1498 res))
1403 1499
1404 ;; `gnus-uu-choose-action' chooses what action to perform given the name 1500 ;; `gnus-uu-choose-action' chooses what action to perform given the name
1405 ;; and `gnus-uu-file-action-list'. Returns either nil if no action is 1501 ;; and `gnus-uu-file-action-list'. Returns either nil if no action is
1407 (defun gnus-uu-choose-action (file-name file-action-list &optional no-ignore) 1503 (defun gnus-uu-choose-action (file-name file-action-list &optional no-ignore)
1408 (let ((action-list (copy-sequence file-action-list)) 1504 (let ((action-list (copy-sequence file-action-list))
1409 (case-fold-search t) 1505 (case-fold-search t)
1410 rule action) 1506 rule action)
1411 (and 1507 (and
1412 (or no-ignore 1508 (unless no-ignore
1413 (and (not 1509 (and (not
1414 (and gnus-uu-ignore-files-by-name 1510 (and gnus-uu-ignore-files-by-name
1415 (string-match gnus-uu-ignore-files-by-name file-name))) 1511 (string-match gnus-uu-ignore-files-by-name file-name)))
1416 (not 1512 (not
1417 (and gnus-uu-ignore-files-by-type 1513 (and gnus-uu-ignore-files-by-type
1418 (string-match gnus-uu-ignore-files-by-type 1514 (string-match gnus-uu-ignore-files-by-type
1419 (or (gnus-uu-choose-action 1515 (or (gnus-uu-choose-action
1420 file-name gnus-uu-ext-to-mime-list t) 1516 file-name gnus-uu-ext-to-mime-list t)
1421 "")))))) 1517 ""))))))
1422 (while (not (or (eq action-list ()) action)) 1518 (while (not (or (eq action-list ()) action))
1423 (setq rule (car action-list)) 1519 (setq rule (car action-list))
1424 (setq action-list (cdr action-list)) 1520 (setq action-list (cdr action-list))
1425 (if (string-match (car rule) file-name) 1521 (when (string-match (car rule) file-name)
1426 (setq action (cadr rule))))) 1522 (setq action (cadr rule)))))
1427 action)) 1523 action))
1428 1524
1429 (defun gnus-uu-treat-archive (file-path) 1525 (defun gnus-uu-treat-archive (file-path)
1430 ;; Unpacks an archive. Returns t if unpacking is successful. 1526 ;; Unpacks an archive. Returns t if unpacking is successful.
1431 (let ((did-unpack t) 1527 (let ((did-unpack t)
1432 action command dir) 1528 action command dir)
1433 (setq action (gnus-uu-choose-action 1529 (setq action (gnus-uu-choose-action
1434 file-path (append gnus-uu-user-archive-rules 1530 file-path (append gnus-uu-user-archive-rules
1435 (if gnus-uu-ignore-default-archive-rules 1531 (if gnus-uu-ignore-default-archive-rules
1436 nil 1532 nil
1437 gnus-uu-default-archive-rules)))) 1533 gnus-uu-default-archive-rules))))
1438 1534
1439 (if (not action) (error "No unpackers for the file %s" file-path)) 1535 (when (not action)
1536 (error "No unpackers for the file %s" file-path))
1440 1537
1441 (string-match "/[^/]*$" file-path) 1538 (string-match "/[^/]*$" file-path)
1442 (setq dir (substring file-path 0 (match-beginning 0))) 1539 (setq dir (substring file-path 0 (match-beginning 0)))
1443 1540
1444 (if (member action gnus-uu-destructive-archivers) 1541 (when (member action gnus-uu-destructive-archivers)
1445 (copy-file file-path (concat file-path "~") t)) 1542 (copy-file file-path (concat file-path "~") t))
1446 1543
1447 (setq command (format "cd %s ; %s" dir (gnus-uu-command action file-path))) 1544 (setq command (format "cd %s ; %s" dir (gnus-uu-command action file-path)))
1448 1545
1449 (save-excursion 1546 (save-excursion
1450 (set-buffer (get-buffer-create gnus-uu-output-buffer-name)) 1547 (set-buffer (get-buffer-create gnus-uu-output-buffer-name))
1457 nil shell-command-switch command)) 1554 nil shell-command-switch command))
1458 (message "") 1555 (message "")
1459 (gnus-message 2 "Error during unpacking of archive") 1556 (gnus-message 2 "Error during unpacking of archive")
1460 (setq did-unpack nil)) 1557 (setq did-unpack nil))
1461 1558
1462 (if (member action gnus-uu-destructive-archivers) 1559 (when (member action gnus-uu-destructive-archivers)
1463 (rename-file (concat file-path "~") file-path t)) 1560 (rename-file (concat file-path "~") file-path t))
1464 1561
1465 did-unpack)) 1562 did-unpack))
1466 1563
1467 (defun gnus-uu-dir-files (dir) 1564 (defun gnus-uu-dir-files (dir)
1468 (let ((dirs (directory-files dir t "[^/][^\\.][^\\.]?$")) 1565 (let ((dirs (directory-files dir t "[^/][^\\.][^\\.]?$"))
1469 files file) 1566 files file)
1470 (while dirs 1567 (while dirs
1471 (if (file-directory-p (setq file (car dirs))) 1568 (if (file-directory-p (setq file (car dirs)))
1472 (setq files (append files (gnus-uu-dir-files file))) 1569 (setq files (append files (gnus-uu-dir-files file)))
1473 (setq files (cons file files))) 1570 (push file files))
1474 (setq dirs (cdr dirs))) 1571 (setq dirs (cdr dirs)))
1475 files)) 1572 files))
1476 1573
1477 (defun gnus-uu-unpack-files (files &optional ignore) 1574 (defun gnus-uu-unpack-files (files &optional ignore)
1478 ;; Go through FILES and look for files to unpack. 1575 ;; Go through FILES and look for files to unpack.
1479 (let* ((totfiles (gnus-uu-ls-r gnus-uu-work-dir)) 1576 (let* ((totfiles (gnus-uu-ls-r gnus-uu-work-dir))
1480 (ofiles files) 1577 (ofiles files)
1481 file did-unpack) 1578 file did-unpack)
1482 (while files 1579 (while files
1483 (setq file (cdr (assq 'name (car files)))) 1580 (setq file (cdr (assq 'name (car files))))
1484 (if (and (not (member file ignore)) 1581 (when (and (not (member file ignore))
1485 (equal (gnus-uu-get-action (file-name-nondirectory file)) 1582 (equal (gnus-uu-get-action (file-name-nondirectory file))
1486 "gnus-uu-archive")) 1583 "gnus-uu-archive"))
1487 (progn 1584 (push file did-unpack)
1488 (setq did-unpack (cons file did-unpack)) 1585 (unless (gnus-uu-treat-archive file)
1489 (or (gnus-uu-treat-archive file) 1586 (gnus-message 2 "Error during unpacking of %s" file))
1490 (gnus-message 2 "Error during unpacking of %s" file)) 1587 (let* ((newfiles (gnus-uu-ls-r gnus-uu-work-dir))
1491 (let* ((newfiles (gnus-uu-ls-r gnus-uu-work-dir)) 1588 (nfiles newfiles))
1492 (nfiles newfiles)) 1589 (while nfiles
1493 (while nfiles 1590 (unless (member (car nfiles) totfiles)
1494 (or (member (car nfiles) totfiles) 1591 (push (list (cons 'name (car nfiles))
1495 (setq ofiles (cons (list (cons 'name (car nfiles)) 1592 (cons 'original file))
1496 (cons 'original file)) 1593 ofiles))
1497 ofiles))) 1594 (setq nfiles (cdr nfiles)))
1498 (setq nfiles (cdr nfiles))) 1595 (setq totfiles newfiles)))
1499 (setq totfiles newfiles))))
1500 (setq files (cdr files))) 1596 (setq files (cdr files)))
1501 (if did-unpack 1597 (if did-unpack
1502 (gnus-uu-unpack-files ofiles (append did-unpack ignore)) 1598 (gnus-uu-unpack-files ofiles (append did-unpack ignore))
1503 ofiles))) 1599 ofiles)))
1504 1600
1505 (defun gnus-uu-ls-r (dir) 1601 (defun gnus-uu-ls-r (dir)
1506 (let* ((files (gnus-uu-directory-files dir t)) 1602 (let* ((files (gnus-uu-directory-files dir t))
1507 (ofiles files)) 1603 (ofiles files))
1508 (while files 1604 (while files
1509 (if (file-directory-p (car files)) 1605 (when (file-directory-p (car files))
1510 (progn 1606 (setq ofiles (delete (car files) ofiles))
1511 (setq ofiles (delete (car files) ofiles)) 1607 (setq ofiles (append ofiles (gnus-uu-ls-r (car files)))))
1512 (setq ofiles (append ofiles (gnus-uu-ls-r (car files))))))
1513 (setq files (cdr files))) 1608 (setq files (cdr files)))
1514 ofiles)) 1609 ofiles))
1515 1610
1516 ;; Various stuff 1611 ;; Various stuff
1517 1612
1519 (let (files out file) 1614 (let (files out file)
1520 (setq files (directory-files dir full)) 1615 (setq files (directory-files dir full))
1521 (while files 1616 (while files
1522 (setq file (car files)) 1617 (setq file (car files))
1523 (setq files (cdr files)) 1618 (setq files (cdr files))
1524 (or (member (file-name-nondirectory file) '("." "..")) 1619 (unless (member (file-name-nondirectory file) '("." ".."))
1525 (setq out (cons file out)))) 1620 (push file out)))
1526 (setq out (nreverse out)) 1621 (setq out (nreverse out))
1527 out)) 1622 out))
1528 1623
1529 (defun gnus-uu-check-correct-stripped-uucode (start end) 1624 (defun gnus-uu-check-correct-stripped-uucode (start end)
1530 (save-excursion 1625 (save-excursion
1536 (if (re-search-forward " \\|`" end t) 1631 (if (re-search-forward " \\|`" end t)
1537 (progn 1632 (progn
1538 (goto-char start) 1633 (goto-char start)
1539 (while (not (eobp)) 1634 (while (not (eobp))
1540 (progn 1635 (progn
1541 (if (looking-at "\n") (replace-match "")) 1636 (when (looking-at "\n")
1637 (replace-match ""))
1542 (forward-line 1)))) 1638 (forward-line 1))))
1543 1639
1544 (while (not (eobp)) 1640 (while (not (eobp))
1545 (if (looking-at (concat gnus-uu-begin-string "\\|" 1641 (if (looking-at (concat gnus-uu-begin-string "\\|"
1546 gnus-uu-end-string)) 1642 gnus-uu-end-string))
1547 () 1643 ()
1548 (if (not found) 1644 (when (not found)
1549 (progn 1645 (beginning-of-line)
1550 (beginning-of-line) 1646 (setq beg (point))
1551 (setq beg (point)) 1647 (end-of-line)
1552 (end-of-line) 1648 (setq length (- (point) beg)))
1553 (setq length (- (point) beg))))
1554 (setq found t) 1649 (setq found t)
1555 (beginning-of-line) 1650 (beginning-of-line)
1556 (setq beg (point)) 1651 (setq beg (point))
1557 (end-of-line) 1652 (end-of-line)
1558 (if (not (= length (- (point) beg))) 1653 (when (not (= length (- (point) beg)))
1559 (insert (make-string (- length (- (point) beg)) ? )))) 1654 (insert (make-string (- length (- (point) beg)) ? ))))
1560 (forward-line 1))))))) 1655 (forward-line 1)))))))
1561 1656
1562 (defvar gnus-uu-tmp-alist nil) 1657 (defvar gnus-uu-tmp-alist nil)
1563 1658
1564 (defun gnus-uu-initialize (&optional scan) 1659 (defun gnus-uu-initialize (&optional scan)
1565 (let (entry) 1660 (let (entry)
1566 (if (and (not scan) 1661 (if (and (not scan)
1567 (if (setq entry (assoc gnus-newsgroup-name gnus-uu-tmp-alist)) 1662 (when (setq entry (assoc gnus-newsgroup-name gnus-uu-tmp-alist))
1568 (if (file-exists-p (cdr entry)) 1663 (if (file-exists-p (cdr entry))
1569 (setq gnus-uu-work-dir (cdr entry)) 1664 (setq gnus-uu-work-dir (cdr entry))
1570 (setq gnus-uu-tmp-alist (delq entry gnus-uu-tmp-alist)) 1665 (setq gnus-uu-tmp-alist (delq entry gnus-uu-tmp-alist))
1571 nil))) 1666 nil)))
1572 t 1667 t
1573 (setq gnus-uu-tmp-dir (file-name-as-directory 1668 (setq gnus-uu-tmp-dir (file-name-as-directory
1574 (expand-file-name gnus-uu-tmp-dir))) 1669 (expand-file-name gnus-uu-tmp-dir)))
1575 (if (not (file-directory-p gnus-uu-tmp-dir)) 1670 (if (not (file-directory-p gnus-uu-tmp-dir))
1576 (error "Temp directory %s doesn't exist" gnus-uu-tmp-dir) 1671 (error "Temp directory %s doesn't exist" gnus-uu-tmp-dir)
1577 (if (not (file-writable-p gnus-uu-tmp-dir)) 1672 (when (not (file-writable-p gnus-uu-tmp-dir))
1578 (error "Temp directory %s can't be written to" 1673 (error "Temp directory %s can't be written to"
1579 gnus-uu-tmp-dir))) 1674 gnus-uu-tmp-dir)))
1580 1675
1581 (setq gnus-uu-work-dir 1676 (setq gnus-uu-work-dir
1582 (make-temp-name (concat gnus-uu-tmp-dir "gnus"))) 1677 (make-temp-name (concat gnus-uu-tmp-dir "gnus")))
1583 (if (not (file-directory-p gnus-uu-work-dir)) 1678 (gnus-make-directory gnus-uu-work-dir)
1584 (gnus-make-directory gnus-uu-work-dir))
1585 (set-file-modes gnus-uu-work-dir 448) 1679 (set-file-modes gnus-uu-work-dir 448)
1586 (setq gnus-uu-work-dir (file-name-as-directory gnus-uu-work-dir)) 1680 (setq gnus-uu-work-dir (file-name-as-directory gnus-uu-work-dir))
1587 (setq gnus-uu-tmp-alist (cons (cons gnus-newsgroup-name gnus-uu-work-dir) 1681 (push (cons gnus-newsgroup-name gnus-uu-work-dir)
1588 gnus-uu-tmp-alist))))) 1682 gnus-uu-tmp-alist))))
1589 1683
1590 1684
1591 ;; Kills the temporary uu buffers, kills any processes, etc. 1685 ;; Kills the temporary uu buffers, kills any processes, etc.
1592 (defun gnus-uu-clean-up () 1686 (defun gnus-uu-clean-up ()
1593 (let (buf) 1687 (let (buf)
1594 (and gnus-uu-uudecode-process 1688 (and gnus-uu-uudecode-process
1595 (memq (process-status (or gnus-uu-uudecode-process "nevair")) 1689 (memq (process-status (or gnus-uu-uudecode-process "nevair"))
1596 '(stop run)) 1690 '(stop run))
1597 (delete-process gnus-uu-uudecode-process)) 1691 (delete-process gnus-uu-uudecode-process))
1598 (and (setq buf (get-buffer gnus-uu-output-buffer-name)) 1692 (when (setq buf (get-buffer gnus-uu-output-buffer-name))
1599 (kill-buffer buf)))) 1693 (kill-buffer buf))))
1600 1694
1601 ;; Inputs an action and a file and returns a full command, putting 1695 (defun gnus-quote-arg-for-sh-or-csh (arg)
1602 ;; quotes round the file name and escaping any quotes in the file name. 1696 (let ((pos 0) new-pos accum)
1697 ;; *** bug: we don't handle newline characters properly
1698 (while (setq new-pos (string-match "[!`\"$\\& \t]" arg pos))
1699 (push (substring arg pos new-pos) accum)
1700 (push "\\" accum)
1701 (push (list (aref arg new-pos)) accum)
1702 (setq pos (1+ new-pos)))
1703 (if (= pos 0)
1704 arg
1705 (apply 'concat (nconc (nreverse accum) (list (substring arg pos)))))))
1706
1707 ;; Inputs an action and a filename and returns a full command, making sure
1708 ;; that the filename will be treated as a single argument when the shell
1709 ;; executes the command.
1603 (defun gnus-uu-command (action file) 1710 (defun gnus-uu-command (action file)
1604 (let ((ofile "")) 1711 (let ((quoted-file (gnus-quote-arg-for-sh-or-csh file)))
1605 (while (string-match "!\\|`\\|\"\\|\\$\\|\\\\\\|&" file)
1606 (progn
1607 (setq ofile
1608 (concat ofile (substring file 0 (match-beginning 0)) "\\"
1609 (substring file (match-beginning 0) (match-end 0))))
1610 (setq file (substring file (1+ (match-beginning 0))))))
1611 (setq ofile (concat "\"" ofile file "\""))
1612 (if (string-match "%s" action) 1712 (if (string-match "%s" action)
1613 (format action ofile) 1713 (format action quoted-file)
1614 (concat action " " ofile)))) 1714 (concat action " " quoted-file))))
1615 1715
1616 (defun gnus-uu-delete-work-dir (&optional dir) 1716 (defun gnus-uu-delete-work-dir (&optional dir)
1617 "Delete recursively all files and directories under `gnus-uu-work-dir'." 1717 "Delete recursively all files and directories under `gnus-uu-work-dir'."
1618 (if dir 1718 (if dir
1619 (gnus-message 7 "Deleting directory %s..." dir) 1719 (gnus-message 7 "Deleting directory %s..." dir)
1641 ;;; 1741 ;;;
1642 ;;; uuencoded posting 1742 ;;; uuencoded posting
1643 ;;; 1743 ;;;
1644 1744
1645 ;; Any function that is to be used as and encoding method will take two 1745 ;; Any function that is to be used as and encoding method will take two
1646 ;; parameters: PATH-NAME and FILE-NAME. (E.g. "/home/gaga/spiral.jpg" 1746 ;; parameters: PATH-NAME and FILE-NAME. (E.g. "/home/gaga/spiral.jpg"
1647 ;; and "spiral.jpg", respectively.) The function should return nil if 1747 ;; and "spiral.jpg", respectively.) The function should return nil if
1648 ;; the encoding wasn't successful. 1748 ;; the encoding wasn't successful.
1649 (defvar gnus-uu-post-encode-method 'gnus-uu-post-encode-uuencode 1749 (defcustom gnus-uu-post-encode-method 'gnus-uu-post-encode-uuencode
1650 "Function used for encoding binary files. 1750 "Function used for encoding binary files.
1651 There are three functions supplied with gnus-uu for encoding files: 1751 There are three functions supplied with gnus-uu for encoding files:
1652 `gnus-uu-post-encode-uuencode', which does straight uuencoding; 1752 `gnus-uu-post-encode-uuencode', which does straight uuencoding;
1653 `gnus-uu-post-encode-mime', which encodes with base64 and adds MIME 1753 `gnus-uu-post-encode-mime', which encodes with base64 and adds MIME
1654 headers; and `gnus-uu-post-encode-mime-uuencode', which encodes with 1754 headers; and `gnus-uu-post-encode-mime-uuencode', which encodes with
1655 uuencode and adds MIME headers.") 1755 uuencode and adds MIME headers."
1656 1756 :group 'gnus-extract-post
1657 (defvar gnus-uu-post-include-before-composing nil 1757 :type '(radio (function-item gnus-uu-post-encode-uuencode)
1758 (function-item gnus-uu-post-encode-mime)
1759 (function-item gnus-uu-post-encode-mime-uuencode)
1760 (function :tag "Other")))
1761
1762 (defcustom gnus-uu-post-include-before-composing nil
1658 "Non-nil means that gnus-uu will ask for a file to encode before you compose the article. 1763 "Non-nil means that gnus-uu will ask for a file to encode before you compose the article.
1659 If this variable is t, you can either include an encoded file with 1764 If this variable is t, you can either include an encoded file with
1660 \\[gnus-uu-post-insert-binary-in-article] or have one included for you when you post the article.") 1765 \\[gnus-uu-post-insert-binary-in-article] or have one included for you when you post the article."
1661 1766 :group 'gnus-extract-post
1662 (defvar gnus-uu-post-length 990 1767 :type 'boolean)
1768
1769 (defcustom gnus-uu-post-length 990
1663 "Maximum length of an article. 1770 "Maximum length of an article.
1664 The encoded file will be split into how many articles it takes to 1771 The encoded file will be split into how many articles it takes to
1665 post the entire file.") 1772 post the entire file."
1666 1773 :group 'gnus-extract-post
1667 (defvar gnus-uu-post-threaded nil 1774 :type 'integer)
1775
1776 (defcustom gnus-uu-post-threaded nil
1668 "Non-nil means that gnus-uu will post the encoded file in a thread. 1777 "Non-nil means that gnus-uu will post the encoded file in a thread.
1669 This may not be smart, as no other decoder I have seen are able to 1778 This may not be smart, as no other decoder I have seen are able to
1670 follow threads when collecting uuencoded articles. (Well, I have seen 1779 follow threads when collecting uuencoded articles. (Well, I have seen
1671 one package that does that - gnus-uu, but somehow, I don't think that 1780 one package that does that - gnus-uu, but somehow, I don't think that
1672 counts...) Default is nil.") 1781 counts...) Default is nil."
1673 1782 :group 'gnus-extract-post
1674 (defvar gnus-uu-post-separate-description t 1783 :type 'boolean)
1784
1785 (defcustom gnus-uu-post-separate-description t
1675 "Non-nil means that the description will be posted in a separate article. 1786 "Non-nil means that the description will be posted in a separate article.
1676 The first article will typically be numbered (0/x). If this variable 1787 The first article will typically be numbered (0/x). If this variable
1677 is nil, the description the user enters will be included at the 1788 is nil, the description the user enters will be included at the
1678 beginning of the first article, which will be numbered (1/x). Default 1789 beginning of the first article, which will be numbered (1/x). Default
1679 is t.") 1790 is t."
1791 :group 'gnus-extract-post
1792 :type 'boolean)
1680 1793
1681 (defvar gnus-uu-post-binary-separator "--binary follows this line--") 1794 (defvar gnus-uu-post-binary-separator "--binary follows this line--")
1682 (defvar gnus-uu-post-message-id nil) 1795 (defvar gnus-uu-post-message-id nil)
1683 (defvar gnus-uu-post-inserted-file-name nil) 1796 (defvar gnus-uu-post-inserted-file-name nil)
1684 (defvar gnus-uu-winconf-post-news nil) 1797 (defvar gnus-uu-winconf-post-news nil)
1695 (local-set-key "\C-c\C-c" 'gnus-summary-edit-article-done) 1808 (local-set-key "\C-c\C-c" 'gnus-summary-edit-article-done)
1696 (local-set-key "\C-c\C-c" 'gnus-uu-post-news-inews) 1809 (local-set-key "\C-c\C-c" 'gnus-uu-post-news-inews)
1697 (local-set-key "\C-c\C-s" 'gnus-uu-post-news-inews) 1810 (local-set-key "\C-c\C-s" 'gnus-uu-post-news-inews)
1698 (local-set-key "\C-c\C-i" 'gnus-uu-post-insert-binary-in-article) 1811 (local-set-key "\C-c\C-i" 'gnus-uu-post-insert-binary-in-article)
1699 1812
1700 (if gnus-uu-post-include-before-composing 1813 (when gnus-uu-post-include-before-composing
1701 (save-excursion (setq gnus-uu-post-inserted-file-name 1814 (save-excursion (setq gnus-uu-post-inserted-file-name
1702 (gnus-uu-post-insert-binary))))) 1815 (gnus-uu-post-insert-binary)))))
1703 1816
1704 (defun gnus-uu-post-insert-binary-in-article () 1817 (defun gnus-uu-post-insert-binary-in-article ()
1705 "Inserts an encoded file in the buffer. 1818 "Inserts an encoded file in the buffer.
1706 The user will be asked for a file name." 1819 The user will be asked for a file name."
1707 (interactive) 1820 (interactive)
1708 (save-excursion 1821 (save-excursion
1709 (setq gnus-uu-post-inserted-file-name (gnus-uu-post-insert-binary)))) 1822 (setq gnus-uu-post-inserted-file-name (gnus-uu-post-insert-binary))))
1710 1823
1711 ;; Encodes with uuencode and substitutes all spaces with backticks. 1824 ;; Encodes with uuencode and substitutes all spaces with backticks.
1712 (defun gnus-uu-post-encode-uuencode (path file-name) 1825 (defun gnus-uu-post-encode-uuencode (path file-name)
1713 (if (gnus-uu-post-encode-file "uuencode" path file-name) 1826 (when (gnus-uu-post-encode-file "uuencode" path file-name)
1714 (progn 1827 (goto-char (point-min))
1715 (goto-char (point-min)) 1828 (forward-line 1)
1716 (forward-line 1) 1829 (while (re-search-forward " " nil t)
1717 (while (re-search-forward " " nil t) 1830 (replace-match "`"))
1718 (replace-match "`")) 1831 t))
1719 t)))
1720 1832
1721 ;; Encodes with uuencode and adds MIME headers. 1833 ;; Encodes with uuencode and adds MIME headers.
1722 (defun gnus-uu-post-encode-mime-uuencode (path file-name) 1834 (defun gnus-uu-post-encode-mime-uuencode (path file-name)
1723 (if (gnus-uu-post-encode-uuencode path file-name) 1835 (when (gnus-uu-post-encode-uuencode path file-name)
1724 (progn 1836 (gnus-uu-post-make-mime file-name "x-uue")
1725 (gnus-uu-post-make-mime file-name "x-uue") 1837 t))
1726 t)))
1727 1838
1728 ;; Encodes with base64 and adds MIME headers 1839 ;; Encodes with base64 and adds MIME headers
1729 (defun gnus-uu-post-encode-mime (path file-name) 1840 (defun gnus-uu-post-encode-mime (path file-name)
1730 (if (gnus-uu-post-encode-file "mmencode" path file-name) 1841 (when (gnus-uu-post-encode-file "mmencode" path file-name)
1731 (progn 1842 (gnus-uu-post-make-mime file-name "base64")
1732 (gnus-uu-post-make-mime file-name "base64") 1843 t))
1733 t)))
1734 1844
1735 ;; Adds MIME headers. 1845 ;; Adds MIME headers.
1736 (defun gnus-uu-post-make-mime (file-name encoding) 1846 (defun gnus-uu-post-make-mime (file-name encoding)
1737 (goto-char (point-min)) 1847 (goto-char (point-min))
1738 (insert (format "Content-Type: %s; name=\"%s\"\n" 1848 (insert (format "Content-Type: %s; name=\"%s\"\n"
1739 (gnus-uu-choose-action file-name gnus-uu-ext-to-mime-list) 1849 (gnus-uu-choose-action file-name gnus-uu-ext-to-mime-list)
1740 file-name)) 1850 file-name))
1741 (insert (format "Content-Transfer-Encoding: %s\n\n" encoding)) 1851 (insert (format "Content-Transfer-Encoding: %s\n\n" encoding))
1742 (save-restriction 1852 (save-restriction
1743 (set-buffer gnus-message-buffer) 1853 (set-buffer gnus-message-buffer)
1744 (goto-char (point-min)) 1854 (goto-char (point-min))
1745 (re-search-forward (concat "^" (regexp-quote mail-header-separator) "$")) 1855 (re-search-forward (concat "^" (regexp-quote mail-header-separator) "$"))
1746 (forward-line -1) 1856 (forward-line -1)
1747 (narrow-to-region 1 (point)) 1857 (narrow-to-region 1 (point))
1748 (or (mail-fetch-field "mime-version") 1858 (unless (mail-fetch-field "mime-version")
1749 (progn 1859 (widen)
1750 (widen) 1860 (insert "MIME-Version: 1.0\n"))
1751 (insert "MIME-Version: 1.0\n")))
1752 (widen))) 1861 (widen)))
1753 1862
1754 ;; Encodes a file PATH with COMMAND, leaving the result in the 1863 ;; Encodes a file PATH with COMMAND, leaving the result in the
1755 ;; current buffer. 1864 ;; current buffer.
1756 (defun gnus-uu-post-encode-file (command path file-name) 1865 (defun gnus-uu-post-encode-file (command path file-name)
1776 gnus-inews-article-hook) 1885 gnus-inews-article-hook)
1777 1886
1778 (setq gnus-inews-article-hook (if (listp gnus-inews-article-hook) 1887 (setq gnus-inews-article-hook (if (listp gnus-inews-article-hook)
1779 gnus-inews-article-hook 1888 gnus-inews-article-hook
1780 (list gnus-inews-article-hook))) 1889 (list gnus-inews-article-hook)))
1781 (setq gnus-inews-article-hook 1890 (push
1782 (cons 1891 '(lambda ()
1783 '(lambda () 1892 (save-excursion
1784 (save-excursion 1893 (goto-char (point-min))
1785 (goto-char (point-min)) 1894 (if (re-search-forward "^Message-ID: \\(.*\\)$" nil t)
1786 (if (re-search-forward "^Message-ID: \\(.*\\)$" nil t) 1895 (setq gnus-uu-post-message-id
1787 (setq gnus-uu-post-message-id 1896 (buffer-substring
1788 (buffer-substring 1897 (match-beginning 1) (match-end 1)))
1789 (match-beginning 1) (match-end 1))) 1898 (setq gnus-uu-post-message-id nil))))
1790 (setq gnus-uu-post-message-id nil)))) 1899 gnus-inews-article-hook)
1791 gnus-inews-article-hook))
1792 (gnus-uu-post-encoded file-name t)) 1900 (gnus-uu-post-encoded file-name t))
1793 (gnus-uu-post-encoded file-name nil))) 1901 (gnus-uu-post-encoded file-name nil)))
1794 (setq gnus-uu-post-inserted-file-name nil) 1902 (setq gnus-uu-post-inserted-file-name nil)
1795 (and gnus-uu-winconf-post-news 1903 (when gnus-uu-winconf-post-news
1796 (set-window-configuration gnus-uu-winconf-post-news))) 1904 (set-window-configuration gnus-uu-winconf-post-news)))
1797 1905
1798 ;; Asks for a file to encode, encodes it and inserts the result in 1906 ;; Asks for a file to encode, encodes it and inserts the result in
1799 ;; the current buffer. Returns the file name the user gave. 1907 ;; the current buffer. Returns the file name the user gave.
1800 (defun gnus-uu-post-insert-binary () 1908 (defun gnus-uu-post-insert-binary ()
1801 (let ((uuencode-buffer-name "*uuencode buffer*") 1909 (let ((uuencode-buffer-name "*uuencode buffer*")
1802 file-path uubuf file-name) 1910 file-path uubuf file-name)
1803 1911
1804 (setq file-path (read-file-name 1912 (setq file-path (read-file-name
1805 "What file do you want to encode? ")) 1913 "What file do you want to encode? "))
1806 (if (not (file-exists-p file-path)) 1914 (when (not (file-exists-p file-path))
1807 (error "%s: No such file" file-path)) 1915 (error "%s: No such file" file-path))
1808 1916
1809 (goto-char (point-max)) 1917 (goto-char (point-max))
1810 (insert (format "\n%s\n" gnus-uu-post-binary-separator)) 1918 (insert (format "\n%s\n" gnus-uu-post-binary-separator))
1811 1919
1812 (if (string-match "^~/" file-path) 1920 (when (string-match "^~/" file-path)
1813 (setq file-path (concat "$HOME" (substring file-path 1)))) 1921 (setq file-path (concat "$HOME" (substring file-path 1))))
1814 (if (string-match "/[^/]*$" file-path) 1922 (if (string-match "/[^/]*$" file-path)
1815 (setq file-name (substring file-path (1+ (match-beginning 0)))) 1923 (setq file-name (substring file-path (1+ (match-beginning 0))))
1816 (setq file-name file-path)) 1924 (setq file-name file-path))
1817 1925
1818 (unwind-protect 1926 (unwind-protect
1836 beg-line minlen buf post-buf whole-len beg-binary end-binary) 1944 beg-line minlen buf post-buf whole-len beg-binary end-binary)
1837 1945
1838 (setq post-buf (current-buffer)) 1946 (setq post-buf (current-buffer))
1839 1947
1840 (goto-char (point-min)) 1948 (goto-char (point-min))
1841 (if (not (re-search-forward 1949 (when (not (re-search-forward
1842 (if gnus-uu-post-separate-description 1950 (if gnus-uu-post-separate-description
1843 (concat "^" (regexp-quote gnus-uu-post-binary-separator) 1951 (concat "^" (regexp-quote gnus-uu-post-binary-separator)
1844 "$") 1952 "$")
1845 (concat "^" (regexp-quote mail-header-separator) "$")) nil t)) 1953 (concat "^" (regexp-quote mail-header-separator) "$"))
1846 (error "Internal error: No binary/header separator")) 1954 nil t))
1955 (error "Internal error: No binary/header separator"))
1847 (beginning-of-line) 1956 (beginning-of-line)
1848 (forward-line 1) 1957 (forward-line 1)
1849 (setq beg-binary (point)) 1958 (setq beg-binary (point))
1850 (setq end-binary (point-max)) 1959 (setq end-binary (point-max))
1851 1960
1854 (erase-buffer) 1963 (erase-buffer)
1855 (insert-buffer-substring post-buf beg-binary end-binary) 1964 (insert-buffer-substring post-buf beg-binary end-binary)
1856 (goto-char (point-min)) 1965 (goto-char (point-min))
1857 (setq length (count-lines 1 (point-max))) 1966 (setq length (count-lines 1 (point-max)))
1858 (setq parts (/ length gnus-uu-post-length)) 1967 (setq parts (/ length gnus-uu-post-length))
1859 (if (not (< (% length gnus-uu-post-length) 4)) 1968 (when (not (< (% length gnus-uu-post-length) 4))
1860 (setq parts (1+ parts)))) 1969 (setq parts (1+ parts))))
1861 1970
1862 (if gnus-uu-post-separate-description 1971 (when gnus-uu-post-separate-description
1863 (forward-line -1)) 1972 (forward-line -1))
1864 (kill-region (point) (point-max)) 1973 (kill-region (point) (point-max))
1865 1974
1866 (goto-char (point-min)) 1975 (goto-char (point-min))
1867 (re-search-forward 1976 (re-search-forward
1868 (concat "^" (regexp-quote mail-header-separator) "$") nil t) 1977 (concat "^" (regexp-quote mail-header-separator) "$") nil t)
1870 (setq header (buffer-substring 1 (point))) 1979 (setq header (buffer-substring 1 (point)))
1871 1980
1872 (goto-char (point-min)) 1981 (goto-char (point-min))
1873 (if (not gnus-uu-post-separate-description) 1982 (if (not gnus-uu-post-separate-description)
1874 () 1983 ()
1875 (if (and (not threaded) (re-search-forward "^Subject: " nil t)) 1984 (when (and (not threaded) (re-search-forward "^Subject: " nil t))
1876 (progn 1985 (end-of-line)
1877 (end-of-line) 1986 (insert (format " (0/%d)" parts)))
1878 (insert (format " (0/%d)" parts))))
1879 (message-send)) 1987 (message-send))
1880 1988
1881 (save-excursion 1989 (save-excursion
1882 (setq i 1) 1990 (setq i 1)
1883 (setq beg 1) 1991 (setq beg 1)
1884 (while (not (> i parts)) 1992 (while (not (> i parts))
1885 (set-buffer (get-buffer-create send-buffer-name)) 1993 (set-buffer (get-buffer-create send-buffer-name))
1886 (erase-buffer) 1994 (erase-buffer)
1887 (insert header) 1995 (insert header)
1888 (if (and threaded gnus-uu-post-message-id) 1996 (when (and threaded gnus-uu-post-message-id)
1889 (insert (format "References: %s\n" gnus-uu-post-message-id))) 1997 (insert (format "References: %s\n" gnus-uu-post-message-id)))
1890 (insert separator) 1998 (insert separator)
1891 (setq whole-len 1999 (setq whole-len
1892 (- 62 (length (format top-string "" file-name i parts "")))) 2000 (- 62 (length (format top-string "" file-name i parts ""))))
1893 (if (> 1 (setq minlen (/ whole-len 2))) 2001 (when (> 1 (setq minlen (/ whole-len 2)))
1894 (setq minlen 1)) 2002 (setq minlen 1))
1895 (setq 2003 (setq
1896 beg-line 2004 beg-line
1897 (format top-string 2005 (format top-string
1898 (make-string minlen ?-) 2006 (make-string minlen ?-)
1899 file-name i parts 2007 file-name i parts
1900 (make-string 2008 (make-string
1901 (if (= 0 (% whole-len 2)) (1- minlen) minlen) ?-))) 2009 (if (= 0 (% whole-len 2)) (1- minlen) minlen) ?-)))
1902 2010
1903 (goto-char (point-min)) 2011 (goto-char (point-min))
1905 () 2013 ()
1906 (if (not threaded) 2014 (if (not threaded)
1907 (progn 2015 (progn
1908 (end-of-line) 2016 (end-of-line)
1909 (insert (format " (%d/%d)" i parts))) 2017 (insert (format " (%d/%d)" i parts)))
1910 (if (or (and (= i 2) gnus-uu-post-separate-description) 2018 (when (or (and (= i 2) gnus-uu-post-separate-description)
1911 (and (= i 1) (not gnus-uu-post-separate-description))) 2019 (and (= i 1) (not gnus-uu-post-separate-description)))
1912 (replace-match "Subject: Re: ")))) 2020 (replace-match "Subject: Re: "))))
1913 2021
1914 (goto-char (point-max)) 2022 (goto-char (point-max))
1915 (save-excursion 2023 (save-excursion
1916 (set-buffer uubuf) 2024 (set-buffer uubuf)
1917 (goto-char beg) 2025 (goto-char beg)
1918 (if (= i parts) 2026 (if (= i parts)
1919 (goto-char (point-max)) 2027 (goto-char (point-max))
1920 (forward-line gnus-uu-post-length)) 2028 (forward-line gnus-uu-post-length))
1921 (if (and (= (1+ i) parts) (< (count-lines (point) (point-max)) 4)) 2029 (when (and (= (1+ i) parts) (< (count-lines (point) (point-max)) 4))
1922 (forward-line -4)) 2030 (forward-line -4))
1923 (setq end (point))) 2031 (setq end (point)))
1924 (insert-buffer-substring uubuf beg end) 2032 (insert-buffer-substring uubuf beg end)
1925 (insert beg-line) 2033 (insert beg-line)
1926 (insert "\n") 2034 (insert "\n")
1927 (setq beg end) 2035 (setq beg end)
1929 (goto-char (point-min)) 2037 (goto-char (point-min))
1930 (re-search-forward 2038 (re-search-forward
1931 (concat "^" (regexp-quote mail-header-separator) "$") nil t) 2039 (concat "^" (regexp-quote mail-header-separator) "$") nil t)
1932 (beginning-of-line) 2040 (beginning-of-line)
1933 (forward-line 2) 2041 (forward-line 2)
1934 (if (re-search-forward 2042 (when (re-search-forward
1935 (concat "^" (regexp-quote gnus-uu-post-binary-separator) "$") 2043 (concat "^" (regexp-quote gnus-uu-post-binary-separator) "$")
1936 nil t) 2044 nil t)
1937 (progn 2045 (replace-match "")
1938 (replace-match "") 2046 (forward-line 1))
1939 (forward-line 1)))
1940 (insert beg-line) 2047 (insert beg-line)
1941 (insert "\n") 2048 (insert "\n")
1942 (let (message-sent-message-via) 2049 (let (message-sent-message-via)
1943 (message-send)))) 2050 (message-send))))
1944 2051
1945 (and (setq buf (get-buffer send-buffer-name)) 2052 (when (setq buf (get-buffer send-buffer-name))
1946 (kill-buffer buf)) 2053 (kill-buffer buf))
1947 (and (setq buf (get-buffer encoded-buffer-name)) 2054 (when (setq buf (get-buffer encoded-buffer-name))
1948 (kill-buffer buf)) 2055 (kill-buffer buf))
1949 2056
1950 (if (not gnus-uu-post-separate-description) 2057 (when (not gnus-uu-post-separate-description)
1951 (progn 2058 (set-buffer-modified-p nil)
1952 (set-buffer-modified-p nil) 2059 (when (fboundp 'bury-buffer)
1953 (and (fboundp 'bury-buffer) (bury-buffer)))))) 2060 (bury-buffer)))))
1954 2061
1955 (provide 'gnus-uu) 2062 (provide 'gnus-uu)
1956 2063
1957 ;; gnus-uu.el ends here 2064 ;; gnus-uu.el ends here