ronin-web 0.1.3 → 0.2.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.
Files changed (56) hide show
  1. data.tar.gz.sig +0 -0
  2. data/History.txt +25 -0
  3. data/Manifest.txt +36 -4
  4. data/README.txt +67 -64
  5. data/Rakefile +12 -3
  6. data/bin/ronin-web +1 -1
  7. data/lib/ronin/network/helpers/web.rb +221 -0
  8. data/lib/ronin/web.rb +1 -2
  9. data/lib/ronin/web/extensions.rb +0 -2
  10. data/lib/ronin/web/extensions/nokogiri.rb +0 -23
  11. data/lib/ronin/web/proxy.rb +3 -103
  12. data/lib/ronin/web/proxy/app.rb +31 -0
  13. data/lib/ronin/web/proxy/base.rb +41 -0
  14. data/lib/ronin/web/proxy/web.rb +42 -0
  15. data/lib/ronin/web/server.rb +3 -530
  16. data/lib/ronin/web/server/app.rb +31 -0
  17. data/lib/ronin/web/server/base.rb +334 -0
  18. data/lib/ronin/web/server/files.rb +92 -0
  19. data/lib/ronin/web/server/helpers.rb +25 -0
  20. data/lib/ronin/web/server/helpers/files.rb +126 -0
  21. data/lib/ronin/web/server/helpers/hosts.rb +72 -0
  22. data/lib/ronin/web/server/helpers/proxy.rb +153 -0
  23. data/lib/ronin/web/server/helpers/rendering.rb +36 -0
  24. data/lib/ronin/web/server/hosts.rb +86 -0
  25. data/lib/ronin/web/server/proxy.rb +116 -0
  26. data/lib/ronin/web/server/web.rb +62 -0
  27. data/lib/ronin/web/spider.rb +53 -26
  28. data/lib/ronin/web/version.rb +1 -3
  29. data/lib/ronin/web/web.rb +253 -95
  30. data/spec/spec_helper.rb +1 -1
  31. data/spec/web/proxy/base_spec.rb +9 -0
  32. data/spec/web/server/base_spec.rb +86 -0
  33. data/spec/web/server/classes/files/dir/file.txt +1 -0
  34. data/spec/web/server/classes/files/dir/index.html +1 -0
  35. data/spec/web/server/classes/files/dir2/file2.txt +1 -0
  36. data/spec/web/server/classes/files/dir3/page.xml +4 -0
  37. data/spec/web/server/classes/files/file.txt +1 -0
  38. data/spec/web/server/classes/files_app.rb +27 -0
  39. data/spec/web/server/classes/hosts_app.rb +40 -0
  40. data/spec/web/server/classes/proxy_app.rb +45 -0
  41. data/spec/web/server/classes/public1/static1.txt +1 -0
  42. data/spec/web/server/classes/public2/static2.txt +1 -0
  43. data/spec/web/server/classes/sub_app.rb +13 -0
  44. data/spec/web/server/classes/test_app.rb +20 -0
  45. data/spec/web/server/files_spec.rb +74 -0
  46. data/spec/web/server/helpers/server.rb +42 -0
  47. data/spec/web/server/hosts_spec.rb +55 -0
  48. data/spec/web/server/proxy_spec.rb +49 -0
  49. data/tasks/spec.rb +1 -0
  50. data/tasks/yard.rb +13 -0
  51. metadata +76 -17
  52. metadata.gz.sig +0 -0
  53. data/TODO.txt +0 -7
  54. data/lib/ronin/sessions/web.rb +0 -80
  55. data/lib/ronin/web/fingerprint.rb +0 -76
  56. data/spec/web/server_spec.rb +0 -142
@@ -1,5 +1,4 @@
1
1
  #
2
- #--
3
2
  # Ronin Web - A Ruby library for Ronin that provides support for web
4
3
  # scraping and spidering functionality.
5
4
  #
@@ -18,13 +17,13 @@
18
17
  # You should have received a copy of the GNU General Public License
19
18
  # along with this program; if not, write to the Free Software
20
19
  # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
