recog 2.3.22 → 3.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (128) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +2 -0
  3. data/LICENSE +1 -1
  4. data/README.md +25 -16
  5. data/Rakefile +2 -9
  6. data/lib/recog/db_manager.rb +1 -1
  7. data/lib/recog/fingerprint.rb +21 -7
  8. data/lib/recog/fingerprint_parse_error.rb +10 -0
  9. data/lib/recog/match_reporter.rb +37 -3
  10. data/lib/recog/matcher.rb +5 -10
  11. data/lib/recog/verifier.rb +4 -4
  12. data/lib/recog/verify_reporter.rb +7 -6
  13. data/lib/recog/version.rb +1 -1
  14. data/{bin → recog/bin}/recog_match +20 -7
  15. data/{xml → recog/xml}/apache_modules.xml +0 -0
  16. data/{xml → recog/xml}/apache_os.xml +61 -19
  17. data/{xml → recog/xml}/architecture.xml +15 -1
  18. data/{xml → recog/xml}/dhcp_vendor_class.xml +10 -10
  19. data/{xml → recog/xml}/dns_versionbind.xml +16 -13
  20. data/{xml → recog/xml}/favicons.xml +167 -9
  21. data/{xml → recog/xml}/fingerprints.xsd +9 -1
  22. data/{xml → recog/xml}/ftp_banners.xml +131 -141
  23. data/{xml → recog/xml}/h323_callresp.xml +2 -2
  24. data/{xml → recog/xml}/hp_pjl_id.xml +81 -81
  25. data/{xml → recog/xml}/html_title.xml +250 -9
  26. data/{xml → recog/xml}/http_cookies.xml +111 -34
  27. data/{xml → recog/xml}/http_servers.xml +483 -270
  28. data/{xml → recog/xml}/http_wwwauth.xml +83 -37
  29. data/{xml → recog/xml}/imap_banners.xml +10 -10
  30. data/{xml → recog/xml}/ldap_searchresult.xml +0 -0
  31. data/{xml → recog/xml}/mdns_device-info_txt.xml +0 -0
  32. data/{xml → recog/xml}/mdns_workstation_txt.xml +0 -0
  33. data/{xml → recog/xml}/mysql_banners.xml +0 -0
  34. data/{xml → recog/xml}/mysql_error.xml +0 -0
  35. data/{xml → recog/xml}/nntp_banners.xml +8 -5
  36. data/{xml → recog/xml}/ntp_banners.xml +33 -33
  37. data/{xml → recog/xml}/operating_system.xml +92 -77
  38. data/{xml → recog/xml}/pop_banners.xml +25 -25
  39. data/{xml → recog/xml}/rsh_resp.xml +0 -0
  40. data/{xml → recog/xml}/rtsp_servers.xml +0 -0
  41. data/{xml → recog/xml}/sip_banners.xml +16 -5
  42. data/{xml → recog/xml}/sip_user_agents.xml +122 -27
  43. data/{xml → recog/xml}/smb_native_lm.xml +5 -5
  44. data/{xml → recog/xml}/smb_native_os.xml +25 -25
  45. data/{xml → recog/xml}/smtp_banners.xml +132 -131
  46. data/{xml → recog/xml}/smtp_debug.xml +0 -0
  47. data/{xml → recog/xml}/smtp_ehlo.xml +0 -0
  48. data/{xml → recog/xml}/smtp_expn.xml +0 -0
  49. data/{xml → recog/xml}/smtp_help.xml +1 -1
  50. data/{xml → recog/xml}/smtp_mailfrom.xml +0 -0
  51. data/{xml → recog/xml}/smtp_noop.xml +0 -0
  52. data/{xml → recog/xml}/smtp_quit.xml +0 -0
  53. data/{xml → recog/xml}/smtp_rcptto.xml +0 -0
  54. data/{xml → recog/xml}/smtp_rset.xml +0 -0
  55. data/{xml → recog/xml}/smtp_turn.xml +0 -0
  56. data/{xml → recog/xml}/smtp_vrfy.xml +0 -0
  57. data/{xml → recog/xml}/snmp_sysdescr.xml +1248 -1233
  58. data/{xml → recog/xml}/snmp_sysobjid.xml +13 -2
  59. data/{xml → recog/xml}/ssh_banners.xml +9 -5
  60. data/{xml → recog/xml}/telnet_banners.xml +83 -1
  61. data/{xml → recog/xml}/tls_jarm.xml +30 -2
  62. data/{xml → recog/xml}/x11_banners.xml +3 -3
  63. data/{xml → recog/xml}/x509_issuers.xml +24 -4
  64. data/{xml → recog/xml}/x509_subjects.xml +32 -3
  65. data/recog.gemspec +9 -5
  66. data/spec/data/external_example_fingerprint/hp_printer_ex_01.txt +1 -0
  67. data/spec/data/external_example_fingerprint/hp_printer_ex_02.txt +1 -0
  68. data/spec/data/external_example_fingerprint.xml +8 -0
  69. data/spec/data/external_example_illegal_path_fingerprint.xml +7 -0
  70. data/spec/lib/recog/db_spec.rb +84 -61
  71. data/spec/lib/recog/fingerprint_spec.rb +4 -4
  72. data/spec/lib/recog/match_reporter_spec.rb +22 -8
  73. data/spec/lib/recog/verify_reporter_spec.rb +8 -8
  74. data/spec/spec_helper.rb +4 -0
  75. data.tar.gz.sig +0 -0
  76. metadata +154 -142
  77. metadata.gz.sig +0 -0
  78. data/.github/ISSUE_TEMPLATE/bug_report.md +0 -37
  79. data/.github/ISSUE_TEMPLATE/feature_request.md +0 -17
  80. data/.github/ISSUE_TEMPLATE/fingerprint_request.md +0 -27
  81. data/.github/PULL_REQUEST_TEMPLATE +0 -24
  82. data/.github/SECURITY.md +0 -35
  83. data/.github/dependabot.yml +0 -8
  84. data/.github/workflows/ci.yml +0 -26
  85. data/.github/workflows/verify.yml +0 -89
  86. data/.gitignore +0 -23
  87. data/.rspec +0 -3
  88. data/.ruby-gemset +0 -1
  89. data/.ruby-version +0 -1
  90. data/.snyk +0 -10
  91. data/.travis.yml +0 -25
  92. data/CONTRIBUTING.md +0 -276
  93. data/bin/recog_cleanup +0 -16
  94. data/bin/recog_export +0 -81
  95. data/bin/recog_standardize +0 -163
  96. data/bin/recog_verify +0 -63
  97. data/cpe-remap.yaml +0 -356
  98. data/features/data/failing_banners_fingerprints.xml +0 -20
  99. data/features/data/matching_banners_fingerprints.xml +0 -23
  100. data/features/data/multiple_banners_fingerprints.xml +0 -32
  101. data/features/data/no_tests.xml +0 -3
  102. data/features/data/sample_banner.txt +0 -2
  103. data/features/data/successful_tests.xml +0 -18
  104. data/features/data/tests_with_failures.xml +0 -20
  105. data/features/data/tests_with_warnings.xml +0 -17
  106. data/features/match.feature +0 -36
  107. data/features/support/aruba.rb +0 -3
  108. data/features/support/env.rb +0 -6
  109. data/features/verify.feature +0 -48
  110. data/identifiers/README.md +0 -70
  111. data/identifiers/fields.txt +0 -105
  112. data/identifiers/hw_device.txt +0 -84
  113. data/identifiers/hw_family.txt +0 -121
  114. data/identifiers/hw_product.txt +0 -461
  115. data/identifiers/os_architecture.txt +0 -10
  116. data/identifiers/os_device.txt +0 -75
  117. data/identifiers/os_family.txt +0 -234
  118. data/identifiers/os_product.txt +0 -350
  119. data/identifiers/service_family.txt +0 -249
  120. data/identifiers/service_product.txt +0 -764
  121. data/identifiers/vendor.txt +0 -847
  122. data/lib/recog/verifier_factory.rb +0 -13
  123. data/misc/convert_mysql_err +0 -61
  124. data/misc/order.xsl +0 -17
  125. data/requirements.txt +0 -2
  126. data/spec/lib/fingerprint_self_test_spec.rb +0 -175
  127. data/tools/dev/hooks/pre-commit +0 -21
  128. data/update_cpes.py +0 -250
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5e33013be558344280c798bb77321b809289a604f55a9f8447bba1cdd2b93151
4
- data.tar.gz: 4088c7af5a4dc2250562a610f2bbc6307436fefabe1203f1bd00fd2a9f9c0e3d
3
+ metadata.gz: fb6f2415bc93d48b60c359793b6aee1e30e513b16a35de7c7bda4373a99cb996
4
+ data.tar.gz: 106fdf45bfe575ad27e6d9bc71ef2192967d573d00e7eda9a51c1ac50a40b964
5
5
  SHA512:
