diff options
| author | Chong Yidong | 2011-01-08 14:19:55 -0500 |
|---|---|---|
| committer | Chong Yidong | 2011-01-08 14:19:55 -0500 |
| commit | 278f68456b8c25fff6d2274476cdc8ee3609f68b (patch) | |
| tree | a3366a2afbb024409409486534f43e053e643039 | |
| parent | 3ef01959de6b49dc0db5a930154a6f915f7a2678 (diff) | |
| download | emacs-278f68456b8c25fff6d2274476cdc8ee3609f68b.tar.gz emacs-278f68456b8c25fff6d2274476cdc8ee3609f68b.zip | |
Load themes using `load', querying if theme file not known safe.
* custom.el (custom-safe-theme-files): New defcustom.
(custom-theme-load-confirm): New function.
(load-theme): Load theme using `load', confirming with
custom-theme-load-confirm if necessary.
| -rw-r--r-- | etc/NEWS | 4 | ||||
| -rw-r--r-- | lisp/ChangeLog | 5 | ||||
| -rw-r--r-- | lisp/custom.el | 111 |
3 files changed, 88 insertions, 32 deletions
| @@ -219,6 +219,10 @@ Emacs no longer looks for custom themes in `load-path'. The default | |||
| 219 | is to search in `custom-theme-directory', followed by a built-in theme | 219 | is to search in `custom-theme-directory', followed by a built-in theme |
| 220 | directory named "themes/" in `data-directory'. | 220 | directory named "themes/" in `data-directory'. |
| 221 | 221 | ||
| 222 | *** New option `custom-safe-theme-files' lists known-safe theme files. | ||
| 223 | If a theme is not in this list, Emacs queries before loading it. | ||
| 224 | The default value treats all themes included in Emacs as safe. | ||
| 225 | |||
| 222 | ** The user option `remote-file-name-inhibit-cache' controls whether | 226 | ** The user option `remote-file-name-inhibit-cache' controls whether |
| 223 | the remote file-name cache is used for read access. | 227 | the remote file-name cache is used for read access. |
| 224 | 228 | ||
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 0f84b977d56..86f9e8fa0b9 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,5 +1,10 @@ | |||
| 1 | 2011-01-08 Chong Yidong <cyd@stupidchicken.com> | 1 | 2011-01-08 Chong Yidong <cyd@stupidchicken.com> |
| 2 | 2 | ||
| 3 | * custom.el (custom-safe-theme-files): New defcustom. | ||
| 4 | (custom-theme-load-confirm): New function. | ||
| 5 | (load-theme): Load theme using `load', confirming with | ||
| 6 | custom-theme-load-confirm if necessary. | ||
| 7 | |||
| 3 | * subr.el (read-char-choice): New function, factored out from | 8 | * subr.el (read-char-choice): New function, factored out from |
| 4 | dired-query and hack-local-variables-confirm. | 9 | dired-query and hack-local-variables-confirm. |
| 5 | 10 | ||
diff --git a/lisp/custom.el b/lisp/custom.el index bcb78e46a3c..f984d132dd1 100644 --- a/lisp/custom.el +++ b/lisp/custom.el | |||
| @@ -1105,15 +1105,26 @@ property `theme-feature' (which is usually a symbol created by | |||
| 1105 | (let ((custom-enabling-themes t)) | 1105 | (let ((custom-enabling-themes t)) |
| 1106 | (enable-theme 'user)))) | 1106 | (enable-theme 'user)))) |
| 1107 | 1107 | ||
| 1108 | (defcustom custom-safe-theme-files '(default) | ||
| 1109 | "List of theme files that are considered safe to load. | ||
| 1110 | Each list element should be either an absolute file name, or the | ||
| 1111 | symbol `default', which stands for the built-in Emacs theme | ||
| 1112 | directory (a directory named \"themes\" in `data-directory'." | ||
| 1113 | :type '(repeat | ||
| 1114 | (choice file (const :tag "Built-in theme directory" default))) | ||
| 1115 | :group 'customize | ||
| 1116 | :version "24.1") | ||
| 1117 | |||
| 1108 | (defvar safe-functions) ; From unsafep.el | 1118 | (defvar safe-functions) ; From unsafep.el |
| 1109 | 1119 | ||
| 1110 | (defun load-theme (theme &optional no-enable) | 1120 | (defun load-theme (theme &optional no-enable) |
| 1111 | "Load a theme's settings from its file. | 1121 | "Load a theme's settings from its file. |
| 1112 | Normally, this also enables the theme; use `disable-theme' to | 1122 | Normally, this also enables the theme; use `disable-theme' to |
| 1113 | disable it. If optional arg NO-ENABLE is non-nil, don't enable | 1123 | disable it. If optional arg NO-ENABLE is non-nil, don't enable |
| 1114 | the theme." | 1124 | the theme. |
| 1115 | ;; Note we do no check for validity of the theme here. | 1125 | |
| 1116 | ;; This allows to pull in themes by a file-name convention | 1126 | A theme file is named THEME-theme.el, where THEME is the theme name, |
| 1127 | in one of the directories specified by `custom-theme-load-path'." | ||
| 1117 | (interactive | 1128 | (interactive |
| 1118 | (list | 1129 | (list |
| 1119 | (intern (completing-read "Load custom theme: " | 1130 | (intern (completing-read "Load custom theme: " |
| @@ -1132,35 +1143,71 @@ the theme." | |||
| 1132 | '("" "c")))) | 1143 | '("" "c")))) |
| 1133 | (unless fn | 1144 | (unless fn |
| 1134 | (error "Unable to find theme file for `%s'." theme)) | 1145 | (error "Unable to find theme file for `%s'." theme)) |
| 1135 | ;; Instead of simply loading the theme file, read it manually. | 1146 | ;; Check file safety. |
| 1136 | (with-temp-buffer | 1147 | (when (or (and (memq 'default custom-safe-theme-files) |
| 1137 | (insert-file-contents fn) | 1148 | (equal (file-name-directory fn) |
| 1138 | (require 'unsafep) | 1149 | (expand-file-name "themes/" data-directory))) |
| 1139 | (let ((custom--inhibit-theme-enable no-enable) | 1150 | (member fn custom-safe-theme-files) |
| 1140 | (safe-functions (append '(custom-theme-set-variables | 1151 | ;; If the file is not in the builtin theme directory or |
| 1141 | custom-theme-set-faces) | 1152 | ;; in `custom-safe-theme-files', check it with unsafep. |
| 1142 | safe-functions)) | 1153 | (with-temp-buffer |
| 1143 | form scar) | 1154 | (require 'unsafep) |
| 1144 | (while (setq form (let ((read-circle nil)) | 1155 | (insert-file-contents fn) |
| 1145 | (condition-case nil | 1156 | (let ((safe-functions (append '(provide-theme deftheme |
| 1146 | (read (current-buffer)) | 1157 | custom-theme-set-variables |
| 1147 | (end-of-file nil)))) | 1158 | custom-theme-set-faces) |
| 1148 | (cond | 1159 | safe-functions)) |
| 1149 | ;; Check `deftheme' expressions. | 1160 | unsafep form) |
| 1150 | ((eq (setq scar (car form)) 'deftheme) | 1161 | (while (and (setq form (condition-case nil |
| 1151 | (unless (eq (cadr form) theme) | 1162 | (let ((read-circle nil)) |
| 1152 | (error "Incorrect theme name in `deftheme'")) | 1163 | (read (current-buffer))) |
| 1153 | (and (symbolp (nth 1 form)) | 1164 | (end-of-file nil))) |
| 1154 | (stringp (nth 2 form)) | 1165 | (null (setq unsafep (unsafep form))))) |
| 1155 | (eval (list scar (nth 1 form) (nth 2 form))))) | 1166 | (or (null unsafep) |
| 1156 | ;; Check `provide-theme' expressions. | 1167 | (custom-theme-load-confirm fn))))) |
| 1157 | ((and (eq scar 'provide-theme) | 1168 | (let ((custom--inhibit-theme-enable no-enable)) |
| 1158 | (equal (cadr form) `(quote ,theme)) | 1169 | (load fn))))) |
| 1159 | (= (length form) 2)) | 1170 | |
| 1160 | (eval form)) | 1171 | (defun custom-theme-load-confirm (filename) |
| 1161 | ;; All other expressions need to be safe. | 1172 | (if noninteractive |
| 1162 | ((not (unsafep form)) | 1173 | nil |
| 1163 | (eval form)))))))) | 1174 | (let ((existing-buffer (find-buffer-visiting filename)) |
| 1175 | (exit-chars '(?y ?n ?\s ?\C-g)) | ||
| 1176 | prompt char) | ||
| 1177 | (save-window-excursion | ||
| 1178 | (if existing-buffer | ||
| 1179 | (pop-to-buffer existing-buffer) | ||
| 1180 | (find-file filename)) | ||
| 1181 | (unwind-protect | ||
| 1182 | (progn | ||
| 1183 | (setq prompt | ||
| 1184 | (format "This theme is not guaranteed to be safe. Really load? %s" | ||
| 1185 | (if (< (line-number-at-pos (point-max)) | ||
| 1186 | (window-body-height)) | ||
| 1187 | "(y or n) " | ||
| 1188 | (push ?\C-v exit-chars) | ||
| 1189 | "Type y or n, or C-v to scroll: "))) | ||
| 1190 | (goto-char (point-min)) | ||
| 1191 | (while (null char) | ||
| 1192 | (setq char (read-char-choice prompt exit-chars t)) | ||
| 1193 | (when (eq char ?\C-v) | ||
| 1194 | (condition-case nil | ||
| 1195 | (scroll-up) | ||
| 1196 | (error (goto-char (point-min)))) | ||
| 1197 | (setq char nil))) | ||
| 1198 | (when (memq char '(?\s ?y)) | ||
| 1199 | (push filename custom-safe-theme-files) | ||
| 1200 | ;; Offer to save to `custom-safe-theme-files'. | ||
| 1201 | (and (or custom-file user-init-file) | ||
| 1202 | (y-or-n-p "Treat %s as safe for future loads? " | ||
| 1203 | (file-name-nondirectory filename)) | ||
| 1204 | (let ((coding-system-for-read nil)) | ||
| 1205 | (customize-save-variable | ||
| 1206 | 'custom-safe-theme-files | ||
| 1207 | custom-safe-theme-files))) | ||
| 1208 | t)) | ||
| 1209 | ;; Unwind form. | ||
| 1210 | (unless existing-buffer (kill-buffer))))))) | ||
| 1164 | 1211 | ||
| 1165 | (defun custom-theme-name-valid-p (name) | 1212 | (defun custom-theme-name-valid-p (name) |
| 1166 | "Return t if NAME is a valid name for a Custom theme, nil otherwise. | 1213 | "Return t if NAME is a valid name for a Custom theme, nil otherwise. |