@@ -270,7 +270,7 @@ func fileNameOK(r rune) bool {
270
270
271
271
// CheckPath checks that a module path is valid.
272
272
// A valid module path is a valid import path, as checked by CheckImportPath,
273
- // with two additional constraints.
273
+ // with three additional constraints.
274
274
// First, the leading path element (up to the first slash, if any),
275
275
// by convention a domain name, must contain only lower-case ASCII letters,
276
276
// ASCII digits, dots (U+002E), and dashes (U+002D);
@@ -280,8 +280,9 @@ func fileNameOK(r rune) bool {
280
280
// and must not contain any dots. For paths beginning with "gopkg.in/",
281
281
// this second requirement is replaced by a requirement that the path
282
282
// follow the gopkg.in server's conventions.
283
+ // Third, no path element may begin with a dot.
283
284
func CheckPath (path string ) error {
284
- if err := checkPath (path , false ); err != nil {
285
+ if err := checkPath (path , modulePath ); err != nil {
285
286
return fmt .Errorf ("malformed module path %q: %v" , path , err )
286
287
}
287
288
i := strings .Index (path , "/" )
@@ -315,7 +316,7 @@ func CheckPath(path string) error {
315
316
//
316
317
// A valid path element is a non-empty string made up of
317
318
// ASCII letters, ASCII digits, and limited ASCII punctuation: - . _ and ~.
318
- // It must not begin or end with a dot (U+002E), nor contain two dots in a row.
319
+ // It must not end with a dot (U+002E), nor contain two dots in a row.
319
320
//
320
321
// The element prefix up to the first dot must not be a reserved file name
321
322
// on Windows, regardless of case (CON, com1, NuL, and so on). The element
@@ -326,19 +327,29 @@ func CheckPath(path string) error {
326
327
// top-level package documentation for additional information about
327
328
// subtleties of Unicode.
328
329
func CheckImportPath (path string ) error {
329
- if err := checkPath (path , false ); err != nil {
330
+ if err := checkPath (path , importPath ); err != nil {
330
331
return fmt .Errorf ("malformed import path %q: %v" , path , err )
331
332
}
332
333
return nil
333
334
}
334
335
336
+ // pathKind indicates what kind of path we're checking. Module paths,
337
+ // import paths, and file paths have different restrictions.
338
+ type pathKind int
339
+
340
+ const (
341
+ modulePath pathKind = iota
342
+ importPath
343
+ filePath
344
+ )
345
+
335
346
// checkPath checks that a general path is valid.
336
347
// It returns an error describing why but not mentioning path.
337
348
// Because these checks apply to both module paths and import paths,
338
349
// the caller is expected to add the "malformed ___ path %q: " prefix.
339
350
// fileName indicates whether the final element of the path is a file name
340
351
// (as opposed to a directory name).
341
- func checkPath (path string , fileName bool ) error {
352
+ func checkPath (path string , kind pathKind ) error {
342
353
if ! utf8 .ValidString (path ) {
343
354
return fmt .Errorf ("invalid UTF-8" )
344
355
}
@@ -357,35 +368,34 @@ func checkPath(path string, fileName bool) error {
357
368
elemStart := 0
358
369
for i , r := range path {
359
370
if r == '/' {
360
- if err := checkElem (path [elemStart :i ], fileName ); err != nil {
371
+ if err := checkElem (path [elemStart :i ], kind ); err != nil {
361
372
return err
362
373
}
363
374
elemStart = i + 1
364
375
}
365
376
}
366
- if err := checkElem (path [elemStart :], fileName ); err != nil {
377
+ if err := checkElem (path [elemStart :], kind ); err != nil {
367
378
return err
368
379
}
369
380
return nil
370
381
}
371
382
372
383
// checkElem checks whether an individual path element is valid.
373
- // fileName indicates whether the element is a file name (not a directory name).
374
- func checkElem (elem string , fileName bool ) error {
384
+ func checkElem (elem string , kind pathKind ) error {
375
385
if elem == "" {
376
386
return fmt .Errorf ("empty path element" )
377
387
}
378
388
if strings .Count (elem , "." ) == len (elem ) {
379
389
return fmt .Errorf ("invalid path element %q" , elem )
380
390
}
381
- if elem [0 ] == '.' && ! fileName {
391
+ if elem [0 ] == '.' && kind == modulePath {
382
392
return fmt .Errorf ("leading dot in path element" )
383
393
}
384
394
if elem [len (elem )- 1 ] == '.' {
385
395
return fmt .Errorf ("trailing dot in path element" )
386
396
}
387
397
charOK := pathOK
388
- if fileName {
398
+ if kind == filePath {
389
399
charOK = fileNameOK
390
400
}
391
401
for _ , r := range elem {
@@ -406,7 +416,7 @@ func checkElem(elem string, fileName bool) error {
406
416
}
407
417
}
408
418
409
- if fileName {
419
+ if kind == filePath {
410
420
// don't check for Windows short-names in file names. They're
411
421
// only an issue for import paths.
412
422
return nil
@@ -444,7 +454,7 @@ func checkElem(elem string, fileName bool) error {
444
454
// top-level package documentation for additional information about
445
455
// subtleties of Unicode.
446
456
func CheckFilePath (path string ) error {
447
- if err := checkPath (path , true ); err != nil {
457
+ if err := checkPath (path , filePath ); err != nil {
448
458
return fmt .Errorf ("malformed file path %q: %v" , path , err )
449
459
}
450
460
return nil
@@ -647,7 +657,7 @@ func EscapePath(path string) (escaped string, err error) {
647
657
// Versions are allowed to be in non-semver form but must be valid file names
648
658
// and not contain exclamation marks.
649
659
func EscapeVersion (v string ) (escaped string , err error ) {
650
- if err := checkElem (v , true ); err != nil || strings .Contains (v , "!" ) {
660
+ if err := checkElem (v , filePath ); err != nil || strings .Contains (v , "!" ) {
651
661
return "" , & InvalidVersionError {
652
662
Version : v ,
653
663
Err : fmt .Errorf ("disallowed version string" ),
@@ -706,7 +716,7 @@ func UnescapeVersion(escaped string) (v string, err error) {
706
716
if ! ok {
707
717
return "" , fmt .Errorf ("invalid escaped version %q" , escaped )
708
718
}
709
- if err := checkElem (v , true ); err != nil {
719
+ if err := checkElem (v , filePath ); err != nil {
710
720
return "" , fmt .Errorf ("invalid escaped version %q: %v" , v , err )
711
721
}
712
722
return v , nil
0 commit comments