ronin-web 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,3 +1,13 @@
1
+ === 0.1.2 / 2009-03-28
2
+
3
+ * Added Ronin::Web::Proxy.
4
+ * Added diagnostic messages to Ronin::Web::Spider.
5
+ * Fixed Rack 0.9.1 compatibility bugs in Ronin::Web::Server.
6
+ * Server#response now uses Rack::Response.
7
+ * Ronin::Web::Server now uses a Rack::Request object instead of the
8
+ standard env Hash.
9
+ * Updated specs for Ronin::Web::Server.
10
+
1
11
  === 0.1.1 / 2009-02-23
2
12
 
3
13
  * Added a git style sub-command (<tt>ronin-web</tt>) which starts the Ronin
data/Manifest.txt CHANGED
@@ -14,6 +14,7 @@ lib/ronin/web/extensions/nokogiri/xml/attr.rb
14
14
  lib/ronin/web/extensions/nokogiri/xml/element.rb
15
15
  lib/ronin/web/extensions/nokogiri/xml/document.rb
16
16
  lib/ronin/web/server.rb
17
+ lib/ronin/web/proxy.rb
17
18
  lib/ronin/web/spider.rb
18
19
  lib/ronin/web/web.rb
19
20
  lib/ronin/web/version.rb
data/README.txt CHANGED
@@ -41,8 +41,9 @@ of Ronin.
41
41
 
42
42
  * Web access (utilizing Mechanize and Nokogiri).
43
43
  * Integrates Spidr into Ronin::Web::Spider.
44
- * Provides Ronin::Web::Server, a customizable Rack web server that supports
45
- path and host-name routing.
44
+ * Provides Ronin::Web::Server, a customizable Rack based Web Server that
45
+ supports path and host-name routing.
46
+ * Provides Ronin::Web::Proxy, a configurable Rack based Web Proxy.
46
47
 
47
48
  == REQUIREMENTS:
48
49
 
