heel 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +10 -0
- data/README +42 -9
- data/lib/heel/dir_handler.rb +86 -72
- data/lib/heel/error_handler.rb +4 -1
- data/lib/heel/gemspec.rb +2 -0
- data/lib/heel/server.rb +33 -14
- data/lib/heel/version.rb +1 -1
- data/resources/css/coderay-cycnus.css +104 -0
- data/resources/css/coderay-murphy.css +98 -0
- data/resources/css/error.css +38 -0
- data/resources/css/listing.css +29 -0
- data/resources/error.rhtml +1 -40
- data/resources/famfamfam/icons/error.png +0 -0
- data/resources/listing.rhtml +4 -31
- data/spec/dir_handler_spec.rb +91 -2
- data/spec/error_handler_spec.rb +1 -0
- data/spec/server_spec.rb +6 -0
- metadata +26 -2
data/CHANGES
CHANGED
@@ -1,4 +1,14 @@
|
|
1
1
|
= Changelog
|
2
|
+
== Version 0.5.0 - 2007-11-19
|
3
|
+
|
4
|
+
* Add in code highlighting support via coderay
|
5
|
+
* extract CSS files to a resource
|
6
|
+
* increase test coverage
|
7
|
+
|
8
|
+
== Version 0.4.1 - 2007-11-15
|
9
|
+
|
10
|
+
* Fix bug [#15645] - not starting up on windows
|
11
|
+
|
2
12
|
== Version 0.4.0 - 2007-11-04
|
3
13
|
|
4
14
|
* Added common log format output to terminal or logfile as appropriate.
|
data/README
CHANGED
@@ -10,19 +10,51 @@ Heel is a small static file web server based on {mongrel}[http://mongrel.rubyfor
|
|
10
10
|
for use when you need a quick web server for a directory. Once the server is running heel will use
|
11
11
|
{launchy}[http://copiousfreetime.rubyforge.org/launchy/] to open your browser at the URL of your document root.
|
12
12
|
|
13
|
+
% heel
|
14
|
+
** Signals ready. TERM => stop. USR2 => restart. INT => stop (no restart).
|
15
|
+
** heel running at http://127.0.0.1:4331 with document root /Users/jeremy/Projects/heel
|
16
|
+
** Use Ctrl-C to stop.
|
17
|
+
** Launching your browser...
|
18
|
+
127.0.0.1 - - [19/Nov/2007:23:23:33 MST] "GET / HTTP/1.1" 200 8374
|
19
|
+
127.0.0.1 - - [19/Nov/2007:23:23:33 MST] "GET /css/listing.css HTTP/1.1" 200 984
|
20
|
+
127.0.0.1 - - [19/Nov/2007:23:23:33 MST] "GET /icons/application.png HTTP/1.1" 200 464
|
21
|
+
127.0.0.1 - - [19/Nov/2007:23:23:33 MST] "GET /icons/folder.png HTTP/1.1" 200 537
|
22
|
+
127.0.0.1 - - [19/Nov/2007:23:23:33 MST] "GET /favicon.ico HTTP/1.1" 404 0
|
23
|
+
|
24
|
+
Or run it in the background
|
25
|
+
|
26
|
+
% heel --daemonize
|
27
|
+
Created /Users/jeremy/.heel
|
28
|
+
heel's PID (/Users/jeremy/.heel/heel.pid) and log file (/Users/jeremy/.heel/heel.log) are stored here
|
29
|
+
|
30
|
+
% heel --kill
|
31
|
+
Sending TERM to process 1086
|
32
|
+
Done.
|
33
|
+
|
34
|
+
== FEATURES
|
35
|
+
|
36
|
+
* Automatic launching of your browser to the URL it is serving with {launchy}[http://copiousfreetime.rubyforge.org/launchy/]
|
37
|
+
* Automatic syntax highlighting of source code files with {coderay}[http://coderay.rubychan.de/]
|
38
|
+
* Run in the foreground or daemonized
|
39
|
+
* Bind to any address and port (default is 127.0.0.1:4331)
|
40
|
+
|
13
41
|
== SYNOPSIS:
|
14
42
|
|
15
43
|
Usage: heel [options]
|
16
44
|
|
17
45
|
-a, --address ADDRESS Address to bind to
|
18
|
-
|
46
|
+
(default: 127.0.0.1)
|
19
47
|
-d, --daemonize Run daemonized in the background
|
20
48
|
-h, --help Display this text
|
21
49
|
-k, --kill Kill an existing daemonized heel process
|
50
|
+
--[no-]highlighting Turn on or off syntax highlighting
|
51
|
+
(default: on)
|
52
|
+
--[no-]launch-browser Turn on or off automatic browser launch
|
53
|
+
(default: on)
|
22
54
|
-p, --port PORT Port to bind to
|
23
|
-
|
55
|
+
(default: 4331)
|
24
56
|
-r, --root ROOT Set the document root
|
25
|
-
|
57
|
+
(default: current working directory)
|
26
58
|
-v, --version Show version
|
27
59
|
|
28
60
|
|
@@ -30,15 +62,16 @@ for use when you need a quick web server for a directory. Once the server is ru
|
|
30
62
|
|
31
63
|
=== For running:
|
32
64
|
|
33
|
-
*
|
65
|
+
* {coderay}[http://coderay.rubychan.de/]
|
34
66
|
* {launchy}[http://copiousfreetime.rubyforge.org/launchy/] >= 0.1.1
|
35
|
-
* mime-types
|
67
|
+
* {mime-types}[http://mime-types.rubyforge.org/]
|
68
|
+
* {mongrel}[http://mongrel.rubyforge.org/]
|
69
|
+
* {rake}[http://rake.rubyforge.org/] >= 0.7.1
|
36
70
|
|
37
71
|
=== For development:
|
38
72
|
|
39
|
-
*
|
40
|
-
*
|
41
|
-
* rspec >= 0.7.3
|
73
|
+
* {rcov}[http://eigenclass.org/hiki.rb?rcov] >= 0.7.0.1
|
74
|
+
* {rspec}[http://rspec.rubyforge.org/] >= 0.7.3
|
42
75
|
|
43
76
|
== INSTALL:
|
44
77
|
|
@@ -49,7 +82,7 @@ for use when you need a quick web server for a directory. Once the server is ru
|
|
49
82
|
* Zed Shaw for {mongrel}[http://mongrel.rubyforge.org]
|
50
83
|
* http://www.famfamfam.com/ for amazing icons
|
51
84
|
|
52
|
-
== LICENSE:
|
85
|
+
== BSD LICENSE:
|
53
86
|
|
54
87
|
Copyright (c) 2007, Jeremy Hinegardner
|
55
88
|
|
data/lib/heel/dir_handler.rb
CHANGED
@@ -1,20 +1,25 @@
|
|
1
1
|
require 'heel'
|
2
2
|
require 'mime/types'
|
3
3
|
require 'erb'
|
4
|
+
require 'coderay'
|
5
|
+
require 'coderay/helpers/file_type'
|
4
6
|
|
5
7
|
module Heel
|
6
8
|
|
7
9
|
# A refactored version of Mongrel::DirHandler using the mime-types
|
8
10
|
# gem and a prettier directory listing.
|
9
11
|
class DirHandler < ::Mongrel::HttpHandler
|
10
|
-
attr_reader
|
11
|
-
attr_reader
|
12
|
-
attr_reader
|
13
|
-
attr_reader
|
14
|
-
attr_reader
|
15
|
-
attr_reader
|
16
|
-
attr_reader
|
17
|
-
attr_reader
|
12
|
+
attr_reader :document_root
|
13
|
+
attr_reader :directory_index_html
|
14
|
+
attr_reader :icon_url
|
15
|
+
attr_reader :default_mime_type
|
16
|
+
attr_reader :highlighting
|
17
|
+
attr_reader :ignore_globs
|
18
|
+
attr_reader :reload_template_changes
|
19
|
+
attr_reader :template
|
20
|
+
attr_reader :template_mtime
|
21
|
+
attr_accessor :listener
|
22
|
+
attr_reader :request_notify
|
18
23
|
|
19
24
|
# if any other mime types are needed, add them directly via the
|
20
25
|
# mime-types calls.
|
@@ -53,6 +58,7 @@ module Heel
|
|
53
58
|
@using_icons = options[:using_icons] || true
|
54
59
|
@icon_url = options[:icon_url] || "/icons"
|
55
60
|
@reload_template_changes = options[:reload_template_changes] || false
|
61
|
+
@highlighting = options[:highlighting] || false
|
56
62
|
reload_template
|
57
63
|
|
58
64
|
ADDITIONAL_MIME_TYPES.each do |mt|
|
@@ -99,48 +105,48 @@ module Heel
|
|
99
105
|
@template_mtime ||= fstat.mtime
|
100
106
|
if @template.nil? or fstat.mtime > @template_mtime then
|
101
107
|
@template = ::ERB.new(File.read(fname))
|
102
|
-
# log "Reloaded #{fname}"
|
103
108
|
end
|
104
109
|
end
|
105
110
|
|
106
111
|
# determine how to respond to the request, it will either be a
|
107
112
|
# directory listing, a file return, or an error return.
|
108
|
-
def how_to_respond(req_path)
|
109
|
-
|
110
|
-
|
111
|
-
|
113
|
+
def how_to_respond(req_path,query_params = {})
|
114
|
+
return 403 unless req_path.index(document_root) == 0
|
115
|
+
begin
|
116
|
+
stat = File.stat(req_path)
|
112
117
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
return 403
|
128
|
-
end
|
129
|
-
return req_path
|
130
|
-
else
|
131
|
-
# TODO: debug log
|
118
|
+
# if it is a directory, we either return the
|
119
|
+
# directory index file, or a directory listing
|
120
|
+
if stat.directory? then
|
121
|
+
dir_index = File.join(req_path,directory_index_html)
|
122
|
+
if File.exists?(dir_index) then
|
123
|
+
return dir_index
|
124
|
+
elsif directory_listing_allowed?
|
125
|
+
return :directory_listing
|
126
|
+
end
|
127
|
+
|
128
|
+
# if it is a file and readable, make sure that the
|
129
|
+
# path is a legal path
|
130
|
+
elsif stat.file? and stat.readable? then
|
131
|
+
if should_ignore?(File.basename(req_path)) then
|
132
132
|
return 403
|
133
|
+
elsif highlighting and not %w(false off).include? query_params['highlighting'].to_s.downcase
|
134
|
+
ft = ::FileType[req_path,true]
|
135
|
+
return :highlighted_file if ft and ft != :html
|
133
136
|
end
|
137
|
+
return req_path
|
138
|
+
else
|
139
|
+
log "ERROR: #{req_path} is not a directory or a readable file"
|
140
|
+
return 403
|
141
|
+
end
|
134
142
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
end
|
139
|
-
# TODO: debug log
|
140
|
-
return 500
|
143
|
+
rescue => error
|
144
|
+
if error.kind_of?(Errno::ENOENT) then
|
145
|
+
return 404
|
141
146
|
end
|
142
|
-
|
143
|
-
|
147
|
+
log "ERROR: Unknown, check out the stacktrace"
|
148
|
+
log error
|
149
|
+
return 500
|
144
150
|
end
|
145
151
|
end
|
146
152
|
|
@@ -193,45 +199,52 @@ module Heel
|
|
193
199
|
return res_bytes
|
194
200
|
end
|
195
201
|
|
196
|
-
|
197
|
-
#
|
202
|
+
|
203
|
+
# send the file back with the appropriate mimetype
|
198
204
|
def respond_with_send_file(path,method,request,response)
|
199
205
|
stat = File.stat(path)
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
last_response_time = Time.httpddate(modified_since) rescue nil
|
207
|
-
|
208
|
-
same_response = case
|
209
|
-
when modified_since && !last_response_time : false
|
210
|
-
when modified_since && last_response_time > Time.now : false
|
211
|
-
when modified_since && mtime > last_response_time : false
|
212
|
-
when none_match && none_match == "*" : false
|
213
|
-
when none_match && !none_match.strip.split(/\s*,\s*/).include?(etag) : false
|
214
|
-
else modified_since || none_match
|
215
|
-
end
|
216
|
-
header = response.header
|
217
|
-
header[::Mongrel::Const::ETAG] = etag
|
218
|
-
|
219
|
-
if same_response then
|
220
|
-
response.start(304) {}
|
221
|
-
else
|
222
|
-
response.status = 200
|
223
|
-
header[::Mongrel::Const::LAST_MODIFIED] = mtime.httpdate
|
224
|
-
header[::Mongrel::Const::CONTENT_TYPE] = (MIME::Types.of(path).first || default_mime_type).to_s
|
225
|
-
end
|
226
|
-
|
206
|
+
header = response.header
|
207
|
+
|
208
|
+
header[::Mongrel::Const::LAST_MODIFIED] = stat.mtime
|
209
|
+
header[::Mongrel::Const::CONTENT_TYPE] = (MIME::Types.of(path).first || default_mime_type).to_s
|
210
|
+
|
211
|
+
response.status = 200
|
227
212
|
response.send_status(stat.size)
|
228
213
|
response.send_header
|
229
|
-
|
214
|
+
|
230
215
|
if method == ::Mongrel::Const::GET then
|
231
216
|
response.send_file(path,stat.size < ::Mongrel::Const::CHUNK_SIZE * 2)
|
232
217
|
end
|
218
|
+
|
233
219
|
return stat.size
|
234
220
|
end
|
221
|
+
|
222
|
+
#
|
223
|
+
# send back the file marked up by code ray
|
224
|
+
def respond_with_highlighted_file(path,request,response)
|
225
|
+
res_bytes = 0
|
226
|
+
response.start(200) do |head,out|
|
227
|
+
head[::Mongrel::Const::CONTENT_TYPE] = 'text/html'
|
228
|
+
bytes = CodeRay.scan_file(path,:auto).html
|
229
|
+
res_bytes = out.write(<<-EOM)
|
230
|
+
<html>
|
231
|
+
<head>
|
232
|
+
<title>#{path}</title>
|
233
|
+
<!-- CodeRay syntax highlighting CSS -->
|
234
|
+
<link rel="stylesheet" href="/css/coderay-cycnus.css" type="text/css" />
|
235
|
+
</head>
|
236
|
+
<body>
|
237
|
+
<div class="CodeRay">
|
238
|
+
<pre>
|
239
|
+
#{CodeRay.scan_file(path,:auto).html({:line_numbers => :inline})}
|
240
|
+
</pre>
|
241
|
+
</div>
|
242
|
+
</body>
|
243
|
+
</html>
|
244
|
+
EOM
|
245
|
+
end
|
246
|
+
return res_bytes
|
247
|
+
end
|
235
248
|
|
236
249
|
# process the request, returning either the file, a directory
|
237
250
|
# listing (if allowed) or an appropriate error
|
@@ -244,12 +257,13 @@ module Heel
|
|
244
257
|
req_path = File.expand_path(File.join(@document_root,
|
245
258
|
::Mongrel::HttpRequest.unescape(request.params[Mongrel::Const::PATH_INFO])),
|
246
259
|
@document_root)
|
247
|
-
res_type = how_to_respond(req_path)
|
260
|
+
res_type = how_to_respond(req_path,::Mongrel::HttpRequest.query_parse(request.params['QUERY_STRING']))
|
248
261
|
res_size = 0
|
249
|
-
|
250
262
|
case res_type
|
251
263
|
when :directory_listing
|
252
264
|
res_size = respond_with_directory_listing(req_path,request,response)
|
265
|
+
when :highlighted_file
|
266
|
+
res_size = respond_with_highlighted_file(req_path,request,response)
|
253
267
|
when String
|
254
268
|
res_size = respond_with_send_file(res_type,method,request,response)
|
255
269
|
when Integer
|
data/lib/heel/error_handler.rb
CHANGED
@@ -5,7 +5,10 @@ module Heel
|
|
5
5
|
|
6
6
|
class ErrorHandler < ::Mongrel::HttpHandler
|
7
7
|
|
8
|
-
attr_reader
|
8
|
+
attr_reader :template
|
9
|
+
attr_accessor :listener
|
10
|
+
attr_reader :request_notify
|
11
|
+
|
9
12
|
|
10
13
|
def initialize(options = {})
|
11
14
|
@template = ::ERB.new File.read(File.join(APP_RESOURCE_DIR,"error.rhtml"))
|
data/lib/heel/gemspec.rb
CHANGED
@@ -36,6 +36,8 @@ module Heel
|
|
36
36
|
spec.add_dependency("mongrel", ">= 1.0.1")
|
37
37
|
spec.add_dependency("launchy", ">= 0.3.0")
|
38
38
|
spec.add_dependency("mime-types", ">= 1.15")
|
39
|
+
spec.add_dependency("coderay", ">= 0.7.4.215")
|
40
|
+
spec.add_dependency("rake", ">= 0.7.3")
|
39
41
|
|
40
42
|
spec.required_ruby_version = ">= 1.8.5"
|
41
43
|
|
data/lib/heel/server.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'heel'
|
2
2
|
require 'ostruct'
|
3
|
-
require 'daemons/daemonize'
|
4
3
|
require 'launchy'
|
5
4
|
require 'tmpdir'
|
6
5
|
require 'fileutils'
|
@@ -53,6 +52,7 @@ module Heel
|
|
53
52
|
@default_options.port = 4331
|
54
53
|
@default_options.document_root = Dir.pwd
|
55
54
|
@default_options.daemonize = false
|
55
|
+
@default_options.highlighting = true
|
56
56
|
@default_options.kill = false
|
57
57
|
@default_options.launch_browser = true
|
58
58
|
end
|
@@ -76,7 +76,7 @@ module Heel
|
|
76
76
|
op.separator ""
|
77
77
|
|
78
78
|
op.on("-a", "--address ADDRESS", "Address to bind to",
|
79
|
-
"(default: #{default_options.address})") do |add|
|
79
|
+
" (default: #{default_options.address})") do |add|
|
80
80
|
@parsed_options.address = add
|
81
81
|
end
|
82
82
|
|
@@ -92,12 +92,18 @@ module Heel
|
|
92
92
|
@parsed_options.kill = true
|
93
93
|
end
|
94
94
|
|
95
|
-
op.on("
|
95
|
+
op.on("--[no-]highlighting", "Turn on or off syntax highlighting",
|
96
|
+
" (default: on)") do |highlighting|
|
97
|
+
@parsed_options.highlighting = highlighting
|
98
|
+
end
|
99
|
+
|
100
|
+
op.on("--[no-]launch-browser", "Turn on or off automatic browser launch",
|
101
|
+
" (default: on)") do |l|
|
96
102
|
@parsed_options.launch_browser = l
|
97
103
|
end
|
98
104
|
|
99
105
|
op.on("-p", "--port PORT", Integer, "Port to bind to",
|
100
|
-
"(default: #{default_options.port})") do |port|
|
106
|
+
" (default: #{default_options.port})") do |port|
|
101
107
|
@parsed_options.port = port
|
102
108
|
end
|
103
109
|
|
@@ -171,8 +177,7 @@ module Heel
|
|
171
177
|
if not File.exists?(default_directory) then
|
172
178
|
FileUtils.mkdir_p(default_directory)
|
173
179
|
@stdout.puts "Created #{default_directory}"
|
174
|
-
@stdout.puts "PID file #{
|
175
|
-
@stdout.puts "along with the log #{log_file}"
|
180
|
+
@stdout.puts "heel's PID (#{pid_file}) and log file (#{log_file}) are stored here"
|
176
181
|
end
|
177
182
|
end
|
178
183
|
|
@@ -184,9 +189,12 @@ module Heel
|
|
184
189
|
setup_heel_dir
|
185
190
|
|
186
191
|
# capture method/variables into a local context so they can be used inside the Configurator block
|
192
|
+
c_address = options.address
|
193
|
+
c_port = options.port
|
187
194
|
c_document_root = options.document_root
|
188
195
|
c_background_me = options.daemonize
|
189
196
|
c_default_dir = default_directory
|
197
|
+
c_highlighting = options.highlighting
|
190
198
|
c_pid_file = pid_file
|
191
199
|
c_log_file = log_file
|
192
200
|
|
@@ -202,15 +210,23 @@ module Heel
|
|
202
210
|
daemonize({:cwd => c_default_dir, :log_file => c_log_file})
|
203
211
|
end
|
204
212
|
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
213
|
+
begin
|
214
|
+
|
215
|
+
listener do
|
216
|
+
uri "/", :handler => stats
|
217
|
+
uri "/", :handler => Heel::DirHandler.new({:document_root => c_document_root,
|
218
|
+
:highlighting => c_highlighting })
|
219
|
+
uri "/", :handler => Heel::ErrorHandler.new
|
220
|
+
uri "/css", :handler => Heel::DirHandler.new({:document_root =>
|
221
|
+
File.join(APP_RESOURCE_DIR, "css")})
|
222
|
+
uri "/icons", :handler => Heel::DirHandler.new({ :document_root =>
|
223
|
+
File.join(APP_RESOURCE_DIR, "famfamfam", "icons")})
|
224
|
+
uri "/status", :handler => ::Mongrel::StatusHandler.new(:stats_filter => stats)
|
225
|
+
end
|
226
|
+
rescue Errno::EADDRINUSE
|
227
|
+
log "ERROR: Address (#{c_address}:#{c_port}) is already in use, please check running processes or run `heel --kill'"
|
228
|
+
exit 1
|
212
229
|
end
|
213
|
-
|
214
230
|
setup_signals
|
215
231
|
end
|
216
232
|
|
@@ -225,6 +241,9 @@ module Heel
|
|
225
241
|
|
226
242
|
if options.launch_browser then
|
227
243
|
config.log "Launching your browser..."
|
244
|
+
if c_background_me then
|
245
|
+
puts "Launching your browser to http://#{options.address}:#{options.port}/"
|
246
|
+
end
|
228
247
|
::Launchy.open("http://#{options.address}:#{options.port}/")
|
229
248
|
end
|
230
249
|
|
data/lib/heel/version.rb
CHANGED
@@ -0,0 +1,104 @@
|
|
1
|
+
.CodeRay {
|
2
|
+
background-color: #f8f8f8;
|
3
|
+
/* border: 1px solid silver;
|
4
|
+
*/ font-family: 'Courier New', 'Terminal', monospace;
|
5
|
+
color: #100;
|
6
|
+
}
|
7
|
+
.CodeRay pre { margin: 0px }
|
8
|
+
|
9
|
+
div.CodeRay { }
|
10
|
+
|
11
|
+
span.CodeRay { white-space: pre; border: 0px; padding: 2px }
|
12
|
+
|
13
|
+
table.CodeRay { border-collapse: collapse; width: 100%; padding: 2px }
|
14
|
+
table.CodeRay td { padding: 2px 4px; vertical-align: top }
|
15
|
+
|
16
|
+
.CodeRay .line_numbers, .CodeRay .no {
|
17
|
+
background-color: #def;
|
18
|
+
color: gray;
|
19
|
+
text-align: right;
|
20
|
+
}
|
21
|
+
.CodeRay .line_numbers tt { font-weight: bold }
|
22
|
+
.CodeRay .no { padding: 0px 4px }
|
23
|
+
.CodeRay .code { width: 100% }
|
24
|
+
|
25
|
+
ol.CodeRay { font-size: 10pt }
|
26
|
+
ol.CodeRay li { white-space: pre }
|
27
|
+
|
28
|
+
.CodeRay .code pre { overflow: auto }
|
29
|
+
|
30
|
+
.CodeRay .af { color:#00C }
|
31
|
+
.CodeRay .an { color:#007 }
|
32
|
+
.CodeRay .av { color:#700 }
|
33
|
+
.CodeRay .aw { color:#C00 }
|
34
|
+
.CodeRay .bi { color:#509; font-weight:bold }
|
35
|
+
.CodeRay .c { color:#888 }
|
36
|
+
|
37
|
+
.CodeRay .ch { color:#04D }
|
38
|
+
.CodeRay .ch .k { color:#04D }
|
39
|
+
.CodeRay .ch .dl { color:#039 }
|
40
|
+
|
41
|
+
.CodeRay .cl { color:#B06; font-weight:bold }
|
42
|
+
.CodeRay .co { color:#036; font-weight:bold }
|
43
|
+
.CodeRay .cr { color:#0A0 }
|
44
|
+
.CodeRay .cv { color:#369 }
|
45
|
+
.CodeRay .df { color:#099; font-weight:bold }
|
46
|
+
.CodeRay .di { color:#088; font-weight:bold }
|
47
|
+
.CodeRay .dl { color:black }
|
48
|
+
.CodeRay .do { color:#970 }
|
49
|
+
.CodeRay .ds { color:#D42; font-weight:bold }
|
50
|
+
.CodeRay .e { color:#666; font-weight:bold }
|
51
|
+
.CodeRay .en { color:#800; font-weight:bold }
|
52
|
+
.CodeRay .er { color:#F00; background-color:#FAA }
|
53
|
+
.CodeRay .ex { color:#F00; font-weight:bold }
|
54
|
+
.CodeRay .fl { color:#60E; font-weight:bold }
|
55
|
+
.CodeRay .fu { color:#06B; font-weight:bold }
|
56
|
+
.CodeRay .gv { color:#d70; font-weight:bold }
|
57
|
+
.CodeRay .hx { color:#058; font-weight:bold }
|
58
|
+
.CodeRay .i { color:#00D; font-weight:bold }
|
59
|
+
.CodeRay .ic { color:#B44; font-weight:bold }
|
60
|
+
|
61
|
+
.CodeRay .il { background: #eee }
|
62
|
+
.CodeRay .il .il { background: #ddd }
|
63
|
+
.CodeRay .il .il .il { background: #ccc }
|
64
|
+
.CodeRay .il .idl { font-weight: bold; color: #888 }
|
65
|
+
|
66
|
+
.CodeRay .in { color:#B2B; font-weight:bold }
|
67
|
+
.CodeRay .iv { color:#33B }
|
68
|
+
.CodeRay .la { color:#970; font-weight:bold }
|
69
|
+
.CodeRay .lv { color:#963 }
|
70
|
+
.CodeRay .oc { color:#40E; font-weight:bold }
|
71
|
+
.CodeRay .on { color:#000; font-weight:bold }
|
72
|
+
.CodeRay .op { }
|
73
|
+
.CodeRay .pc { color:#038; font-weight:bold }
|
74
|
+
.CodeRay .pd { color:#369; font-weight:bold }
|
75
|
+
.CodeRay .pp { color:#579 }
|
76
|
+
.CodeRay .pt { color:#339; font-weight:bold }
|
77
|
+
.CodeRay .r { color:#080; font-weight:bold }
|
78
|
+
|
79
|
+
.CodeRay .rx { background-color:#fff0ff }
|
80
|
+
.CodeRay .rx .k { color:#808 }
|
81
|
+
.CodeRay .rx .dl { color:#404 }
|
82
|
+
.CodeRay .rx .mod { color:#C2C }
|
83
|
+
.CodeRay .rx .fu { color:#404; font-weight: bold }
|
84
|
+
|
85
|
+
.CodeRay .s { background-color:#fff0f0 }
|
86
|
+
.CodeRay .s .s { background-color:#ffe0e0 }
|
87
|
+
.CodeRay .s .s .s { background-color:#ffd0d0 }
|
88
|
+
.CodeRay .s .k { color:#D20 }
|
89
|
+
.CodeRay .s .dl { color:#710 }
|
90
|
+
|
91
|
+
.CodeRay .sh { background-color:#f0fff0 }
|
92
|
+
.CodeRay .sh .k { color:#2B2 }
|
93
|
+
.CodeRay .sh .dl { color:#161 }
|
94
|
+
|
95
|
+
.CodeRay .sy { color:#A60 }
|
96
|
+
.CodeRay .sy .k { color:#A60 }
|
97
|
+
.CodeRay .sy .dl { color:#630 }
|
98
|
+
|
99
|
+
.CodeRay .ta { color:#070 }
|
100
|
+
.CodeRay .tf { color:#070; font-weight:bold }
|
101
|
+
.CodeRay .ts { color:#D70; font-weight:bold }
|
102
|
+
.CodeRay .ty { color:#339; font-weight:bold }
|
103
|
+
.CodeRay .v { color:#036 }
|
104
|
+
.CodeRay .xt { color:#444 }
|
@@ -0,0 +1,98 @@
|
|
1
|
+
.CodeRay {
|
2
|
+
background-color: #001129;
|
3
|
+
border: 1px solid silver;
|
4
|
+
font-family: 'Courier New', 'Terminal', monospace;
|
5
|
+
color: #C0C0C0;
|
6
|
+
}
|
7
|
+
.CodeRay pre { margin: 0px; }
|
8
|
+
|
9
|
+
div.CodeRay { }
|
10
|
+
|
11
|
+
span.CodeRay { white-space: pre; border: 0px; padding: 2px; }
|
12
|
+
|
13
|
+
table.CodeRay { border-collapse: collapse; width: 100%; padding: 2px; }
|
14
|
+
table.CodeRay td { padding: 2px 4px; vertical-align: top; }
|
15
|
+
|
16
|
+
.CodeRay .line_numbers, .CodeRay .no {
|
17
|
+
background-color: #001129;
|
18
|
+
color: gray;
|
19
|
+
text-align: right;
|
20
|
+
}
|
21
|
+
.CodeRay .line_numbers tt { font-weight: bold; }
|
22
|
+
.CodeRay .no { padding: 0px 4px; }
|
23
|
+
.CodeRay .code { width: 100%; }
|
24
|
+
|
25
|
+
ol.CodeRay { font-size: 10pt; }
|
26
|
+
ol.CodeRay li { white-space: pre; }
|
27
|
+
|
28
|
+
.CodeRay .code pre { overflow: auto; }
|
29
|
+
|
30
|
+
.CodeRay .af { color:#00C; }
|
31
|
+
.CodeRay .an { color:#007; }
|
32
|
+
.CodeRay .av { color:#700; }
|
33
|
+
.CodeRay .aw { color:#C00; }
|
34
|
+
.CodeRay .bi { color:#509; font-weight:bold; }
|
35
|
+
.CodeRay .c { color:#666; }
|
36
|
+
|
37
|
+
.CodeRay .ch { color:#88F; }
|
38
|
+
.CodeRay .ch .k { color:#04D; }
|
39
|
+
.CodeRay .ch .dl { color:#039; }
|
40
|
+
|
41
|
+
.CodeRay .cl { color:#e9e; font-weight:bold; }
|
42
|
+
.CodeRay .co { color:#5ED; font-weight:bold; }
|
43
|
+
.CodeRay .cr { color:#0A0; }
|
44
|
+
.CodeRay .cv { color:#ccf; }
|
45
|
+
.CodeRay .df { color:#099; font-weight:bold; }
|
46
|
+
.CodeRay .di { color:#088; font-weight:bold; }
|
47
|
+
.CodeRay .dl { color:black; }
|
48
|
+
.CodeRay .do { color:#970; }
|
49
|
+
.CodeRay .ds { color:#D42; font-weight:bold; }
|
50
|
+
.CodeRay .e { color:#666; font-weight:bold; }
|
51
|
+
.CodeRay .er { color:#F00; background-color:#FAA; }
|
52
|
+
.CodeRay .ex { color:#F00; font-weight:bold; }
|
53
|
+
.CodeRay .fl { color:#60E; font-weight:bold; }
|
54
|
+
.CodeRay .fu { color:#5ed; font-weight:bold; }
|
55
|
+
.CodeRay .gv { color:#f84; }
|
56
|
+
.CodeRay .hx { color:#058; font-weight:bold; }
|
57
|
+
.CodeRay .i { color:#66f; font-weight:bold; }
|
58
|
+
.CodeRay .ic { color:#B44; font-weight:bold; }
|
59
|
+
.CodeRay .il { }
|
60
|
+
.CodeRay .in { color:#B2B; font-weight:bold; }
|
61
|
+
.CodeRay .iv { color:#aaf; }
|
62
|
+
.CodeRay .la { color:#970; font-weight:bold; }
|
63
|
+
.CodeRay .lv { color:#963; }
|
64
|
+
.CodeRay .oc { color:#40E; font-weight:bold; }
|
65
|
+
.CodeRay .on { color:#000; font-weight:bold; }
|
66
|
+
.CodeRay .op { }
|
67
|
+
.CodeRay .pc { color:#08f; font-weight:bold; }
|
68
|
+
.CodeRay .pd { color:#369; font-weight:bold; }
|
69
|
+
.CodeRay .pp { color:#579; }
|
70
|
+
.CodeRay .pt { color:#66f; font-weight:bold; }
|
71
|
+
.CodeRay .r { color:#5de; font-weight:bold; }
|
72
|
+
|
73
|
+
.CodeRay .rx { background-color:#221133; }
|
74
|
+
.CodeRay .rx .k { color:#f8f; }
|
75
|
+
.CodeRay .rx .dl { color:#f0f; }
|
76
|
+
.CodeRay .rx .mod { color:#f0b; }
|
77
|
+
.CodeRay .rx .fu { color:#404; font-weight: bold; }
|
78
|
+
|
79
|
+
.CodeRay .s { background-color:#331122; }
|
80
|
+
.CodeRay .s .s { background-color:#ffe0e0; }
|
81
|
+
.CodeRay .s .s .s { background-color:#ffd0d0; }
|
82
|
+
.CodeRay .s .k { color:#F88; }
|
83
|
+
.CodeRay .s .dl { color:#f55; }
|
84
|
+
|
85
|
+
.CodeRay .sh { background-color:#f0fff0; }
|
86
|
+
.CodeRay .sh .k { color:#2B2; }
|
87
|
+
.CodeRay .sh .dl { color:#161; }
|
88
|
+
|
89
|
+
.CodeRay .sy { color:#Fc8; }
|
90
|
+
.CodeRay .sy .k { color:#Fc8; }
|
91
|
+
.CodeRay .sy .dl { color:#F84; }
|
92
|
+
|
93
|
+
.CodeRay .ta { color:#070; }
|
94
|
+
.CodeRay .tf { color:#070; font-weight:bold; }
|
95
|
+
.CodeRay .ts { color:#D70; font-weight:bold; }
|
96
|
+
.CodeRay .ty { color:#339; font-weight:bold; }
|
97
|
+
.CodeRay .v { color:#036; }
|
98
|
+
.CodeRay .xt { color:#444; }
|
@@ -0,0 +1,38 @@
|
|
1
|
+
body { font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #e0e0e0;}
|
2
|
+
div.wrap {
|
3
|
+
background: transparent;
|
4
|
+
text-align: left;
|
5
|
+
width: 400px;
|
6
|
+
margin-top: 100px;
|
7
|
+
margin-left: auto;
|
8
|
+
margin-right: auto;
|
9
|
+
}
|
10
|
+
div.box {
|
11
|
+
border-left: 1px solid #333;
|
12
|
+
border-right: 1px solid #333;
|
13
|
+
background: #FFF;
|
14
|
+
display: block;
|
15
|
+
}
|
16
|
+
img { padding-right: 20px;}
|
17
|
+
h1 { display: inline; font-weight: bold; }
|
18
|
+
h2 { display: inline; font-weight: bold; padding-left: 25px;text-align: center;}
|
19
|
+
div.header { font-size: x-large; }
|
20
|
+
div.content { font-size: x-large; border: 0; padding: 10px 25px 10px 25px;}
|
21
|
+
div.footer { text-align: right; width: 400px; }
|
22
|
+
|
23
|
+
.curved { background: transparent;}
|
24
|
+
.curved .c1, .curved .c2, .curved .c3, .curved .c4 {
|
25
|
+
display: block;
|
26
|
+
overflow: hidden;
|
27
|
+
height: 1px;
|
28
|
+
font-size: 1px;
|
29
|
+
}
|
30
|
+
.curved .c2, .curved .c3, .curved .c4 {
|
31
|
+
background: #fff;
|
32
|
+
border-left: 1px solid #000;
|
33
|
+
border-right: 1px solid #000;
|
34
|
+
}
|
35
|
+
.c1 { margin: 0 5px 0 5px; background: #000; }
|
36
|
+
.c2 { margin: 0 3px 0 3px; border-left: 2px solid #000; border-right: 2px solid #000; }
|
37
|
+
.c3 { margin: 0 2px 0 2px; }
|
38
|
+
.c4 { margin: 0 1px 0 1px; }
|
@@ -0,0 +1,29 @@
|
|
1
|
+
a, a:active { text-decoration: none; color: blue;}
|
2
|
+
a:visited { color: purple;}
|
3
|
+
a:hover, a:focus { text-decoration: underline; color: red;}
|
4
|
+
body { font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #eee; }
|
5
|
+
.c { text-align: center; }
|
6
|
+
table { border-collapse: collapse; border-spacing: 0px; width: 100%;}
|
7
|
+
tr { background-color: #ccf;}
|
8
|
+
tr:hover { background-color: #faa;}
|
9
|
+
td, th {
|
10
|
+
border-bottom: 1px solid #ccc;
|
11
|
+
padding: 0em .3em 0em .3em ;
|
12
|
+
color: #666;
|
13
|
+
text-align: left;
|
14
|
+
vertical-align: middle;
|
15
|
+
}
|
16
|
+
thead th {
|
17
|
+
border-top: 2px solid #666;
|
18
|
+
border-bottom: 2px solid #666;
|
19
|
+
font-weight: bold;
|
20
|
+
background: #aaa;
|
21
|
+
color: #fff;
|
22
|
+
text-transform: uppercase;
|
23
|
+
}
|
24
|
+
tr.odd { background-color: #cfc; color: #333;}
|
25
|
+
tr.odd:hover { background-color: #faa; color: #333;}
|
26
|
+
td.n { text-align: right; padding-right: 2em;}
|
27
|
+
div.header { }
|
28
|
+
div.content { background: #FFF; width: 100%;}
|
29
|
+
div.footer { border-top: 2px solid #333; text-align: right;}
|
data/resources/error.rhtml
CHANGED
@@ -3,46 +3,7 @@
|
|
3
3
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
|
4
4
|
<head>
|
5
5
|
<title>Error <%= status %> </title>
|
6
|
-
|
7
|
-
body { font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #e0e0e0;}
|
8
|
-
div.wrap {
|
9
|
-
background: transparent;
|
10
|
-
text-align: left;
|
11
|
-
width: 400px;
|
12
|
-
margin-top: 100px;
|
13
|
-
margin-left: auto;
|
14
|
-
margin-right: auto;
|
15
|
-
}
|
16
|
-
div.box {
|
17
|
-
border-left: 1px solid #333;
|
18
|
-
border-right: 1px solid #333;
|
19
|
-
background: #FFF;
|
20
|
-
display: block;
|
21
|
-
}
|
22
|
-
img { padding-right: 20px;}
|
23
|
-
h1 { display: inline; font-weight: bold; }
|
24
|
-
h2 { display: inline; font-weight: bold; padding-left: 25px;text-align: center;}
|
25
|
-
div.header { font-size: x-large; }
|
26
|
-
div.content { font-size: x-large; border: 0; padding: 10px 25px 10px 25px;}
|
27
|
-
div.footer { text-align: right; width: 400px; }
|
28
|
-
|
29
|
-
.curved { background: transparent;}
|
30
|
-
.curved .c1, .curved .c2, .curved .c3, .curved .c4 {
|
31
|
-
display: block;
|
32
|
-
overflow: hidden;
|
33
|
-
height: 1px;
|
34
|
-
font-size: 1px;
|
35
|
-
}
|
36
|
-
.curved .c2, .curved .c3, .curved .c4 {
|
37
|
-
background: #fff;
|
38
|
-
border-left: 1px solid #000;
|
39
|
-
border-right: 1px solid #000;
|
40
|
-
}
|
41
|
-
.c1 { margin: 0 5px 0 5px; background: #000; }
|
42
|
-
.c2 { margin: 0 3px 0 3px; border-left: 2px solid #000; border-right: 2px solid #000; }
|
43
|
-
.c3 { margin: 0 2px 0 2px; }
|
44
|
-
.c4 { margin: 0 1px 0 1px; }
|
45
|
-
</style>
|
6
|
+
<link rel="stylesheet" href="/css/error.css" type="text/css" />
|
46
7
|
</head>
|
47
8
|
<body>
|
48
9
|
<div class="wrap">
|
Binary file
|
data/resources/listing.rhtml
CHANGED
@@ -3,37 +3,7 @@
|
|
3
3
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
|
4
4
|
<head>
|
5
5
|
<title>Index of <%= base_uri %></title>
|
6
|
-
|
7
|
-
a, a:active { text-decoration: none; color: blue;}
|
8
|
-
a:visited { color: purple;}
|
9
|
-
a:hover, a:focus { text-decoration: underline; color: red;}
|
10
|
-
body { font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #eee; }
|
11
|
-
.c { text-align: center; }
|
12
|
-
table { border-collapse: collapse; border-spacing: 0px; width: 100%;}
|
13
|
-
tr { background-color: #ccf;}
|
14
|
-
tr:hover { background-color: #faa;}
|
15
|
-
td, th {
|
16
|
-
border-bottom: 1px solid #ccc;
|
17
|
-
padding: 0em .3em 0em .3em ;
|
18
|
-
color: #666;
|
19
|
-
text-align: left;
|
20
|
-
vertical-align: middle;
|
21
|
-
}
|
22
|
-
thead th {
|
23
|
-
border-top: 2px solid #666;
|
24
|
-
border-bottom: 2px solid #666;
|
25
|
-
font-weight: bold;
|
26
|
-
background: #aaa;
|
27
|
-
color: #fff;
|
28
|
-
text-transform: uppercase;
|
29
|
-
}
|
30
|
-
tr.odd { background-color: #cfc; color: #333;}
|
31
|
-
tr.odd:hover { background-color: #faa; color: #333;}
|
32
|
-
td.n { text-align: right; padding-right: 2em;}
|
33
|
-
div.header { }
|
34
|
-
div.content { background: #FFF; width: 100%;}
|
35
|
-
div.footer { border-top: 2px solid #333; text-align: right;}
|
36
|
-
</style>
|
6
|
+
<link rel="stylesheet" href="/css/listing.css" type="text/css" />
|
37
7
|
</head>
|
38
8
|
<body>
|
39
9
|
<div class="header">
|
@@ -52,6 +22,9 @@
|
|
52
22
|
<img src="<%= entry.icon_url %>" width="16" height="16" alt="icon for type <%= entry.content_type %>" />
|
53
23
|
<% end %>
|
54
24
|
<a href="<%= "#{base_uri.chomp('/')}/#{entry.link}" %>"><%= entry.name %></a>
|
25
|
+
<% if highlighting and entry.content_type != 'Directory' then %>
|
26
|
+
(<a href="<%= "#{base_uri.chomp('/')}/#{entry.link}?highlighting=false" %>">download</a>)
|
27
|
+
<% end %>
|
55
28
|
</td>
|
56
29
|
<td><%= entry.last_modified %></td>
|
57
30
|
<td class="<%= entry.content_type == "Directory" ? 'c' : 'n' %>" ><%= entry.size %></td>
|
data/spec/dir_handler_spec.rb
CHANGED
@@ -4,7 +4,7 @@ require 'stringio'
|
|
4
4
|
|
5
5
|
describe Heel::DirHandler do
|
6
6
|
before(:each) do
|
7
|
-
@handler = Heel::DirHandler.new
|
7
|
+
@handler = Heel::DirHandler.new({:highlighting => true})
|
8
8
|
@classifier = Mongrel::URIClassifier.new
|
9
9
|
@classifier.register("/",1)
|
10
10
|
@socket = StringIO.new
|
@@ -26,7 +26,80 @@ describe Heel::DirHandler do
|
|
26
26
|
@response.finished
|
27
27
|
|
28
28
|
@response.status.should == 200
|
29
|
-
@
|
29
|
+
@socket.string.should =~ /Index of/m
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should return an existing directory index page if it exists" do
|
33
|
+
File.open("index.html", "w") { |f| f.write('delete me') }
|
34
|
+
@params[Mongrel::Const::REQUEST_URI] = "/"
|
35
|
+
junk1,path_info,junk2 = @classifier.resolve(@params[Mongrel::Const::REQUEST_URI])
|
36
|
+
|
37
|
+
@params[Mongrel::Const::PATH_INFO] = path_info
|
38
|
+
@request = Mongrel::HttpRequest.new(@params,@socket,nil)
|
39
|
+
|
40
|
+
@handler.process(@request,@response)
|
41
|
+
@response.finished
|
42
|
+
File.unlink("index.html")
|
43
|
+
|
44
|
+
@response.status.should == 200
|
45
|
+
@socket.string.should =~ /delete me/m
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should return a 403 if a request for an ignorable file is made" do
|
49
|
+
File.open(".htaccess", "w") { |f| f.write('delete me') }
|
50
|
+
@params[Mongrel::Const::REQUEST_URI] = "/.htaccess"
|
51
|
+
junk1,path_info,junk2 = @classifier.resolve(@params[Mongrel::Const::REQUEST_URI])
|
52
|
+
|
53
|
+
@params[Mongrel::Const::PATH_INFO] = path_info
|
54
|
+
@request = Mongrel::HttpRequest.new(@params,@socket,nil)
|
55
|
+
|
56
|
+
@handler.process(@request,@response)
|
57
|
+
@response.finished
|
58
|
+
|
59
|
+
File.unlink(".htaccess")
|
60
|
+
@response.status.should == 403
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should return a 403 if an invalid request method is used" do
|
65
|
+
@params[Mongrel::Const::REQUEST_METHOD] = "PUT"
|
66
|
+
@params[Mongrel::Const::REQUEST_URI] = "/"
|
67
|
+
junk1,path_info,junk2 = @classifier.resolve(@params[Mongrel::Const::REQUEST_URI])
|
68
|
+
|
69
|
+
@params[Mongrel::Const::PATH_INFO] = path_info
|
70
|
+
@request = Mongrel::HttpRequest.new(@params,@socket,nil)
|
71
|
+
|
72
|
+
@handler.process(@request,@response)
|
73
|
+
@response.finished
|
74
|
+
|
75
|
+
@response.status.should == 403
|
76
|
+
@socket.string.should =~ /Only HEAD and GET requests are honored./m
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should format a ruby file and return it as a content-type text/html" do
|
80
|
+
@params[Mongrel::Const::REQUEST_URI] = "/spec/" + File.basename(__FILE__)
|
81
|
+
junk1,path_info,junk2 = @classifier.resolve(@params[Mongrel::Const::REQUEST_URI])
|
82
|
+
|
83
|
+
@params[Mongrel::Const::PATH_INFO] = path_info
|
84
|
+
@request = Mongrel::HttpRequest.new(@params,@socket,nil)
|
85
|
+
@handler.process(@request,@response)
|
86
|
+
@response.finished
|
87
|
+
@response.status.should == 200
|
88
|
+
@socket.string.should =~ /Content-Type: text\/html/m
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should parse the highlighting cgi parameter and return non-highlighted text if highlighting=off" do
|
93
|
+
@params[Mongrel::Const::REQUEST_URI] = "/spec/" + File.basename(__FILE__)
|
94
|
+
@params['QUERY_STRING'] = "highlighting=off"
|
95
|
+
junk1,path_info,junk2 = @classifier.resolve(@params[Mongrel::Const::REQUEST_URI])
|
96
|
+
|
97
|
+
@params[Mongrel::Const::PATH_INFO] = path_info
|
98
|
+
@request = Mongrel::HttpRequest.new(@params,@socket,nil)
|
99
|
+
@handler.process(@request,@response)
|
100
|
+
@response.finished
|
101
|
+
@response.status.should == 200
|
102
|
+
@socket.string.should =~ /Content-Type: text\/plain/m
|
30
103
|
end
|
31
104
|
|
32
105
|
it "should return icons appropriately for unknown mime_type" do
|
@@ -36,4 +109,20 @@ describe Heel::DirHandler do
|
|
36
109
|
it "should test if templates need to be reloaded" do
|
37
110
|
@handler.reload_template_changes?.should == false
|
38
111
|
end
|
112
|
+
|
113
|
+
it "should return 403 if we access something that exists but is not a readable file" do
|
114
|
+
File.open("deleteme.html", "w") { |f| f.write('delete me') }
|
115
|
+
File.chmod(0111, "deleteme.html")
|
116
|
+
@params[Mongrel::Const::REQUEST_URI] = "/deleteme.html"
|
117
|
+
junk1,path_info,junk2 = @classifier.resolve(@params[Mongrel::Const::REQUEST_URI])
|
118
|
+
|
119
|
+
@params[Mongrel::Const::PATH_INFO] = path_info
|
120
|
+
@request = Mongrel::HttpRequest.new(@params,@socket,nil)
|
121
|
+
|
122
|
+
@handler.process(@request,@response)
|
123
|
+
@response.finished
|
124
|
+
File.unlink("deleteme.html")
|
125
|
+
|
126
|
+
@response.status.should == 403
|
127
|
+
end
|
39
128
|
end
|
data/spec/error_handler_spec.rb
CHANGED
data/spec/server_spec.rb
CHANGED
@@ -63,6 +63,12 @@ describe Heel::Server do
|
|
63
63
|
server.options.port.should == 4242
|
64
64
|
end
|
65
65
|
|
66
|
+
it "should allow the highlighting option to be unset" do
|
67
|
+
server = Heel::Server.new(%w[--no-highlighting])
|
68
|
+
server.merge_options
|
69
|
+
server.options.highlighting.should == false
|
70
|
+
end
|
71
|
+
|
66
72
|
it "should set no-launch-browser option and kill option" do
|
67
73
|
server = Heel::Server.new(%w[--no-launch-browser])
|
68
74
|
server.merge_options
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.2
|
|
3
3
|
specification_version: 1
|
4
4
|
name: heel
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.
|
7
|
-
date: 2007-11-
|
6
|
+
version: 0.5.0
|
7
|
+
date: 2007-11-19 00:00:00 -07:00
|
8
8
|
summary: A mongrel based static file webserver.
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -43,11 +43,17 @@ files:
|
|
43
43
|
- lib/heel/specification.rb
|
44
44
|
- lib/heel/version.rb
|
45
45
|
- lib/heel.rb
|
46
|
+
- resources/css
|
47
|
+
- resources/css/coderay-cycnus.css
|
48
|
+
- resources/css/coderay-murphy.css
|
49
|
+
- resources/css/error.css
|
50
|
+
- resources/css/listing.css
|
46
51
|
- resources/error.rhtml
|
47
52
|
- resources/famfamfam
|
48
53
|
- resources/famfamfam/icons
|
49
54
|
- resources/famfamfam/icons/application.png
|
50
55
|
- resources/famfamfam/icons/compress.png
|
56
|
+
- resources/famfamfam/icons/error.png
|
51
57
|
- resources/famfamfam/icons/folder.png
|
52
58
|
- resources/famfamfam/icons/html.png
|
53
59
|
- resources/famfamfam/icons/page_excel.png
|
@@ -112,3 +118,21 @@ dependencies:
|
|
112
118
|
- !ruby/object:Gem::Version
|
113
119
|
version: "1.15"
|
114
120
|
version:
|
121
|
+
- !ruby/object:Gem::Dependency
|
122
|
+
name: coderay
|
123
|
+
version_requirement:
|
124
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
125
|
+
requirements:
|
126
|
+
- - ">="
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
version: 0.7.4.215
|
129
|
+
version:
|
130
|
+
- !ruby/object:Gem::Dependency
|
131
|
+
name: rake
|
132
|
+
version_requirement:
|
133
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
134
|
+
requirements:
|
135
|
+
- - ">="
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: 0.7.3
|
138
|
+
version:
|