Skip to content

Commit 0583a0c

Browse files
committed
org: Add setting for remote file download policy
* lisp/org.el (org-resource-download-policy, org-safe-remote-resources): Two new customisations to configure the policy for downloading remote resources. (org--should-fetch-remote-resource-p, org--safe-remote-resource-p, org--confirm-resource-safe): Introduce the new function `org--should-fetch-remote-resource-p' for internal use determining whether a remote resource should be downloaded according to the download policy. This function makes use of two helper functions, `org--safe-remote-resource-p' and `org--confirm-resource-safe'. (org-file-contents): Apply `org--safe-remote-resource-p' to file downloading. * lisp/org-persist.el (org-persist-write): Apply `org--safe-remote-resource-p' to url downloading. * lisp/org-attach.el (org-attach-attach, org-attach-url): Apply `org--safe-remote-resource-p' to url downloading.
1 parent d947988 commit 0583a0c

File tree

3 files changed

+127
-19
lines changed

3 files changed

+127
-19
lines changed

lisp/org-attach.el

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,9 @@ DIR-property exists (that is different from the unset one)."
486486
(defun org-attach-url (url)
487487
"Attach URL."
488488
(interactive "MURL of the file to attach: \n")
489-
(let ((org-attach-method 'url))
489+
(let ((org-attach-method 'url)
490+
(org-safe-remote-resources ; Assume saftey if in an interactive session.
491+
(if noninteractive org-safe-remote-resources '(""))))
490492
(org-attach-attach url)))
491493

492494
(defun org-attach-buffer (buffer-name)
@@ -525,9 +527,12 @@ METHOD may be `cp', `mv', `ln', `lns' or `url' default taken from
525527
((eq method 'mv) (rename-file file attach-file))
526528
((eq method 'cp) (copy-file file attach-file))
527529
((eq method 'ln) (add-name-to-file file attach-file))
528-
;; We pass integer third argument to auto-expand "~" in FILE.
529530
((eq method 'lns) (make-symbolic-link file attach-file 1))
530-
((eq method 'url) (url-copy-file file attach-file)))
531+
((eq method 'url)
532+
(if (org--should-fetch-remote-resource-p file)
533+
(url-copy-file file attach-file)
534+
(error "The remote resource %S is considered unsafe, and will not be downloaded."
535+
file))))
531536
(run-hook-with-args 'org-attach-after-change-hook attach-dir)
532537
(org-attach-tag)
533538
(cond ((eq org-attach-store-link-p 'attached)

lisp/org-persist.el

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -657,7 +657,10 @@ COLLECTION is the plist holding data collection."
657657
(format "%s-%s.%s" persist-file (md5 path) ext))))
658658
(unless (file-exists-p (file-name-directory file-copy))
659659
(make-directory (file-name-directory file-copy) t))
660-
(url-copy-file path file-copy 'overwrite)
660+
(if (org--should-fetch-remote-resource-p path)
661+
(url-copy-file path file-copy 'overwrite)
662+
(error "The remote resource %S is considered unsafe, and will not be downloaded."
663+
path))
661664
(format "%s-%s.%s" persist-file (md5 path) ext)))))
662665

663666
(defun org-persist-write:index (container _)

lisp/org.el

Lines changed: 115 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1353,6 +1353,34 @@ For more examples, see the system specific constants
13531353
(string :tag "Command")
13541354
(function :tag "Function")))))
13551355

1356+
(defcustom org-resource-download-policy 'prompt
1357+
"The policy applied to requests to obtain remote resources.
1358+
1359+
This affects keywords like #+setupfile and #+incude on export,
1360+
`org-persist-write:url',and `org-attach-url' in non-interactive
1361+
Emacs sessions.
1362+
1363+
This recognises four possible values:
1364+
- t, remote resources should always be downloaded.
1365+
- prompt, you will be prompted to download resources nt considered safe.
1366+
- safe, only resources considered safe will be downloaded.
1367+
- nil, never download remote resources.
1368+
1369+
A resource is considered safe if it matches one of the patterns
1370+
in `org-safe-remote-resources'."
1371+
:group 'org
1372+
:type '(choice (const :tag "Always download remote resources" t)
1373+
(const :tag "Prompt before downloading an unsafe resource" prompt)
1374+
(const :tag "Only download resources considered safe" safe)
1375+
(const :tag "Never download any resources" nil)))
1376+
1377+
(defcustom org-safe-remote-resources nil
1378+
"A list of regexp patterns matching safe URIs.
1379+
URI regexps are applied to both URLs and Org files requesting
1380+
remote resources."
1381+
:group 'org
1382+
:type '(list regexp))
1383+
13561384
(defcustom org-open-non-existing-files nil
13571385
"Non-nil means `org-open-file' opens non-existing files.
13581386

@@ -4468,21 +4496,25 @@ is available. This option applies only if FILE is a URL."
44684496
(cond
44694497
(cache)
44704498
(is-url
4471-
(with-current-buffer (url-retrieve-synchronously file)
4472-
(goto-char (point-min))
4473-
;; Move point to after the url-retrieve header.
4474-
(search-forward "\n\n" nil :move)
4475-
;; Search for the success code only in the url-retrieve header.
4476-
(if (save-excursion
4477-
(re-search-backward "HTTP.*\\s-+200\\s-OK" nil :noerror))
4478-
;; Update the cache `org--file-cache' and return contents.
4479-
(puthash file
4480-
(buffer-substring-no-properties (point) (point-max))
4481-
org--file-cache)
4482-
(funcall (if noerror #'message #'user-error)
4483-
"Unable to fetch file from %S"
4484-
file)
4485-
nil)))
4499+
(if (org--should-fetch-remote-resource-p file)
4500+
(with-current-buffer (url-retrieve-synchronously file)
4501+
(goto-char (point-min))
4502+
;; Move point to after the url-retrieve header.
4503+
(search-forward "\n\n" nil :move)
4504+
;; Search for the success code only in the url-retrieve header.
4505+
(if (save-excursion
4506+
(re-search-backward "HTTP.*\\s-+200\\s-OK" nil :noerror))
4507+
;; Update the cache `org--file-cache' and return contents.
4508+
(puthash file
4509+
(buffer-substring-no-properties (point) (point-max))
4510+
org--file-cache)
4511+
(funcall (if noerror #'message #'user-error)
4512+
"Unable to fetch file from %S"
4513+
file)
4514+
nil))
4515+
(funcall (if noerror #'message #'user-error)
4516+
"The remote resource %S is considered unsafe, and will not be downloaded."
4517+
file)))
44864518
(t
44874519
(with-temp-buffer
44884520
(condition-case nil
@@ -4495,6 +4527,74 @@ is available. This option applies only if FILE is a URL."
44954527
file)
44964528
nil)))))))
44974529

4530+
(defun org--should-fetch-remote-resource-p (uri)
4531+
"Return non-nil if the URI should be fetched."
4532+
(or (eq org-resource-download-policy t)
4533+
(org--safe-remote-resource-p uri)
4534+
(and (eq org-resource-download-policy 'prompt)
4535+
(org--confirm-resource-safe uri))))
4536+
4537+
(defun org--safe-remote-resource-p (uri)
4538+
"Return non-nil if URI is considered safe.
4539+
This checks every pattern in `org-safe-remote-resources', and
4540+
returns non-nil if any of them match."
4541+
(let ((uri-patterns org-safe-remote-resources)
4542+
(file-uri (and buffer-file-name
4543+
(concat "file://" (file-truename buffer-file-name))))
4544+
match-p)
4545+
(while (and (not match-p) uri-patterns)
4546+
(setq match-p (or (string-match-p (car uri-patterns) uri)
4547+
(and file-uri (string-match-p (car uri-patterns) file-uri)))
4548+
uri-patterns (cdr uri-patterns)))
4549+
match-p))
4550+
4551+
(defun org--confirm-resource-safe (uri)
4552+
"Ask the user if URI should be considered safe, returning non-nil if so."
4553+
(unless noninteractive
4554+
(let ((current-file (and buffer-file-name (file-truename buffer-file-name)))
4555+
(buf (get-buffer-create "*Org Remote Resource*")))
4556+
;; Set up the contents of the *Org Remote Resource* buffer.
4557+
(with-current-buffer buf
4558+
(erase-buffer)
4559+
(insert "An org-mode document would like to download "
4560+
(propertize uri 'face '(:inherit org-link :weight normal))
4561+
", which is not considered safe.\n\n"
4562+
"Do you want to download this? You can type\n "
4563+
(propertize "!" 'face 'success)
4564+
" to download this resource, and permanantly mark it as safe.\n "
4565+
(propertize "f" 'face 'success)
4566+
" to download this resource, and permanantly mark all resources in "
4567+
(propertize current-file 'face 'fixed-pitch-serif)
4568+
" as safe.\n "
4569+
(propertize "y" 'face 'warning)
4570+
" to download this resource, just this once.\n "
4571+
(propertize "n" 'face 'error)
4572+
" to skip this resource.\n")
4573+
(setq-local cursor-type nil)
4574+
(set-buffer-modified-p nil)
4575+
(goto-char (point-min)))
4576+
;; Display the buffer and read a choice.
4577+
(save-window-excursion
4578+
(pop-to-buffer buf)
4579+
(let* ((exit-chars '(?y ?n ?! ?f ?\s))
4580+
(prompt (format "Please type y, n, f, or !%s: "
4581+
(if (< (line-number-at-pos (point-max))
4582+
(window-body-height))
4583+
""
4584+
", or C-v/M-v to scroll")))
4585+
char)
4586+
(setq char (read-char-choice prompt exit-chars))
4587+
(when (memq char '(?! ?f))
4588+
(customize-push-and-save
4589+
'org-safe-remote-resources
4590+
(list (rx string-start
4591+
(literal
4592+
(if (and (= char ?f) current-file)
4593+
(concat "file://" current-file) uri))
4594+
string-end))))
4595+
(prog1 (memq char '(?! ?\s ?y ?f))
4596+
(quit-window t)))))))
4597+
44984598
(defun org-extract-log-state-settings (x)
44994599
"Extract the log state setting from a TODO keyword string.
45004600
This will extract info from a string like \"WAIT(w@/!)\"."

0 commit comments

Comments
 (0)