@@ -125,48 +125,78 @@ type challenge struct {
125
125
userhash string
126
126
}
127
127
128
+ func (c * challenge ) setValue (k , v string ) error {
129
+ switch k {
130
+ case "realm" :
131
+ c .realm = v
132
+ case "domain" :
133
+ c .domain = v
134
+ case "nonce" :
135
+ c .nonce = v
136
+ case "opaque" :
137
+ c .opaque = v
138
+ case "stale" :
139
+ c .stale = v
140
+ case "algorithm" :
141
+ c .algorithm = v
142
+ case "qop" :
143
+ c .qop = v
144
+ case "charset" :
145
+ if strings .ToUpper (v ) != "UTF-8" {
146
+ return ErrDigestCharset
147
+ }
148
+ case "userhash" :
149
+ c .userhash = v
150
+ default :
151
+ return ErrDigestBadChallenge
152
+ }
153
+ return nil
154
+ }
155
+
128
156
func parseChallenge (input string ) (* challenge , error ) {
129
157
const ws = " \n \r \t "
130
- const qs = `"`
131
158
s := strings .Trim (input , ws )
132
159
if ! strings .HasPrefix (s , "Digest " ) {
133
160
return nil , ErrDigestBadChallenge
134
161
}
135
162
s = strings .Trim (s [7 :], ws )
136
- sl := strings .Split (s , "," )
137
163
c := & challenge {}
138
- var r []string
139
- for i := range sl {
140
- sl [i ] = strings .TrimSpace (sl [i ])
141
- r = strings .SplitN (sl [i ], "=" , 2 )
142
- if len (r ) != 2 {
143
- return nil , ErrDigestBadChallenge
144
- }
145
- r [0 ] = strings .TrimSpace (r [0 ])
146
- r [1 ] = strings .TrimSpace (r [1 ])
147
- switch r [0 ] {
148
- case "realm" :
149
- c .realm = strings .Trim (r [1 ], qs )
150
- case "domain" :
151
- c .domain = strings .Trim (r [1 ], qs )
152
- case "nonce" :
153
- c .nonce = strings .Trim (r [1 ], qs )
154
- case "opaque" :
155
- c .opaque = strings .Trim (r [1 ], qs )
156
- case "stale" :
157
- c .stale = strings .Trim (r [1 ], qs )
158
- case "algorithm" :
159
- c .algorithm = strings .Trim (r [1 ], qs )
160
- case "qop" :
161
- c .qop = strings .Trim (r [1 ], qs )
162
- case "charset" :
163
- if strings .ToUpper (strings .Trim (r [1 ], qs )) != "UTF-8" {
164
- return nil , ErrDigestCharset
164
+ b := strings.Builder {}
165
+ key := ""
166
+ quoted := false
167
+ for _ , r := range s {
168
+ switch r {
169
+ case '"' :
170
+ quoted = ! quoted
171
+ case ',' :
172
+ if quoted {
173
+ b .WriteRune (r )
174
+ } else {
175
+ val := strings .Trim (b .String (), ws )
176
+ b .Reset ()
177
+ if err := c .setValue (key , val ); err != nil {
178
+ return nil , err
179
+ }
180
+ key = ""
181
+ }
182
+ case '=' :
183
+ if quoted {
184
+ b .WriteRune (r )
185
+ } else {
186
+ key = strings .Trim (b .String (), ws )
187
+ b .Reset ()
165
188
}
166
- case "userhash" :
167
- c .userhash = strings .Trim (r [1 ], qs )
168
189
default :
169
- return nil , ErrDigestBadChallenge
190
+ b .WriteRune (r )
191
+ }
192
+ }
193
+ if quoted || (key == "" && b .Len () > 0 ) {
194
+ return nil , ErrDigestBadChallenge
195
+ }
196
+ if key != "" {
197
+ val := strings .Trim (b .String (), ws )
198
+ if err := c .setValue (key , val ); err != nil {
199
+ return nil , err
170
200
}
171
201
}
172
202
return c , nil
0 commit comments