2010年5月13日

[mew-dist 29226]受け取った暗号化 Zip の内容を Mew のメッセージバッファに表示する

濱野と申します。

暗号化 Zip ファイルでメール本文をやり取りする事があり、その内容を
Mew のメッセージバッファで見たいと考え、添付の elisp を作成して使っ
ています。今回、Zip の暗号化機能が搭載されたとあり、問題点は数多く
残ってはおりますが、思い切って投稿してみます。

主な機能は、以下の通りです。


メールに添付された暗号化 Zip ファイルを裏で zip コマンドを使用し
て解凍し、解凍したファイルの内容をメッセージバッファに表示する。
解凍後のファイルが複数あれば、その中からどのファイルをメッセージ
バッファに表示するかを選択し、選択したファイルを表示する。

利点は、端末に戻ってパスワードを入力して Zip ファイルを解凍、そして閲覧、
という動作を Emacs 内で完結できる点です。

現状はらんでいる主な問題点は、以下の通りです。

* Mew 6.3 と Mew 4.2 でのみしか動かない。
* パスワードを間違えた事を検知できない。
* パスワードを間違って記憶させると、クリアするコマンドが無い。
* このディレクトリでは、このパスワードのような組み合わせができない。
* などなど

よろしければ、どうぞ。

--
HAMANO Kiyoto
kiyoto@xxxxx

Content-Disposition: inline; filename="mew-dispzip.el"

;; -*- Coding:iso-2022-jp; Mode:Emacs-lisp -*-

;; version: 0.4
;; created by HAMANO Kiyoto <kiyoto@xxxxx>

