Skip to content

Commit 2a5c386

Browse files
committed
fix: make sure relative paths are checked correctly
logo, monochromeLogo, authorsFile and screenshots are supposed to be either relative paths or HTTP URLs.
1 parent 5773d64 commit 2a5c386

File tree

7 files changed

+275
-20
lines changed

7 files changed

+275
-20
lines changed

fields.go

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package publiccode
33
import (
44
"fmt"
55
"net/url"
6+
"strings"
67

78
"github.com/alranel/go-vcsurl/v2"
89
urlutil "github.com/italia/publiccode-parser-go/v4/internal"
@@ -47,26 +48,32 @@ func validateFieldsV0(publiccode PublicCode, parser Parser, network bool) error
4748
}
4849

4950
if publiccodev0.Logo != "" {
50-
if validLogo, err := parser.validLogo(toCodeHostingURL(publiccodev0.Logo, parser.baseURL), network); !validLogo {
51+
if _, err := isRelativePathOrURL(publiccodev0.Logo, "logo"); err != nil {
52+
vr = append(vr, err)
53+
} else if validLogo, err := parser.validLogo(toCodeHostingURL(publiccodev0.Logo, parser.baseURL), network); !validLogo {
5154
vr = append(vr, newValidationError("logo", err.Error()))
5255
}
5356
}
5457

5558
if publiccodev0.MonochromeLogo != "" {
5659
vr = append(vr, ValidationWarning{"monochromeLogo", "This key is DEPRECATED and will be removed in the future", 0, 0})
5760

58-
if validLogo, err := parser.validLogo(toCodeHostingURL(publiccodev0.MonochromeLogo, parser.baseURL), network); !validLogo {
61+
if _, err := isRelativePathOrURL(publiccodev0.MonochromeLogo, "monochromeLogo"); err != nil {
62+
vr = append(vr, err)
63+
} else if validLogo, err := parser.validLogo(toCodeHostingURL(publiccodev0.MonochromeLogo, parser.baseURL), network); !validLogo {
5964
vr = append(vr, newValidationError("monochromeLogo", err.Error()))
6065
}
6166
}
6267

6368
if publiccodev0.Legal.AuthorsFile != nil {
6469
vr = append(vr, ValidationWarning{"legal.authorsFile", "This key is DEPRECATED and will be removed in the future", 0, 0})
6570

66-
if !parser.fileExists(toCodeHostingURL(*publiccodev0.Legal.AuthorsFile, parser.baseURL), network) {
71+
if _, err := isRelativePathOrURL(*publiccodev0.Legal.AuthorsFile, "legal.authorsFile"); err != nil {
72+
vr = append(vr, err)
73+
} else if exists, err := parser.fileExists(toCodeHostingURL(*publiccodev0.Legal.AuthorsFile, parser.baseURL), network); !exists {
6774
u := toCodeHostingURL(*publiccodev0.Legal.AuthorsFile, parser.baseURL)
6875

69-
vr = append(vr, newValidationError("legal.authorsFile", "'%s' does not exist", urlutil.DisplayURL(&u)))
76+
vr = append(vr, newValidationError("legal.authorsFile", "'%s' does not exist: %s", urlutil.DisplayURL(&u), err.Error()))
7077
}
7178
}
7279

@@ -109,9 +116,12 @@ func validateFieldsV0(publiccode PublicCode, parser Parser, network bool) error
109116
}
110117

111118
for i, v := range desc.Screenshots {
112-
if isImage, err := parser.isImageFile(toCodeHostingURL(v, parser.baseURL), network); !isImage {
119+
keyName := fmt.Sprintf("description.%s.screenshots[%d]", lang, i)
120+
if _, err := isRelativePathOrURL(v, keyName); err != nil {
121+
vr = append(vr, err)
122+
} else if isImage, err := parser.isImageFile(toCodeHostingURL(v, parser.baseURL), network); !isImage {
113123
vr = append(vr, newValidationError(
114-
fmt.Sprintf("description.%s.screenshots[%d]", lang, i),
124+
keyName,
115125
"'%s' is not an image: %s", v, err.Error(),
116126
))
117127
}
@@ -134,3 +144,19 @@ func validateFieldsV0(publiccode PublicCode, parser Parser, network bool) error
134144

135145
return vr
136146
}
147+
148+
// isRelativePathOrURL checks whether the field contains either a relative filename
149+
// or an HTTP URL
150+
//
151+
//nolint:unparam
152+
func isRelativePathOrURL(content string, keyName string) (bool, error) {
153+
if strings.HasPrefix(content, "/") {
154+
return false, newValidationError(keyName, "is an absolute path. Only relative paths or HTTP(s) URLs allowed")
155+
}
156+
157+
if strings.HasPrefix(content, "file:") {
158+
return false, newValidationError(keyName, "is a file:// URL. Only relative paths or HTTP(s) URLs allowed")
159+
}
160+
161+
return true, nil
162+
}

parser_test.go

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,19 @@ func TestInvalidTestcasesV0(t *testing.T) {
250250
ValidationError{"logo", "invalid file extension for: https://raw.githubusercontent.com/italia/developers.italia.it/main/logo.mpg", 18, 1},
251251
},
252252
"logo_missing_file.yml": ValidationResults{
253-
ValidationError{"logo", "no such file: https://raw.githubusercontent.com/italia/developers.italia.it/main/no_such_file.png", 18, 1},
253+
ValidationError{"logo", "HTTP GET failed for https://raw.githubusercontent.com/italia/developers.italia.it/main/no_such_file.png: not found", 18, 1},
254+
},
255+
"logo_absolute_path.yml": ValidationResults{
256+
ValidationError{"logo", "is an absolute path. Only relative paths or HTTP(s) URLs allowed", 18, 1},
257+
},
258+
"logo_file_scheme.yml": ValidationResults{
259+
ValidationError{"logo", "is a file:// URL. Only relative paths or HTTP(s) URLs allowed", 18, 1},
260+
},
261+
"logo_file_scheme2.yml": ValidationResults{
262+
ValidationError{"logo", "is a file:// URL. Only relative paths or HTTP(s) URLs allowed", 18, 1},
263+
},
264+
"logo_file_scheme3.yml": ValidationResults{
265+
ValidationError{"logo", "is a file:// URL. Only relative paths or HTTP(s) URLs allowed", 18, 1},
254266
},
255267

256268
// monochromeLogo
@@ -268,7 +280,7 @@ func TestInvalidTestcasesV0(t *testing.T) {
268280
},
269281
"monochromeLogo_missing_file.yml": ValidationResults{
270282
ValidationWarning{"monochromeLogo", "This key is DEPRECATED and will be removed in the future", 18, 1},
271-
ValidationError{"monochromeLogo", "no such file: https://raw.githubusercontent.com/italia/developers.italia.it/main/no_such_file.png", 18, 1},
283+
ValidationError{"monochromeLogo", "HTTP GET failed for https://raw.githubusercontent.com/italia/developers.italia.it/main/no_such_file.png: not found", 18, 1},
272284
},
273285

274286
// inputTypes
@@ -427,7 +439,7 @@ func TestInvalidTestcasesV0(t *testing.T) {
427439
"description_en_screenshots_missing_file.yml": ValidationResults{
428440
ValidationError{
429441
"description.en.screenshots[0]",
430-
"'no_such_file.png' is not an image: no such file : https://raw.githubusercontent.com/italia/developers.italia.it/main/no_such_file.png",
442+
"'no_such_file.png' is not an image: HTTP GET failed for https://raw.githubusercontent.com/italia/developers.italia.it/main/no_such_file.png: not found",
431443
20,
432444
5,
433445
},
@@ -463,7 +475,7 @@ func TestInvalidTestcasesV0(t *testing.T) {
463475
},
464476
ValidationError{
465477
"legal.authorsFile",
466-
"'https://raw.githubusercontent.com/italia/developers.italia.it/main/no_such_authors_file.txt' does not exist",
478+
"'https://raw.githubusercontent.com/italia/developers.italia.it/main/no_such_authors_file.txt' does not exist: HTTP GET failed for https://raw.githubusercontent.com/italia/developers.italia.it/main/no_such_authors_file.txt: not found",
467479
42,
468480
3,
469481
},
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
publiccodeYmlVersion: "0.4"
2+
3+
name: Medusa
4+
url: "https://github.com/italia/developers.italia.it.git"
5+
releaseDate: "2017-04-15"
6+
7+
platforms:
8+
- web
9+
10+
categories:
11+
- cloud-management
12+
13+
developmentStatus: development
14+
15+
softwareType: "standalone/other"
16+
17+
# Should NOT validate: it's an absolute path. logo must be either an HTTP URL or a relative path
18+
logo: "/logo.png"
19+
20+
description:
21+
en:
22+
localisedName: Medusa
23+
shortDescription: >
24+
A rather short description which
25+
is probably useless
26+
longDescription: >
27+
Very long description of this software, also split
28+
on multiple rows. You should note what the software
29+
is and why one should need it. This is 158 characters.
30+
Very long description of this software, also split
31+
on multiple rows. You should note what the software
32+
is and why one should need it. This is 316 characters.
33+
Very long description of this software, also split
34+
on multiple rows. You should note what the software
35+
is and why one should need it. This is 474 characters.
36+
Very long description of this software, also split
37+
on multiple rows. You should note what the software
38+
is and why one should need it. This is 632 characters.
39+
features:
40+
- Just one feature
41+
42+
legal:
43+
license: AGPL-3.0-or-later
44+
45+
maintenance:
46+
type: "community"
47+
48+
contacts:
49+
- name: Francesco Rossi
50+
51+
localisation:
52+
localisationReady: true
53+
availableLanguages:
54+
- en
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
publiccodeYmlVersion: "0.4"
2+
3+
name: Medusa
4+
url: "https://github.com/italia/developers.italia.it.git"
5+
releaseDate: "2017-04-15"
6+
7+
platforms:
8+
- web
9+
10+
categories:
11+
- cloud-management
12+
13+
developmentStatus: development
14+
15+
softwareType: "standalone/other"
16+
17+
# Should NOT validate: it has a "file:" scheme. logo must be either an HTTP URL or a relative path
18+
logo: "file:///logo.png"
19+
20+
description:
21+
en:
22+
localisedName: Medusa
23+
shortDescription: >
24+
A rather short description which
25+
is probably useless
26+
longDescription: >
27+
Very long description of this software, also split
28+
on multiple rows. You should note what the software
29+
is and why one should need it. This is 158 characters.
30+
Very long description of this software, also split
31+
on multiple rows. You should note what the software
32+
is and why one should need it. This is 316 characters.
33+
Very long description of this software, also split
34+
on multiple rows. You should note what the software
35+
is and why one should need it. This is 474 characters.
36+
Very long description of this software, also split
37+
on multiple rows. You should note what the software
38+
is and why one should need it. This is 632 characters.
39+
features:
40+
- Just one feature
41+
42+
legal:
43+
license: AGPL-3.0-or-later
44+
45+
maintenance:
46+
type: "community"
47+
48+
contacts:
49+
- name: Francesco Rossi
50+
51+
localisation:
52+
localisationReady: true
53+
availableLanguages:
54+
- en
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
publiccodeYmlVersion: "0.4"
2+
3+
name: Medusa
4+
url: "https://github.com/italia/developers.italia.it.git"
5+
releaseDate: "2017-04-15"
6+
7+
platforms:
8+
- web
9+
10+
categories:
11+
- cloud-management
12+
13+
developmentStatus: development
14+
15+
softwareType: "standalone/other"
16+
17+
# Should NOT validate: it has a (invalid) "file:" scheme. logo must be either an HTTP URL or a relative path
18+
logo: "file://logo.png"
19+
20+
description:
21+
en:
22+
localisedName: Medusa
23+
shortDescription: >
24+
A rather short description which
25+
is probably useless
26+
longDescription: >
27+
Very long description of this software, also split
28+
on multiple rows. You should note what the software
29+
is and why one should need it. This is 158 characters.
30+
Very long description of this software, also split
31+
on multiple rows. You should note what the software
32+
is and why one should need it. This is 316 characters.
33+
Very long description of this software, also split
34+
on multiple rows. You should note what the software
35+
is and why one should need it. This is 474 characters.
36+
Very long description of this software, also split
37+
on multiple rows. You should note what the software
38+
is and why one should need it. This is 632 characters.
39+
features:
40+
- Just one feature
41+
42+
legal:
43+
license: AGPL-3.0-or-later
44+
45+
maintenance:
46+
type: "community"
47+
48+
contacts:
49+
- name: Francesco Rossi
50+
51+
localisation:
52+
localisationReady: true
53+
availableLanguages:
54+
- en
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
publiccodeYmlVersion: "0.4"
2+
3+
name: Medusa
4+
url: "https://github.com/italia/developers.italia.it.git"
5+
releaseDate: "2017-04-15"
6+
7+
platforms:
8+
- web
9+
10+
categories:
11+
- cloud-management
12+
13+
developmentStatus: development
14+
15+
softwareType: "standalone/other"
16+
17+
# Should NOT validate: it has a (invalid) "file:" scheme. logo must be either an HTTP URL or a relative path
18+
logo: "file:/logo.png"
19+
20+
description:
21+
en:
22+
localisedName: Medusa
23+
shortDescription: >
24+
A rather short description which
25+
is probably useless
26+
longDescription: >
27+
Very long description of this software, also split
28+
on multiple rows. You should note what the software
29+
is and why one should need it. This is 158 characters.
30+
Very long description of this software, also split
31+
on multiple rows. You should note what the software
32+
is and why one should need it. This is 316 characters.
33+
Very long description of this software, also split
34+
on multiple rows. You should note what the software
35+
is and why one should need it. This is 474 characters.
36+
Very long description of this software, also split
37+
on multiple rows. You should note what the software
38+
is and why one should need it. This is 632 characters.
39+
features:
40+
- Just one feature
41+
42+
legal:
43+
license: AGPL-3.0-or-later
44+
45+
maintenance:
46+
type: "community"
47+
48+
contacts:
49+
- name: Francesco Rossi
50+
51+
localisation:
52+
localisationReady: true
53+
availableLanguages:
54+
- en

0 commit comments

Comments
 (0)