impostor 0.0.1 → 0.1.0

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.
data/History.txt CHANGED
@@ -1,4 +1,10 @@
1
- == 0.0.1 / 2008-02-02
1
+ ### 0.2.0 / 2008-07-30 (don't use this code for spam)
2
+
3
+ * 1 minor enhancement:
4
+ * support for phpBB3
5
+
6
+ ### 0.0.1 / 2008-02-02
2
7
 
3
8
  * 1 major enhancement
4
9
  * Birthday!
10
+
data/Manifest.txt CHANGED
@@ -5,6 +5,7 @@ Rakefile
5
5
  lib/impostor.rb
6
6
  lib/www/impostor.rb
7
7
  lib/www/impostor/phpbb2.rb
8
+ lib/www/impostor/phpbb3.rb
8
9
  lib/www/impostor/wwf79.rb
9
10
  lib/www/impostor/wwf80.rb
10
11
  test/fixtures/phpbb2-get-new_topic-form-good-response.html
@@ -18,6 +19,13 @@ test/fixtures/phpbb2-post-new_topic-good-response.html
18
19
  test/fixtures/phpbb2-post-reply-good-response.html
19
20
  test/fixtures/phpbb2-post-reply-throttled-response.html
20
21
  test/fixtures/phpbb2-too-many-posts.html
22
+ test/fixtures/phpbb3-get-new-topic-form-good-response.html
23
+ test/fixtures/phpbb3-get-reply-form-good-response.html
24
+ test/fixtures/phpbb3-logged-in.html
25
+ test/fixtures/phpbb3-login.html
26
+ test/fixtures/phpbb3-not-logged-in.html
27
+ test/fixtures/phpbb3-post-new_topic-good-response.html
28
+ test/fixtures/phpbb3-post-reply-good-response.html
21
29
  test/fixtures/wwf79-forum_posts.html
22
30
  test/fixtures/wwf79-general-new-topic-error.html
23
31
  test/fixtures/wwf79-general-posting-error.html
@@ -44,6 +52,7 @@ test/fixtures/wwf80-too-many-posts.html
44
52
  test/test_helper.rb
45
53
  test/test_www_impostor.rb
46
54
  test/test_www_impostor_phpbb2.rb
55
+ test/test_www_impostor_phpbb3.rb
47
56
  test/test_www_impostor_wwf79.rb
48
57
  test/test_www_impostor_wwf80.rb
49
58
  vendor/plugins/impostor/lib/autotest/discover.rb
data/README.txt CHANGED
@@ -8,16 +8,18 @@ imPOSTor posts messages to forums
8
8
 
9
9
  == FEATURES/PROBLEMS:
10
10
 
11
- Makes automatic posts to the following forum applications:
11
+ Makes automated posts to the following forum applications:
12
12
 
13
13
  * Web Wiz Forums (WWF) 7.9
14
14
  * Web Wiz Forums (WWF) 8.0
15
15
  * PHP Bullitin Board (phpBB) 2.0 (2.0.22)
16
+ * PHP Bullitin Board (phpBB) 3.0
16
17
 
17
18
  == SYNOPSIS:
18
19
 
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
20
+ # config yaml has options specific to wwf79, phpbb2, etc.
21
+ # Read the impostor docs for configuration options for the kind of forum to
22
+ # be accessed.
21
23
  # config can be keyed by symbols or strings
22
24
  config = YAML::load_file('conf/impostor.yml')
23
25
  post = WWW::Impostor.new(config)
@@ -35,6 +37,11 @@ post.logout
35
37
  * mechanize
36
38
  * hpricot
37
39
 
40
+ == SOURCE
41
+
42
+ git clone git://github.com/monde/impostor.git
43
+ svn co svn://rubyforge.org/var/svn/impostor/trunk impostor
44
+
38
45
  == INSTALL:
39
46
 
40
47
  * sudo gem install impostor
data/Rakefile CHANGED
@@ -15,7 +15,7 @@ Hoe.new('impostor', WWW::Impostor::VERSION) do |p|
15
15
  p.author = 'Mike Mondragon'
16
16
  p.email = 'mikemondragon@gmail.com'
17
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")
18
+ p.description = p.paragraphs_of('README.txt', 2..5).join("\n\n")
19
19
  p.url = p.paragraphs_of('README.txt', 0).first.split(/\n/)[1..-1]
20
20
  p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
21
21
  p.extra_deps << ['hpricot', '>= 0.5.0']
@@ -5,7 +5,7 @@ require 'mechanize'
5
5
  require 'cgi'
6
6
 
7
7
  ##
8
- # phpBB version of the Impostor
8
+ # phpBB2 version of the Impostor
9
9
  #
10
10
 
11
11
  class WWW::Impostor
@@ -248,12 +248,10 @@ class WWW::Impostor
248
248
  # Checks if the agent is already logged by stored cookie
249
249
 