6
- metadata.gz: abca30fbb5b218e69a2178c0b9b7337af15f1611d67076031ee5d489140505c558fe8981513d8d446bddc91b4166f304b88fed9eb23e22de0d4a5e10f2bfb668
7
- data.tar.gz: 57c7e248435b5d52860cd2117a814176673c0e8cb193f854880b3244c91d9b745ee67ca1bc8f2f67f1f3046d26857ca198c81a0e129f9d50b8cc28349070d250
6
+ metadata.gz: fd7943c87258799dde4b700bc0a121f5f6973e371f9904d5442e2fd3b4615bc4012b97f66426a7f7a628409c94515f2490273eb83a6cce4d57ad2071b8df58ff
7
+ data.tar.gz: d8ccfa23a65f4aa5c2d1638647042c6e47e8e9c2ce409a3fb01bf825fd28341c133948b6fff2a3e0dddb7d978460e45a113b883b774ae62cd84b0ce378fb8fe7
checksums.yaml.gz.sig ADDED
@@ -0,0 +1,2 @@
1
+ ?K��RF|m��/�E�b��ζ�A�}"�RDRz��b�C:��yi�S]l�=�}!��a�B�e�dN���i�s��}��z�gbD;�m8@��+�D�A;�,�+t�z���ĀR��cS��K�[��I�!��}qϞ[�AqeXR� E��C���ނKg�{2>VL'�|{��!k_i�Bb>̚O�Y�W\�J�O���^�m�vh���I��U��mA r3� E?p����
2
+ �ܦ`T���2tI6SX
data/LICENSE CHANGED
@@ -1,5 +1,5 @@
1
1
  Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
2
- Source: https://github.com/rapid7/recog
2
+ Source: https://github.com/rapid7/recog-ruby
3
3
 
4
4
  Files: *
5
5
  Copyright: 2014, Rapid7, Inc.
data/README.md CHANGED
@@ -1,41 +1,50 @@
1
- # Recog: A Recognition Framework
1
+ # Recog-Ruby: A Recognition Framework
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/recog.svg)](http://badge.fury.io/rb/recog)
4
- [![Build Status](https://travis-ci.org/rapid7/recog.svg?branch=master)](https://travis-ci.org/rapid7/recog)
4
+ [![CI Workflow](https://github.com/rapid7/recog-ruby/actions/workflows/ci.yml/badge.svg)](https://github.com/rapid7/recog-ruby/actions/workflows/ci.yml)
5
5
 
6
6
 
7
- Recog is a framework for identifying products, services, operating systems, and hardware by matching fingerprints against data returned from various network probes. Recog makes it simple to extract useful information from web server banners, snmp system description fields, and a whole lot more.
7
+ Recog is a framework for identifying products, services, operating systems, and hardware by matching fingerprints against data returned from various network probes. Recog makes it simple to extract useful information from web server banners, SNMP system description fields, and a whole lot more.
8
8
 
9
- Recog is open source, please see the [LICENSE](https://raw.githubusercontent.com/rapid7/recog/master/LICENSE) file for more information.
9
+ The Recog-Ruby repository contains the Ruby language implementation of the Recog recognition framework library and the [Recog](https://github.com/rapid7/recog) content, XML fingerprint files, as a git submodule. That makes it easy to develop, test, and use the contained fingerprints.
10
+
11
+ Recog-Ruby is open source, please see the [LICENSE](LICENSE) file for more information.
10
12
 
11
13
  ## Table of Contents
12
14
 
15
+ 1. [Repository split](#repository-split)
13
16
  1. [Installation](#installation)
14
17
  1. [Maturity](#maturity)
15
18
  1. [Fingerprints](#fingerprints)
16
19
  1. [Contributing](#contributing)
17
20
 
21
+ ## Repository split
22
+
23
+ On March 31, 2022, the Recog content - XML fingerprint files and utilities - were split from the Recog framework library implementation. The original [Recog](https://github.com/rapid7/recog) repository now contains the Recog content and the [Recog-Ruby](https://github.com/rapid7/recog-ruby) repository contains the Ruby language implementation. The Recog content is included in Recog-Ruby as a git submodule and is nested under the `recog` directory. All post-split Recog gem versions equal or greater than 3.0.0 will: 1. contain the XML fingerprint directory under the `recog` directory, and 2. only include the `recog_match` tool since the other tools are focused on fingerprint management.
24
+
25
+ [^back to top](#recog-ruby-a-recognition-framework)
26
+
18
27
  ## Installation
19
28
 
20
- Recog consists of both XML fingerprint files and an assortment of code, mostly in Ruby, that makes it easy to develop, test, and use the contained fingerprints. In order to use the included ruby code, a recent version of Ruby (2.31+) is required, along with Rubygems and the `bundler` gem. Once these dependencies are in place, use the following commands to grab the latest source code and install any additional dependencies.
29
+ In order to use the included Ruby code, a recent version of Ruby (2.31+) is required, along with Rubygems and the `bundler` gem. Once these dependencies are in place, use the following commands to grab the latest source code and install any additional dependencies.
21
30
 
22
31
  ```shell
