« ^ »

GnuPGで暗号化されたPDFファイルをEmacsで表示できるようにする

所要時間: 約 3分

Emacsではdoc-view-modeが標準で提供されているため、画像やPDFはファイルを開くだけで描画される。この当たり前の機能は、オーバーレイによって実装されており、表示を切り替える事で生の状態のデータをバッファに表示する事もできる。そのため、ファイルのデータ自体を直接編集する事もできる。

PDFでのdoc-view-modeの挙動を確認してみた所、概ね以下のような順序で処理が行われていた。

  1. PDFから画像を作成する。
  2. オーバーレイを作成する。
  3. オーバーレイに画像を紐付け、バッファに挿入する。

PDFから画像を作成する際、その環境にインストールされている外部プログラムを使用する。僕の環境では mudraw が使われていた1

GnuPGで暗号化されたファイルの場合、一度GnuPGで復号化した後、そのデータを描画する必要がある。注意したい点としては、GnuPGで暗号化されたファイルというものは、誰かに盗まれたくないデータであるため暗号化しているのであって、復号化したデータをできるだけファイルには書き出さない、又はちゃんと削除するという事を実施したい。

まず mudraw の機能について確認していく。ポイントとしては2つある。1つ目は標準入力からのデータを受け付けるか、2つ目は標準出力に結果を出力できるかだ。確認した所、この2点については mudraw はサポートしてないようだった2。仕方がないので、一時ファイルに書き出して処理を行うようにする。

  1. gpg を使い、指定したファイルを復号化し、PDFを書き出す。

    gpg -o temp.pdf --decrypt sample_copy.pdf.gpg
  2. mudraw を使い、PNGファイルを書き出す。

    mutool draw -o temp.png temp.pdf
  3. 表示用のバッファを作成する。

    (get-buffer-create "*Doc View: PDF GPG*")
  4. PNGファイルからEmacsの画像データを create-image で作成する。

    (setq-local current-image (create-image (expand-file-name "./temp.png")))
  5. オーバーレイを作成する。

    (insert " ")
    (setq-local current-overlay (make-overlay (point-min) (1+ (point-min))))
  6. オーバーレイに画像を関連付け、表示する。

    (overlay-put current-overlay 'display current-image)

この一連の処理をdiredでファイルを開こうとした時に実施できれば良い。 dired でファイルを開く時は、 dired-find-file が呼び出される。この時に、先程の処理をする必要がある。

少し頭の中を整理すると、gpgと拡張子が付いているファイルを開く場合、Emacsは復号化しようとしてくれるため、手動で復号化をする必要はなかった。そこでファイルを開いた後のバッファの内容を一時ファイルに書き出し、それを開いた後、ファイル自体を削除してしまえばいいという結論になった。

(defun display-pdf ()
  (interactive)
  (let ((current-dir default-directory)
	(temp-file-path (make-temp-file "testing" nil ".pdf")))
    (write-region (point-min) (point-max) temp-file-path)
    (find-file temp-file-path)
    (delete-file temp-file-path)))

save-file を呼び出してしまうと、復号済みのファイルが保存されてしまうけれど、一旦はこれで良しとする。


1

mudrawはMuPDFに梱包されているプログラム。

2

mupdfのドキュメントには、出力ファイルの指定を省略した場合、標準出力に出力するという記述があるが、 Homebrew でインストールした mudraw version 1.23.7 では、出力ファイルの指定を省略しても、標準出力には何も出力されなかった。https://mupdf.readthedocs.io/en/latest/mutool-draw.html