]> code.delx.au - gnu-emacs-elpa/blob - packages/url-http-ntlm/url-http-ntlm-parse-headers-24.2.el
* packages/sisu-mode/sisu-mode.el: Update to 7.1.8
[gnu-emacs-elpa] / packages / url-http-ntlm / url-http-ntlm-parse-headers-24.2.el
1 ;;; url-http-ntlm-parse-headers-24.2.el --- Override url-http-parse-headers
2
3 ;; Copyright (C) 1999, 2001, 2004-2016 Free Software Foundation, Inc.
4
5 ;; Author: Bill Perry <wmperry@gnu.org>
6 ;; Keywords: comm, data, processes
7
8 ;; This file is part of GNU Emacs.
9 ;;
10 ;; GNU Emacs is free software: you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation, either version 3 of the License, or
13 ;; (at your option) any later version.
14
15 ;; GNU Emacs is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;; GNU General Public License for more details.
19
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
22
23 ;;; Commentary:
24
25 ;; Override url-http-parse-headers to clear Authorization headers
26 ;; from url-http-extra-headers prior to executing a redirect. The
27 ;; only change is to apply this backward-compatible patch:
28 ;;
29 ;; diff --git a/lisp/url/url-http.el b/lisp/url/url-http.el
30 ;; index 2bae194..110d339 100644
31 ;; --- a/lisp/url/url-http.el
32 ;; +++ b/lisp/url/url-http.el
33 ;; @@ -619,6 +619,15 @@ should be shown to the user."
34 ;; ;; compute the redirection relative to the URL of the proxy.
35 ;; (setq redirect-uri
36 ;; (url-expand-file-name redirect-uri url-http-target-url)))
37 ;; + ;; Do not automatically include an authorization header in the
38 ;; + ;; redirect. If needed it will be regenerated by the relevant
39 ;; + ;; auth scheme when the new request happens.
40 ;; + (setq url-http-extra-headers
41 ;; + (let (result)
42 ;; + (dolist (header url-http-extra-headers)
43 ;; + (if (not (equal (car header) "Authorization"))
44 ;; + (push header result)))
45 ;; + (nreverse result)))
46 ;; (let ((url-request-method url-http-method)
47 ;; (url-request-data url-http-data)
48 ;; (url-request-extra-headers url-http-extra-headers))
49
50 ;;; Code:
51
52 (eval-when-compile (require 'cl))
53
54 (require 'url-gw)
55 (require 'url-parse)
56 (require 'url-cookie)
57 (require 'mail-parse)
58 (require 'url-auth)
59 (require 'url)
60 (autoload 'url-cache-create-filename "url-cache")
61 (require 'url-http)
62
63 (defvar url-http-target-url)
64 (defvar url-http-extra-headers)
65
66 (defun url-http-parse-headers ()
67 "Parse and handle HTTP specific headers.
68 Return t if and only if the current buffer is still active and
69 should be shown to the user."
70 ;; The comments after each status code handled are taken from RFC
71 ;; 2616 (HTTP/1.1)
72 (declare (special url-http-end-of-headers url-http-response-status
73 url-http-response-version
74 url-http-method url-http-data url-http-process
75 url-callback-function url-callback-arguments))
76
77 (url-http-mark-connection-as-free (url-host url-current-object)
78 (url-port url-current-object)
79 url-http-process)
80
81 (if (or (not (boundp 'url-http-end-of-headers))
82 (not url-http-end-of-headers))
83 (error "Trying to parse headers in odd buffer: %s" (buffer-name)))
84 (goto-char (point-min))
85 (url-http-debug "url-http-parse-headers called in (%s)" (buffer-name))
86 (url-http-parse-response)
87 (mail-narrow-to-head)
88 ;;(narrow-to-region (point-min) url-http-end-of-headers)
89 (let ((connection (mail-fetch-field "Connection")))
90 ;; In HTTP 1.0, keep the connection only if there is a
91 ;; "Connection: keep-alive" header.
92 ;; In HTTP 1.1 (and greater), keep the connection unless there is a
93 ;; "Connection: close" header
94 (cond
95 ((string= url-http-response-version "1.0")
96 (unless (and connection
97 (string= (downcase connection) "keep-alive"))
98 (delete-process url-http-process)))
99 (t
100 (when (and connection
101 (string= (downcase connection) "close"))
102 (delete-process url-http-process)))))
103 (let ((buffer (current-buffer))
104 (class nil)
105 (success nil)
106 ;; other status symbols: jewelry and luxury cars
107 (status-symbol (cadr (assq url-http-response-status url-http-codes)))
108 ;; The filename part of a URL could be in remote file syntax,
109 ;; see Bug#6717 for an example. We disable file name
110 ;; handlers, therefore.
111 (file-name-handler-alist nil))
112 (setq class (/ url-http-response-status 100))
113 (url-http-debug "Parsed HTTP headers: class=%d status=%d" class url-http-response-status)
114 (when (url-use-cookies url-http-target-url)
115 (url-http-handle-cookies))
116
117 (case class
118 ;; Classes of response codes
119 ;;
120 ;; 5xx = Server Error
121 ;; 4xx = Client Error
122 ;; 3xx = Redirection
123 ;; 2xx = Successful
124 ;; 1xx = Informational
125 (1 ; Information messages
126 ;; 100 = Continue with request
127 ;; 101 = Switching protocols
128 ;; 102 = Processing (Added by DAV)
129 (url-mark-buffer-as-dead buffer)
130 (error "HTTP responses in class 1xx not supported (%d)" url-http-response-status))
131 (2 ; Success
132 ;; 200 Ok
133 ;; 201 Created
134 ;; 202 Accepted
135 ;; 203 Non-authoritative information
136 ;; 204 No content
137 ;; 205 Reset content
138 ;; 206 Partial content
139 ;; 207 Multi-status (Added by DAV)
140 (case status-symbol
141 ((no-content reset-content)
142 ;; No new data, just stay at the same document
143 (url-mark-buffer-as-dead buffer)
144 (setq success t))
145 (otherwise
146 ;; Generic success for all others. Store in the cache, and
147 ;; mark it as successful.
148 (widen)
149 (if (and url-automatic-caching (equal url-http-method "GET"))
150 (url-store-in-cache buffer))
151 (setq success t))))
152 (3 ; Redirection
153 ;; 300 Multiple choices
154 ;; 301 Moved permanently
155 ;; 302 Found
156 ;; 303 See other
157 ;; 304 Not modified
158 ;; 305 Use proxy
159 ;; 307 Temporary redirect
160 (let ((redirect-uri (or (mail-fetch-field "Location")
161 (mail-fetch-field "URI"))))
162 (case status-symbol
163 (multiple-choices ; 300
164 ;; Quoth the spec (section 10.3.1)
165 ;; -------------------------------
166 ;; The requested resource corresponds to any one of a set of
167 ;; representations, each with its own specific location and
168 ;; agent-driven negotiation information is being provided so
169 ;; that the user can select a preferred representation and
170 ;; redirect its request to that location.
171 ;; [...]
172 ;; If the server has a preferred choice of representation, it
173 ;; SHOULD include the specific URI for that representation in
174 ;; the Location field; user agents MAY use the Location field
175 ;; value for automatic redirection.
176 ;; -------------------------------
177 ;; We do not support agent-driven negotiation, so we just
178 ;; redirect to the preferred URI if one is provided.
179 nil)
180 ((moved-permanently found temporary-redirect) ; 301 302 307
181 ;; If the 301|302 status code is received in response to a
182 ;; request other than GET or HEAD, the user agent MUST NOT
183 ;; automatically redirect the request unless it can be
184 ;; confirmed by the user, since this might change the
185 ;; conditions under which the request was issued.
186 (unless (member url-http-method '("HEAD" "GET"))
187 (setq redirect-uri nil)))
188 (see-other ; 303
189 ;; The response to the request can be found under a different
190 ;; URI and SHOULD be retrieved using a GET method on that
191 ;; resource.
192 (setq url-http-method "GET"
193 url-http-data nil))
194 (not-modified ; 304
195 ;; The 304 response MUST NOT contain a message-body.
196 (url-http-debug "Extracting document from cache... (%s)"
197 (url-cache-create-filename (url-view-url t)))
198 (url-cache-extract (url-cache-create-filename (url-view-url t)))
199 (setq redirect-uri nil
200 success t))
201 (use-proxy ; 305
202 ;; The requested resource MUST be accessed through the
203 ;; proxy given by the Location field. The Location field
204 ;; gives the URI of the proxy. The recipient is expected
205 ;; to repeat this single request via the proxy. 305
206 ;; responses MUST only be generated by origin servers.
207 (error "Redirection thru a proxy server not supported: %s"
208 redirect-uri))
209 (otherwise
210 ;; Treat everything like '300'
211 nil))
212 (when redirect-uri
213 ;; Clean off any whitespace and/or <...> cruft.
214 (if (string-match "\\([^ \t]+\\)[ \t]" redirect-uri)
215 (setq redirect-uri (match-string 1 redirect-uri)))
216 (if (string-match "^<\\(.*\\)>$" redirect-uri)
217 (setq redirect-uri (match-string 1 redirect-uri)))
218
219 ;; Some stupid sites (like sourceforge) send a
220 ;; non-fully-qualified URL (ie: /), which royally confuses
221 ;; the URL library.
222 (if (not (string-match url-nonrelative-link redirect-uri))
223 ;; Be careful to use the real target URL, otherwise we may
224 ;; compute the redirection relative to the URL of the proxy.
225 (setq redirect-uri
226 (url-expand-file-name redirect-uri url-http-target-url)))
227 ;; Do not automatically include an authorization header in the
228 ;; redirect. If needed it will be regenerated by the relevant
229 ;; auth scheme when the new request happens.
230 (setq url-http-extra-headers
231 (let (result)
232 (dolist (header url-http-extra-headers)
233 (if (not (equal (car header) "Authorization"))
234 (push header result)))
235 (nreverse result)))
236 (let ((url-request-method url-http-method)
237 (url-request-data url-http-data)
238 (url-request-extra-headers url-http-extra-headers))
239 ;; Check existing number of redirects
240 (if (or (< url-max-redirections 0)
241 (and (> url-max-redirections 0)
242 (let ((events (car url-callback-arguments))
243 (old-redirects 0))
244 (while events
245 (if (eq (car events) :redirect)
246 (setq old-redirects (1+ old-redirects)))
247 (and (setq events (cdr events))
248 (setq events (cdr events))))
249 (< old-redirects url-max-redirections))))
250 ;; url-max-redirections hasn't been reached, so go
251 ;; ahead and redirect.
252 (progn
253 ;; Remember that the request was redirected.
254 (setf (car url-callback-arguments)
255 (nconc (list :redirect redirect-uri)
256 (car url-callback-arguments)))
257 ;; Put in the current buffer a forwarding pointer to the new
258 ;; destination buffer.
259 ;; FIXME: This is a hack to fix url-retrieve-synchronously
260 ;; without changing the API. Instead url-retrieve should
261 ;; either simply not return the "destination" buffer, or it
262 ;; should take an optional `dest-buf' argument.
263 (set (make-local-variable 'url-redirect-buffer)
264 (url-retrieve-internal
265 redirect-uri url-callback-function
266 url-callback-arguments
267 (url-silent url-current-object)
268 (not (url-use-cookies url-current-object))))
269 (url-mark-buffer-as-dead buffer))
270 ;; We hit url-max-redirections, so issue an error and
271 ;; stop redirecting.
272 (url-http-debug "Maximum redirections reached")
273 (setf (car url-callback-arguments)
274 (nconc (list :error (list 'error 'http-redirect-limit
275 redirect-uri))
276 (car url-callback-arguments)))
277 (setq success t))))))
278 (4 ; Client error
279 ;; 400 Bad Request
280 ;; 401 Unauthorized
281 ;; 402 Payment required
282 ;; 403 Forbidden
283 ;; 404 Not found
284 ;; 405 Method not allowed
285 ;; 406 Not acceptable
286 ;; 407 Proxy authentication required
287 ;; 408 Request time-out
288 ;; 409 Conflict
289 ;; 410 Gone
290 ;; 411 Length required
291 ;; 412 Precondition failed
292 ;; 413 Request entity too large
293 ;; 414 Request-URI too large
294 ;; 415 Unsupported media type
295 ;; 416 Requested range not satisfiable
296 ;; 417 Expectation failed
297 ;; 422 Unprocessable Entity (Added by DAV)
298 ;; 423 Locked
299 ;; 424 Failed Dependency
300 (case status-symbol
301 (unauthorized ; 401
302 ;; The request requires user authentication. The response
303 ;; MUST include a WWW-Authenticate header field containing a
304 ;; challenge applicable to the requested resource. The
305 ;; client MAY repeat the request with a suitable
306 ;; Authorization header field.
307 (url-http-handle-authentication nil))
308 (payment-required ; 402
309 ;; This code is reserved for future use
310 (url-mark-buffer-as-dead buffer)
311 (error "Somebody wants you to give them money"))
312 (forbidden ; 403
313 ;; The server understood the request, but is refusing to
314 ;; fulfill it. Authorization will not help and the request
315 ;; SHOULD NOT be repeated.
316 (setq success t))
317 (not-found ; 404
318 ;; Not found
319 (setq success t))
320 (method-not-allowed ; 405
321 ;; The method specified in the Request-Line is not allowed
322 ;; for the resource identified by the Request-URI. The
323 ;; response MUST include an Allow header containing a list of
324 ;; valid methods for the requested resource.
325 (setq success t))
326 (not-acceptable ; 406
327 ;; The resource identified by the request is only capable of
328 ;; generating response entities which have content
329 ;; characteristics not acceptable according to the accept
330 ;; headers sent in the request.
331 (setq success t))
332 (proxy-authentication-required ; 407
333 ;; This code is similar to 401 (Unauthorized), but indicates
334 ;; that the client must first authenticate itself with the
335 ;; proxy. The proxy MUST return a Proxy-Authenticate header
336 ;; field containing a challenge applicable to the proxy for
337 ;; the requested resource.
338 (url-http-handle-authentication t))
339 (request-timeout ; 408
340 ;; The client did not produce a request within the time that
341 ;; the server was prepared to wait. The client MAY repeat
342 ;; the request without modifications at any later time.
343 (setq success t))
344 (conflict ; 409
345 ;; The request could not be completed due to a conflict with
346 ;; the current state of the resource. This code is only
347 ;; allowed in situations where it is expected that the user
348 ;; might be able to resolve the conflict and resubmit the
349 ;; request. The response body SHOULD include enough
350 ;; information for the user to recognize the source of the
351 ;; conflict.
352 (setq success t))
353 (gone ; 410
354 ;; The requested resource is no longer available at the
355 ;; server and no forwarding address is known.
356 (setq success t))
357 (length-required ; 411
358 ;; The server refuses to accept the request without a defined
359 ;; Content-Length. The client MAY repeat the request if it
360 ;; adds a valid Content-Length header field containing the
361 ;; length of the message-body in the request message.
362 ;;
363 ;; NOTE - this will never happen because
364 ;; `url-http-create-request' automatically calculates the
365 ;; content-length.
366 (setq success t))
367 (precondition-failed ; 412
368 ;; The precondition given in one or more of the
369 ;; request-header fields evaluated to false when it was
370 ;; tested on the server.
371 (setq success t))
372 ((request-entity-too-large request-uri-too-large) ; 413 414
373 ;; The server is refusing to process a request because the
374 ;; request entity|URI is larger than the server is willing or
375 ;; able to process.
376 (setq success t))
377 (unsupported-media-type ; 415
378 ;; The server is refusing to service the request because the
379 ;; entity of the request is in a format not supported by the
380 ;; requested resource for the requested method.
381 (setq success t))
382 (requested-range-not-satisfiable ; 416
383 ;; A server SHOULD return a response with this status code if
384 ;; a request included a Range request-header field, and none
385 ;; of the range-specifier values in this field overlap the
386 ;; current extent of the selected resource, and the request
387 ;; did not include an If-Range request-header field.
388 (setq success t))
389 (expectation-failed ; 417
390 ;; The expectation given in an Expect request-header field
391 ;; could not be met by this server, or, if the server is a
392 ;; proxy, the server has unambiguous evidence that the
393 ;; request could not be met by the next-hop server.
394 (setq success t))
395 (otherwise
396 ;; The request could not be understood by the server due to
397 ;; malformed syntax. The client SHOULD NOT repeat the
398 ;; request without modifications.
399 (setq success t)))
400 ;; Tell the callback that an error occurred, and what the
401 ;; status code was.
402 (when success
403 (setf (car url-callback-arguments)
404 (nconc (list :error (list 'error 'http url-http-response-status))
405 (car url-callback-arguments)))))
406 (5
407 ;; 500 Internal server error
408 ;; 501 Not implemented
409 ;; 502 Bad gateway
410 ;; 503 Service unavailable
411 ;; 504 Gateway time-out
412 ;; 505 HTTP version not supported
413 ;; 507 Insufficient storage
414 (setq success t)
415 (case url-http-response-status
416 (not-implemented ; 501
417 ;; The server does not support the functionality required to
418 ;; fulfill the request.
419 nil)
420 (bad-gateway ; 502
421 ;; The server, while acting as a gateway or proxy, received
422 ;; an invalid response from the upstream server it accessed
423 ;; in attempting to fulfill the request.
424 nil)
425 (service-unavailable ; 503
426 ;; The server is currently unable to handle the request due
427 ;; to a temporary overloading or maintenance of the server.
428 ;; The implication is that this is a temporary condition
429 ;; which will be alleviated after some delay. If known, the
430 ;; length of the delay MAY be indicated in a Retry-After
431 ;; header. If no Retry-After is given, the client SHOULD
432 ;; handle the response as it would for a 500 response.
433 nil)
434 (gateway-timeout ; 504
435 ;; The server, while acting as a gateway or proxy, did not
436 ;; receive a timely response from the upstream server
437 ;; specified by the URI (e.g. HTTP, FTP, LDAP) or some other
438 ;; auxiliary server (e.g. DNS) it needed to access in
439 ;; attempting to complete the request.
440 nil)
441 (http-version-not-supported ; 505
442 ;; The server does not support, or refuses to support, the
443 ;; HTTP protocol version that was used in the request
444 ;; message.
445 nil)
446 (insufficient-storage ; 507 (DAV)
447 ;; The method could not be performed on the resource
448 ;; because the server is unable to store the representation
449 ;; needed to successfully complete the request. This
450 ;; condition is considered to be temporary. If the request
451 ;; which received this status code was the result of a user
452 ;; action, the request MUST NOT be repeated until it is
453 ;; requested by a separate user action.
454 nil))
455 ;; Tell the callback that an error occurred, and what the
456 ;; status code was.
457 (when success
458 (setf (car url-callback-arguments)
459 (nconc (list :error (list 'error 'http url-http-response-status))
460 (car url-callback-arguments)))))
461 (otherwise
462 (error "Unknown class of HTTP response code: %d (%d)"
463 class url-http-response-status)))
464 (if (not success)
465 (url-mark-buffer-as-dead buffer))
466 (url-http-debug "Finished parsing HTTP headers: %S" success)
467 (widen)
468 success))
469
470 (provide 'url-http-ntlm-parse-headers-24.2)
471
472 ;;; url-http-ntlm-parse-headers-24.2.el ends here