moby.rb 1.0.0 → 1.0.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 59fc23e9713b37a55d2e866bc1109b525dd188f04136092b05ae0b8f2a860d10
4
- data.tar.gz: 6945ecfdea1a8f3437bae309c1d9b0e20dbe31d3a28006699e145e9dd57abec9
3
+ metadata.gz: 8a52161eceecdfce20494ae2ff6b8e8fa8aefceb1d6911db3c2fd3bac475896f
4
+ data.tar.gz: 6242e8451d3d66b70b9452dc305329c121e97a8e1d868cb6744228208d2e8da6
5
5
  SHA512:
6
- metadata.gz: f909d78a0a23c40143f3ed9d876a80b5fdd1f963670cbaea39d5f5ad42224ee0458adf1a095c9734c65e95e122b6ba9b69ea65fe95e860edf03c12442c2eab65
7
- data.tar.gz: 1eb639787025eccdcc74517655651eef1e0ef2d142015abaad3523eab31dcc298f33e1a5bf7afb66735b281856261a49f03f499792eca4f7ad8c93c6f89036e1
6
+ metadata.gz: 40ccfc56a276bb2c2ef6ad12e903dd2791f5be79f857ad4f6718c846b848ddee3ee62974f0a60e7a56e2cd8560f6761ccd53a5aecad3919fb6b4e9bc0274d752
7
+ data.tar.gz: dd7eba42a50b08e714407079b8191348f8f18d0ee389881dfce367af78d185c6b0a16570fa484d57362df8a23ec1278986ebb970c3815db897432e11b51b3f7f
data/CHANGELOG ADDED
@@ -0,0 +1,89 @@
1
+ # CHANGELOG
2
+
3
+ ## 20260807
4
+
5
+ 1.0.1: Add a CHANGELOG in the form changelogger writes, and retire CHANGES.txt.
6
+
7
+ 1. + CHANGELOG, in the form changelogger writes: a dated heading per version, the version and its summary on the first line of the body, then the numbered items, newest first — the form the other repositories already use. Versions 0.8.0 to 1.0.0 are carried across from CHANGES.txt; 0.7.0 to 0.7.4 are recovered from the git-importall revisions, each of which carries a version and a date of its own. Nothing before 0.7.0 is recorded: the 2006 series stamps every version with the one creation date, and the revisions between it and 0.7.0 carry a date but no version, so neither a reliable date nor a reliable version can be had for them.
8
+ 2. - CHANGES.txt. The CHANGELOG holds that record now, and keeping both invites them to disagree. Its changelog_uri and file list in moby.rb.gemspec are pointed at CHANGELOG in its place.
9
+ 3. ~ lib/Moby/VERSION.rb: VERSION: /1.0.0/1.0.1/
10
+ 4. ~ test/Moby/VERSION_test.rb: /1.0.0/1.0.1/
11
+
12
+ ## 20260108
13
+
14
+ 1.0.0: Ensure that tests are in place and that version handling is working properly.
15
+
16
+ 1. + tests
17
+ 2. + moby.rb.gemspec
18
+ 3. ~ lib/moby.rb: - Moby::VERSION_STRING
19
+ 4. ~ lib/moby.rb: Fix finding username and password fields by name. It was returning the name of the field and not the field object.
20
+ 5. + lib/Moby/VERSION.rb
21
+ 6. ~ bin/moby: + --version flag
22
+ 7. ~ README.md: Updated installation and usage.
23
+ 8. ~ CHANGES.txt: Reorganised in descending order and added dates.
24
+ 9. ~ LICENSE.txt: Updated the years to include the year this was started: /2026/2006-2026/
25
+
26
+ ## 20260105
27
+
28
+ 0.9.1: Fix syntax errors in README.md.
29
+
30
+ 1. ~ README.md: Fix syntax errors.
31
+ 2. ~ lib/Moby.rb: VERSION_STRING: /0.9.0/0.9.1/
32
+
33
+ ## 20240605
34
+
35
+ 0.9.0: Merge of 2019's 0.8.0 and 2023's 0.8.1.
36
+
37
+ ## 20231206
38
+
39
+ 0.8.1: Fix when username or password field number is specified or nothing is specified.
40
+
41
+ 1. ~ lib/Whale: ~ set_username_field(): Fix when username field number is specified or nothing is specified.
42
+ 2. ~ lib/Whale: ~ set_password_field(): Fix when password field number is specified or nothing is specified.
43
+
44
+ ## 20231119
45
+
46
+ 0.8.0: An accidental fork of 0.7.0 in 2023.
47
+
48
+ 1. + README.md
49
+ 2. + CHANGES.txt
50
+ 3. + Gemfile
51
+ 4. ~ bin/whale: ~ main(): - args (unnecessary)
52
+ 5. ~ bin/whale VERSION_STRING --> lib/Whale::VERSION_STRING
53
+ 6. ~ bin/whale: ~ switches(): use Whale::VERSION_STRING
54
+ 7. ~ lib/Whale.rb: general tidying
55
+ 8. + lib/File/self.collect.rb
56
+
57
+ ## 20190820
58
+
59
+ 0.7.4: Rescue Net::OpenTimeout in the submission loop.
60
+
61
+ 1. ~ counter_phish(): + rescue Net::OpenTimeout.
62
+
63
+ ## 20190819
64
+
65
+ 0.7.3: Rescue Net::HTTP::Persistent::Error in place of EOFError.
66
+
67
+ 1. ~ counter_phish(): rescue Net::HTTP::Persistent::Error in place of EOFError.
68
+
69
+ ## 20190819
70
+
71
+ 0.7.2: Set field values on the field objects rather than through the setter methods.
72
+
73
+ 1. ~ counter_phish(): set the user agent and field values inline — mechanize.user_agent_alias, username_field.value, password_field.value — in place of set_user_agent()/set_username_field()/set_password_field().
74
+ 2. ~ username(): use the username_is_email_address? predicate, its default nil in place of false.
75
+ 3. ~ user_agent: attr_writer in place of attr_accessor.
76
+ 4. ~ counter_phish(): verbose reports username_field.value:password_field.value.
77
+
78
+ ## 20190819
79
+
80
+ 0.7.1: Assign to the field's value rather than replacing the field object.
81
+
82
+ 1. ~ set_username_field()/set_password_field(): set the field's value in place of replacing the field object at form.fields[n].
83
+ 2. ~ counter_phish(): + rescue EOFError; + pp page in debug.
84
+
85
+ ## 20190815
86
+
87
+ 0.7.0: The earliest recoverable version.
88
+
89
+ 1. whale floods a phishing form with fake credentials: counter_phish() loads the page, then loops submitting a generated username and password, each built from random dictionary words and TLDs. Recorded as an inventory of the first cleanly-versioned revision; the revision before it carries no version and a different structure, and is not reconstructed here.
data/lib/Moby/VERSION.rb CHANGED
@@ -2,5 +2,5 @@
2
2
  # Moby::VERSION
