changelog shortlog graph tags branches changeset files file revisions raw help

Mercurial > core / annotate lisp/lib/obj/uri/path.lisp

changeset 698: 96958d3eb5b0
parent: 78ef6145e272
author: Richard Westhaver <ellis@rwest.io>
date: Fri, 04 Oct 2024 22:04:59 -0400
permissions: -rw-r--r--
description: fixes
275
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1
 ;;; obj/uri/path.lisp --- URI Path merging functions
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2
 
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3
 ;;
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
4
 
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
5
 ;;; Code:
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
6
 (in-package :obj/uri)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
7
 ;; merging and unmerging
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
8
 (defmethod merge-uris ((uri string) (base string) &optional place)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
9
   (merge-uris (parse-uri uri) (parse-uri base) place))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
10
 
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
11
 (defmethod merge-uris ((uri uri) (base string) &optional place)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
12
   (merge-uris uri (parse-uri base) place))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
13
 
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
14
 (defmethod merge-uris ((uri string) (base uri) &optional place)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
15
   (merge-uris (parse-uri uri) base place))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
16
 
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
17
 (defmethod merge-uris ((uri uri) (base uri) &optional place)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
18
   ;; When PLACE is nil, this function returns a new URI.
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
19
   ;; When PLACE is non-nil, it is return.
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
20
   (tagbody
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
21
     (when (and (null (uri-path uri))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
22
                (null (uri-scheme uri))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
23
                (null (uri-host uri))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
24
                (null (uri-userinfo uri))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
25
                (null (uri-port uri))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
26
                (null (uri-query uri)))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
27
       (return-from merge-uris
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
28
         (let ((new (copy-uri base :place place)))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
29
           (when (uri-query uri)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
30
             (setf (uri-query new) (uri-query uri)))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
31
           (when (uri-fragment uri)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
32
             (setf (uri-fragment new) (uri-fragment uri)))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
33
           new)))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
34
 
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
35
     (setq uri (copy-uri uri :place place))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
36
 
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
37
     (when (uri-scheme uri) (go :done))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
38
 
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
39
     (setf (uri-scheme uri) (uri-scheme base))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
40
 
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
41
     ;; if URI has a host, we're done
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
42
     (when (uri-host uri) (go :done))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
43
 
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
44
     (set-host uri
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
45
               (%uri-host base)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
46
               (%uri-ipv6 base)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
47
               (%uri-zone-id base))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
48
     (setf (uri-userinfo uri) (uri-userinfo base))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
49
     (setf (uri-port uri) (uri-port base))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
50
 
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
51
     (let ((p (uri-parsed-path uri)))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
52
       (when (null p)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
53
         (setf (uri-path uri) (uri-path base))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
54
         (go :done))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
55
 
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
56
       (when (and p (eq :absolute (car p)))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
57
         (if* (equal '(:absolute "") p)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
58
            then ;; Canonicalize the way parsing does:
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
59
                 (setf (uri-path uri) nil)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
60
          elseif (eq :absolute (first p))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
61
            then ;; this also sets uri-path
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
62
                 (multiple-value-bind (new changed)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
63
                     (canonicalize-path-list p)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
64
                   (when changed
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
65
                     (setf (uri-parsed-path uri) new))))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
66
         (go :done)))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
67
 
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
68
     (let* ((base-path
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
69
             (or (uri-parsed-path base)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
70
                 ;; needed because we canonicalize away a path of just `/':
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
71
                 '(:absolute "")))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
72
            (path (uri-parsed-path uri))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
73
            new-path-list)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
74
       (when (not (eq :absolute (car base-path)))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
75
         (error "Cannot merge ~a and ~a, since the latter is not absolute."
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
76
                uri base))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
77
 
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
78
       (setq new-path-list
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
79
         (append (butlast base-path)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
80
                 (if* path then (cdr path) else '(""))))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
81
 
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
82
       (let ((last (last new-path-list)))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
83
         (if* (atom (car last))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
84
            then (when (string= "." (car last))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
85
                   (setf (car last) ""))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
86
            else (when (string= "." (caar last))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
87
                   (setf (caar last) ""))))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
88
       (setq new-path-list
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
89
         (delete "." new-path-list :test #'(lambda (a b)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
90
                                             (if* (atom b)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
91
                                                then (string= a b)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
92
                                                else nil))))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
93
 
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
94
       (let ((npl (cdr new-path-list))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
95
             index tmp fix-tail)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
96
         (setq fix-tail
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
97
           (string= ".." (let ((l (car (last npl))))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
98
                           (if* (atom l)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
99
                              then l
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
100
                              else (car l)))))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
101
         (loop
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
102
           (setq index
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
103
             (position ".." npl
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
104
                       :test #'(lambda (a b)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
105
                                 (string= a
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
106
                                          (if* (atom b)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
107
                                             then b
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
108
                                             else (car b))))))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
109
           (when (null index) (return))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
110
 
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
111
           (if* (= 0 index)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
112
              then ;; rfe11852: RFC 3986, in section 5.4.2 (Abnormal
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
113
                   ;; Examples) says parsers; must be careful in handling
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
114
                   ;; cases where there are more ".." segments in a
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
115
                   ;; relative-path reference than there are in the base
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
116
                   ;; URI's path.  The examples, between the two RFC's were
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
117
                   ;; changed to show the additional, leading ..'s to be
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
118
                   ;; removed. So, we'll do that now.
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
119
                   (setq npl (cdr npl))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
120
            elseif (= 1 index)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
121
              then (setq npl (cddr npl))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
122
              else (setq tmp npl)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
123
                   (dotimes (x (- index 2)) (setq tmp (cdr tmp)))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
124
                   (setf (cdr tmp) (cdddr tmp))))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
125
         (setf (cdr new-path-list) npl)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
126
         (when fix-tail (setq new-path-list (nconc new-path-list '("")))))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
127
 
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
128
       (when (eq :absolute (first new-path-list))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
129
         (multiple-value-bind (new changed)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
130
             (canonicalize-path-list new-path-list)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
131
           (when changed (setq new-path-list new))))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
132
 
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
133
       ;; Also sets uri-path:
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
134
       (setf (uri-parsed-path uri) new-path-list))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
135
 
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
136
    :done
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
137
     (return-from merge-uris uri)))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
138
 
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
139
 (defun canonicalize-path-list (path-list &aux changed)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
140
   ;; Return two values: new version of PATH-LIST and an indicator if it was
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
141
   ;; changed.  We are only called when (car path-list) is :absolute.
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
142
   (loop while (or (equal "." (second path-list))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
143
                   (equal ".." (second path-list)))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
144
         do (setf (cdr path-list) (cddr path-list))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
145
            (setq changed t))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
146
   (values path-list changed))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
147
 
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
148
 (defmethod merge-uris ((urn urn) (base urn) &optional place)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
149
   (if* place
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
150
      then (setf (urn-nid place) (urn-nid urn))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
151
           (setf (urn-nss place) (urn-nss urn))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
152
           place
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
153
      else urn))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
154
 
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
155
 (defmethod merge-uris ((urn urn) (base uri) &optional place)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
156
   (if* place
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
157
      then (setf (urn-nid place) (urn-nid urn))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
158
           (setf (urn-nss place) (urn-nss urn))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
159
           place
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
160
      else urn))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
161
 
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
162
 (defmethod merge-uris ((uri uri) (base urn) &optional place)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
163
   (copy-uri uri :place place))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
164
 
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
165
 (defmethod enough-uri ((uri string) (base string) &optional place)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
166
   (enough-uri (parse-uri uri) (parse-uri base) place))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
167
 
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
168
 (defmethod enough-uri ((uri uri) (base string) &optional place)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
169
   (enough-uri uri (parse-uri base) place))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
170
 
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
171
 (defmethod enough-uri ((uri string) (base uri) &optional place)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
172
   (enough-uri (parse-uri uri) base place))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
173
 
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
174
 (defmethod enough-uri ((uri uri) (base uri) &optional place)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
175
   ;; Like ENOUGH-PATHNAME, but for URIs.
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
176
   (let ((new-scheme nil)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
177
         (new-host nil)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
178
         (new-ipv6 nil)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
179
         (new-zone-id nil)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
180
         (new-userinfo nil)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
181
         (new-port nil)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
182
         (new-parsed-path nil))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
183
 
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
184
     ;; If the scheme and authority are not the same, then return URI.
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
185
     (when (or (and (uri-scheme uri)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
186
                    (not (equalp (uri-scheme uri) (uri-scheme base))))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
187
               ;; We don't use uri-authority, because it conses a lot.
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
188
               (and (uri-host uri)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
189
                    (not (equalp (uri-host uri) (uri-host base))))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
190
               (not (equalp (uri-userinfo uri) (uri-userinfo base)))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
191
               (not (equalp (uri-port uri) (uri-port base))))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
192
       (return-from enough-uri uri))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
193
 
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
194
     ;; For this group, if the slot is nil in URI, then the return value is
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
195
     ;; copied from from BASE:
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
196
     (when (null (uri-scheme uri)) (setq new-scheme (uri-scheme base)))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
197
     (when (null (uri-host uri))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
198
       ;; These are copied as a unit:
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
199
       (setq new-host (%uri-host base))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
200
       (setq new-ipv6 (%uri-ipv6 base))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
201
       (setq new-zone-id (%uri-zone-id base)))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
202
     (when (null (uri-userinfo uri)) (setq new-userinfo (uri-userinfo base)))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
203
     (when (null (uri-port uri)) (setq new-port (uri-port base)))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
204
 
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
205
     ;; Now, for the hard one, path.
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
206
     ;; We essentially do here what enough-namestring does.
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
207
     (do* ((base-path (uri-parsed-path base))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
208
           (path (uri-parsed-path uri))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
209
           (bp base-path (cdr bp))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
210
           (p path (cdr p)))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
211
         ((or (null bp) (null p))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
212
          ;; If p is nil, that means we have something like
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
213
          ;; (enough-uri "/foo/bar" "/foo/bar/baz.htm"), so
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
214
          ;; new-parsed-path will be nil.
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
215
          (when (null bp)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
216
            (setq new-parsed-path (copy-list p))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
217
            (when (not (symbolp (car new-parsed-path)))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
218
              (push :relative new-parsed-path))))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
219
       (if* (equal (car bp) (car p))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
220
          thenret ;; skip it
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
221
          else (setq new-parsed-path (copy-list p))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
222
               (when (not (symbolp (car new-parsed-path)))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
223
                 (push :relative new-parsed-path))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
224
               (return)))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
225
 
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
226
     (let ((new-path 
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
227
            (or (when new-parsed-path
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
228
                  (render-parsed-path new-parsed-path
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
229
                                      ;; don't know, so have to assume:
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
230
                                      t))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
231
                ;; can't have a completely empty uri!
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
232
                "/")))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
233
       (copy-uri nil :class (class-of uri) :place place
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
234
             ;;; these come from base if the original slot was nil
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
235
                 :scheme new-scheme
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
236
                 :host new-host
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
237
                 :ipv6 new-ipv6
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
238
                 :zone-id new-zone-id
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
239
                 :userinfo new-userinfo
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
240
                 :port new-port
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
241
                 :path new-path
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
242
                 :parsed-path new-parsed-path
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
243
             ;;; never from base... why? is this documented?
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
244
                 :query (uri-query uri)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
245
                 :fragment (uri-fragment uri)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
246
                 :plist (copy-list (uri-plist uri))))))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
247
 
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
248
 (defmethod enough-uri ((urn urn) (base urn) &optional place)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
249
   (if* place
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
250
      then (setf (urn-nid place) (urn-nid urn))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
251
           (setf (urn-nss place) (urn-nss urn))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
252
           place
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
253
      else urn))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
254
 
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
255
 (defmethod enough-uri ((urn urn) (base uri) &optional place)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
256
   (declare (ignore place))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
257
   (error "enough-uri of a URN (~a) and URI (~a)." urn base))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
258
 
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
259
 (defmethod enough-uri ((uri uri) (base urn) &optional place)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
260
   (declare (ignore place))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
261
   (error "enough-uri of a URI (~a) and URN (~a)." uri base))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
262
 
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
263
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
264
 
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
265
 (defun uri-to-pathname (uri)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
266
   ;; On Windows, turn file:///d:/foo/bar.cl into #p"d:/foo/bar.cl"
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
267
   ;; On UNIX,    turn file:///foo/bar.cl    into #p"/foo/bar.cl"
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
268
   (when (not (eq :file (uri-scheme uri)))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
269
     (error "Only file: URIs can be converted to pathnames: ~s." uri))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
270
   (when (null (uri-path uri)) (error "URI has no path: ~s." uri))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
271
     (pathname
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
272
      (percent-decode-string
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
273
       (uri-path uri)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
274
       nil)))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
275
 
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
276
 (defun pathname-to-uri (pathname)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
277
   (when (not (uiop:absolute-pathname-p pathname t))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
278
     (error "A relative pathname cannot be converted to a URI: ~s." pathname))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
279
   (parse-uri
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
280
    (let ((s (percent-encode-string
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
281
              #+mswindows (substitute #\/ #\\ (namestring pathname))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
282
              #-mswindows (namestring pathname)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
283
              *pchar/-bitvector*)))
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
284
      #-mswindows (format nil "file://~a" s)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
285
      #+mswindows (if* (pathname-device pathname)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
286
                     then (format nil "file:///~a" s)
78ef6145e272 return of the uri
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
287
                     else (format nil "file://~a" s)))))