wpscan 3.0.8 → 3.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE +1 -1
- data/README.md +1 -1
- data/app/controllers.rb +1 -0
- data/app/controllers/aliases.rb +12 -0
- data/app/controllers/core.rb +3 -5
- data/app/controllers/enumeration.rb +2 -28
- data/app/controllers/enumeration/enum_methods.rb +12 -2
- data/app/controllers/wp_version.rb +4 -0
- data/app/finders/main_theme/css_style.rb +2 -2
- data/app/finders/main_theme/urls_in_homepage.rb +3 -3
- data/app/finders/plugin_version.rb +1 -8
- data/app/finders/plugins.rb +13 -4
- data/app/finders/plugins/body_pattern.rb +27 -0
- data/app/finders/plugins/comment.rb +31 -0
- data/app/finders/plugins/config_parser.rb +31 -0
- data/app/finders/plugins/header_pattern.rb +41 -0
- data/app/finders/plugins/javascript_var.rb +29 -0
- data/app/finders/plugins/known_locations.rb +5 -5
- data/app/finders/plugins/query_parameter.rb +25 -0
- data/app/finders/plugins/urls_in_homepage.rb +4 -8
- data/app/finders/plugins/xpath.rb +29 -0
- data/app/finders/theme_version.rb +1 -1
- data/app/finders/theme_version/woo_framework_meta_generator.rb +2 -2
- data/app/finders/themes/known_locations.rb +5 -5
- data/app/finders/themes/urls_in_homepage.rb +2 -2
- data/app/finders/users/login_error_messages.rb +1 -4
- data/app/finders/users/wp_json_api.rb +2 -2
- data/app/finders/wp_items/urls_in_homepage.rb +1 -1
- data/app/finders/wp_version.rb +21 -18
- data/app/models/plugin.rb +4 -4
- data/app/models/theme.rb +6 -6
- data/app/models/timthumb.rb +1 -3
- data/app/models/wp_item.rb +15 -15
- data/app/views/json/enumeration/plugins.erb +1 -1
- data/app/views/json/enumeration/themes.erb +1 -1
- data/app/views/json/wp_item.erb +1 -1
- data/bin/wpscan +2 -1
- data/lib/wpscan/db.rb +14 -10
- data/lib/wpscan/db/dynamic_finders/base.rb +41 -0
- data/lib/wpscan/db/dynamic_finders/plugin.rb +111 -0
- data/lib/wpscan/db/dynamic_finders/theme.rb +16 -0
- data/lib/wpscan/db/dynamic_finders/wordpress.rb +75 -0
- data/lib/wpscan/db/updater.rb +2 -2
- data/lib/wpscan/finders.rb +13 -1
- data/lib/wpscan/finders/dynamic_finder/finder.rb +66 -0
- data/lib/wpscan/finders/dynamic_finder/version/body_pattern.rb +28 -0
- data/lib/wpscan/finders/dynamic_finder/version/comment.rb +16 -0
- data/lib/wpscan/finders/dynamic_finder/version/config_parser.rb +52 -0
- data/lib/wpscan/finders/dynamic_finder/version/finder.rb +29 -0
- data/lib/wpscan/finders/dynamic_finder/version/header_pattern.rb +28 -0
- data/lib/wpscan/finders/dynamic_finder/version/javascript_var.rb +56 -0
- data/lib/wpscan/finders/dynamic_finder/version/query_parameter.rb +62 -0
- data/lib/wpscan/finders/dynamic_finder/version/xpath.rb +34 -0
- data/lib/wpscan/finders/dynamic_finder/wp_item_version.rb +42 -0
- data/lib/wpscan/finders/dynamic_finder/wp_items/finder.rb +96 -0
- data/lib/wpscan/finders/dynamic_finder/wp_version.rb +60 -0
- data/lib/wpscan/helper.rb +11 -0
- data/lib/wpscan/target/platform/wordpress/custom_directories.rb +16 -1
- data/lib/wpscan/version.rb +1 -1
- metadata +32 -24
- data/app/finders/plugin_version/layer_slider/translation_file.rb +0 -40
- data/app/finders/plugin_version/revslider/release_log.rb +0 -35
- data/app/finders/plugin_version/shareaholic/meta_tag.rb +0 -27
- data/app/finders/plugin_version/sitepress_multilingual_cms/meta_generator.rb +0 -27
- data/app/finders/plugin_version/sitepress_multilingual_cms/version_parameter.rb +0 -31
- data/app/finders/plugin_version/w3_total_cache/headers.rb +0 -28
- data/app/finders/plugins/comments.rb +0 -31
- data/app/finders/plugins/headers.rb +0 -36
- data/app/finders/wp_version/homepage_stylesheet_numbers.rb +0 -59
- data/app/finders/wp_version/install_stylesheet_numbers.rb +0 -16
- data/app/finders/wp_version/meta_generator.rb +0 -27
- data/app/finders/wp_version/opml_generator.rb +0 -23
- data/app/finders/wp_version/sitemap_generator.rb +0 -23
- data/app/finders/wp_version/upgrade_stylesheet_numbers.rb +0 -13
- data/lib/wpscan/db/dynamic_finders.rb +0 -55
- data/lib/wpscan/finders/finder/plugin_version/comments.rb +0 -27
@@ -2,6 +2,8 @@ module WPScan
|
|
2
2
|
module Finders
|
3
3
|
module Plugins
|
4
4
|
# URLs In Homepage Finder
|
5
|
+
# Typically, the items detected from URLs like
|
6
|
+
# /wp-content/plugins/<slug>/
|
5
7
|
class UrlsInHomepage < CMSScanner::Finders::Finder
|
6
8
|
include WpItems::URLsInHomepage
|
7
9
|
|
@@ -11,14 +13,8 @@ module WPScan
|
|
11
13
|
def passive(opts = {})
|
12
14
|
found = []
|
13
15
|
|
14
|
-
(items_from_links('plugins') + items_from_codes('plugins')).uniq.sort.each do |
|
15
|
-
found << Plugin.new(
|
16
|
-
end
|
17
|
-
|
18
|
-
DB::DynamicPluginFinders.urls_in_page.each do |name, config|
|
19
|
-
next unless target.homepage_res.html.xpath(config['xpath']).any?
|
20
|
-
|
21
|
-
found << Plugin.new(name, target, opts.merge(found_by: found_by, confidence: 100))
|
16
|
+
(items_from_links('plugins') + items_from_codes('plugins')).uniq.sort.each do |slug|
|
17
|
+
found << Plugin.new(slug, target, opts.merge(found_by: found_by, confidence: 80))
|
22
18
|
end
|
23
19
|
|
24
20
|
found
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module WPScan
|
2
|
+
module Finders
|
3
|
+
module Plugins
|
4
|
+
# Plugins finder from the Dynamic Finder 'Xpath'
|
5
|
+
class Xpath < WPScan::Finders::DynamicFinder::WpItems::Finder
|
6
|
+
DEFAULT_CONFIDENCE = 40
|
7
|
+
|
8
|
+
# @param [ Hash ] opts The options from the #passive, #aggressive methods
|
9
|
+
# @param [ Typhoeus::Response ] response
|
10
|
+
# @param [ String ] slug
|
11
|
+
# @param [ String ] klass
|
12
|
+
# @param [ Hash ] config The related dynamic finder config hash
|
13
|
+
#
|
14
|
+
# @return [ Plugin ] The detected plugin in the response, related to the config
|
15
|
+
def process_response(opts, response, slug, klass, config)
|
16
|
+
response.html.xpath(config['xpath']).each do |node|
|
17
|
+
next if config['pattern'] && !node.text.match(config['pattern'])
|
18
|
+
|
19
|
+
return Plugin.new(
|
20
|
+
slug,
|
21
|
+
target,
|
22
|
+
opts.merge(found_by: found_by(klass), confidence: config['confidence'] || DEFAULT_CONFIDENCE)
|
23
|
+
)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -7,9 +7,9 @@ module WPScan
|
|
7
7
|
#
|
8
8
|
# @return [ Version ]
|
9
9
|
def passive(_opts = {})
|
10
|
-
return unless target.
|
10
|
+
return unless target.blog.homepage_res.body =~ Finders::MainTheme::WooFrameworkMetaGenerator::PATTERN
|
11
11
|
|
12
|
-
return unless Regexp.last_match[1] == target.
|
12
|
+
return unless Regexp.last_match[1] == target.slug
|
13
13
|
|
14
14
|
WPScan::Version.new(Regexp.last_match[2], found_by: found_by, confidence: 80)
|
15
15
|
end
|
@@ -12,12 +12,12 @@ module WPScan
|
|
12
12
|
def aggressive(opts = {})
|
13
13
|
found = []
|
14
14
|
|
15
|
-
enumerate(target_urls(opts), opts) do |res,
|
15
|
+
enumerate(target_urls(opts), opts) do |res, slug|
|
16
16
|
# TODO: follow the location (from enumerate()) and remove the 301 here ?
|
17
17
|
# As a result, it might remove false positive due to redirection to the homepage
|
18
18
|
next unless [200, 401, 403, 301].include?(res.code)
|
19
19
|
|
20
|
-
found << WPScan::Theme.new(
|
20
|
+
found << WPScan::Theme.new(slug, target, opts.merge(found_by: found_by, confidence: 80))
|
21
21
|
end
|
22
22
|
|
23
23
|
found
|
@@ -28,12 +28,12 @@ module WPScan
|
|
28
28
|
#
|
29
29
|
# @return [ Hash ]
|
30
30
|
def target_urls(opts = {})
|
31
|
-
|
31
|
+
slugs = opts[:list] || DB::Themes.vulnerable_slugs
|
32
32
|
urls = {}
|
33
33
|
themes_url = target.url('wp-content/themes/')
|
34
34
|
|
35
|
-
|
36
|
-
urls["#{themes_url}#{URI.encode(
|
35
|
+
slugs.each do |slug|
|
36
|
+
urls["#{themes_url}#{URI.encode(slug)}/"] = slug
|
37
37
|
end
|
38
38
|
|
39
39
|
urls
|
@@ -11,8 +11,8 @@ module WPScan
|
|
11
11
|
def passive(opts = {})
|
12
12
|
found = []
|
13
13
|
|
14
|
-
(items_from_links('themes') + items_from_codes('themes')).uniq.sort.each do |
|
15
|
-
found << WPScan::Theme.new(
|
14
|
+
(items_from_links('themes') + items_from_codes('themes')).uniq.sort.each do |slug|
|
15
|
+
found << WPScan::Theme.new(slug, target, opts.merge(found_by: found_by, confidence: 80))
|
16
16
|
end
|
17
17
|
|
18
18
|
found
|
@@ -17,10 +17,7 @@ module WPScan
|
|
17
17
|
found = []
|
18
18
|
|
19
19
|
usernames(opts).each do |username|
|
20
|
-
res
|
21
|
-
|
22
|
-
return found unless res.code == 200
|
23
|
-
|
20
|
+
res = target.do_login(username, SecureRandom.hex[0, 8])
|
24
21
|
error = res.html.css('div#login_error').text.strip
|
25
22
|
|
26
23
|
return found if error.empty? # Protection plugin / error disabled
|
@@ -12,7 +12,7 @@ module WPScan
|
|
12
12
|
def aggressive(_opts = {})
|
13
13
|
found = []
|
14
14
|
|
15
|
-
JSON.parse(Browser.get(api_url).body)
|
15
|
+
JSON.parse(Browser.get(api_url).body)&.each do |user|
|
16
16
|
found << WPScan::User.new(user['slug'],
|
17
17
|
id: user['id'],
|
18
18
|
found_by: found_by,
|
@@ -21,7 +21,7 @@ module WPScan
|
|
21
21
|
end
|
22
22
|
|
23
23
|
found
|
24
|
-
rescue JSON::ParserError
|
24
|
+
rescue JSON::ParserError, TypeError
|
25
25
|
found
|
26
26
|
end
|
27
27
|
|
@@ -30,7 +30,7 @@ module WPScan
|
|
30
30
|
code = tag.text.to_s
|
31
31
|
next if code.empty?
|
32
32
|
|
33
|
-
code.scan(item_code_pattern(type)).flatten.uniq.each { |
|
33
|
+
code.scan(item_code_pattern(type)).flatten.uniq.each { |slug| found << slug }
|
34
34
|
end
|
35
35
|
|
36
36
|
uniq ? found.uniq.sort : found.sort
|
data/app/finders/wp_version.rb
CHANGED
@@ -1,17 +1,23 @@
|
|
1
|
-
require_relative 'wp_version/meta_generator'
|
2
1
|
require_relative 'wp_version/rss_generator'
|
3
2
|
require_relative 'wp_version/atom_generator'
|
4
3
|
require_relative 'wp_version/rdf_generator'
|
5
4
|
require_relative 'wp_version/readme'
|
6
|
-
require_relative 'wp_version/sitemap_generator'
|
7
|
-
require_relative 'wp_version/opml_generator'
|
8
|
-
require_relative 'wp_version/homepage_stylesheet_numbers'
|
9
|
-
require_relative 'wp_version/install_stylesheet_numbers'
|
10
|
-
require_relative 'wp_version/upgrade_stylesheet_numbers'
|
11
5
|
require_relative 'wp_version/unique_fingerprinting'
|
12
6
|
|
13
7
|
module WPScan
|
14
8
|
module Finders
|
9
|
+
# Specific Finders container to filter the version detected
|
10
|
+
# and remove the one with low confidence to avoid false
|
11
|
+
# positive when there is not enought information to accurately
|
12
|
+
# determine it.
|
13
|
+
class WpVersionFinders < UniqueFinders
|
14
|
+
def filter_findings
|
15
|
+
best_finding = super
|
16
|
+
|
17
|
+
best_finding && best_finding.confidence >= 40 ? best_finding : false
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
15
21
|
module WpVersion
|
16
22
|
# Wp Version Finder
|
17
23
|
class Base
|
@@ -19,18 +25,15 @@ module WPScan
|
|
19
25
|
|
20
26
|
# @param [ WPScan::Target ] target
|
21
27
|
def initialize(target)
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
WpVersion
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
WpVersion::SitemapGenerator.new(target) <<
|
32
|
-
WpVersion::OpmlGenerator.new(target) <<
|
33
|
-
WpVersion::UniqueFingerprinting.new(target)
|
28
|
+
(WPScan::DB::DynamicFinders::Wordpress.versions_finders_configs.keys +
|
29
|
+
%w[RSSGenerator AtomGenerator RDFGenerator Readme UniqueFingerprinting]
|
30
|
+
).each do |finder_name|
|
31
|
+
finders << WpVersion.const_get(finder_name.to_sym).new(target)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def finders
|
36
|
+
@finders ||= Finders::WpVersionFinders.new
|
34
37
|
end
|
35
38
|
end
|
36
39
|
end
|
data/app/models/plugin.rb
CHANGED
@@ -2,15 +2,15 @@ module WPScan
|
|
2
2
|
# WordPress Plugin
|
3
3
|
class Plugin < WpItem
|
4
4
|
# See WpItem
|
5
|
-
def initialize(
|
6
|
-
super(
|
5
|
+
def initialize(slug, blog, opts = {})
|
6
|
+
super(slug, blog, opts)
|
7
7
|
|
8
|
-
@uri = Addressable::URI.parse(
|
8
|
+
@uri = Addressable::URI.parse(blog.url("wp-content/plugins/#{slug}/"))
|
9
9
|
end
|
10
10
|
|
11
11
|
# @return [ JSON ]
|
12
12
|
def db_data
|
13
|
-
DB::Plugin.db_data(
|
13
|
+
DB::Plugin.db_data(slug)
|
14
14
|
end
|
15
15
|
|
16
16
|
# @param [ Hash ] opts
|
data/app/models/theme.rb
CHANGED
@@ -5,10 +5,10 @@ module WPScan
|
|
5
5
|
:license, :license_uri, :tags, :text_domain
|
6
6
|
|
7
7
|
# See WpItem
|
8
|
-
def initialize(
|
9
|
-
super(
|
8
|
+
def initialize(slug, blog, opts = {})
|
9
|
+
super(slug, blog, opts)
|
10
10
|
|
11
|
-
@uri = Addressable::URI.parse(
|
11
|
+
@uri = Addressable::URI.parse(blog.url("wp-content/themes/#{slug}/"))
|
12
12
|
@style_url = opts[:style_url] || url('style.css')
|
13
13
|
|
14
14
|
parse_style
|
@@ -16,7 +16,7 @@ module WPScan
|
|
16
16
|
|
17
17
|
# @return [ JSON ]
|
18
18
|
def db_data
|
19
|
-
DB::Theme.db_data(
|
19
|
+
DB::Theme.db_data(slug)
|
20
20
|
end
|
21
21
|
|
22
22
|
# @param [ Hash ] opts
|
@@ -39,7 +39,7 @@ module WPScan
|
|
39
39
|
confidence: 100
|
40
40
|
).merge(version_detection: version_detection_opts)
|
41
41
|
|
42
|
-
self.class.new(template,
|
42
|
+
self.class.new(template, blog, opts)
|
43
43
|
end
|
44
44
|
|
45
45
|
# @param [ Integer ] depth
|
@@ -89,7 +89,7 @@ module WPScan
|
|
89
89
|
def parse_style_tag(body, tag)
|
90
90
|
value = body[/^\s*#{Regexp.escape(tag)}:[\t ]*([^\r\n]+)/i, 1]
|
91
91
|
|
92
|
-
value && !value.strip.empty? ? value.strip : nil
|
92
|
+
value && !value.strip.empty? ? value.strip : nil
|
93
93
|
end
|
94
94
|
|
95
95
|
def ==(other)
|
data/app/models/timthumb.rb
CHANGED
@@ -18,9 +18,7 @@ module WPScan
|
|
18
18
|
#
|
19
19
|
# @return [ WPScan::Version, false ]
|
20
20
|
def version(opts = {})
|
21
|
-
if @version.nil?
|
22
|
-
@version = Finders::TimthumbVersion::Base.find(self, version_detection_opts.merge(opts))
|
23
|
-
end
|
21
|
+
@version = Finders::TimthumbVersion::Base.find(self, version_detection_opts.merge(opts)) if @version.nil?
|
24
22
|
|
25
23
|
@version
|
26
24
|
end
|
data/app/models/wp_item.rb
CHANGED
@@ -9,20 +9,22 @@ module WPScan
|
|
9
9
|
READMES = %w[readme.txt README.txt README.md readme.md Readme.txt].freeze
|
10
10
|
CHANGELOGS = %w[changelog.txt CHANGELOG.md changelog.md].freeze
|
11
11
|
|
12
|
-
attr_reader :uri, :
|
12
|
+
attr_reader :uri, :slug, :detection_opts, :version_detection_opts, :blog, :db_data
|
13
13
|
|
14
|
-
|
15
|
-
|
14
|
+
delegate :homepage_res, :xpath_pattern_from_page, :in_scope_urls, to: :blog
|
15
|
+
|
16
|
+
# @param [ String ] slug The plugin/theme slug
|
17
|
+
# @param [ Target ] blog The targeted blog
|
16
18
|
# @param [ Hash ] opts
|
17
19
|
# @option opts [ Symbol ] :mode The detection mode to use
|
18
20
|
# @option opts [ Hash ] :version_detection The options to use when looking for the version
|
19
21
|
# @option opts [ String ] :url The URL of the item
|
20
|
-
def initialize(
|
21
|
-
@
|
22
|
-
@
|
23
|
-
@uri
|
22
|
+
def initialize(slug, blog, opts = {})
|
23
|
+
@slug = URI.decode(slug)
|
24
|
+
@blog = blog
|
25
|
+
@uri = Addressable::URI.parse(opts[:url]) if opts[:url]
|
24
26
|
|
25
|
-
@detection_opts
|
27
|
+
@detection_opts = { mode: opts[:mode] }
|
26
28
|
@version_detection_opts = opts[:version_detection] || {}
|
27
29
|
|
28
30
|
parse_finding_options(opts)
|
@@ -95,18 +97,16 @@ module WPScan
|
|
95
97
|
|
96
98
|
# @return [ Boolean ]
|
97
99
|
def ==(other)
|
98
|
-
|
99
|
-
|
100
|
-
name == other.name
|
100
|
+
self.class == other.class && slug == other.slug
|
101
101
|
end
|
102
102
|
|
103
103
|
def to_s
|
104
|
-
|
104
|
+
slug
|
105
105
|
end
|
106
106
|
|
107
|
-
# @return [ Symbol ] The Class
|
108
|
-
def
|
109
|
-
|
107
|
+
# @return [ Symbol ] The Class symbol associated to the item
|
108
|
+
def classify
|
109
|
+
@classify ||= classify_slug(slug)
|
110
110
|
end
|
111
111
|
|
112
112
|
# @return [ String ] The readme url if found
|
@@ -2,7 +2,7 @@
|
|
2
2
|
<% unless @plugins.empty? -%>
|
3
3
|
<% last_index = @plugins.size - 1 -%>
|
4
4
|
<% @plugins.each_with_index do |plugin, index| -%>
|
5
|
-
<%= plugin.
|
5
|
+
<%= plugin.slug.to_json %>: {
|
6
6
|
<%= render('@wp_item', wp_item: plugin) %>,
|
7
7
|
<%= render('@finding', item: plugin) -%>,
|
8
8
|
<% if plugin.version -%>
|
@@ -2,7 +2,7 @@
|
|
2
2
|
<% unless @themes.empty? -%>
|
3
3
|
<% last_index = @themes.size - 1 -%>
|
4
4
|
<% @themes.each_with_index do |theme, index| -%>
|
5
|
-
<%= theme.
|
5
|
+
<%= theme.slug.to_json %>: {
|
6
6
|
<%= render('@theme', theme: theme) -%>
|
7
7
|
}<% unless index == last_index -%>,<% end -%>
|
8
8
|
<% end -%>
|
data/app/views/json/wp_item.erb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
"
|
1
|
+
"slug": <%= @wp_item.slug.to_json %>,
|
2
2
|
"location": <%= @wp_item.url.to_json %>,
|
3
3
|
"latest_version": <%= @wp_item.latest_version ? @wp_item.latest_version.number.to_json : nil.to_json %>,
|
4
4
|
"last_updated": <%= @wp_item.last_updated.to_json %>,
|
data/bin/wpscan
CHANGED
@@ -9,7 +9,8 @@ WPScan::Scan.new do |s|
|
|
9
9
|
WPScan::Controller::WpVersion.new <<
|
10
10
|
WPScan::Controller::MainTheme.new <<
|
11
11
|
WPScan::Controller::Enumeration.new <<
|
12
|
-
WPScan::Controller::BruteForce.new
|
12
|
+
WPScan::Controller::BruteForce.new <<
|
13
|
+
WPScan::Controller::Aliases.new
|
13
14
|
|
14
15
|
s.run
|
15
16
|
end
|
data/lib/wpscan/db.rb
CHANGED
@@ -1,10 +1,14 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
1
|
+
require_relative 'db/wp_item'
|
2
|
+
require_relative 'db/updater'
|
3
|
+
require_relative 'db/wp_items'
|
4
|
+
require_relative 'db/plugins'
|
5
|
+
require_relative 'db/themes'
|
6
|
+
require_relative 'db/plugin'
|
7
|
+
require_relative 'db/theme'
|
8
|
+
require_relative 'db/wp_version'
|
9
|
+
require_relative 'db/fingerprints'
|
10
|
+
|
11
|
+
require_relative 'db/dynamic_finders/base'
|
12
|
+
require_relative 'db/dynamic_finders/plugin'
|
13
|
+
require_relative 'db/dynamic_finders/theme'
|
14
|
+
require_relative 'db/dynamic_finders/wordpress'
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module WPScan
|
2
|
+
module DB
|
3
|
+
module DynamicFinders
|
4
|
+
class Base
|
5
|
+
# @return [ String ]
|
6
|
+
def self.db_file
|
7
|
+
@db_file ||= File.join(DB_DIR, 'dynamic_finders.yml')
|
8
|
+
end
|
9
|
+
|
10
|
+
# @return [ Hash ]
|
11
|
+
def self.db_data
|
12
|
+
# true allows aliases to be loaded
|
13
|
+
@db_data ||= YAML.safe_load(File.read(db_file), [Regexp], [], true)
|
14
|
+
end
|
15
|
+
|
16
|
+
# @return [ Array<Symbol> ]
|
17
|
+
def self.allowed_classes
|
18
|
+
@allowed_classes ||= %i[Comment Xpath HeaderPattern BodyPattern JavascriptVar QueryParameter ConfigParser]
|
19
|
+
end
|
20
|
+
|
21
|
+
# @param [ Symbol ] sym
|
22
|
+
def self.method_missing(sym)
|
23
|
+
super unless sym =~ /\A(passive|aggressive)_(.*)_finder_configs\z/i
|
24
|
+
|
25
|
+
finder_class = Regexp.last_match[2].camelize.to_sym
|
26
|
+
|
27
|
+
raise "#{finder_class} is not allowed as a Dynamic Finder" unless allowed_classes.include?(finder_class)
|
28
|
+
|
29
|
+
finder_configs(
|
30
|
+
finder_class,
|
31
|
+
Regexp.last_match[1] == 'aggressive'
|
32
|
+
)
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.respond_to_missing?(sym, *_args)
|
36
|
+
sym =~ /\A(passive|aggressive)_(.*)_finder_configs\z/i
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|