3
3
 
4
4
  class Moby
5
- VERSION = '1.0.0'
5
+ VERSION = '1.0.1'
6
6
  end
@@ -1,4 +1,4 @@
1
- # moby.gemspec
1
+ # moby.rb.gemspec
2
2
 
3
3
  require_relative './lib/Moby/VERSION'
4
4
 
@@ -30,10 +30,10 @@ Gem::Specification.new do |spec|
30
30
  'bin/*',
31
31
  'lib/**/*.rb',
32
32
  'test/**/*.rb',
33
- 'CHANGES.txt',
33
+ 'CHANGELOG',
34
34
  'Gemfile',
35
35
  'LICENSE.txt',
36
- 'moby.gemspec',
36
+ 'moby.rb.gemspec',
37
37
  'Rakefile',
38
38
  'README.md',
39
39
  ]
@@ -44,7 +44,7 @@ Gem::Specification.new do |spec|
44
44
 
45
45
  spec.metadata = {
46
46
  "bug_tracker_uri" => "https://github.com/thoran/moby/issues",
47
- "changelog_uri" => "https://github.com/thoran/moby/blob/main/CHANGES.txt",
47
+ "changelog_uri" => "https://github.com/thoran/moby/blob/main/CHANGELOG",
48
48
  "source_code_uri" => "https://github.com/thoran/moby",
49
49
  "documentation_uri" => "https://github.com/thoran/moby/blob/main/README.md"
50
50
  }
@@ -16,8 +16,8 @@ describe Moby do
16
16
  _(Moby::VERSION).must_match(/\d+\.\d+\.\d+/)
