@@ -98,24 +98,32 @@ func FormatMediaType(t string, param map[string]string) string {
98
98
func checkMediaTypeDisposition (s string ) error {
99
99
typ , rest := consumeToken (s )
100
100
if typ == "" {
101
- return errors . New ( "mime: no media type" )
101
+ return errNoMediaType
102
102
}
103
103
if rest == "" {
104
104
return nil
105
105
}
106
- if ! strings .HasPrefix (rest , "/" ) {
107
- return errors .New ("mime: expected slash after first token" )
106
+ var ok bool
107
+ if rest , ok = strings .CutPrefix (rest , "/" ); ! ok {
108
+ return errNoSlashAfterFirstToken
108
109
}
109
- subtype , rest := consumeToken (rest [ 1 :] )
110
+ subtype , rest := consumeToken (rest )
110
111
if subtype == "" {
111
- return errors . New ( "mime: expected token after slash" )
112
+ return errNoTokenAfterSlash
112
113
}
113
114
if rest != "" {
114
- return errors . New ( "mime: unexpected content after media subtype" )
115
+ return errUnexpectedContentAfterMediaSubtype
115
116
}
116
117
return nil
117
118
}
118
119
120
+ var (
121
+ errNoMediaType = errors .New ("mime: no media type" )
122
+ errNoSlashAfterFirstToken = errors .New ("mime: expected slash after first token" )
123
+ errNoTokenAfterSlash = errors .New ("mime: expected token after slash" )
124
+ errUnexpectedContentAfterMediaSubtype = errors .New ("mime: unexpected content after media subtype" )
125
+ )
126
+
119
127
// ErrInvalidMediaParameter is returned by [ParseMediaType] if
120
128
// the media type value was found but there was an error parsing
121
129
// the optional parameters
@@ -169,15 +177,14 @@ func ParseMediaType(v string) (mediatype string, params map[string]string, err e
169
177
if continuation == nil {
170
178
continuation = make (map [string ]map [string ]string )
171
179
}
172
- var ok bool
173
180
if pmap , ok = continuation [baseName ]; ! ok {
174
181
continuation [baseName ] = make (map [string ]string )
175
182
pmap = continuation [baseName ]
176
183
}
177
184
}
178
185
if v , exists := pmap [key ]; exists && v != value {
179
186
// Duplicate parameter names are incorrect, but we allow them if they are equal.
180
- return "" , nil , errors . New ( "mime: duplicate parameter name" )
187
+ return "" , nil , errDuplicateParamName
181
188
}
182
189
pmap [key ] = value
183
190
v = rest
@@ -227,27 +234,28 @@ func ParseMediaType(v string) (mediatype string, params map[string]string, err e
227
234
return
228
235
}
229
236
237
+ var errDuplicateParamName = errors .New ("mime: duplicate parameter name" )
238
+
230
239
func decode2231Enc (v string ) (string , bool ) {
231
- sv := strings .SplitN (v , "'" , 3 )
232
- if len ( sv ) != 3 {
240
+ charset , v , ok := strings .Cut (v , "'" )
241
+ if ! ok {
233
242
return "" , false
234
243
}
235
- // TODO: ignoring lang in sv[1] for now. If anybody needs it we'll
244
+ // TODO: ignoring the language part for now. If anybody needs it, we'll
236
245
// need to decide how to expose it in the API. But I'm not sure
237
246
// anybody uses it in practice.
238
- charset := strings .ToLower ( sv [ 0 ] )
239
- if len ( charset ) == 0 {
247
+ _ , extOtherVals , ok := strings .Cut ( v , "'" )
248
+ if ! ok {
240
249
return "" , false
241
250
}
242
- if charset != "us-ascii" && charset != "utf-8" {
243
- // TODO: unsupported encoding
251
+ charset = strings .ToLower (charset )
252
+ switch charset {
253
+ case "us-ascii" , "utf-8" :
254
+ default :
255
+ // Empty or unsupported encoding.
244
256
return "" , false
245
257
}
246
- encv , err := percentHexUnescape (sv [2 ])
247
- if err != nil {
248
- return "" , false
249
- }
250
- return encv , true
258
+ return percentHexUnescape (extOtherVals )
251
259
}
252
260
253
261
// consumeToken consumes a token from the beginning of provided
@@ -309,11 +317,11 @@ func consumeValue(v string) (value, rest string) {
309
317
310
318
func consumeMediaParam (v string ) (param , value , rest string ) {
311
319
rest = strings .TrimLeftFunc (v , unicode .IsSpace )
312
- if ! strings .HasPrefix (rest , ";" ) {
320
+ var ok bool
321
+ if rest , ok = strings .CutPrefix (rest , ";" ); ! ok {
313
322
return "" , "" , v
314
323
}
315
324
316
- rest = rest [1 :] // consume semicolon
317
325
rest = strings .TrimLeftFunc (rest , unicode .IsSpace )
318
326
param , rest = consumeToken (rest )
319
327
param = strings .ToLower (param )
@@ -322,10 +330,9 @@ func consumeMediaParam(v string) (param, value, rest string) {
322
330
}
323
331
324
332
rest = strings .TrimLeftFunc (rest , unicode .IsSpace )
325
- if ! strings .HasPrefix (rest , "=" ) {
333
+ if rest , ok = strings .CutPrefix (rest , "=" ); ! ok {
326
334
return "" , "" , v
327
335
}
328
- rest = rest [1 :] // consume equals sign
329
336
rest = strings .TrimLeftFunc (rest , unicode .IsSpace )
330
337
value , rest2 := consumeValue (rest )
331
338
if value == "" && rest2 == rest {
@@ -335,7 +342,7 @@ func consumeMediaParam(v string) (param, value, rest string) {
335
342
return param , value , rest
336
343
}
337
344
338
- func percentHexUnescape (s string ) (string , error ) {
345
+ func percentHexUnescape (s string ) (string , bool ) {
339
346
// Count %, check that they're well-formed.
340
347
percents := 0
341
348
for i := 0 ; i < len (s ); {
@@ -345,16 +352,12 @@ func percentHexUnescape(s string) (string, error) {
345
352
}
346
353
percents ++
347
354
if i + 2 >= len (s ) || ! ishex (s [i + 1 ]) || ! ishex (s [i + 2 ]) {
348
- s = s [i :]
349
- if len (s ) > 3 {
350
- s = s [0 :3 ]
351
- }
352
- return "" , fmt .Errorf ("mime: bogus characters after %%: %q" , s )
355
+ return "" , false
353
356
}
354
357
i += 3
355
358
}
356
359
if percents == 0 {
357
- return s , nil
360
+ return s , true
358
361
}
359
362
360
363
t := make ([]byte , len (s )- 2 * percents )
@@ -371,7 +374,7 @@ func percentHexUnescape(s string) (string, error) {
371
374
i ++
372
375
}
373
376
}
374
- return string (t ), nil
377
+ return string (t ), true
375
378
}
376
379
377
380
func ishex (c byte ) bool {
0 commit comments