File: utilities.go

package info (click to toggle)
golang-github-knqyf263-go-cpe 0.0~git20180327.659663f6-4
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, experimental, forky, sid, trixie
  • size: 18,036 kB
  • sloc: sh: 11; makefile: 4
file content (170 lines) | stat: -rw-r--r-- 4,748 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
package common

import (
	"strings"
	"unicode"

	"github.com/pkg/errors"
)

// IndexOf searches a string for the first occurrence of another string, starting
// at a given offset.
// @param str1 String to search.
// @param str2 String to search for.
// @param off Integer offset or -1 if not found.
func IndexOf(str1, str2 string, off int) int {
	index := strings.Index(str1[off:], str2)
	if index == -1 {
		return -1
	}
	return index + off
}

// ContainsWildcards searches string for special characters * and ?
// @param string String to be searched
// @return true if string contains wildcard, false otherwise
func ContainsWildcards(str string) bool {
	prev := ' '
	for _, s := range str {
		if s == '*' || s == '?' {
			if prev != '\\' {
				return true
			}
		}
		prev = s
	}
	return false
}

// ContainsQuestions searches string for special characters ?
// @param string String to be searched
// @return true if string contains wildcard, false otherwise
func ContainsQuestions(str string) bool {
	prev := ' '
	for _, s := range str {
		if s == '?' {
			if prev != '\\' {
				return true
			}
		}
		prev = s
	}
	return false
}

// CountEscapeCharacters counts the number of escape characters in the string beginning and ending
// at the given indices
// @param str string to search
// @param start beginning index
// @param end ending index
// @return number of escape characters in string
func CountEscapeCharacters(str string) (result int) {
	active := false
	for _, s := range str {
		if !active && s == '\\' {
			result++
			active = true
		} else {
			active = false
		}
	}
	return result
}

// LengthWithEscapeCharacters counts the number of characters with escape characters
func LengthWithEscapeCharacters(str string) (result int) {
	return len(str) - CountEscapeCharacters(str)
}

// GetUnescapedColonIndex searches a string for the first unescaped colon and returns the index of that colon
// @param str string to search
// @return index of first unescaped colon, or 0 if not found
func GetUnescapedColonIndex(str string) (idx int) {
	for i, s := range str {
		if s == ':' {
			if i == 0 || str[i-1] != '\\' {
				idx = i
				break
			}
		}
	}
	return idx
}

// IsAlphanum returns true if the string contains only
// alphanumeric characters or the underscore character,
// false otherwise.
// @param c the string in question
// @return true if c is alphanumeric or underscore, false if not
func IsAlphanum(s string) bool {
	for _, r := range s {
		if !IsAlpha(r) && !unicode.IsDigit(r) && r != '_' {
			return false
		}
	}
	return true
}

// IsAlpha returns true if the rune contains only 'a'..'z' and 'A'..'Z'.
func IsAlpha(r rune) bool {
	if (r < 'a' || r > 'z') && (r < 'A' || r > 'Z') {
		return false
	}
	return true
}

// ValidateURI is not part of the reference implementation pseudo code
// found in the CPE 2.3 specification.  It enforces two rules in the
// specification:
//   URI must start with the characters "cpe:/"
//   A URI may not contain more than 7 components
// If either rule is violated, a ParseErr is thrown.
func ValidateURI(in string) error {
	in = strings.ToLower(in)
	// make sure uri starts with cpe:/
	if !strings.HasPrefix(in, "cpe:/") {
		return errors.Wrapf(ErrParse, "Error: URI must start with 'cpe:/'.  Given: %s", in)
	}
	// make sure uri doesn't contain more than 7 colons
	if count := strings.Count(in, ":"); count > 7 {
		return errors.Wrapf(ErrParse, "Error parsing URI.  Found %d extra components in: %s", count-7, in)
	}
	return nil
}

// ValidateFS is not part of the reference implementation pseudo code
// found in the CPE 2.3 specification.  It enforces three rules found in the
// specification:
//    Formatted string must start with the characters "cpe:2.3:"
//    A formatted string must contain 11 components
//    A formatted string must not contain empty components
// If any rule is violated, a ParseException is thrown.
func ValidateFS(in string) error {
	in = strings.ToLower(in)
	if !strings.HasPrefix(in, "cpe:2.3:") {
		return errors.Wrapf(ErrParse, "Error: Formatted String must start with \"cpe:2.3\". Given: %s", in)
	}
	// make sure fs contains exactly 12 unquoted colons
	count := 0
	for i := 0; i != len(in); i++ {
		if in[i] == ':' {
			if i == 0 || in[i-1] != '\\' {
				count++
			} else {
				continue
			}
			if i < len(in)-1 && in[i+1] == ':' {
				return errors.Wrap(ErrParse, "Error parsing formatted string. Found empty component")
			}
		}
	}
	if count > 12 {
		extra := count - 12
		return errors.Wrapf(ErrParse, "Error parsing formatted string. Found %d components in: %s", extra, in)
	}
	if count < 12 {
		missing := 12 - count
		return errors.Wrapf(ErrParse, "Error parsing formatted string. Missing %d components in: %s", missing, in)
	}
	return nil
}