23
- $ git clone git@github.com:rapid7/recog.git
24
- $ cd recog
32
+ $ git clone --recurse-submodules git@github.com:rapid7/recog-ruby.git
33
+ $ cd recog-ruby
25
34
  $ bundle install
26
35
  ```
27
36
 
28
- [^back to top](#recog-a-recognition-framework)
37
+ [^back to top](#recog-ruby-a-recognition-framework)
29
38
 
30
39
  ## Maturity
31
40
 
32
- Please note that while the XML fingerprints themselves are quite stable and well-tested, the Ruby codebase in Recog is still fairly new and subject to change quickly. Please contact us (research[at]rapid7.com) before leveraging the Recog code within any production projects.
41
+ Please note that while the XML fingerprints themselves are quite stable and well-tested, the Ruby codebase is still fairly new and subject to change quickly. Please contact us (research[at]rapid7.com) before leveraging the Recog code within any production projects.
33
42
 
34
- [^back to top](#recog-a-recognition-framework)
43
+ [^back to top](#recog-ruby-a-recognition-framework)
35
44
 
36
45
  ## Fingerprints
37
46
 
38
- The fingerprints within Recog are stored in XML files, each of which is designed to match a specific protocol response string or field. For example, the file [ssh_banners.xml](https://github.com/rapid7/recog/blob/master/xml/ssh_banners.xml) can determine the os, vendor, and sometimes hardware product by matching the initial SSH daemon banner string.
47
+ The fingerprints within [Recog](https://github.com/rapid7/recog) are stored in XML files, each of which is designed to match a specific protocol response string or field. For example, the file [ssh_banners.xml](https://github.com/rapid7/recog/blob/master/xml/ssh_banners.xml) can determine the os, vendor, and sometimes hardware product by matching the initial SSH daemon banner string.
39
48
 
40
49
  A fingerprint file consists of an XML document like the following:
41
50
 
@@ -69,12 +78,12 @@ The `param` elements contain a `pos` attribute, which indicates what capture fie
69
78
 
70
79
  The `example` string can be base64 encoded to permit the use of unprintable characters. To signal this to Recog an `_encoding` attribute with the value of `base64` is added to the `example` element. Based64 encoded text that is longer than 80 characters may be wrapped with newlines as shown below to aid in readability.
71
80
 
72
- ````xml
81
+ ```xml
73
82
  <example _encoding="base64">