;; 概要:
;;
;; パスワードつき Zip で圧縮されたメッセージを Mew の *Mew message* バッ
;; ファに表示する。
;;
;; (*) まだバグが多々あると思われます。
;;
;;
;; 使用法:
;;
;; load-path の通ったディレクトリにこのファイルを置き、.emacs に以下の
;; 設定を足す。
;;
;; (require 'mew-dispzip)
;; ;; summary-mode で C-cy でを押す事でzipファイルを解凍し、表示する
;; (add-hook
;; 'mew-summary-mode-hook
;; (lambda ()
;; (define-key mew-summary-mode-map "\C-cy"
;; 'mew-dispzip-summary-execute-command)))
;;
;; C-cy を押すのは、# で作られた文字で大きく Binary と書かれているバッ
;; ファ(*Mew summary*)が表示されている状態で行う。解凍したファイルが 1
;; つのみならば、ただちにそのファイルを表示し、複数ファイルの場合は、
;; どのファイルを表示するかを選択する。
;;
;;
;; 設定:
;;
;; * パスワードの保存
;; パスワードを入力したくない場合は、mew-dispzip-unzip-password にパス
;; ワードを設定する。
;;
;; (setq mew-dispzip-unzip-password "hogehoge")
;;
;; * 一度パスワードを入力したら、キャッシュする
;; パスワードを一度入力したら、上記 mew-dispzip-unzip-password に保存
;; したい場合、mew-dispzip-unzip-password-caching を t にする。
;; (.emacs にパスワードを書きたくない場合)
;;
;; (setq mew-dispzip-unzip-password-caching t)
;;
;; * 展開した zip ファイルの内容を保存するディレクトリを変更する
;; 解凍した zip ファイルの内容を置くディレクトリを変更する場合、
;; mew-dispzip-save-dir の値を変更する。
;; (注) このディレクトリを作成する際、パーミッションの設定は特に行うよ
;; うにしていない。
;;
;; ;; mew-dispzip-directory-clear 関数でクリアするとこのディレクトリ以
;; ;; 下の内容がまるごと削除される可能性があるので、他にファイルのある
;; ;; ディレクトリを指定してはいけない。
;; (setq mew-dispzip-save-dir "/home/foo/.archive")
;;
;; * 展開した zip ファイルの内容を保存しない
;; 毎回 zip ファイルを解凍し、解凍し終わったら、作成したディレクトリ・
;; ファイルを削除するようにする。
;;
;; (setq mew-dispzip-unzip-caching nil)
;;
;;
;; 必要物:
;;
;; * unzip コマンド
;; * mew
;;
;;
;; TODO:
;;
;; * *Mew message* バッファに表示するファイルが txt であるかどうかを確
;; 認する(現在は確認せず insert している)。
;; * Mail のあるディレクトリ毎に使用するパスワードを変える仕組み(不要?)
;; * 入力した password があっていたかどうかの確認処理
;; * 難しいならば、password のキャッシュを削除する処理
;; * 別のディレクトリへzipファイルを見たメールを移動した場合の考慮
;; * 毎回 unzip するオプションを追加した
;; * その場合、mew-dispzip-save-dir に指定されたディレクトリを毎度
;; 削除する。
;; * コメントの追加
;; * 関数名・変数名の修正
;; * だいたい行った
;;
;; ChangeLog:
;;
;; 0.4: Emacs 23.1 + Mew 6.3 暫定対応
;;
;; テスト環境:
;;
;; * emacs 23.1 + mew 6.3
;;

(require 'mew)

;; Variables:

(defvar mew-dispzip-unzip-command "unzip")
(defvar mew-dispzip-unzip-options '("-o"
(concat "-P" mew-dispzip-unzip-password)
(concat "-d" mew-dispzip-save-dir)))
(defvar mew-dispzip-unzip-password nil)
(defvar mew-dispzip-unzip-password-caching nil)
(defvar mew-dispzip-save-dir (concat (getenv "HOME")
"/"
".mew-dispzip-archive")
"*Zip ファイルを解凍した内容が収められるディレクトリ。
`mew-dispzip-unzip-caching' が nil のとき、このディレクトリは、解
凍の都度削除されるので、解凍した Zip ファイル以外に内容があるディ
レクトリを指定してはいけない。")
(defvar mew-dispzip-unzip-caching t)

;; Functions:

(defun mew-dispzip-directory-clear (&optional dir no-confirm)
(interactive)
(let* ((d (if dir
dir
mew-dispzip-save-dir))
(files (mew-dispzip-directory-files d t)))
(when (or no-confirm
(yes-or-no-p (format "Delete the dir %s (yes/no):"
d)))
(message "Delete files...")
(dolist (i files)
(setq i (format "%s/%s" d i))
(cond
((file-directory-p i)
(delete-directory i))
(t
(delete-file i))))
(delete-directory d)
(message "Delete files...done"))))

(defun mew-dispzip-directory-files (dir &optional include-directory)
(let ((mew-dispzip-directory-files-internal
'(lambda (din &optional subdir)
(let ((d din))
(if subdir
(progn
(setq d (concat d "/" subdir))
(if include-directory
(setq files (cons (format "%s/" subdir)
files)))))
(dolist (i (directory-files d))
(cond
((file-directory-p (concat d "/" i))
(unless (or (member i '("." "..")))
(funcall mew-dispzip-directory-files-internal
din
(concat subdir "/" i))))
(t
(cond
(subdir
(setq files (cons (format "%s/%s" subdir i)
files)))
(t
(setq files (cons (format "%s" i)
files))))))))))
files)
(funcall mew-dispzip-directory-files-internal dir)
files))

(defun mew-dispzip-summary-concat-options ()
(let ((password (if mew-dispzip-unzip-password
mew-dispzip-unzip-password
(read-passwd "Password: "))))
(when (and mew-dispzip-unzip-password-caching
(null mew-dispzip-unzip-password))
;; set password to global
(setq mew-dispzip-unzip-password password))
(let ((optstring "")
;; set password to local
(mew-dispzip-unzip-password password))
(dolist (i mew-dispzip-unzip-options)
(cond
((and (listp i)
(symbolp (car i)))
(setq optstring (concat optstring " " (eval i))))
(t
(setq optstring (concat optstring " " i)))))
optstring)))

;; for mew 6.3
(defun my-mew-dispzip-summary-execute-external (program options)
(mew-summary-msg-or-part
(let* ((fld (mew-summary-folder-name))
(msg (mew-summary-message-number2))
(nums (mew-syntax-nums))
(cache (mew-cache-hit fld msg 'must-hit))
(syntax (mew-cache-decode-syntax cache))
(stx (mew-syntax-get-entry syntax nums))
(ctl (mew-syntax-get-ct stx))
(ct (mew-syntax-get-value ctl 'cap))
(win (selected-window))
(begin (mew-syntax-get-begin stx))
(end (mew-syntax-get-end stx))
(params (mew-syntax-get-params ctl))
(cdpl (mew-syntax-get-cdp stx))
(fname (mew-syntax-get-filename cdpl ctl)))
(mew-summary-toggle-disp-msg 'on)
(mew-window-configure 'message)
;; message buffer
(unwind-protect
(mew-elet
;; nil or t
(mew-summary-execute-program
program ct ctl cache begin end params fname options t)
(mew-summary-display-postscript 'no-hook))
(select-window win)))))

(defun mew-dispzip-summary-execute-command (&optional arg)
"zip ファイルを解凍し、*Mew message* バッファに表示する。一度解凍し
たファイルは、mew-dispzip-save-dir にキャッシュされ、以後、そのファイルが使
われる。unzip し直したい場合は、前置引数(C-u など)をつけてこの関数を実
行する。"
(interactive "P")
(let* ((num (mew-summary-message-number2))
(dir (substring (mew-summary-folder-name) 1))
(mew-dispzip-save-dir
(concat mew-dispzip-save-dir
(unless (equal "/"
(substring mew-dispzip-save-dir
(1- (length mew-dispzip-save-dir))))
"/")
dir
"/"
num))
filenum
selected)
;; clear unzip cache
(when (and (null mew-dispzip-unzip-caching)
(file-exists-p mew-dispzip-save-dir))
(mew-dispzip-directory-clear mew-dispzip-save-dir t)
(message "")) ; clear minibuffer
;; directory don't exist.
(unless (file-exists-p mew-dispzip-save-dir)
(make-directory mew-dispzip-save-dir t)
(unless (file-exists-p mew-dispzip-save-dir)
(error "make-directory")))
;; do unzip
(when (or arg
(= 2 (length (directory-files mew-dispzip-save-dir))))
(when (and num dir mew-dispzip-save-dir)
(mew-summary-msg-or-part
(cond
((string= mew-version-number "4.2")
(mew-summary-execute-base
nil
mew-dispzip-unzip-command
(delete "" (mew-split-quoted (mew-dispzip-summary-concat-options)
mew-sp
?\"
?\"))))
((string= mew-version-number "6.3")
(my-mew-dispzip-summary-execute-external
mew-dispzip-unzip-command
(delete "" (mew-split-quoted (mew-dispzip-summary-concat-options)
mew-sp
?\"
?\"))))))
(sit-for 0.1))) ; force sync...
;; select file
(setq filenum (length (mew-dispzip-directory-files mew-dispzip-save-dir)))
(when (> filenum 0)
(setq selected
(cond
((= filenum 1)
(car (nthcdr 2 (directory-files mew-dispzip-save-dir))))
(t
(completing-read
"Select File: "
(mapcar 'list
(mew-dispzip-directory-files mew-dispzip-save-dir))
nil
t))))
;; display selected file to *Mew message* buffer.
(let ((cwin (get-buffer-window (current-buffer)))
(mwin (get-buffer-window (mew-buffer-message))))
(when mwin
(select-window mwin)
(unwind-protect
(progn
(setq buffer-read-only nil)
(erase-buffer)
(mew-message-clear-end-of)
(insert (with-current-buffer (find-file-noselect
(concat mew-dispzip-save-dir
"/"
selected))
(buffer-string)))
(mew-message-set-end-of)
(goto-char (point-min)))
(progn (setq buffer-read-only t)
(select-window cwin)))))
;; clear unzip cache
(when (and (null mew-dispzip-unzip-caching)
(file-exists-p mew-dispzip-save-dir))
(mew-dispzip-directory-clear mew-dispzip-save-dir t)
(message ""))))) ; clear minibuffer

(provide 'mew-dispzip)
;; mew-dispzip.el ends here

投稿者 xml-rpc : 2010年5月13日 19:11
役に立ちました?:
過去のフィードバック 平均:(0) 総合:(0) 投票回数:(0)
本記事へのTrackback: http://hoop.euqset.org/blog/mt-tb2006.cgi/95729
トラックバック
コメント
コメントする




画像の中に見える文字を入力してください。