-ARGS is expected to contain the WWW-Authentication header from
-the server's last response. These are used by
-`url-http-get-stage' to determine what stage we are at."
- (url-ntlm-ensure-keepalive)
- (let ((stage (url-ntlm-get-stage args)))
- (case stage
- ;; NTLM Type 1 message: the request
- (:request
- (destructuring-bind (&optional server user hash)
- (url-http-ntlm-authorisation url)
- (when server
- (url-http-ntlm-string (ntlm-build-auth-request user server)))))
- ;; NTLM Type 3 message: the response
- (:response
- (let ((challenge (url-http-ntlm-get-challenge)))
- (destructuring-bind (server user hash)
- (url-http-ntlm-authorisation url)
- (url-http-ntlm-string (ntlm-build-auth-response challenge
- user
- hash)))))
- (:error
- (url-http-ntlm-authorisation url :clear)))))
+\f
+;;; Private functions.
+(defun url-http-ntlm--detect-loop (url)
+ "Detect potential infinite loop when NTLM fails on URL."
+ (when (not url-http-ntlm--loop-timer-counter)
+ (setq url-http-ntlm--loop-timer-counter (make-hash-table :test 'equal)))
+ (let* ((url-string (url-recreate-url url))
+ (last-entry (gethash url-string url-http-ntlm--loop-timer-counter))
+ (start-time (car last-entry))
+ (counter (cdr last-entry)))
+ (if last-entry
+ (progn
+ (if (< (- (float-time) start-time) 10.0)
+ (if (< counter 20)
+ ;; Still within time window, so increment count.
+ (puthash url-string (cons start-time (1+ counter))
+ url-http-ntlm--loop-timer-counter)
+ ;; Error detected, so remove entry and clear.
+ (url-http-ntlm--authorization url-string :clear)
+ (remhash url-string url-http-ntlm--loop-timer-counter)
+ (error
+ (format (concat "Access rate to %s is too high,"
+ " indicating an NTLM failure;"
+ " to debug, re-run with url-debug set to 1")
+ url-string)))
+ ;; Timeout expired, so reset counter.
+ (puthash url-string (cons (float-time) 0)
+ url-http-ntlm--loop-timer-counter)))
+ ;; New access, so initialize counter to 0.
+ (puthash url-string (cons (float-time) 0)
+ url-http-ntlm--loop-timer-counter))))
+
+(defun url-http-ntlm--ensure-user (url)
+ "Return URL with its user slot set.
+If URL's user slot is nil, set it to the last user that made a
+request to the host in URL's server slot."
+ (let ((new-url url))
+ (if (url-user new-url)
+ new-url
+ (setf (url-user new-url)
+ (cdr (assoc (url-host new-url) url-http-ntlm--default-users)))
+ new-url)))