Coverage report: /home/ellis/comp/core/lib/obj/uri/domain.lisp
Kind | Covered | All | % |
expression | 2 | 549 | 0.4 |
branch | 0 | 96 | 0.0 |
Key
Not instrumented
Conditionalized out
Executed
Not executed
Both branches taken
One branch taken
Neither branch taken
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 :core ".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)))))))))))