Commit 0565caeb authored by Miles Bader's avatar Miles Bader
Browse files

Revision: emacs@sv.gnu.org/emacs--devo--0--patch-249

Merge from gnus--rel--5.10

Patches applied:

 * gnus--rel--5.10  (patch 91-95)

   - Merge from emacs--devo--0
   - Update from CVS
parent 8570ce80
2006-04-26 Reiner Steib <Reiner.Steib@gmx.de>
* deuglify.el (gnus-outlook-deuglify-unwrap-min)
(gnus-outlook-deuglify-unwrap-max): Remove autoload.
* mml-sec.el (mml-secure-method): New internal variable.
(mml-secure-sign, mml-secure-encrypt, mml-secure-message-sign)
(mml-secure-message-sign-encrypt, mml-secure-message-encrypt): New
functions using mml-secure-method. Sync from the trunk.
* mml.el (mml-mode-map): Add key bindings for those functions.
(mml-menu): Simplify security menu entries. Suggested by Jesper
Harder <harder@myrealbox.com>. Sync from the trunk.
* message.el (message-valid-fqdn-regexp): Add TLDs .cat, jobs,
.mobi and .travel. Remove .nato, .bitnet and .uucp.
(message-in-body-p): New function. Sync from the trunk.
* mml.el (mml-mode, mml-dnd-protocol-alist)
(mml-dnd-attach-options, mml-dnd-attach-file)
(mml-attach-file, mml-attach-buffer, mml-attach-external): Sync
DND support and use of message-in-body-p from the trunk.
2006-04-25 Andreas Seltenreich <uwi7@rz.uni-karlsruhe.de>
* nnweb.el (nnweb-google-wash-article): Sync up to new Google
HTML.
2006-04-25 Katsumi Yamaoka <yamaoka@jpl.org>
* mm-uu.el (mm-uu-pgp-signed-test): Erase prompt.
(mm-uu-pgp-encrypted-test): Ditto.
(mm-uu-pgp-encrypted-extract-1): Make sure there's a blank line
between header and body; return application/pgp-encrypted handle
if decryption failed; decode decrypted body by charset.
* mm-decode.el (mm-automatic-display): Don't make application/pgp
element match to application/pgp-*.
2006-04-20 Reiner Steib <Reiner.Steib@gmx.de>
* gnus-util.el (gnus-replace-in-string): Prefer
......
......@@ -234,14 +234,12 @@
:version "22.1"
:group 'gnus)
;;;###autoload
(defcustom gnus-outlook-deuglify-unwrap-min 45
"Minimum length of the cited line above the (possibly) wrapped line."
:version "22.1"
:type 'integer
:group 'gnus-outlook-deuglify)
;;;###autoload
(defcustom gnus-outlook-deuglify-unwrap-max 95
"Maximum length of the cited line after unwrapping."
:version "22.1"
......@@ -288,7 +286,6 @@
:type 'string
:group 'gnus-outlook-deuglify)
;;;###autoload
(defcustom gnus-outlook-display-hook nil
"A hook called after an deuglified article has been prepared.
It is run after `gnus-article-prepare-hook'."
......
......@@ -1586,11 +1586,16 @@ functionality to work."
(defcustom message-valid-fqdn-regexp
(concat "[a-z0-9][-.a-z0-9]+\\." ;; [hostname.subdomain.]domain.
;; valid TLDs:
"\\([a-z][a-z]" ;; two letter country TDLs
"\\|biz\\|com\\|edu\\|gov\\|int\\|mil\\|net\\|org"
"\\|aero\\|coop\\|info\\|name\\|museum"
"\\|arpa\\|pro\\|uucp\\|bitnet\\|bofh" ;; old style?
"\\)")
"\\([a-z][a-z]\\|" ;; two letter country TDLs
"aero\\|arpa\\|bitnet\\|biz\\|bofh\\|"
"cat\\|com\\|coop\\|edu\\|gov\\|"
"info\\|int\\|jobs\\|"
"mil\\|mobi\\|museum\\|name\\|net\\|"
"org\\|pro\\|travel\\|uucp\\)")
;; http://en.wikipedia.org/wiki/List_of_Internet_top-level_domains
;; http://en.wikipedia.org/wiki/GTLD
;; `in the process of being approved': .asia .post .tel .sex
;; "dead" nato bitnet uucp
"Regular expression that matches a valid FQDN."
;; see also: gnus-button-valid-fqdn-regexp
:version "22.1"
......@@ -2679,6 +2684,11 @@ M-RET `message-newline-and-reformat' (break the line and reformat)."
(or (search-forward (concat "\n" mail-header-separator "\n") nil t)
(search-forward-regexp "[^:]+:\\([^\n]\\|\n[ \t]\\)+\n\n" nil t)))
(defun message-in-body-p ()
"Return t if point is in the message body."
(let ((body (save-excursion (message-goto-body) (point))))
(>= (point) body)))
(defun message-goto-eoh ()
"Move point to the end of the headers."
(interactive)
......
......@@ -307,7 +307,7 @@ when selecting a different article."
"application/pkcs7-signature" "application/x-pkcs7-mime"
"application/pkcs7-mime"
;; Mutt still uses this even though it has already been withdrawn.
"application/pgp")
"application/pgp\\'")
"A list of MIME types to be displayed automatically."
:type '(repeat regexp)
:group 'mime-display)
......
......@@ -352,7 +352,9 @@ Return that buffer."
((eq mm-verify-option 'never) nil)
((eq mm-verify-option 'always) t)
((eq mm-verify-option 'known) t)
(t (y-or-n-p "Verify pgp signed part? ")))))
(t (prog1
(y-or-n-p "Verify pgp signed part? ")
(message ""))))))
(eval-when-compile
(defvar gnus-newsgroup-charset))
......@@ -403,15 +405,44 @@ Return that buffer."
((eq mm-decrypt-option 'never) nil)
((eq mm-decrypt-option 'always) t)
((eq mm-decrypt-option 'known) t)
(t (y-or-n-p "Decrypt pgp encrypted part? ")))))
(t (prog1
(y-or-n-p "Decrypt pgp encrypted part? ")
(message ""))))))
(defun mm-uu-pgp-encrypted-extract-1 (handles ctl)
(let ((buf (mm-uu-copy-to-buffer (point-min) (point-max))))
(if (mm-uu-pgp-encrypted-test)
(with-current-buffer buf
(mml2015-clean-buffer)
(funcall (mml2015-clear-decrypt-function))))
(list (mm-make-handle buf mm-uu-text-plain-type))))
(let ((buf (mm-uu-copy-to-buffer (point-min) (point-max)))
(first t)
charset)
;; Make sure there's a blank line between header and body.
(with-current-buffer buf
(goto-char (point-min))
(while (prog2
(forward-line 1)
(if first
(looking-at "[^\t\n ]+:")
(looking-at "[^\t\n ]+:\\|[\t ]"))
(setq first nil)))
(unless (memq (char-after) '(?\n nil))
(insert "\n"))
(save-restriction
(narrow-to-region (point-min) (point))
(setq charset (mail-fetch-field "charset")))
(if (and (mm-uu-pgp-encrypted-test)
(progn
(mml2015-clean-buffer)
(funcall (mml2015-clear-decrypt-function))
(equal (mm-handle-multipart-ctl-parameter mm-security-handle
'gnus-info)
"OK")))
(progn
;; Decode charset.
(when (and (or charset
(setq charset gnus-newsgroup-charset))
(setq charset (mm-charset-to-coding-system charset))
(not (eq charset 'ascii)))
(mm-decode-coding-region (point-min) (point-max) charset))
(list (mm-make-handle buf mm-uu-text-plain-type)))
(list (mm-make-handle buf '("application/pgp-encrypted")))))))
(defun mm-uu-pgp-encrypted-extract ()
(let ((mm-security-handle (list (format "multipart/encrypted"))))
......
......@@ -188,6 +188,29 @@ You can also customize or set `mml-signencrypt-style-alist' instead."
(cons method tags))))
(t (error "The message is corrupted. No mail header separator"))))))
(defvar mml-secure-method
(if (equal mml-default-encrypt-method mml-default-sign-method)
mml-default-sign-method
"pgpmime")
"Current security method. Internal variable.")
(defun mml-secure-sign (&optional method)
"Add MML tags to sign this MML part.
Use METHOD if given. Else use `mml-secure-method' or
`mml-default-sign-method'."
(interactive)
(mml-secure-part
(or method mml-secure-method mml-default-sign-method)
'sign))
(defun mml-secure-encrypt (&optional method)
"Add MML tags to encrypt this MML part.
Use METHOD if given. Else use `mml-secure-method' or
`mml-default-sign-method'."
(interactive)
(mml-secure-part
(or method mml-secure-method mml-default-sign-method)))
(defun mml-secure-sign-pgp ()
"Add MML tags to PGP sign this MML part."
(interactive)
......@@ -249,6 +272,34 @@ You can also customize or set `mml-signencrypt-style-alist' instead."
(when (re-search-backward "^<#secure.*>\n" nil t)
(delete-region (match-beginning 0) (match-end 0)))))
(defun mml-secure-message-sign (&optional method)
"Add MML tags to sign this MML part.
Use METHOD if given. Else use `mml-secure-method' or
`mml-default-sign-method'."
(interactive)
(mml-secure-part
(or method mml-secure-method mml-default-sign-method)
'sign))
(defun mml-secure-message-sign-encrypt (&optional method)
"Add MML tag to sign and encrypt the entire message.
Use METHOD if given. Else use `mml-secure-method' or
`mml-default-sign-method'."
(interactive)
(mml-secure-message
(or method mml-secure-method mml-default-sign-method)
'signencrypt))
(defun mml-secure-message-encrypt (&optional method)
"Add MML tag to encrypt the entire message.
Use METHOD if given. Else use `mml-secure-method' or
`mml-default-sign-method'."
(interactive)
(mml-secure-message
(or method mml-secure-method mml-default-sign-method)
'encrypt))
(defun mml-secure-message-sign-smime ()
"Add MML tag to encrypt/sign the entire message."
(interactive)
......
......@@ -40,7 +40,8 @@
(autoload 'message-fetch-field "message")
(autoload 'message-info "message")
(autoload 'fill-flowed-encode "flow-fill")
(autoload 'message-posting-charset "message"))
(autoload 'message-posting-charset "message")
(autoload 'dnd-get-local-file-name "dnd"))
(defvar gnus-article-mime-handles)
(defvar gnus-mouse-2)
......@@ -51,6 +52,7 @@
(defvar message-posting-charset)
(defvar message-required-mail-headers)
(defvar message-required-news-headers)
(defvar dnd-protocol-alist)
(defcustom mml-content-type-parameters
'(name access-type expiration size permission format)
......@@ -878,6 +880,11 @@ If HANDLES is non-nil, use it instead reparsing the buffer."
(encryptpart (make-sparse-keymap))
(map (make-sparse-keymap))
(main (make-sparse-keymap)))
(define-key map "\C-s" 'mml-secure-message-sign)
(define-key map "\C-c" 'mml-secure-message-encrypt)
(define-key map "\C-e" 'mml-secure-message-sign-encrypt)
(define-key map "\C-p\C-s" 'mml-secure-sign)
(define-key map "\C-p\C-c" 'mml-secure-encrypt)
(define-key sign "p" 'mml-secure-message-sign-pgpmime)
(define-key sign "o" 'mml-secure-message-sign-pgp)
(define-key sign "s" 'mml-secure-message-sign-smime)
......@@ -915,26 +922,54 @@ If HANDLES is non-nil, use it instead reparsing the buffer."
["Attach File..." mml-attach-file
,@(if (featurep 'xemacs) '(t)
'(:help "Attach a file at point"))]
["Attach Buffer..." mml-attach-buffer t]
["Attach External..." mml-attach-external t]
["Insert Part..." mml-insert-part t]
["Insert Multipart..." mml-insert-multipart t]
["PGP/MIME Sign" mml-secure-message-sign-pgpmime t]
["PGP/MIME Encrypt" mml-secure-message-encrypt-pgpmime t]
["PGP Sign" mml-secure-message-sign-pgp t]
["PGP Encrypt" mml-secure-message-encrypt-pgp t]
["S/MIME Sign" mml-secure-message-sign-smime t]
["S/MIME Encrypt" mml-secure-message-encrypt-smime t]
("Secure MIME part"
["PGP/MIME Sign Part" mml-secure-sign-pgpmime t]
["PGP/MIME Encrypt Part" mml-secure-encrypt-pgpmime t]
["PGP Sign Part" mml-secure-sign-pgp t]
["PGP Encrypt Part" mml-secure-encrypt-pgp t]
["S/MIME Sign Part" mml-secure-sign-smime t]
["S/MIME Encrypt Part" mml-secure-encrypt-smime t])
["Encrypt/Sign off" mml-unsecure-message t]
["Attach Buffer..." mml-attach-buffer
,@(if (featurep 'xemacs) '(t)
'(:help "Attach a buffer to the outgoing MIME message"))]
["Attach External..." mml-attach-external
,@(if (featurep 'xemacs) '(t)
'(:help "Attach reference to file"))]
;;
("Change Security Method"
["PGP/MIME"
(lambda () (interactive) (setq mml-secure-method "pgpmime"))
,@(if (featurep 'xemacs) nil
'(:help "Set Security Method to PGP/MIME"))
:style radio
:selected (equal mml-secure-method "pgpmime") ]
["S/MIME"
(lambda () (interactive) (setq mml-secure-method "smime"))
,@(if (featurep 'xemacs) nil
'(:help "Set Security Method to S/MIME"))
:style radio
:selected (equal mml-secure-method "smime") ]
["Inline PGP"
(lambda () (interactive) (setq mml-secure-method "pgp"))
,@(if (featurep 'xemacs) nil
'(:help "Set Security Method to inline PGP"))
:style radio
:selected (equal mml-secure-method "pgp") ] )
;;
["Sign Message" mml-secure-message-sign t]
["Encrypt Message" mml-secure-message-encrypt t]
["Sign and Encrypt Message" mml-secure-message-sign-encrypt t]
["Encrypt/Sign off" mml-unsecure-message
,@(if (featurep 'xemacs) '(t)
'(:help "Don't Encrypt/Sign Message"))]
;; Maybe we could remove these, because people who write MML most probably
;; don't use the menu:
["Insert Part..." mml-insert-part
:active (message-in-body-p)]
["Insert Multipart..." mml-insert-multipart
:active (message-in-body-p)]
;;
;; Do we have separate encrypt and encrypt/sign commands for parts?
["Sign Part" mml-secure-sign t]
["Encrypt Part" mml-secure-encrypt t]
;;["Narrow" mml-narrow-to-part t]
["Quote MML" mml-quote-region t]
["Quote MML in region" mml-quote-region
:active (message-mark-active-p)
,@(if (featurep 'xemacs) nil
'(:help "Quote MML tags in region"))]
["Validate MML" mml-validate t]
["Preview" mml-preview t]
"----"
......@@ -958,8 +993,11 @@ See Info node `(emacs-mime)Composing'.
(when (set (make-local-variable 'mml-mode)
(if (null arg) (not mml-mode)
(> (prefix-numeric-value arg) 0)))
(gnus-add-minor-mode 'mml-mode " MML" mml-mode-map)
(add-minor-mode 'mml-mode " MML" mml-mode-map)
(easy-menu-add mml-menu mml-mode-map)
(when (boundp 'dnd-protocol-alist)
(set (make-local-variable 'dnd-protocol-alist)
(append mml-dnd-protocol-alist dnd-protocol-alist)))
(run-hooks 'mml-mode-hook)))
;;;
......@@ -1057,6 +1095,36 @@ See Info node `(emacs-mime)Composing'.
;;; Attachment functions.
(defcustom mml-dnd-protocol-alist
'(("^file:///" . mml-dnd-attach-file)
("^file://" . dnd-open-file)
("^file:" . mml-dnd-attach-file))
"The functions to call when a drop in `mml-mode' is made.
See `dnd-protocol-alist' for more information. When nil, behave
as in other buffers."
:type '(choice (repeat (cons (regexp) (function)))
(const :tag "Behave as in other buffers" nil))
:version "22.1" ;; Gnus 5.10.9
:group 'message)
(defcustom mml-dnd-attach-options nil
"Which options should be queried when attaching a file via drag and drop.
If it is a list, valid members are `type', `description' and
`disposition'. `disposition' implies `type'. If it is nil,
don't ask for options. If it is t, ask the user whether or not
to specify options."
:type '(choice
(const :tag "Non" nil)
(const :tag "Query" t)
(list :value (type description disposition)
(set :inline t
(const type)
(const description)
(const disposition))))
:version "22.1" ;; Gnus 5.10.9
:group 'message)
(defun mml-attach-file (file &optional type description disposition)
"Attach a file to the outgoing MIME message.
The file is not inserted or encoded until you send the message with
......@@ -1074,11 +1142,37 @@ body) or \"attachment\" (separate from the body)."
(description (mml-minibuffer-read-description))
(disposition (mml-minibuffer-read-disposition type)))
(list file type description disposition)))
(mml-insert-empty-tag 'part
'type type
'filename file
'disposition (or disposition "attachment")
'description description))
(save-excursion
(unless (message-in-body-p) (goto-char (point-max)))
(mml-insert-empty-tag 'part
'type type
'filename file
'disposition (or disposition "attachment")
'description description)))
(defun mml-dnd-attach-file (uri action)
"Attach a drag and drop file.
Ask for type, description or disposition according to
`mml-dnd-attach-options'."
(let ((file (dnd-get-local-file-name uri t)))
(when (and file (file-regular-p file))
(let ((mml-dnd-attach-options mml-dnd-attach-options)
type description disposition)
(setq mml-dnd-attach-options
(when (and (eq mml-dnd-attach-options t)
(not
(y-or-n-p
"Use default type, disposition and description? ")))
'(type description disposition)))
(when (or (memq 'type mml-dnd-attach-options)
(memq 'disposition mml-dnd-attach-options))
(setq type (mml-minibuffer-read-type file)))
(when (memq 'description mml-dnd-attach-options)
(setq description (mml-minibuffer-read-description)))
(when (memq 'disposition mml-dnd-attach-options)
(setq disposition (mml-minibuffer-read-disposition type)))
(mml-attach-file file type description disposition)))))
(defun mml-attach-buffer (buffer &optional type description)
"Attach a buffer to the outgoing MIME message.
......@@ -1088,8 +1182,11 @@ See `mml-attach-file' for details of operation."
(type (mml-minibuffer-read-type buffer "text/plain"))
(description (mml-minibuffer-read-description)))
(list buffer type description)))
(mml-insert-empty-tag 'part 'type type 'buffer buffer
'disposition "attachment" 'description description))
(save-excursion
(unless (message-in-body-p) (goto-char (point-max)))
(mml-insert-empty-tag 'part 'type type 'buffer buffer
'disposition "attachment"
'description description)))
(defun mml-attach-external (file &optional type description)
"Attach an external file into the buffer.
......@@ -1100,8 +1197,10 @@ TYPE is the MIME type to use."
(type (mml-minibuffer-read-type file))
(description (mml-minibuffer-read-description)))
(list file type description)))
(mml-insert-empty-tag 'external 'type type 'name file
'disposition "attachment" 'description description))
(save-excursion
(unless (message-in-body-p) (goto-char (point-max)))
(mml-insert-empty-tag 'external 'type type 'name file
'disposition "attachment" 'description description)))
(defun mml-insert-multipart (&optional type)
(interactive (list (completing-read "Multipart type (default mixed): "
......
......@@ -229,23 +229,25 @@
(defvar pgg-output-buffer))
(defun mml1991-pgg-sign (cont)
;; Make sure to load pgg.el before binding pgg-* variables.
(require 'pgg)
(let ((pgg-text-mode t)
(pgg-default-user-id (or (message-options-get 'mml-sender)
pgg-default-user-id))
headers cte)
;; Don't sign headers.
(goto-char (point-min))
(while (not (looking-at "^$"))
(forward-line))
(unless (eobp) ;; no headers?
(when (re-search-forward "^$" nil t)
(setq headers (buffer-substring (point-min) (point)))
(forward-line) ;; skip header/body separator
(delete-region (point-min) (point)))
(when (string-match "^Content-Transfer-Encoding: \\(.+\\)" headers)
(setq cte (intern (match-string 1 headers))))
(mm-decode-content-transfer-encoding cte)
(unless (let ((pgg-default-user-id
(or (message-options-get 'mml-sender)
pgg-default-user-id)))
(pgg-sign-region (point-min) (point-max) t))
(save-restriction
(narrow-to-region (point-min) (point))
(setq cte (mail-fetch-field "content-transfer-encoding")))
(forward-line 1)
(delete-region (point-min) (point))
(when cte
(setq cte (intern (downcase cte)))
(mm-decode-content-transfer-encoding cte)))
(unless (pgg-sign-region (point-min) (point-max) t)
(pop-to-buffer pgg-errors-buffer)
(error "Encrypt error"))
(delete-region (point-min) (point-max))
......@@ -254,7 +256,8 @@
(goto-char (point-min))
(while (re-search-forward "\r+$" nil t)
(replace-match "" t t))
(mm-encode-content-transfer-encoding cte)
(when cte
(mm-encode-content-transfer-encoding cte))
(goto-char (point-min))
(when headers
(insert headers))
......@@ -262,34 +265,35 @@
t))
(defun mml1991-pgg-encrypt (cont &optional sign)
(let ((pgg-text-mode t)
cte)
;; Strip MIME Content[^ ]: headers since it will be ASCII ARMOURED
(goto-char (point-min))
(while (looking-at "^Content[^ ]+:")
(when (looking-at "^Content-Transfer-Encoding: \\(.+\\)")
(setq cte (intern (match-string 1))))
(forward-line))
(unless (bobp)
(delete-region (point-min) (point)))
(mm-decode-content-transfer-encoding cte)
(unless (pgg-encrypt-region
(point-min) (point-max)
(split-string
(or
(message-options-get 'message-recipients)
(message-options-set 'message-recipients
(read-string "Recipients: ")))
"[ \f\t\n\r\v,]+")
sign)
(pop-to-buffer pgg-errors-buffer)
(error "Encrypt error"))
(delete-region (point-min) (point-max))
;;(insert "Content-Type: application/pgp-encrypted\n\n")
;;(insert "Version: 1\n\n")
(insert "\n")
(insert-buffer-substring pgg-output-buffer)
t))
(goto-char (point-min))
(when (re-search-forward "^$" nil t)
(let ((cte (save-restriction
(narrow-to-region (point-min) (point))
(mail-fetch-field "content-transfer-encoding"))))
;; Strip MIME headers since it will be ASCII armoured.
(forward-line 1)
(delete-region (point-min) (point))
(when cte
(mm-decode-content-transfer-encoding (intern (downcase cte))))))
(unless (progn
;; Make sure to load pgg.el before binding `pgg-text-mode'.
(require 'pgg)
(let ((pgg-text-mode t))
(pgg-encrypt-region
(point-min) (point-max)
(split-string
(or
(message-options-get 'message-recipients)
(message-options-set 'message-recipients
(read-string "Recipients: ")))
"[ \f\t\n\r\v,]+")
sign)))
(pop-to-buffer pgg-errors-buffer)
(error "Encrypt error"))
(delete-region (point-min) (point-max))
(insert "\n")
(insert-buffer-substring pgg-output-buffer)
t)
;;;###autoload
(defun mml1991-encrypt (cont &optional sign)
......
......@@ -307,8 +307,8 @@ Valid types include `google', `dejanews', and `gmane'.")
(defun nnweb-google-wash-article ()
;; We have Google's masked e-mail addresses here. :-/
(let ((case-fold-search t)
(start-re "<pre>\n *")
(end-re "\n *</pre>"))
(start-re "<pre>[\r\n ]*")
(end-re "[\r\n ]*</pre>"))
(goto-char (point-min))
(if (save-excursion
(or (re-search-forward "The requested message.*could not be found."
......
2006-04-26 Reiner Steib <Reiner.Steib@gmx.de>
* pgg.texi (Caching passphrase): Fix markup and typos. Simplify.
2006-04-26 Sascha Wilde <wilde@sha-bang.de>
* pgg.texi (Caching passphrase): Added documentation for
pgg-gpg-use-agent.
2006-04-24 Bill Wohler <wohler@newt.com>
* mh-e.texi (Getting Started): Made it more explicit that you need
......
......@@ -234,6 +234,14 @@ variable to @code{nil}.
Elapsed time for expiration in seconds.
@end defvar
@defvar pgg-gpg-use-agent
When using GnuPG (gpg) as PGP scheme you can use @code{gpg-agent} for
caching@footnote{Actually @code{gpg-agent} does not cache passphrases
but private keys. On the other hand, from a users point of view this
technical difference isn't visible.}. If non-@code{nil} try to use a
running @code{gpg-agent}. It defaults to @code{nil}.
@end defvar
@node Default user identity
@section Default user identity
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment