impostor 0.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.
Files changed (53) hide show
  1. data/History.txt +4 -0
  2. data/Manifest.txt +50 -0
  3. data/README.txt +65 -0
  4. data/Rakefile +40 -0
  5. data/lib/impostor.rb +6 -0
  6. data/lib/www/impostor/phpbb2.rb +260 -0
  7. data/lib/www/impostor/wwf79.rb +254 -0
  8. data/lib/www/impostor/wwf80.rb +264 -0
  9. data/lib/www/impostor.rb +269 -0
  10. data/test/fixtures/phpbb2-get-new_topic-form-good-response.html +725 -0
  11. data/test/fixtures/phpbb2-get-viewtopic-for-new-topic-good-response.html +364 -0
  12. data/test/fixtures/phpbb2-get-viewtopic-for-new-topic-malformed-response.html +364 -0
  13. data/test/fixtures/phpbb2-index.html +361 -0
  14. data/test/fixtures/phpbb2-logged-in.html +349 -0
  15. data/test/fixtures/phpbb2-login.html +306 -0
  16. data/test/fixtures/phpbb2-not-logged-in.html +349 -0
  17. data/test/fixtures/phpbb2-post-new_topic-good-response.html +290 -0
  18. data/test/fixtures/phpbb2-post-reply-good-response.html +290 -0
  19. data/test/fixtures/phpbb2-post-reply-throttled-response.html +290 -0
  20. data/test/fixtures/phpbb2-too-many-posts.html +290 -0
  21. data/test/fixtures/wwf79-forum_posts.html +422 -0
  22. data/test/fixtures/wwf79-general-new-topic-error.html +46 -0
  23. data/test/fixtures/wwf79-general-posting-error.html +46 -0
  24. data/test/fixtures/wwf79-good-post-forum_posts.html +462 -0
  25. data/test/fixtures/wwf79-index.html +137 -0
  26. data/test/fixtures/wwf79-logged-in.html +46 -0
  27. data/test/fixtures/wwf79-login.html +123 -0
  28. data/test/fixtures/wwf79-new-topic-forum_posts-response.html +305 -0
  29. data/test/fixtures/wwf79-new-topic-post_message_form.html +212 -0
  30. data/test/fixtures/wwf79-not-logged-in.html +128 -0
  31. data/test/fixtures/wwf79-too-many-posts.html +46 -0
  32. data/test/fixtures/wwf79-too-many-topics.html +46 -0
  33. data/test/fixtures/wwf80-general-posting-error.html +54 -0
  34. data/test/fixtures/wwf80-get-new_topic-form-good-response.html +217 -0
  35. data/test/fixtures/wwf80-get-viewtopic-for-new-topic-good-response.html +290 -0
  36. data/test/fixtures/wwf80-index.html +371 -0
  37. data/test/fixtures/wwf80-logged-in.html +52 -0
  38. data/test/fixtures/wwf80-login.html +125 -0
  39. data/test/fixtures/wwf80-new_reply_form.html +204 -0
  40. data/test/fixtures/wwf80-not-logged-in.html +136 -0
  41. data/test/fixtures/wwf80-post-new_topic-good-response.html +293 -0
  42. data/test/fixtures/wwf80-post-reply-good-response.html +331 -0
  43. data/test/fixtures/wwf80-too-many-posts.html +54 -0
  44. data/test/test_helper.rb +38 -0
  45. data/test/test_www_impostor.rb +165 -0
  46. data/test/test_www_impostor_phpbb2.rb +536 -0
  47. data/test/test_www_impostor_wwf79.rb +535 -0
  48. data/test/test_www_impostor_wwf80.rb +535 -0
  49. data/vendor/plugins/impostor/lib/autotest/discover.rb +3 -0
  50. data/vendor/plugins/impostor/lib/autotest/impostor.rb +49 -0
  51. data.tar.gz.sig +3 -0
  52. metadata +156 -0
  53. metadata.gz.sig +3 -0
