impostor 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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