rack 0.4.0 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rack might be problematic. Click here for more details.
- data/RDOX +61 -3
- data/README +52 -37
- data/Rakefile +9 -0
- data/SPEC +6 -3
- data/bin/rackup +0 -0
- data/lib/rack.rb +7 -2
- data/lib/rack/adapter/camping.rb +1 -1
- data/lib/rack/auth/openid.rb +4 -3
- data/lib/rack/builder.rb +12 -1
- data/lib/rack/conditionalget.rb +43 -0
- data/lib/rack/content_length.rb +25 -0
- data/lib/rack/deflater.rb +29 -5
- data/lib/rack/directory.rb +82 -91
- data/lib/rack/file.rb +45 -76
- data/lib/rack/handler.rb +4 -0
- data/lib/rack/handler/evented_mongrel.rb +1 -1
- data/lib/rack/handler/fastcgi.rb +2 -0
- data/lib/rack/handler/mongrel.rb +6 -2
- data/lib/rack/handler/swiftiplied_mongrel.rb +8 -0
- data/lib/rack/handler/thin.rb +15 -0
- data/lib/rack/handler/webrick.rb +8 -4
- data/lib/rack/head.rb +19 -0
- data/lib/rack/lint.rb +74 -10
- data/lib/rack/lobster.rb +13 -13
- data/lib/rack/methodoverride.rb +27 -0
- data/lib/rack/mime.rb +204 -0
- data/lib/rack/request.rb +10 -1
- data/lib/rack/response.rb +7 -2
- data/lib/rack/session/abstract/id.rb +14 -1
- data/lib/rack/session/cookie.rb +19 -1
- data/lib/rack/session/memcache.rb +1 -1
- data/lib/rack/session/pool.rb +1 -1
- data/lib/rack/showexceptions.rb +5 -1
- data/lib/rack/showstatus.rb +3 -2
- data/lib/rack/urlmap.rb +1 -1
- data/lib/rack/utils.rb +42 -13
- data/test/cgi/lighttpd.conf +1 -1
- data/test/cgi/test +0 -0
- data/test/cgi/test.fcgi +0 -0
- data/test/cgi/test.ru +0 -0
- data/test/spec_rack_builder.rb +34 -0
- data/test/spec_rack_conditionalget.rb +41 -0
- data/test/spec_rack_content_length.rb +43 -0
- data/test/spec_rack_deflater.rb +49 -14
- data/test/spec_rack_file.rb +7 -0
- data/test/spec_rack_handler.rb +3 -3
- data/test/spec_rack_head.rb +30 -0
- data/test/spec_rack_lint.rb +79 -2
- data/test/spec_rack_methodoverride.rb +60 -0
- data/test/spec_rack_mock.rb +1 -1
- data/test/spec_rack_mongrel.rb +20 -1
- data/test/spec_rack_request.rb +46 -1
- data/test/spec_rack_response.rb +10 -3
- data/test/spec_rack_session_cookie.rb +33 -0
- data/test/spec_rack_thin.rb +90 -0
- data/test/spec_rack_utils.rb +20 -18
- data/test/spec_rack_webrick.rb +17 -0
- data/test/testrequest.rb +12 -0
- metadata +91 -5
data/lib/rack/handler.rb
CHANGED
@@ -29,16 +29,20 @@ module Rack
|
|
29
29
|
autoload :FastCGI, "rack/handler/fastcgi"
|
30
30
|
autoload :Mongrel, "rack/handler/mongrel"
|
31
31
|
autoload :EventedMongrel, "rack/handler/evented_mongrel"
|
32
|
+
autoload :SwiftipliedMongrel, "rack/handler/swiftiplied_mongrel"
|
32
33
|
autoload :WEBrick, "rack/handler/webrick"
|
33
34
|
autoload :LSWS, "rack/handler/lsws"
|
34
35
|
autoload :SCGI, "rack/handler/scgi"
|
36
|
+
autoload :Thin, "rack/handler/thin"
|
35
37
|
|
36
38
|
register 'cgi', 'Rack::Handler::CGI'
|
37
39
|
register 'fastcgi', 'Rack::Handler::FastCGI'
|
38
40
|
register 'mongrel', 'Rack::Handler::Mongrel'
|
39
41
|
register 'emongrel', 'Rack::Handler::EventedMongrel'
|
42
|
+
register 'smongrel', 'Rack::Handler::SwiftipliedMongrel'
|
40
43
|
register 'webrick', 'Rack::Handler::WEBrick'
|
41
44
|
register 'lsws', 'Rack::Handler::LSWS'
|
42
45
|
register 'scgi', 'Rack::Handler::SCGI'
|
46
|
+
register 'thin', 'Rack::Handler::Thin'
|
43
47
|
end
|
44
48
|
end
|
data/lib/rack/handler/fastcgi.rb
CHANGED
@@ -51,6 +51,8 @@ module Rack
|
|
51
51
|
env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"]
|
52
52
|
env["REQUEST_PATH"] ||= "/"
|
53
53
|
env.delete "PATH_INFO" if env["PATH_INFO"] == ""
|
54
|
+
env.delete "CONTENT_TYPE" if env["CONTENT_TYPE"] == ""
|
55
|
+
env.delete "CONTENT_LENGTH" if env["CONTENT_LENGTH"] == ""
|
54
56
|
|
55
57
|
status, headers, body = app.call(env)
|
56
58
|
begin
|
data/lib/rack/handler/mongrel.rb
CHANGED
@@ -60,15 +60,19 @@ module Rack
|
|
60
60
|
|
61
61
|
begin
|
62
62
|
response.status = status.to_i
|
63
|
+
response.send_status(nil)
|
64
|
+
|
63
65
|
headers.each { |k, vs|
|
64
66
|
vs.each { |v|
|
65
67
|
response.header[k] = v
|
66
68
|
}
|
67
69
|
}
|
70
|
+
response.send_header
|
71
|
+
|
68
72
|
body.each { |part|
|
69
|
-
response.
|
73
|
+
response.write part
|
74
|
+
response.socket.flush
|
70
75
|
}
|
71
|
-
response.finished
|
72
76
|
ensure
|
73
77
|
body.close if body.respond_to? :close
|
74
78
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require "thin"
|
2
|
+
|
3
|
+
module Rack
|
4
|
+
module Handler
|
5
|
+
class Thin
|
6
|
+
def self.run(app, options={})
|
7
|
+
server = ::Thin::Server.new(options[:Host] || '0.0.0.0',
|
8
|
+
options[:Port] || 8080,
|
9
|
+
app)
|
10
|
+
yield server if block_given?
|
11
|
+
server.start
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/rack/handler/webrick.rb
CHANGED
@@ -3,7 +3,7 @@ require 'stringio'
|
|
3
3
|
|
4
4
|
module Rack
|
5
5
|
module Handler
|
6
|
-
class WEBrick < WEBrick::HTTPServlet::AbstractServlet
|
6
|
+
class WEBrick < ::WEBrick::HTTPServlet::AbstractServlet
|
7
7
|
def self.run(app, options={})
|
8
8
|
server = ::WEBrick::HTTPServer.new(options)
|
9
9
|
server.mount "/", Rack::Handler::WEBrick, app
|
@@ -41,9 +41,13 @@ module Rack
|
|
41
41
|
begin
|
42
42
|
res.status = status.to_i
|
43
43
|
headers.each { |k, vs|
|
44
|
-
|
45
|
-
res
|
46
|
-
|
44
|
+
if k.downcase == "set-cookie"
|
45
|
+
res.cookies.concat vs.to_a
|
46
|
+
else
|
47
|
+
vs.each { |v|
|
48
|
+
res[k] = v
|
49
|
+
}
|
50
|
+
end
|
47
51
|
}
|
48
52
|
body.each { |part|
|
49
53
|
res.body << part
|
data/lib/rack/head.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
module Rack
|
2
|
+
|
3
|
+
class Head
|
4
|
+
def initialize(app)
|
5
|
+
@app = app
|
6
|
+
end
|
7
|
+
|
8
|
+
def call(env)
|
9
|
+
status, headers, body = @app.call(env)
|
10
|
+
|
11
|
+
if env["REQUEST_METHOD"] == "HEAD"
|
12
|
+
[status, headers, []]
|
13
|
+
else
|
14
|
+
[status, headers, body]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
data/lib/rack/lint.rb
CHANGED
@@ -29,8 +29,8 @@ module Rack
|
|
29
29
|
|
30
30
|
## A Rack application is an Ruby object (not a class) that
|
31
31
|
## responds to +call+.
|
32
|
-
def call(env=nil)
|
33
|
-
dup._call(env)
|
32
|
+
def call(env=nil)
|
33
|
+
dup._call(env)
|
34
34
|
end
|
35
35
|
|
36
36
|
def _call(env)
|
@@ -49,6 +49,7 @@ module Rack
|
|
49
49
|
check_headers headers
|
50
50
|
## and the *body*.
|
51
51
|
check_content_type status, headers
|
52
|
+
check_content_length status, headers, env
|
52
53
|
[status, headers, self]
|
53
54
|
end
|
54
55
|
|
@@ -162,11 +163,9 @@ module Rack
|
|
162
163
|
## * There must be a valid error stream in <tt>rack.errors</tt>.
|
163
164
|
check_error env["rack.errors"]
|
164
165
|
|
165
|
-
## * The <tt>REQUEST_METHOD</tt> must be
|
166
|
-
## +DELETE+, +HEAD+, +OPTIONS+, +TRACE+.
|
166
|
+
## * The <tt>REQUEST_METHOD</tt> must be a valid token.
|
167
167
|
assert("REQUEST_METHOD unknown: #{env["REQUEST_METHOD"]}") {
|
168
|
-
|
169
|
-
HEAD OPTIONS TRACE].include?(env["REQUEST_METHOD"])
|
168
|
+
env["REQUEST_METHOD"] =~ /\A[0-9A-Za-z!\#$%&'*+.^_`|~-]+\z/
|
170
169
|
}
|
171
170
|
|
172
171
|
## * The <tt>SCRIPT_NAME</tt>, if non-empty, must start with <tt>/</tt>
|
@@ -215,6 +214,14 @@ module Rack
|
|
215
214
|
@input = input
|
216
215
|
end
|
217
216
|
|
217
|
+
def size
|
218
|
+
@input.size
|
219
|
+
end
|
220
|
+
|
221
|
+
def rewind
|
222
|
+
@input.rewind
|
223
|
+
end
|
224
|
+
|
218
225
|
## * +gets+ must be called without arguments and return a string,
|
219
226
|
## or +nil+ on EOF.
|
220
227
|
def gets(*args)
|
@@ -350,18 +357,75 @@ module Rack
|
|
350
357
|
def check_content_type(status, headers)
|
351
358
|
headers.each { |key, value|
|
352
359
|
## There must be a <tt>Content-Type</tt>, except when the
|
353
|
-
## +Status+ is 204 or 304, in which case there must be none
|
360
|
+
## +Status+ is 1xx, 204 or 304, in which case there must be none
|
354
361
|
## given.
|
355
362
|
if key.downcase == "content-type"
|
356
|
-
assert("Content-Type header found in #{status} response, not allowed"){
|
357
|
-
not
|
363
|
+
assert("Content-Type header found in #{status} response, not allowed") {
|
364
|
+
not Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.include? status.to_i
|
358
365
|
}
|
359
366
|
return
|
360
367
|
end
|
361
368
|
}
|
362
369
|
assert("No Content-Type header found") {
|
363
|
-
|
370
|
+
Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.include? status.to_i
|
371
|
+
}
|
372
|
+
end
|
373
|
+
|
374
|
+
## === The Content-Length
|
375
|
+
def check_content_length(status, headers, env)
|
376
|
+
chunked_response = false
|
377
|
+
headers.each { |key, value|
|
378
|
+
if key.downcase == 'transfer-encoding'
|
379
|
+
chunked_response = value.downcase != 'identity'
|
380
|
+
end
|
381
|
+
}
|
382
|
+
|
383
|
+
headers.each { |key, value|
|
384
|
+
if key.downcase == 'content-length'
|
385
|
+
## There must be a <tt>Content-Length</tt>, except when the
|
386
|
+
## +Status+ is 1xx, 204 or 304, in which case there must be none
|
387
|
+
## given.
|
388
|
+
assert("Content-Length header found in #{status} response, not allowed") {
|
389
|
+
not Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.include? status.to_i
|
390
|
+
}
|
391
|
+
|
392
|
+
assert('Content-Length header should not be used if body is chunked') {
|
393
|
+
not chunked_response
|
394
|
+
}
|
395
|
+
|
396
|
+
bytes = 0
|
397
|
+
string_body = true
|
398
|
+
|
399
|
+
@body.each { |part|
|
400
|
+
unless part.kind_of?(String)
|
401
|
+
string_body = false
|
402
|
+
break
|
403
|
+
end
|
404
|
+
|
405
|
+
bytes += (part.respond_to?(:bytesize) ? part.bytesize : part.size)
|
406
|
+
}
|
407
|
+
|
408
|
+
if env["REQUEST_METHOD"] == "HEAD"
|
409
|
+
assert("Response body was given for HEAD request, but should be empty") {
|
410
|
+
bytes == 0
|
411
|
+
}
|
412
|
+
else
|
413
|
+
if string_body
|
414
|
+
assert("Content-Length header was #{value}, but should be #{bytes}") {
|
415
|
+
value == bytes.to_s
|
416
|
+
}
|
417
|
+
end
|
418
|
+
end
|
419
|
+
|
420
|
+
return
|
421
|
+
end
|
364
422
|
}
|
423
|
+
|
424
|
+
if [ String, Array ].include?(@body.class) && !chunked_response
|
425
|
+
assert('No Content-Length header found') {
|
426
|
+
Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.include? status.to_i
|
427
|
+
}
|
428
|
+
end
|
365
429
|
end
|
366
430
|
|
367
431
|
## === The Body
|
data/lib/rack/lobster.rb
CHANGED
@@ -22,11 +22,11 @@ module Rack
|
|
22
22
|
href = "?flip"
|
23
23
|
end
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
]
|
25
|
+
content = ["<title>Lobstericious!</title>",
|
26
|
+
"<pre>", lobster, "</pre>",
|
27
|
+
"<a href='#{href}'>flip!</a>"]
|
28
|
+
length = content.inject(0) { |a,e| a+e.size }.to_s
|
29
|
+
[200, {"Content-Type" => "text/html", "Content-Length" => length}, content]
|
30
30
|
}
|
31
31
|
|
32
32
|
def call(env)
|
@@ -43,14 +43,14 @@ module Rack
|
|
43
43
|
href = "?flip=left"
|
44
44
|
end
|
45
45
|
|
46
|
-
Response.new
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
46
|
+
res = Response.new
|
47
|
+
res.write "<title>Lobstericious!</title>"
|
48
|
+
res.write "<pre>"
|
49
|
+
res.write lobster
|
50
|
+
res.write "</pre>"
|
51
|
+
res.write "<p><a href='#{href}'>flip!</a></p>"
|
52
|
+
res.write "<p><a href='?flip=crash'>crash!</a></p>"
|
53
|
+
res.finish
|
54
54
|
end
|
55
55
|
|
56
56
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Rack
|
2
|
+
class MethodOverride
|
3
|
+
HTTP_METHODS = %w(GET HEAD PUT POST DELETE OPTIONS)
|
4
|
+
|
5
|
+
METHOD_OVERRIDE_PARAM_KEY = "_method".freeze
|
6
|
+
HTTP_METHOD_OVERRIDE_HEADER = "HTTP_X_HTTP_METHOD_OVERRIDE".freeze
|
7
|
+
|
8
|
+
def initialize(app)
|
9
|
+
@app = app
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(env)
|
13
|
+
if env["REQUEST_METHOD"] == "POST"
|
14
|
+
req = Request.new(env)
|
15
|
+
method = req.POST[METHOD_OVERRIDE_PARAM_KEY] ||
|
16
|
+
env[HTTP_METHOD_OVERRIDE_HEADER]
|
17
|
+
method = method.to_s.upcase
|
18
|
+
if HTTP_METHODS.include?(method)
|
19
|
+
env["rack.methodoverride.original_method"] = env["REQUEST_METHOD"]
|
20
|
+
env["REQUEST_METHOD"] = method
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
@app.call(env)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/rack/mime.rb
ADDED
@@ -0,0 +1,204 @@
|
|
1
|
+
module Rack
|
2
|
+
module Mime
|
3
|
+
# Returns String with mime type if found, otherwise use +fallback+.
|
4
|
+
# +ext+ should be filename extension in the '.ext' format that
|
5
|
+
# File.extname(file) returns.
|
6
|
+
# +fallback+ may be any object
|
7
|
+
#
|
8
|
+
# Also see the documentation for MIME_TYPES
|
9
|
+
#
|
10
|
+
# Usage:
|
11
|
+
# Rack::Utils.mime_type('.foo')
|
12
|
+
#
|
13
|
+
# This is a shortcut for:
|
14
|
+
# Rack::Utils::MIME_TYPES.fetch('.foo', 'application/octet-stream')
|
15
|
+
|
16
|
+
def mime_type(ext, fallback='application/octet-stream')
|
17
|
+
MIME_TYPES.fetch(ext, fallback)
|
18
|
+
end
|
19
|
+
module_function :mime_type
|
20
|
+
|
21
|
+
# List of most common mime-types, selected various sources
|
22
|
+
# according to their usefulness in a webserving scope for Ruby
|
23
|
+
# users.
|
24
|
+
#
|
25
|
+
# To amend this list with your local mime.types list you can use:
|
26
|
+
#
|
27
|
+
# require 'webrick/httputils'
|
28
|
+
# list = WEBrick::HTTPUtils.load_mime_types('/etc/mime.types')
|
29
|
+
# Rack::Utils::MIME_TYPES.merge!(list)
|
30
|
+
#
|
31
|
+
# To add the list mongrel provides, use:
|
32
|
+
#
|
33
|
+
# require 'mongrel/handlers'
|
34
|
+
# Rack::Utils::MIME_TYPES.merge!(Mongrel::DirHandler::MIME_TYPES)
|
35
|
+
|
36
|
+
MIME_TYPES = {
|
37
|
+
".3gp" => "video/3gpp",
|
38
|
+
".a" => "application/octet-stream",
|
39
|
+
".ai" => "application/postscript",
|
40
|
+
".aif" => "audio/x-aiff",
|
41
|
+
".aiff" => "audio/x-aiff",
|
42
|
+
".asc" => "application/pgp-signature",
|
43
|
+
".asf" => "video/x-ms-asf",
|
44
|
+
".asm" => "text/x-asm",
|
45
|
+
".asx" => "video/x-ms-asf",
|
46
|
+
".atom" => "application/atom+xml",
|
47
|
+
".au" => "audio/basic",
|
48
|
+
".avi" => "video/x-msvideo",
|
49
|
+
".bat" => "application/x-msdownload",
|
50
|
+
".bin" => "application/octet-stream",
|
51
|
+
".bmp" => "image/bmp",
|
52
|
+
".bz2" => "application/x-bzip2",
|
53
|
+
".c" => "text/x-c",
|
54
|
+
".cab" => "application/vnd.ms-cab-compressed",
|
55
|
+
".cc" => "text/x-c",
|
56
|
+
".chm" => "application/vnd.ms-htmlhelp",
|
57
|
+
".class" => "application/octet-stream",
|
58
|
+
".com" => "application/x-msdownload",
|
59
|
+
".conf" => "text/plain",
|
60
|
+
".cpp" => "text/x-c",
|
61
|
+
".crt" => "application/x-x509-ca-cert",
|
62
|
+
".css" => "text/css",
|
63
|
+
".csv" => "text/csv",
|
64
|
+
".cxx" => "text/x-c",
|
65
|
+
".deb" => "application/x-debian-package",
|
66
|
+
".der" => "application/x-x509-ca-cert",
|
67
|
+
".diff" => "text/x-diff",
|
68
|
+
".djv" => "image/vnd.djvu",
|
69
|
+
".djvu" => "image/vnd.djvu",
|
70
|
+
".dll" => "application/x-msdownload",
|
71
|
+
".dmg" => "application/octet-stream",
|
72
|
+
".doc" => "application/msword",
|
73
|
+
".dot" => "application/msword",
|
74
|
+
".dtd" => "application/xml-dtd",
|
75
|
+
".dvi" => "application/x-dvi",
|
76
|
+
".ear" => "application/java-archive",
|
77
|
+
".eml" => "message/rfc822",
|
78
|
+
".eps" => "application/postscript",
|
79
|
+
".exe" => "application/x-msdownload",
|
80
|
+
".f" => "text/x-fortran",
|
81
|
+
".f77" => "text/x-fortran",
|
82
|
+
".f90" => "text/x-fortran",
|
83
|
+
".flv" => "video/x-flv",
|
84
|
+
".for" => "text/x-fortran",
|
85
|
+
".gem" => "application/octet-stream",
|
86
|
+
".gemspec" => "text/x-script.ruby",
|
87
|
+
".gif" => "image/gif",
|
88
|
+
".gz" => "application/x-gzip",
|
89
|
+
".h" => "text/x-c",
|
90
|
+
".hh" => "text/x-c",
|
91
|
+
".htm" => "text/html",
|
92
|
+
".html" => "text/html",
|
93
|
+
".ico" => "image/vnd.microsoft.icon",
|
94
|
+
".ics" => "text/calendar",
|
95
|
+
".ifb" => "text/calendar",
|
96
|
+
".iso" => "application/octet-stream",
|
97
|
+
".jar" => "application/java-archive",
|
98
|
+
".java" => "text/x-java-source",
|
99
|
+
".jnlp" => "application/x-java-jnlp-file",
|
100
|
+
".jpeg" => "image/jpeg",
|
101
|
+
".jpg" => "image/jpeg",
|
102
|
+
".js" => "application/javascript",
|
103
|
+
".json" => "application/json",
|
104
|
+
".log" => "text/plain",
|
105
|
+
".m3u" => "audio/x-mpegurl",
|
106
|
+
".m4v" => "video/mp4",
|
107
|
+
".man" => "text/troff",
|
108
|
+
".mathml" => "application/mathml+xml",
|
109
|
+
".mbox" => "application/mbox",
|
110
|
+
".mdoc" => "text/troff",
|
111
|
+
".me" => "text/troff",
|
112
|
+
".mid" => "audio/midi",
|
113
|
+
".midi" => "audio/midi",
|
114
|
+
".mime" => "message/rfc822",
|
115
|
+
".mml" => "application/mathml+xml",
|
116
|
+
".mng" => "video/x-mng",
|
117
|
+
".mov" => "video/quicktime",
|
118
|
+
".mp3" => "audio/mpeg",
|
119
|
+
".mp4" => "video/mp4",
|
120
|
+
".mp4v" => "video/mp4",
|
121
|
+
".mpeg" => "video/mpeg",
|
122
|
+
".mpg" => "video/mpeg",
|
123
|
+
".ms" => "text/troff",
|
124
|
+
".msi" => "application/x-msdownload",
|
125
|
+
".odp" => "application/vnd.oasis.opendocument.presentation",
|
126
|
+
".ods" => "application/vnd.oasis.opendocument.spreadsheet",
|
127
|
+
".odt" => "application/vnd.oasis.opendocument.text",
|
128
|
+
".ogg" => "application/ogg",
|
129
|
+
".p" => "text/x-pascal",
|
130
|
+
".pas" => "text/x-pascal",
|
131
|
+
".pbm" => "image/x-portable-bitmap",
|
132
|
+
".pdf" => "application/pdf",
|
133
|
+
".pem" => "application/x-x509-ca-cert",
|
134
|
+
".pgm" => "image/x-portable-graymap",
|
135
|
+
".pgp" => "application/pgp-encrypted",
|
136
|
+
".pkg" => "application/octet-stream",
|
137
|
+
".pl" => "text/x-script.perl",
|
138
|
+
".pm" => "text/x-script.perl-module",
|
139
|
+
".png" => "image/png",
|
140
|
+
".pnm" => "image/x-portable-anymap",
|
141
|
+
".ppm" => "image/x-portable-pixmap",
|
142
|
+
".pps" => "application/vnd.ms-powerpoint",
|
143
|
+
".ppt" => "application/vnd.ms-powerpoint",
|
144
|
+
".ps" => "application/postscript",
|
145
|
+
".psd" => "image/vnd.adobe.photoshop",
|
146
|
+
".py" => "text/x-script.python",
|
147
|
+
".qt" => "video/quicktime",
|
148
|
+
".ra" => "audio/x-pn-realaudio",
|
149
|
+
".rake" => "text/x-script.ruby",
|
150
|
+
".ram" => "audio/x-pn-realaudio",
|
151
|
+
".rar" => "application/x-rar-compressed",
|
152
|
+
".rb" => "text/x-script.ruby",
|
153
|
+
".rdf" => "application/rdf+xml",
|
154
|
+
".roff" => "text/troff",
|
155
|
+
".rpm" => "application/x-redhat-package-manager",
|
156
|
+
".rss" => "application/rss+xml",
|
157
|
+
".rtf" => "application/rtf",
|
158
|
+
".ru" => "text/x-script.ruby",
|
159
|
+
".s" => "text/x-asm",
|
160
|
+
".sgm" => "text/sgml",
|
161
|
+
".sgml" => "text/sgml",
|
162
|
+
".sh" => "application/x-sh",
|
163
|
+
".sig" => "application/pgp-signature",
|
164
|
+
".snd" => "audio/basic",
|
165
|
+
".so" => "application/octet-stream",
|
166
|
+
".svg" => "image/svg+xml",
|
167
|
+
".svgz" => "image/svg+xml",
|
168
|
+
".swf" => "application/x-shockwave-flash",
|
169
|
+
".t" => "text/troff",
|
170
|
+
".tar" => "application/x-tar",
|
171
|
+
".tbz" => "application/x-bzip-compressed-tar",
|
172
|
+
".tcl" => "application/x-tcl",
|
173
|
+
".tex" => "application/x-tex",
|
174
|
+
".texi" => "application/x-texinfo",
|
175
|
+
".texinfo" => "application/x-texinfo",
|
176
|
+
".text" => "text/plain",
|
177
|
+
".tif" => "image/tiff",
|
178
|
+
".tiff" => "image/tiff",
|
179
|
+
".torrent" => "application/x-bittorrent",
|
180
|
+
".tr" => "text/troff",
|
181
|
+
".txt" => "text/plain",
|
182
|
+
".vcf" => "text/x-vcard",
|
183
|
+
".vcs" => "text/x-vcalendar",
|
184
|
+
".vrml" => "model/vrml",
|
185
|
+
".war" => "application/java-archive",
|
186
|
+
".wav" => "audio/x-wav",
|
187
|
+
".wma" => "audio/x-ms-wma",
|
188
|
+
".wmv" => "video/x-ms-wmv",
|
189
|
+
".wmx" => "video/x-ms-wmx",
|
190
|
+
".wrl" => "model/vrml",
|
191
|
+
".wsdl" => "application/wsdl+xml",
|
192
|
+
".xbm" => "image/x-xbitmap",
|
193
|
+
".xhtml" => "application/xhtml+xml",
|
194
|
+
".xls" => "application/vnd.ms-excel",
|
195
|
+
".xml" => "application/xml",
|
196
|
+
".xpm" => "image/x-xpixmap",
|
197
|
+
".xsl" => "application/xml",
|
198
|
+
".xslt" => "application/xslt+xml",
|
199
|
+
".yaml" => "text/yaml",
|
200
|
+
".yml" => "text/yaml",
|
201
|
+
".zip" => "application/zip",
|
202
|
+
}
|
203
|
+
end
|
204
|
+
end
|