puppet-sec-lint 0.1.2 → 0.5.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/main.yml +4 -2
- data/.idea/puppet-sec-lint.iml +7 -4
- data/Gemfile +3 -1
- data/Gemfile.lock +14 -1
- data/README.md +36 -17
- data/_config.yml +1 -0
- data/docs/404.html +24 -0
- data/docs/Gemfile +30 -0
- data/docs/Gemfile.lock +275 -0
- data/docs/_config.yml +41 -0
- data/docs/_posts/2021-05-03-welcome-to-jekyll.markdown +25 -0
- data/docs/_site/404.html +71 -0
- data/docs/_site/feed.xml +13 -0
- data/docs/_site/index.html +1 -0
- data/docs/_site/jekyll/update/2021/05/03/welcome-to-jekyll.html +77 -0
- data/docs/hard-coded-credentials.md +17 -0
- data/docs/images/puppet-sec-lint_console.png +0 -0
- data/docs/images/puppet-sec-lint_vscode.png +0 -0
- data/docs/index.md +6 -0
- data/exe/puppet-sec-lint +81 -15
- data/file.pp +77 -0
- data/lib/configurations/configuration.rb +2 -1
- data/lib/configurations/regex_configuration.rb +9 -0
- data/lib/facades/configuration_file_facade.rb +3 -1
- data/lib/facades/configuration_page_facade.rb +6 -0
- data/lib/lol.pp +6 -6
- data/lib/puppet-sec-lint/version.rb +3 -1
- data/lib/rule_engine.rb +15 -3
- data/lib/rules/admin_by_default_rule.rb +33 -0
- data/lib/rules/cyrillic_homograph_attack.rb +27 -0
- data/lib/rules/empty_password_rule.rb +35 -0
- data/lib/rules/hard_coded_credentials_rule.rb +22 -31
- data/lib/rules/invalid_ip_addr_binding_rule.rb +37 -0
- data/lib/rules/no_http_rule.rb +26 -9
- data/lib/rules/rule.rb +72 -0
- data/lib/rules/suspicious_comment_rule.rb +28 -0
- data/lib/rules/use_weak_crypto_algorithms_rule.rb +28 -0
- data/lib/servers/language_server.rb +101 -0
- data/lib/servers/linter_server.rb +52 -0
- data/lib/settings.ini +39 -0
- data/lib/{sin.rb → sin/sin.rb} +6 -1
- data/lib/sin/sin_type.rb +44 -0
- data/lib/test.txt +15 -0
- data/lib/test2.rb +16 -0
- data/lib/test3.rb +32 -0
- data/lib/test_new.rb +19 -0
- data/puppet-sec-lint-0.5.3.gem +0 -0
- data/puppet-sec-lint.gemspec +7 -1
- metadata +139 -6
- data/lib/language_server.rb +0 -78
- data/lib/sin_type.rb +0 -12
@@ -13,7 +13,7 @@ class ConfigurationFileFacade
|
|
13
13
|
when DisplayField[:SelectBox]
|
14
14
|
ini[rule][configuration.id] = configuration.value.join(',')
|
15
15
|
else
|
16
|
-
ini[rule][configuration.id] = configuration.value
|
16
|
+
ini[rule][configuration.id] = configuration.value.to_s
|
17
17
|
end
|
18
18
|
end
|
19
19
|
end
|
@@ -32,6 +32,8 @@ class ConfigurationFileFacade
|
|
32
32
|
case configuration.displayfield
|
33
33
|
when DisplayField[:SelectBox]
|
34
34
|
configuration.value = ini[rule][configuration.id].split(',')
|
35
|
+
when DisplayField[:RegexBox]
|
36
|
+
configuration.value = Regexp.new ini[rule][configuration.id]
|
35
37
|
else
|
36
38
|
configuration.value = ini[rule][configuration.id]
|
37
39
|
end
|
@@ -50,6 +50,8 @@ class ConfigurationPageFacade
|
|
50
50
|
return_value+="#{option}\n"
|
51
51
|
end
|
52
52
|
return_value += "</textarea>"
|
53
|
+
when DisplayField[:TextBox], DisplayField[:RegexBox]
|
54
|
+
return_value += "<input type=\"text\" id=\"#{configuration.id}\" name=\"#{configuration.id}\" value=\"#{configuration.value.to_s}\" size=\"#{configuration.value.to_s.length()}\"><br>\n"
|
53
55
|
end
|
54
56
|
|
55
57
|
return_value += "<p style=\"color:gray\">#{configuration.description}</p>\n<br>\n"
|
@@ -71,6 +73,10 @@ class ConfigurationPageFacade
|
|
71
73
|
|
72
74
|
when DisplayField[:SelectBox]
|
73
75
|
configuration.value = new_conf[configuration.id].split(/\r?\n/).delete_if(&:empty?)
|
76
|
+
|
77
|
+
when DisplayField[:RegexBox]
|
78
|
+
configuration.value = Regexp.new new_conf[configuration.id]
|
79
|
+
|
74
80
|
else
|
75
81
|
configuration.value = new_conf[configuration.id]
|
76
82
|
end
|
data/lib/lol.pp
CHANGED
@@ -8,17 +8,17 @@
|
|
8
8
|
# the following code addresses the bug: https://bugs.launchpad.net/keystone/+bug/1472285 .
|
9
9
|
|
10
10
|
class consul_template::service (
|
11
|
-
$
|
12
|
-
$
|
13
|
-
$
|
14
|
-
$
|
11
|
+
$pass = lols(3),
|
12
|
+
$aijoijooiumihhn_password = 'pe-puppet'
|
13
|
+
$admin = 'ceisssesrelometer',
|
14
|
+
$aijoijooiumihhn_password = '(adiyu(guygmin',
|
15
15
|
) {
|
16
16
|
exec { 'network-restart':
|
17
17
|
command => 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDM release-runner key',
|
18
18
|
path => '/usr/bin:/usr/sbin:/bin:/sbin',
|
19
19
|
refreshonly => true,
|
20
20
|
vmware_md5 => 'LOL',
|
21
|
-
autho => '
|
21
|
+
autho => 'MDi09i09i5',
|
22
22
|
cmd => 'virsh secret-define --file ${secret_xml} && virsh secret-set-value --secret ${rbd_secret_uuid} --base64 $(ceph auth get-key client.${user})',
|
23
23
|
$auth_uri => 'http://127.0.0.1:5000',
|
24
24
|
'bind_address' => '0.0.0.0',
|
@@ -80,4 +80,4 @@ UcXHbA==
|
|
80
80
|
replace => true,
|
81
81
|
require => File['/var/lib/gerrit/.ssh']
|
82
82
|
}
|
83
|
-
}
|
83
|
+
}
|
data/lib/rule_engine.rb
CHANGED
@@ -2,18 +2,30 @@ require 'puppet-lint'
|
|
2
2
|
require_relative 'rules/rule'
|
3
3
|
require_relative 'rules/hard_coded_credentials_rule'
|
4
4
|
require_relative 'rules/no_http_rule'
|
5
|
+
require_relative 'rules/admin_by_default_rule'
|
6
|
+
require_relative 'rules/empty_password_rule'
|
7
|
+
require_relative 'rules/invalid_ip_addr_binding_rule'
|
8
|
+
require_relative 'rules/suspicious_comment_rule'
|
9
|
+
require_relative 'rules/use_weak_crypto_algorithms_rule'
|
10
|
+
require_relative 'rules/cyrillic_homograph_attack'
|
5
11
|
|
6
12
|
|
7
13
|
class RuleEngine
|
8
|
-
@rules=[HardCodedCredentialsRule,NoHTTPRule]
|
14
|
+
@rules=[HardCodedCredentialsRule,NoHTTPRule,AdminByDefaultRule,EmptyPasswordRule,InvalidIPAddrBindingRule,UseWeakCryptoAlgorithmsRule,SuspiciousCommentRule,CyrillicHomographAttack]
|
9
15
|
|
10
16
|
class << self
|
11
17
|
attr_accessor :rules
|
12
18
|
end
|
13
19
|
|
14
20
|
def self.getTokens(code)
|
15
|
-
|
16
|
-
|
21
|
+
begin
|
22
|
+
lexer = PuppetLint::Lexer.new
|
23
|
+
tokens = lexer.tokenise(code)
|
24
|
+
rescue
|
25
|
+
puts "Error in getting tokens from Puppet-Lint"
|
26
|
+
tokens = []
|
27
|
+
end
|
28
|
+
|
17
29
|
return tokens
|
18
30
|
end
|
19
31
|
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require_relative '../configurations/list_configuration'
|
2
|
+
|
3
|
+
class AdminByDefaultRule < Rule
|
4
|
+
@name = "Admin by default"
|
5
|
+
|
6
|
+
@credentials = /user|usr|pass(word|_|$)|pwd/
|
7
|
+
|
8
|
+
@credentials_conf = RegexConfiguration.new("Regular expression of words present in credentials", @credentials, "Regular expression of words that if present indicate the existence of a secret.")
|
9
|
+
|
10
|
+
@configurations+=[@credentials_conf]
|
11
|
+
|
12
|
+
def self.AnalyzeTokens(tokens)
|
13
|
+
result = []
|
14
|
+
|
15
|
+
ftokens = self.get_tokens(tokens,'admin')
|
16
|
+
ftokens.each do |token|
|
17
|
+
token_value = token.value.downcase
|
18
|
+
token_type = token.type.to_s
|
19
|
+
if ["EQUALS", "FARROW"].include? token.prev_code_token.type.to_s
|
20
|
+
prev_token = token.prev_code_token
|
21
|
+
left_side = prev_token.prev_code_token
|
22
|
+
if left_side.value.downcase =~ @credentials_conf.value and ["VARIABLE", "NAME"].include? left_side.type.to_s
|
23
|
+
if token_value == 'admin'
|
24
|
+
result.append(Sin.new(SinType::AdminByDefault, left_side.line, left_side.column, token.line, token.column+token_value.length))
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
return result
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require_relative '../configurations/list_configuration'
|
2
|
+
|
3
|
+
class CyrillicHomographAttack < Rule
|
4
|
+
@name = "Cyrillic Homograph attack"
|
5
|
+
|
6
|
+
@site_w_cyrillic = /^(http(s)?:\/\/)?.*\p{Cyrillic}+/
|
7
|
+
|
8
|
+
@site_w_cyrillic_conf = RegexConfiguration.new("Regular expression of links with Cyrillic characters", @site_w_cyrillic, "Regular expression of website links that have Cyrillic characters.")
|
9
|
+
|
10
|
+
@configurations+=[@site_w_cyrillic_conf]
|
11
|
+
|
12
|
+
def self.AnalyzeTokens(tokens)
|
13
|
+
result = []
|
14
|
+
|
15
|
+
ftokens = self.filter_tokens(tokens)
|
16
|
+
tokens.each do |token|
|
17
|
+
token_value = token.value.downcase
|
18
|
+
token_type = token.type.to_s
|
19
|
+
if ["STRING", "SSTRING"].include? token_type and token_value =~ @site_w_cyrillic_conf.value
|
20
|
+
result.append(Sin.new(SinType::CyrillicHomographAttack, token.line, token.column, token.line, token.column+token_value.length))
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
return result
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require_relative '../configurations/list_configuration'
|
2
|
+
|
3
|
+
class EmptyPasswordRule < Rule
|
4
|
+
@default_trigger_words = %w[pwd password pass]
|
5
|
+
@password = /pass(word|_|$)|pwd/
|
6
|
+
|
7
|
+
@trigger_words_conf = ListConfiguration.new("List of trigger words", @default_trigger_words, "List of words that identify a password variable")
|
8
|
+
@password_conf = RegexConfiguration.new("Regular expression of password name", @password, "Regular expression of names used for password variables.")
|
9
|
+
|
10
|
+
@configurations+=[@trigger_words_conf, @password_conf]
|
11
|
+
|
12
|
+
@name = "Check empty password"
|
13
|
+
|
14
|
+
def self.AnalyzeTokens(tokens)
|
15
|
+
result = []
|
16
|
+
|
17
|
+
ftokens = self.get_string_tokens(tokens,'')
|
18
|
+
ftokens.each do |token|
|
19
|
+
token_value = token.value.downcase
|
20
|
+
token_type = token.type.to_s
|
21
|
+
if ["EQUALS", "FARROW"].include? token.prev_code_token.type.to_s
|
22
|
+
prev_token = token.prev_code_token
|
23
|
+
left_side = prev_token.prev_code_token
|
24
|
+
if left_side.value.downcase =~ @password_conf.value and ["VARIABLE", "NAME"].include? left_side.type.to_s
|
25
|
+
if token_value == ''
|
26
|
+
result.append(Sin.new(SinType::EmptyPassword, prev_token.line, prev_token.column, token.line, token.column+token_value.length))
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
return result
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -1,40 +1,34 @@
|
|
1
1
|
require_relative '../configurations/list_configuration'
|
2
|
+
require_relative '../configurations/regex_configuration'
|
2
3
|
|
3
4
|
class HardCodedCredentialsRule < Rule
|
4
|
-
@
|
5
|
-
@
|
6
|
-
@
|
5
|
+
@not_considered_creds = %w[pe-puppet pe-webserver pe-puppetdb pe-postgres pe-console-services pe-orchestration-services pe-ace-server pe-bolt-server]
|
6
|
+
@invalid_values = %w[undefined unset www-data wwwrun www no yes [] root]
|
7
|
+
@secrets = /user|usr|pass(word|_|$)|pwd|key|secret/
|
8
|
+
@non_secrets = /gpg|path|type|buff|zone|mode|tag|header|scheme|length|guid/
|
9
|
+
|
10
|
+
@not_considered_creds_conf = ListConfiguration.new("List of known words not considered in credentials", @not_considered_creds, "List of words not considered secrets by the community (https://puppet.com/docs/pe/2019.8/what_gets_installed_and_where.html#user_and_group_accounts_installed)")
|
11
|
+
@invalid_values_conf = ListConfiguration.new("List of invalid values in credentials", @invalid_values, "List of words that are not valid in a credential, advised by puppet specialists.")
|
12
|
+
@secrets_conf = RegexConfiguration.new("Regular expression of words present in credentials", @secrets, "Regular expression of words that if present indicate the existence of a secret.")
|
13
|
+
@non_secrets_conf = RegexConfiguration.new("Regular expression of words not present in credentials", @non_secrets, "Regular expression of words that if present discard the existence of a secret.")
|
7
14
|
|
8
15
|
@name = "Hard Coded Credentials"
|
9
|
-
@configurations+=[@
|
16
|
+
@configurations+=[@not_considered_creds_conf, @invalid_values_conf, @secrets_conf, @non_secrets_conf]
|
10
17
|
|
11
18
|
def self.AnalyzeTokens(tokens)
|
12
19
|
result = []
|
13
20
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
nxt_nxt_line = nxt_nxt_token.line
|
26
|
-
if (token_type.eql? 'NAME') || (token_type.eql? 'VARIABLE')
|
27
|
-
# puts "Token type: #{token_type}"
|
28
|
-
if (token_line==nxt_nxt_line)
|
29
|
-
token_valu = indi_token.value.downcase
|
30
|
-
nxt_nxt_val = nxt_nxt_token.value.downcase
|
31
|
-
nxt_nxt_type = nxt_nxt_token.type.to_s ## to handle false positives,
|
32
|
-
|
33
|
-
if (self.TriggerWordInString(token_valu)) && ((nxt_nxt_val.length > 0)) && ((!nxt_nxt_type.eql? 'VARIABLE') && (!token_valu.include? "("))
|
34
|
-
result.append(Sin.new(SinType::HardCodedCred, indi_token.line, indi_token.column, nxt_nxt_token.line, nxt_nxt_token.column+nxt_nxt_token.value.length))
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
21
|
+
ftokens = self.filter_tokens(tokens)
|
22
|
+
ftokens.each do |token|
|
23
|
+
token_value = token.value.downcase
|
24
|
+
token_type = token.type.to_s
|
25
|
+
next_token = token.next_code_token
|
26
|
+
# accepts <VARIABLE> <EQUALS> secret OR <NAME> <FARROW> secret, checks if <VARIABLE> | <NAME> satisfy SECRETS but not satisfy NON_SECRETS
|
27
|
+
if ["VARIABLE", "NAME"].include? token_type and ["EQUALS", "FARROW"].include? next_token.type.to_s and token_value =~ @secrets_conf.value and !(token_value =~ @non_secrets_conf.value)
|
28
|
+
right_side_type = next_token.next_code_token.type.to_s
|
29
|
+
right_side_value = next_token.next_code_token.value.downcase
|
30
|
+
if ["STRING", "SSTRING"].include? right_side_type and right_side_value.length > 1 and !@invalid_values_conf.value.include? right_side_value and !(right_side_value =~ /::|\/|\.|\\/ ) and !@not_considered_creds_conf.value.include? right_side_value
|
31
|
+
result.append(Sin.new(SinType::HardCodedCred, token.line, token.column, next_token.next_code_token.line, next_token.next_code_token.column+right_side_value.length))
|
38
32
|
end
|
39
33
|
end
|
40
34
|
end
|
@@ -42,7 +36,4 @@ class HardCodedCredentialsRule < Rule
|
|
42
36
|
return result
|
43
37
|
end
|
44
38
|
|
45
|
-
def self.TriggerWordInString(string)
|
46
|
-
return @trigger_words_conf.value.any? { |word| string.include?(word) }
|
47
|
-
end
|
48
39
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require_relative '../configurations/list_configuration'
|
2
|
+
|
3
|
+
class InvalidIPAddrBindingRule < Rule
|
4
|
+
@name = "Invalid IP Address Binding"
|
5
|
+
|
6
|
+
@ip_addr_bin_regex = /^((http(s)?:\/\/)?0.0.0.0(:\d{1,5})?)$/
|
7
|
+
|
8
|
+
@ip_addr_bin_regex_conf = RegexConfiguration.new("Regular expression of an invalid IP address", @ip_addr_bin_regex, "Regular expression of an IP address considered invalid or insecure to use.")
|
9
|
+
|
10
|
+
@configurations+=[@ip_addr_bin_regex_conf]
|
11
|
+
|
12
|
+
def self.AnalyzeTokens(tokens)
|
13
|
+
result = []
|
14
|
+
|
15
|
+
ftokens = get_tokens(tokens,"0.0.0.0")
|
16
|
+
ftokens.each do |token|
|
17
|
+
token_value = token.value.downcase
|
18
|
+
token_type = token.type.to_s
|
19
|
+
if ["EQUALS", "FARROW"].include? token.prev_code_token.type.to_s
|
20
|
+
prev_token = token.prev_code_token
|
21
|
+
left_side = prev_token.prev_code_token
|
22
|
+
if token_value =~ @ip_addr_bin_regex_conf.value and ["VARIABLE", "NAME"].include? left_side.type.to_s
|
23
|
+
result.append(Sin.new(SinType::InvalidIPAddrBinding, left_side.line, left_side.column, token.line, token.column+token_value.length))
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
return result
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.filter_tokens_per_value(tokens, token)
|
32
|
+
ftokens=tokens.find_all do |hash|
|
33
|
+
(hash.type.to_s == 'SSTRING' || hash.type.to_s == 'STRING') and hash.value.downcase.include? token
|
34
|
+
end
|
35
|
+
return ftokens
|
36
|
+
end
|
37
|
+
end
|
data/lib/rules/no_http_rule.rb
CHANGED
@@ -1,19 +1,36 @@
|
|
1
1
|
require_relative '../configurations/list_configuration'
|
2
|
-
require_relative '../sin'
|
3
|
-
require_relative '../sin_type'
|
2
|
+
require_relative '../sin/sin'
|
3
|
+
require_relative '../sin/sin_type'
|
4
4
|
|
5
5
|
class NoHTTPRule < Rule
|
6
|
-
@name="No
|
6
|
+
@name="No HTTPS Connections"
|
7
|
+
|
8
|
+
@resources = %w[apt::source ::apt::source wget::fetch yumrepo yum:: aptly::mirror util::system_package yum::managed_yumrepo]
|
9
|
+
@keywords = %w[backport key download uri mirror]
|
10
|
+
@http = /^http:\/\/.+/
|
11
|
+
@whitelist = [] # Todo:Need to check how is this set up
|
12
|
+
|
13
|
+
@resources_conf = ListConfiguration.new("List of resources that can use HTTP", @resources, "List of resources that are known to not use HTTPS but that validate the transferred content with other secure methods.")
|
14
|
+
@keywords_conf = ListConfiguration.new("List of keywords for URLs", @keywords, "List of keywords that identify hyperlinks that should be analyzed.")
|
15
|
+
@http_conf = RegexConfiguration.new("Regular expression of a normal HTTP address", @http, "Regular expression that identifies the URL of a website using the regular non-secure HTTP protocol.")
|
16
|
+
|
17
|
+
@configurations+=[@resources_conf, @keywords_conf, @http_conf]
|
7
18
|
|
8
19
|
def self.AnalyzeTokens(tokens)
|
9
20
|
result = []
|
10
21
|
|
11
|
-
tokens.
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
22
|
+
ptokens = self.filter_resources(tokens, @resources_conf.value)
|
23
|
+
ctokens = self.filter_variables(ptokens, @keywords_conf.value)
|
24
|
+
if @whitelist
|
25
|
+
wtokens = self.filter_whitelist(ctokens)
|
26
|
+
else
|
27
|
+
wtokens = ptokens
|
28
|
+
end
|
29
|
+
wtokens.each do |token|
|
30
|
+
token_value = token.value.downcase
|
31
|
+
token_type = token.type.to_s
|
32
|
+
if (token_value =~ @http_conf.value)
|
33
|
+
result.append(Sin.new(SinType::HttpWithoutTLS, token.line, token.column, token.line, token.column+token_value.length))
|
17
34
|
end
|
18
35
|
end
|
19
36
|
|
data/lib/rules/rule.rb
CHANGED
@@ -14,4 +14,76 @@ class Rule
|
|
14
14
|
puts "Implement this"
|
15
15
|
return
|
16
16
|
end
|
17
|
+
|
18
|
+
def self.get_tokens(tokens, token)
|
19
|
+
ftokens=tokens.find_all do |hash|
|
20
|
+
(hash.type.to_s == 'NAME' || hash.type.to_s == 'VARIABLE' || hash.type.to_s == 'SSTRING' || hash.type.to_s == 'STRING') and hash.value.downcase.include? token
|
21
|
+
end
|
22
|
+
return ftokens
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.filter_tokens(tokens)
|
26
|
+
ftokens=tokens.find_all do |hash|
|
27
|
+
(hash.type.to_s == 'SSTRING' || hash.type.to_s == 'STRING' || hash.type.to_s == 'VARIABLE' || hash.type.to_s == 'NAME')
|
28
|
+
end
|
29
|
+
return ftokens
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.filter_resources(tokens, resources)
|
33
|
+
is_resource = false
|
34
|
+
brackets = 0
|
35
|
+
ftokens=tokens.find_all do |hash|
|
36
|
+
|
37
|
+
if resources.include? hash.value.downcase
|
38
|
+
is_resource = true
|
39
|
+
elsif is_resource and hash.type.to_s == "LBRACE"
|
40
|
+
brackets += 1
|
41
|
+
elsif is_resource and hash.type.to_s == "RBRACE"
|
42
|
+
brackets -=1
|
43
|
+
end
|
44
|
+
|
45
|
+
if is_resource and hash.type.to_s == "RBRACE" and brackets == 0
|
46
|
+
is_resource = false
|
47
|
+
end
|
48
|
+
|
49
|
+
if !is_resource
|
50
|
+
(hash.type.to_s == 'NAME' || hash.type.to_s == 'VARIABLE' || hash.type.to_s == 'SSTRING' || hash.type.to_s == 'STRING')
|
51
|
+
end
|
52
|
+
end
|
53
|
+
return ftokens
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.get_string_tokens(tokens, token)
|
57
|
+
ftokens=tokens.find_all do |hash|
|
58
|
+
(hash.type.to_s == 'SSTRING' || hash.type.to_s == 'STRING') and hash.value.downcase.include? token
|
59
|
+
end
|
60
|
+
return ftokens
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.get_comments(tokens)
|
64
|
+
ftokens=tokens.find_all do |hash|
|
65
|
+
(hash.type.to_s == 'COMMENT' || hash.type.to_s == 'MLCOMMENT' || hash.type.to_s == 'SLASH_COMMENT')
|
66
|
+
end
|
67
|
+
return ftokens
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.filter_whitelist(tokens)
|
71
|
+
ftokens=tokens.find_all do |hash|
|
72
|
+
#!(@whitelist =~ hash.value.downcase)
|
73
|
+
true # TODO: Understand the whitelist
|
74
|
+
end
|
75
|
+
return ftokens
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.filter_variables(tokens, keywords)
|
79
|
+
line = -1
|
80
|
+
kw_regex = Regexp.new keywords.join("|")
|
81
|
+
ftokens=tokens.find_all do |hash|
|
82
|
+
if (hash.type.to_s == 'VARIABLE' || hash.type.to_s == 'NAME') and hash.value.downcase =~ kw_regex
|
83
|
+
line = hash.line
|
84
|
+
elsif hash.line != line
|
85
|
+
hash
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
17
89
|
end
|