;;; mm-url.el --- a wrapper of url functions/commands for Gnus
-;; Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+
+;; Copyright (C) 2001-2011 Free Software Foundation, Inc.
;; Author: Shenghuo Zhu <zsh@cs.rochester.edu>
;; This file is part of GNU Emacs.
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published
-;; by the Free Software Foundation; either version 2, or (at your
-;; option) any later version.
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
-;; GNU Emacs is distributed in the hope that it will be useful, but
-;; WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-;; General Public License for more details.
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
(require 'mm-util)
(require 'gnus)
-(eval-and-compile
- (autoload 'executable-find "executable"))
-
-(eval-when-compile
- (require 'timer))
+(defvar url-current-object)
+(defvar url-package-name)
+(defvar url-package-version)
(defgroup mm-url nil
"A wrapper of url package and external url command for Gnus."
(require 'url)
(error nil)))
"*If non-nil, use external grab program `mm-url-program'."
+ :version "22.1"
:type 'boolean
:group 'mm-url)
'((wget "wget" "--user-agent=mm-url" "-q" "-O" "-")
(w3m "w3m" "-dump_source")
(lynx "lynx" "-source")
- (curl "curl")))
+ (curl "curl" "--silent" "--user-agent" "mm-url" "--location")))
(defcustom mm-url-program
(cond
(t "GET"))
"The url grab program.
Likely values are `wget', `w3m', `lynx' and `curl'."
+ :version "22.1"
:type '(choice
(symbol :tag "wget" wget)
(symbol :tag "w3m" w3m)
(defcustom mm-url-arguments nil
"The arguments for `mm-url-program'."
+ :version "22.1"
:type '(repeat string)
:group 'mm-url)
(defun mm-url-load-url ()
"Load `url-insert-file-contents'."
(unless (condition-case ()
- (require 'url-handlers)
+ (progn
+ (require 'url-handlers)
+ (require 'url-parse)
+ (require 'url-vars))
(error nil))
;; w3-4.0pre0.46 or earlier version.
(require 'w3-vars)
(require 'url)))
+;;;###autoload
(defun mm-url-insert-file-contents (url)
+ "Insert file contents of URL.
+If `mm-url-use-external' is non-nil, use `mm-url-program'."
(if mm-url-use-external
(progn
(if (string-match "^file:/+" url)
(mm-url-insert-file-contents-external url))
(goto-char (point-min))
(if (fboundp 'url-generic-parse-url)
- (setq url-current-object
+ (setq url-current-object
(url-generic-parse-url url)))
(list url (buffer-size)))
(mm-url-load-url)
(let ((name buffer-file-name)
- (url-request-extra-headers (list (cons "Connection" "Close")))
+ (url-request-extra-headers
+ ;; ISTM setting a Connection header was a workaround for
+ ;; older versions of url included with w3, but it does more
+ ;; harm than good with the one shipped with Emacs. --ansel
+ (if (not (and (boundp 'url-version)
+ (equal url-version "Emacs")))
+ (list (cons "Connection" "Close"))))
(url-package-name (or mm-url-package-name
url-package-name))
(url-package-version (or mm-url-package-version
(car result))))
result)))
+;;;###autoload
(defun mm-url-insert-file-contents-external (url)
+ "Insert file contents of URL using `mm-url-program'."
(let (program args)
(if (symbolp mm-url-program)
(let ((item (cdr (assq mm-url-program mm-url-predefined-programs))))
(defun mm-url-decode-entities ()
"Decode all HTML entities."
(goto-char (point-min))
- (while (re-search-forward "&\\(#[0-9]+\\|[a-z]+\\);" nil t)
- (let ((elem (if (eq (aref (match-string 1) 0) ?\#)
- (let ((c
- (string-to-number (substring
- (match-string 1) 1))))
- (if (mm-char-or-char-int-p c) c 32))
- (or (cdr (assq (intern (match-string 1))
- mm-url-html-entities))
- ?#))))
+ (while (re-search-forward "&\\(#[0-9]+\\|#x[0-9a-f]+\\|[a-z]+[0-9]*\\);"
+ nil t)
+ (let* ((entity (match-string 1))
+ (elem (if (eq (aref entity 0) ?\#)
+ (let ((c
+ ;; Hex number: ㈒
+ (if (eq (aref entity 1) ?x)
+ (string-to-number (substring entity 2)
+ 16)
+ ;; Decimal number: 
+ (string-to-number (substring entity 1)))))
+ (setq c (or (cdr (assq c mm-extra-numeric-entities))
+ (mm-ucs-to-char c)))
+ (if (mm-char-or-char-int-p c) c ?#))
+ (or (cdr (assq (intern entity)
+ mm-url-html-entities))
+ ?#))))
(unless (stringp elem)
(setq elem (char-to-string elem)))
(replace-match elem t t))))
((= char ? ) "+")
((memq char mm-url-unreserved-chars) (char-to-string char))
(t (upcase (format "%%%02x" char)))))
- ;; Fixme: Should this actually be accepting multibyte? Is there a
- ;; better way in XEmacs?
- (if (featurep 'mule)
- (encode-coding-string chunk
- (if (fboundp 'find-coding-systems-string)
- (car (find-coding-systems-string chunk))
- buffer-file-coding-system))
- chunk)
+ (mm-encode-coding-string chunk
+ (if (fboundp 'find-coding-systems-string)
+ (car (find-coding-systems-string chunk))
+ buffer-file-coding-system))
""))
(defun mm-url-encode-www-form-urlencoded (pairs)
(mm-url-form-encode-xwfu (cdr data))))
pairs "&"))
+(autoload 'mml-compute-boundary "mml")
+
+(defun mm-url-encode-multipart-form-data (pairs &optional boundary)
+ "Return PAIRS encoded in multipart/form-data."
+ ;; RFC1867
+
+ ;; Get a good boundary
+ (unless boundary
+ (setq boundary (mml-compute-boundary '())))
+
+ (concat
+
+ ;; Start with the boundary
+ "--" boundary "\r\n"
+
+ ;; Create name value pairs
+ (mapconcat
+ 'identity
+ ;; Delete any returned items that are empty
+ (delq nil
+ (mapcar (lambda (data)
+ (when (car data)
+ ;; For each pair
+ (concat
+
+ ;; Encode the name
+ "Content-Disposition: form-data; name=\""
+ (car data) "\"\r\n"
+ "Content-Type: text/plain; charset=utf-8\r\n"
+ "Content-Transfer-Encoding: binary\r\n\r\n"
+
+ (cond ((stringp (cdr data))
+ (cdr data))
+ ((integerp (cdr data))
+ (int-to-string (cdr data))))
+
+ "\r\n")))
+ pairs))
+ ;; use the boundary as a separator
+ (concat "--" boundary "\r\n"))
+
+ ;; put a boundary at the end.
+ "--" boundary "--\r\n"))
+
(defun mm-url-fetch-form (url pairs)
"Fetch a form from URL with PAIRS as the data using the POST method."
(mm-url-load-url)