1 ;;; modb-entity.el --- Message Entity Interface.
3 ;; Copyright (C) 2003 Yuuichi Teranishi <teranisi@gohome.org>
5 ;; Author: Yuuichi Teranishi <teranisi@gohome.org>
6 ;; Hiroya Murata <lapis-lazuli@pop06.odn.ne.jp>
7 ;; Keywords: mail, net news
9 ;; This file is part of ELMO (Elisp Library for Message Orchestration).
11 ;; This program is free software; you can redistribute it and/or modify
12 ;; it under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation; either version 2, or (at your option)
16 ;; This program is distributed in the hope that it will be useful,
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 ;; GNU General Public License for more details.
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with GNU Emacs; see the file COPYING. If not, write to the
23 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24 ;; Boston, MA 02111-1307, USA.
29 ;; Message entity handling.
33 (eval-when-compile (require 'cl
))
40 (luna-define-class modb-entity-handler
() (mime-charset))
41 (luna-define-internal-accessors 'modb-entity-handler
))
43 (defcustom modb-entity-default-handler
'modb-legacy-entity-handler
44 "Default entity handler."
48 (defcustom modb-entity-field-extractor-alist
49 '((ml-info modb-entity-extract-mailing-list-info
50 modb-entity-ml-info-real-fields
))
51 "*An alist of field name and function to extract field body from buffer."
52 :type
'(repeat (list (symbol :tag
"Field Name")
53 (function :tag
"Extractor")
54 (choice :tag
"Real Field"
55 (repeat :tag
"Field Name List" string
)
56 (function :tag
"Function"))))
59 (defvar modb-entity-default-cache-internal nil
)
61 (defun elmo-message-entity-handler (&optional entity
)
62 "Get modb entity handler instance which corresponds to the ENTITY."
65 (not (eq (car entity
) t
))
66 (not (stringp (car entity
))))
68 (or modb-entity-default-cache-internal
69 (setq modb-entity-default-cache-internal
70 (luna-make-entity modb-entity-default-handler
)))))
72 (luna-define-generic modb-entity-handler-list-parameters
(handler)
73 "Return a parameter list of HANDLER.")
75 (luna-define-generic elmo-msgdb-make-message-entity
(handler &rest args
)
76 "Make a message entity using HANDLER.")
78 (luna-define-generic elmo-msgdb-message-entity-number
(handler entity
)
79 "Number of the ENTITY.")
81 (luna-define-generic elmo-msgdb-message-entity-set-number
(handler
83 "Set number of the ENTITY.")
85 (luna-define-generic elmo-msgdb-message-entity-field
(handler entity field
87 "Retrieve field value of the message entity.
88 HANDLER is the message entity handler.
89 ENTITY is the message entity structure.
90 FIELD is a symbol of the field.
91 If optional argument TYPE is specified, return converted value.")
93 (luna-define-generic elmo-msgdb-message-entity-set-field
(handler
95 "Set the field value of the message entity.
96 HANDLER is the message entity handler.
97 ENTITY is the message entity structure.
98 FIELD is a symbol of the field.
99 VALUE is the field value to set.")
101 (luna-define-generic elmo-msgdb-message-entity-update-fields
(handler
103 "Update message entity by VALUES.
104 HANDLER is the message entity handler.
105 ENTITY is the message entity structure.
106 VALUES is an alist of field-name and field-value.")
108 (luna-define-generic elmo-msgdb-copy-message-entity
(handler entity
111 "Copy message entity.
112 HANDLER is the message entity handler.
113 ENTITY is the message entity structure.
114 If optional argument MAKE-HANDLER is specified, use it to make new entity.")
116 (luna-define-generic elmo-msgdb-create-message-entity-from-file
(handler
119 "Create message entity from file.
120 HANDLER is the message entity handler.
121 NUMBER is the number of the newly created message entity.
122 FILE is the message file.")
124 (luna-define-generic elmo-msgdb-create-message-entity-from-buffer
(handler
127 "Create message entity from current buffer.
128 HANDLER is the message entity handler.
129 NUMBER is the number of the newly created message entity.
130 Rest of the ARGS is a plist of message entity field for initial value.
131 Header region is supposed to be narrowed.")
133 ;; Transitional interface.
134 (luna-define-generic elmo-msgdb-message-match-condition
(handler
137 "Return non-nil when the entity matches the condition.")
139 ;; Generic implementation.
140 (luna-define-method initialize-instance
:after
((handler modb-entity-handler
)
142 (unless (modb-entity-handler-mime-charset-internal handler
)
143 (modb-entity-handler-set-mime-charset-internal handler elmo-mime-charset
))
146 (luna-define-method modb-entity-handler-list-parameters
147 ((handler modb-entity-handler
))
148 (list 'mime-charset
))
150 (luna-define-method elmo-msgdb-create-message-entity-from-file
151 ((handler modb-entity-handler
) number file
)
152 (let (insert-file-contents-pre-hook ; To avoid autoconv-xmas...
153 insert-file-contents-post-hook header-end
154 (attrib (file-attributes file
))
157 (if (not (file-exists-p file
))
159 (setq size
(nth 7 attrib
))
160 (setq mtime
(timezone-make-date-arpa-standard
161 (current-time-string (nth 5 attrib
)) (current-time-zone)))
162 ;; insert header from file.
165 (elmo-msgdb-insert-file-header file
)
166 (error (throw 'done nil
)))
167 (goto-char (point-min))
169 (if (re-search-forward "\\(^--.*$\\)\\|\\(\n\n\\)" nil t
)
172 (narrow-to-region (point-min) header-end
)
173 (elmo-msgdb-create-message-entity-from-buffer
174 handler number
:size size
:date mtime
))))))
176 (luna-define-method elmo-msgdb-make-message-entity
((handler
181 (luna-define-method elmo-msgdb-message-entity-field
((handler
185 (plist-get (cdr entity
) (intern (concat ":" (symbol-name field
)))))
187 (luna-define-method elmo-msgdb-message-entity-number
((handler
190 (plist-get (cdr entity
) :number
))
192 (luna-define-method elmo-msgdb-message-entity-update-fields
193 ((handler modb-entity-handler
) entity values
)
195 (dolist (pair values
)
198 (elmo-msgdb-message-entity-field handler entity
(car pair
)))
199 (elmo-msgdb-message-entity-set-field handler entity
200 (car pair
) (cdr pair
))
205 (defsubst modb-entity-handler-mime-charset
(handler)
206 (or (modb-entity-handler-mime-charset-internal handler
)
209 (defun modb-entity-handler-equal-p (handler other
)
210 "Return non-nil, if OTHER hanlder is equal this HANDLER."
211 (and (eq (luna-class-name handler
)
212 (luna-class-name other
))
214 (dolist (slot (modb-entity-handler-list-parameters handler
))
215 (when (not (equal (luna-slot-value handler slot
)
216 (luna-slot-value other slot
)))
217 (throw 'mismatch nil
)))
220 (defun modb-entity-handler-dump-parameters (handler)
221 "Return parameters for reconstruct HANDLER as plist."
223 (mapcar (lambda (slot)
224 (let ((value (luna-slot-value handler slot
)))
226 (list (intern (concat ":" (symbol-name slot
)))
228 (modb-entity-handler-list-parameters handler
))))
230 ;; field in/out converter
231 (defun modb-set-field-converter (converter type
&rest specs
)
232 "Set convert function of TYPE into CONVERTER.
233 SPECS must be like `FIELD1 FUNCTION1 FIELD2 FUNCTION2 ...'.
234 If each field is t, function is set as default converter."
236 (let ((alist (symbol-value converter
))
239 (let ((field (pop specs
))
240 (function (pop specs
))
242 (if (setq cell
(assq type alist
))
243 (setcdr cell
(put-alist field function
(cdr cell
)))
244 (setq cell
(cons type
(list (cons field function
)))
245 alist
(cons cell alist
)))
246 ;; support colon keyword (syntax sugar).
247 (unless (or (eq field t
)
248 (string-match "^:" (symbol-name field
)))
249 (setcdr cell
(put-alist (intern (concat ":" (symbol-name field
)))
252 (set converter alist
))))
253 (put 'modb-set-field-converter
'lisp-indent-function
2)
255 (defsubst modb-convert-field-value
(converter field value
&optional type
)
257 (let* ((alist (cdr (assq (or type t
) converter
)))
258 (function (cdr (or (assq field alist
)
261 (funcall function field value
)
265 (defvar elmo-msgdb-decoded-cache-hashtb nil
)
266 (make-variable-buffer-local 'elmo-msgdb-decoded-cache-hashtb
)
268 (defsubst elmo-msgdb-get-decoded-cache
(string)
269 (if elmo-use-decoded-cache
270 (let ((hashtb (or elmo-msgdb-decoded-cache-hashtb
271 (setq elmo-msgdb-decoded-cache-hashtb
272 (elmo-make-hash 2048))))
274 (or (elmo-get-hash-val string hashtb
)
277 (elmo-with-enable-multibyte
278 (decode-mime-charset-string string elmo-mime-charset
)))
279 (elmo-set-hash-val string decoded hashtb
))))
280 (elmo-with-enable-multibyte
281 (decode-mime-charset-string string elmo-mime-charset
))))
283 (defun modb-entity-string-decoder (field value
)
284 (elmo-msgdb-get-decoded-cache value
))
286 (defun modb-entity-string-encoder (field value
)
287 (elmo-with-enable-multibyte
288 (encode-mime-charset-string value elmo-mime-charset
)))
290 (defun modb-entity-parse-date-string (field value
)
292 (elmo-time-parse-date-string value
)
295 (defun modb-entity-make-date-string (field value
)
298 (elmo-time-make-date-string value
)))
300 (defun modb-entity-mime-decoder (field value
)
301 (mime-decode-field-body value
(symbol-name field
) 'summary
))
303 (defun modb-entity-mime-encoder (field value
)
304 (mime-encode-field-body value
(symbol-name field
)))
306 (defun modb-entity-address-list-decoder (field value
)
308 (mapcar (lambda (address)
309 (mime-decode-field-body address
(symbol-name field
)))
310 (elmo-parse-addresses value
))
313 (defun modb-entity-address-list-encoder (field value
)
316 (mime-encode-field-body (mapconcat 'identity value
", ")
317 (symbol-name field
))))
319 (defun modb-entity-parse-address-string (field value
)
320 (modb-entity-encode-string-recursive
323 (elmo-parse-addresses value
)
326 (defun modb-entity-make-address-string (field value
)
327 (let ((value (modb-entity-decode-string-recursive field value
)))
330 (mapconcat 'identity value
", "))))
332 (defun modb-entity-decode-string-recursive (field value
)
335 (if (stringp element
)
336 (elmo-msgdb-get-decoded-cache element
)
340 (defun modb-entity-encode-string-recursive (field value
)
343 (if (stringp element
)
344 (elmo-with-enable-multibyte
345 (encode-mime-charset-string element elmo-mime-charset
))
349 (defun modb-entity-create-field-indices (slots)
353 (setq indices
(cons (cons (car slots
) index
) indices
)
358 (mapcar (lambda (cell)
359 (cons (intern (concat ":" (symbol-name (car cell
))))
364 ;; Legacy implementation.
366 (luna-define-class modb-legacy-entity-handler
(modb-entity-handler)))
368 (defconst modb-legacy-entity-field-slots
379 (defconst modb-legacy-entity-field-indices
380 (modb-entity-create-field-indices modb-legacy-entity-field-slots
))
382 (defvar modb-legacy-entity-normalizer nil
)
383 (modb-set-field-converter 'modb-legacy-entity-normalizer nil
387 'from
#'modb-entity-string-encoder
388 'subject
#'modb-entity-string-encoder
389 'date
#'modb-entity-make-date-string
390 'to
#'modb-entity-address-list-encoder
391 'cc
#'modb-entity-address-list-encoder
393 t
#'modb-entity-mime-encoder
)
395 (defvar modb-legacy-entity-specializer nil
)
397 (modb-set-field-converter 'modb-legacy-entity-specializer nil
401 'from
#'modb-entity-string-decoder
402 'subject
#'modb-entity-string-decoder
403 'date
#'modb-entity-parse-date-string
404 'to
#'modb-entity-address-list-decoder
405 'cc
#'modb-entity-address-list-decoder
407 t
#'modb-entity-mime-decoder
)
409 (modb-set-field-converter 'modb-legacy-entity-specializer
'string
411 'number nil
; not supported
413 'from
#'modb-entity-string-decoder
414 'subject
#'modb-entity-string-decoder
416 'size nil
; not supported
417 t
#'modb-entity-mime-decoder
)
420 (defmacro modb-legacy-entity-field-index
(field)
421 `(cdr (assq ,field modb-legacy-entity-field-indices
)))
423 (defsubst modb-legacy-entity-set-field
(entity field value
&optional as-is
)
427 (setq value
(modb-convert-field-value
428 modb-legacy-entity-normalizer
430 (cond ((memq field
'(message-id :message-id
))
431 (setcar entity value
))
432 ((setq index
(modb-legacy-entity-field-index field
))
433 (aset (cdr entity
) index value
))
435 (setq index
(modb-legacy-entity-field-index :extra
))
436 (let ((extras (and entity
(aref (cdr entity
) index
)))
438 (if (setq extra
(assoc (symbol-name field
) extras
))
440 (aset (cdr entity
) index
(cons (cons (symbol-name field
)
441 value
) extras
)))))))))
443 (defsubst modb-legacy-make-message-entity
(args)
444 "Make an message entity."
445 (let ((entity (cons nil
(make-vector 9 nil
)))
448 (setq field
(pop args
)
451 (modb-legacy-entity-set-field entity field value
)))
454 (luna-define-method elmo-msgdb-make-message-entity
455 ((handler modb-legacy-entity-handler
) args
)
456 (modb-legacy-make-message-entity args
))
458 (luna-define-method elmo-msgdb-create-message-entity-from-buffer
459 ((handler modb-legacy-entity-handler
) number args
)
460 (let ((extras elmo-msgdb-extra-fields
)
461 (default-mime-charset default-mime-charset
)
462 entity message-id references from subject to cc date
463 extra field-body charset size
)
465 (setq entity
(modb-legacy-make-message-entity args
))
466 (set-buffer-multibyte default-enable-multibyte-characters
)
467 (setq message-id
(elmo-msgdb-get-message-id-from-buffer))
468 (and (setq charset
(cdr (assoc "charset" (mime-read-Content-Type))))
469 (setq charset
(intern-soft charset
))
470 (setq default-mime-charset charset
))
472 (elmo-msgdb-get-references-from-buffer)
473 from
(elmo-replace-in-string
474 (elmo-mime-string (or (elmo-field-body "from")
477 subject
(elmo-replace-in-string
478 (elmo-mime-string (or (elmo-field-body "subject")
481 date
(elmo-decoded-field-body "date")
482 to
(mapconcat 'identity
(elmo-multiple-field-body "to") ",")
483 cc
(mapconcat 'identity
(elmo-multiple-field-body "cc") ","))
484 (unless (elmo-msgdb-message-entity-field handler entity
'size
)
485 (if (setq size
(elmo-field-body "content-length"))
486 (setq size
(string-to-number size
))
489 (if (setq field-body
(elmo-field-body (car extras
)))
490 (modb-legacy-entity-set-field
491 entity
(intern (downcase (car extras
))) field-body
'as-is
))
492 (setq extras
(cdr extras
)))
493 (dolist (field '(message-id number references from subject
495 (when (symbol-value field
)
496 (modb-legacy-entity-set-field
497 entity field
(symbol-value field
) 'as-is
)))
500 (luna-define-method elmo-msgdb-message-entity-number
501 ((handler modb-legacy-entity-handler
) entity
)
502 (and entity
(aref (cdr entity
) 0)))
504 (luna-define-method elmo-msgdb-message-entity-set-number
505 ((handler modb-legacy-entity-handler
) entity number
)
506 (and entity
(aset (cdr entity
) 0 number
)))
508 (luna-define-method elmo-msgdb-message-entity-field
509 ((handler modb-legacy-entity-handler
) entity field
&optional type
)
512 (modb-convert-field-value
513 modb-legacy-entity-specializer
515 (cond ((memq field
'(message-id :message-id
))
517 ((setq index
(modb-legacy-entity-field-index field
))
518 (aref (cdr entity
) index
))
520 (setq index
(modb-legacy-entity-field-index :extra
))
521 (cdr (assoc (symbol-name field
)
522 (aref (cdr entity
) index
)))))
525 (luna-define-method elmo-msgdb-message-entity-set-field
526 ((handler modb-legacy-entity-handler
) entity field value
)
527 (modb-legacy-entity-set-field entity field value
))
529 (luna-define-method elmo-msgdb-copy-message-entity
530 ((handler modb-legacy-entity-handler
) entity
&optional make-handler
)
532 (let ((copy (elmo-msgdb-make-message-entity make-handler
)))
533 (dolist (field (append '(message-id number references from subject
535 (mapcar (lambda (extra) (intern (car extra
)))
536 (aref (cdr entity
) 8))))
537 (elmo-msgdb-message-entity-set-field
538 make-handler copy field
539 (elmo-msgdb-message-entity-field handler entity field
)))
542 (copy-sequence (cdr entity
)))))
544 (luna-define-method elmo-msgdb-message-match-condition
545 ((handler modb-entity-handler
) condition entity
)
546 (let ((key (elmo-filter-key condition
))
550 ((or (string= key
"since")
551 (string= key
"before"))
552 (let ((field-date (elmo-msgdb-message-entity-field
553 handler entity
'date
))
555 (elmo-datevec-to-time
556 (elmo-date-get-datevec
557 (elmo-filter-value condition
)))))
558 (if (string= key
"since")
559 (not (elmo-time< field-date specified-date
))
560 (elmo-time< field-date specified-date
))))
561 ((or (string= key
"larger")
562 (string= key
"smaller"))
563 (let ((bytes (elmo-msgdb-message-entity-field handler entity
'size
))
564 (threshold (string-to-number (elmo-filter-value condition
))))
565 (if (string= key
"larger")
567 (< bytes threshold
))))
568 ((setq field-value
(elmo-msgdb-message-entity-field handler
572 (and (stringp field-value
)
573 (string-match (elmo-filter-value condition
) field-value
)))
578 ;; Standard implementation.
580 (luna-define-class modb-standard-entity-handler
(modb-entity-handler)))
582 (defconst modb-standard-entity-field-slots
595 (defconst modb-standard-entity-field-indices
596 (modb-entity-create-field-indices modb-standard-entity-field-slots
))
598 (defvar modb-standard-entity-normalizer nil
)
599 (modb-set-field-converter 'modb-standard-entity-normalizer nil
602 'date
#'modb-entity-parse-date-string
603 'to
#'modb-entity-parse-address-string
604 'cc
#'modb-entity-parse-address-string
608 t
#'modb-entity-encode-string-recursive
)
610 (defvar modb-standard-entity-specializer nil
)
611 (modb-set-field-converter 'modb-standard-entity-specializer nil
618 t
#'modb-entity-decode-string-recursive
)
619 (modb-set-field-converter 'modb-standard-entity-specializer
'string
622 'date
#'modb-entity-make-date-string
623 'to
#'modb-entity-make-address-string
624 'cc
#'modb-entity-make-address-string
628 'ml-info
#'modb-entity-make-mailing-list-info-string
629 t
#'modb-entity-decode-string-recursive
)
631 (defmacro modb-standard-entity-field-index
(field)
632 `(cdr (assq ,field modb-standard-entity-field-indices
)))
634 (defsubst modb-standard-entity-set-field
(entity field value
&optional as-is
)
638 (let ((elmo-mime-charset
639 (modb-entity-handler-mime-charset (car entity
))))
640 (setq value
(modb-convert-field-value modb-standard-entity-normalizer
642 (cond ((memq field
'(message-id :message-id
))
643 (setcar (cdr entity
) value
))
644 ((setq index
(modb-standard-entity-field-index field
))
645 (aset (cdr (cdr entity
)) index value
))
647 (setq index
(modb-standard-entity-field-index :extra
))
648 (let ((extras (aref (cdr (cdr entity
)) index
))
650 (if (setq cell
(assq field extras
))
652 (aset (cdr (cdr entity
))
654 (cons (cons field value
) extras
)))))))))
656 (defsubst modb-standard-make-message-entity
(handler args
)
657 (let ((entity (cons handler
660 (length modb-standard-entity-field-slots
)
664 (setq field
(pop args
)
667 (modb-standard-entity-set-field entity field value
)))
670 (luna-define-method elmo-msgdb-make-message-entity
671 ((handler modb-standard-entity-handler
) args
)
672 (modb-standard-make-message-entity handler args
))
674 (luna-define-method elmo-msgdb-message-entity-number
675 ((handler modb-standard-entity-handler
) entity
)
676 (and entity
(aref (cdr (cdr entity
)) 0)))
678 (luna-define-method elmo-msgdb-message-entity-set-number
679 ((handler modb-standard-entity-handler
) entity number
)
680 (and entity
(aset (cdr (cdr entity
)) 0 number
)))
682 (luna-define-method elmo-msgdb-message-entity-field
683 ((handler modb-standard-entity-handler
) entity field
&optional type
)
685 (let ((elmo-mime-charset
686 (modb-entity-handler-mime-charset handler
))
688 (modb-convert-field-value
689 modb-standard-entity-specializer
691 (cond ((memq field
'(message-id :message-id
))
693 ((setq index
(modb-standard-entity-field-index field
))
694 (aref (cdr (cdr entity
)) index
))
696 (setq index
(modb-standard-entity-field-index :extra
))
697 (cdr (assq field
(aref (cdr (cdr entity
)) index
)))))
700 (luna-define-method elmo-msgdb-message-entity-set-field
701 ((handler modb-standard-entity-handler
) entity field value
)
702 (modb-standard-entity-set-field entity field value
))
704 (luna-define-method elmo-msgdb-copy-message-entity
705 ((handler modb-standard-entity-handler
) entity
&optional make-handler
)
707 (let ((copy (elmo-msgdb-make-message-entity make-handler
)))
708 (dolist (field (nconc
710 (copy-sequence modb-standard-entity-field-slots
))
714 (modb-standard-entity-field-index :extra
)))
716 (elmo-msgdb-message-entity-set-field
717 make-handler copy field
718 (elmo-msgdb-message-entity-field handler entity field
)))
721 (cons (car (cdr entity
))
722 (copy-sequence (cdr (cdr entity
)))))))
724 (luna-define-method elmo-msgdb-create-message-entity-from-buffer
725 ((handler modb-standard-entity-handler
) number args
)
728 (set-buffer-multibyte default-enable-multibyte-characters
)
730 (modb-standard-make-message-entity
738 (elmo-msgdb-get-message-id-from-buffer)
740 (elmo-msgdb-get-references-from-buffer)
742 (elmo-replace-in-string
743 (or (elmo-decoded-field-body "from" 'summary
)
747 (elmo-replace-in-string
748 (or (elmo-decoded-field-body "subject" 'summary
)
752 (elmo-decoded-field-body "date" 'summary
)
756 (mime-decode-field-body field-body
"to" 'summary
))
757 (elmo-multiple-field-body "to") ",")
761 (mime-decode-field-body field-body
"cc" 'summary
))
762 (elmo-multiple-field-body "cc") ",")
764 (elmo-decoded-field-body "content-type" 'summary
)
766 (let ((size (elmo-field-body "content-length")))
768 (string-to-number size
)
769 (or (plist-get args
:size
) 0)))))))
770 (let (field-name field-body extractor
)
771 (dolist (extra (cons "newsgroups" elmo-msgdb-extra-fields
))
772 (setq field-name
(intern (downcase extra
))
773 extractor
(nth 1 (assq field-name
774 modb-entity-field-extractor-alist
))
775 field-body
(if extractor
776 (funcall extractor field-name
)
777 (elmo-decoded-field-body extra
'summary
)))
779 (modb-standard-entity-set-field entity field-name field-body
))))
783 ;; mailing list info handling
784 (defun modb-entity-extract-mailing-list-info (field)
785 (let* ((getter (lambda (field)
786 (elmo-decoded-field-body (symbol-name field
) 'summary
)))
787 (name (elmo-find-list-match-value
788 elmo-mailing-list-name-spec-list
790 (count (elmo-find-list-match-value
791 elmo-mailing-list-count-spec-list
793 (when (or name count
)
794 (cons name
(and count
(string-to-number count
))))))
796 (defun modb-entity-ml-info-real-fields (field)
798 (mapcar (lambda (entry)
799 (symbol-name (if (consp entry
) (car entry
) entry
)))
800 (append elmo-mailing-list-name-spec-list
801 elmo-mailing-list-count-spec-list
))))
803 (defun modb-entity-make-mailing-list-info-string (field value
)
805 (format (if (cdr value
) "(%s %05.0f)" "(%s)")
806 (elmo-msgdb-get-decoded-cache (car value
))
809 ;; message buffer handler
811 (luna-define-class modb-buffer-entity-handler
(modb-entity-handler)))
813 (defvar modb-buffer-entity-specializer nil
)
814 (modb-set-field-converter 'modb-buffer-entity-specializer nil
815 'date
#'elmo-time-parse-date-string
)
817 (luna-define-method elmo-msgdb-make-message-entity
818 ((handler modb-buffer-entity-handler
) args
)
819 (cons handler
(cons (or (plist-get args
:number
)
820 (plist-get args
'number
))
821 (or (plist-get args
:buffer
)
822 (plist-get args
'buffer
)
825 (luna-define-method elmo-msgdb-message-entity-number
826 ((handler modb-buffer-entity-handler
) entity
)
829 (luna-define-method elmo-msgdb-message-entity-set-number
830 ((handler modb-buffer-entity-handler
) entity number
)
831 (and entity
(setcar (cdr entity
) number
)))
833 (luna-define-method elmo-msgdb-message-entity-field
834 ((handler modb-buffer-entity-handler
) entity field
&optional type
)
836 (let ((elmo-mime-charset
837 (modb-entity-handler-mime-charset handler
)))
838 (modb-convert-field-value
839 modb-buffer-entity-specializer
841 (if (memq field
'(number :number
))
843 (with-current-buffer (cdr (cdr entity
))
845 (nth 1 (assq field modb-entity-field-extractor-alist
))))
847 (funcall extractor field
)
850 (mime-decode-field-body field-body
(symbol-name field
)
852 (elmo-multiple-field-body (symbol-name field
))
856 (luna-define-method elmo-msgdb-message-match-condition
:around
857 ((handler modb-buffer-entity-handler
) condition entity
)
858 (let ((key (elmo-filter-key condition
))
859 (case-fold-search t
))
861 ((string= (elmo-filter-key condition
) "body")
862 (with-current-buffer (cdr (cdr entity
))
863 (goto-char (point-min))
864 (and (re-search-forward "^$" nil t
) ; goto body
865 (search-forward (elmo-filter-value condition
) nil t
))))
867 (luna-call-next-method)))))
870 (product-provide (provide 'modb-entity
) (require 'elmo-version
))
872 ;;; modb-entity.el ends here