url-methods.el 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. ;;; url-methods.el --- Load URL schemes as needed
  2. ;; Copyright (C) 1996-1999, 2004-2012 Free Software Foundation, Inc.
  3. ;; Keywords: comm, data, processes, hypermedia
  4. ;; This file is part of GNU Emacs.
  5. ;; GNU Emacs is free software: you can redistribute it and/or modify
  6. ;; it under the terms of the GNU General Public License as published by
  7. ;; the Free Software Foundation, either version 3 of the License, or
  8. ;; (at your option) any later version.
  9. ;; GNU Emacs is distributed in the hope that it will be useful,
  10. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. ;; GNU General Public License for more details.
  13. ;; You should have received a copy of the GNU General Public License
  14. ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
  15. ;;; Commentary:
  16. ;;; Code:
  17. (eval-when-compile
  18. (require 'cl))
  19. ;; This loads up some of the small, silly URLs that I really don't
  20. ;; want to bother putting in their own separate files.
  21. (require 'url-parse)
  22. (defvar url-scheme-registry (make-hash-table :size 7 :test 'equal))
  23. (defconst url-scheme-methods
  24. '((default-port . variable)
  25. (asynchronous-p . variable)
  26. (expand-file-name . function)
  27. (file-exists-p . function)
  28. (file-attributes . function)
  29. (parse-url . function)
  30. (file-symlink-p . function)
  31. (file-writable-p . function)
  32. (file-directory-p . function)
  33. (file-executable-p . function)
  34. (directory-files . function)
  35. (file-truename . function))
  36. "Assoc-list of methods that each URL loader can provide.")
  37. (defconst url-scheme-default-properties
  38. (list 'name "unknown"
  39. 'loader 'url-scheme-default-loader
  40. 'default-port 0
  41. 'expand-file-name 'url-identity-expander
  42. 'parse-url 'url-generic-parse-url
  43. 'asynchronous-p nil
  44. 'file-directory-p 'ignore
  45. 'file-truename (lambda (&rest args)
  46. (url-recreate-url (car args)))
  47. 'file-exists-p 'ignore
  48. 'file-attributes 'ignore))
  49. (defun url-scheme-default-loader (url &optional callback cbargs)
  50. "Signal an error for an unknown URL scheme."
  51. (error "Unknown URL scheme: %s" (url-type url)))
  52. (defvar url-scheme--registering-proxy nil)
  53. (defun url-scheme-register-proxy (scheme)
  54. "Automatically find a proxy for SCHEME and put it in `url-proxy-services'."
  55. (let* ((env-var (concat scheme "_proxy"))
  56. (env-proxy (or (getenv (upcase env-var))
  57. (getenv (downcase env-var))))
  58. (cur-proxy (assoc scheme url-proxy-services))
  59. (urlobj nil)
  60. (url-scheme--registering-proxy t))
  61. ;; If env-proxy is an empty string, treat it as if it were nil
  62. (when (and (stringp env-proxy)
  63. (string= env-proxy ""))
  64. (setq env-proxy nil))
  65. ;; Store any proxying information - this will not overwrite an old
  66. ;; entry, so that people can still set this information in their
  67. ;; .emacs file
  68. (cond
  69. (cur-proxy nil) ; Keep their old settings
  70. ((null env-proxy) nil) ; No proxy setup
  71. ;; First check if its something like hostname:port
  72. ((string-match "^\\([^:]+\\):\\([0-9]+\\)$" env-proxy)
  73. (setq urlobj (url-generic-parse-url nil)) ; Get a blank object
  74. (setf (url-type urlobj) "http")
  75. (setf (url-host urlobj) (match-string 1 env-proxy))
  76. (setf (url-port urlobj) (string-to-number (match-string 2 env-proxy))))
  77. ;; Then check if its a fully specified URL
  78. ((string-match url-nonrelative-link env-proxy)
  79. (setq urlobj (url-generic-parse-url env-proxy))
  80. (setf (url-type urlobj) "http")
  81. (setf (url-target urlobj) nil))
  82. ;; Finally, fall back on the assumption that its just a hostname
  83. (t
  84. (setq urlobj (url-generic-parse-url nil)) ; Get a blank object
  85. (setf (url-type urlobj) "http")
  86. (setf (url-host urlobj) env-proxy)))
  87. (if (and (not cur-proxy) urlobj)
  88. (progn
  89. (setq url-proxy-services
  90. (cons (cons scheme (format "%s:%d" (url-host urlobj)
  91. (url-port urlobj)))
  92. url-proxy-services))
  93. (message "Using a proxy for %s..." scheme)))))
  94. (defun url-scheme-get-property (scheme property)
  95. "Get PROPERTY of a URL SCHEME.
  96. Will automatically try to load a backend from url-SCHEME.el if
  97. it has not already been loaded."
  98. (setq scheme (downcase scheme))
  99. (let ((desc (gethash scheme url-scheme-registry)))
  100. (if (not desc)
  101. (let* ((stub (concat "url-" scheme))
  102. (loader (intern stub)))
  103. (condition-case ()
  104. (require loader)
  105. (error nil))
  106. (if (fboundp loader)
  107. (progn
  108. ;; Found the module to handle <scheme> URLs
  109. (unless url-scheme--registering-proxy
  110. (url-scheme-register-proxy scheme))
  111. (setq desc (list 'name scheme
  112. 'loader loader))
  113. (dolist (cell url-scheme-methods)
  114. (let ((symbol (intern-soft (format "%s-%s" stub (car cell))))
  115. (type (cdr cell)))
  116. (if symbol
  117. (case type
  118. (function
  119. ;; Store the symbol name of a function
  120. (if (fboundp symbol)
  121. (setq desc (plist-put desc (car cell) symbol))))
  122. (variable
  123. ;; Store the VALUE of a variable
  124. (if (boundp symbol)
  125. (setq desc (plist-put desc (car cell)
  126. (symbol-value symbol)))))
  127. (otherwise
  128. (error "Malformed url-scheme-methods entry: %S"
  129. cell))))))
  130. (puthash scheme desc url-scheme-registry)))))
  131. (or (plist-get desc property)
  132. (plist-get url-scheme-default-properties property))))
  133. (provide 'url-methods)
  134. ;;; url-methods.el ends here