17
17
  end
18
18
 
19
- it "version is 1.0.0" do
20
- _(Moby::VERSION).must_equal('1.0.0')
19
+ it "version is 1.0.1" do
20
+ _(Moby::VERSION).must_equal('1.0.1')
21
21
  end
22
22
  end
23
23
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: moby.rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - thoran
@@ -102,7 +102,7 @@ executables:
102
102
  extensions: []
103
103
  extra_rdoc_files: []
104
104
  files:
105
- - CHANGES.txt
105
+ - CHANGELOG
106
106
  - Gemfile
107
107
  - LICENSE.txt
108
108
  - README.md
@@ -110,17 +110,9 @@ files:
110
110
  - bin/moby
111
111
  - lib/File/self.collect.rb
112
112
  - lib/Moby.rb
113
- - lib/Moby/Backends/MechanizeBackend.rb
114
- - lib/Moby/Backends/SeleniumBackend.rb
115
- - lib/Moby/Configuration.rb
116
- - lib/Moby/RandomInputGenerator.rb
117
113
  - lib/Moby/VERSION.rb
118
- - lib/Selenium/WebDriver/Driver/Attempt/attempt.rb
119
- - lib/Selenium/WebDriver/SearchContext/ElementPresentQ/element_presentQ.rb
120
114
  - lib/Thoran/File/SelfCollect/self.collect.rb
121
- - lib/Thoran/Selenium/WebDriver/Driver/Attempt/attempt.rb
122
- - lib/Thoran/Selenium/WebDriver/SearchContext/ElementPresentQ/element_presentQ.rb
123
- - moby.gemspec
115
+ - moby.rb.gemspec
124
116
  - test/Moby/VERSION_test.rb
125
117
  - test/moby_test.rb
126
118
  - test/test_helper.rb
@@ -129,7 +121,7 @@ licenses:
129
121
  - MIT
130
122
  metadata:
131
123
  bug_tracker_uri: https://github.com/thoran/moby/issues
132
- changelog_uri: https://github.com/thoran/moby/blob/main/CHANGES.txt
124
+ changelog_uri: https://github.com/thoran/moby/blob/main/CHANGELOG
133
125
  source_code_uri: https://github.com/thoran/moby
134
126
  documentation_uri: https://github.com/thoran/moby/blob/main/README.md
135
127
  rdoc_options: []
@@ -146,7 +138,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
146
138
  - !ruby/object:Gem::Version
147
139
  version: '0'
148
140
  requirements: []
149
- rubygems_version: 4.0.3
141
+ rubygems_version: 4.0.17
150
142
  specification_version: 4
151
143
  summary: Moby is a credentials poisoning tool which floods phishing forms with fake
152
144
  credentials.
