* modb.el (modb-generic): Added slot `mime-charset'.
[elisp/wanderlust.git] / elmo / elmo.el
1 ;;; elmo.el --- Elisp Library for Message Orchestration.
2
3 ;; Copyright (C) 1998,1999,2000 Yuuichi Teranishi <teranisi@gohome.org>
4
5 ;; Author: Yuuichi Teranishi <teranisi@gohome.org>
6 ;; Keywords: mail, net news
7
8 ;; This file is part of ELMO (Elisp Library for Message Orchestration).
9
10 ;; This program is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 2, or (at your option)
13 ;; any later version.
14 ;;
15 ;; This program is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 ;; GNU General Public License for more details.
19 ;;
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
22 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
24 ;;
25
26 ;;; Commentary:
27 ;;
28
29 ;;; Code:
30 ;;
31
32 (require 'luna)
33
34 (require 'elmo-version)                 ; reduce recursive-load-depth
35 (require 'elmo-vars)
36 (require 'elmo-util)
37 (require 'elmo-msgdb)
38 (require 'elmo-signal)
39
40 (eval-when-compile (require 'cl))
41
42 (if (or (featurep 'dbm)
43         (featurep 'gnudbm)
44         (featurep 'berkdb)
45         (featurep 'berkeley-db))
46     (require 'elmo-database))
47
48 (defcustom elmo-message-fetch-threshold 30000
49   "Fetch threshold."
50   :type '(choice (integer :tag "Threshold (bytes)")
51                  (const :tag "No limitation" nil))
52   :group 'elmo)
53
54 (defcustom elmo-message-fetch-confirm t
55   "If non-nil, confirm fetching if message size is larger than
56 `elmo-message-fetch-threshold'.
57 Otherwise, entire fetching of the message is aborted without confirmation."
58   :type 'boolean
59   :group 'elmo)
60
61 (defcustom elmo-folder-update-threshold 500
62   "Update threshold."
63   :type '(choice (integer :tag "Number of messages")
64                  (const :tag "No limitation" nil))
65   :group 'elmo)
66
67 (defcustom elmo-folder-update-confirm t
68   "Confirm if update number exceeds `elmo-folder-update-threshold'."
69   :type 'boolean
70   :group 'elmo)
71
72 (defcustom elmo-msgdb-path-encode-threshold nil
73   "*Encode msgdb path if its length is longer than this value."
74   :type '(choice (const :tag "No encode" nil)
75                  number)
76   :group 'elmo)
77
78 (defvar elmo-message-displaying nil
79   "A global switch to indicate message is displaying or not.")
80
81 ;;; internal
82 (defvar elmo-folder-type-alist nil)
83
84 (defvar elmo-newsgroups-hashtb nil)
85
86 (elmo-define-error 'elmo-error "Error" 'error)
87 (elmo-define-error 'elmo-open-error "Cannot open" 'elmo-error)
88 (elmo-define-error 'elmo-authenticate-error "Login failed" 'elmo-open-error)
89 (elmo-define-error 'elmo-imap4-bye-error "IMAP4 session was terminated" 'elmo-open-error)
90
91 ;; Event declarations
92 (elmo-define-signal flag-changing (number old-flags new-flags)
93   "Notify the changing flag of the messages with NUMBER.")
94
95 (elmo-define-signal flag-changed (numbers)
96   "Notify the change flag of the messages with NUMBERS.")
97
98 (elmo-define-signal cache-changed (number)
99   "Notify the change cache status of the message with NUMBER.")
100
101 (elmo-define-signal update-overview (number)
102   "Notify update overview of the message with NUMBER.")
103
104 (elmo-define-signal message-number-changed (old-number new-number)
105   "Notify change of message number within the folder.")
106
107 ;; autoloads
108 (eval-and-compile
109   (autoload 'md5 "md5")
110   (autoload 'elmo-dop-queue-flush "elmo-dop")
111   (autoload 'elmo-nntp-post "elmo-nntp")
112   (autoload 'elmo-global-flag-p "elmo-flag")
113   (autoload 'elmo-local-flag-p "elmo-flag")
114   (autoload 'elmo-global-flag-detach "elmo-flag")
115   (autoload 'elmo-global-flag-detach-messages "elmo-flag")
116   (autoload 'elmo-global-flag-set "elmo-flag")
117   (autoload 'elmo-get-global-flags "elmo-flag")
118   (autoload 'elmo-global-flags-initialize "elmo-flag")
119   (autoload 'elmo-global-mark-migrate "elmo-flag")
120   (autoload 'elmo-folder-list-global-flag-messages "elmo-flag"))
121
122 (defun elmo-define-folder (prefix backend)
123   "Define a folder.
124 If a folder name begins with PREFIX, use BACKEND."
125   (let ((pair (assq prefix elmo-folder-type-alist)))
126     (if pair
127         (progn
128           (setcar pair prefix)
129           (setcdr pair backend))
130       (setq elmo-folder-type-alist (cons (cons prefix backend)
131                                          elmo-folder-type-alist)))))
132
133 (defmacro elmo-folder-type (name)
134   "Get folder type from NAME string."
135   `(and (stringp ,name)
136         (cdr (assoc (string-to-char ,name) elmo-folder-type-alist))))
137
138 ;;; ELMO folder
139 ;; A elmo folder provides uniformed (orchestrated) access
140 ;; to the internet messages.
141 (eval-and-compile
142   (luna-define-class elmo-folder () (type   ; folder type symbol.
143                                      name   ; orignal folder name string.
144                                      prefix ; prefix for folder name
145                                      path   ; directory path for msgdb.
146                                      msgdb  ; msgdb (may be nil).
147                                      killed-list  ; killed list.
148                                      flag-table   ; flag table.
149                                      persistent   ; non-nil if persistent.
150                                      process-duplicates  ; read or hide
151                                      biff   ; folder for biff
152                                      mime-charset ; charset for encode & decode
153                                      ))
154   (luna-define-internal-accessors 'elmo-folder))
155
156 (luna-define-generic elmo-folder-initialize (folder name)
157   ;; Initialize a FOLDER structure with NAME."
158   )
159
160 (defmacro elmo-folder-send (folder message &rest args)
161   "Let FOLDER receive the MESSAGE with ARGS."
162   (` (luna-send (, folder) (, message) (, folder) (,@ args))))
163
164 ;;;###autoload
165 (defun elmo-make-folder (name &optional non-persistent mime-charset)
166   "Make an ELMO folder structure specified by NAME.
167 If optional argument NON-PERSISTENT is non-nil, the folder msgdb is not saved.
168 If optional argument MIME-CHARSET is specified, it is used for
169 encode and decode a multibyte string."
170   (let ((type (elmo-folder-type name))
171         prefix split class folder original)
172     (setq original (elmo-string name))
173     (if type
174         (progn
175           (setq prefix (elmo-string (substring name 0 1)))
176           (setq name (elmo-string (substring name 1))))
177       (setq type (intern (car (setq split (split-string name ":")))))
178       (if (>= (length split) 2)
179           (setq name (substring name (+ 1 (length (car split)))))
180         (error "Error in folder name `%s'" original))
181       (setq prefix (concat (car split) ":")))
182     (setq class (format "elmo-%s" (symbol-name type)))
183     (require (intern class))
184     (setq folder (luna-make-entity (intern (concat class "-folder"))
185                                    :type type
186                                    :prefix prefix
187                                    :name original
188                                    :persistent (not non-persistent)
189                                    :mime-charset mime-charset))
190     (save-match-data
191       (elmo-folder-send folder 'elmo-folder-initialize name))))
192
193 ;; Note that this function is for internal use only.
194 (luna-define-generic elmo-folder-msgdb (folder)
195   "Return the msgdb of FOLDER (on-demand loading).
196 \(For internal use only.\)")
197
198 (luna-define-method elmo-folder-msgdb ((folder elmo-folder))
199   (or (elmo-folder-msgdb-internal folder)
200       (elmo-folder-set-msgdb-internal folder
201                                       (elmo-folder-msgdb-load folder))))
202
203 (luna-define-generic elmo-folder-open (folder &optional load-msgdb)
204   "Open and setup (load saved status) FOLDER.
205 If optional LOAD-MSGDB is non-nil, msgdb is loaded.
206 \(otherwise, msgdb is loaded on-demand)")
207
208 (luna-define-generic elmo-folder-open-internal (folder)
209   "Open FOLDER (without loading saved folder status).")
210
211 (luna-define-generic elmo-folder-check (folder)
212   "Check the FOLDER to obtain newest information at the next list operation.")
213
214 (luna-define-generic elmo-folder-clear (folder &optional keep-killed)
215   "Clear FOLDER to the initial state.
216 If optional KEEP-KILLED is non-nil, killed-list is not cleared.")
217
218 (luna-define-generic elmo-folder-commit (folder)
219   "Save current status of FOLDER.")
220
221 (luna-define-generic elmo-folder-close (folder)
222   "Close, save and clearnup FOLDER.")
223
224 (luna-define-generic elmo-folder-close-internal (folder)
225   "Close FOLDER (without saving folder status).")
226
227 (luna-define-generic elmo-folder-plugged-p (folder)
228   "Returns t if FOLDER is plugged.")
229
230 (luna-define-generic elmo-folder-set-plugged (folder plugged &optional add)
231   "Set FOLDER as plugged.")
232
233 (luna-define-generic elmo-net-port-info (folder)
234   "Get port information of FOLDER.")
235
236 (luna-define-generic elmo-folder-use-flag-p (folder)
237   "Returns t if FOLDER treats unread/important flag itself.")
238
239 (luna-define-generic elmo-folder-diff (folder)
240   "Get diff of FOLDER.
241 Return value is cons cell or list:
242  - a cons cell (new . all)
243  - a list (new unread all)")
244
245 (luna-define-generic elmo-folder-status (folder)
246   "Returns a cons cell of (MAX-NUMBER . MESSAGES) in the FOLDER.")
247
248 (luna-define-generic elmo-folder-reserve-status-p (folder)
249   "If non-nil, the folder should not close folder after `elmo-folder-status'.")
250
251 (luna-define-generic elmo-folder-list-messages (folder &optional visible-only
252                                                        in-msgdb)
253   "Return a list of message numbers contained in FOLDER.
254 If optional VISIBLE-ONLY is non-nil, killed messages are not listed.
255 If second optional IN-MSGDB is non-nil, only messages in the msgdb are listed.")
256
257 (luna-define-method elmo-folder-list-messages ((folder elmo-folder)
258                                                &optional visible-only in-msgdb)
259   (let ((list (if in-msgdb
260                   t
261                 (elmo-folder-list-messages-internal folder visible-only)))
262         (killed-list (elmo-folder-killed-list-internal folder)))
263     (unless (listp list)
264       ;; Use current list.
265       (setq list (elmo-msgdb-list-messages (elmo-folder-msgdb folder))))
266     (if visible-only
267         (elmo-living-messages list killed-list)
268       (if (and in-msgdb killed-list)
269           (elmo-uniq-sorted-list
270            (sort (nconc (elmo-number-set-to-number-list killed-list) list) #'<)
271            #'eq)
272         list))))
273
274 (luna-define-generic elmo-folder-list-messages-internal (folder &optional
275                                                                 visible-only)
276   ;; Return a list of message numbers contained in FOLDER.
277   ;; Return t if the message list is not available.
278   )
279
280 (luna-define-generic elmo-folder-list-flagged (folder flag &optional in-msgdb)
281   "List messages in the FOLDER with FLAG.
282 FLAG is a symbol which is one of the following:
283   `new'        (new messages)
284   `unread'     (unread messages (new messages are included))
285   `answered'   (answered or forwarded)
286   `important'  (marked as important)
287 'sugar' flags:
288   `read'       (not unread)
289   `digest'     (unread + important + other flags)
290   `any'        (digest + answered + other flags)
291 If optional IN-MSGDB is non-nil, retrieve flag information from msgdb.")
292
293 (luna-define-method elmo-folder-list-flagged ((folder elmo-folder) flag
294                                               &optional in-msgdb)
295   (let ((msgs (if in-msgdb
296                   t
297                 (elmo-folder-list-flagged-internal folder flag))))
298     (unless (listp msgs)
299       (setq msgs (elmo-msgdb-list-flagged (elmo-folder-msgdb folder) flag)))
300     (if in-msgdb
301         msgs
302       (elmo-uniq-list
303        (nconc (elmo-folder-list-global-flag-messages folder flag) msgs)
304        #'delq))))
305
306 (luna-define-generic elmo-folder-list-flagged-internal (folder flag)
307   "Return a list of message in the FOLDER with FLAG.
308 Return t if the message list is not available.")
309
310 (luna-define-method elmo-folder-list-flagged-internal ((folder elmo-folder)
311                                                        flag)
312   t)
313
314 (luna-define-generic elmo-folder-list-subfolders (folder &optional one-level)
315   "Returns a list of subfolders contained in FOLDER.
316 If optional argument ONE-LEVEL is non-nil, only children of FOLDER is returned.
317 \(a folder which have children is returned as a list\)
318 Otherwise, all descendent folders are returned.")
319
320 (luna-define-generic elmo-folder-have-subfolder-p (folder)
321   "Return non-nil when FOLDER has subfolders.")
322
323 (luna-define-generic elmo-folder-exists-p (folder)
324   "Returns non-nil when FOLDER exists.")
325
326 (luna-define-generic elmo-folder-creatable-p (folder)
327   "Returns non-nil when FOLDER is creatable.")
328
329 (luna-define-generic elmo-folder-writable-p (folder)
330   "Returns non-nil when FOLDER is writable.")
331
332 (luna-define-generic elmo-folder-persistent-p (folder)
333   "Return non-nil when FOLDER is persistent.")
334
335 (luna-define-generic elmo-folder-create (folder)
336   "Create a FOLDER.")
337
338 (luna-define-generic elmo-message-deletable-p (folder number)
339   "Returns non-nil when the message in the FOLDER with NUMBER is deletable.")
340
341 (luna-define-generic elmo-folder-delete (folder)
342   "Delete FOLDER completely.")
343
344 (luna-define-generic elmo-folder-rename (folder new-name)
345   "Rename FOLDER to NEW-NAME (string).")
346
347 (luna-define-generic elmo-folder-delete-messages (folder numbers)
348   "Delete messages with msgdb entity.
349 FOLDER is the ELMO folder structure.
350 NUMBERS is a list of message numbers to be deleted.
351 It is not recommended to use this function other than internal use.
352 Use `elmo-folder-move-messages' with dst-folder 'null instead.")
353
354 (luna-define-generic elmo-folder-delete-messages-internal (folder numbers)
355   "Delete messages, but no delete msgdb entity.
356 FOLDER is the ELMO folder structure.
357 NUMBERS is a list of message numbers to be deleted.
358 Override this method by each implement of `elmo-folder'.")
359
360 (luna-define-generic elmo-folder-search (folder condition &optional numbers)
361   "Search and return list of message numbers.
362 FOLDER is the ELMO folder structure.
363 CONDITION is a condition structure for searching.
364 If optional argument NUMBERS is specified and is a list of message numbers,
365 messages are searched from the list.")
366
367 (luna-define-generic elmo-message-match-condition (folder number
368                                                           condition
369                                                           numbers)
370   "Return non-nil when the message in the FOLDER with NUMBER is matched.
371 CONDITION is a condition structure for testing.
372 NUMBERS is a list of message numbers,
373 use to be test for \"last\" and \"first\" predicates.")
374
375 (luna-define-generic elmo-folder-msgdb-create (folder numbers flag-table)
376   "Create a message database (implemented in each backends).
377 FOLDER is the ELMO folder structure.
378 NUMBERS is a list of message numbers to create msgdb.
379 FLAG-TABLE is a hashtable of message-id and flag.")
380
381 (luna-define-generic elmo-folder-set-flag (folder numbers flag
382                                                   &optional is-local)
383   "Set messages flag.
384 FOLDER is a ELMO folder structure.
385 NUMBERS is a list of message number to set flag.
386
387 FLAG is a symbol which is one of the following:
388   `unread'    (set the message as unread)
389   `answered'  (set the message as answered)
390   `important' (set the message as important)
391 'sugar' flag:
392   `read'      (remove new and unread flags)
393 If optional IS-LOCAL is non-nil, update only local (not server) status.")
394
395 (luna-define-generic elmo-folder-unset-flag (folder numbers flag
396                                                     &optional is-local)
397   "Unset messages flag.
398 FOLDER is a ELMO folder structure.
399 NUMBERS is a list of message number to unset flag.
400
401 FLAG is a symbol which is one of the following:
402   `unread'    (remove unread and new flag)
403   `answered'  (remove answered flag)
404   `important' (remove important flag)
405 'sugar' flag:
406   `read'      (set unread flag)
407   `all'       (remove all flags)
408 If optional IS-LOCAL is non-nil, update only local (not server) status.")
409
410 (luna-define-generic elmo-message-flag-available-p (folder number flag)
411   "Return non-nil when a message in the FOLDER with NUMBER treats FLAG.")
412
413 (luna-define-generic elmo-folder-next-message-number (folder)
414   "The next message number that will be assigned to a new message.
415 FOLDER is the ELMO folder structure.")
416
417 (luna-define-generic elmo-folder-append-buffer (folder &optional flags
418                                                        number)
419   "Append current buffer as a new message.
420 FOLDER is the destination folder (ELMO folder structure).
421 FLAGS is the flag list for the appended message (list of symbols).
422 If FLAGS contain `read', the message is appended as `not-unread'.
423 If it is nil, the appended message will be treated as `new'.
424 If optional argument NUMBER is specified, the new message number is set
425 \(if possible\).
426 Return nil on failure.")
427
428 (luna-define-generic elmo-folder-append-messages (folder
429                                                   src-folder
430                                                   numbers
431                                                   &optional
432                                                   same-number)
433   "Append messages from folder.
434 FOLDER is the ELMO folder structure.
435 Caller should make sure FOLDER is `writable'.
436 \(Can be checked with `elmo-folder-writable-p'\).
437 SRC-FOLDER is the source ELMO folder structure.
438 NUMBERS is the message numbers to be appended in the SRC-FOLDER.
439 If second optional argument SAME-NUMBER is specified,
440 message number is preserved \(if possible\).
441 Returns a list of message numbers successfully appended.")
442
443 (luna-define-generic elmo-folder-pack-numbers (folder)
444   "Pack message numbers of FOLDER.")
445
446 (luna-define-generic elmo-folder-update-number (folder)
447   "Update number of FOLDER.")
448
449 (luna-define-generic elmo-folder-diff-async (folder)
450   "Get diff of FOLDER asynchronously.")
451
452 (luna-define-generic elmo-folder-expand-msgdb-path (folder)
453   "Expand path for FOLDER.")
454
455 (luna-define-generic elmo-folder-get-primitive-list (folder)
456   "Get primitive folder structure list contained in FOLDER.")
457
458 (luna-define-generic elmo-folder-contains-type (folder type)
459   "Returns t if FOLDER contains TYPE.")
460
461 (luna-define-generic elmo-folder-local-p (folder)
462   "Returns t if FOLDER is local.")
463
464 (luna-define-generic elmo-folder-message-file-p (folder)
465   "Returns t if all messages in the FOLDER are files.")
466
467 ;;; Message methods.
468 (luna-define-generic elmo-message-use-cache-p (folder number)
469   "Returns t if the message in the FOLDER with NUMBER uses cache.")
470
471 (luna-define-generic elmo-message-file-name (folder number)
472   "Return the file name of a message specified by FOLDER and NUMBER.")
473
474 ;;; For archive
475
476 ;;; Use original file
477 (luna-define-generic elmo-folder-message-file-number-p (folder)
478   "Return t if the file name in the FOLDER is the message number.")
479
480 (luna-define-generic elmo-folder-message-file-directory (folder)
481   "Return the directory of the message files of FOLDER.")
482
483 ;;; Use temporary file
484 (luna-define-generic elmo-folder-message-make-temp-file-p (folder)
485   "Return t if the messages in the FOLDER makes local temporary file.")
486
487 (luna-define-generic elmo-folder-message-make-temp-files (folder
488                                                           numbers
489                                                           &optional
490                                                           start-number)
491   "Make a new temporary files from the messages in the FOLDER with NUMBERS.
492 If START-NUMBER is specified, temporary files begin from the number.
493 Otherwise, same number is used for temporary files.
494 Return newly created temporary directory name which contains temporary files.")
495
496 (luna-define-generic elmo-message-file-p (folder number)
497   "Return t if message in the FOLDER with NUMBER is a file.")
498
499 (luna-define-generic elmo-message-flags (folder number)
500   "Return a list of flags.
501 FOLDER is a ELMO folder structure.
502 NUMBER is a number of the message.")
503
504 (defun elmo-message-flags-for-append (folder number &optional message-id)
505   "Return a list of flags for `elmo-folder-append-buffer'.
506 FOLDER is a ELMO folder structure.
507 NUMBER is a number of the message.
508 If optional argument MESSAGES-ID is not specified, get it from current buffer."
509   (let ((this-id (elmo-message-field folder number 'message-id)))
510     (and this-id
511          (string= this-id (or message-id
512                               (elmo-msgdb-get-message-id-from-buffer)))
513          (or (elmo-message-flags folder number)
514              ;; message exists, but no flag.
515              '(read)))))
516
517 (luna-define-method elmo-message-flag-available-p ((folder elmo-folder) number
518                                                    flag)
519   (elmo-msgdb-flag-available-p (elmo-folder-msgdb folder) flag))
520
521 (luna-define-method elmo-message-flags ((folder elmo-folder) number)
522   (elmo-msgdb-flags (elmo-folder-msgdb folder) number))
523
524 (defsubst elmo-message-flagged-p (folder number flag)
525   "Return non-nil if the message is set FLAG.
526 FOLDER is a ELMO folder structure.
527 NUMBER is a message number to test."
528   (let ((cur-flags (elmo-message-flags folder number)))
529     (case flag
530       (read
531        (not (memq 'unread cur-flags)))
532       (t
533        (memq flag cur-flags)))))
534
535 (luna-define-generic elmo-find-fetch-strategy (folder number
536                                                       &optional
537                                                       ignore-cache
538                                                       require-entireness)
539   "Return the message fetching strategy suitable for the message with NUMBER.
540 FOLDER is the ELMO folder structure.
541 If optional argument IGNORE-CACHE is non-nil, existing cache is ignored.
542 If second optional argument REQUIRE-ENTIRENESS is non-nil,
543 ensure that entireness of the returned strategy is entire.
544 Returned value is a elmo-fetch-strategy object.
545 If return value is nil, message should not be nil.")
546
547 (defmacro elmo-make-fetch-strategy (entireness
548                                     &optional
549                                     use-cache
550                                     save-cache
551                                     cache-path)
552   "Make elmo-message-fetching strategy.
553 ENTIRENESS is 'entire or 'section.
554 'entire means fetch message entirely at once.
555 'section means fetch message section by section.
556 If optional USE-CACHE is non-nil, existing cache is used and otherwise,
557 existing cache is thrown away.
558 If SAVE-CACHE is non-nil, fetched message is saved.
559 CACHE-PATH is the cache path to be used as a message cache file."
560   `(vector ,entireness ,use-cache ,save-cache ,cache-path))
561
562 (defmacro elmo-fetch-strategy-entireness (strategy)
563   "Return entireness of STRATEGY."
564   `(aref ,strategy 0))
565
566 (defmacro elmo-fetch-strategy-use-cache (strategy)
567   "Return use-cache of STRATEGY."
568   `(aref ,strategy 1))
569
570 (defmacro elmo-fetch-strategy-save-cache (strategy)
571   "Return save-cache of STRATEGY."
572   `(aref ,strategy 2))
573
574 (defmacro elmo-fetch-strategy-cache-path (strategy)
575   "Return cache-path of STRATEGY."
576   `(aref ,strategy 3))
577
578 (luna-define-method elmo-find-fetch-strategy ((folder elmo-folder) number
579                                               &optional
580                                               ignore-cache
581                                               require-entireness)
582   (let ((entity (elmo-message-entity folder number)))
583     (if (null entity)
584         (elmo-make-fetch-strategy 'entire)
585       (let* ((size (elmo-message-entity-field entity 'size))
586              (message-id (elmo-message-entity-field entity 'message-id))
587              (cache-file (elmo-file-cache-get message-id))
588              (use-cache (elmo-message-use-cache-p folder number)))
589         (if (and (not ignore-cache)
590                  use-cache
591                  (eq (elmo-file-cache-status cache-file) 'entire))
592             ;; Cache exists and use it.
593             (elmo-make-fetch-strategy
594              'entire
595              t                          ; Use cache.
596              use-cache                  ; Save cache.
597              (elmo-file-cache-path cache-file))
598           ;; No cache or ignore-cache.
599           (if (and (not (elmo-folder-local-p folder))
600                    (not require-entireness)
601                    elmo-message-fetch-threshold
602                    (integerp size)
603                    (>= size elmo-message-fetch-threshold)
604                    (or (not elmo-message-fetch-confirm)
605                        (not (prog1
606                                 (y-or-n-p
607                                  (format "Fetch entire message(%dbytes)? "
608                                          size))
609                               (message "")))))
610               ;; Don't fetch message at all.
611               nil
612             ;; Don't use existing cache and fetch entire message at once.
613             (elmo-make-fetch-strategy
614              'entire
615              nil                        ; Don't use cache.
616              use-cache                  ; Save cache.
617              (elmo-file-cache-path cache-file))))))))
618
619 (luna-define-method elmo-folder-list-messages-internal
620   ((folder elmo-folder) &optional visible-only)
621   t)
622
623 (luna-define-generic elmo-message-encache (folder number &optional read)
624   "Encache message in the FOLDER with NUMBER.
625 If READ is non-nil, message is flaged as read.")
626
627 (luna-define-method elmo-message-encache ((folder elmo-folder) number
628                                           &optional read)
629   (let (path)
630     (with-temp-buffer
631       (elmo-message-fetch
632        folder number
633        (elmo-make-fetch-strategy 'entire
634                                  nil ;use-cache
635                                  t   ;save-cache
636                                  (setq path (elmo-file-cache-get-path
637                                              (elmo-message-field
638                                               folder number 'message-id))))
639        (not read)))
640     path))
641
642 (luna-define-generic elmo-message-fetch-bodystructure (folder number strategy)
643   "Fetch bodystructure of the message in FOLDER with NUMBER using STRATEGY.")
644
645 (luna-define-generic elmo-message-fetch (folder number strategy
646                                                 &optional
647                                                 unread
648                                                 section)
649   "Fetch a message into current buffer.
650 FOLDER is the ELMO folder structure.
651 NUMBER is the number of the message in the FOLDER.
652 STRATEGY is the message fetching strategy.
653 If optional argument UNREAD is non-nil, message is not flaged as read.
654 If second optional argument SECTION is specified, only the
655 SECTION of the message is fetched (if possible).
656 Returns non-nil if fetching was succeed.")
657
658 (luna-define-generic elmo-message-fetch-internal (folder number strategy
659                                                          &optional
660                                                          section
661                                                          unread)
662   "Fetch a message into current buffer.
663 FOLDER is the ELMO folder structure.
664 NUMBER is the number of the message in the FOLDER.
665 STRATEGY is the message fetching strategy.
666 If optional argument SECTION is specified, only the SECTION of the message
667 is fetched (if possible).
668 If second optional argument UNREAD is non-nil, message is not flaged as read.
669 Returns non-nil if fetching was succeed.")
670
671 (luna-define-generic elmo-message-fetch-field (folder number field)
672   "Fetch a message field value.
673 FOLDER is the ELMO folder structure.
674 NUMBER is the number of the message in the FOLDER.
675 FIELD is a symbol of the field name.")
676
677 (luna-define-generic elmo-message-folder (folder number)
678   "Get primitive folder of the message.")
679
680 (luna-define-generic elmo-folder-process-crosspost (folder)
681   "Process crosspost for FOLDER.
682 Return a cons cell of (NUMBER-CROSSPOSTS . NEW-FLAG-ALIST).")
683
684 (luna-define-generic elmo-folder-newsgroups (folder)
685   "Return list of newsgroup name of FOLDER.")
686
687 (luna-define-generic elmo-folder-search-requires-msgdb-p (folder condition)
688   "Return non-nil if searching in FOLDER by CONDITION requires msgdb fetch.")
689
690 (defun elmo-folder-search-requires-msgdb-p-internal (folder condition)
691   (if (listp condition)
692       (or (elmo-folder-search-requires-msgdb-p-internal
693            folder (nth 1 condition))
694           (elmo-folder-search-requires-msgdb-p-internal
695            folder (nth 2 condition)))
696     (and (not (string= (elmo-filter-key condition) "last"))
697          (not (string= (elmo-filter-key condition) "first")))))
698
699 (luna-define-method elmo-folder-search-requires-msgdb-p ((folder elmo-folder)
700                                                          condition)
701   (elmo-folder-search-requires-msgdb-p-internal folder condition))
702
703 (luna-define-method elmo-folder-newsgroups ((folder elmo-folder))
704   nil)
705
706 (luna-define-method elmo-folder-open ((folder elmo-folder)
707                                       &optional load-msgdb)
708   (elmo-generic-folder-open folder load-msgdb))
709
710 (defun elmo-generic-folder-open (folder load-msgdb)
711   (let ((inhibit-quit t))
712     (if load-msgdb (elmo-folder-msgdb folder))
713     (elmo-folder-set-killed-list-internal
714      folder
715      (elmo-msgdb-killed-list-load (elmo-folder-msgdb-path folder))))
716   (elmo-folder-open-internal folder))
717
718 (luna-define-method elmo-folder-open-internal ((folder elmo-folder))
719   nil ; default is do nothing.
720   )
721
722 (luna-define-method elmo-folder-check ((folder elmo-folder))
723   nil) ; default is noop.
724
725 (luna-define-method elmo-folder-commit ((folder elmo-folder))
726   (elmo-generic-folder-commit folder))
727
728 (defun elmo-generic-folder-commit (folder)
729   (when (elmo-folder-persistent-p folder)
730     (let ((msgdb (elmo-folder-msgdb-internal folder)))
731       (when msgdb
732         (when (elmo-msgdb-message-modified-p msgdb)
733           (elmo-folder-set-info-max-by-numdb
734            folder
735            (elmo-folder-list-messages folder nil 'in-msgdb)))
736         (elmo-msgdb-save msgdb)))
737     (elmo-msgdb-killed-list-save
738      (elmo-folder-msgdb-path folder)
739      (elmo-folder-killed-list-internal folder))))
740
741 (luna-define-method elmo-folder-close-internal ((folder elmo-folder))
742   ;; do nothing.
743   )
744
745 (luna-define-method elmo-folder-close ((folder elmo-folder))
746   (elmo-generic-folder-close folder)
747   (elmo-folder-close-internal folder))
748
749 (defun elmo-generic-folder-close (folder)
750   (elmo-folder-commit folder)
751   (elmo-folder-set-msgdb-internal folder nil)
752   (elmo-folder-set-killed-list-internal folder nil))
753
754 (luna-define-method elmo-folder-plugged-p ((folder elmo-folder))
755   t) ; default is plugged.
756
757 (luna-define-method elmo-folder-set-plugged ((folder elmo-folder) plugged
758                                              &optional add)
759   nil) ; default is do nothing.
760
761 (luna-define-method elmo-folder-use-flag-p ((folder elmo-folder))
762   nil) ; default is no flag.
763
764 (luna-define-method elmo-folder-persistent-p ((folder elmo-folder))
765   (elmo-folder-persistent-internal folder))
766
767 (luna-define-method elmo-folder-creatable-p ((folder elmo-folder))
768   nil) ; default is not creatable.
769
770 (luna-define-method elmo-folder-writable-p ((folder elmo-folder))
771   nil) ; default is not writable.
772
773 (luna-define-method elmo-folder-delete ((folder elmo-folder))
774   (when (yes-or-no-p (format "Delete msgdb of \"%s\"? "
775                              (elmo-folder-name-internal folder)))
776     (elmo-msgdb-delete-path folder)
777     t))
778
779 (luna-define-method elmo-folder-rename ((folder elmo-folder) new-name)
780   (let* ((new-folder (elmo-make-folder new-name)))
781     (unless (eq (elmo-folder-type-internal folder)
782                 (elmo-folder-type-internal new-folder))
783       (error "Not same folder type"))
784     (if (or (file-exists-p (elmo-folder-msgdb-path new-folder))
785             (elmo-folder-exists-p new-folder))
786         (error "Already exists folder: %s" new-name))
787     (elmo-folder-send folder 'elmo-folder-rename-internal new-folder)
788     (elmo-msgdb-rename-path folder new-folder)))
789
790 (luna-define-method elmo-folder-delete-messages ((folder elmo-folder)
791                                                  numbers)
792   (and (elmo-folder-delete-messages-internal folder numbers)
793        (elmo-folder-detach-messages folder numbers)))
794
795 (luna-define-method elmo-folder-search ((folder elmo-folder)
796                                         condition
797                                         &optional numbers)
798   (let ((numbers (or numbers (elmo-folder-list-messages folder)))
799         (msgdb (elmo-folder-msgdb folder))
800         results)
801     (setq results (elmo-msgdb-search msgdb condition numbers))
802     (if (listp results)
803         results
804       (let ((len (length numbers))
805             matched)
806         (elmo-with-progress-display (> len elmo-display-progress-threshold)
807             (elmo-folder-search len "Searching...")
808           (dolist (number numbers)
809             (let (result)
810               (setq result (elmo-msgdb-match-condition msgdb
811                                                        condition
812                                                        number
813                                                        numbers))
814               (when (elmo-filter-condition-p result)
815                 (setq result (elmo-message-match-condition folder
816                                                            number
817                                                            condition
818                                                            numbers)))
819               (when result
820                 (setq matched (cons number matched))))
821             (elmo-progress-notify 'elmo-folder-search)))
822         (message "Searching...done")
823         (nreverse matched)))))
824
825 (luna-define-method elmo-message-match-condition ((folder elmo-folder)
826                                                   number condition
827                                                   numbers)
828   (let* (cache cache-path
829          (filename (cond
830                     ((elmo-message-file-name folder number))
831                     ((progn
832                        (setq cache (elmo-file-cache-get
833                                     (elmo-message-field folder number
834                                                         'message-id)))
835                        (setq cache-path (elmo-file-cache-path cache))
836                        (and cache-path
837                             (not (elmo-cache-path-section-p cache-path))))
838                      cache-path))))
839     (when (and filename (file-readable-p filename))
840       (with-temp-buffer
841         (set-buffer-multibyte nil)
842         ;;(insert-file-contents-as-binary filename)
843         (elmo-message-fetch folder number
844                             (elmo-make-fetch-strategy 'entire
845                                                       (and cache t)
846                                                       nil
847                                                       cache-path)
848                             'unread)
849         (set-buffer-multibyte default-enable-multibyte-characters)
850         (decode-coding-region (point-min) (point-max)
851                               elmo-mime-display-as-is-coding-system)
852         (elmo-buffer-field-condition-match condition number numbers)))))
853
854 (luna-define-method elmo-folder-pack-numbers ((folder elmo-folder))
855   nil) ; default is noop.
856
857 (luna-define-method elmo-folder-update-number ((folder elmo-folder))
858   nil) ; default is noop.
859
860 (luna-define-method elmo-folder-message-file-p ((folder elmo-folder))
861   nil) ; default is not file.
862
863 (luna-define-method elmo-folder-message-file-number-p ((folder elmo-folder))
864   nil) ; default is not number.
865
866 (luna-define-method elmo-folder-message-make-temp-file-p ((folder elmo-folder))
867   nil) ; default is not make temp file.
868
869 (luna-define-method elmo-message-file-name ((folder elmo-folder)
870                                                    number)
871   nil) ; default is no name.
872
873 (luna-define-method elmo-folder-local-p ((folder elmo-folder))
874   t)   ; default is local.
875
876 (luna-define-method elmo-folder-have-subfolder-p ((folder elmo-folder))
877   t)
878
879 ;; Flag table
880 (luna-define-generic elmo-folder-flag-table (folder &optional if-exists)
881   "Return the flag-table of FOLDER.
882 If optional argument IF-EXISTS is nil, load on demand.
883 \(For internal use only.\)")
884
885 (luna-define-generic elmo-folder-close-flag-table (folder)
886   "Close flag-table of FOLDER.")
887
888 (luna-define-method elmo-folder-flag-table ((folder elmo-folder)
889                                             &optional if-exists)
890   (or (elmo-folder-flag-table-internal folder)
891       (unless if-exists
892         (elmo-folder-set-flag-table-internal
893          folder
894          (elmo-flag-table-load (elmo-folder-msgdb-path folder))))))
895
896 (luna-define-method elmo-folder-close-flag-table ((folder elmo-folder))
897   (elmo-flag-table-save (elmo-folder-msgdb-path folder)
898                         (elmo-folder-flag-table folder))
899   (elmo-folder-set-flag-table-internal folder nil))
900
901 (defun elmo-folder-preserve-flags (folder msgid flags)
902   "Preserve FLAGS into FOLDER for a message that has MSGID."
903   (when (and msgid flags)
904     (let ((flag-table (elmo-folder-flag-table folder 'if-exists))
905           load-now)
906       (when (setq load-now (null flag-table))
907         (setq flag-table (elmo-folder-flag-table folder)))
908       (elmo-flag-table-set flag-table msgid flags)
909       (when load-now
910         (elmo-folder-close-flag-table folder)))))
911
912 ;;; Folder info
913 ;; Folder info is a message number information cache (hashtable)
914 (defsubst elmo-folder-get-info (folder &optional hashtb)
915   "Return FOLDER info from HASHTB (default is `elmo-folder-info-hashtb')."
916   (elmo-get-hash-val (elmo-folder-name-internal folder)
917                      (or hashtb elmo-folder-info-hashtb)))
918
919 (defun elmo-folder-set-info-hashtb (folder max numbers &optional new unread)
920   "Set FOLDER info (means MAX, NUMBERS, NEW and UNREAD)."
921   (let ((info (elmo-folder-get-info folder)))
922     (when info
923       (or new     (setq new     (nth 0 info)))
924       (or unread  (setq unread  (nth 1 info)))
925       (or numbers (setq numbers (nth 2 info)))
926       (or max     (setq max     (nth 3 info))))
927     (elmo-set-hash-val (elmo-folder-name-internal folder)
928                        (list new unread numbers max)
929                        elmo-folder-info-hashtb)))
930
931 (defun elmo-folder-set-info-max-by-numdb (folder numbers)
932   "Set FOLDER info by MSGDB-NUMBER in msgdb."
933   (elmo-folder-set-info-hashtb
934    folder
935    (if numbers (apply #'max numbers) 0)
936    nil ;;(length num-db)
937    ))
938
939 (defun elmo-folder-get-info-max (folder)
940   "Return max number of FODLER from folder info."
941   (nth 3 (elmo-folder-get-info folder)))
942
943 (defun elmo-folder-get-info-length (folder)
944   "Return length of FODLER from folder info."
945   (nth 2 (elmo-folder-get-info folder)))
946
947 (defun elmo-folder-get-info-unread (folder)
948   "Return unread of FODLER from folder info."
949   (nth 1 (elmo-folder-get-info folder)))
950
951 (defun elmo-folder-info-make-hashtb (info-alist hashtb)
952   "Setup folder info hashtable by INFO-ALIST on HASHTB."
953   (let* ((hashtb (or hashtb
954                      (elmo-make-hash (length info-alist)))))
955     (mapcar
956      (lambda (x)
957        (let ((info (cadr x)))
958          (and (intern-soft (car x) hashtb)
959               (elmo-set-hash-val (car x)
960                                  (list (nth 2 info)   ;; new
961                                        (nth 3 info)   ;; unread
962                                        (nth 1 info)   ;; length
963                                        (nth 0 info))  ;; max
964                                  hashtb))))
965      info-alist)
966     (setq elmo-folder-info-hashtb hashtb)))
967
968 (defsubst elmo-diff-new (diff)
969   (car diff))
970
971 (defsubst elmo-diff-unread (diff)
972   (when (consp (cdr diff))
973     (nth 1 diff)))
974
975 (defsubst elmo-diff-all (diff)
976   (if (consp (cdr diff))
977       (nth 2 diff)
978     (cdr diff)))
979
980 (defsubst elmo-strict-folder-diff (folder)
981   "Return folder diff information strictly from FOLDER."
982   (let ((in-db (sort (elmo-folder-list-messages folder nil 'in-msgdb) '<))
983         (in-folder  (elmo-folder-list-messages folder))
984         append-list delete-list diff)
985     (cons (if (equal in-folder in-db)
986               0
987             (setq diff (elmo-list-diff in-folder in-db))
988             (setq append-list (car diff))
989             (setq delete-list (cadr diff))
990             (if append-list
991                 (length append-list)
992               (if delete-list
993                   (- 0 (length delete-list))
994                 0)))
995           (length in-folder))))
996
997 (luna-define-method elmo-folder-diff ((folder elmo-folder))
998   (elmo-generic-folder-diff folder))
999
1000 (defun elmo-generic-folder-diff (folder)
1001   (if (elmo-string-match-member (elmo-folder-name-internal folder)
1002                                 elmo-strict-diff-folder-list)
1003       (elmo-strict-folder-diff folder)
1004     (let ((cached-in-db-max (elmo-folder-get-info-max folder))
1005           (in-folder (elmo-folder-status folder))
1006           (in-db t)
1007           unsync messages
1008           in-db-max)
1009       (if (not cached-in-db-max)
1010           (let ((number-list (elmo-folder-list-messages folder
1011                                                         nil 'in-msgdb)))
1012             ;; No info-cache.
1013             (setq in-db number-list)
1014             (setq in-db-max (if in-db (apply #'max in-db) 0))
1015             (elmo-folder-set-info-hashtb folder in-db-max nil))
1016         (setq in-db-max cached-in-db-max))
1017       (setq unsync (if (and in-db (car in-folder))
1018                        (- (car in-folder) in-db-max)
1019                      (if (and in-folder (null in-db))
1020                          (cdr in-folder)
1021                        (car in-folder))))
1022       (setq messages (cdr in-folder))
1023       (if (and unsync messages (> unsync messages))
1024           (setq unsync messages))
1025       (cons (or unsync 0) (or messages 0)))))
1026
1027 (defvar elmo-folder-diff-async-callback nil)
1028 (defvar elmo-folder-diff-async-callback-data nil)
1029
1030 (luna-define-method elmo-folder-diff-async ((folder elmo-folder))
1031   (and elmo-folder-diff-async-callback
1032        (funcall elmo-folder-diff-async-callback
1033                 folder
1034                 (elmo-folder-diff folder))))
1035
1036 (luna-define-method elmo-folder-get-primitive-list ((folder elmo-folder))
1037   (list folder))
1038
1039 (luna-define-method elmo-folder-contains-type ((folder elmo-folder) type)
1040   (eq (elmo-folder-type-internal folder) type))
1041
1042 (luna-define-method elmo-folder-next-message-number ((folder elmo-folder))
1043   (+ 1 (elmo-max-of-list (or (elmo-folder-list-messages folder)
1044                              '(0)))))
1045
1046 (luna-define-method elmo-folder-append-messages ((folder elmo-folder)
1047                                                  src-folder
1048                                                  numbers
1049                                                  &optional
1050                                                  same-number)
1051   (elmo-generic-folder-append-messages folder src-folder numbers
1052                                        same-number))
1053
1054 (defun elmo-generic-folder-append-messages (folder src-folder numbers
1055                                                    same-number)
1056   (let ((src-msgdb-exists (not (zerop (elmo-folder-length src-folder))))
1057         unseen table
1058         succeed-numbers failure cache id)
1059     (setq table (elmo-folder-flag-table folder))
1060     (with-temp-buffer
1061       (set-buffer-multibyte nil)
1062       (while numbers
1063         (setq failure nil
1064               id (and src-msgdb-exists
1065                       (elmo-message-field src-folder (car numbers)
1066                                           'message-id)))
1067         (condition-case nil
1068             (setq cache (elmo-file-cache-get id)
1069                   failure
1070                   (not
1071                    (and
1072                     (elmo-message-fetch
1073                      src-folder (car numbers)
1074                      (if (elmo-folder-plugged-p src-folder)
1075                          (elmo-make-fetch-strategy
1076                           'entire 'maybe nil
1077                           (and cache (elmo-file-cache-path cache)))
1078                        (or (and elmo-enable-disconnected-operation
1079                                 cache
1080                                 (eq (elmo-file-cache-status cache) 'entire)
1081                                 (elmo-make-fetch-strategy
1082                                  'entire t nil
1083                                  (elmo-file-cache-path cache)))
1084                            (error "Unplugged")))
1085                      'unread)
1086                     (> (buffer-size) 0)
1087                     (elmo-folder-append-buffer
1088                      folder
1089                      (elmo-message-flags-for-append src-folder (car numbers))
1090                      (if same-number (car numbers))))))
1091           (error (setq failure t)))
1092         ;; FETCH & APPEND finished
1093         (unless failure
1094           (setq succeed-numbers (cons (car numbers) succeed-numbers)))
1095         (elmo-progress-notify 'elmo-folder-move-messages)
1096         (setq numbers (cdr numbers)))
1097       (when (elmo-folder-persistent-p folder)
1098         (elmo-folder-close-flag-table folder))
1099       succeed-numbers)))
1100
1101 ;; Arguments should be reduced.
1102 (defun elmo-folder-move-messages (src-folder msgs dst-folder
1103                                              &optional
1104                                              no-delete
1105                                              same-number)
1106   (save-excursion
1107     (let* ((messages msgs)
1108            (elmo-inhibit-display-retrieval-progress t)
1109            (len (length msgs))
1110            succeeds i result)
1111       (if (eq dst-folder 'null)
1112           (setq succeeds messages)
1113         (unless (elmo-folder-writable-p dst-folder)
1114           (error "move: %d is not writable"
1115                  (elmo-folder-name-internal dst-folder)))
1116         (when messages
1117           ;; src is already opened.
1118           (elmo-folder-open-internal dst-folder)
1119           (unless (setq succeeds (elmo-folder-append-messages dst-folder
1120                                                               src-folder
1121                                                               messages
1122                                                               same-number))
1123             (error "move: append message to %s failed"
1124                    (elmo-folder-name-internal dst-folder)))
1125           (elmo-folder-close dst-folder)))
1126       (if (and (not no-delete) succeeds)
1127           (progn
1128             (if (elmo-folder-delete-messages src-folder succeeds)
1129                 (progn
1130                   (elmo-global-flag-detach-messages
1131                    src-folder succeeds (eq dst-folder 'null))
1132                   (setq result t))
1133               (message "move: delete messages from %s failed."
1134                        (elmo-folder-name-internal src-folder))
1135               (setq result nil))
1136             result)
1137         (if no-delete
1138             (progn
1139               ;; (message "Copying messages...done")
1140               t)
1141           (if (eq len 0)
1142               (message "No message was moved.")
1143             (message "Moving messages failed.")
1144             nil ; failure
1145             ))))))
1146
1147 (defun elmo-folder-msgdb-path (folder)
1148   "Return the msgdb path for FOLDER."
1149   (or (elmo-folder-path-internal folder)
1150       (elmo-folder-set-path-internal
1151        folder
1152        (if (null elmo-msgdb-path-encode-threshold)
1153            (elmo-folder-expand-msgdb-path folder)
1154          (let* ((path (directory-file-name
1155                        (elmo-folder-expand-msgdb-path folder)))
1156                 (dirname (file-name-nondirectory path)))
1157            (if (<= (length dirname) elmo-msgdb-path-encode-threshold)
1158                path
1159              (require 'md5)
1160              (setq dirname (md5 dirname))
1161              (when (> (length dirname) elmo-msgdb-path-encode-threshold)
1162                (error "Cannot shrink msgdb path for `%s'"
1163                       (elmo-folder-name-internal folder)))
1164              (expand-file-name dirname (file-name-directory path))))))))
1165
1166 (luna-define-generic elmo-message-cached-p (folder number)
1167   "Return non-nil if the message is cached.")
1168
1169 (luna-define-method elmo-message-cached-p ((folder elmo-folder) number)
1170   (elmo-message-flagged-p folder number 'cached))
1171
1172 (defun elmo-message-accessible-p (folder number)
1173   "Get accessibility of the message.
1174 Return non-nil when message is accessible."
1175   (or (elmo-folder-plugged-p folder)
1176       (elmo-folder-local-p folder)
1177       (< number 0) ; in dop spool
1178       (elmo-message-cached-p folder number)))
1179
1180 (luna-define-generic elmo-message-set-cached (folder number cached)
1181   "Set cache status of the message in the msgdb.
1182 FOLDER is the ELMO folder structure.
1183 NUMBER is a number of the message.
1184 If CACHED is t, message is set as cached.")
1185
1186 (luna-define-method elmo-message-set-cached ((folder elmo-folder)
1187                                              number cached)
1188   (if cached
1189       (elmo-msgdb-set-flag (elmo-folder-msgdb folder) number 'cached)
1190     (elmo-msgdb-unset-flag (elmo-folder-msgdb folder) number 'cached))
1191   (elmo-emit-signal 'cache-changed folder number))
1192
1193 (defun elmo-message-copy-entity (entity)
1194   (elmo-msgdb-copy-message-entity (elmo-message-entity-handler entity)
1195                                   entity))
1196
1197 (luna-define-generic elmo-message-number (folder message-id)
1198   "Get message number from MSGDB which corresponds to MESSAGE-ID.")
1199
1200 (luna-define-method elmo-message-number ((folder elmo-folder) message-id)
1201   (elmo-msgdb-message-number (elmo-folder-msgdb folder) message-id))
1202
1203 (luna-define-generic elmo-message-entity (folder key)
1204   "Return the message-entity structure which matches to the KEY.
1205 KEY is a number or a string.
1206 A number is for message number in the FOLDER.
1207 A string is for message-id of the message.")
1208
1209 (luna-define-method elmo-message-entity ((folder elmo-folder) key)
1210   (elmo-msgdb-message-entity (elmo-folder-msgdb folder) key))
1211
1212 (luna-define-generic elmo-message-entity-parent (folder entity)
1213   "Return the parent message-entity structure in the FOLDER.
1214 ENTITY is the message-entity to get the parent.")
1215
1216 (luna-define-method elmo-message-entity-parent ((folder elmo-folder) entity)
1217   (elmo-msgdb-get-parent-entity entity (elmo-folder-msgdb folder)))
1218
1219 (put 'elmo-folder-do-each-message-entity 'lisp-indent-function '1)
1220 (def-edebug-spec elmo-folder-do-each-message-entity
1221   ((symbolp form &rest form) &rest form))
1222
1223 (defsubst elmo-folder-list-message-entities (folder)
1224   ;; List all message entities in the FOLDER.
1225   (mapcar
1226    (lambda (number) (elmo-message-entity folder number))
1227    (elmo-folder-list-messages folder nil t))) ; XXX killed-list is not used.
1228
1229 (defmacro elmo-folder-do-each-message-entity (spec &rest form)
1230   "Iterator for message entity in the folder.
1231 \(elmo-folder-do-each-message-entity \(entity folder\)
1232  ... do the process using entity...
1233 \)"
1234   `(dolist (,(car spec) (elmo-folder-list-message-entities ,(car (cdr spec))))
1235      ,@form))
1236
1237 (luna-define-generic elmo-folder-count-flags (folder)
1238   "Count flagged message number in the msgdb of the FOLDER.
1239 Return alist of flag and numbers.
1240 Example:
1241 \(\(new . 10\)
1242   \(unread . 20\)
1243   \(answered . 3\)\)")
1244
1245 (luna-define-method elmo-folder-count-flags ((folder elmo-folder))
1246   (elmo-msgdb-flag-count (elmo-folder-msgdb folder)))
1247
1248 (defun elmo-message-set-flag (folder number flag &optional is-local)
1249   "Set message flag.
1250 FOLDER is a ELMO folder structure.
1251 NUMBER is a message number to set flag.
1252
1253 FLAG is a symbol which is one of the following:
1254   `unread'    (set the message as unread)
1255   `answered'  (set the message as answered)
1256   `important' (set the message as important)
1257 'sugar' flag:
1258   `read'      (remove new and unread flags)
1259 If optional IS-LOCAL is non-nil, update only local (not server) status."
1260   ;; XXX Transitional implementation.
1261   (elmo-folder-set-flag folder (list number) flag is-local))
1262
1263 (defun elmo-message-unset-flag (folder number flag &optional is-local)
1264   "Unset message flag.
1265 FOLDER is a ELMO folder structure.
1266 NUMBER is a message number to set flag.
1267
1268 FLAG is a symbol which is one of the following:
1269   `unread'    (remove unread and new flag)
1270   `answered'  (remove answered flag)
1271   `important' (remove important flag)
1272 'sugar' flag:
1273   `read'      (set unread flag)
1274 If optional IS-LOCAL is non-nil, update only local (not server) status."
1275   ;; XXX Transitional implementation.
1276   (elmo-folder-unset-flag folder (list number) flag is-local))
1277
1278 (luna-define-generic elmo-message-field (folder number field &optional type)
1279   "Get message field value in the msgdb.
1280 FOLDER is the ELMO folder structure.
1281 NUMBER is a number of the message.
1282 FIELD is a symbol of the field.
1283 If optional argument TYPE is specified, return converted value.")
1284
1285 (luna-define-method elmo-message-field ((folder elmo-folder)
1286                                         number field &optional type)
1287   (elmo-msgdb-message-field (elmo-folder-msgdb folder) number field type))
1288
1289 (luna-define-generic elmo-message-set-field (folder number field value)
1290   "Set message field value in the msgdb.
1291 FOLDER is the ELMO folder structure.
1292 NUMBER is a number of the message.
1293 FIELD is a symbol of the field.
1294 VALUE is a value to set.")
1295
1296 (luna-define-method elmo-message-set-field ((folder elmo-folder) number
1297                                             field value)
1298   (elmo-message-entity-set-field (elmo-message-entity folder number)
1299                                  field value))
1300
1301 (luna-define-method elmo-message-use-cache-p ((folder elmo-folder) number)
1302   nil) ; default is not use cache.
1303
1304 (luna-define-method elmo-message-folder ((folder elmo-folder) number)
1305   folder) ; default is folder
1306
1307 (luna-define-method elmo-folder-set-flag ((folder elmo-folder)
1308                                           numbers
1309                                           flag
1310                                           &optional is-local)
1311   (when (elmo-folder-msgdb-internal folder)
1312     (dolist (number numbers)
1313       (let ((old-flags (elmo-message-flags folder number)))
1314         (when (elmo-global-flag-p flag)
1315           (let ((message-id (elmo-message-field folder number 'message-id)))
1316             (elmo-global-flag-set flag folder number message-id)))
1317         (elmo-msgdb-set-flag (elmo-folder-msgdb folder) number flag)
1318         (elmo-emit-signal 'flag-changing
1319                           folder
1320                           number
1321                           old-flags
1322                           (elmo-message-flags folder number))))
1323     (elmo-emit-signal 'flag-changed folder numbers)))
1324
1325 (defun elmo-message-has-global-flag-p (folder number)
1326   "Return non-nil when the message in the FOLDER with NUMBER has global flag."
1327   (let ((flags (elmo-message-flags folder number))
1328         result)
1329     (while flags
1330       (when (and (elmo-global-flag-p (car flags))
1331                  (not (memq (car flags) '(answered unread cached))))
1332         (setq result t
1333               flags nil))
1334       (setq flags (cdr flags)))
1335     result))
1336
1337 (defun elmo-message-set-global-flags (folder number flags &optional local)
1338   "Set global flags of the message in the FOLDER with NUMBER as FLAGS.
1339 If Optional LOCAL is non-nil, don't update server flag."
1340   (dolist (flag flags)
1341     (unless (elmo-global-flag-p flag)
1342       (error "Not a global flag")))
1343   (let ((old-flags (elmo-get-global-flags (elmo-message-flags folder number))))
1344     (dolist (flag flags)
1345       (unless (memq flag old-flags)
1346         (elmo-message-set-flag folder number flag local)))
1347     (dolist (flag old-flags)
1348       (unless (memq flag flags)
1349         (elmo-message-unset-flag folder number flag local)))))
1350
1351 (luna-define-method elmo-folder-unset-flag ((folder elmo-folder)
1352                                             numbers
1353                                             flag
1354                                             &optional is-local)
1355   (when (elmo-folder-msgdb-internal folder)
1356     (dolist (number numbers)
1357       (let ((old-flags (elmo-message-flags folder number)))
1358         (when (elmo-global-flag-p flag)
1359           (elmo-global-flag-detach flag folder number 'always))
1360         (elmo-msgdb-unset-flag (elmo-folder-msgdb folder) number flag)
1361         (elmo-emit-signal 'flag-changing
1362                           folder
1363                           number
1364                           old-flags
1365                           (elmo-message-flags folder number))))
1366     (elmo-emit-signal 'flag-changed folder numbers)))
1367
1368 (luna-define-method elmo-folder-process-crosspost ((folder elmo-folder))
1369   ;; Do nothing.
1370   )
1371
1372 ;;(luna-define-generic elmo-folder-append-message-entity (folder entity
1373 ;;                                                             &optional
1374 ;;                                                             flag-table)
1375 ;;  "Append ENTITY to the folder.")
1376
1377 (defun elmo-msgdb-merge (folder msgdb-merge)
1378   "Return a list of messages which have duplicated message-id."
1379   (let (msgdb duplicates)
1380     (setq msgdb (or (elmo-folder-msgdb-internal folder)
1381                     (elmo-make-msgdb (elmo-folder-msgdb-path folder))))
1382     (setq duplicates (elmo-msgdb-append msgdb msgdb-merge))
1383     (elmo-folder-set-msgdb-internal folder msgdb)
1384     duplicates))
1385
1386 (defsubst elmo-folder-append-msgdb (folder append-msgdb)
1387   (if append-msgdb
1388       (let ((duplicates (elmo-msgdb-merge folder append-msgdb)))
1389         (cond ((eq (elmo-folder-process-duplicates-internal folder)
1390                    'hide)
1391                ;; Let duplicates be a temporary killed message.
1392                (elmo-folder-kill-messages folder duplicates)
1393                ;; Should be flag as read.
1394                (elmo-folder-unset-flag folder duplicates 'unread))
1395               ((eq (elmo-folder-process-duplicates-internal folder)
1396                    'read)
1397                ;; Flag as read duplicates.
1398                (elmo-folder-unset-flag folder duplicates 'unread))
1399               (t
1400                ;; Do nothing.
1401                (setq duplicates nil)))
1402         (length duplicates))
1403     0))
1404
1405 (defun elmo-folder-confirm-appends (appends)
1406   (let ((len (length appends))
1407         in)
1408     (if (and elmo-folder-update-threshold
1409              (> len elmo-folder-update-threshold)
1410              elmo-folder-update-confirm)
1411         (if (y-or-n-p (format "Too many messages(%d).  Update all? " len))
1412             appends
1413           (setq in elmo-folder-update-threshold)
1414           (catch 'end
1415             (while t
1416               (setq in (read-from-minibuffer "Update number: "
1417                                              (int-to-string in))
1418                     in (string-to-int in))
1419               (if (< len in)
1420                   (throw 'end len))
1421               (if (y-or-n-p (format
1422                              "%d messages are killed (not appeared). OK? "
1423                              (max (- len in) 0)))
1424                   (throw 'end in))))
1425           (nthcdr (max (- len in) 0) appends))
1426       (if (and elmo-folder-update-threshold
1427                (> len elmo-folder-update-threshold)
1428                (not elmo-folder-update-confirm))
1429           (nthcdr (max (- len elmo-folder-update-threshold) 0) appends)
1430         appends))))
1431
1432 (luna-define-method elmo-message-fetch-bodystructure ((folder elmo-folder)
1433                                                       number strategy)
1434   nil)
1435
1436 (defun elmo-message-fetch-string (folder number strategy
1437                                          &optional
1438                                          unread
1439                                          section)
1440   (with-temp-buffer
1441     (set-buffer-multibyte nil)
1442     (when (elmo-message-fetch folder number strategy unread section)
1443       (buffer-string))))
1444
1445 (luna-define-method elmo-message-fetch ((folder elmo-folder)
1446                                         number strategy
1447                                         &optional
1448                                         unread
1449                                         section)
1450   (erase-buffer)
1451   (let ((cache-path (elmo-fetch-strategy-cache-path strategy))
1452         (method-priorities
1453          (cond ((eq (elmo-fetch-strategy-use-cache strategy) 'maybe)
1454                 '(entity cache))
1455                ((elmo-fetch-strategy-use-cache strategy)
1456                 '(cache entity))
1457                (t
1458                 '(entity))))
1459         result err updated-server-flag)
1460     (while (and method-priorities
1461                 (not result))
1462       (setq result
1463             (case (car method-priorities)
1464               (cache
1465                (elmo-file-cache-load cache-path section))
1466               (entity
1467                (when (condition-case error
1468                          (elmo-message-fetch-internal folder number
1469                                                       strategy
1470                                                       section
1471                                                       unread)
1472                        (error (setq err error) nil))
1473                  (setq updated-server-flag t)
1474                  (when (and (elmo-fetch-strategy-save-cache strategy)
1475                             cache-path)
1476                    (elmo-file-cache-save cache-path section))
1477                  t)))
1478             method-priorities (cdr method-priorities)))
1479     (if result
1480         (when (and (not unread)
1481                    (elmo-message-flagged-p folder number 'unread))
1482           (elmo-message-unset-flag folder number 'unread updated-server-flag))
1483       (when err
1484         (signal (car err) (cdr err))))
1485     result))
1486
1487 (defun elmo-folder-kill-messages-range (folder beg end)
1488   (elmo-folder-set-killed-list-internal
1489    folder
1490    (nconc
1491     (elmo-folder-killed-list-internal folder)
1492     (list (cons beg end)))))
1493
1494 (defun elmo-folder-kill-messages (folder numbers)
1495   "Kill(hide) messages in the FOLDER with NUMBERS."
1496   (elmo-folder-set-killed-list-internal
1497    folder
1498    (elmo-number-set-append-list
1499     (elmo-folder-killed-list-internal folder)
1500     numbers))
1501   (elmo-folder-unset-flag folder numbers 'all 'local-only))
1502
1503 (luna-define-method elmo-folder-clear ((folder elmo-folder)
1504                                        &optional keep-killed)
1505   (unless keep-killed
1506     (elmo-folder-set-killed-list-internal folder nil))
1507   (if (eq elmo-msgdb-convert-type 'sync)
1508       (elmo-folder-set-msgdb-internal
1509        folder
1510        (elmo-make-msgdb (elmo-folder-msgdb-path folder)))
1511     (elmo-msgdb-clear (elmo-folder-msgdb folder))))
1512
1513 (luna-define-generic elmo-folder-synchronize (folder
1514                                               &optional
1515                                               disable-killed
1516                                               ignore-msgdb
1517                                               no-check
1518                                               mask)
1519   "Synchronize the folder data to the newest status.
1520 FOLDER is the ELMO folder structure.
1521
1522 If optional DISABLE-KILLED is non-nil, killed messages are also synchronized.
1523 If optional IGNORE-MSGDB is non-nil, current msgdb is thrown away except
1524 flag status.
1525 If NO-CHECK is non-nil, rechecking folder is skipped.
1526 If optional argument MASK is specified and is a list of message numbers,
1527 synchronize messages only which are contained the list.
1528 Return amount of cross-posted messages.
1529 If update process is interrupted, return nil.")
1530
1531 (luna-define-method elmo-folder-synchronize ((folder elmo-folder)
1532                                              &optional
1533                                              disable-killed
1534                                              ignore-msgdb
1535                                              no-check
1536                                              mask)
1537   (let ((old-msgdb (elmo-folder-msgdb folder))
1538         (killed-list (elmo-folder-killed-list-internal folder))
1539         (flag-table (elmo-flag-table-load (elmo-folder-msgdb-path folder)))
1540         (before-append t))
1541     (when ignore-msgdb
1542       (elmo-msgdb-flag-table (elmo-folder-msgdb folder) flag-table)
1543       (elmo-folder-clear folder (not disable-killed)))
1544     (unless no-check (elmo-folder-check folder))
1545     (condition-case nil
1546         (let ((killed-list (elmo-folder-killed-list-internal folder))
1547               diff-new diff-del
1548               delete-list new-list new-msgdb crossed)
1549           (message "Checking folder diff...")
1550           (elmo-set-list
1551            '(diff-new diff-del)
1552            (elmo-list-diff (elmo-folder-list-messages folder)
1553                            (elmo-folder-list-messages folder nil 'in-msgdb)))
1554           (when diff-new
1555             (setq diff-new (sort diff-new #'<))
1556             (unless disable-killed
1557               (setq diff-new (elmo-living-messages diff-new killed-list)))
1558             (when (and mask (not ignore-msgdb))
1559               (setq diff-new (elmo-list-filter mask diff-new))))
1560           (message "Checking folder diff...done")
1561           (setq new-list (elmo-folder-confirm-appends diff-new))
1562           ;; Append to killed list as (MIN-OF-DISAPPEARED . MAX-OF-DISAPPEARED)
1563           (when (not (eq (length diff-new)
1564                          (length new-list)))
1565             (let* ((diff (elmo-list-diff diff-new new-list))
1566                    (disappeared (sort (car diff) #'<)))
1567               (when disappeared
1568                 (elmo-folder-kill-messages-range folder
1569                                                  (car disappeared)
1570                                                  (elmo-last disappeared)))))
1571           (setq delete-list diff-del)
1572           (if (and (null diff-new) (null diff-del))
1573               (progn
1574                 (elmo-folder-update-number folder)
1575                 (elmo-folder-process-crosspost folder)
1576                 0)                      ; `0' means no updates.
1577             (when delete-list
1578               (elmo-folder-detach-messages folder delete-list))
1579             (when new-list
1580               (elmo-msgdb-out-of-date-messages (elmo-folder-msgdb folder))
1581               (setq new-msgdb (elmo-folder-msgdb-create
1582                                folder new-list flag-table))
1583               ;; Clear flag-table
1584               (if (elmo-folder-persistent-p folder)
1585                   (elmo-flag-table-save (elmo-folder-msgdb-path folder)
1586                                         nil))
1587               (setq before-append nil)
1588               (setq crossed (elmo-folder-append-msgdb folder new-msgdb))
1589               ;; process crosspost.
1590               ;; Return a cons cell of (NUMBER-CROSSPOSTS . NEW-FLAG-ALIST).
1591               (elmo-folder-process-crosspost folder))
1592             ;; return value.
1593             (or crossed 0)))
1594       (quit
1595        ;; Resume to the original status.
1596        (if before-append (elmo-folder-set-msgdb-internal folder old-msgdb))
1597        (elmo-folder-set-killed-list-internal folder killed-list)
1598        nil))))
1599
1600 (luna-define-generic elmo-folder-detach-messages (folder numbers)
1601   "Remove messages with NUMBERS from MSGDB.")
1602
1603 (luna-define-method elmo-folder-detach-messages ((folder elmo-folder)
1604                                                  numbers)
1605   (when (elmo-msgdb-delete-messages (elmo-folder-msgdb folder) numbers)
1606     ;; Remove NUMBERS from killed message list.
1607     (elmo-folder-set-killed-list-internal
1608      folder
1609      (elmo-number-set-delete-list
1610       (elmo-folder-killed-list-internal folder)
1611       numbers))
1612     t))
1613
1614 (luna-define-generic elmo-folder-length (folder)
1615   "Return number of messages in the FOLDER.")
1616
1617 (luna-define-method elmo-folder-length ((folder elmo-folder))
1618   (if (elmo-folder-msgdb-internal folder)
1619       (elmo-msgdb-length (elmo-folder-msgdb folder))
1620     0))
1621
1622 (defun elmo-folder-msgdb-load (folder &optional silent)
1623   (unless silent
1624     (message "Loading msgdb for %s..." (elmo-folder-name-internal folder)))
1625   (let ((msgdb (elmo-load-msgdb (elmo-folder-msgdb-path folder)
1626                                 (elmo-folder-mime-charset-internal folder))))
1627     (elmo-folder-set-info-max-by-numdb
1628      folder
1629      (elmo-msgdb-list-messages msgdb))
1630     (unless silent
1631       (message "Loading msgdb for %s...done"
1632                (elmo-folder-name-internal folder)))
1633     msgdb))
1634
1635 (defun elmo-msgdb-delete-path (folder)
1636   (let ((path (elmo-folder-msgdb-path folder)))
1637     (if (file-directory-p path)
1638         (elmo-delete-directory path t))))
1639
1640 (defun elmo-msgdb-rename-path (old-folder new-folder)
1641   (let* ((old (directory-file-name (elmo-folder-msgdb-path old-folder)))
1642          (new (directory-file-name (elmo-folder-msgdb-path new-folder)))
1643          (new-dir (directory-file-name (file-name-directory new))))
1644     (if (not (file-directory-p old))
1645         ()
1646       (if (file-exists-p new)
1647           (error "Already exists directory: %s" new)
1648         (if (not (file-exists-p new-dir))
1649             (elmo-make-directory new-dir))
1650         (rename-file old new)))))
1651
1652 (defun elmo-setup-subscribed-newsgroups (groups)
1653   "Setup subscribed newsgroups.
1654 GROUPS is a list of newsgroup name string.
1655 Return a hashtable for newsgroups."
1656   (let ((hashtb (or elmo-newsgroups-hashtb
1657                     (setq elmo-newsgroups-hashtb
1658                           (elmo-make-hash (length groups))))))
1659     (dolist (group groups)
1660       (or (elmo-get-hash-val group hashtb)
1661           (elmo-set-hash-val group nil hashtb)))
1662     (setq elmo-newsgroups-hashtb hashtb)))
1663
1664 (defvar elmo-crosspost-message-alist-modified nil)
1665 (defun elmo-crosspost-message-alist-load ()
1666   "Load crosspost message alist."
1667   (setq elmo-crosspost-message-alist (elmo-crosspost-alist-load))
1668   (setq elmo-crosspost-message-alist-modified nil))
1669
1670 (defun elmo-crosspost-message-alist-save ()
1671   "Save crosspost message alist."
1672   (when elmo-crosspost-message-alist-modified
1673     (let ((alist elmo-crosspost-message-alist)
1674           newsgroups)
1675       (while alist
1676         (setq newsgroups
1677               (elmo-delete-if
1678                '(lambda (x)
1679                   (not (intern-soft x elmo-newsgroups-hashtb)))
1680                (nth 1 (car alist))))
1681         (if newsgroups
1682             (setcar (cdar alist) newsgroups)
1683           (setq elmo-crosspost-message-alist
1684                 (delete (car alist) elmo-crosspost-message-alist)))
1685         (setq alist (cdr alist)))
1686       (elmo-crosspost-alist-save elmo-crosspost-message-alist)
1687       (setq elmo-crosspost-message-alist-modified nil))))
1688
1689 (defun elmo-folder-make-temporary-directory (folder)
1690   ;; Make a temporary directory for FOLDER.
1691   (let ((temp-dir (make-temp-name
1692                    (concat
1693                     (file-name-as-directory (elmo-folder-msgdb-path folder))
1694                     "elmo"))))
1695     (elmo-make-directory temp-dir)
1696     temp-dir))
1697
1698 ;;;
1699 (defun elmo-init ()
1700   "Initialize ELMO module."
1701   (elmo-crosspost-message-alist-load)
1702   (elmo-resque-obsolete-variables)
1703   (elmo-dop-queue-load)
1704   (run-hooks 'elmo-init-hook))
1705
1706 (defun elmo-quit ()
1707   "Quit and cleanup ELMO."
1708   (elmo-crosspost-message-alist-save)
1709   (elmo-dop-queue-save)
1710   ;; Not implemented yet.
1711   (let ((types elmo-folder-type-alist)
1712         class)
1713     (while types
1714       (setq class
1715             (luna-find-class
1716              (intern (format "elmo-%s-folder"
1717                              (symbol-name (cdr (car types)))))))
1718       ;; Call all folder's `elmo-quit' method.
1719       (if class
1720           (dolist (func (luna-class-find-functions class 'elmo-quit))
1721             (funcall func nil)))
1722       (setq types (cdr types)))))
1723
1724 (luna-define-method elmo-folder-rename-internal ((folder elmo-folder)
1725                                                  new-folder)
1726   (error "Cannot rename %s folder"
1727          (symbol-name (elmo-folder-type-internal folder))))
1728
1729 ;;; Define folders.
1730 (elmo-define-folder ?% 'imap4)
1731 (elmo-define-folder ?-  'nntp)
1732 (elmo-define-folder ?\+ 'localdir)
1733 (elmo-define-folder ?\* 'multi)
1734 (elmo-define-folder ?\/ 'filter)
1735 (elmo-define-folder ?\$ 'archive)
1736 (elmo-define-folder ?&  'pop3)
1737 (elmo-define-folder ?=  'localnews)
1738 (elmo-define-folder ?|  'pipe)
1739 (elmo-define-folder ?.  'maildir)
1740 (elmo-define-folder ?'  'internal)
1741 (elmo-define-folder ?\[  'nmz)
1742 (elmo-define-folder ?@  'shimbun)
1743
1744 ;;; Obsolete variables.
1745 (elmo-define-obsolete-variable 'elmo-default-imap4-mailbox
1746                                'elmo-imap4-default-mailbox)
1747 (elmo-define-obsolete-variable 'elmo-default-imap4-server
1748                                'elmo-imap4-default-server)
1749 (elmo-define-obsolete-variable 'elmo-default-imap4-authenticate-type
1750                                'elmo-imap4-default-authenticate-type)
1751 (elmo-define-obsolete-variable 'elmo-default-imap4-user
1752                                'elmo-imap4-default-user)
1753 (elmo-define-obsolete-variable 'elmo-default-imap4-port
1754                                'elmo-imap4-default-port)
1755 (elmo-define-obsolete-variable 'elmo-default-imap4-stream-type
1756                                'elmo-imap4-default-stream-type)
1757 (elmo-define-obsolete-variable 'elmo-default-nntp-server
1758                                'elmo-nntp-default-server)
1759 (elmo-define-obsolete-variable 'elmo-default-nntp-user
1760                                'elmo-nntp-default-user)
1761 (elmo-define-obsolete-variable 'elmo-default-nntp-port
1762                                'elmo-nntp-default-port)
1763 (elmo-define-obsolete-variable 'elmo-default-nntp-stream-type
1764                                'elmo-nntp-default-stream-type)
1765 (elmo-define-obsolete-variable 'elmo-default-pop3-server
1766                                'elmo-pop3-default-server)
1767 (elmo-define-obsolete-variable 'elmo-default-pop3-user
1768                                'elmo-pop3-default-user)
1769 (elmo-define-obsolete-variable 'elmo-default-pop3-authenticate-type
1770                                'elmo-pop3-default-authenticate-type)
1771 (elmo-define-obsolete-variable 'elmo-default-pop3-port
1772                                'elmo-pop3-default-port)
1773 (elmo-define-obsolete-variable 'elmo-default-pop3-stream-type
1774                                'elmo-pop3-default-stream-type)
1775 (elmo-define-obsolete-variable 'elmo-cache-dirname
1776                                'elmo-cache-directory)
1777 (elmo-define-obsolete-variable 'elmo-msgdb-dir
1778                                'elmo-msgdb-directory)
1779 (elmo-define-obsolete-variable 'elmo-global-flag-list
1780                                'elmo-global-flags)
1781
1782 ;; Obsolete functions.
1783 ;; 2001-12-11: *-dir -> *-directory
1784 (defalias 'elmo-folder-make-temp-dir 'elmo-folder-make-temporary-directory)
1785 (make-obsolete 'elmo-folder-make-temp-dir
1786                'elmo-folder-make-temporary-directory)
1787
1788 (require 'product)
1789 (product-provide (provide 'elmo) (require 'elmo-version))
1790
1791 ;;; elmo.el ends here