- #++
22
20
  #
23
21
 
24
22
  require 'ronin/web/extensions'
25
23
  require 'ronin/web/web'
26
24
  require 'ronin/web/spider'
27
25
  require 'ronin/web/server'
26
+ require 'ronin/web/proxy'
28
27
  require 'ronin/web/version'
29
28
  require 'ronin/config'
30
29
 
@@ -1,5 +1,4 @@
1
1
  #
2
- #--
3
2
  # Ronin Web - A Ruby library for Ronin that provides support for web
4
3
  # scraping and spidering functionality.
5
4
  #
@@ -18,7 +17,6 @@
18
17
  # You should have received a copy of the GNU General Public License
19
18
  # along with this program; if not, write to the Free Software
20
19
  # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
- #++
22
20
  #
23
21
 
24
22
  require 'ronin/web/extensions/nokogiri'
@@ -1,24 +1 @@
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
1
  require 'ronin/web/extensions/nokogiri/xml'
@@ -1,5 +1,4 @@
1
1
  #
2
- #--
3
2
  # Ronin Web - A Ruby library for Ronin that provides support for web
4
3
  # scraping and spidering functionality.
5
4
  #
@@ -18,107 +17,8 @@
18
17
  # You should have received a copy of the GNU General Public License
19
18
  # along with this program; if not, write to the Free Software
20
19
  # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
- #++
22
20
  #
23
21
 
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
22
+ require 'ronin/web/proxy/base'
23
+ require 'ronin/web/proxy/app'
24
+ require 'ronin/web/proxy/web'
@@ -0,0 +1,31 @@
1
+ #
2
+ # Ronin Web - A Ruby library for Ronin that provides support for web
3
+ # scraping and spidering functionality.
4
+ #
5
+ # Copyright (c) 2006-2009 Hal Brodigan (postmodern.mod3 at gmail.com)
6
+ #
7
+ # This program is free software; you can redistribute it and/or modify
8
+ # it under the terms of the GNU General Public License as published by
9
+ # the Free Software Foundation; either version 2 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # This program is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License
18
+ # along with this program; if not, write to the Free Software
19
+ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20
+ #
21
+
22
+ require 'ronin/web/proxy/base'
23
+
24
+ module Ronin
25
+ module Web
26
+ module Proxy
27
+ class App < Base
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,41 @@
1
+ #
2
+ # Ronin Web - A Ruby library for Ronin that provides support for web
3
+ # scraping and spidering functionality.
4
+ #
5
+ # Copyright (c) 2006-2009 Hal Brodigan (postmodern.mod3 at gmail.com)
6
+ #
7
+ # This program is free software; you can redistribute it and/or modify
8
+ # it under the terms of the GNU General Public License as published by
9
+ # the Free Software Foundation; either version 2 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # This program is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License
18
+ # along with this program; if not, write to the Free Software
19
+ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20
+ #
21
+
22
+ require 'ronin/web/server/base'
23
+
24
+ module Ronin
25
+ module Web
26
+ module Proxy
27
+ class Base < Server::Base
28
+
29
+ # The default port to run the Web Proxy on
30
+ DEFAULT_PORT = 8080
31
+
32
+ set :port, DEFAULT_PORT
33
+
34
+ default do
35
+ proxy
36
+ end
37
+
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,42 @@
1
+ #
2
+ # Ronin Web - A Ruby library for Ronin that provides support for web
3
+ # scraping and spidering functionality.
4
+ #
5
+ # Copyright (c) 2006-2009 Hal Brodigan (postmodern.mod3 at gmail.com)
6
+ #
7
+ # This program is free software; you can redistribute it and/or modify
8
+ # it under the terms of the GNU General Public License as published by
9
+ # the Free Software Foundation; either version 2 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # This program is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License
18
+ # along with this program; if not, write to the Free Software
19
+ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20
+ #
21
+
22
+ require 'ronin/web/proxy/app'
23
+
24
+ module Ronin
25
+ module Web
26
+ #
27
+ # Returns the Ronin Web Proxy. When called for the first time
28
+ # the proxy will be started in the background with the given
29
+ # _options_.
30
+ #
31
+ def Web.proxy(options={},&block)
32
+ unless class_variable_defined?('@@ronin_web_proxy')
33
+ @@ronin_web_proxy = Proxy::App
34
+ @@ronin_web_proxy.run!(options.merge(:background => true))
35
+ end
36
+
37
+ @@ronin_web_proxy.class_eval(&block)
38
+
39
+ return @@ronin_web_proxy
40
+ end
41
+ end
42
+ end
@@ -1,5 +1,4 @@
1
1
  #
