17
17
package detect
18
18
19
19
import (
20
+ "bufio"
20
21
"fmt"
22
+ "io"
23
+ "strconv"
21
24
"strings"
22
25
23
26
"github.com/anchore/syft/syft/source"
24
27
"github.com/docker/index-cli-plugin/types"
25
28
)
26
29
27
- func nodePackageDetector (_ []types.Package , image source.Source , lm types.LayerMapping ) []types.Package {
30
+ func nodePackageDetector (pkgs []types.Package , image source.Source , lm types.LayerMapping ) []types.Package {
31
+ // Already found nodejs via package manager
32
+ for _ , p := range pkgs {
33
+ if purl , err := types .ToPackageUrl (p .Purl ); err == nil && purl .Name == "nodejs" {
34
+ return []types.Package {}
35
+ }
36
+ }
37
+
28
38
var path []string
29
39
var nodeVersion string
30
40
@@ -40,12 +50,25 @@ func nodePackageDetector(_ []types.Package, image source.Source, lm types.LayerM
40
50
}
41
51
}
42
52
43
- if nodeVersion != "" && len (path ) > 0 {
53
+ if len (path ) > 0 {
44
54
res , _ := image .FileResolver (source .SquashedScope )
45
55
for _ , p := range path {
46
56
fp := fmt .Sprintf ("%s/node" , p )
47
57
if locations , err := res .FilesByPath (fp ); err == nil && len (locations ) > 0 {
48
58
loc := locations [0 ]
59
+
60
+ if nodeVersion == "" {
61
+ f , _ := res .FileContentsByLocation (loc )
62
+ values := readStrings (f , "node.js/v" )
63
+ if len (values ) == 1 {
64
+ nodeVersion = values [0 ][9 :]
65
+ }
66
+ }
67
+
68
+ if nodeVersion == "" {
69
+ continue
70
+ }
71
+
49
72
return []types.Package {{
50
73
Type : "github" ,
51
74
Namespace : "nodejs" ,
@@ -68,3 +91,48 @@ func nodePackageDetector(_ []types.Package, image source.Source, lm types.LayerM
68
91
69
92
return []types.Package {}
70
93
}
94
+
95
+ var (
96
+ min = 6
97
+ max = 256
98
+ ascii = true
99
+ )
100
+
101
+ func readStrings (file io.ReadCloser , prefix string ) []string {
102
+ detected := make ([]string , 0 )
103
+ in := bufio .NewReader (file )
104
+ str := make ([]rune , 0 , max )
105
+ filePos := int64 (0 )
106
+ print := func () {
107
+ if len (str ) >= min {
108
+ s := string (str )
109
+ if strings .HasPrefix (s , prefix ) {
110
+ detected = append (detected , s )
111
+ }
112
+ }
113
+ str = str [0 :0 ]
114
+ }
115
+ for {
116
+ var (
117
+ r rune
118
+ wid int
119
+ err error
120
+ )
121
+ for ; ; filePos += int64 (wid ) {
122
+ r , wid , err = in .ReadRune ()
123
+ if err != nil {
124
+ return detected
125
+ }
126
+ if ! strconv .IsPrint (r ) || ascii && r >= 0xFF {
127
+ print ()
128
+ continue
129
+ }
130
+ // It's printable. Keep it.
131
+ if len (str ) >= max {
132
+ print ()
133
+ }
134
+ str = append (str , r )
135
+ }
136
+ }
137
+ return detected
138
+ }
0 commit comments