data/CHANGES.txt DELETED
@@ -1,32 +0,0 @@
1
- 1.0.0 - 2026-01-08
2
- Ensure that tests are in place and that version handling is working properly.
3
- + tests
4
- + moby.gemspec
5
- ~ lib/moby.rb: - Moby::VERSION_STRING
6
- ~ lib/moby.rb: Fix finding username and password fields by name. It was returning the name of the field and not the field object.
7
- + lib/Moby/VERSION.rb
8
- ~ bin/moby: + --version flag
9
- ~ README.md: Updated installation and usage.
10
- ~ CHANGES.txt: Reorganised in descending order and added dates.
11
- ~ LICENSE.txt: Updated the years to include the year this was started: /2026/2006-2026/
12
-
13
- 0.9.1 - 2026-01-05
14
- ~ README.md: Fix syntax errors.
15
- ~ lib/Moby.rb: VERSION_STRING: /0.9.0/0.9.1/
16
-
17
- 0.9.0 - 2024-06-05
18
- Merged the 2019 0.8.0 version of moby with the 2023 0.8.1 version of whale.
19
-
20
- 0.8.1 - 2023-12-06
21
- ~ lib/Whale: ~ set_username_field(): Fix when username field number is specified or nothing is specified.
22
- ~ lib/Whale: ~ set_password_field(): Fix when password field number is specified or nothing is specified.
23
-
24
- 0.8.0 - 2023-11-19
25
- + README.md
26
- + CHANGES.txt
27
- + Gemfile
28
- ~ bin/whale: ~ main(): - args (unnecessary)
29
- ~ bin/whale VERSION_STRING --> lib/Whale::VERSION_STRING
30
- ~ bin/whale: ~ switches(): use Whale::VERSION_STRING
31
- ~ lib/Whale.rb: general tidying
32
- + lib/File/self.collect.rb
@@ -1,157 +0,0 @@
1
- # lib/moby/backends/mechanize_backend.rb
2
- # Moby::Backends::MechanizeBackend
3
-
4
- require 'mechanize'
5
- require 'pp'
6
-
7
- class Moby
8
- module Backends
9
- class MechanizeBackend
10
- def counter_phish
11
- set_up_agent
12
- load_page
13
- repeatedly_fill_and_submit_login_form
14
- end
15
-
16
- private
17
-
18
- def initialize(config:, random_input_generator:)
19
- @config = config
20
- @random_input_generator = random_input_generator
21
- end
22
-
23
- def agent
24
- @agent ||= (
25
- puts "Setting up Mechanize agent..." if @config.verbose?
26
- agent = Mechanize.new
27
- puts "Agent setup complete." if @config.verbose?
28
- agent
29
- )
30
- end
31
- alias_method :set_up_agent, :agent
32
-
33
- def page
34
- @page ||= (
35
- puts "Navigating to #{@config.url}..." if @config.verbose?
36
- page = agent.get(@config.url)
37
- puts "Page loaded successfully." if @config.verbose?
38
- page
39
- )
40
- end
41
- alias_method :load_page, :page
42
-
43
- def form
44
- @form ||= (
45
- if @config.using_form_name?
46
- find_form_by_name
47
- else
48
- find_form_by_number
49
- end
50
- )
51
- end
52
-
53
- def repeatedly_fill_and_submit_login_form
54
- start_time = Time.now
55
- puts "moby session begun #{start_time}."
56
- submission_count = 0
57
- begin
58
- if @config.fixed_number_of_submissions?
59
- @config.iterations.times do |iteration|
60
- fill_and_submit_login_form
61
- submission_count += 1
62
- puts "Iteration #{submission_count} of #{@config.iterations}." if @config.verbose?
63
- end
64
- puts "Successfully completed #{@config.iterations} submissions." if @config.verbose?
65
- else
66
- loop do
67
- fill_and_submit_login_form
68
- submission_count += 1
69
- puts "#{submission_count} #{username}:#{password}" if @config.verbose?
70
- end
71
- end
72
- ensure
73
- finish_time = Time.now
74
- time_delta_in_minutes = (finish_time - start_time) / 60
75
- submissions_per_minute = submission_count / time_delta_in_minutes
76
- puts "moby session terminated #{finish_time} with #{submission_count} counter-phishes served in #{time_delta_in_minutes} minutes for an average of #{submissions_per_minute} submissions per minute."
77
- end
78
- end
79
-
80
- def fill_and_submit_login_form
81
- puts "Filling with: #{username}:#{password}" if @config.verbose?
82
- agent.user_agent_alias = @config.user_agent
83
- username_field.value = username
84
- password_field.value = password
85
- pp page if @config.debug?
86
- result = agent.submit(form)
87
- pp result if @config.debug?
88
- sleep @config.delay if @config.delay > 0
89
- rescue Net::HTTP::Persistent::Error
90
- puts "\n\nNet::HTTP::Persistent::Error rescued.\n\n" if @config.verbose?
91
- rescue Net::OpenTimeout
92
- puts "\n\nNet::OpenTimeout rescued.\n\n" if @config.verbose?
93
- end
94
-
95
- def find_form_by_name
96
- page.form_with(name: @config.form_name) ||
97
- page.form_with(id: @config.form_name) ||
98
- raise("Could not find a form with the name or id of #{@config.form_name}.")
99
- end
100
-
101
- def find_form_by_number
102
- page.forms[@config.form_number] ||
103
- raise("Could not find a form at index #{@config.form_number}.")
104
- end
105
-
106
- def username
107
- @random_input_generator.random_username
108
- end
109
-
110
- def password
111
- @random_input_generator.random_password
112
- end
113
-
114
- def username_field
115
- @username_field ||=(
116
- if @config.using_username_field_name?
117
- find_username_field_by_name
118
- else
119
- find_username_field_by_number
120
- end
121
- )
122
- end
123
-
124
- def password_field
125
- @password_field ||= (
126
- if @config.using_password_field_name?
127
- find_password_field_by_name
128
- else
129
- find_password_field_by_number
130
- end
131
- )
132
- end
133
-
134
- def find_username_field_by_name
135
- form.field_with(name: @config.username_field_name) ||
136
- form.field_with(id: @config.username_field_name) ||
137
- raise("Could not find username field: #{@config.username_field_name}")
138
- end
139
-
140
- def find_username_field_by_number
141
- form.fields[@config.username_field_number] ||
142
- raise("Could not find username field at index #{@config.username_field_number}")
143
- end
144
-
145
- def find_password_field_by_name
146
- form.field_with(name: @config.password_field_name) ||
147
- form.field_with(id: @config.password_field_name) ||
148
- raise("Could not find password field: #{@config.password_field_name}.")
149
- end
150
-
151
- def find_password_field_by_number
152
- form.fields[@config.password_field_number] ||
153
- raise("Could not find password field at index: #{@config.password_field_number}.")
154
- end
155
- end
156
- end
157
- end
@@ -1,236 +0,0 @@
1
- # lib/Moby/Backends/SeleniumBackend.rb
2
- # Moby::Backends::SeleniumBackend
3
-
4
- require 'selenium-webdriver'
5
-
6
- require_relative '../Selenium/WebDriver/Driver/Attempt/attempt'
7
- require_relative '../Selenium/WebDriver/SearchContext/ElementPresentQ/element_presentQ'
8
-
9
- class Moby
10
- module Backends
11
- class SeleniumBackend
12
- def counter_phish
13
- set_up_driver
14
- navigate_to_target
15
- repeatedly_fill_and_submit_login_form
16
- ensure
17
- cleanup_driver unless @config.debug?
18
- end
19
-
20
- private
21
-
22
- def initialize(config:, random_input_generator:)
23
- @config = config
24
- @random_input_generator = random_input_generator
25
- @driver = nil
26
- end
27
-
28
- def driver
29
- puts "Setting up #{@config.browser} driver..." if @config.verbose
30
- case @config.browser.to_sym
31
- when :chrome
32
- options = Selenium::WebDriver::Chrome::Options.new
33
- options.add_argument('--headless') unless @config.debug
34
- options.add_argument('--disable-gpu')
35
- options.add_argument('--no-sandbox')
36
- options.add_argument("user-agent=#{@config.user_agent}") if @config.user_agent
37
- @driver = Selenium::WebDriver.for(:chrome, options: options)
38
- when :firefox
39
- options = Selenium::WebDriver::Firefox::Options.new
40
- options.add_argument('--headless') unless @config.debug
41
- options.add_preference('general.useragent.override', @config.user_agent) if @config.user_agent
42
- @driver = Selenium::WebDriver.for(:firefox, options: options)
43
- else
44
- @driver = Selenium::WebDriver.for(@config.browser)
45
- end
46
- puts "Driver setup complete." if @config.verbose?
47
- end
48
- alias_method :set_up_driver, :driver
49
-
50
- def navigate_to_target
51
- puts "Navigating to #{@config.url}..." if @config.verbose?
52
- @driver.attempt do
53
- @driver.get(@config.url)
54
- wait_for_page_load
55
- end
56
- puts "Page loaded successfully." if @config.verbose?
57
- end
58
-
59
- def wait_for_page_load
60
- wait = Selenium::WebDriver::Wait.new(timeout: 10)
61
- wait.until do
62
- @driver.execute_script('return document.readyState') == 'complete'
63
- end
64
- end
65
-
66
- def form
67
- @form ||= (
68
- if @config.using_form_name?
69
- find_form_by_name
70
- else
71
- find_form_by_number
72
- end
73
- )
74
- end
75
-
76
- def repeatedly_fill_and_submit_login_form
77
- start_time = Time.now
78
- puts "moby session begun #{start_time}."
79
- submission_count = 0
80
- begin
81
- if @config.fixed_number_of_submissions?
82
- @config.iterations.times do |iteration|
83
- fill_and_submit_login_form
84
- submission_count += 1
85
- puts "Submission #{submission_count} of #{@config.iterations}." if @config.verbose?
86
- end
87
- puts "Successfully completed #{@config.iterations} submissions." if @config.verbose?
88
- else
89
- loop do
90
- fill_and_submit_login_form
91
- submission_count += 1
92
- puts "#{submission_count} #{username}:#{password}" if @config.verbose?
93
- end
94
- end
95
- ensure
96
- finish_time = Time.now
97
- time_delta_in_minutes = (finish_time - start_time) / 60
98
- submissions_per_minute = submission_count / time_delta_in_minutes
99
- puts "moby session terminated #{finish_time} with #{submission_count} counter-phishes served in #{time_delta_in_minutes} minutes for an average of #{submissions_per_minute} submissions per minute."
100
- end
101
- end
102
-
103
- def fill_and_submit_login_form
104
- puts "Filling with: #{username}:#{password}" if @config.verbose?
105
- driver.navigate.to(@config.url)
106
- wait_for_page_load
107
- driver.attempt do
108
- username_field.clear
109
- username_field.send_keys(username)
110
- password_field.clear
111
- password_field.send_keys(password)
112
- submit_form(form)
113
- end
114
- sleep @config.delay if @config.delay > 0
115
- end
116
-
117
- def find_form_by_name
118
- name = @config.form_name
119
- selectors = [
120
- [:name, name],
121
- [:id, name],
122
- [:css, "form[name='#{name}']"],
123
- [:css, "form##{name}"]
124
- ]
125
- selectors.each do |type, selector|
126
- if @driver.element_present?(type, selector)
127
- return @driver.find_element(type, selector)
128
- end
129
- end
130
- raise("Could not find a form with the name or id of #{@config.form_name}.")
131
- end
132
-
133
- def find_form_by_number
134
- index = @config.form_number
135
- forms = @driver.find_elements(:tag_name, 'form')
136
- return forms[index] if forms[index]
137
- raise("Could not find a form at index #{@config.form_number}.")
138
- end
139
-
140
- def username
141
- @random_input_generator.random_username
142
- end
143
-
144
- def password
145
- @random_input_generator.random_password
146
- end
147
-
148
- def username_field
149
- @username_field ||= (
150
- if @config.using_username_field_name?
151
- find_username_field_by_name
152
- else
153
- find_username_field_by_number
154
- end
155
- )
156
- end
157
-
158
- def password_field
159
- @password_field ||= (
160
- if @config.using_password_field_name?
161
- find_password_field_by_name
162
- else
163
- find_password_field_by_number
164
- end
165
- )
166
- end
167
-
168
- def find_username_field_by_name
169
- name = @config.username_field_name
170
- selectors = [
171
- [:name, name],
172
- [:id, name],
173
- [:css, "input[name='#{name}']"],
174
- [:css, "input##{name}"]
175
- ]
176
- selectors.each do |type, selector|
177
- begin
178
- element = form.find_element(type, selector)
179
- return element if element
180
- rescue Selenium::WebDriver::Error::NoSuchElementError
181
- next
182
- end
183
- end
184
- raise("Could not find username field: #{@config.username_field_name}")
185
- end
186
-
187
- def find_username_field_by_number
188
- index = @config.username_field_number
189
- inputs = form.find_elements(:tag_name, 'input')
190
- inputs[index] ||
191
- raise("Could not find username field at index #{index}")
192
- end
193
-
194
- def find_password_field_by_name
195
- name = @config.password_field_name
196
- selectors = [
197
- [:name, name],
198
- [:id, name],
199
- [:css, "input[name='#{name}']"],
200
- [:css, "input##{name}"]
201
- ]
202
- selectors.each do |type, selector|
203
- begin
204
- element = form.find_element(type, selector)
205
- return element if element
206
- rescue Selenium::WebDriver::Error::NoSuchElementError
207
- next
208
- end
209
- end
210
- raise("Could not find password field: #{@config.password_field_name}")
211
- end
212
-
213
- def find_password_field_by_number
214
- index = @config.password_field_number
215
- inputs = form.find_elements(:tag_name, 'input')
216
- inputs[index] ||
217
- raise("Could not find password field at index #{index}")
218
- end
219
-
220
- def submit_form(form)
221
- begin
222
- submit_button = form.find_element(:css, "input[type='submit'], button[type='submit'], button")
223
- submit_button.click
224
- rescue
225
- form.submit
226
- end
227
- sleep 0.5
228
- end
229
-
230
- def cleanup_driver
231
- @driver.quit if @driver
232
- puts "Driver closed." if @config.verbose?
233
- end
234
- end
235
- end
236
- end
@@ -1,113 +0,0 @@
1
- # lib/Moby/Configuration.rb
2
- # Moby::Configuration
3
-
4
- require 'mechanize'
5
-
6
- class Moby
7
- class Configuration
8
- AVAILABLE_USER_AGENTS = (Mechanize::AGENT_ALIASES.keys - ['Mechanize']).freeze
9
-
10
- attr_accessor(
11
- :url,
12
- :backend,
13
- :browser,
14
- :debug,
15
- :verbose,
16
- :form_name,
17
- :form_number,
18
- :username_field_name,
19
- :username_field_number,
20
- :password_field_name,
21
- :password_field_number,
22
- :username_hostname,
23
- :username_is_email_address,
24
- :iterations,
25
- :delay,
26
- :word_list_path
27
- )
28
-
29
- attr_writer(
30
- :user_agent,
31
- )
32
-
33
- def user_agent
34
- @user_agent || random_user_agent
35
- end
36
-
37
- def using_form_name?
38
- !@form_name.nil?
39
- end
40
-
41
- def using_username_field_name?
42
- !@username_field_name.nil?
43
- end
44
-
45
- def using_password_field_name?
46
- !@password_field_name.nil?
47
- end
48
-
49
- def mechanize?
50
- @backend == :mechanize
51
- end
52
-
53
- def selenium?
54
- @backend == :selenium
55
- end
56
-
57
- def username_is_email_address?
58
- @username_is_email_address || @username_hostname || @username_field_name == 'email'
59
- end
60
-
61
- def debug?
62
- @debug
63
- end
64
-
65
- def verbose?
66
- @verbose
67
- end
68
-
69
- def fixed_number_of_submissions?
70
- !!@iterations
71
- end
72
-
73
- private
74
-
75
- # @param url [String] The target URL
76
- # @param backend [Symbol] :mechanize or :selenium (default: :selenium)
77
- # @param browser [Symbol] :chrome or :firefox (default: :chrome)
78
-
79
- def initialize(url:, backend: :selenium, browser: :chrome, **args)
80
- @url = url
81
- @backend = backend.to_sym
82
-
83
- # Browser configuration (for Selenium)
84
- @browser = browser.to_sym
85
- @user_agent = args[:user_agent]
86
-
87
- # Form identification
88
- @form_name = args[:form_name]
89
- @form_number = args[:form_number] || 0
90
-
91
- # Field identification
92
- @username_field_name = args[:username_field_name]
93
- @username_field_number = args[:username_field_number] || 0
94
- @password_field_name = args[:password_field_name]
95
- @password_field_number = args[:password_field_number] || 1
96
-
97
- # Username configuration
98
- @username_hostname = args[:username_hostname]
99
- @username_is_email_address = args[:username_is_email_address] || false
100
-
101
- # Runtime configuration
102
- @debug = args[:debug] || false
103
- @verbose = args[:verbose] || false
104
- @iterations = args[:iterations] || 100
105
- @delay = args[:delay] || 0
106
- @word_list_path = args[:word_list_path] || '/usr/share/dict/words'
107
- end
108
-
109
- def random_user_agent
110
- AVAILABLE_USER_AGENTS.sample
111
- end
112
- end
113
- end
@@ -1,49 +0,0 @@
1
- # lib/Moby/RandomInputGenerator.rb
2
- # Moby::RandomInputGenerator
3
-
4
- class Moby
5
- class RandomInputGenerator
6
- TLD = %w{com net org edu int mil gov arpa biz aero name coop info pro museum}
7
-
8
- def random_username
9
- if username_is_email_address?
10
- if @username_hostname
11
- "#{random_word}@#{@username_hostname}"
12
- else
13
- "#{random_word}@#{random_word}.#{random_TLD}"
14
- end
15
- else
16
- random_word
17
- end
18
- end
19
-
20
- def random_password
21
- random_word
22
- end
23
-
24
- private
25
-
26
- def initialize(word_list_path:, username_hostname: nil, username_is_email_address: false)
27
- @word_list_path = word_list_path
28
- @username_hostname = username_hostname
29
- @username_is_email_address = username_is_email_address
30
- end
31
-
32
- def random_word
33
- words.sample
34
- end
35
-
36
- def words
37
- @words ||= File.readlines(@word_list_path).map(&:chomp).reject(&:empty?)
38
- end
39
- alias_method :load_words, :words
40
-
41
- def random_TLD
42
- TLD.sample
43
- end
44
-
45
- def username_is_email_address?
46
- @username_is_email_address
47
- end
48
- end
49
- end
@@ -1,18 +0,0 @@
1
- # Selenium/WebDriver/Driver/Attempt/attempt.rb
2
- # Selenium::WebDriver::Driver::Attempt.attempt
3
-
4
- # 20200418
5
- # 0.3.0
6
-
7
- # Examples:
8
- # 1. driver.attempt do |driver|
9
- # driver.get('https://example.com/users/sign_in')
10
- # enter_username
11
- # enter_password
12
- # sign_in
13
- # end
14
-
15
- # Changes:
16
- # 1. Moved all the logic into the Thoran namespace.
17
-
18
- require 'Thoran/Selenium/WebDriver/Driver/Attempt/attempt'
@@ -1,13 +0,0 @@
1
- # Selenium/WebDriver/SearchContext/ElementPresentQ/element_presentQ.rb
2
- # Selenium::WebDriver::SearchContext::ElementPresentQ.element_present?
3
-
4
- # 20200418
5
- # 0.3.0
6
-
7
- # Examples:
8
- # 1. driver.element_present?(:xpath, '//a[@id="submit"]')
9
-
10
- # Changes:
11
- # 1. Moved all the logic into the Thoran namespace.
12
-
13
- require 'Thoran/Selenium/WebDriver/SearchContext/ElementPresentQ/element_presentQ'
@@ -1,53 +0,0 @@
1
- # Thoran/Selenium/WebDriver/Attempt/attempt.rb
2
- # Thoran::Selenium::WebDriver::Attempt.attempt
3
-
4
- # 20200419
5
- # 0.0.1
6
-
7
- # Examples:
8
- # 1. driver.attempt do |driver|
9
- # driver.get('https://example.com/users/sign_in')
10
- # enter_username
11
- # enter_password
12
- # sign_in
13
- # end
14
-
15
- # Changes:
16
- # 1. + Thoran namespace.
17
-
18
- module Thoran
19
- module Selenium
20
- module WebDriver
21
- module Driver
22
- module Attempt
23
-
24
- def attempt(max_attempts = 3, &block)
25
- attempts = 0
26
- loop do
27
- begin
28
- yield
29
- break
30
- rescue Timeout::Error, ::Selenium::WebDriver::Error::UnknownError, ::Selenium::WebDriver::Error::NoSuchElementError => e
31
- attempts += 1
32
- if attempts >= max_attempts
33
- @driver.quit
34
- puts "Giving up after #{max_attempts} attempts to #{__method__} because #{e}."
35
- exit
36
- end
37
- end
38
- end
39
- end
40
-
41
- end
42
- end
43
- end
44
- end
45
- end
46
-
47
- module Selenium
48
- module WebDriver
49
- class Driver
50
- include Thoran::Selenium::WebDriver::Driver::Attempt
51
- end
52
- end
53
- end
@@ -1,39 +0,0 @@
1
- # Thoran/Selenium/WebDriver/SearchContext/ElementPresentQ/element_presentQ.rb
2
- # Thoran::Selenium::WebDriver::SearchContext::ElementPresentQ.element_present?
3
-
4
- # 20200418
5
- # 0.0.0
6
-
7
- # Examples:
8
- # 1. driver.element_present?(:xpath, '//a[@id="submit"]')
9
- # 2. driver.element_present?(:id, @logout_button_id)
10
-
11
- # Changes:
12
- # 1. + Thoran namespace.
13
-
14
- module Thoran
15
- module Selenium
16
- module WebDriver
17
- module SearchContext
18
- module ElementPresentQ
19
-
20
- def element_present?(selector_type, selector)
21
- bridge.find_element_by(selector_type, selector)
22
- true
23
- rescue ::Selenium::WebDriver::Error::NoSuchElementError
24
- false
25
- end
26
-
27
- end
28
- end
29
- end
30
- end
31
- end
32
-
33
- module Selenium
34
- module WebDriver
35
- class Driver
36
- include Thoran::Selenium::WebDriver::SearchContext::ElementPresentQ
37
- end
38
- end
39
- end