* wl-template.el (wl-template-select): Reset draft config exec
[elisp/wanderlust.git] / elmo / elmo-file.el
index 4f259e7..572528a 100644 (file)
 
 ;;; Code:
 ;;
+(eval-when-compile (require 'cl))
+
 (require 'elmo)
 (require 'elmo-map)
 (require 'mime-edit)
 
+(defun elmo-file-find (files)
+  "Return the first existing filename in the FILES."
+  (let (file)
+    (while files
+      (when (file-exists-p (car files))
+       (setq file (car files)
+             files nil))
+      (setq files (cdr files)))
+    (and file (expand-file-name file))))
+
+(defcustom elmo-file-command (exec-installed-p "file")
+  "*Program name of the file type detection command `file'."
+  :type '(string :tag "Program name of the file")
+  :group 'elmo)
+
+(defcustom elmo-file-command-argument
+  (let ((magic-file (elmo-file-find
+                    '("/usr/share/magic.mime"
+                      "/usr/share/file/magic.mime"
+                      "/cygwin/usr/share/file/magic.mime"))))
+    (if magic-file (list "-m" magic-file)))
+  "*Argument list for the `file' command.
+\(It should return the MIME content type\)"
+  :type '(repeat string)
+  :group 'elmo)
+
+(defcustom elmo-file-fetch-max-size (* 1024 1024)
+  "*Max size of the message fetching."
+  :type 'integer
+  :group 'elmo)
+
 (eval-and-compile
-  (luna-define-class elmo-file-folder (elmo-map-folder) (file-path))
+  (luna-define-class elmo-file-folder (elmo-map-folder elmo-file-tag)
+                    (file-path))
   (luna-define-internal-accessors 'elmo-file-folder))
 
 (luna-define-method elmo-folder-initialize ((folder
     (concat (elmo-match-string 1 s) ", "
            (timezone-make-date-arpa-standard s (current-time-zone)))))
 
+(defun elmo-file-detect-content-type (file)
+  "Return content-type of the FILE."
+  (if (or (not (file-exists-p file))
+         (file-directory-p file))
+      "application/octet-stream"
+    (let (type)
+      (setq type (mime-find-file-type file))
+      (if (and (string= (nth 0 type) "application")
+              (string= (nth 1 type) "octet-stream"))
+         (if (and elmo-file-command
+                  elmo-file-command-argument)
+             (with-temp-buffer
+               (if (zerop (apply 'call-process elmo-file-command
+                                 nil `(,(current-buffer) nil)
+                                 nil (append elmo-file-command-argument
+                                             (list (expand-file-name file)))))
+                   (progn
+                     (goto-char (point-min))
+                     (when (re-search-forward ": *" nil t)
+                       (setq type (buffer-substring (match-end 0)
+                                                    (point-at-eol))))
+                     (cond
+                      ((string= "empty" type)
+                       "application/octet-stream")
+                      ((string-match "text" type)
+                       "text/plain")
+                      (t
+                       (car (split-string type)))))
+                 "application/octet-stream"))
+           (concat (nth 0 type) "/" (nth 1 type)))
+       (concat (nth 0 type) "/" (nth 1 type))))))
+
 (defun elmo-file-msgdb-create-entity (msgdb folder number)
   "Create msgdb entity for the message in the FOLDER with NUMBER."
   (let* ((file (elmo-message-file-name folder number))
 (luna-define-method elmo-folder-msgdb-create ((folder elmo-file-folder)
                                              numlist flag-table)
   (let ((new-msgdb (elmo-make-msgdb))
-       entity mark i percent num)
-    (setq num (length numlist))
-    (setq i 0)
-    (message "Creating msgdb...")
-    (while numlist
-      (setq entity
-           (elmo-file-msgdb-create-entity new-msgdb folder (car numlist)))
-      (when entity
-       (elmo-msgdb-append-entity new-msgdb entity '(new unread)))
-      (when (> num elmo-display-progress-threshold)
-       (setq i (1+ i))
-       (setq percent (/ (* i 100) num))
-       (elmo-display-progress
-        'elmo-folder-msgdb-create "Creating msgdb..."
-        percent))
-      (setq numlist (cdr numlist)))
-    (message "Creating msgdb...done")
+       entity)
+    (elmo-with-progress-display (elmo-folder-msgdb-create (length numlist))
+       "Creating msgdb"
+      (dolist (number numlist)
+       (setq entity (elmo-file-msgdb-create-entity new-msgdb folder number))
+       (when entity
+         (elmo-msgdb-append-entity new-msgdb entity '(new unread)))
+       (elmo-progress-notify 'elmo-folder-msgdb-create)))
     new-msgdb))
 
 (luna-define-method elmo-folder-message-file-p ((folder elmo-file-folder))
                                                         &optional
                                                         start-number)
   (let ((temp-dir (elmo-folder-make-temporary-directory folder))
-       (cur-number (if start-number 0)))
+       (cur-number (or start-number 0)))
     (dolist (number numbers)
       (elmo-copy-file
        (elmo-message-file-name folder number)
        (expand-file-name
-       (int-to-string (if start-number (incf cur-number) number))
-       temp-dir)))
+       (number-to-string (if start-number cur-number number))
+       temp-dir))
+      (incf cur-number))
     temp-dir))
 
 (luna-define-method elmo-map-message-fetch ((folder elmo-file-folder)
                                            &optional section unseen)
   (let ((file (expand-file-name (car (split-string location "/"))
                                (elmo-file-folder-file-path-internal folder)))
-       charset guess uid)
+       charset guess uid is-text)
     (when (file-exists-p file)
       (set-buffer-multibyte nil)
       (prog1
-         (insert-file-contents-as-binary file)
+         (insert-file-contents-as-binary file nil 0 elmo-file-fetch-max-size)
        (unless (or (std11-field-body "To")
                    (std11-field-body "Cc")
                    (std11-field-body "Subject"))
-         (setq guess (mime-find-file-type file))
-         (when (string= (nth 0 guess) "text")
+         (setq guess (elmo-file-detect-content-type file))
+         (setq is-text (string-match "^text/" guess))
+         (when is-text
            (set-buffer-multibyte t)
            (decode-coding-region
             (point-min) (point-max)
                  (concat "<" (elmo-replace-in-string file "/" ":")
                          "@" (system-name) ">\n"))
          (insert "Content-Type: "
-                 (concat (nth 0 guess) "/" (nth 1 guess))
-                 (or (and (string= (nth 0 guess) "text")
+                 guess
+                 (or (and is-text
                           (concat
                            "; charset=" (upcase (symbol-name charset))))
                      "")
                  "\nMIME-Version: 1.0\n\n")
-         (when (string= (nth 0 guess) "text")
+         (when is-text
            (encode-mime-charset-region (point-min) (point-max) charset))
          (set-buffer-multibyte nil))))))
 
 (luna-define-method elmo-map-folder-list-message-locations
   ((folder elmo-file-folder))
-  (mapcar
-   (lambda (file)
-     (concat
-      file "/"
-      (mapconcat
-       'number-to-string
-       (nth 5 (file-attributes (expand-file-name
-                               file
-                               (elmo-file-folder-file-path-internal
-                                folder))))
-       ":")))
-   (directory-files (elmo-file-folder-file-path-internal folder))))
+  (delq nil
+       (mapcar
+        (lambda (file)
+          (when (not (file-directory-p file))
+            (concat
+             file "/"
+             (mapconcat
+              'number-to-string
+              (nth 5 (file-attributes (expand-file-name
+                                       file
+                                       (elmo-file-folder-file-path-internal
+                                        folder))))
+              ":"))))
+        (directory-files (elmo-file-folder-file-path-internal folder)))))
 
 (luna-define-method elmo-folder-exists-p ((folder elmo-file-folder))
   (file-directory-p (elmo-file-folder-file-path-internal folder)))