@@ -50,7 +51,7 @@ of Ronin.
50
51
  * {mechanize}[http://mechanize.rubyforge.org/] >= 0.9.0
51
52
  * {spidr}[http://spidr.rubyforge.org/] >= 0.1.3
52
53
  * {rack}[http://rack.rubyforge.org/] >= 0.9.1
53
- * {ronin}[http://ronin.rubyforge.org/] >= 0.1.4
54
+ * {ronin}[http://ronin.rubyforge.org/] >= 0.2.2
54
55
 
55
56
  == INSTALL:
56
57
 
data/Rakefile CHANGED
@@ -14,7 +14,7 @@ Hoe.new('ronin-web', Ronin::Web::VERSION) do |p|
14
14
  ['mechanize', '>=0.9.0'],
15
15
  ['spidr', '>=0.1.3'],
16
16
  ['rack', '>=0.9.1'],
17
- ['ronin', '>=0.2.1']
17
+ ['ronin', '>=0.2.2']
18
18
  ]
19
19
  end
20
20
 
data/bin/ronin-web CHANGED
@@ -2,6 +2,11 @@
2
2
 
3
3
  require 'rubygems'
4
4
 
5
+ lib_dir = File.expand_path(File.join(File.dirname(__FILE__),'..','lib'))
6
+ unless $LOAD_PATH.include?(lib_dir)
7
+ $LOAD_PATH << lib_dir
8
+ end
9
+
5
10
  require 'ronin/ui/command_line/commands/console'
6
11
  require 'ronin/ui/console'
7
12
 
@@ -0,0 +1,124 @@
1
+ #
2
+ #--
3
+ # Ronin Web - A Ruby library for Ronin that provides support for web
4
+ # scraping and spidering functionality.
5
+ #
6
+ # Copyright (c) 2006-2009 Hal Brodigan (postmodern.mod3 at gmail.com)
7
+ #
8
+ # This program is free software; you can redistribute it and/or modify
9
+ # it under the terms of the GNU General Public License as published by
10
+ # the Free Software Foundation; either version 2 of the License, or
11
+ # (at your option) any later version.
12
+ #
13
+ # This program is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU General Public License
19
+ # along with this program; if not, write to the Free Software
20
+ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
+ #++
22
+ #
23
+
24
+ require 'ronin/web/server'
25
+ require 'ronin/network/http'
26
+
27
+ require 'net/http'
28
+
29
+ module Ronin
30
+ module Web
31
+ class Proxy < Server
32
+
33
+ # The default HTTP Request to use
34
+ DEFAULT_HTTP_REQUEST = Net::HTTP::Get
35
+
36
+ #
37
+ # Creates a new Web Proxy using the given configuration _block_.
38
+ #
39
+ # _options_ may contain the following keys:
40
+ # <tt>:host</tt>:: The host to bind to.
41
+ # <tt>:port</tt>:: The port to listen on.
42
+ # <tt>:config</tt>:: A +Hash+ of configurable variables to be used
43
+ # in responses.
44
+ #
45
+ def initialize(options={},&block)
46
+ super(options)
47
+
48
+ @default = method(:proxy)
49
+
50
+ instance_eval(&block) if block
51
+ end
52
+
53
+ #
54
+ # Proxies the specified Rack _request_ and returns a corresponding
55
+ # Rack response.
56
+ #
57
+ def proxy(request)
58
+ server_response = http_response(request)
59
+ server_headers = server_response.to_hash
60
+ body = (server_response.body || '')
61
+
62
+ return response(body,server_headers)
63
+ end
64
+
65
+ protected
66
+
67
+ #
68
+ # Returns the Net::HTTP Request class that represents the specified
69
+ # HTTP _request_method_.
70
+ #
71
+ # http_class('POST')
72
+ # # => Net::HTTP::Post
73
+ #
74
+ def http_class(request_method)
75
+ http_method = request_method.downcase.capitalize
76
+ http_class = DEFAULT_HTTP_REQUEST
77
+
78
+ if Net::HTTP.const_defined?(http_method)
79
+ http_class = Net::HTTP.const_get(http_method)
80
+
81
+ unless http_class.kind_of?(Net::HTTPRequest)
82
+ http_class = DEFAULT_HTTP_REQUEST
83
+ end
84
+ end
85
+
86
+ return http_class
87
+ end
88
+
89
+ #
90
+ # Converts the Rack headers within the specified _request_ to
91
+ # Net::HTTP formatted HTTP headers.
92
+ #
93
+ def http_headers(request)
94
+ client_headers = {}
95
+
96
+ request.env.each do |name,value|
97
+ if name =~ /^HTTP_/
98
+ header_name = name.gsub(/^HTTP_/,'').split('_').map { |word|
99
+ word.capitalize
100
+ }.join('-')
101
+
102
+ client_headers[header_name] = value
103
+ end
104
+ end
105
+
106
+ return client_headers
107
+ end
108
+
109
+ #
110
+ # Returns the Net::HTTP response for the specified Rack _request_.
111
+ #
112
+ def http_response(request)
113
+ path = request.fullpath
114
+ http_method = http_class(request.request_method)
115
+ client_request = http_method.new(path,http_headers(request))
116
+
117
+ Net.http_session(:host => request.host, :port => request.port) do |http|
118
+ return http.request(client_request)
119
+ end
120
+ end
121
+
122
+ end
123
+ end
124
+ end
@@ -206,8 +206,8 @@ module Ronin
206
206
  #
207
207
  # Returns the HTTP 404 Not Found message for the requested path.
208
208
  #
209
- def not_found(env)
210
- path = env['PATH_INFO']
209
+ def not_found(request)
210
+ path = request.path_info
211
211
  body = %{<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
212
212
  <html>
213
213
  <head>
@@ -228,14 +228,14 @@ module Ronin
228
228
  # an index file. If no index file can be found or _path_ points to a
229
229
  # non-existant file, a "404 Not Found" response will be returned.
230
230
  #
231
- def return_file(path,env)
231
+ def return_file(path,request)
232
232
  if !(File.exists?(path))
233
- return not_found(env)
233
+ return not_found(request)
234
234
  end
235
235
 
236
236
  if File.directory?(path)
237
237
  unless (path = index_of(path))
238
- return not_found(env)
238
+ return not_found(request)
239
239
  end
240
240
  end
241
241
 
@@ -251,8 +251,8 @@ module Ronin
251
251
  #
252
252
  # response("<data>lol</data>", :content_type => 'text/xml')
253
253
  #
254
- def response(body=[],options={},&block)
255
- status = (options.delete(:status) || 200)
254
+ def response(body='',options={},&block)
255
+ status = (options.delete(:status) || options.delete('Status') || 200)
256
256
  headers = {}
257
257
 
258
258
  options.each do |name,value|
@@ -263,7 +263,7 @@ module Ronin
263
263
  headers[header_name] = value.to_s
264
264
  end
265
265
 
266
- return Rack::Response.new(body,status,headers,&block)
266
+ return Rack::Response.new(body,status,headers,&block).finish
267
267
  end
268
268
 
269
269
  #
@@ -288,7 +288,7 @@ module Ronin
288
288
  # Use the given _server_ or _block_ as the default route for all
289
289
  # other requests.
290
290
  #
291
- # default do |env|
291
+ # default do |request|
292
292
  # [200, {'Content-Type' => 'text/html'}, 'lol train']
293
293
  # end
294
294
  #
@@ -302,7 +302,7 @@ module Ronin
302
302
  # requests to host names which match the specified _pattern_.
303
303
  #
304
304
  # hosts_like(/^a[0-9]\./) do
305
- # map('/download/') do |env|
305
+ # map('/download/') do |request|
306
306
  # ...
307
307
  # end
308
308
  # end
@@ -315,7 +315,7 @@ module Ronin
315
315
  # Registers the given _server_ or _block_ to be called when receiving
316
316
  # requests for paths which match the specified _pattern_.
317
317
  #
318
- # paths_like(/\.xml$/) do |env|
318
+ # paths_like(/\.xml$/) do |request|
319
319
  # ...
320
320
  # end
321
321
  #
@@ -340,7 +340,7 @@ module Ronin
340
340
  #
341
341
  # Binds the specified URL _path_ to the given _server_ or _block_.
342
342
  #
343
- # bind '/secrets.xml' do |env|
343
+ # bind '/secrets.xml' do |request|
344
344
  # [200, {'Content-Type' => 'text/xml'}, "Made you look."]
345
345
  # end
346
346
  #
@@ -353,7 +353,7 @@ module Ronin
353
353
  # Binds the specified URL directory _path_ to the given
354
354
  # _server_ or _block_.
355
355
  #
356
- # map '/downloads' do |env|
356
+ # map '/downloads' do |request|
357
357
  # response(
358
358
  # "Your somewhere inside the downloads directory",
359
359
  # :content_type' => 'text/xml'
@@ -375,11 +375,11 @@ module Ronin
375
375
  file = File.expand_path(file)
376
376
  content_type = (options[:content_type] || content_type_for(file))
377
377
 
378
- bind(path) do |env|
378
+ bind(path) do |request|
379
379
  if File.file?(file)
380
- return_file(file,env)
380
+ return_file(file,request)
381
381
  else
382
- not_found(env)
382
+ not_found(request)
383
383
  end
384
384
  end
385
385
  end
@@ -394,14 +394,14 @@ module Ronin
394
394
  sub_dirs = path.split('/')
395
395
  directory = File.expand_path(directory)
396
396
 
397
- map(path) do |env|
398
- http_path = File.expand_path(env['PATH_INFO'])
397
+ map(path) do |request|
398
+ http_path = File.expand_path(request.path_info)
399
399
  http_dirs = http_path.split('/')
400
400
 
401
401
  sub_path = http_dirs[sub_dirs.length..-1].join('/')
402
402
  absolute_path = File.join(directory,sub_path)
403
403
 
404
- return_file(absolute_path,env)
404
+ return_file(absolute_path,request)
405
405
  end
406
406
  end
407
407
 
@@ -419,6 +419,7 @@ module Ronin
419
419
  def call(env)
420
420
  http_host = env['HTTP_HOST']
421
421
  http_path = File.expand_path(env['PATH_INFO'])
422
+ request = Rack::Request.new(env)
422
423
 
423
424
  if http_host
424
425
  if (server = virtual_host(http_host))
@@ -428,12 +429,12 @@ module Ronin
428
429
 
429
430
  if http_path
430
431
  if (block = @paths[http_path])
431
- return block.call(env)
432
+ return block.call(request)
432
433
  end
433
434
 
434
435
  @path_patterns.each do |pattern,block|
435
436
  if http_path.match(pattern)
436
- return block.call(env)
437
+ return block.call(request)
437
438
  end
438
439
  end
439
440
 
@@ -446,11 +447,11 @@ module Ronin
446
447
  }.sort.last
447
448
 
448
449
  if (sub_dir && (block = @directories[sub_dir]))
449
- return block.call(env)
450
+ return block.call(request)
450
451
  end
451
452
  end
452
453
 
453
- return @default.call(env)
454
+ return @default.call(request)
454
455
  end
455
456
 
456
457
  #
@@ -22,12 +22,16 @@
22
22
  #
23
23
 
24
24
  require 'ronin/web/web'
25
+ require 'ronin/ui/diagnostics'
25
26
 
26
27
  require 'spidr/agent'
27
28
 
28
29
  module Ronin
29
30
  module Web
30
31
  class Spider < Spidr::Agent
32
+
33
+ include UI::Diagnostics
34
+
31
35
  #
32
36
  # Creates a new Spider object with the given _options_ and
33
37
  # _block_. If a _block_ is given, it will be passed the newly created
@@ -52,28 +56,14 @@ module Ronin
52
56
  # <tt>:ignore_exts</tt>:: An +Array+ of File extension patterns to not
53
57
  # visit.
54
58
  #
55
- def self.agent(options={},&block)
56
- self.new(self.default_options.merge(options),&block)
57
- end
59
+ def initialize(options={},&block)
60
+ super(default_options.merge(options))
58
61
 
59
- #
60
- # Creates a new Spider object with the given _options_ and will begin
61
- # spidering the specified host _name_. If a _block_ is given it
62
- # will be passed the newly created Spider object, before the agent
63
- # begins spidering.
64
- #
65
- def self.host(name,options={},&block)
66
- super(name,self.default_options.merge(options),&block)
67
- end
62
+ every_url do |url|
63
+ print_info("Spidering #{url}")
64
+ end
68
65
 
69
- #
70
- # Creates a new Spider object with the given _options_ and will begin
71
- # spidering the host of the specified _url_. If a _block_ is
72
- # given it will be passed the newly created Spider object, before
73
- # the agent begins spidering.
74
- #
75
- def self.site(url,options={},&block)
76
- super(url,self.default_options.merge(options),&block)
66
+ block.call(self) if block
77
67
  end
78
68
 
79
69
  protected
@@ -81,7 +71,7 @@ module Ronin
81
71
  #
82
72
  # Returns the default options for Spider.
83
73
  #
84
- def self.default_options
74
+ def default_options
85
75
  {:proxy => Web.proxy, :user_agent => Web.user_agent}
86
76
  end
87
77
  end
@@ -24,6 +24,6 @@
24
24
  module Ronin
25
25
  module Web
26
26
  # Ronin Web Version
27
- VERSION = '0.1.1'
27
+ VERSION = '0.1.2'
28
28
  end
29
29
  end
data/spec/spec_helper.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  require 'rubygems'
2
- gem 'rspec', '>=1.1.3'
2
+ gem 'rspec', '>=1.1.12'
3
3
  require 'spec'
4
4
 
5
5
  require 'ronin/web/version'
@@ -1,2 +1,10 @@
1
1
  # Web Server root directory
2
2
  WEB_SERVER_ROOT = File.expand_path(File.join(File.dirname(__FILE__),'root'))
3
+
4
+ def get_path(server,path)
5
+ server.route_path(path).last
6
+ end
7
+
8
+ def get_url(server,url)
9
+ server.route(url).last
10
+ end
@@ -75,68 +75,68 @@ describe Web::Server do
75
75
  it "should have a default response for un-matched paths" do
76
76
  path = '/test/default'
77
77
 
78
- @server.route_path(path).body.should == ['This is default.']
78
+ get_path(@server,path).body.should == ['This is default.']
79
79
  end
80
80
 
81
81
  it "should bind a path to a certain response" do
82
82
  path = '/test/bind.xml'
83
83
 
84
- @server.route_path(path).body.should == ['<secret/>']
84
+ get_path(@server,path).body.should == ['<secret/>']
85
85
  end
86
86
 
87
87
  it "should match paths with patterns" do
88
88
  path = '/test/path_patterns/secret.pdf'
89
89
 
90
- @server.route_path(path).body.should == ['No secrets here.']
90
+ get_path(@server,path).body.should == ['No secrets here.']
91
91
  end
92
92
 
93
93
  it "should match paths to sub-directories" do
94
94
  path = '/test/map/impossible.html'
95
95
 
96
- @server.route_path(path).body.should == ['mapped']
96
+ get_path(@server,path).body.should == ['mapped']
97
97
  end
98
98
 
99
99
  it "should return a response for a file" do
100
100
  path = '/test/file.txt'
101
101
 
102
- @server.route_path(path).body.should == ["This is a test.\n"]
102
+ get_path(@server,path).body.should == ["This is a test.\n"]
103
103
  end
104
104
 
105
105
  it "should return files from bound directories" do
106
106
  path = '/test/directory/test.txt'
107
107
 
108
- @server.route_path(path).body.should == ["This is a test.\n"]
108
+ get_path(@server,path).body.should == ["This is a test.\n"]
109
109
  end
110
110
 
111
111
  it "should return the index file for a bound directory" do
112
112
  path = '/test/directory/'
113
113
 
114
- @server.route_path(path).body.should == ["Index of files.\n"]
114
+ get_path(@server,path).body.should == ["Index of files.\n"]
115
115
  end
116
116
 
117
117
  it "should match virtual hosts" do
118
118
  url = 'http://virtual.host.com/test/virtual_host.xml'
119
119
 
120
- @server.route(url).body.should == ['<virtual/>']
120
+ get_url(@server,url).body.should == ['<virtual/>']
121
121
  end
122
122
 
123
123
  it "should match virtual hosts with patterns" do
124
124
  url = 'http://virtual0.host.com/test/virtual_host_patterns.xml'
125
125
 
126
- @server.route(url).body.should == ['<virtual-patterns/>']
126
+ get_url(@server,url).body.should == ['<virtual-patterns/>']
127
127
  end
128
128
 
129
129
  it "should provide access to servers via their host-names" do
130
130
  virtual_host = @server.virtual_host('virtual.host.com')
131
131
  url = 'http://virtual.host.com/test/virtual_host.xml'
132
132
 
133
- virtual_host.route(url).body.should == ['<virtual/>']
133
+ get_url(virtual_host,url).body.should == ['<virtual/>']
134
134
  end
135
135
 
136
136
  it "should provide access to servers via their host-names that match virtual host patterns" do
137
137
  virtual_host = @server.virtual_host('virtual1.host.com')
138
138
  url = 'http://virtual0.host.com/test/virtual_host_patterns.xml'
139
139
 
140
- virtual_host.route(url).body.should == ['<virtual-patterns/>']
140
+ get_url(virtual_host,url).body.should == ['<virtual-patterns/>']
141
141
  end
142
142
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ronin-web
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Postmodern
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-02-23 00:00:00 -08:00
12
+ date: 2009-03-28 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -60,7 +60,7 @@ dependencies:
60
60
  requirements:
61
61
  - - ">="
62
62
  - !ruby/object:Gem::Version
63
- version: 0.2.1
63
+ version: 0.2.2
64
64
  version:
65
65
  - !ruby/object:Gem::Dependency
66
66
  name: hoe
@@ -70,7 +70,7 @@ dependencies:
70
70
  requirements:
71
71
  - - ">="
72
72
  - !ruby/object:Gem::Version
73
- version: 1.8.3
73
+ version: 1.11.0
74
74
  version:
75
75
  description: Ronin Web is a Ruby library for Ronin that provides support for web scraping and spidering functionality. Ronin is a Ruby platform designed for information security and data exploration tasks. Ronin allows for the rapid development and distribution of code over many of the common Source-Code-Management (SCM) systems.
76
76
  email:
@@ -83,7 +83,6 @@ extra_rdoc_files:
83
83
  - History.txt
84
84
  - Manifest.txt
85
85
  - README.txt
86
- - spec/web/helpers/root/test.txt
87
86
  files:
88
87
  - History.txt
89
88
  - Manifest.txt
@@ -101,6 +100,7 @@ files:
101
100
  - lib/ronin/web/extensions/nokogiri/xml/element.rb
102
101
  - lib/ronin/web/extensions/nokogiri/xml/document.rb
103
102
  - lib/ronin/web/server.rb
103
+ - lib/ronin/web/proxy.rb
104
104
  - lib/ronin/web/spider.rb
105
105
  - lib/ronin/web/web.rb
106
106
  - lib/ronin/web/version.rb