1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-01-05 19:31:02 -08:00

Allow doc-view to open password-protected PDF files (bug#33684)

* lisp/doc-view.el (doc-view-ghostscript-options): Removed "-sDEVICE"
option.
(doc-view-ghostscript-device): New customizable variable, passed as
"-sDEVICE" option to GhostScript.
(doc-view-pdf-password-protected-ghostscript-p): New function.
(doc-view-pdf->png-converter-ghostscript): Can now open
password-protected PDF files.
(doc-view-pdfdraw-program-subcommand): New function.
(doc-view-pdf-password-protected-pdfdraw-p): New function.
(doc-view-pdf->png-converter-mupdf): Can now open password-protected
PDF files.
* etc/NEWS: Mention new doc-view-mode feature.
This commit is contained in:
Federico Tedin 2019-02-03 13:48:31 -03:00 committed by Tassilo Horn
parent d6f430cb88
commit d5f629d193
2 changed files with 60 additions and 20 deletions

View file

@ -334,6 +334,7 @@ asked to use :host 'local and :family 'ipv6.
** doc-view-mode ** doc-view-mode
*** New commands doc-view-presentation and doc-view-fit-window-to-page *** New commands doc-view-presentation and doc-view-fit-window-to-page
*** Added support for password-protected PDF files
** map.el ** map.el
*** Now also understands plists. *** Now also understands plists.

View file

@ -183,11 +183,16 @@
(defcustom doc-view-ghostscript-options (defcustom doc-view-ghostscript-options
'("-dSAFER" ;; Avoid security problems when rendering files from untrusted '("-dSAFER" ;; Avoid security problems when rendering files from untrusted
;; sources. ;; sources.
"-dNOPAUSE" "-sDEVICE=png16m" "-dTextAlphaBits=4" "-dNOPAUSE" "-dTextAlphaBits=4"
"-dBATCH" "-dGraphicsAlphaBits=4" "-dQUIET") "-dBATCH" "-dGraphicsAlphaBits=4" "-dQUIET")
"A list of options to give to ghostscript." "A list of options to give to ghostscript."
:type '(repeat string)) :type '(repeat string))
(defcustom doc-view-ghostscript-device "png16m"
"Output device to give to ghostscript."
:type 'string
:version "27.1")
(defcustom doc-view-resolution 100 (defcustom doc-view-resolution 100
"Dots per inch resolution used to render the documents. "Dots per inch resolution used to render the documents.
Higher values result in larger images." Higher values result in larger images."
@ -950,16 +955,31 @@ Should be invoked when the cached images aren't up-to-date."
(list "-o" pdf dvi) (list "-o" pdf dvi)
callback))) callback)))
(defun doc-view-pdf-password-protected-ghostscript-p (pdf)
"Return non-nil if a PDF file is password-protected.
The test is performed using `doc-view-ghostscript-program'."
(with-temp-buffer
(apply #'call-process doc-view-ghostscript-program nil (current-buffer)
nil `(,@doc-view-ghostscript-options
"-sNODISPLAY"
,pdf))
(goto-char (point-min))
(search-forward "This file requires a password for access." nil t)))
(defun doc-view-pdf->png-converter-ghostscript (pdf png page callback) (defun doc-view-pdf->png-converter-ghostscript (pdf png page callback)
(doc-view-start-process (let ((pdf-passwd (if (doc-view-pdf-password-protected-ghostscript-p pdf)
"pdf/ps->png" doc-view-ghostscript-program (read-passwd "Enter password for PDF file: "))))
`(,@doc-view-ghostscript-options (doc-view-start-process
,(format "-r%d" (round doc-view-resolution)) "pdf/ps->png" doc-view-ghostscript-program
,@(if page `(,(format "-dFirstPage=%d" page))) `(,@doc-view-ghostscript-options
,@(if page `(,(format "-dLastPage=%d" page))) ,(concat "-sDEVICE=" doc-view-ghostscript-device)
,(concat "-sOutputFile=" png) ,(format "-r%d" (round doc-view-resolution))
,pdf) ,@(if page `(,(format "-dFirstPage=%d" page)))
callback)) ,@(if page `(,(format "-dLastPage=%d" page)))
,@(if pdf-passwd `(,(format "-sPDFPassword=%s" pdf-passwd)))
,(concat "-sOutputFile=" png)
,pdf)
callback)))
(defalias 'doc-view-ps->png-converter-ghostscript (defalias 'doc-view-ps->png-converter-ghostscript
'doc-view-pdf->png-converter-ghostscript) 'doc-view-pdf->png-converter-ghostscript)
@ -980,17 +1000,36 @@ If PAGE is nil, convert the whole document."
,tiff) ,tiff)
callback)) callback))
(defun doc-view-pdfdraw-program-subcommand ()
"Return the mutool subcommand replacing mudraw.
Recent MuPDF distributions replaced 'mudraw' with 'mutool draw'."
(when (string-match "mutool[^/\\]*$" doc-view-pdfdraw-program)
'("draw")))
(defun doc-view-pdf-password-protected-pdfdraw-p (pdf)
"Return non-nil if a PDF file is password-protected.
The test is performed using `doc-view-pdfdraw-program'."
(with-temp-buffer
(apply #'call-process doc-view-pdfdraw-program nil (current-buffer) nil
`(,@(doc-view-pdfdraw-program-subcommand)
,(concat "-o" null-device)
;; In case PDF isn't password-protected, "draw" only one page.
,pdf "1"))
(goto-char (point-min))
(search-forward "error: cannot authenticate password" nil t)))
(defun doc-view-pdf->png-converter-mupdf (pdf png page callback) (defun doc-view-pdf->png-converter-mupdf (pdf png page callback)
(doc-view-start-process (let ((pdf-passwd (if (doc-view-pdf-password-protected-pdfdraw-p pdf)
"pdf->png" doc-view-pdfdraw-program (read-passwd "Enter password for PDF file: "))))
;; FIXME: Ugly hack: recent mupdf distribution replaced "mudraw" with (doc-view-start-process
;; "mutool draw". "pdf->png" doc-view-pdfdraw-program
`(,@(if (string-match "mutool[^/\\]*$" doc-view-pdfdraw-program) '("draw")) `(,@(doc-view-pdfdraw-program-subcommand)
,(concat "-o" png) ,(concat "-o" png)
,(format "-r%d" (round doc-view-resolution)) ,(format "-r%d" (round doc-view-resolution))
,pdf ,@(if pdf-passwd `("-p" ,pdf-passwd))
,@(if page `(,(format "%d" page)))) ,pdf
callback)) ,@(if page `(,(format "%d" page))))
callback)))
(defun doc-view-odf->pdf-converter-unoconv (odf callback) (defun doc-view-odf->pdf-converter-unoconv (odf callback)
"Convert ODF to PDF asynchronously and call CALLBACK when finished. "Convert ODF to PDF asynchronously and call CALLBACK when finished.