heel 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/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:
|