ronin-web 0.1.1 → 0.1.2

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,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