Mercurial > core / lisp/lib/obj/uri/domain.lisp
changeset 698: |
96958d3eb5b0 |
parent: |
49c3f3d11432
|
author: |
Richard Westhaver <ellis@rwest.io> |
date: |
Fri, 04 Oct 2024 22:04:59 -0400 |
permissions: |
-rw-r--r-- |
description: |
fixes |
1 ;;; obj/uri/domain.lisp --- URI Domains 8 (eval-when (:compile-toplevel :load-toplevel :execute) 9 (defparameter *default-etld-names* 10 (probe-file #.(asdf:system-relative-pathname :prelude #P"../.stash/psl.dat"))) 12 (defun load-etld-data (&optional (etld-names-file *default-etld-names*)) 14 (with-open-file (in etld-names-file 15 :element-type #+lispworks :default #-lispworks 'character 16 :external-format #+clisp charset:utf-8 #-clisp :utf-8) 17 (loop with special-tlds = nil 18 with normal-tlds = (make-hash-table :test 'equal) 19 with wildcard-tlds = (make-hash-table :test 'equal) 20 for line = (read-line in nil nil) 22 unless (or (= 0 (length line)) 23 (starts-with-subseq "//" line)) 25 ((starts-with-subseq "*" line) 26 (setf (gethash (subseq line 2) wildcard-tlds) t)) 27 ((starts-with-subseq "!" line) 28 (push (subseq line 1) special-tlds)) 30 (setf (gethash line normal-tlds) t))) 31 finally (return (list normal-tlds wildcard-tlds special-tlds))))))) 33 (defvar *etlds* (load-etld-data)) 35 (defun next-subdomain (hostname &optional (start 0)) 36 (let ((pos (position #\. hostname :start start))) 39 (values (subseq hostname pos) 42 (defun make-subdomain-iter (hostname) 50 (multiple-value-bind (subdomain pos) 51 (next-subdomain hostname current-pos) 53 (setf current-pos pos) 56 (defun parse-domain (hostname) 58 (dolist (tld (third *etlds*)) 59 (when (ends-with-subseq tld hostname) 60 (if (= (length tld) (length hostname)) 61 (return-from parse-domain hostname) 62 (when (char= (aref hostname (- (length hostname) (length tld) 1)) 64 (return-from parse-domain 66 (- (length hostname) (length tld)))))))) 67 (loop with iter = (make-subdomain-iter hostname) 68 with pre-prev-subdomain = nil 69 with prev-subdomain = nil 70 for subdomain = (funcall iter) 72 if (gethash subdomain (second *etlds*)) do 73 (return pre-prev-subdomain) 74 else if (gethash subdomain (first *etlds*)) do 75 (return (if (string= subdomain hostname) 78 do (setf pre-prev-subdomain prev-subdomain 79 prev-subdomain subdomain) 81 (let* ((pos (position #\. hostname :from-end t)) 83 (position #\. hostname :from-end t :end pos)))) 86 (subseq hostname (1+ pos)) 90 (let ((host (uri-host uri))) 92 (not (ip-addr-p host))) 93 (let ((pos (position #\. host :from-end t))) 95 (subseq host (1+ pos)) 98 (defun uri-domain (uri) 99 (let ((host (uri-host uri))) 101 (not (ip-addr-p host))) 102 (parse-domain host)))) 104 (defun ipv4-addr-p (host) 105 (declare (optimize (speed 3) (safety 2)) 106 #+sbcl (sb-ext:muffle-conditions sb-ext:compiler-note)) 107 (check-type host string) 108 (flet ((read-byte-string (string start) 109 (declare (type fixnum start)) 110 (when (<= (length string) start) 111 (return-from read-byte-string nil)) 112 (let* ((end (+ start 2)) 113 (endp (<= (1- (length string)) end)) 118 (declare (type fixnum end res)) 119 (do ((i start (1+ i))) 121 (declare (type fixnum i)) 122 (unless (char<= #\0 (aref string i) #\9) 123 (return-from read-byte-string 126 (values res i nil)))) 129 (- (char-code (aref string i)) 48)))) 133 ((char= (aref string (1+ end)) #\.) 134 (values res (1+ end) nil)))))) 137 (multiple-value-bind (byte pos endp) 138 (read-byte-string host start) 139 (unless (typep byte '(unsigned-byte 8)) 141 (unless (xor endp (not (= i 3))) 143 (setq start (1+ pos))))))) 145 (defun trim-brackets (host) 146 (if (char= (aref host 0) #\[) 147 (if (char= (aref host (1- (length host))) #\]) 148 (subseq host 1 (1- (length host))) 152 (defun ipv6-addr-p (host) 153 (declare (optimize (speed 3) (safety 2)) 154 #+sbcl (sb-ext:muffle-conditions sb-ext:compiler-note)) 155 (check-type host string) 156 (when (= (length host) 0) 157 (return-from ipv6-addr-p nil)) 159 (labels ((read-section (string start &optional read-colons) 160 (declare (type string string) 162 (when (<= (length string) start) 163 (return-from read-section 164 (values start read-colons t))) 165 (when (char= (aref string start) #\:) 167 ((<= (length string) (1+ start)) 168 (return-from read-section nil)) 169 ((char= (aref string (1+ start)) #\:) 171 (return-from read-section nil) 172 (return-from read-section (read-section string (+ 2 start) t)))) 174 (let* ((end (+ start 4)) 175 (endp (<= (length string) end)) 179 (declare (type fixnum end)) 181 (do ((i start (1+ i))) 183 (let ((ch (aref string i))) 186 (return-from read-section 187 (values i read-colons nil))) 188 ((or (char<= #\0 ch #\9) 190 (char<= #\A ch #\F))) 191 (t (return-from read-section nil))))) 194 (values end read-colons endp) 195 (if (char= (aref string end) #\:) 196 (values end read-colons endp) 199 (setq host (trim-brackets host)) 201 (return-from ipv6-addr-p nil)) 206 (multiple-value-bind (e read-colons endp) 207 (read-section host start read-colons-p) 209 (return-from ipv6-addr-p nil)) 211 (when (and (not (= i 7)) 213 (return-from ipv6-addr-p nil)) 214 (return-from ipv6-addr-p t)) 215 (when (and (= i 7) (not endp)) 216 (return-from ipv6-addr-p nil)) 218 read-colons-p read-colons)))))) 220 (defun ip-addr-p (host) 221 (or (ipv4-addr-p host) 224 (defun ip-addr= (ip1 ip2) 225 (flet ((parse-ipv6 (ip) 226 (setq ip (trim-brackets ip)) 228 ((char= (aref ip 0) #\:) 229 (setq ip (concatenate 'string "0" ip))) 230 ((char= (aref ip (1- (length ip))) #\:) 231 (setq ip (concatenate 'string ip "0")))) 232 (let* ((ip-parsed (split-sequence #\: ip)) 233 (len (length ip-parsed))) 234 (loop for section in ip-parsed 235 if (string= section "") 236 append (make-list (- 9 len) :initial-element 0) 238 collect (parse-integer section :radix 16))))) 243 (and (ipv6-addr-p ip2) 244 (equal (parse-ipv6 ip1) 245 (parse-ipv6 ip2))))))) 247 (defun cookie-domain-p (domain cookie-domain) 248 (unless cookie-domain 249 (return-from cookie-domain-p t)) 250 (if (ip-addr-p domain) 251 (ip-addr= domain cookie-domain) 253 ;; ignore the preceding "." 254 (when (char= (aref cookie-domain 0) #\.) 255 (setq cookie-domain (subseq cookie-domain 1))) 256 (when-let ((registered-domain (parse-domain domain))) 258 ((= (length registered-domain) (length cookie-domain)) 259 (string= registered-domain cookie-domain)) 260 ((= (length domain) (length cookie-domain)) 261 (string= domain cookie-domain)) 262 (t (and (ends-with-subseq domain cookie-domain) 264 (aref cookie-domain (- (length cookie-domain) 265 (length registered-domain)))))))))))