74
83
  dGllczGEAAAAlQQWMS4yLjg0MC4xMTM1NTYuMS40LjgwMAQuZGF0YS5yZW1vdmVkLjCEAAAAK
75
84
  AQdZG9tYWluQ29udHJvbGxlckZ1bmN0aW9uYWxpdHkxhAAAAAMEATc=
76
85
  </example>
77
- ````
86
+ ```
78
87
 
79
88
  Additionally, examples can be placed in a directory with the same base name as the XML file, in the same directory as the XML file:
80
89
 
@@ -93,12 +102,12 @@ They can then be loaded using the `_filename` attribute:
93
102
 
94
103
  This is useful for long examples.
95
104
 
96
- [^back to top](#recog-a-recognition-framework)
105
+ [^back to top](#recog-ruby-a-recognition-framework)
97
106
 
98
107
  ## Contributing
99
108
 
100
- The users and maintainers of Recog would greatly appreciate any contributions
109
+ The users and maintainers of Recog-Ruby would greatly appreciate any contributions
101
110
  you can make to the project. For guidelines and instructions please see
102
111
  [CONTRIBUTING.MD](CONTRIBUTING.md)
103
112
 
104
- [^back to top](#recog-a-recognition-framework)
113
+ [^back to top](#recog-ruby-a-recognition-framework)
data/Rakefile CHANGED
@@ -2,7 +2,7 @@ require "bundler/gem_tasks"
2
2
 
3
3
  require 'rspec/core/rake_task'
4
4
  RSpec::Core::RakeTask.new do |t|
5
- t.pattern = "spec/**/*_spec.rb"
5
+ t.pattern = ['spec/**/*_spec.rb', 'recog/spec/**/*_spec.rb']
6
6
  end
7
7
 
8
8
  require 'yard'
@@ -11,12 +11,5 @@ YARD::Rake::YardocTask.new do |t|
11
11
  t.files = ['lib/**/*.rb', '-', 'README.md']
12
12
  end
13
13
 
14
- require 'cucumber'
15
- require 'cucumber/rake/task'
16
-
17
- Cucumber::Rake::Task.new(:features) do |t|
18
- t.cucumber_opts = "features --format pretty"
19
- end
20
-
21
14
  task :default => [ :tests, :yard ]
22
- task :tests => [ :spec, :features ]
15
+ task :tests => [ :spec ]
@@ -5,7 +5,7 @@ class DBManager
5
5
 
6
6
  attr_accessor :path, :databases
7
7
 
8
- DefaultDatabasePath = File.expand_path( File.join( File.dirname(__FILE__), "..", "..", "xml") )
8
+ DefaultDatabasePath = File.expand_path(File.join(File.expand_path(__dir__), ["..", "..", "recog", "xml"]))
9
9
 
10
10
  def initialize(path = DefaultDatabasePath)
11
11
  self.path = path
@@ -5,6 +5,7 @@ module Recog
5
5
  class Fingerprint
6
6
  require 'set'
7
7
 
8
+ require 'recog/fingerprint_parse_error'
8
9
  require 'recog/fingerprint/regexp_factory'
9
10
  require 'recog/fingerprint/test'
10
11
 
@@ -28,20 +29,27 @@ class Fingerprint
28
29
  # @return (see #parse_examples)
29
30
  attr_reader :tests
30
31
 
32
+ # The line number of the XML entity in the source file for this
33
+ # fingerprint.
34
+ #
35
+ # @return [Integer] The line number of this entity.
36
+ attr_reader :line
37
+
31
38
  # @param xml [Nokogiri::XML::Element]
32
39
  # @param match_key [String] See Recog::DB
33
40
  # @param protocol [String] Protocol such as ftp, mssql, http, etc.
34
- # @param filepath [String] Directory path for fingerprint example files
35
- def initialize(xml, match_key=nil, protocol=nil, filepath=nil)
41
+ # @param example_path [String] Directory path for fingerprint example files
42
+ def initialize(xml, match_key=nil, protocol=nil, example_path=nil)
36
43
  @match_key = match_key
37
44
  @protocol = protocol
38
45
  @name = parse_description(xml)
39
46
  @regex = create_regexp(xml)
47
+ @line = xml.line
40
48
  @params = {}
41
49
  @tests = []
42
50
 
43
51
  @protocol.downcase! if @protocol
44
- parse_examples(xml, filepath)
52
+ parse_examples(xml, example_path)
45
53
  parse_params(xml)
46
54
  end
47
55
 
@@ -161,6 +169,7 @@ class Fingerprint
161
169
  # look for the presence of test cases
162
170
  if tests.size == 0
163
171
  yield :warn, "'#{@name}' has no test cases"
172
+ return
164
173
  end
165
174
 
166
175
  # make sure each test case passes
@@ -226,7 +235,7 @@ class Fingerprint
226
235
  if !param_used
227
236
  message = "'#{@name}' is missing an example that checks for parameter '#{param_name}' " +
228
237
  "which is derived from a capture group"
229
- yield :warn, message
238
+ yield :fail, message
230
239
  end
231
240
  end
232
241
  end
@@ -249,9 +258,9 @@ class Fingerprint
249
258
  end
250
259
 
251
260
  # @param xml [Nokogiri::XML::Element]
252
- # @param filepath [String] Directory path for fingerprint example files
261
+ # @param example_path [String] Directory path for fingerprint example files
253
262
  # @return [void]
254
- def parse_examples(xml, filepath)
263
+ def parse_examples(xml, example_path)
255
264
  elements = xml.xpath('example')
256
265
 
257
266
  elements.each do |elem|
@@ -259,7 +268,12 @@ class Fingerprint
259
268
  attrs = elem.attributes.values.reduce({}) { |a,e| a.merge(e.name => e.value) }
260
269
  if attrs["_filename"]
261
270
  contents = ""
262
- fn = File.join(filepath, attrs["_filename"])
271
+ filename = attrs["_filename"]
272
+ fn = File.expand_path(File.join(example_path, filename))
273
+ unless fn.start_with?(File.expand_path(example_path) + File::Separator)
274
+ raise FingerprintParseError.new("an example specifies an illegal file path '#{filename}'", line_number = @line)
275
+ end
276
+
263
277
  File.open(fn, "rb") do |file|
264
278
  contents = file.read
265
279
  contents.force_encoding(Encoding::ASCII_8BIT)
@@ -0,0 +1,10 @@
1
+ module Recog
2
+ class FingerprintParseError < StandardError
3
+ attr_reader :line_number
4
+
5
+ def initialize(msg, line_number=nil)
6
+ @line_number = line_number
7
+ super(msg)
8
+ end
9
+ end
10
+ end
@@ -1,3 +1,5 @@
1
+ require 'json'
2
+
1
3
  module Recog
2
4
  class MatchReporter
3
5
  attr_reader :formatter
@@ -24,14 +26,46 @@ class MatchReporter
24
26
  @line_count += 1
25
27
  end
26
28
 
27
- def match(text)
29
+ def match(match_data)
28
30
  @match_count += 1
29
- formatter.success_message(text)
31
+ if @options.json_format
32
+ # remove data field from all matches and promote to a top-level field
33
+ data_field = match_data[0]["data"]
34
+ match_data.each { |h| h.delete("data") }
35
+ new_object = {
36
+ 'data' => data_field,
37
+ }
38
+
39
+ if @options.multi_match
40
+ new_object['matches'] = match_data
41
+ else
42
+ new_object['match'] = match_data[0]
43
+ end
44
+ msg = new_object.to_json
45
+ else
46
+ match_prefix = match_data.size > 1 ? 'MATCHES' : 'MATCH'
47
+ msg = "#{match_prefix}: #{match_data.map(&:inspect).join(',')}"
48
+ end
49
+ formatter.success_message("#{msg}")
30
50
  end
31
51
 
32
52
  def failure(text)
33
53
  @fail_count += 1
34
- formatter.failure_message(text)
54
+ if @options.json_format
55
+ new_object = {
56
+ 'data' => text,
57
+ 'match_failure' => true
58
+ }
59
+ if @options.multi_match
60
+ new_object['matches'] = nil
61
+ else
62
+ new_object['match'] = nil
63
+ end
64
+ msg = new_object.to_json
65
+ else
66
+ msg = "FAIL: #{text}"
67
+ end
68
+ formatter.failure_message("#{msg}")
35
69
  end
36
70
 
37
71
  def print_summary
data/lib/recog/matcher.rb CHANGED
@@ -29,26 +29,21 @@ class Matcher
29
29
  line = line.to_s.unpack("C*").pack("C*").strip.gsub(/\\[rn]/, '')
30
30
  found_extractions = false
31
31
 
32
- all_extractions = []
32
+ extraction_data = []
33
33
  fingerprints.each do |fp|
34
34
  extractions = fp.match(line)
35
35
  if extractions
36
36
  found_extractions = true
37
37
  extractions['data'] = line
38
- if multi_match
39
- all_extractions << extractions
40
- else
41
- reporter.match "MATCH: #{extractions.inspect}"
42
- break
43
- end
38
+ extraction_data << extractions
39
+ break unless multi_match
44
40
  end
45
41
  end
46
42
 
47
43
  if found_extractions
48
- match_prefix = all_extractions.size > 1 ? 'MATCHES' : 'MATCH'
49
- reporter.match "#{match_prefix}: #{all_extractions.map(&:inspect).join(',')}" if multi_match
44
+ reporter.match extraction_data
50
45
  else
51
- reporter.failure "FAIL: #{line}"
46
+ reporter.failure line
52
47
  end
53
48
 
54
49
  if reporter.stop?
@@ -15,9 +15,9 @@ class Verifier
15
15
  fp.verify_params do |status, message|
16
16
  case status
17
17
  when :warn
18
- reporter.warning "WARN: #{message}"
18
+ reporter.warning message, fp.line
19
19
  when :fail
20
- reporter.failure "FAIL: #{message}"
20
+ reporter.failure message, fp.line
21
21
  when :success
22
22
  reporter.success(message)
23
23
  end
@@ -25,9 +25,9 @@ class Verifier
25
25
  fp.verify_tests do |status, message|
26
26
  case status
27
27
  when :warn
28
- reporter.warning "WARN: #{message}"
28
+ reporter.warning message, fp.line
29
29
  when :fail
30
- reporter.failure "FAIL: #{message}"
30
+ reporter.failure message, fp.line
31
31
  when :success
32
32
  reporter.success(message)
33
33
  end
@@ -24,15 +24,15 @@ class VerifyReporter
24
24
  formatter.success_message("#{padding}#{text}") if detail?
25
25
  end
26
26
 
27
- def warning(text)
27
+ def warning(text, line=nil)
28
28
  return unless @options.warnings
29
29
  @warning_count += 1
30
- formatter.warning_message("#{path_label}#{padding}#{text}")
30
+ formatter.warning_message("#{path_label(line)}#{padding}WARN: #{text}")
31
31
  end
32
32
 
33
- def failure(text)
33
+ def failure(text, line=nil)
34
34
  @failure_count += 1
35
- formatter.failure_message("#{path_label}#{padding}#{text}")
35
+ formatter.failure_message("#{path_label(line)}#{padding}FAIL: #{text}")
36
36
  end
37
37
 
38
38
  def print_name(fingerprint)
@@ -65,9 +65,10 @@ class VerifyReporter
65
65
  @options.detail
66
66
  end
67
67
 
68
- def path_label
68
+ def path_label(line=nil)
69
69
  unless detail?
70
- @path.to_s.empty? ? "" : "#{@path}: "
70
+ line_label = line ? line.to_s + ":" : ""
71
+ @path.to_s.empty? ? "" : "#{@path}:#{line_label} "
71
72
  end
72
73
  end
73
74
 
data/lib/recog/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Recog
2
- VERSION = '2.3.22'
2
+ VERSION = '3.0.2'
3
3
  end
@@ -1,12 +1,11 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- $:.unshift(File.expand_path(File.join(File.dirname(__FILE__), "..", "lib")))
4
3
  require 'optparse'
5
4
  require 'ostruct'
6
5
  require 'recog'
7
6
  require 'recog/matcher_factory'
8
7
 
9
- options = OpenStruct.new(color: false, detail: false, fail_fast: false, multi_match: false)
8
+ options = OpenStruct.new(color: false, detail: false, json_format: false, fail_fast: false, multi_match: false)
10
9
 
11
10
  option_parser = OptionParser.new do |opts|
12
11
  opts.banner = "Usage: #{$0} [options] XML_FINGERPRINT_FILE [BANNERS_FILE]"
@@ -14,12 +13,18 @@ option_parser = OptionParser.new do |opts|
14
13
  opts.separator ""
15
14
  opts.separator "Options"
16
15
 
17
- opts.on("-f", "--format FORMATTER",
16
+ opts.on("-f", "--format FORMATTER", [:summary, :detail, :json],
18
17
  "Choose a formatter.",
19
18
  " [s]ummary (default - failure/match msgs)",
20
- " [d]etail (msgs with total counts)") do |format|
21
- if format.start_with? 'd'
19
+ " [d]etail (msgs with total counts)",
20
+ " [j]son (JSON failure/match msgs)") do |format|
21
+ if format == :summary
22
+ options.detail = false
23
+ options.json_format = false
24
+ elsif format == :detail
22
25
  options.detail = true
26
+ elsif format == :json
27
+ options.json_format = true
23
28
  end
24
29
  end
25
30
 
@@ -42,9 +47,17 @@ option_parser = OptionParser.new do |opts|
42
47
  exit
43
48
  end
44
49
  end
45
- option_parser.parse!(ARGV)
46
50
 
47
- if ARGV.count != 1 && ARGV.count != 2
51
+
52
+ begin
53
+ option_parser.parse!(ARGV)
54
+ rescue OptionParser::ParseError => e
55
+ puts e.message
56
+ puts option_parser
57
+ exit(1)
58
+ end
59
+
60
+ if ARGV.count < 1 || ARGV.count > 2
48
61
  puts option_parser
49
62
  exit(1)
50
63
  end
File without changes