wpscan 3.0.8 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|