patch_finder 1.0.1 → 1.0.2
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/bin/msu_finder +4 -4
- data/lib/{core → patch_finder/core}/config.rb +0 -0
- data/lib/{core → patch_finder/core}/helper.rb +9 -3
- data/lib/{core → patch_finder/core}/thread_pool.rb +8 -0
- data/lib/{engine → patch_finder/engine}/msu/constants.rb +0 -0
- data/lib/{engine → patch_finder/engine}/msu/google.rb +3 -3
- data/lib/{engine → patch_finder/engine}/msu/technet.rb +3 -3
- data/lib/{msu.rb → patch_finder/msu.rb} +31 -23
- data/patch_finder.gemspec +1 -1
- metadata +9 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1b6514503dbfbe97478245193cee9cb9ebd5ce8a
|
4
|
+
data.tar.gz: 0321ea95b7f6e67866884f5feda131fd286185c2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 730774a09da258d5bf5a63b858195211aced5366584677968220aab68c684ab3e4969c126deb607f8b72212d000f8b4b288d956181766c0d7d228d0d22b5aa16
|
7
|
+
data.tar.gz: 42c328ee3827716cac1d606ef1c7e4fe5b7c2b0fa3078b95fa32c1ce1faeb03cf91fa57e9c128cbb4ceb552011ef631239e291fc50f779592efcc8bc1114216b
|
data/bin/msu_finder
CHANGED
@@ -11,10 +11,10 @@
|
|
11
11
|
lib = File.expand_path('../../lib', __FILE__)
|
12
12
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
13
13
|
|
14
|
-
require 'core/helper'
|
15
|
-
require 'core/config'
|
14
|
+
require 'patch_finder/core/helper'
|
15
|
+
require 'patch_finder/core/config'
|
16
|
+
require 'patch_finder/msu'
|
16
17
|
require 'optparse'
|
17
|
-
require 'msu'
|
18
18
|
|
19
19
|
class PatchFinderBin
|
20
20
|
|
@@ -109,7 +109,7 @@ class PatchFinderBin
|
|
109
109
|
end
|
110
110
|
|
111
111
|
def main
|
112
|
-
cli = PatchFinder::MSU.new
|
112
|
+
cli = PatchFinder::MSU.new(verbose: true)
|
113
113
|
links = cli.find_msu_download_links(args)
|
114
114
|
if args[:destdir]
|
115
115
|
print_status("Download links found: #{links.length}")
|
File without changes
|
@@ -5,11 +5,17 @@ module PatchFinder
|
|
5
5
|
|
6
6
|
class PatchFinderException < RuntimeError; end
|
7
7
|
|
8
|
-
|
8
|
+
attr_accessor :verbose
|
9
|
+
|
10
|
+
# Prints a message if verbose is set
|
9
11
|
#
|
10
12
|
# @return [void]
|
11
|
-
def
|
12
|
-
$stderr.puts "[
|
13
|
+
def print_verbose(msg = '')
|
14
|
+
$stderr.puts "[*] #{msg}" if self.verbose
|
15
|
+
end
|
16
|
+
|
17
|
+
def print_verbose_error(msg='')
|
18
|
+
print_error(msge) if self.verbose
|
13
19
|
end
|
14
20
|
|
15
21
|
# Prints a status message.
|
File without changes
|
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'json'
|
2
|
-
require 'core/helper'
|
2
|
+
require 'patch_finder/core/helper'
|
3
3
|
require_relative 'constants'
|
4
4
|
|
5
5
|
module PatchFinder
|
@@ -64,7 +64,7 @@ module PatchFinder
|
|
64
64
|
break if next_page.nil? || next_starting_index > 100
|
65
65
|
end
|
66
66
|
rescue GoogleClientException => e
|
67
|
-
|
67
|
+
print_verbose_error(e.message)
|
68
68
|
return msb_numbers.uniq
|
69
69
|
end
|
70
70
|
|
@@ -97,7 +97,7 @@ module PatchFinder
|
|
97
97
|
res = send_http_get_request(req_str)
|
98
98
|
results = parse_results(res)
|
99
99
|
if starting_index == 1
|
100
|
-
|
100
|
+
print_verbose("Number of search results: #{get_total_results(results)}")
|
101
101
|
end
|
102
102
|
|
103
103
|
results
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'json'
|
2
2
|
require 'nokogiri'
|
3
|
-
require 'core/helper'
|
3
|
+
require 'patch_finder/core/helper'
|
4
4
|
require_relative 'constants'
|
5
5
|
|
6
6
|
module PatchFinder
|
@@ -28,7 +28,7 @@ module PatchFinder
|
|
28
28
|
def find_msb_numbers(keyword)
|
29
29
|
product_list_matches = get_product_dropdown_list.select { |p| Regexp.new(keyword) === p[:option_text] }
|
30
30
|
if product_list_matches.empty?
|
31
|
-
|
31
|
+
print_verbose('No match from the product list, attempting a generic search')
|
32
32
|
search_by_keyword(keyword)
|
33
33
|
else
|
34
34
|
product_names = []
|
@@ -37,7 +37,7 @@ module PatchFinder
|
|
37
37
|
ids << e[:option_value]
|
38
38
|
product_names << e[:option_text]
|
39
39
|
end
|
40
|
-
|
40
|
+
print_verbose("Matches from the product list (#{product_names.length}): #{ product_names * ', ' }")
|
41
41
|
search_by_product_ids(ids)
|
42
42
|
end
|
43
43
|
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
require 'nokogiri'
|
2
|
-
require 'core/thread_pool'
|
3
|
-
require 'engine/msu/google'
|
4
|
-
require 'engine/msu/technet'
|
5
|
-
require 'engine/msu/constants'
|
2
|
+
require 'patch_finder/core/thread_pool'
|
3
|
+
require 'patch_finder/engine/msu/google'
|
4
|
+
require 'patch_finder/engine/msu/technet'
|
5
|
+
require 'patch_finder/engine/msu/constants'
|
6
6
|
|
7
7
|
module PatchFinder
|
8
8
|
class MSU
|
@@ -11,6 +11,10 @@ module PatchFinder
|
|
11
11
|
|
12
12
|
MAX_THREADS = 10
|
13
13
|
|
14
|
+
def initialize(opts={})
|
15
|
+
self.verbose = opts[:verbose] || false
|
16
|
+
end
|
17
|
+
|
14
18
|
# Returns the download links.
|
15
19
|
#
|
16
20
|
# @param args [Hash] Arguments created by the user.
|
@@ -19,27 +23,31 @@ module PatchFinder
|
|
19
23
|
msb_numbers = collect_msbs(args)
|
20
24
|
|
21
25
|
unless msb_numbers.empty?
|
22
|
-
|
23
|
-
|
26
|
+
print_verbose("Advisories found (#{msb_numbers.length}): #{msb_numbers * ', '}")
|
27
|
+
print_verbose('Please wait while the download links are being collected...')
|
24
28
|
end
|
25
29
|
|
26
30
|
download_links = []
|
27
31
|
|
28
|
-
|
32
|
+
print_verbose("Max number of active collecting clients: #{MAX_THREADS}")
|
29
33
|
pool = PatchFinder::ThreadPool.new(MAX_THREADS)
|
30
34
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
35
|
+
begin
|
36
|
+
msb_numbers.each do |msb|
|
37
|
+
pool.schedule do
|
38
|
+
links = collect_links_from_msb(msb, args[:regex])
|
39
|
+
pool.mutex.synchronize do
|
40
|
+
download_links.concat(links)
|
41
|
+
end
|
36
42
|
end
|
37
43
|
end
|
38
|
-
end
|
39
44
|
|
40
|
-
|
45
|
+
pool.shutdown
|
41
46
|
|
42
|
-
|
47
|
+
sleep(0.5) until pool.eop?
|
48
|
+
ensure
|
49
|
+
pool.cleanup
|
50
|
+
end
|
43
51
|
|
44
52
|
download_links
|
45
53
|
end
|
@@ -55,10 +63,10 @@ module PatchFinder
|
|
55
63
|
|
56
64
|
case args[:search_engine]
|
57
65
|
when :technet
|
58
|
-
|
66
|
+
print_verbose("Searching advisories that include #{args[:keyword]} via Technet")
|
59
67
|
msb_numbers = technet_search(args[:keyword])
|
60
68
|
when :google
|
61
|
-
|
69
|
+
print_verbose("Searching advisories that include #{args[:keyword]} via Google")
|
62
70
|
msb_numbers = google_search(args[:keyword], args[:google_api_key], args[:google_search_engine_id])
|
63
71
|
end
|
64
72
|
|
@@ -72,24 +80,24 @@ module PatchFinder
|
|
72
80
|
# @return [Array]
|
73
81
|
def collect_links_from_msb(msb, regex = nil)
|
74
82
|
unless is_valid_msb?(msb)
|
75
|
-
|
76
|
-
|
83
|
+
print_verbose_error "Not a valid MSB format: #{msb}"
|
84
|
+
print_verbose_error 'Example of a correct one: ms15-100'
|
77
85
|
return []
|
78
86
|
end
|
79
87
|
|
80
88
|
res = download_advisory(msb)
|
81
89
|
|
82
90
|
if !has_advisory?(res)
|
83
|
-
|
91
|
+
print_verbose_error "The advisory cannot be found for #{msb}"
|
84
92
|
return []
|
85
93
|
end
|
86
94
|
|
87
95
|
links = get_details_aspx(res)
|
88
96
|
if links.length == 0
|
89
|
-
|
97
|
+
print_verbose_error "Unable to find download.microsoft.com links for #{msb}."
|
90
98
|
return []
|
91
99
|
else
|
92
|
-
|
100
|
+
print_verbose("Found #{links.length} affected products for #{msb}.")
|
93
101
|
end
|
94
102
|
|
95
103
|
link_collector = []
|
@@ -169,7 +177,7 @@ module PatchFinder
|
|
169
177
|
begin
|
170
178
|
links << found_link
|
171
179
|
rescue ::URI::InvalidURIError
|
172
|
-
|
180
|
+
print_verbose_error "Unable to parse URI: #{found_link}"
|
173
181
|
end
|
174
182
|
end
|
175
183
|
end
|
data/patch_finder.gemspec
CHANGED
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
6
|
spec.name = 'patch_finder'
|
7
|
-
spec.version = '1.0.
|
7
|
+
spec.version = '1.0.2'
|
8
8
|
spec.authors = ['wchen-r7']
|
9
9
|
spec.email = ['wei_chen@rapid7.com']
|
10
10
|
spec.summary = 'Patch Finder'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: patch_finder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- wchen-r7
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-03-
|
11
|
+
date: 2016-03-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -65,13 +65,13 @@ files:
|
|
65
65
|
- Rakefile
|
66
66
|
- bin/msu_finder
|
67
67
|
- docs/bin/msu_finder.txt
|
68
|
-
- lib/core/config.rb
|
69
|
-
- lib/core/helper.rb
|
70
|
-
- lib/core/thread_pool.rb
|
71
|
-
- lib/engine/msu/constants.rb
|
72
|
-
- lib/engine/msu/google.rb
|
73
|
-
- lib/engine/msu/technet.rb
|
74
|
-
- lib/msu.rb
|
68
|
+
- lib/patch_finder/core/config.rb
|
69
|
+
- lib/patch_finder/core/helper.rb
|
70
|
+
- lib/patch_finder/core/thread_pool.rb
|
71
|
+
- lib/patch_finder/engine/msu/constants.rb
|
72
|
+
- lib/patch_finder/engine/msu/google.rb
|
73
|
+
- lib/patch_finder/engine/msu/technet.rb
|
74
|
+
- lib/patch_finder/msu.rb
|
75
75
|
- patch_finder.gemspec
|
76
76
|
- tools/extract_msu.bat
|
77
77
|
- tools/list_dll.rb
|