data/History.txt ADDED
@@ -0,0 +1,4 @@
1
+ == 0.0.1 / 2008-02-02
2
+
3
+ * 1 major enhancement
4
+ * Birthday!
data/Manifest.txt ADDED
@@ -0,0 +1,50 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ lib/impostor.rb
6
+ lib/www/impostor.rb
7
+ lib/www/impostor/phpbb2.rb
8
+ lib/www/impostor/wwf79.rb
9
+ lib/www/impostor/wwf80.rb
10
+ test/fixtures/phpbb2-get-new_topic-form-good-response.html
11
+ test/fixtures/phpbb2-get-viewtopic-for-new-topic-good-response.html
12
+ test/fixtures/phpbb2-get-viewtopic-for-new-topic-malformed-response.html
13
+ test/fixtures/phpbb2-index.html
14
+ test/fixtures/phpbb2-logged-in.html
15
+ test/fixtures/phpbb2-login.html
16
+ test/fixtures/phpbb2-not-logged-in.html
17
+ test/fixtures/phpbb2-post-new_topic-good-response.html
18
+ test/fixtures/phpbb2-post-reply-good-response.html
19
+ test/fixtures/phpbb2-post-reply-throttled-response.html
20
+ test/fixtures/phpbb2-too-many-posts.html
21
+ test/fixtures/wwf79-forum_posts.html
22
+ test/fixtures/wwf79-general-new-topic-error.html
23
+ test/fixtures/wwf79-general-posting-error.html
24
+ test/fixtures/wwf79-good-post-forum_posts.html
25
+ test/fixtures/wwf79-index.html
26
+ test/fixtures/wwf79-logged-in.html
27
+ test/fixtures/wwf79-login.html
28
+ test/fixtures/wwf79-new-topic-forum_posts-response.html
29
+ test/fixtures/wwf79-new-topic-post_message_form.html
30
+ test/fixtures/wwf79-not-logged-in.html
31
+ test/fixtures/wwf79-too-many-posts.html
32
+ test/fixtures/wwf79-too-many-topics.html
33
+ test/fixtures/wwf80-general-posting-error.html
34
+ test/fixtures/wwf80-get-new_topic-form-good-response.html
35
+ test/fixtures/wwf80-get-viewtopic-for-new-topic-good-response.html
36
+ test/fixtures/wwf80-index.html
37
+ test/fixtures/wwf80-logged-in.html
38
+ test/fixtures/wwf80-login.html
39
+ test/fixtures/wwf80-new_reply_form.html
40
+ test/fixtures/wwf80-not-logged-in.html
41
+ test/fixtures/wwf80-post-new_topic-good-response.html
42
+ test/fixtures/wwf80-post-reply-good-response.html
43
+ test/fixtures/wwf80-too-many-posts.html
44
+ test/test_helper.rb
45
+ test/test_www_impostor.rb
46
+ test/test_www_impostor_phpbb2.rb
47
+ test/test_www_impostor_wwf79.rb
48
+ test/test_www_impostor_wwf80.rb
49
+ vendor/plugins/impostor/lib/autotest/discover.rb
50
+ vendor/plugins/impostor/lib/autotest/impostor.rb
data/README.txt ADDED
@@ -0,0 +1,65 @@
1
+ impostor
2
+ by Mike Mondragon
3
+ http://impostor.rubyforge.org/
4
+
5
+ == DESCRIPTION:
6
+
7
+ imPOSTor posts messages to forums
8
+
9
+ == FEATURES/PROBLEMS:
10
+
11
+ Makes automatic posts to the following forum applications:
12
+
13
+ * Web Wiz Forums (WWF) 7.9
14
+ * Web Wiz Forums (WWF) 8.0
15
+ * PHP Bullitin Board (phpBB) 2.0 (2.0.22)
16
+
17
+ == SYNOPSIS:
18
+
19
+ # config yaml has options specefic to wwf79, wwf80, phpbb2, etc.
20
+ # read the impostor docs for options to the kind of forum in use
21
+ # config can be keyed by symbols or strings
22
+ config = YAML::load_file('conf/impostor.yml')
23
+ post = WWW::Impostor.new(config)
24
+ message = %q{hello world is to application
25
+ programmers as tea pots are to graphics programmers}
26
+ # your application stores forum and topic ids
27
+ post.post(forum=5,topic=10,message)
28
+ # make a new topic
29
+ subject = "about programmers..."
30
+ post.new_topic(forum=7,subject,message)
31
+ post.logout
32
+
33
+ == REQUIREMENTS:
34
+
35
+ * mechanize
36
+ * hpricot
37
+
38
+ == INSTALL:
39
+
40
+ * sudo gem install impostor
41
+
42
+ == LICENSE:
43
+
44
+ (The MIT License)
45
+
46
+ Copyright (c) 2008 Mike Mondragon
47
+
48
+ Permission is hereby granted, free of charge, to any person obtaining
49
+ a copy of this software and associated documentation files (the
50
+ 'Software'), to deal in the Software without restriction, including
51
+ without limitation the rights to use, copy, modify, merge, publish,
52
+ distribute, sublicense, and/or sell copies of the Software, and to
53
+ permit persons to whom the Software is furnished to do so, subject to
54
+ the following conditions:
55
+
56
+ The above copyright notice and this permission notice shall be
57
+ included in all copies or substantial portions of the Software.
58
+
59
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
60
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
61
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
62
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
63
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
64
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
65
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,40 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+ begin
6
+ require 'rcov/rcovtask'
7
+ rescue LoadError
8
+ end
9
+ require 'mechanize'
10
+ $LOAD_PATH.unshift 'lib'
11
+ require 'impostor'
12
+
13
+ Hoe.new('impostor', WWW::Impostor::VERSION) do |p|
14
+ p.rubyforge_name = 'impostor'
15
+ p.author = 'Mike Mondragon'
16
+ p.email = 'mikemondragon@gmail.com'
17
+ p.summary = 'imPOSTor posts messages to non-RESTful forums and blogs'
18
+ p.description = p.paragraphs_of('README.txt', 3..6).join("\n\n")
19
+ p.url = p.paragraphs_of('README.txt', 0).first.split(/\n/)[1..-1]
20
+ p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
21
+ p.extra_deps << ['hpricot', '>= 0.5.0']
22
+ p.extra_deps << ['mechanize', '>= 0.7.0']
23
+ p.clean_globs << 'coverage'
24
+ end
25
+
26
+ begin
27
+ Rcov::RcovTask.new do |t|
28
+ t.test_files = FileList['test/test_www_impostor*.rb']
29
+ t.verbose = true
30
+ end
31
+ rescue NameError
32
+ end
33
+
34
+ Rake::TestTask.new do |t|
35
+ t.libs << "test"
36
+ t.test_files = FileList['test/test_www_impostor*.rb']
37
+ t.verbose = true
38
+ end
39
+
40
+ # vim: syntax=Ruby
data/lib/impostor.rb ADDED
@@ -0,0 +1,6 @@
1
+ # Copyright (c) 2008 by Mike Mondragon (mikemondragon@gmail.com)
2
+ #
3
+ # Please see the LICENSE file for licensing.
4
+ #
5
+
6
+ require 'www/impostor'
@@ -0,0 +1,260 @@
1
+ require 'rubygems'
2
+ require 'hpricot'
3
+ gem 'mechanize', '>= 0.7.0'
4
+ require 'mechanize'
5
+ require 'cgi'
6
+
7
+ ##
8
+ # phpBB version of the Impostor
9
+ #
10
+
11
+ class WWW::Impostor
12
+
13
+ class Phpbb2 < WWW::Impostor
14
+
15
+ ##
16
+ # After initializing the parent a mechanize agent is created
17
+ #
18
+ # Additional configuration parameters:
19
+ #
20
+ # :posting_page
21
+ #
22
+ # Typical configuration parameters
23
+ # { :type => :phpbb2,
24
+ # :app_root => 'http://example.com/forum/',
25
+ # :login_page => 'login.php',
26
+ # :posting_page => 'posting.php',
27
+ # :user_agent => 'Windows IE 7',
28
+ # :username => 'myuser',
29
+ # :password => 'mypasswd' }
30
+
31
+ def initialize(config={})
32
+ super(config)
33
+ @agent = WWW::Mechanize.new
34
+ @agent.user_agent_alias = user_agent
35
+ # jar is a yaml file
36
+ @agent.cookie_jar.load(cookie_jar) if cookie_jar && File.exist?(cookie_jar)
37
+ @message = nil
38
+ @loggedin = false
39
+ end
40
+
41
+ ##
42
+ # clean up the state of the library and log out
43
+
44
+ def logout
45
+ return false unless @loggedin
46
+
47
+ @agent.cookie_jar.save_as(cookie_jar) if cookie_jar
48
+ save_topics
49
+
50
+ @forum = nil
51
+ @topic = nil
52
+ @message = nil
53
+
54
+ @loggedin = false
55
+ true
56
+ end
57
+
58
+ ##
59
+ # make a new topic
60
+
61
+ def new_topic(forum=@forum, subject=@subject, message=@message)
62
+ raise PostError.new("forum not set") unless forum
63
+ raise PostError.new("topic name not given") unless subject
64
+ raise PostError.new("message not set") unless message
65
+
66
+ login
67
+ raise PostError.new("not logged in") unless @loggedin
68
+
69
+ uri = posting_page
70
+ uri.query = "mode=newtopic&f=#{forum}"
71
+
72
+ # get the submit form
73
+ begin
74
+ page = @agent.get(uri)
75
+ rescue StandardError => err
76
+ raise PostError.new(err)
77
+ end
78
+
79
+ form = page.form('post') rescue nil
80
+ button = form.buttons.with.name('post').first rescue nil
81
+ raise PostError.new("post form not found") unless button && form
82
+
83
+ # set up the form and submit it
84
+ form.subject = subject
85
+ form.message = message
86
+ form['disable_html'] = nil
87
+ form['disable_bbcode'] = 'on'
88
+ form['disable_smilies'] = 'on'
89
+ begin
90
+ page = @agent.submit(form, button)
91
+ rescue StandardError => err
92
+ raise PostError.new(err)
93
+ end
94
+
95
+ # if the response is correct there will be a meta link that looks something like
96
+ # <meta http-equiv="refresh" content="3;url=viewtopic.php?p=29#29">
97
+ #
98
+ # this link needs to be followed, the page it leads to will give us
99
+ # the topic id that was created for the topic name that we created
100
+ a = (page.search("//meta[@http-equiv='refresh']").attr('content') rescue nil)
101
+ a = (/url=(.*)/.match(a)[1] rescue nil)
102
+ raise PostError.new('unexpected new topic response from refresh') unless a
103
+
104
+ a = URI.join(app_root, a)
105
+ page = @agent.get(a)
106
+ link = (page.search("//link[@rel='prev']").first['href'] rescue nil)
107
+ raise PostError.new('unexpected new topic response from link prev') unless link
108
+
109
+ # t=XXX will be our new topic id, i.e.
110
+ # <link rel="prev" href="http://localhost/phpBB2/viewtopic.php?t=5&amp;view=previous" title="View previous topic"
111
+ u = (URI.parse(link) rescue nil)
112
+ topic = (CGI::parse(u.query)['t'][0] rescue nil)
113
+ topic = topic.to_i
114
+ raise PostError.new('unexpected new topic ID') unless topic > 0
115
+
116
+ # save new topic id and topic name
117
+ add_subject(forum, topic, subject)
118
+ @forum=forum; @topic=topic; @subject=subject; @message=message
119
+ true
120
+ end
121
+
122
+ ##
123
+ # Attempt to post to the forum
124
+
125
+ def post(forum = @forum, topic = @topic, message = @message)
126
+ raise PostError.new("forum not set") unless forum
127
+ raise PostError.new("topic not set") unless topic
128
+ raise PostError.new("message not set") unless message
129
+
130
+ login
131
+ raise PostError.new("not logged in") unless @loggedin
132
+
133
+ uri = posting_page
134
+ uri.query = "mode=reply&t=#{topic}"
135
+
136
+ # get the submit form
137
+ begin
138
+ page = @agent.get(uri)
139
+ rescue StandardError => err
140
+ raise PostError.new(err)
141
+ end
142
+
143
+ form = page.form('post') rescue nil
144
+ button = form.buttons.with.name('post').first rescue nil
145
+ raise PostError.new("post form not found") unless button && form
146
+
147
+ # set up the form and submit it
148
+ form.message = message
149
+ form['disable_html'] = nil
150
+ form['disable_bbcode'] = 'on'
151
+ form['disable_smilies'] = 'on'
152
+ begin
153
+ page = @agent.submit(form, button)
154
+ rescue StandardError => err
155
+ raise PostError.new(err)
156
+ end
157
+
158
+ mes = page.search("//span[@class='gen']").last
159
+ posted = mes.innerText =~ /Your message has been entered successfully./ rescue false
160
+ if posted
161
+ @forum=forum; @topic=topic; @subject=get_subject(forum,topic); @message=message
162
+ return true
163
+ end
164
+
165
+ too_many = (mes.innerText =~
166
+ /You cannot make another post so soon after your last; please try again in a short while./ rescue
167
+ false)
168
+ raise ThrottledError.new("too many posts in too short amount of time") if too_many
169
+
170
+ # false otherwise, should we raise an exception instead?
171
+ false
172
+ end
173
+
174
+ ##
175
+ # Get the posting page for the application (specific to phpBB2)
176
+
177
+ def posting_page
178
+ URI.join(app_root, config[:posting_page])
179
+ end
180
+
181
+ ##
182
+ # does the work of logging into phpbb
183
+
184
+ def login
185
+ return true if @loggedin
186
+
187
+ # get the login page
188
+ page = fetch_login_page
189
+
190
+ # return if we are already logged in from a cookie state
191
+ return true if logged_in?(page)
192
+
193
+ # setup the form and submit
194
+ form, button = login_form_and_button(page)
195
+ page = post_login(form, button)
196
+
197
+ # set up the rest of the state if we are logged in
198
+ @loggedin = logged_in?(page)
199
+ load_topics if @loggedin
200
+
201
+ @loggedin
202
+ end
203
+
204
+ def version
205
+ @version ||= self.class.to_s
206
+ end
207
+
208
+ protected
209
+
210
+ ##
211
+ # does the work of posting the login form
212
+
213
+ def post_login(form, button)
214
+ begin
215
+ page = @agent.submit(form, button)
216
+ rescue StandardError => err
217
+ raise LoginError.new(err)
218
+ end
219
+ end
220
+
221
+ ##
222
+ # returns the login form and its button from the login page
223
+
224
+ def login_form_and_button(page)
225
+ form = page.forms.first rescue nil
226
+ raise LoginError.new("unknown login page format") unless form
227
+
228
+ button = page.forms.first.buttons.with.name('login').first
229
+ form['username'] = username
230
+ form['password'] = password
231
+ form['autologin'] = 'on'
232
+
233
+ return form, button
234
+ end
235
+
236
+ ##
237
+ # fetches the login page
238
+
239
+ def fetch_login_page
240
+ begin
241
+ page = @agent.get(login_page)
242
+ rescue StandardError => err
243
+ raise LoginError.new(err)
244
+ end
245
+ end
246
+
247
+ ##
248
+ # Checks if the agent is already logged by stored cookie
249
+
250
+ def logged_in?(page)
251
+ mm = page.search("//a[@class='mainmenu']")
252
+ return false unless mm
253
+ mm.each do |m|
254
+ return true if (m.innerText =~ /Log out \[ #{username} \]/ rescue false)
255
+ end
256
+ false
257
+ end
258
+
259
+ end
260
+ end
@@ -0,0 +1,254 @@
1
+ require 'rubygems'
2
+ require 'hpricot'
3
+ gem 'mechanize', '>= 0.7.0'
4
+ require 'mechanize'
5
+ require 'cgi'
6
+
7
+ ##
8
+ # Web Wiz Forums version 7.9 of the Impostor
9
+ #
10
+
11
+ class WWW::Impostor
12
+
13
+ class Wwf79 < WWW::Impostor
14
+
15
+ ##
16
+ # After initializing the parent a mechanize agent is created
17
+ #
18
+ # Additional configuration parameters:
19
+ #
20
+ # :forum_posts_page
21
+ # :post_message_page
22
+ #
23
+ # Typical configuration parameters
24
+ # { :type => :wwf79,
25
+ # :app_root => 'http://example.com/forum/',
26
+ # :login_page => 'login_user.asp',
27
+ # :forum_posts_page => 'forum_posts.asp',
28
+ # :post_message_page => 'post_message_form.asp'
29
+ # :user_agent => 'Windows IE 7',
30
+ # :username => 'myuser',
31
+ # :password => 'mypasswd' }
32
+
33
+ def initialize(config={})
34
+ super(config)
35
+ @agent = WWW::Mechanize.new
36
+ @agent.user_agent_alias = user_agent
37
+ @agent.cookie_jar.load(cookie_jar) if cookie_jar && File.exist?(cookie_jar)
38
+ @message = nil
39
+ @loggedin = false
40
+ end
41
+
42
+ ##
43
+ # clean up the state of the library and log out
44
+
45
+ def logout
46
+ return false unless @loggedin
47
+
48
+ @agent.cookie_jar.save_as(cookie_jar) if cookie_jar
49
+ save_topics
50
+
51
+ @forum = nil
52
+ @topic = nil
53
+ @message = nil
54
+
55
+ @loggedin = false
56
+ true
57
+ end
58
+
59
+ ##
60
+ # create a new topic
61
+
62
+ def new_topic(forum=@forum, subject=@subject, message=@message)
63
+ raise PostError.new("forum not set") unless forum
64
+ raise PostError.new("topic name not given") unless subject
65
+ raise PostError.new("message not set") unless message
66
+
67
+ login
68
+ raise PostError.new("not logged in") unless @loggedin
69
+
70
+ uri = post_message_page
71
+ uri.query = "FID=#{forum}"
72
+
73
+ # get the submit form
74
+ begin
75
+ page = @agent.get(uri)
76
+ rescue StandardError => err
77
+ raise PostError.new(err)
78
+ end
79
+ form = page.form('frmAddMessage') rescue nil
80
+ button = form.buttons.with.name('Submit').first rescue nil
81
+ raise PostError.new("post form not found") unless button && form
82
+
83
+ # set up the form and submit it
84
+ form.subject = subject
85
+ form.message = message
86
+ begin
87
+ page = @agent.submit(form, button)
88
+ rescue StandardError => err
89
+ raise PostError.new(err)
90
+ end
91
+
92
+ error = page.body =~ /Message Not Posted/
93
+ if error
94
+
95
+ # throttled
96
+ throttled = "You have exceeded the number of posts permitted in the time span"
97
+ too_many = page.body =~ /#{throttled}/
98
+ raise ThrottledError.new(throttled) if too_many
99
+
100
+ # general error
101
+ raise PostError.new("There was an error creating the topic")
102
+ end
103
+
104
+ # look up the new topic id
105
+ form = page.form('frmAddMessage') rescue nil
106
+ topic = form['TID'].to_i rescue 0
107
+ raise PostError.new('unexpected new topic ID') if topic < 1
108
+
109
+ # save new topic id and topic name
110
+ add_subject(forum, topic, subject)
111
+ @forum=forum; @topic=topic; @subject=subject; @message=message
112
+ return true
113
+ end
114
+
115
+ ##
116
+ # Attempt to post to the forum
117
+
118
+ def post(forum = @forum, topic = @topic, message = @message)
119
+ raise PostError.new("forum not set") unless forum
120
+ raise PostError.new("topic not set") unless topic
121
+ raise PostError.new("message not set") unless message
122
+
123
+ login
124
+ raise PostError.new("not logged in") unless @loggedin
125
+
126
+ uri = forum_posts_page
127
+ uri.query = "TID=#{topic}&TPN=10000"
128
+
129
+ # get the submit form
130
+ begin
131
+ page = @agent.get(uri)
132
+ rescue StandardError => err
133
+ raise PostError.new(err)
134
+ end
135
+ form = page.form('frmAddMessage') rescue nil
136
+ button = form.buttons.with.name('Submit').first rescue nil
137
+ raise PostError.new("post form not found") unless button && form
138
+
139
+ # set up the form and submit it
140
+ form.message = message
141
+ begin
142
+ page = @agent.submit(form, button)
143
+ rescue StandardError => err
144
+ raise PostError.new(err)
145
+ end
146
+
147
+ error = page.body =~ /Message Not Posted/
148
+ if error
149
+
150
+ # throttled
151
+ throttled = "You have exceeded the number of posts permitted in the time span"
152
+ too_many = page.body =~ /#{throttled}/
153
+ raise ThrottledError.new(throttled) if too_many
154
+
155
+ # general error
156
+ raise PostError.new("There was an error making the post")
157
+ end
158
+
159
+ @forum=forum; @topic=topic; @subject=get_subject(forum,topic); @message=message
160
+ return true
161
+ end
162
+
163
+ ##
164
+ # Get the new posts page for the application (specific to WWF7.9)
165
+
166
+ def forum_posts_page
167
+ URI.join(app_root, config[:forum_posts_page])
168
+ end
169
+
170
+ ##
171
+ # Get the new topic page for the application (specific to WWF7.9)
172
+
173
+ def post_message_page
174
+ URI.join(app_root, config[:post_message_page])
175
+ end
176
+
177
+ ##
178
+ # does the work of logging into WWF 7.9
179
+
180
+ def login
181
+ return true if @loggedin
182
+
183
+ # get the login page
184
+ page = fetch_login_page
185
+
186
+ # return if we are already logged in from a cookie state
187
+ return true if logged_in?(page)
188
+
189
+ # setup the form and submit
190
+ form, button = login_form_and_button(page)
191
+ page = post_login(form, button)
192
+
193
+ # set up the rest of the state if we are logged in
194
+ @loggedin = logged_in?(page)
195
+ load_topics if @loggedin
196
+
197
+ @loggedin
198
+ end
199
+
200
+ def version
201
+ @version ||= self.class.to_s
202
+ end
203
+
204
+ protected
205
+
206
+ ##
207
+ # does the work of posting the login form
208
+
209
+ def post_login(form, button)
210
+ begin
211
+ page = @agent.submit(form, button)
212
+ rescue StandardError => err
213
+ raise LoginError.new(err)
214
+ end
215
+ end
216
+
217
+ ##
218
+ # returns the login form and its button from the login page
219
+
220
+ def login_form_and_button(page)
221
+ form = page.forms.with.name('frmLogin').first rescue nil
222
+ raise LoginError.new("unknown login page format") unless form
223
+
224
+ button = WWW::Mechanize::Form::Button.new('Submit', 'Forum Login')
225
+ form.add_button_to_query(button)
226
+ form['name'] = username
227
+ form['password'] = password
228
+ return form, button
229
+ end
230
+
231
+ ##
232
+ # fetches the login page
233
+
234
+ def fetch_login_page
235
+ begin
236
+ page = @agent.get(login_page)
237
+ rescue StandardError => err
238
+ raise LoginError.new(err)
239
+ end
240
+ end
241
+
242
+ ##
243
+ # Checks if the agent is already logged by stored cookie
244
+
245
+ def logged_in?(page)
246
+ mm = page.search("//a[@class='nav']")
247
+ return false unless mm
248
+ mm.each do |m|
249
+ return true if (m.innerText =~ /Logout \[#{username}\]/ rescue false)
250
+ end
251
+ false
252
+ end
253
+ end
254
+ end