1
2
3
4
5 package webdav
6
7
8
9
10 import (
11 "strings"
12 )
13
14
15 type ifHeader struct {
16 lists []ifList
17 }
18
19
20 type ifList struct {
21 resourceTag string
22 conditions []Condition
23 }
24
25
26
27
28 func parseIfHeader(httpHeader string) (h ifHeader, ok bool) {
29 s := strings.TrimSpace(httpHeader)
30 switch tokenType, _, _ := lex(s); tokenType {
31 case '(':
32 return parseNoTagLists(s)
33 case angleTokenType:
34 return parseTaggedLists(s)
35 default:
36 return ifHeader{}, false
37 }
38 }
39
40 func parseNoTagLists(s string) (h ifHeader, ok bool) {
41 for {
42 l, remaining, ok := parseList(s)
43 if !ok {
44 return ifHeader{}, false
45 }
46 h.lists = append(h.lists, l)
47 if remaining == "" {
48 return h, true
49 }
50 s = remaining
51 }
52 }
53
54 func parseTaggedLists(s string) (h ifHeader, ok bool) {
55 resourceTag, n := "", 0
56 for first := true; ; first = false {
57 tokenType, tokenStr, remaining := lex(s)
58 switch tokenType {
59 case angleTokenType:
60 if !first && n == 0 {
61 return ifHeader{}, false
62 }
63 resourceTag, n = tokenStr, 0
64 s = remaining
65 case '(':
66 n++
67 l, remaining, ok := parseList(s)
68 if !ok {
69 return ifHeader{}, false
70 }
71 l.resourceTag = resourceTag
72 h.lists = append(h.lists, l)
73 if remaining == "" {
74 return h, true
75 }
76 s = remaining
77 default:
78 return ifHeader{}, false
79 }
80 }
81 }
82
83 func parseList(s string) (l ifList, remaining string, ok bool) {
84 tokenType, _, s := lex(s)
85 if tokenType != '(' {
86 return ifList{}, "", false
87 }
88 for {
89 tokenType, _, remaining = lex(s)
90 if tokenType == ')' {
91 if len(l.conditions) == 0 {
92 return ifList{}, "", false
93 }
94 return l, remaining, true
95 }
96 c, remaining, ok := parseCondition(s)
97 if !ok {
98 return ifList{}, "", false
99 }
100 l.conditions = append(l.conditions, c)
101 s = remaining
102 }
103 }
104
105 func parseCondition(s string) (c Condition, remaining string, ok bool) {
106 tokenType, tokenStr, s := lex(s)
107 if tokenType == notTokenType {
108 c.Not = true
109 tokenType, tokenStr, s = lex(s)
110 }
111 switch tokenType {
112 case strTokenType, angleTokenType:
113 c.Token = tokenStr
114 case squareTokenType:
115 c.ETag = tokenStr
116 default:
117 return Condition{}, "", false
118 }
119 return c, s, true
120 }
121
122
123
124 const (
125 errTokenType = rune(-1)
126 eofTokenType = rune(-2)
127 strTokenType = rune(-3)
128 notTokenType = rune(-4)
129 angleTokenType = rune(-5)
130 squareTokenType = rune(-6)
131 )
132
133 func lex(s string) (tokenType rune, tokenStr string, remaining string) {
134
135
136
137 for len(s) > 0 && (s[0] == '\t' || s[0] == ' ') {
138 s = s[1:]
139 }
140 if len(s) == 0 {
141 return eofTokenType, "", ""
142 }
143 i := 0
144 loop:
145 for ; i < len(s); i++ {
146 switch s[i] {
147 case '\t', ' ', '(', ')', '<', '>', '[', ']':
148 break loop
149 }
150 }
151
152 if i != 0 {
153 tokenStr, remaining = s[:i], s[i:]
154 if tokenStr == "Not" {
155 return notTokenType, "", remaining
156 }
157 return strTokenType, tokenStr, remaining
158 }
159
160 j := 0
161 switch s[0] {
162 case '<':
163 j, tokenType = strings.IndexByte(s, '>'), angleTokenType
164 case '[':
165 j, tokenType = strings.IndexByte(s, ']'), squareTokenType
166 default:
167 return rune(s[0]), "", s[1:]
168 }
169 if j < 0 {
170 return errTokenType, "", ""
171 }
172 return tokenType, s[1:j], s[j+1:]
173 }
174
View as plain text