aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard M. Stallman1994-04-07 16:39:44 +0000
committerRichard M. Stallman1994-04-07 16:39:44 +0000
commitf919f65ca97361b637aae6a20f7b4d803d6b29cb (patch)
tree6b8779f614724a202e4f4de42524d9f8410d5b75
parent206250958ead8f88ab2c59185e64bc175c451b64 (diff)
downloademacs-f919f65ca97361b637aae6a20f7b4d803d6b29cb.tar.gz
emacs-f919f65ca97361b637aae6a20f7b4d803d6b29cb.zip
Initial revision
-rw-r--r--lisp/gnus-uu.el2120
1 files changed, 2120 insertions, 0 deletions
diff --git a/lisp/gnus-uu.el b/lisp/gnus-uu.el
new file mode 100644
index 00000000000..32664933314
--- /dev/null
+++ b/lisp/gnus-uu.el
@@ -0,0 +1,2120 @@
1;;; gnus-uu.el --- extract, view or save (uu)encoded files from gnus
2;;
3;; Author: Lars Ingebrigtsen <larsi@ifi.uio.no>
4;; Created: 2 Oct 1993
5;; Version: gnus-uu.el v 1.3.6 1994/04/07
6;; Keyword: gnus
7;;
8;; For gnus 4.*.
9;;
10;; All gnus-uu commands start with `C-c C-v'.
11;;
12;; Typing `C-c C-v C-v' (gnus-uu-decode-and-view) in the summary
13;; buffer will try to find all articles in the same series, uudecode
14;; them and view the resulting file(s).
15;;
16;; gnus-uu guesses what articles are in the series according to the
17;; following simple rule: The subjects must be identical, except for
18;; the last two numbers of the line.
19;;
20;; For example: If you choose a subject called "cat.gif (2/3)" gnus-uu
21;; will find all the articles that matches "^cat.gif
22;; ([0-9]+/[0-9]+).*$". Subjects that are nonstandard, like "cat.gif
23;; (2/3) Part 6 of a series", will not be properly recognized by 'C-c
24;; C-v C-v', and you have to mark the articles manually with '#'.
25;;
26;; Typing `C-c C-v v' (gnus-uu-decode-and-save) will do the same as
27;; `C-c C-v C-v', except that it will not display the resulting file, but
28;; save it instead.
29;;
30;; Typing `C-c C-v s' (gnus-uu-shar-and-save) does the same as `C-c
31;; C-v v', and `C-c C-v C-s' (gnus-uu-shar-and-view) does the same as
32;; `C-c C-v C-v', except that they unshar files instead, i. e. run
33;; them through /bin/sh. Most shar files can be viewed and/or saved
34;; with the normal uudecode commands, which is much safer, as no
35;; foreign code is run.
36;;
37;; `#' (gnus-uu-mark-article) marks an article for later
38;; decoding/unsharing/saving/viewing. The files will be decoded in the
39;; sequence they were marked. To decode the files after you've marked
40;; the articles you are interested in, type the corresponding key
41;; strokes as the normal decoding commands, but put a `M-' in the last
42;; keystroke. For instance, to perform a standard uudecode and view,
43;; you would type `C-c C-v C-v'. To perform a marked uudecode and
44;; view, say `C-v C-v M-C-v'. All the other view and save commands are
45;; handled the same way; marked uudecode and save is then `C-c C-v
46;; M-v'.
47;;
48;; `M-#' (gnus-uu-unmark-article) will remove the mark from a
49;; previosly marked article.
50;;
51;; `C-c C-v C-u' (gnus-uu-unmark-all-articles) will remove the mark from
52;; all marked articles.
53;;
54;; `C-c C-v C-r' (gnus-uu-mark-by-regexp) will prompt for a regular
55;; expression and mark (forward) all articles matching that regular
56;; expression.
57;;
58;; There's an additional way to reach the decoding functions to make
59;; future expansions easier: `C-c C-v C-m'
60;; (gnus-uu-multi-decode-and-view) and the corresponding save, marked
61;; view and marked save keystrokes, `C-c C-v m', `C-c C-v M-C-m' and
62;; `C-c C-v M-m' respectively. You will be prompted for decoding
63;; method, like uudecode, shar, binhex or plain save. Note that
64;; methods like binhex and save doesn't have view modes; even if you
65;; issue a view command (`C-c C-v C-m' and "binhex"), gnus-uu will
66;; just save the resulting binhex file.
67;;
68;; `C-c C-v C-b' (gnus-uu-decode-and-show-in-buffer) will decode the
69;; current article and display the results in an emacs buffer. This
70;; might be useful if there's jsut some text in the current article
71;; that has been uuencoded by some perverse poster.
72;;
73;; `C-c C-v a' (gnus-uu-decode-and-save-all-articles) looks at all the
74;; articles in the current newsgroup and tries to uudecode everything
75;; it can find. The user will be prompted for a directory where the
76;; resulting files (if any) will be stored. `C-c C-v M-a' only looks
77;; at unread article. `C-c C-v w' does the same as `C-c C-v a', but
78;; also marks as read all articles it has peeked through, even if they
79;; weren't uuencoded articles. `C-c C-v M-w' is, as you might have
80;; guessed, similar to `C-c C-v M-a'.
81;;
82;; `C-c C-v C-l' (gnus-uu-edit-begin-line) lets you edit the begin
83;; line of the current buffer. Useful to change an incorrect suffix or
84;; an incorrect begin line.
85;;
86;;
87;; When using the view commands, `C-c C-v C-v' for instance, gnus-uu
88;; will (normally, see below) try to view the file according to the
89;; rules given in gnus-uu-default-view-rules and
90;; gnus-uu-user-view-rules. If it recognises the file, it will display
91;; it immediately. If the file is some sort of archive, gnus-uu will
92;; attempt to unpack the archive and see if any of the files in the
93;; archive can be viewed. For instance, if you have a gzipped tar file
94;; "pics.tar.gz" containing the files "pic1.jpg" and "pic2.gif",
95;; gnus-uu will uncompress and detar the main file, and then view the
96;; two pictures. This unpacking process is recursive, so if the
97;; archive contains archives of archives, it'll all be unpacked.
98;;
99;; If the view command doesn't recognise the file type, or can't view
100;; it because you don't have the viewer, or can't view *any* of the
101;; files in the archive, the user will be asked if she wishes to have
102;; the file saved somewhere. Note that if the decoded file is an
103;; archive, and gnus-uu manages to view some of the files in the
104;; archive, it won't tell the user that there were some files that
105;; were unviewable. See "Interactive view" for a different approach.
106;;
107;;
108;; Note that gnus-uu adds a function to `gnus-exit-group-hook' to
109;; clear the list of marked articles and check for any generated files
110;; that might have escaped deletion if the user typed `C-g'.
111;;
112;;
113;; `C-c C-v C-a' (gnus-uu-toggle-asynchronous) toggles the
114;; gnus-uu-asynchronous variable. See below for explanation.
115;;
116;; `C-c C-v C-q' (gnus-uu-toggle-query) toggles the
117;; gnus-uu-ask-before-view variable. See below for explanation.
118;;
119;; `C-c C-v C-p' (gnus-uu-toggle-always-ask) toggles the
120;; gnus-uu-view-and-save variable. See below for explanation.
121;;
122;; `C-c C-v C-k' (gnus-uu-toggle-kill-carriage-return) toggles the
123;; gnus-uu-kill-carriage-return variable. See below for explanation.
124;;
125;; `C-c C-v C-i' (gnus-uu-toggle-interactive-view) toggles interactive
126;; mode. If it is turned on, gnus-uu won't view files immediately but
127;; give you a buffer with the default commands and files and lets you
128;; edit the commands and execute them at leisure.
129;;
130;; `C-c C-v C-t' (gnus-uu-toggle-any-variable) is an interface to the
131;; five toggle commands listed above.
132;;
133;; gnus-uu-toggle-correct-stripped-articles toggles whether to check
134;; and correct uuencoded articles that may have had trailing spaces
135;; stripped by mailers.
136;;
137;;
138;; Customization
139;;
140;; To load this file when starting gnus, put sumething like the
141;; following in your .emacs file:
142;;
143;; (setq gnus-group-mode-hook
144;; '(lambda () (load "gnus-uu")))
145;;
146;; To make gnus-uu use, for instance, "xli" to view JPEGs and GIFs,
147;; put this in your .emacs file:
148;;
149;; (setq gnus-uu-user-view-rules
150;; (list
151;; '("jpg$\\|gif$" "xli")
152;; ))
153;;
154;; This variable is a list where each list item is a list containing
155;; two strings. The first string is a regular expression. If the file
156;; name is matched by this expression, the command given in the
157;; second string is executed on this file. If the command contains
158;; "%s", the file will be inserted there in the command string. Eg.
159;; "giftoppm %s | xv -" will result in the file name being inserted at
160;; the "%s".
161;;
162;; If you don't want to display certain file types, like if you
163;; haven't got sound capabilities, you could put something like
164;;
165;; (setq gnus-uu-user-view-rules
166;; (list
167;; '("au$\\|voc$\\|wav$" nil)
168;; ))
169;;
170;; in your .emacs file.
171;;
172;; There's a similar variable called 'gnus-uu-user-archive-rules'
173;; which gives a list of unarcers to use when looking inside archives
174;; for files to display.
175;;
176;; If you don't want gnus-uu to look inside archives for files to
177;; display, say
178;;
179;; (setq gnus-uu-do-not-unpack-archives t)
180;;
181;;
182;; If you want gnus-uu to ask you if you want to save a file after
183;; viewing, say
184;;
185;; (setq gnus-uu-view-and-save t)
186;;
187;;
188;; If you don't want to wait for the viewing command to finish before
189;; returning to emacs, say
190;;
191;; (setq gnus-uu-asynchronous t)
192;;
193;;
194;; This can be useful if you're viewing long .mod files, for instance,
195;; which often takes several minutes. Note, however, that since
196;; gnus-uu doesn't ask, and if you are viewing an archive with lots of
197;; viewable files, you'll get them all up more or less at once, which
198;; can be confusing, to say the least. To get gnus-uu to ask you
199;; before viewing a file, say
200;;
201;; (setq gnus-uu-ask-before-view t)
202;;
203;; You can set this variable even if you're not using asynchronous
204;; viewing, of course.
205;;
206;; If the articles has been posted by some numbscull with a PC (isn't
207;; that a bit redundant, though?) and there's lots of carriage returns
208;; everywhere, say
209;;
210;; (setq gnus-uu-kill-carriage-return t)
211;;
212;; If you want gnus-uu to ignore the default file rules when viewing,
213;; for instance if there's several file types that you can't view, set
214;; `gnus-uu-ignore-default-view-rules' to `t'. There's a similar
215;; variable to disable the default unarchive rule list,
216;; `gnus-uu-ignore-default-archive-rules'.
217;;
218;; If you want a more interactive approach to file viewing, say
219;;
220;; (setq gnus-uu-use-interactive-view t)
221;;
222;; If this variable is set, whenever you type `C-c C-v C-v' (or any of
223;; the other view commands), gnus-uu will present you with a buffer
224;; with the default actions and file names after decoding. You can
225;; edit the command lines and execute them in a convenient fashion.
226;; The output from the commands will be displayed in a small window at
227;; the bottom of the emacs window. End interactive mode by typing `C-c
228;; C-c' in the view window.
229;;
230;; If you want gnus-uu to unmark articles that you have asked to
231;; decode, but can't be decoded (if, for instance, the articles aren't
232;; uuencoded files or the posting is incomplete), say
233;;
234;; (setq gnus-uu-unmark-articles-not-decoded t)
235;;
236;;
237;; History
238;;
239;; v1.0: First version released Oct 2 1992.
240;;
241;; v1.1: Changed `C-c C-r' to `C-c C-e' and `C-c C-p' to `C-c C-k'.
242;; Changed (setq gnus-exit-group-hook) to (add-hook). Removed
243;; checking for "Re:" for finding parts.
244;;
245;; v2.2: Fixed handling of currupted archives. Changed uudecoding to
246;; an asynchronous process to avoid loading tons of data into emacs
247;; buffers. No longer reads articles emacs already have aboard. Fixed
248;; a firmer support for shar files. Made regexp searches for files
249;; more convenient. Added `C-c C-l' for editing uucode begin
250;; lines. Added multi-system decoder entry point. Added interactive
251;; view mode. Added function for decoding and saving all uuencoded
252;; articles in the current newsgroup.
253;;
254;; v2.3: After suggestions I have changed all the gnus-uu key bindings
255;; to avoid hogging all the user keys (C-c LETTER). Also added
256;; (provide) and fixed some saving stuff. First posted version to
257;; gnu.emacs.sources.
258;;
259;; v2.4: Fixed some more in the save-all category. Automatic fixing of
260;; uucode "begin" lines: names on the form of "dir/file" are
261;; translated into "dir-file". Added a function for fixing stripped
262;; uucode articles. Added binhex save.
263;;
264;;
265;; Keymap overview:
266;;
267;; All commands start with `C-c C-v'. The difference is in the third
268;; keystroke. All view commands are `C-LETTER'. All save commands are
269;; just `LETTER'. All marked commands are the same as the unmarked
270;; commands, except that they have `M-' before in the last keystroke.
271;;
272;; `C-c C-v C-v' gnus-uu-decode-and-view
273;; `C-c C-v v' gnus-uu-decode-and-save
274;; `C-c C-v C-s' gnus-uu-shar-and-view
275;; `C-c C-v s' gnus-uu-shar-and-save
276;; `C-c C-v C-m' gnus-uu-multi-decode-and-view
277;; `C-c C-v m' gnus-uu-multi-decode-and-save
278;;
279;; `C-c C-v C-b' gnus-uu-decode-and-show-in-buffer
280;; `C-c C-v C-l' gnus-uu-edit-begin-line
281;; `C-c C-v M-a' gnus-uu-decode-and-save-all-unread-articles
282;; `C-c C-v a' gnus-uu-decode-and-save-all-articles
283;; `C-c C-v M-w' gnus-uu-decode-and-save-all-unread-articles-and-mark
284;; `C-c C-v w' gnus-uu-decode-and-save-all-articles-and-mark
285;;
286;; `#' gnus-uu-mark-article
287;; `M-#' gnus-uu-unmark-article
288;; `C-c C-v C-u' gnus-uu-unmark-all-articles
289;; `C-c C-v C-r' gnus-uu-mark-by-regexp
290;; `C-c C-v M-C-v' gnus-uu-marked-decode-and-view
291;; `C-c C-v M-v' gnus-uu-marked-decode-and-save
292;; `C-c C-v M-C-s' gnus-uu-marked-shar-and-view
293;; `C-c C-v M-s' gnus-uu-marked-shar-and-save
294;; `C-c C-v M-C-m' gnus-uu-marked-multi-decode-and-view
295;; `C-c C-v M-m' gnus-uu-marked-multi-decode-and-save
296;;
297;; `C-c C-v C-a' gnus-uu-toggle-asynchronous
298;; `C-c C-v C-q' gnus-uu-toggle-query
299;; `C-c C-v C-p' gnus-uu-toggle-always-ask
300;; `C-c C-v C-k' gnus-uu-toggle-kill-carriage-return
301;; `C-c C-v C-i' gnus-uu-toggle-interactive-view
302;; `C-c C-v C-t' gnus-uu-toggle-any-variable
303
304(require 'gnus)
305
306;; Binding of keys to the gnus-uu functions.
307
308(defvar gnus-uu-ctl-map nil)
309(define-prefix-command 'gnus-uu-ctl-map)
310(define-key gnus-summary-mode-map "\C-c\C-v" gnus-uu-ctl-map)
311
312(define-key gnus-uu-ctl-map "\C-v" 'gnus-uu-decode-and-view)
313(define-key gnus-uu-ctl-map "v" 'gnus-uu-decode-and-save)
314(define-key gnus-uu-ctl-map "\C-s" 'gnus-uu-shar-and-view)
315(define-key gnus-uu-ctl-map "s" 'gnus-uu-shar-and-save)
316(define-key gnus-uu-ctl-map "\C-m" 'gnus-uu-multi-decode-and-view)
317(define-key gnus-uu-ctl-map "m" 'gnus-uu-multi-decode-and-save)
318
319(define-key gnus-uu-ctl-map "\C-b" 'gnus-uu-decode-and-show-in-buffer)
320
321(define-key gnus-summary-mode-map "#" 'gnus-uu-mark-article)
322(define-key gnus-summary-mode-map "\M-#" 'gnus-uu-unmark-article)
323(define-key gnus-uu-ctl-map "\C-u" 'gnus-uu-unmark-all-articles)
324(define-key gnus-uu-ctl-map "\C-r" 'gnus-uu-mark-by-regexp)
325
326(define-key gnus-uu-ctl-map "\M-\C-v" 'gnus-uu-marked-decode-and-view)
327(define-key gnus-uu-ctl-map "\M-v" 'gnus-uu-marked-decode-and-save)
328(define-key gnus-uu-ctl-map "\M-\C-s" 'gnus-uu-marked-shar-and-view)
329(define-key gnus-uu-ctl-map "\M-s" 'gnus-uu-marked-shar-and-save)
330(define-key gnus-uu-ctl-map "\M-\C-m" 'gnus-uu-marked-multi-decode-and-view)
331(define-key gnus-uu-ctl-map "\M-m" 'gnus-uu-marked-multi-decode-and-save)
332
333(define-key gnus-uu-ctl-map "\C-a" 'gnus-uu-toggle-asynchronous)
334(define-key gnus-uu-ctl-map "\C-q" 'gnus-uu-toggle-query)
335(define-key gnus-uu-ctl-map "\C-p" 'gnus-uu-toggle-always-ask)
336(define-key gnus-uu-ctl-map "\C-k" 'gnus-uu-toggle-kill-carriage-return)
337(define-key gnus-uu-ctl-map "\C-i" 'gnus-uu-toggle-interactive-view)
338(define-key gnus-uu-ctl-map "\C-t" 'gnus-uu-toggle-any-variable)
339
340(define-key gnus-uu-ctl-map "\C-l" 'gnus-uu-edit-begin-line)
341
342(define-key gnus-uu-ctl-map "\M-a" 'gnus-uu-decode-and-save-all-unread-articles)
343(define-key gnus-uu-ctl-map "a" 'gnus-uu-decode-and-save-all-articles)
344(define-key gnus-uu-ctl-map "\M-w" 'gnus-uu-decode-and-save-all-unread-articles-and-mark)
345(define-key gnus-uu-ctl-map "w" 'gnus-uu-decode-and-save-all-articles-and-mark)
346
347;(load "rnewspost")
348;(define-key news-reply-mode-map "\C-c\C-v" 'gnus-uu-uuencode-and-post)
349
350;; Default viewing action rules
351
352(defconst gnus-uu-default-view-rules
353 (list
354 '("\\.\\(jpe?g\\|gif\\|tiff?\\|p[pgb]m\\|xwd\\|xbm\\|pcx\\)$" "xv")
355 '("\\.tga$" "tgatoppm %s | xv -")
356 '("\\.te?xt$\\|\\.doc$\\|read.*me" "xterm -e less")
357 '("\\.fli$" "xflick")
358 '("\\.\\(wav\\|aiff\\|hcom\\|u[blw]\\|s[bfw]\\|voc\\|smp\\)$"
359 "sox -v .5 %s -t .au -u - > /dev/audio")
360 '("\\.au$" "cat %s > /dev/audio")
361 '("\\.mod$" "str32")
362 '("\\.ps$" "ghostview")
363 '("\\.dvi$" "xdvi")
364 '("\\.1$" "xterm -e man -l")
365 '("\\.html$" "xmosaic")
366 '("\\.mpe?g$" "mpeg_play")
367 '("\\.\\(tar\\|arj\\|zip\\|zoo\\|arc\\|gz\\|Z\\|lzh\\|ar\\)$"
368 "gnus-uu-archive"))
369
370
371 "This constant is a list that gives the default actions to be taken
372when the user asks to view a file. To change the behaviour, you can
373either edit this constant or set 'gnus-uu-user-view-rules' to
374something useful. To add a default \"end\" rule, edit the
375'gnus-uu-user-view-rules-end' variable.
376
377For example:
378
379To make gnus-uu use 'xli' to display JPEG and GIF files, put the
380following in your .emacs file
381
382 (setq gnus-uu-user-view-rules (list '(\"jpg$\\\\|gif$\" \"xli\")))
383
384Both these variables are lists of lists of strings, where the first
385string is a regular expression. If the file name matches this regular
386expression, the command in the second string is fed the file.
387
388If the command string contains \"%s\", the file name will be inserted
389at that point in the command string. If there's no \"%s\" in the
390command string, the file name will be appended to the command before
391executing. ")
392
393(defvar gnus-uu-user-view-rules nil
394 "User variable. See explanation of the 'gnus-uu-default-view-rules' for
395details.")
396
397(defvar gnus-uu-user-view-rules-end nil
398 "The user may use this variable to provide default viewing rules.")
399
400(defvar gnus-uu-user-interactive-view-rules nil
401 "If this variable is set and interactive mode is to be used, this
402variable will be used instead of gnus-uu-user-view-rules.")
403
404(defvar gnus-uu-user-interactive-view-rules-end nil
405 "If this variable is set and interactive mode is to be used, this
406variable will be used instead of gnus-uu-user-view-rules-end.")
407
408(defconst gnus-uu-default-interactive-view-rules-begin
409 (list
410 '("\\.te?xt$\\|\\.doc$\\|read.*me\\|\\.c?$\\|\\.h$\\|\\.bat$\\|\\.asm$\\|makefile" "cat %s | sed s/ //g")
411 '("\\.pas$" "cat %s | sed s/ //g")
412 ))
413
414
415;; Default unpacking commands
416
417(defconst gnus-uu-default-archive-rules
418 (list '("\\.tar$" "tar xf")
419 '("\\.zip$" "unzip")
420 '("\\.ar$" "ar x")
421 '("\\.arj$" "unarj x")
422 '("\\.zoo$" "zoo -e")
423 '("\\.lzh$" "lha x")
424 '("\\.Z$" "uncompress")
425 '("\\.gz$" "gunzip")
426 '("\\.arc$" "arc -x"))
427 "*")
428(defvar gnus-uu-user-archive-rules nil)
429
430
431;; Various variables users may set
432
433(defvar gnus-uu-tmp-dir "/tmp/"
434 "Variable saying where gnus-uu is to do its work. Default is \"/tmp/\".")
435
436(defvar gnus-uu-do-not-unpack-archives nil
437 "Set this variable if you don't want gnus-uu to look inside
438archives for files to display. Default is `nil'.")
439
440(defvar gnus-uu-do-not-unpack-archives nil
441 "Set this variable if you don't want gnus-uu to look inside
442archives for files to display. Default is `nil'.")
443
444(defvar gnus-uu-view-and-save nil
445 "Set this variable if you want to be asked if you want to save the
446file after viewing. If this variable is nil, which is the default,
447gnus-uu won't offer to save a file if viewing is successful. Default
448is `nil'.")
449
450(defvar gnus-uu-asynchronous nil
451 "Set this variable to `t' if you don't want gnus-uu to wait until
452the viewing command has ended before returning control to emacs.
453Default is `nil'.")
454
455(defvar gnus-uu-ask-before-view nil
456 "Set this variable to `t' if you want gnus-uu to ask you before
457viewing every file. Useful when `gnus-uu-asynchronous' is set. Default
458is `nil'.")
459
460(defvar gnus-uu-ignore-default-view-rules nil
461 "Set this variable if you want gnus-uu to ignore the default viewing
462rules and just use the rules given in gnus-uu-user-view-rules. Default
463is `nil'.")
464
465(defvar gnus-uu-ignore-default-archive-rules nil
466 "Set this variable if you want gnus-uu to ignore the default archive
467unpacking commands and just use the rules given in
468gnus-uu-user-archive-rules. Default is `nil'.")
469
470(defvar gnus-uu-kill-carriage-return t
471 "Set this variable if you want to remove all carriage returns from
472the mail articles. Default is `t'.")
473
474(defvar gnus-uu-unmark-articles-not-decoded nil
475 "If this variable is set, artciles that are unsuccessfully decoded
476are marked as unread. Default is `nil'.")
477
478(defvar gnus-uu-output-window-height 20
479 "This variable says how hight the output buffer window is to be when
480using interactive view mode. Change it at your convenience. Default is 20.")
481
482(defvar gnus-uu-correct-stripped-uucode nil
483 "If this variable is set, gnus-uu will try to correct uuencoded files that
484have had trailing spaces stripped by nosy mail saoftware. Default is `nil'.")
485
486(defvar gnus-uu-use-interactive-view nil
487 "If this variable is set, gnus-uu will create a special buffer where
488the user may choose interactively which files to view and how. Default
489is `nil'.")
490
491
492;; Internal variables
493
494(defconst gnus-uu-begin-string "^begin[ \t]+[0-7][0-7][0-7][ \t]+\\(.*\\)$"
495 "*")
496(defconst gnus-uu-end-string "^end[ \t]*$")
497(defconst gnus-uu-body-line
498"^M.............................................................?$" "*")
499(defconst gnus-uu-shar-begin-string "^#! */bin/sh" "*")
500
501(defvar gnus-uu-shar-file-name nil "*")
502(defconst gnus-uu-shar-name-marker "begin [0-7][0-7][0-7][ \t]+\\(\\(\\w\\|\\.\\)*\\b\\)" "*")
503(defvar gnus-uu-shar-directory nil)
504
505(defvar gnus-uu-file-name nil)
506(defconst gnus-uu-uudecode-process nil)
507
508(defvar gnus-uu-interactive-file-list nil)
509(defvar gnus-uu-marked-article-list nil)
510(defvar gnus-uu-generated-file-list nil)
511
512(defconst gnus-uu-interactive-buffer-name "*gnus-uu interactive*")
513(defconst gnus-uu-output-buffer-name "*Gnus UU Output*")
514(defconst gnus-uu-result-buffer "*Gnus UU Result Buffer*")
515
516
517;; Interactive functions
518
519;; UUdecode and view
520
521(defun gnus-uu-decode-and-view ()
522 "UUdecodes and 'views' (if possible) the resulting file.
523'Viewing' can be any action at all, as defined in the
524'gnus-uu-file-action-list' variable. Running 'xv' on gifs and
525'play' on au files are popular actions. If the file can't be viewed,
526the user is asked if she would like to save the file instead."
527 (interactive)
528 (gnus-uu-decode-and-view-or-save t nil))
529
530(defun gnus-uu-decode-and-save ()
531 "uudecodes and saves the resulting file."
532 (interactive)
533 (gnus-uu-decode-and-view-or-save nil nil))
534
535(defun gnus-uu-marked-decode-and-view ()
536 "The marked equivalent to gnus-uu-decode-and-view."
537 (interactive)
538 (gnus-uu-decode-and-view-or-save t t))
539
540(defun gnus-uu-marked-decode-and-save ()
541 "The marked equivalent to gnus-uu-decode-and-save."
542 (interactive)
543 (gnus-uu-decode-and-view-or-save nil t))
544
545
546;; Unshar and view
547
548(defun gnus-uu-shar-and-view ()
549 "Does the same as gnus-uu-decode-and-view for shar files."
550 (interactive)
551 (gnus-uu-unshar-and-view-or-save t nil))
552
553(defun gnus-uu-shar-and-save ()
554 "Does the same as gnus-uu-decode-and-save for shar files."
555 (interactive)
556 (gnus-uu-unshar-and-view-or-save nil nil))
557
558(defun gnus-uu-marked-shar-and-view ()
559 "The marked equivalent to gnus-uu-shar-and-view."
560 (interactive)
561 (gnus-uu-unshar-and-view-or-save t t))
562
563(defun gnus-uu-marked-shar-and-save ()
564 "The marked equivalent to gnus-uu-shar-and-save."
565 (interactive)
566 (gnus-uu-unshar-and-view-or-save nil t))
567
568
569;; Decode and show in buffer
570
571(defun gnus-uu-decode-and-show-in-buffer ()
572 "uudecodes the current article and displays the result in a buffer."
573 (interactive)
574 (let ((uu-buffer (get-buffer-create gnus-uu-output-buffer-name))
575 list-of-articles file-name)
576 (save-excursion
577 (and
578 (setq list-of-articles (list gnus-current-article))
579 (gnus-uu-grab-articles list-of-articles 'gnus-uu-uustrip-article-as)
580 (setq file-name (gnus-uu-decode gnus-uu-tmp-dir))
581 (progn
582 (save-excursion
583 (set-buffer uu-buffer)
584 (erase-buffer)
585 (insert-file-contents file-name))
586 (set-window-buffer (get-buffer-window gnus-article-buffer)
587 uu-buffer)
588 (message (format "Showing file %s in buffer" file-name))
589 (delete-file file-name))))))
590
591
592;; Toggle commands
593
594(defun gnus-uu-toggle-asynchronous ()
595 "This function toggles asynchronous viewing."
596 (interactive)
597 (if (setq gnus-uu-asynchronous (not gnus-uu-asynchronous))
598 (message "gnus-uu will now view files asynchronously")
599 (message "gnus-uu will now view files synchronously")))
600
601(defun gnus-uu-toggle-query ()
602 "This function toggles whether to ask before viewing or not."
603 (interactive)
604 (if (setq gnus-uu-ask-before-view (not gnus-uu-ask-before-view))
605 (message "gnus-uu will now ask before viewing")
606 (message "gnus-uu will now view without asking first")))
607
608(defun gnus-uu-toggle-always-ask ()
609 "This function toggles whether to ask saving a file even after successful
610viewing."
611 (interactive)
612 (if (setq gnus-uu-view-and-save (not gnus-uu-view-and-save))
613 (message "gnus-uu will now ask to save the file after viewing")
614 (message "gnus-uu will now not ask to save after successful viewing")))
615
616(defun gnus-uu-toggle-interactive-view ()
617 "This function toggles whether to use interactive view."
618 (interactive)
619 (if (setq gnus-uu-use-interactive-view (not gnus-uu-use-interactive-view))
620 (message "gnus-uu will now use interactive view")
621 (message "gnus-uu will now use non-interactive view")))
622
623(defun gnus-uu-toggle-unmark-undecoded ()
624 "This function toggles whether to unmark articles not decoded."
625 (interactive)
626 (if (setq gnus-uu-unmark-articles-not-decoded
627 (not gnus-uu-unmark-articles-not-decoded))
628 (message "gnus-uu will now unmark articles not decoded")
629 (message "gnus-uu will now not unmark articles not decoded")))
630
631(defun gnus-uu-toggle-kill-carriage-return ()
632 "This function toggles the stripping of carriage returns from the articles."
633 (interactive)
634 (if (setq gnus-uu-kill-carriage-return (not gnus-uu-kill-carriage-return))
635 (message "gnus-uu will now strip carriage returns")
636 (message "gnus-uu won't strip carriage returns")))
637
638(defun gnus-uu-toggle-correct-stripped-uucode ()
639 "This function toggles whether to correct stripped uucode."
640 (interactive)
641 (if (setq gnus-uu-correct-stripped-uucode
642 (not gnus-uu-correct-stripped-uucode))
643 (message "gnus-uu will now correct stripped uucode")
644 (message "gnus-uu won't check and correct stripped uucode")))
645
646(defun gnus-uu-toggle-any-variable ()
647 "This function ask what variable the user wants to toggle."
648 (interactive)
649 (let (rep)
650 (message "(a)sync, (q)uery, (p)ask, (k)ill CR, (i)nteractive, (u)nmark, (c)orrect")
651 (setq rep (read-char))
652 (if (= rep ?a)
653 (gnus-uu-toggle-asynchronous))
654 (if (= rep ?q)
655 (gnus-uu-toggle-query))
656 (if (= rep ?p)
657 (gnus-uu-toggle-always-ask))
658 (if (= rep ?k)
659 (gnus-uu-toggle-kill-carriage-return))
660 (if (= rep ?u)
661 (gnus-uu-toggle-unmark-undecoded))
662 (if (= rep ?c)
663 (gnus-uu-toggle-correct-stripped-uucode))
664 (if (= rep ?i)
665 (gnus-uu-toggle-interactive-view))))
666
667
668;; Edit line
669
670(defun gnus-uu-edit-begin-line ()
671 "Edit the begin line of the current article."
672 (interactive)
673 (let ((buffer-read-only nil)
674 begin b)
675 (save-excursion
676 (set-buffer gnus-article-buffer)
677 (goto-line 1)
678 (if (not (re-search-forward "begin " nil t))
679 (progn (message "No begin line in the current article") (sit-for 2))
680 (beginning-of-line)
681 (setq b (point))
682 (end-of-line)
683 (setq begin (buffer-substring b (point)))
684 (setq begin (read-string "" begin))
685 (setq buffer-read-only nil)
686 (delete-region b (point))
687 (insert-string begin)))))
688
689;; Multi functions
690
691(defun gnus-uu-multi-decode-and-view ()
692 "This function lets the user decide what method to use for decoding.
693Other than that, it's equivalent to the other decode-and-view functions."
694 (interactive)
695 (gnus-uu-multi-decode-and-view-or-save t nil))
696
697(defun gnus-uu-multi-decode-and-save ()
698 "This function lets the user decide what method to use for decoding.
699Other than that, it's equivalent to the other decode-and-save functions."
700 (interactive)
701 (gnus-uu-multi-decode-and-view-or-save nil nil))
702
703(defun gnus-uu-marked-multi-decode-and-view ()
704 "This function lets the user decide what method to use for decoding.
705Other than that, it's equivalent to the other marked decode-and-view
706functions."
707 (interactive)
708 (gnus-uu-multi-decode-and-view-or-save t t))
709
710(defun gnus-uu-marked-multi-decode-and-save ()
711 "This function lets the user decide what method to use for decoding.
712Other than that, it's equivalent to the other marked decode-and-save
713functions."
714 (interactive)
715 (gnus-uu-multi-decode-and-view-or-save t t))
716
717(defun gnus-uu-multi-decode-and-view-or-save (view marked)
718 (let (decode-type)
719 (message "(u)udecode, (s)har, s(a)ve, (b)inhex: ")
720 (setq decode-type (read-char))
721 (if (= decode-type ? ) (setq decode-type ?u))
722 (if (= decode-type ?u)
723 (gnus-uu-decode-and-view-or-save view marked)
724 (if (= decode-type ?s)
725 (gnus-uu-unshar-and-view-or-save view marked)
726 (if (= decode-type ?b)
727 (gnus-uu-binhex-and-save view marked)
728 (if (= decode-type ?a)
729 (gnus-uu-save-articles view marked)
730 (message (format "Unknown decode method '%c'." decode-type))
731 (sit-for 2)))))))
732
733
734;; uuencode and post
735
736(defun gnus-uu-news-inews ()
737 "Send a news message using inews."
738 (interactive)
739 (let* (newsgroups subject
740 (case-fold-search nil))
741 (save-excursion
742 (save-restriction
743 (goto-char (point-min))
744 (search-forward (concat "\n" mail-header-separator "\n"))
745 (narrow-to-region (point-min) (point))
746 (setq newsgroups (mail-fetch-field "newsgroups")
747 subject (mail-fetch-field "subject")))
748 (widen)
749 (goto-char (point-min))
750; (run-hooks 'news-inews-hook)
751 (goto-char (point-min))
752 (search-forward (concat "\n" mail-header-separator "\n"))
753 (replace-match "\n\n")
754 (goto-char (point-max))
755 ;; require a newline at the end for inews to append .signature to
756 (or (= (preceding-char) ?\n)
757 (insert ?\n))
758 (message "Posting to USENET...")
759 (call-process-region (point-min) (point-max)
760 news-inews-program nil 0 nil
761 "-h") ; take all header lines!
762 ;@@ setting of subject and newsgroups still needed?
763 ;"-t" subject
764 ;"-n" newsgroups
765 (message "Posting to USENET... done")
766 (goto-char (point-min)) ;restore internal header separator
767 (search-forward "\n\n")
768 (replace-match (concat "\n" mail-header-separator "\n")))))
769
770(autoload 'news-inews "rnewspost")
771
772(defun gnus-uu-post-buffer (&optional first)
773 (append-to-file 1 (point-max) "/tmp/gnusuutull")
774; (if first
775; (news-inews)
776; (gnus-uu-news-inews))
777 (message "posted"))
778
779(defconst gnus-uu-uuencode-post-length 20)
780
781(defun gnus-uu-uuencode-and-post ()
782 (interactive)
783 (let (file uubuf sendbuf short-file length parts header i end beg
784 beg-line minlen)
785 (setq file (read-file-name
786 "What file do you want to uuencode and post? " "~/Unrd.jpg"))
787 (if (not (file-exists-p file))
788 (message "%s: No such file" file)
789 (save-excursion
790 (setq uubuf (get-buffer-create "*uuencode buffer*"))
791 (setq sendbuf (get-buffer-create "*uuencode send buffer*"))
792 (set-buffer uubuf)
793 (erase-buffer)
794 (if (string-match "^~/" file)
795 (setq file (concat "$HOME" (substring file 1))))
796 (if (string-match "/[^/]*$" file)
797 (setq short-file (substring file (1+ (match-beginning 0))))
798 (setq short-file file))
799 (call-process "sh" nil uubuf nil "-c"
800 (format "uuencode %s %s" file short-file))
801 (goto-char 1)
802 (forward-line 1)
803 (while (re-search-forward " " nil t)
804 (replace-match "`"))
805 (setq length (count-lines 1 (point-max)))
806 (setq parts (/ length gnus-uu-uuencode-post-length))
807 (if (not (< (% length gnus-uu-uuencode-post-length) 4))
808 (setq parts (1+ parts)))
809 (message "Det er %d parts" parts))
810 (goto-char 1)
811 (search-forward mail-header-separator nil t)
812 (beginning-of-line)
813 (forward-line 1)
814 (setq header (buffer-substring 1 (point)))
815 (goto-char 1)
816 (if (re-search-forward "^Subject: " nil t)
817 (progn
818 (end-of-line)
819 (insert (format " (0/%d)" parts))))
820 (gnus-uu-post-buffer t)
821 (save-excursion
822 (set-buffer sendbuf)
823 (setq i 1)
824 (setq beg 1)
825 (while (not (> i parts))
826 (set-buffer sendbuf)
827 (erase-buffer)
828 (insert header)
829 (insert "\n")
830 (setq minlen (/ (- 62 (length (format " (%d/%d) " i parts))) 2))
831 (setq beg-line (format "[ cut here %s (%d/%d) %s gnus-uu ]\n"
832 (make-string (- minlen 11) ?-) i parts
833 (make-string (- minlen 10) ?-)))
834 (insert beg-line)
835 (goto-char 1)
836 (if (re-search-forward "^Subject: " nil t)
837 (progn
838 (end-of-line)
839 (insert (format " (%d/%d)" i parts))))
840 (goto-char (point-max))
841 (save-excursion
842 (set-buffer uubuf)
843 (goto-char beg)
844 (if (= i parts)
845 (goto-char (point-max))
846 (forward-line gnus-uu-uuencode-post-length))
847 (setq end (point)))
848 (insert-buffer-substring uubuf beg end)
849 (insert beg-line)
850 (setq beg end)
851 (setq i (1+ i))
852 (gnus-uu-post-buffer)))
853 )))
854
855
856
857;; Decode and all files
858
859(defconst gnus-uu-rest-of-articles nil)
860(defconst gnus-uu-do-sloppy-uudecode nil)
861(defvar gnus-uu-current-save-dir nil "*")
862
863(defun gnus-uu-decode-and-save-all-unread-articles ()
864 "This function reads all unread articles in the current group and
865sees whether it can uudecode the articles. The user will be prompted
866for an directory to put the resulting (if any) files."
867 (interactive)
868 (gnus-uu-decode-and-save-articles t t))
869
870(defun gnus-uu-decode-and-save-all-articles ()
871 "Does the same as gnus-uu-decode-and-save-all-unread-articles, except
872that it grabs all articles visible, unread or not."
873 (interactive)
874 (gnus-uu-decode-and-save-articles nil t))
875
876(defun gnus-uu-decode-and-save-all-unread-articles-and-mark ()
877 "Does the same as gnus-uu-decode-and-save-all-unread-articles, except that
878it marks everything as read, even if it couldn't decode the articles."
879 (interactive)
880 (gnus-uu-decode-and-save-articles t nil))
881
882(defun gnus-uu-decode-and-save-all-articles-and-mark ()
883 "Does the same as gnus-uu-decode-and-save-all-articles, except that
884it marks everything as read, even if it couldn't decode the articles."
885 (interactive)
886 (gnus-uu-decode-and-save-articles nil nil))
887
888(defun gnus-uu-decode-and-save-articles (&optional unread unmark)
889 (let ((gnus-uu-unmark-articles-not-decoded unmark)
890 (filest "")
891 where dir did unmark saved-list)
892 (setq gnus-uu-do-sloppy-uudecode t)
893 (setq dir (gnus-uu-read-directory "Where do you want the files? "))
894 (message "Grabbing...")
895 (setq gnus-uu-rest-of-articles
896 (gnus-uu-get-list-of-articles "^." nil unread))
897 (setq gnus-uu-file-name nil)
898 (while (and gnus-uu-rest-of-articles
899 (gnus-uu-grab-articles gnus-uu-rest-of-articles
900 'gnus-uu-uustrip-article-as))
901 (if gnus-uu-file-name
902 (progn
903 (setq saved-list (cons gnus-uu-file-name saved-list))
904 (rename-file (concat gnus-uu-tmp-dir gnus-uu-file-name)
905 (concat dir gnus-uu-file-name) t)
906 (setq did t)
907 (setq gnus-uu-file-name nil))))
908 (if (not did)
909 ()
910 (while saved-list
911 (setq filest (concat filest " " (car saved-list)))
912 (setq saved-list (cdr saved-list)))
913 (message "Saved%s" filest)))
914 (setq gnus-uu-do-sloppy-uudecode nil))
915
916
917;; Work functions
918
919(defun gnus-uu-decode-and-view-or-save (view marked)
920 (gnus-uu-initialize)
921 (let (file decoded)
922 (save-excursion
923 (if (gnus-uu-decode-and-strip nil marked)
924 (progn
925 (setq decoded t)
926 (setq file (concat gnus-uu-tmp-dir gnus-uu-file-name))
927 (if view
928 (gnus-uu-view-file file)
929 (gnus-uu-save-file file)))))
930
931 (gnus-uu-summary-next-subject)
932
933 (if (and gnus-uu-use-interactive-view view decoded)
934 (gnus-uu-do-interactive))
935
936 (if (or (not gnus-uu-use-interactive-view) (not decoded))
937 (gnus-uu-clean-up))))
938
939
940(defun gnus-uu-unshar-and-view-or-save (view marked)
941 "Unshars and views/saves marked/unmarked articles."
942 (gnus-uu-initialize)
943 (let (tar-file files decoded)
944 (save-excursion
945 (setq gnus-uu-shar-directory
946 (make-temp-name (concat gnus-uu-tmp-dir "gnusuush")))
947 (make-directory gnus-uu-shar-directory)
948 (gnus-uu-add-file gnus-uu-shar-directory)
949 (if (gnus-uu-decode-and-strip t marked)
950 (progn
951 (setq decoded t)
952 (setq files (directory-files gnus-uu-shar-directory t))
953 (setq gnus-uu-generated-file-list
954 (append files gnus-uu-generated-file-list))
955 (if (> (length files) 3)
956 (progn
957 (setq tar-file
958 (concat
959 (make-temp-name (concat gnus-uu-tmp-dir "gnusuuar"))
960 ".tar"))
961 (gnus-uu-add-file tar-file)
962 (call-process "sh" nil
963 (get-buffer-create gnus-uu-output-buffer-name)
964 nil "-c"
965 (format "cd %s ; tar cf %s * ; cd .. ; rm -r %s"
966 gnus-uu-shar-directory
967 tar-file
968 gnus-uu-shar-directory))
969 (if view
970 (gnus-uu-view-file tar-file)
971 (gnus-uu-save-file tar-file)))
972 (if view
973 (gnus-uu-view-file (elt files 2))
974 (gnus-uu-save-file (elt files 2)))))))
975
976 (gnus-uu-summary-next-subject)
977
978 (if (and gnus-uu-use-interactive-view view decoded)
979 (gnus-uu-do-interactive))
980
981 (if (or (not gnus-uu-use-interactive-view) (not decoded))
982 (gnus-uu-clean-up))))
983
984
985(defconst gnus-uu-saved-article-name nil)
986(defun gnus-uu-save-articles (view marked)
987 (let (list-of-articles)
988 (save-excursion
989 (if (not marked)
990 (setq list-of-articles (gnus-uu-get-list-of-articles))
991 (setq list-of-articles (reverse gnus-uu-marked-article-list))
992 (setq gnus-uu-marked-article-list nil))
993 (if (not list-of-articles)
994 (progn
995 (message "No list of articles")
996 (sit-for 2))
997 (setq gnus-uu-saved-article-name
998 (concat gnus-uu-tmp-dir
999 (read-file-name "Enter file name: " gnus-newsgroup-name
1000 gnus-newsgroup-name)))
1001 (gnus-uu-add-file gnus-uu-saved-article-name)
1002 (if (gnus-uu-grab-articles list-of-articles 'gnus-uu-save-article)
1003 (gnus-uu-save-file gnus-uu-saved-article-name))
1004 ))))
1005
1006
1007(defun gnus-uu-save-article (buffer in-state)
1008 (save-excursion
1009 (set-buffer buffer)
1010 (call-process-region
1011 1 (point-max) "sh" nil (get-buffer-create gnus-uu-output-buffer-name)
1012 nil "-c" (concat "cat >> " gnus-uu-saved-article-name)))
1013 'ok)
1014
1015
1016;; Binhex
1017(defconst gnus-uu-binhex-body-line
1018 "^................................................................$")
1019(defconst gnus-uu-binhex-begin-line
1020 "^:...............................................................$")
1021(defconst gnus-uu-binhex-end-line
1022 ":$")
1023(defvar gnus-uu-binhex-article-name nil)
1024
1025
1026(defun gnus-uu-binhex-and-save (view marked)
1027 (let (list-of-articles)
1028 (save-excursion
1029 (if (not marked)
1030 (setq list-of-articles (gnus-uu-get-list-of-articles))
1031 (setq list-of-articles (reverse gnus-uu-marked-article-list))
1032 (setq gnus-uu-marked-article-list nil))
1033' (setq gn-dummy-l list-of-articles)
1034 (if (not list-of-articles)
1035 (progn
1036 (message "No list of articles")
1037 (sit-for 2))
1038 (setq gnus-uu-binhex-article-name
1039 (concat gnus-uu-tmp-dir
1040 (read-file-name "Enter binhex file name: "
1041 gnus-newsgroup-name
1042 gnus-newsgroup-name)))
1043 (gnus-uu-add-file gnus-uu-binhex-article-name)
1044 (if (gnus-uu-grab-articles list-of-articles 'gnus-uu-binhex-article)
1045 (gnus-uu-save-file gnus-uu-binhex-article-name))
1046 ))))
1047
1048
1049(defun gnus-uu-binhex-article (buffer in-state)
1050 (let ((state 'ok)
1051 start-char)
1052 (save-excursion
1053 (set-buffer buffer)
1054 (goto-char 1)
1055 (if (not (re-search-forward (concat gnus-uu-binhex-begin-line "\\|"
1056 gnus-uu-binhex-body-line) nil t))
1057 (setq state 'wrong-type)
1058 (beginning-of-line)
1059 (setq start-char (point))
1060 (if (looking-at gnus-uu-binhex-begin-line)
1061 (setq state 'begin)
1062 (setq state 'middle))
1063 (goto-char (point-max))
1064 (re-search-backward (concat gnus-uu-binhex-body-line "\\|"
1065 gnus-uu-binhex-end-line) nil t)
1066 (if (looking-at gnus-uu-binhex-end-line)
1067 (if (eq state 'begin)
1068 (setq state 'begin-and-end)
1069 (setq state 'end)))
1070 (beginning-of-line)
1071 (forward-line 1)
1072 (append-to-file start-char (point) gnus-uu-binhex-article-name)))
1073 state))
1074
1075
1076;; Internal view commands
1077
1078(defun gnus-uu-view-file (file-name &optional dont-ask)
1079 "This function takes two parameters. The first is name of the file to be
1080viewed. gnus-uu-view-file will look for an action associated with the file
1081type of the file. If it finds an appropriate action, the file will be
1082attempted displayed.
1083
1084The second parameter specifies if the user is to be asked whether to
1085save the file if viewing is unsuccessful. `t' means 'do not ask.'
1086
1087Note that the file given will be deleted by this function, one way or
1088another. If `gnus-uu-asynchronous' is set, it won't be deleted right
1089away, but sometime later. If the user is offered to save the file, it'll
1090be moved to wherever the user wants it.
1091
1092gnus-uu-view-file returns `t' if viewing is successful."
1093 (let (action did-view
1094 (didnt-want t)
1095 (do-view t))
1096 (setq action
1097 (gnus-uu-choose-action
1098 file-name
1099 (append
1100 (if (and gnus-uu-use-interactive-view
1101 gnus-uu-user-interactive-view-rules)
1102 gnus-uu-user-interactive-view-rules
1103 gnus-uu-user-view-rules)
1104 (if (or gnus-uu-ignore-default-view-rules
1105 (not gnus-uu-use-interactive-view))
1106 ()
1107 gnus-uu-default-interactive-view-rules-begin)
1108 (if gnus-uu-ignore-default-view-rules
1109 nil
1110 gnus-uu-default-view-rules)
1111 (if (and gnus-uu-use-interactive-view
1112 gnus-uu-user-interactive-view-rules-end)
1113 gnus-uu-user-interactive-view-rules-end
1114 gnus-uu-user-view-rules-end))))
1115
1116 (if (and gnus-uu-use-interactive-view
1117 (not (string= (or action "") "gnus-uu-archive")))
1118 (gnus-uu-enter-interactive-file (or action "") file-name)
1119
1120 (if action
1121 (if (string= action "gnus-uu-archive")
1122 (setq did-view (gnus-uu-treat-archive file-name))
1123
1124 (if gnus-uu-ask-before-view
1125 (setq didnt-want
1126 (or (not
1127 (setq do-view
1128 (y-or-n-p
1129 (format "Do you want to view %s? "
1130 file-name))))
1131 didnt-want)))
1132
1133 (if do-view
1134 (setq did-view
1135 (if gnus-uu-asynchronous
1136 (gnus-uu-call-asynchronous file-name action)
1137 (gnus-uu-call-synchronous file-name action))))))
1138
1139 (if (and (not dont-ask) (not gnus-uu-use-interactive-view))
1140 (progn
1141 (if (and
1142 didnt-want
1143 (or (not action)
1144 (and (string= action "gnus-uu-archive") (not did-view))))
1145 (progn
1146 (message (format "Could find no rule for %s" file-name))
1147 (sit-for 2)))
1148 (and (or (not did-view) gnus-uu-view-and-save)
1149 (y-or-n-p
1150 (format "Do you want to save the file %s? " file-name))
1151 (gnus-uu-save-file file-name))))
1152
1153 (if (and (file-exists-p file-name)
1154 (not gnus-uu-use-interactive-view)
1155 (or
1156 (not (and gnus-uu-asynchronous did-view))
1157 (string= action "gnus-uu-archive")))
1158 (delete-file file-name)))
1159
1160 did-view))
1161
1162
1163(defun gnus-uu-call-synchronous (file-name action)
1164 "Takes two parameters: The name of the file to be displayed and
1165the command to display it with. Returns `t' on success and `nil' if
1166the file couldn't be displayed."
1167 (let (did-view command)
1168 (save-excursion
1169 (set-buffer (get-buffer-create gnus-uu-output-buffer-name))
1170 (erase-buffer)
1171 (if (string-match "%s" action)
1172 (setq command (format action (concat "'" file-name "'")))
1173 (setq command (concat action " " (concat "'" file-name "'"))))
1174 (message (format "Viewing with '%s'" command))
1175 (if (not (= 0 (call-process "sh" nil t nil "-c" command)))
1176 (progn
1177 (goto-char 1)
1178 (while (re-search-forward "\n" nil t)
1179 (replace-match " "))
1180 (message (concat "Error: " (buffer-substring 1 (point-max))))
1181 (sit-for 2))
1182 (message "")
1183 (setq did-view t)))
1184 did-view))
1185
1186
1187(defun gnus-uu-call-asynchronous (file-name action)
1188 "Takes two parameters: The name of the file to be displayed and
1189the command to display it with. Since the view command is executed
1190asynchronously, it's kinda hard to decide whether the command succeded
1191or not, so this function always returns `t'. It also adds \"; rm -f
1192file-name\" to the end of the execution string, so the file will be
1193removed after viewing has ended."
1194 (let (command file tmp-file start)
1195 (while (string-match "/" file-name start)
1196 (setq start (1+ (match-beginning 0))))
1197 (setq file (substring file-name start))
1198 (setq tmp-file (concat gnus-uu-tmp-dir file))
1199 (if (string= tmp-file file-name)
1200 ()
1201 (rename-file file-name tmp-file t)
1202 (setq file-name tmp-file))
1203
1204 (if (string-match "%s" action)
1205 (setq command (format action file-name))
1206 (setq command (concat action " " file-name)))
1207 (setq command (format "%s ; rm -f %s" command file-name))
1208 (message (format "Viewing with %s" command))
1209 (start-process "gnus-uu-view"
1210 nil "sh" "-c" command)
1211 t))
1212
1213
1214(defun gnus-uu-decode-and-strip (&optional shar use-marked)
1215 "This function does all the main work. It finds out what articles
1216to grab, grabs them, strips the result and decodes. If any of
1217these operations fail, it returns `nil', `t' otherwise.
1218If shar is `t', it will pass this on to gnus-uu-grab-articles
1219who will (probably) unshar the articles. If use-marked
1220is non-nil, it won't try to find articles, but use the marked list."
1221 (let (list-of-articles)
1222 (save-excursion
1223
1224 (if use-marked
1225 (progn (if (eq gnus-uu-marked-article-list ())
1226 (message "No articles marked")
1227 (setq list-of-articles (reverse gnus-uu-marked-article-list))
1228 (gnus-uu-unmark-all-articles)))
1229 (setq list-of-articles (gnus-uu-get-list-of-articles)))
1230
1231 (and list-of-articles
1232 (gnus-uu-grab-articles list-of-articles
1233 (if shar
1234 'gnus-uu-unshar-article
1235 'gnus-uu-uustrip-article-as))))))
1236
1237
1238(defun gnus-uu-reginize-string (string)
1239 "Takes a string and puts a \\ in front of every special character;
1240ignores any leading \"version numbers\"
1241thingies that they use in the comp.binaries groups, and either replaces
1242anything that looks like \"2/3\" with \"[0-9]+/[0-9]+\" or, if it can't find
1243something like that, replaces the last two numbers with \"[0-9]+\". This,
1244in my experience, should get most postings of a series."
1245 (let ((count 2)
1246 (vernum "v[0-9][0-9][a-z][0-9]+:")
1247 reg beg)
1248 (save-excursion
1249 (set-buffer (get-buffer-create gnus-uu-output-buffer-name))
1250 (erase-buffer)
1251 (insert (regexp-quote string))
1252 (setq beg 1)
1253
1254 (setq case-fold-search nil)
1255 (goto-char 1)
1256 (if (looking-at vernum)
1257 (progn
1258 (replace-match vernum t t)
1259 (setq beg (length vernum))))
1260
1261 (goto-char beg)
1262 (if (re-search-forward "[ \t]*[0-9]+/[0-9]+" nil t)
1263 (replace-match " [0-9]+/[0-9]+")
1264
1265 (goto-char beg)
1266 (if (re-search-forward "[0-9]+[ \t]*of[ \t]*[0-9]+" nil t)
1267 (replace-match "[0-9]+ of [0-9]+")
1268
1269 (end-of-line)
1270 (while (and (re-search-backward "[0-9]" nil t) (> count 0))
1271 (while (and
1272 (looking-at "[0-9]")
1273 (< 1 (goto-char (1- (point))))))
1274 (re-search-forward "[0-9]+" nil t)
1275 (replace-match "[0-9]+")
1276 (backward-char 5)
1277 (setq count (1- count)))))
1278
1279 (goto-char beg)
1280 (while (re-search-forward "[ \t]+" nil t)
1281 (replace-match "[ \t]*" t t))
1282
1283 (buffer-substring 1 (point-max)))))
1284
1285
1286(defun gnus-uu-get-list-of-articles (&optional subject mark-articles only-unread)
1287 "Finds all articles that matches the regular expression given.
1288Returns the resulting list."
1289 (let (beg end reg-subject list-of-subjects list-of-numbers art-num)
1290 (save-excursion
1291
1292; If the subject is not given, this function looks at the current subject
1293; and takes that.
1294
1295 (if subject
1296 (setq reg-subject subject)
1297 (end-of-line)
1298 (setq end (point))
1299 (beginning-of-line)
1300 (if (not (re-search-forward "\\] " end t))
1301 (progn (message "No valid subject chosen") (sit-for 2))
1302 (setq subject (buffer-substring (point) end))
1303 (setq reg-subject
1304 (concat "\\[.*\\] " (gnus-uu-reginize-string subject)))))
1305
1306; (message reg-subject)(sleep-for 2)
1307
1308 (if reg-subject
1309 (progn
1310
1311; Collect all subjects matching reg-subject.
1312
1313 (let ((case-fold-search t))
1314 (setq case-fold-search t)
1315 (goto-char 1)
1316 (while (re-search-forward reg-subject nil t)
1317 (beginning-of-line)
1318 (setq beg (point))
1319 (if (or (not only-unread) (looking-at " \\|-"))
1320 (progn
1321 (end-of-line)
1322 (setq list-of-subjects (cons
1323 (buffer-substring beg (point))
1324 list-of-subjects)))
1325 (end-of-line))))
1326
1327; Expand all numbers in all the subjects: (hi9 -> hi0009, etc).
1328
1329 (setq list-of-subjects (gnus-uu-expand-numbers list-of-subjects))
1330
1331; Sort the subjects.
1332
1333 (setq list-of-subjects (sort list-of-subjects 'gnus-uu-string<))
1334
1335; Get the article numbers from the sorted list of subjects.
1336
1337 (while list-of-subjects
1338 (setq art-num (gnus-uu-article-number (car list-of-subjects)))
1339 (if mark-articles (gnus-summary-mark-as-read art-num ?#))
1340 (setq list-of-numbers (cons art-num list-of-numbers))
1341 (setq list-of-subjects (cdr list-of-subjects)))
1342
1343 (setq list-of-numbers (nreverse list-of-numbers))
1344
1345 (if (not list-of-numbers)
1346 (progn
1347 (message (concat "No subjects matched " subject))
1348 (sit-for 2)))))
1349
1350 list-of-numbers)))
1351
1352
1353(defun gnus-uu-expand-numbers (string-list)
1354 "Takes a list of strings and \"expands\" all numbers in all the strings.
1355That is, this function makes all numbers equal length by prepending lots
1356of zeroes before each number. This is to ease later sorting to find out
1357what sequence the articles are supposed to be decoded in. Returns the list
1358of expanded strings."
1359 (let (string out-list pos num)
1360 (save-excursion
1361 (set-buffer (get-buffer-create gnus-uu-output-buffer-name))
1362 (while string-list
1363 (erase-buffer)
1364 (setq string (car string-list))
1365 (setq string-list (cdr string-list))
1366 (insert string)
1367 (goto-char 1)
1368 (while (re-search-forward "[ \t]+" nil t)
1369 (replace-match " "))
1370 (goto-char 1)
1371 (while (re-search-forward "[A-Za-z]" nil t)
1372 (replace-match "a" t t))
1373
1374 (goto-char 1)
1375 (if (not (search-forward "] " nil t))
1376 ()
1377 (while (re-search-forward "[0-9]+" nil t)
1378 (replace-match
1379 (format "%06d"
1380 (string-to-int (buffer-substring
1381 (match-beginning 0) (match-end 0))))))
1382 (setq string (buffer-substring 1 (point-max)))
1383 (setq out-list (cons string out-list)))))
1384 out-list))
1385
1386
1387(defun gnus-uu-string< (string1 string2)
1388 "Used in a sort for finding out what string is bigger, but ignoring
1389everything before the subject part."
1390 (string< (substring string1 (string-match "\\] " string1))
1391 (substring string2 (string-match "\\] " string2))))
1392
1393
1394;; gnus-uu-grab-article
1395;;
1396;; This is the general multi-article treatment function.
1397;; It takes a list of articles to be grabbed and a function
1398;; to apply to each article. It puts the result in
1399;; gnus-uu-result-buffer.
1400;;
1401;; The function to be called should take two parameters.
1402;; The first is the buffer that has the article that should
1403;; be treated. The function should leave the result in this
1404;; buffer as well. This result is then appended on to the
1405;; gnus-uu-result-buffer.
1406;; The second parameter is the state of the list of articles,
1407;; and can have three values: 'start, 'middle and 'end.
1408;; The function can have several return values.
1409;; 'error if there was an error while treating.
1410;; 'end if the last article has been sighted.
1411;; 'begin-and-end if the article is both the beginning and
1412;; the end. All these three return values results in
1413;; gnus-uu-grab-articles stopping traversing of the list
1414;; of articles.
1415;; 'middle if the article is a "middle" article.
1416;; 'ok if everything is ok.
1417
1418(defvar gnus-uu-has-been-grabbed nil)
1419
1420(defun gnus-uu-unmark-list-of-grabbed (&optional dont-unmark-last-article)
1421 (let (art)
1422 (if (or (not gnus-uu-has-been-grabbed)
1423 (not gnus-uu-unmark-articles-not-decoded))
1424 ()
1425 (if dont-unmark-last-article
1426 (progn
1427 (setq art (car gnus-uu-has-been-grabbed))
1428 (setq gnus-uu-has-been-grabbed (cdr gnus-uu-has-been-grabbed))))
1429 (while gnus-uu-has-been-grabbed
1430 (gnus-summary-mark-as-unread (car gnus-uu-has-been-grabbed) t)
1431 (setq gnus-uu-has-been-grabbed (cdr gnus-uu-has-been-grabbed)))
1432 (if dont-unmark-last-article
1433 (setq gnus-uu-has-been-grabbed (list art)))
1434 )))
1435
1436
1437(defun gnus-uu-grab-articles (list-of-articles process-function)
1438 "This function takes a list of articles and a function to apply
1439to each article grabbed. The result of the function is appended
1440on to gnus-uu-result-buffer.
1441
1442This function returns `t' if the grabbing and the process-function
1443has been successful and `nil' otherwise."
1444 (let ((result-buffer (get-buffer-create gnus-uu-result-buffer))
1445 (state 'first)
1446 (process-state 'ok)
1447 (result t)
1448 (wrong-type t)
1449 (has-been-begin nil)
1450 (article nil))
1451
1452 (save-excursion
1453 (set-buffer result-buffer)
1454 (erase-buffer))
1455 (setq gnus-uu-has-been-grabbed nil)
1456 (while (and list-of-articles
1457 (not (eq process-state 'end))
1458 (not (eq process-state 'begin-and-end))
1459 (not (eq process-state 'error)))
1460 (setq article (car list-of-articles))
1461 (setq list-of-articles (cdr list-of-articles))
1462 (setq gnus-uu-has-been-grabbed (cons article gnus-uu-has-been-grabbed))
1463
1464 (if (eq list-of-articles ()) (setq state 'last))
1465
1466 (message (format "Getting article %d" article))
1467 (if (not (= (or gnus-current-article 0) article))
1468 (gnus-summary-display-article article))
1469 (gnus-summary-mark-as-read article)
1470
1471 (save-excursion
1472 (set-buffer gnus-article-buffer)
1473 (widen))
1474
1475 (setq process-state (funcall process-function gnus-article-buffer state))
1476
1477 (if (or (eq process-state 'begin) (eq process-state 'begin-and-end)
1478 (eq process-state 'ok))
1479 (setq has-been-begin t))
1480
1481 (if (not (eq process-state 'wrong-type))
1482 (setq wrong-type nil)
1483 (if gnus-uu-unmark-articles-not-decoded
1484 (gnus-summary-mark-as-unread article t)))
1485
1486 (if gnus-uu-do-sloppy-uudecode
1487 (setq wrong-type nil))
1488
1489 (if (and (not has-been-begin)
1490 (not gnus-uu-do-sloppy-uudecode)
1491 (or (eq process-state 'end)
1492 (eq process-state 'middle)))
1493 (progn
1494 (setq process-state 'error)
1495 (message "No begin part at the beginning")
1496 (sit-for 2))
1497 (setq state 'middle)))
1498
1499 (if (and (not has-been-begin) (not gnus-uu-do-sloppy-uudecode))
1500 (progn
1501 (setq result nil)
1502 (message "Wrong type file")
1503 (sit-for 2))
1504 (if (eq process-state 'error)
1505 (setq result nil)
1506 (if (not (or (eq process-state 'ok)
1507 (eq process-state 'end)
1508 (eq process-state 'begin-and-end)))
1509 (progn
1510 (if (not gnus-uu-do-sloppy-uudecode)
1511 (progn
1512 (message "End of articles reached before end of file")
1513 (sit-for 2)))
1514 (gnus-uu-unmark-list-of-grabbed)
1515 (setq result nil)))))
1516 (setq gnus-uu-rest-of-articles list-of-articles)
1517 result))
1518
1519
1520(defun gnus-uu-uudecode-sentinel (process event)
1521; (message "Process '%s' has received event '%s'" process event)
1522; (sit-for 2)
1523 (delete-process (get-process process)))
1524
1525
1526(defun gnus-uu-uustrip-article-as (process-buffer in-state)
1527 (let ((state 'ok)
1528 (process-connection-type nil)
1529 start-char pst name-beg name-end buf-state)
1530 (save-excursion
1531 (set-buffer process-buffer)
1532 (setq buf-state buffer-read-only)
1533 (setq buffer-read-only nil)
1534
1535 (goto-char 1)
1536
1537 (if gnus-uu-kill-carriage-return
1538 (progn
1539 (while (search-forward " " nil t)
1540 (delete-backward-char 1))
1541 (goto-char 1)))
1542
1543 (if (not (re-search-forward
1544 (concat gnus-uu-begin-string "\\|" gnus-uu-body-line) nil t))
1545 (setq state 'wrong-type)
1546
1547 (beginning-of-line)
1548 (setq start-char (point))
1549
1550 (if (looking-at gnus-uu-begin-string)
1551 (progn
1552 (setq name-end (match-end 1))
1553 (goto-char (setq name-beg (match-beginning 1)))
1554 (while (re-search-forward "/" name-end t)
1555 (replace-match "-"))
1556 (setq gnus-uu-file-name (buffer-substring name-beg name-end))
1557 (setq pst (process-status
1558 (or gnus-uu-uudecode-process "nevair")))
1559 (if (or (eq pst 'stop) (eq pst 'run))
1560 (progn
1561 (delete-process gnus-uu-uudecode-process)
1562 (gnus-uu-unmark-list-of-grabbed t)))
1563 (setq gnus-uu-uudecode-process
1564 (start-process
1565 "*uudecode*"
1566 (get-buffer-create gnus-uu-output-buffer-name)
1567 "sh" "-c"
1568 (format "cd %s ; uudecode" gnus-uu-tmp-dir)))
1569 (set-process-sentinel
1570 gnus-uu-uudecode-process 'gnus-uu-uudecode-sentinel)
1571 (setq state 'begin)
1572 (gnus-uu-add-file (concat gnus-uu-tmp-dir gnus-uu-file-name)))
1573 (setq state 'middle))
1574
1575 (goto-char (point-max))
1576 (re-search-backward
1577 (concat gnus-uu-body-line "\\|" gnus-uu-end-string) nil t)
1578 (if (looking-at gnus-uu-end-string)
1579 (if (eq state 'begin)
1580 (setq state 'begin-and-end)
1581 (setq state 'end)))
1582 (forward-line 1)
1583
1584 (setq pst (process-status (or gnus-uu-uudecode-process "nevair")))
1585 (if (or (eq pst 'run) (eq pst 'stop))
1586 (progn
1587 (gnus-uu-check-correct-stripped-uucode start-char (point))
1588 (condition-case err
1589 (process-send-region gnus-uu-uudecode-process start-char
1590 (point))
1591 (error
1592 (progn
1593 (setq state 'wrong-type)
1594 (delete-process gnus-uu-uudecode-process)))))
1595 (setq state 'wrong-type)))
1596 (setq buffer-read-only buf-state))
1597 state))
1598
1599
1600(defun gnus-uu-unshar-article (process-buffer in-state)
1601 "This function is used by gnus-uu-grab-articles to treat
1602a shared article."
1603 (let ((state 'ok)
1604 start-char)
1605 (save-excursion
1606 (set-buffer process-buffer)
1607 (goto-char 1)
1608 (if (not (re-search-forward gnus-uu-shar-begin-string nil t))
1609 (setq state 'wrong-type)
1610 (beginning-of-line)
1611 (setq start-char (point))
1612 (call-process-region
1613 start-char (point-max) "sh" nil
1614 (get-buffer-create gnus-uu-output-buffer-name) nil
1615 "-c" (concat "cd " gnus-uu-shar-directory " ; sh"))))
1616 state))
1617
1618
1619(defun gnus-uu-find-name-in-shar ()
1620 "Returns the name of what the shar file is going to unpack."
1621 (let ((oldpoint (point))
1622 res)
1623 (goto-char 1)
1624 (if (re-search-forward gnus-uu-shar-name-marker nil t)
1625 (setq res (buffer-substring (match-beginning 1) (match-end 1))))
1626 (goto-char oldpoint)
1627 res))
1628
1629
1630(defun gnus-uu-article-number (subject)
1631 "Returns the article number of the given subject."
1632 (let (end)
1633 (string-match "[0-9]+[^0-9]" subject 1)
1634 (setq end (match-end 0))
1635 (string-to-int
1636 (substring subject (string-match "[0-9]" subject 1) end))))
1637
1638
1639(defun gnus-uu-decode (directory)
1640 "UUdecodes everything in the buffer and returns the name of the resulting
1641file."
1642 (let ((command (concat "cd " directory " ; uudecode"))
1643 file-name)
1644 (save-excursion
1645 (message "Uudecoding...")
1646 (set-buffer (get-buffer-create gnus-uu-result-buffer))
1647 (setq file-name (concat gnus-uu-tmp-dir gnus-uu-file-name))
1648 (gnus-uu-add-file file-name)
1649 (call-process-region 1 (point-max) "sh" nil t nil "-c" command)
1650 file-name)))
1651
1652
1653(defun gnus-uu-choose-action (file-name file-action-list)
1654 "Chooses what action to perform given the name and gnus-uu-file-action-list.
1655Returns either nil if no action is found, or the name of the command
1656to run if such a rule is found."
1657 (let ((action-list (copy-sequence file-action-list))
1658 rule action)
1659 (while (not (or (eq action-list ()) action))
1660 (setq rule (car action-list))
1661 (setq action-list (cdr action-list))
1662 (if (string-match (car rule) file-name)
1663 (setq action (car (cdr rule)))))
1664 action))
1665
1666
1667(defun gnus-uu-save-file (from-file-name &optional default-dir ignore-existing)
1668 "Moves the file from the tmp directory to where the user wants it."
1669 (let (dir file-name command)
1670 (string-match "/[^/]*$" from-file-name)
1671 (setq file-name (substring from-file-name (1+ (match-beginning 0))))
1672 (if default-dir
1673 (setq dir default-dir)
1674 (setq dir (gnus-uu-read-directory "Where do you want the file? ")))
1675 (if (and (not ignore-existing) (file-exists-p (concat dir file-name)))
1676 (progn
1677 (message (concat "There already is a file called " file-name))
1678 (sit-for 2)
1679 (setq file-name
1680 (read-file-name "Give a new name: " dir (concat dir file-name)
1681 nil file-name)))
1682 (setq file-name (concat dir file-name)))
1683 (rename-file from-file-name file-name t)))
1684
1685
1686(defun gnus-uu-read-directory (prompt &optional default)
1687 (let (dir ok create)
1688 (while (not ok)
1689 (setq ok t)
1690 (setq dir (if default default
1691 (read-file-name prompt gnus-uu-current-save-dir
1692 gnus-uu-current-save-dir)))
1693 (while (string-match "/$" dir)
1694 (setq dir (substring dir 0 (match-beginning 0))))
1695 (if (file-exists-p dir)
1696 (if (not (file-directory-p dir))
1697 (progn
1698 (setq ok nil)
1699 (message "%s is a file" dir)
1700 (sit-for 2)))
1701 (setq create ?o)
1702 (while (not (or (= create ?y) (= create ?n)))
1703 (message "%s: No such directory. Do you want to create it? (y/n)"
1704 dir)
1705 (setq create (read-char)))
1706 (if (= create ?y) (make-directory dir))))
1707 (setq gnus-uu-current-save-dir (concat dir "/"))))
1708
1709
1710(defun gnus-uu-treat-archive (file-name)
1711 "Unpacks an archive and views all the files in it. Returns `t' if
1712viewing one or more files is successful."
1713 (let ((arc-dir (make-temp-name
1714 (concat gnus-uu-tmp-dir "gnusuu")))
1715 action command files file did-view short-file-name
1716 error-during-unarching)
1717 (setq action (gnus-uu-choose-action
1718 file-name (append gnus-uu-user-archive-rules
1719 (if gnus-uu-ignore-default-archive-rules
1720 nil
1721 gnus-uu-default-archive-rules))))
1722 (if (not action)
1723 (progn (message (format "No unpackers for the file %s" file-name))
1724 (sit-for 2))
1725 (string-match "/[^/]*$" file-name)
1726 (setq short-file-name (substring file-name (1+ (match-beginning 0))))
1727 (setq command (format "%s %s %s ; cd %s ; %s %s "
1728 (if (or (string= action "uncompress")
1729 (string= action "gunzip"))
1730 "cp"
1731 "mv")
1732 file-name arc-dir
1733 arc-dir
1734 action short-file-name))
1735
1736 (make-directory arc-dir)
1737 (gnus-uu-add-file arc-dir)
1738
1739 (save-excursion
1740 (set-buffer (get-buffer-create gnus-uu-output-buffer-name))
1741 (erase-buffer))
1742
1743 (message (format "Unpacking with %s..." action))
1744
1745 (if (= 0 (call-process "sh" nil
1746 (get-buffer-create gnus-uu-output-buffer-name)
1747 nil "-c" command))
1748 (message "")
1749 (message "Error during unpacking of archive")
1750 (sit-for 2)
1751 (sit-for 2)
1752 (setq error-during-unarching t))
1753
1754 (if (not (or (string= action "uncompress")
1755 (string= action "gunzip")))
1756 (call-process "sh" nil (get-buffer gnus-uu-output-buffer-name)
1757 nil "-c" (format "mv %s/%s %s"
1758 arc-dir short-file-name
1759 gnus-uu-tmp-dir)))
1760 (gnus-uu-add-file (concat gnus-uu-tmp-dir short-file-name))
1761
1762 (setq did-view
1763 (or (gnus-uu-show-directory arc-dir gnus-uu-use-interactive-view)
1764 did-view))
1765
1766 (if (and (not gnus-uu-use-interactive-view)
1767 (file-directory-p arc-dir))
1768 (delete-directory arc-dir)))
1769
1770 did-view))
1771
1772
1773(defun gnus-uu-show-directory (dir &optional dont-delete-files)
1774 "Tries to view all the files in the given directory. Returns `t' if
1775viewing one or more files is successful."
1776 (let (files file did-view)
1777 (setq files (directory-files dir t))
1778 (setq gnus-uu-generated-file-list
1779 (append files gnus-uu-generated-file-list))
1780 (while files
1781 (setq file (car files))
1782 (setq files (cdr files))
1783 (if (and (not (string-match "/\\.$" file))
1784 (not (string-match "/\\.\\.$" file)))
1785 (progn
1786 (set-file-modes file 448)
1787 (if (file-directory-p file)
1788 (setq did-view (or (gnus-uu-show-directory file
1789 dont-delete-files)
1790 did-view))
1791 (setq did-view (or (gnus-uu-view-file file t) did-view))
1792 (if (and (not dont-delete-files) (file-exists-p file))
1793 (delete-file file))))))
1794 (if (not dont-delete-files) (delete-directory dir))
1795 did-view))
1796
1797
1798;; Manual marking
1799
1800(defun gnus-uu-enter-mark-in-list ()
1801 (let (article beg)
1802 (beginning-of-line)
1803 (setq beg (point))
1804 (end-of-line)
1805 (setq article (gnus-uu-article-number
1806 (buffer-substring beg (point))))
1807 (message (format "Adding article %d to list" article))
1808 (setq gnus-uu-marked-article-list
1809 (cons article gnus-uu-marked-article-list))))
1810
1811(defun gnus-uu-mark-article ()
1812 "Marks the current article to be decoded later."
1813 (interactive)
1814 (gnus-uu-enter-mark-in-list)
1815 (gnus-summary-mark-as-read nil ?#)
1816 (gnus-summary-next-subject 1 nil))
1817
1818(defun gnus-uu-unmark-article ()
1819 "Unmarks the current article."
1820 (interactive)
1821 (let ((in (copy-sequence gnus-uu-marked-article-list))
1822 out article beg found
1823 (old-point (point)))
1824 (beginning-of-line)
1825 (setq beg (point))
1826 (end-of-line)
1827 (setq article (gnus-uu-article-number (buffer-substring beg (point))))
1828 (message (format "Removing article %d" article))
1829 (while in
1830 (if (not (= (car in) article))
1831 (setq out (cons (car in) out))
1832 (setq found t)
1833 (message (format "Removing article %d" article)))
1834 (setq in (cdr in)))
1835 (if (not found) (message "Not a marked article."))
1836 (setq gnus-uu-marked-article-list (reverse out))
1837 (gnus-summary-mark-as-unread nil t)
1838 (gnus-summary-next-subject 1 nil)))
1839
1840
1841(defun gnus-uu-unmark-all-articles ()
1842 "Removes the mark from all articles marked for decoding."
1843 (interactive)
1844 (let ((articles (copy-sequence gnus-uu-marked-article-list)))
1845 (while articles
1846 (gnus-summary-goto-subject (car articles))
1847 (gnus-summary-mark-as-unread nil t)
1848 (setq articles (cdr articles)))
1849 (setq gnus-uu-marked-article-list ())))
1850
1851(defun gnus-uu-mark-by-regexp ()
1852 "Asks for a regular expression and marks all articles that match for later decoding."
1853 (interactive)
1854 (let (exp)
1855 (setq exp (read-from-minibuffer "Enter regular expression: "))
1856 (setq gnus-uu-marked-article-list
1857 (reverse (gnus-uu-get-list-of-articles exp t)))
1858 (message "")))
1859
1860
1861;; Various
1862
1863(defun gnus-uu-check-correct-stripped-uucode (start end)
1864 (let (found beg length short)
1865 (if (not gnus-uu-correct-stripped-uucode)
1866 ()
1867 (goto-char start)
1868 (while (< (point) end)
1869 (if (looking-at (concat gnus-uu-begin-string "\\|" gnus-uu-end-string))
1870 ()
1871 (if (not found)
1872 (progn
1873 (beginning-of-line)
1874 (setq beg (point))
1875 (end-of-line)
1876 (setq length (- (point) beg))))
1877 (beginning-of-line)
1878 (setq beg (point))
1879 (end-of-line)
1880 (if (not (= length (- (point) beg)))
1881 (insert (make-string (- length (- (point) beg))) ? )))
1882 (forward-line 1)))))
1883
1884(defun gnus-uu-initialize ()
1885 (if (not gnus-uu-use-interactive-view)
1886 ()
1887 (save-excursion
1888 (setq gnus-uu-interactive-file-list nil)
1889 (set-buffer (get-buffer-create gnus-uu-interactive-buffer-name))
1890 (erase-buffer)
1891 (gnus-uu-mode)
1892 (insert
1893 "# Press return to execute a command.
1894# Press `C-c C-c' to exit interactive view.
1895
1896"))))
1897
1898
1899(defun gnus-uu-clean-up ()
1900 "Kills the temporary uu buffers."
1901 (let (buf pst)
1902 (setq gnus-uu-do-sloppy-uudecode nil)
1903 (setq pst (process-status (or gnus-uu-uudecode-process "nevair")))
1904 (if (or (eq pst 'stop) (eq pst 'run))
1905 (delete-process gnus-uu-uudecode-process))
1906 (and (not gnus-uu-asynchronous)
1907 (setq buf (get-buffer gnus-uu-output-buffer-name))
1908 (kill-buffer buf))
1909 (and (setq buf (get-buffer gnus-uu-result-buffer))
1910 (kill-buffer buf))))
1911
1912
1913(defun gnus-uu-check-for-generated-files ()
1914 "Deletes any generated files that hasn't been deleted, if, for
1915instance, the user terminated decoding with `C-g'."
1916 (let (file)
1917 (while gnus-uu-generated-file-list
1918 (setq file (car gnus-uu-generated-file-list))
1919 (setq gnus-uu-generated-file-list (cdr gnus-uu-generated-file-list))
1920 (if (not (string-match "/\\.[\\.]?$" file))
1921 (progn
1922 (if (file-directory-p file)
1923 (delete-directory file)
1924 (if (file-exists-p file)
1925 (delete-file file))))))))
1926
1927
1928(defun gnus-uu-add-file (file)
1929 (setq gnus-uu-generated-file-list
1930 (cons file gnus-uu-generated-file-list)))
1931
1932(defun gnus-uu-summary-next-subject ()
1933 (if (not (gnus-summary-search-forward t))
1934 (progn
1935 (goto-char 1)
1936 (sit-for 0)
1937 (goto-char (point-max))
1938 (forward-line -1)
1939 (beginning-of-line)
1940 (search-forward ":" nil t)))
1941 (sit-for 0)
1942 (gnus-summary-recenter))
1943
1944
1945;; Initializing
1946
1947(add-hook 'gnus-exit-group-hook
1948 '(lambda ()
1949 (gnus-uu-clean-up)
1950 (setq gnus-uu-marked-article-list nil)
1951 (gnus-uu-check-for-generated-files)))
1952
1953
1954;; Interactive exec mode
1955
1956(defvar gnus-uu-output-window nil)
1957(defvar gnus-uu-mode-hook nil)
1958(defvar gnus-uu-mode-map nil)
1959
1960(defun gnus-uu-do-interactive ()
1961 (let (int-buffer out-buf)
1962 (set-buffer
1963 (setq int-buffer (get-buffer gnus-uu-interactive-buffer-name)))
1964 (switch-to-buffer-other-window int-buffer)
1965 (pop-to-buffer int-buffer)
1966 (setq gnus-uu-output-window
1967 (split-window nil (- (window-height) gnus-uu-output-window-height)))
1968 (set-window-buffer gnus-uu-output-window
1969 (setq out-buf
1970 (get-buffer-create gnus-uu-output-buffer-name)))
1971 (save-excursion (set-buffer out-buf) (erase-buffer))
1972 (goto-char 1)
1973 (forward-line 3)
1974 (run-hooks 'gnus-uu-mode-hook)))
1975
1976
1977(defun gnus-uu-enter-interactive-file (action file)
1978 (let (command)
1979 (save-excursion
1980 (setq gnus-uu-interactive-file-list
1981 (cons file gnus-uu-interactive-file-list))
1982 (set-buffer (get-buffer gnus-uu-interactive-buffer-name))
1983 (if (string-match "%s" action)
1984 (setq command (format action (concat "'" file "'")))
1985 (setq command (concat action " " (concat "'" file "'"))))
1986
1987 (insert (format "%s\n" command)))))
1988
1989
1990(defun gnus-uu-interactive-execute ()
1991 (interactive)
1992 (let (beg out-buf command)
1993 (beginning-of-line)
1994 (setq beg (point))
1995 (end-of-line)
1996 (setq command (buffer-substring beg (point)))
1997 (setq out-buf (get-buffer-create gnus-uu-output-buffer-name))
1998 (save-excursion
1999 (set-buffer out-buf)
2000 (erase-buffer)
2001 (insert (format "$ %s \n\n" command)))
2002 (message "Executing...")
2003 (if gnus-uu-asynchronous
2004 (start-process "gnus-uu-view" out-buf "sh" "-c" command)
2005 (call-process "sh" nil out-buf nil "-c" command)
2006 (message ""))
2007 (forward-line 1)
2008 (beginning-of-line)))
2009
2010
2011(defun gnus-uu-interactive-end ()
2012 "This function ends interactive view mode and returns to summary mode."
2013 (interactive)
2014 (let (buf)
2015 (delete-window gnus-uu-output-window)
2016 (gnus-uu-clean-up)
2017 (if (not gnus-uu-asynchronous) (gnus-uu-check-for-generated-files))
2018 (setq buf (get-buffer gnus-uu-interactive-buffer-name))
2019 (if gnus-article-buffer (switch-to-buffer gnus-article-buffer))
2020 (if buf (kill-buffer buf))
2021 (pop-to-buffer gnus-summary-buffer)))
2022
2023
2024(if gnus-uu-mode-map
2025 ()
2026 (setq gnus-uu-mode-map (make-sparse-keymap))
2027 (define-key gnus-uu-mode-map "\C-c\C-x" 'gnus-uu-interactive-execute)
2028 (define-key gnus-uu-mode-map "\C-c\C-v" 'gnus-uu-interactive-execute)
2029 (define-key gnus-uu-mode-map "\C-m" 'gnus-uu-interactive-execute)
2030 (define-key gnus-uu-mode-map "\C-c\C-c" 'gnus-uu-interactive-end)
2031 (define-key gnus-uu-mode-map "\C-cs"
2032 'gnus-uu-interactive-save-current-file)
2033 (define-key gnus-uu-mode-map "\C-c\C-s"
2034 'gnus-uu-interactive-save-current-file-silent)
2035 (define-key gnus-uu-mode-map "\C-c\C-w" 'gnus-uu-interactive-save-all-files)
2036 (define-key gnus-uu-mode-map "\C-c\C-o" 'gnus-uu-interactive-save-original-file))
2037
2038
2039(defun gnus-uu-interactive-save-original-file ()
2040 (interactive)
2041 (let (file)
2042 (if (file-exists-p
2043 (setq file (concat gnus-uu-tmp-dir
2044 (or gnus-uu-file-name gnus-uu-shar-file-name))))
2045 (gnus-uu-save-file file)
2046 (message "Already saved."))))
2047
2048
2049(defun gnus-uu-interactive-save-current-file-silent ()
2050 "hei"
2051 (interactive)
2052 (gnus-uu-interactive-save-current-file t))
2053
2054(defun gnus-uu-interactive-save-current-file (&optional dont-ask silent)
2055 "Saves the file referred to on the current line."
2056 (interactive)
2057 (let (files beg line file)
2058 (setq files (copy-sequence gnus-uu-interactive-file-list))
2059 (beginning-of-line)
2060 (setq beg (point))
2061 (end-of-line)
2062 (setq line (buffer-substring beg (point)))
2063 (while (and files
2064 (not (string-match
2065 (concat "" (regexp-quote (setq file (car files))) "")
2066 line)))
2067 (setq files (cdr files)))
2068 (beginning-of-line)
2069 (forward-line 1)
2070 (if (not files)
2071 (if (not silent)
2072 (progn (message "Could not find file") (sit-for 2)))
2073 (gnus-uu-save-file file (if dont-ask gnus-uu-current-save-dir nil) silent)
2074 (delete-region beg (point)))))
2075
2076
2077(defun gnus-uu-interactive-save-all-files ()
2078 "Saves all files referred to on the current line."
2079 (interactive)
2080 (let (dir)
2081 (goto-char 1)
2082 (setq dir (gnus-uu-read-directory "Where do you want the files? "))
2083 (while (not (eobp))
2084 (gnus-uu-interactive-save-current-file t t))))
2085
2086(defun gnus-uu-mode ()
2087 "Major mode for editing view commands in gnus-uu.
2088
2089
2090Commands:
2091Return, C-c C-v, C-c C-x Execute the current command
2092C-c C-c End interactive mode
2093C-c s Save the current file
2094C-c C-s Save the current file without asking
2095 where to put it
2096C-c C-a Save all files
2097C-c C-o Save the original file: If the files
2098 originated in an archive, the archive
2099 file is saved.
2100"
2101 (interactive)
2102 (kill-all-local-variables)
2103 (use-local-map gnus-uu-mode-map)
2104 (setq mode-name "gnus-uu")
2105 (setq major-mode 'gnus-uu-mode)
2106)
2107
2108 (define-key gnus-uu-mode-map "\C-c\C-x" 'gnus-uu-interactive-execute)
2109 (define-key gnus-uu-mode-map "\C-c\C-v" 'gnus-uu-interactive-execute)
2110 (define-key gnus-uu-mode-map "\C-m" 'gnus-uu-interactive-execute)
2111 (define-key gnus-uu-mode-map "\C-c\C-c" 'gnus-uu-interactive-end)
2112 (define-key gnus-uu-mode-map "\C-cs"
2113 'gnus-uu-interactive-save-current-file)
2114 (define-key gnus-uu-mode-map "\C-c\C-s"
2115 'gnus-uu-interactive-save-current-file-silent)
2116 (define-key gnus-uu-mode-map "\C-c\C-a" 'gnus-uu-interactive-save-all-files)
2117 (define-key gnus-uu-mode-map "\C-c\C-o" 'gnus-uu-interactive-save-original-file)
2118
2119(provide 'gnus-uu)
2120