2
- #--
3
2
  # Ronin Web - A Ruby library for Ronin that provides support for web
4
3
  # scraping and spidering functionality.
5
4
  #
@@ -18,534 +17,8 @@
18
17
  # You should have received a copy of the GNU General Public License
19
18
  # along with this program; if not, write to the Free Software
20
19
  # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
- #++
22
20
  #
23
21
 
24
- require 'uri'
25
- require 'cgi'
26
- require 'thread'
27
-
28
- begin
29
- require 'mongrel'
30
- rescue Gem::LoadError => e
31
- raise(e)
32
- rescue LoadError
33
- require 'webrick'
34
- end
35
-
36
- require 'rack'
37
-
38
- module Ronin
39
- module Web
40
- class Server
41
-
42
- # Default interface to run the Web Server on
43
- HOST = '0.0.0.0'
44
-
45
- # Default port to run the Web Server on
46
- PORT = 8080
47
-
48
- # Directory index files
49
- INDICES = ['index.htm', 'index.html']
50
-
51
- # The host to bind to
52
- attr_accessor :host
53
-
54
- # The port to listen on
55
- attr_accessor :port
56
-
57
- # The handler to run the server under
58
- attr_accessor :handler
59
-
60
- #
61
- # Creates a new Web Server using the given configuration _block_.
62
- #
63
- # _options_ may contain the following keys:
64
- # <tt>:host</tt>:: The host to bind to.
65
- # <tt>:port</tt>:: The port to listen on.
66
- # <tt>:handler</tt>:: The handler to run the server under.
67
- #
68
- def initialize(options={},&block)
69
- @host = options[:host]
70
- @port = options[:port]
71
- @handler = options[:handler]
72
-
73
- @default = method(:not_found)
74
-
75
- @vhost_patterns = {}
76
- @vhosts = {}
77
-
78
- @patterns = {}
79
- @paths = {}
80
- @directories = {}
81
-
82
- @default_mutex = Mutex.new
83
- @vhost_patterns_mutex = Mutex.new
84
- @vhosts_mutex = Mutex.new
85
- @patterns_mutex = Mutex.new
86
- @paths_mutex = Mutex.new
87
- @directories_mutex = Mutex.new
88
-
89
- block.call(self) if block
90
- end
91
-
92
- #
93
- # Returns the default host that the Web Server will be run on.
94
- #
95
- def Server.default_host
96
- @@default_host ||= HOST
97
- end
98
-
99
- #
100
- # Sets the default host that the Web Server will run on to the
101
- # specified _host_.
102
- #
103
- def Server.default_host=(host)
104
- @@default_host = host
105
- end
106
-
107
- #
108
- # Returns the default port that the Web Server will run on.
109
- #
110
- def Server.default_port
111
- @@default_port ||= PORT
112
- end
113
-
114
- #
115
- # Sets the default port the Web Server will run on to the specified
116
- # _port_.
117
- #
118
- def Server.default_port=(port)
119
- @@default_port = port
120
- end
121
-
122
- #
123
- # The Hash of the servers supported file extensions and their HTTP
124
- # Content-Types.
125
- #
126
- def Server.content_types
127
- @@content_types ||= {}
128
- end
129
-
130
- #
131
- # Registers a new content _type_ for the specified file _extensions_.
132
- #
133
- # Server.content_type 'text/xml', ['xml', 'xsl']
134
- #
135
- def Server.content_type(type,extensions)
136
- extensions.each { |ext| Server.content_types[ext] = type }
137
-
138
- return self
139
- end
140
-
141
- #
142
- # Creates a new Web Server object with the given _block_ and starts
143
- # it using the given _options_.
144
- #
145
- def self.start(options={},&block)
146
- self.new(options,&block).start
147
- end
148
-
149
- #
150
- # Returns the HTTP Content-Type for the specified file _extension_.
151
- #
152
- # server.content_type('html')
153
- # # => "text/html"
154
- #
155
- def content_type(extension)
156
- Server.content_types[extension] ||
157
- 'application/x-unknown-content-type'
158
- end
159
-
160
- #
161
- # Returns the HTTP Content-Type for the specified _file_.
162
- #
163
- # server.content_type_for('file.html')
164
- # # => "text/html"
165
- #
166
- def content_type_for(file)
167
- ext = File.extname(file).downcase
168
-
169
- return content_type(ext[1..-1])
170
- end
171
-
172
- #
173
- # Returns the index file contained within the _path_ of the specified
174
- # directory. If no index file can be found, +nil+ will be returned.
175
- #
176
- def index_of(path)
177
- path = File.expand_path(path)
178
-
179
- INDICES.each do |name|
180
- index = File.join(path,name)
181
-
182
- return index if File.file?(index)
183
- end
184
-
185
- return nil
186
- end
187
-
188
- #
189
- # Returns the HTTP 404 Not Found message for the requested path.
190
- #
191
- def not_found(request)
192
- path = request.path_info
193
- body = %{<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
194
- <html>
195
- <head>
196
- <title>404 Not Found</title>
197
- <body>
198
- <h1>Not Found</h1>
199
- <p>The requested URL #{CGI.escapeHTML(path)} was not found on this server.</p>
200
- <hr>
201
- </body>
202
- </html>}
203
-
204
- return response(body, :status => 404, :content_type => 'text/html')
205
- end
206
-
207
- #
208
- # Returns the contents of the file at the specified _path_. If the
209
- # _path_ points to a directory, the directory will be searched for
210
- # an index file. If no index file can be found or _path_ points to a
211
- # non-existant file, a "404 Not Found" response will be returned.
212
- #
213
- def return_file(path,request,content_type=nil)
214
- content_type ||= content_type_for(path)
215
-
216
- if !(File.exists?(path))
217
- return not_found(request)
218
- end
219
-
220
- if File.directory?(path)
221
- unless (path = index_of(path))
222
- return not_found(request)
223
- end
224
- end
225
-
226
- return response(File.new(path), :content_type => content_type)
227
- end
228
-
229
- #
230
- # Returns a Rack Response object with the specified _body_, the given
231
- # _options_ and the given _block_.
232
- #
233
- # _options_ may include the following keys:
234
- # <tt>:status</tt>:: The HTTP Response status code, defaults to 200.
235
- #
236
- # server.response("<data>lol</data>", :content_type => 'text/xml')
237
- #
238
- def response(body='',options={},&block)
239
- status = (
240
- options.delete(:status) ||
241
- options.delete('Status') ||
242
- 200
243
- )
244
- headers = {}
245
-
246
- options.each do |name,value|
247
- header_name = name.to_s.split('_').map { |word|
248
- word.capitalize
249
- }.join('-')
250
-
251
- headers[header_name] = value.to_s
252
- end
253
-
254
- return Rack::Response.new(body,status,headers,&block).finish
255
- end
256
-
257
- #
258
- # Returns the server that handles requests for the specified host
259
- # _name_.
260
- #
261
- def vhost(name)
262
- name = name.to_s
263
-
264
- @vhosts_mutex.synchronize do
265
- if @vhosts.has_key?(name)
266
- return @vhosts[name]
267
- end
268
- end
269
-
270
- @vhost_patterns_mutex.synchronize do
271
- @vhost_patterns.each do |pattern,server|
272
- return server if name.match(pattern)
273
- end
274
- end
275
-
276
- return nil
277
- end
278
-
279
- #
280
- # Use the given _server_ or _block_ as the default route for all
281
- # other requests.
282
- #
283
- # server.default do |request|
284
- # [200, {'Content-Type' => 'text/html'}, 'lol train']
285
- # end
286
- #
287
- def default(server=nil,&block)
288
- @default_mutex.synchronize do
289
- @default = (server || block)
290
- end
291
-
292
- return self
293
- end
294
-
295
- #
296
- # Registers the given _server_ or _block_ to be called when receiving
297
- # requests to host names which match the specified _pattern_.
298
- #
299
- # server.hosts_like(/^a[0-9]\./) do |vhost|
300
- # vhost.map('/download/') do |request|
301
- # ...
302
- # end
303
- # end
304
- #
305
- def hosts_like(pattern,server=nil,&block)
306
- server ||= self.class.new(&block)
307
-
308
- @vhost_patterns_mutex.synchronize do
309
- @vhost_patterns[pattern] = server
310
- end
311
-
312
- return server
313
- end
314
-
315
- #
316
- # Registers the given _server_ or _block_ to be called when receiving
317
- # requests for paths which match the specified _pattern_.
318
- #
319
- # server.paths_like(/\.xml$/) do |request|
320
- # ...
321
- # end
322
- #
323
- def paths_like(pattern,server=nil,&block)
324
- @patterns_mutex.synchronize do
325
- @patterns[pattern] = (server || block)
326
- end
327
-
328
- return self
329
- end
330
-
331
- #
332
- # Creates a new Server object using the specified _block_ and
333
- # connects it as a virtual host representing the specified host
334
- # _name_.
335
- #
336
- # server.host('cdn.evil.com') do |server|
337
- # ...
338
- # end
339
- #
340
- def host(name,server=nil,&block)
341
- server ||= self.class.new(&block)
342
-
343
- @vhosts_mutex.synchronize do
344
- @vhosts[name.to_s] = server
345
- end
346
-
347
- return server
348
- end
349
-
350
- #
351
- # Binds the specified URL _path_ to the given _server_ or _block_.
352
- #
353
- # server.bind '/secrets.xml' do |request|
354
- # [200, {'Content-Type' => 'text/xml'}, "Made you look."]
355
- # end
356
- #
357
- def bind(path,server=nil,&block)
358
- @paths_mutex.synchronize do
359
- @paths[path] = (server || block)
360
- end
361
-
362
- return self
363
- end
364
-
365
- #
366
- # Binds the specified URL directory _path_ to the given
367
- # _server_ or _block_.
368
- #
369
- # server.map '/downloads' do |request|
370
- # server.response(
371
- # "Your somewhere inside the downloads directory",
372
- # :content_type' => 'text/xml'
373
- # )
374
- # end
375
- #
376
- def map(path,server=nil,&block)
377
- @directories_mutex.synchronize do
378
- @directories[path] = (server || block)
379
- end
380
-
381
- return self
382
- end
383
-
384
- #
385
- # Binds the contents of the specified _file_ to the specified URL
386
- # _path_, using the given _options_.
387
- #
388
- # _options_ may contain the following keys:
389
- # <tt>content_type</tt>:: The content-type to use when serving
390
- # the file at the specified _path_.
391
- #
392
- # server.file '/robots.txt', '/path/to/my_robots.txt'
393
- #
394
- def file(path,file,options={})
395
- file = File.expand_path(file)
396
- content_type = options[:content_type]
397
-
398
- bind(path) do |request|
399
- if File.file?(file)
400
- return_file(file,request,content_type)
401
- else
402
- not_found(request)
403
- end
404
- end
405
- end
406
-
407
- #
408
- # Binds the contents of the specified _directory_ to the given
409
- # prefix _path_.
410
- #
411
- # server.directory '/download/', '/tmp/files/'
412
- #
413
- def directory(path,directory)
414
- sub_dirs = path.split('/')
415
- directory = File.expand_path(directory)
416
-
417
- map(path) do |request|
418
- http_path = File.expand_path(request.path_info)
419
- http_dirs = http_path.split('/')
420
-
421
- sub_path = http_dirs[sub_dirs.length..-1].join('/')
422
- absolute_path = File.join(directory,sub_path)
423
-
424
- return_file(absolute_path,request)
425
- end
426
- end
427
-
428
- #
429
- # Starts the server. Mongrel will be used to run the server, if it
430
- # is installed, otherwise WEBrick will be used.
431
- #
432
- def start
433
- rack_handler = [@handler, 'Mongrel', 'WEBrick'].find do |name|
434
- name && Rack::Handler.const_defined?(name)
435
- end
436
-
437
- unless rack_handler
438
- raise(StandardError,"unable to find any Rack handlers",caller)
439
- end
440
-
441
- rack_options = {
442
- 'Host' => (@host || Server.default_host),
443
- 'Port' => (@port || Server.default_port)
444
- }
445
-
446
- Rack::Handler.const_get(rack_handler).run(self,rack_options)
447
- return self
448
- end
449
-
450
- #
451
- # The method which receives all requests.
452
- #
453
- def call(env)
454
- http_host = env['HTTP_HOST']
455
- http_path = File.expand_path(env['PATH_INFO'])
456
- request = Rack::Request.new(env)
457
-
458
- if http_host
459
- if (server = vhost(http_host))
460
- return server.call(env)
461
- end
462
- end
463
-
464
- if http_path
465
- @paths_mutex.synchronize do
466
- if (block = @paths[http_path])
467
- return block.call(request)
468
- end
469
- end
470
-
471
- @patterns_mutex.synchronize do
472
- @patterns.each do |pattern,block|
473
- if http_path.match(pattern)
474
- return block.call(request)
475
- end
476
- end
477
- end
478
-
479
- http_dirs = http_path.split('/')
480
-
481
- @directories_mutex.synchronize do
482
- sub_dir = @directories.keys.select { |path|
483
- dirs = path.split('/')
484
-
485
- http_dirs[0...dirs.length] == dirs
486
- }.sort.last
487
-
488
- if (sub_dir && (block = @directories[sub_dir]))
489
- return block.call(request)
490
- end
491
- end
492
- end
493
-
494
- resp = nil
495
-
496
- @default_mutex.synchronize do
497
- resp = @default.call(request)
498
- end
499
-
500
- return resp
501
- end
502
-
503
- #
504
- # Routes the specified _url_ to the call method.
505
- #
506
- def route(url)
507
- url = URI(url.to_s)
508
-
509
- return call(
510
- 'HTTP_HOST' => url.host,
511
- 'HTTP_PORT' => url.port,
512
- 'SERVER_PORT' => url.port,
513
- 'PATH_INFO' => url.path,
514
- 'QUERY_STRING' => url.query
515
- )
516
- end
517
-
518
- #
519
- # Routes the specified _path_ to the call method.
520
- #
521
- def route_path(path)
522
- path, query = URI.decode(path.to_s).split('?',2)
523
-
524
- return route(URI::HTTP.build(
525
- :host => @host,
526
- :port => @port,
527
- :path => path,
528
- :query => query
529
- ))
530
- end
531
-
532
- protected
533
-
534
- content_type 'text/html', ['html', 'htm', 'xhtml']
535
- content_type 'text/css', ['css']
536
- content_type 'text/gif', ['gif']
537
- content_type 'text/jpeg', ['jpeg', 'jpg']
538
- content_type 'text/png', ['png']
539
- content_type 'image/x-icon', ['ico']
540
- content_type 'text/javascript', ['js']
541
- content_type 'text/xml', ['xml', 'xsl']
542
- content_type 'application/rss+xml', ['rss']
543
- content_type 'application/rdf+xml', ['rdf']
544
- content_type 'application/pdf', ['pdf']
545
- content_type 'application/doc', ['doc']
546
- content_type 'application/zip', ['zip']
547
- content_type 'text/plain', ['txt', 'conf', 'rb', 'py', 'h', 'c', 'hh', 'cc', 'hpp', 'cpp']
548
-
549
- end
550
- end
551
- end
22
+ require 'ronin/web/server/base'
23
+ require 'ronin/web/server/app'
24
+ require 'ronin/web/server/web'