@@ -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.
45004600This will extract info from a string like \"WAIT(w@/!)\"."
0 commit comments