250
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
251
+ mm = page.search( "//a" ).detect{|a| a.inner_html =~ /Log out \[ #{username} \]/i}
252
+ mm ||= page.search( "//a" ).detect{|a| a['href'] =~ /\/login\.php\?logout=true/}
253
+
254
+ mm.nil? ? false : true
257
255
  end
258
256
 
259
257
  end
@@ -0,0 +1,236 @@
1
+ require 'rubygems'
2
+ require 'hpricot'
3
+ gem 'mechanize', '>= 0.7.0'
4
+ require 'mechanize'
5
+ require 'cgi'
6
+
7
+ ##
8
+ # phpBB3 version of the Impostor
9
+ #
10
+
11
+ class WWW::Impostor
12
+
13
+ class Phpbb3 < 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 => :phpbb3,
24
+ # :app_root => 'http://example.com/forum/',
25
+ # :login_page => 'ucp.php?mode=login',
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=post&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('postform') rescue nil
80
+ raise PostError.new("post form not found") unless form
81
+ button = form.buttons.detect{|b| b.name == 'post'}
82
+ raise PostError.new("post form button not found") unless button
83
+
84
+ # set up the form and submit it
85
+ form['subject'] = subject
86
+ form['message'] = message
87
+ form['lastclick'] = (form['lastclick'].to_i - 60).to_s
88
+
89
+ begin
90
+ page = @agent.submit(form, button)
91
+ rescue StandardError => err
92
+ raise PostError.new(err)
93
+ end
94
+
95
+ # new topic will be current page uri since phpbb3 will 302 to the new
96
+ # topic page, e.g.
97
+ # http://example.com/forum/viewtopic.php?f=37&t=52
98
+ topic = page.uri.query.split('&').detect{|a| a =~ /^t=/}.split('=').last.to_i rescue 0
99
+ raise PostError.new('unexpected new topic ID') unless topic > 0
100
+
101
+ # save new topic id and topic name
102
+ add_subject(forum, topic, subject)
103
+ @forum=forum; @topic=topic; @subject=subject; @message=message
104
+ true
105
+ end
106
+
107
+ ##
108
+ # Attempt to post to the forum
109
+
110
+ def post(forum = @forum, topic = @topic, message = @message)
111
+ raise PostError.new("forum not set") unless forum
112
+ raise PostError.new("topic not set") unless topic
113
+ raise PostError.new("message not set") unless message
114
+
115
+ login
116
+ raise PostError.new("not logged in") unless @loggedin
117
+
118
+ uri = posting_page
119
+ uri.query = "mode=reply&f=#{forum}&t=#{topic}"
120
+
121
+ # get the submit form
122
+ begin
123
+ page = @agent.get(uri)
124
+ rescue StandardError => err
125
+ raise PostError.new(err)
126
+ end
127
+
128
+ form = page.form('postform') rescue nil
129
+ button = form.buttons.with.name('post').first rescue nil
130
+ raise PostError.new("post form not found") unless button && form
131
+
132
+ # set up the form and submit it
133
+ form.message = message
134
+ form['lastclick'] = (form['lastclick'].to_i - 60).to_s
135
+
136
+ begin
137
+ page = @agent.submit(form, button)
138
+ rescue StandardError => err
139
+ raise PostError.new(err)
140
+ end
141
+
142
+ # new post will be in current page uri since phpbb3 will 302 to the new
143
+ # post page post anchor, e.g.
144
+ # http://example.com/forum/viewtopic.php?f=37&t=52&p=3725#p3725
145
+ postid = page.uri.query.split('&').detect{|a| a =~ /^p=/}.split('=').last.to_i rescue 0
146
+ raise PostError.new("message did not post") unless postid > 0
147
+
148
+ @forum=forum; @topic=topic; @subject=get_subject(forum,topic); @message=message
149
+
150
+ true
151
+ end
152
+
153
+ ##
154
+ # Get the posting page for the application (specific to phpBB3)
155
+
156
+ def posting_page
157
+ URI.join(app_root, config[:posting_page])
158
+ end
159
+
160
+ ##
161
+ # does the work of logging into phpbb
162
+
163
+ def login
164
+ return true if @loggedin
165
+
166
+ # get the login page
167
+ page = fetch_login_page
168
+
169
+ # return if we are already logged in from a cookie state
170
+ return true if logged_in?(page)
171
+
172
+ # setup the form and submit
173
+ form, button = login_form_and_button(page)
174
+ page = post_login(form, button)
175
+
176
+ # set up the rest of the state if we are logged in
177
+ @loggedin = logged_in?(page)
178
+ load_topics if @loggedin
179
+
180
+ @loggedin
181
+ end
182
+
183
+ def version
184
+ @version ||= self.class.to_s
185
+ end
186
+
187
+ protected
188
+ ##
189
+ # does the work of posting the login form
190
+
191
+ def post_login(form, button)
192
+ begin
193
+ page = @agent.submit(form, button)
194
+ rescue StandardError => err
195
+ raise LoginError.new(err)
196
+ end
197
+ end
198
+
199
+ ##
200
+ # returns the login form and its button from the login page
201
+
202
+ def login_form_and_button(page)
203
+ form = page.forms.first rescue nil
204
+ raise LoginError.new("unknown login page format") unless form
205
+
206
+ button = form.buttons.with.name('login').first
207
+ form['username'] = username
208
+ form['password'] = password
209
+ form['autologin'] = 'on'
210
+
211
+ return form, button
212
+ end
213
+
214
+ ##
215
+ # fetches the login page
216
+
217
+ def fetch_login_page
218
+ begin
219
+ page = @agent.get(login_page)
220
+ rescue StandardError => err
221
+ raise LoginError.new(err)
222
+ end
223
+ end
224
+
225
+ ##
226
+ # Checks if the agent is already logged by stored cookie
227
+
228
+ def logged_in?(page)
229
+ mm = page.search( "//a" ).detect{|a| a.inner_html =~ /Logout \[ #{username} \]/}
230
+ mm ||= page.search( "//a" ).detect{|a| a['href'] =~ /\.\/ucp.php\?mode=logout/}
231
+
232
+ mm.nil? ? false : true
233
+ end
234
+
235
+ end
236
+ end
data/lib/www/impostor.rb CHANGED
@@ -51,7 +51,7 @@ module WWW
51
51
  ##
52
52
  # Gem version of Impostor
53
53
 
54
- VERSION = '0.0.1'
54
+ VERSION = '0.1.0'
55
55
 
56
56
  ##
57
57
  # An application error