sinatra 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of sinatra might be problematic. Click here for more details.

Files changed (83) hide show
  1. data/CHANGELOG +1 -0
  2. data/LICENSE +22 -0
  3. data/Manifest +78 -1
  4. data/lib/sinatra.rb +12 -1
  5. data/sinatra.gemspec +7 -14
  6. data/vendor/rack/AUTHORS +7 -0
  7. data/vendor/rack/COPYING +18 -0
  8. data/vendor/rack/KNOWN-ISSUES +18 -0
  9. data/vendor/rack/README +242 -0
  10. data/vendor/rack/Rakefile +174 -0
  11. data/vendor/rack/bin/rackup +153 -0
  12. data/vendor/rack/contrib/rack_logo.svg +111 -0
  13. data/vendor/rack/example/lobster.ru +4 -0
  14. data/vendor/rack/example/protectedlobster.rb +14 -0
  15. data/vendor/rack/example/protectedlobster.ru +8 -0
  16. data/vendor/rack/lib/rack.rb +92 -0
  17. data/vendor/rack/lib/rack/adapter/camping.rb +22 -0
  18. data/vendor/rack/lib/rack/auth/abstract/handler.rb +28 -0
  19. data/vendor/rack/lib/rack/auth/abstract/request.rb +37 -0
  20. data/vendor/rack/lib/rack/auth/basic.rb +58 -0
  21. data/vendor/rack/lib/rack/auth/digest/md5.rb +124 -0
  22. data/vendor/rack/lib/rack/auth/digest/nonce.rb +51 -0
  23. data/vendor/rack/lib/rack/auth/digest/params.rb +55 -0
  24. data/vendor/rack/lib/rack/auth/digest/request.rb +40 -0
  25. data/vendor/rack/lib/rack/auth/openid.rb +116 -0
  26. data/vendor/rack/lib/rack/builder.rb +56 -0
  27. data/vendor/rack/lib/rack/cascade.rb +36 -0
  28. data/vendor/rack/lib/rack/commonlogger.rb +56 -0
  29. data/vendor/rack/lib/rack/file.rb +112 -0
  30. data/vendor/rack/lib/rack/handler/cgi.rb +57 -0
  31. data/vendor/rack/lib/rack/handler/fastcgi.rb +83 -0
  32. data/vendor/rack/lib/rack/handler/lsws.rb +52 -0
  33. data/vendor/rack/lib/rack/handler/mongrel.rb +78 -0
  34. data/vendor/rack/lib/rack/handler/scgi.rb +57 -0
  35. data/vendor/rack/lib/rack/handler/webrick.rb +57 -0
  36. data/vendor/rack/lib/rack/lint.rb +394 -0
  37. data/vendor/rack/lib/rack/lobster.rb +65 -0
  38. data/vendor/rack/lib/rack/mock.rb +160 -0
  39. data/vendor/rack/lib/rack/recursive.rb +57 -0
  40. data/vendor/rack/lib/rack/reloader.rb +64 -0
  41. data/vendor/rack/lib/rack/request.rb +197 -0
  42. data/vendor/rack/lib/rack/response.rb +166 -0
  43. data/vendor/rack/lib/rack/session/abstract/id.rb +126 -0
  44. data/vendor/rack/lib/rack/session/cookie.rb +71 -0
  45. data/vendor/rack/lib/rack/session/memcache.rb +83 -0
  46. data/vendor/rack/lib/rack/session/pool.rb +67 -0
  47. data/vendor/rack/lib/rack/showexceptions.rb +344 -0
  48. data/vendor/rack/lib/rack/showstatus.rb +103 -0
  49. data/vendor/rack/lib/rack/static.rb +38 -0
  50. data/vendor/rack/lib/rack/urlmap.rb +48 -0
  51. data/vendor/rack/lib/rack/utils.rb +240 -0
  52. data/vendor/rack/test/cgi/lighttpd.conf +20 -0
  53. data/vendor/rack/test/cgi/test +9 -0
  54. data/vendor/rack/test/cgi/test.fcgi +7 -0
  55. data/vendor/rack/test/cgi/test.ru +7 -0
  56. data/vendor/rack/test/spec_rack_auth_basic.rb +69 -0
  57. data/vendor/rack/test/spec_rack_auth_digest.rb +169 -0
  58. data/vendor/rack/test/spec_rack_builder.rb +50 -0
  59. data/vendor/rack/test/spec_rack_camping.rb +47 -0
  60. data/vendor/rack/test/spec_rack_cascade.rb +50 -0
  61. data/vendor/rack/test/spec_rack_cgi.rb +91 -0
  62. data/vendor/rack/test/spec_rack_commonlogger.rb +32 -0
  63. data/vendor/rack/test/spec_rack_fastcgi.rb +91 -0
  64. data/vendor/rack/test/spec_rack_file.rb +40 -0
  65. data/vendor/rack/test/spec_rack_lint.rb +317 -0
  66. data/vendor/rack/test/spec_rack_lobster.rb +45 -0
  67. data/vendor/rack/test/spec_rack_mock.rb +152 -0
  68. data/vendor/rack/test/spec_rack_mongrel.rb +165 -0
  69. data/vendor/rack/test/spec_rack_recursive.rb +77 -0
  70. data/vendor/rack/test/spec_rack_request.rb +384 -0
  71. data/vendor/rack/test/spec_rack_response.rb +167 -0
  72. data/vendor/rack/test/spec_rack_session_cookie.rb +49 -0
  73. data/vendor/rack/test/spec_rack_session_memcache.rb +100 -0
  74. data/vendor/rack/test/spec_rack_session_pool.rb +84 -0
  75. data/vendor/rack/test/spec_rack_showexceptions.rb +21 -0
  76. data/vendor/rack/test/spec_rack_showstatus.rb +71 -0
  77. data/vendor/rack/test/spec_rack_static.rb +37 -0
  78. data/vendor/rack/test/spec_rack_urlmap.rb +175 -0
  79. data/vendor/rack/test/spec_rack_utils.rb +57 -0
  80. data/vendor/rack/test/spec_rack_webrick.rb +106 -0
  81. data/vendor/rack/test/testrequest.rb +43 -0
  82. metadata +81 -4
  83. data/Rakefile +0 -24
@@ -0,0 +1,40 @@
1
+ require 'rack/auth/abstract/request'
2
+ require 'rack/auth/digest/params'
3
+ require 'rack/auth/digest/nonce'
4
+
5
+ module Rack
6
+ module Auth
7
+ module Digest
8
+ class Request < Auth::AbstractRequest
9
+
10
+ def method
11
+ @env['REQUEST_METHOD']
12
+ end
13
+
14
+ def digest?
15
+ :digest == scheme
16
+ end
17
+
18
+ def correct_uri?
19
+ @env['PATH_INFO'] == uri
20
+ end
21
+
22
+ def nonce
23
+ @nonce ||= Nonce.parse(params['nonce'])
24
+ end
25
+
26
+ def params
27
+ @params ||= Params.parse(parts.last)
28
+ end
29
+
30
+ def method_missing(sym)
31
+ if params.has_key? key = sym.to_s
32
+ return params[key]
33
+ end
34
+ super
35
+ end
36
+
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,116 @@
1
+ # AUTHOR: blink <blinketje@gmail.com>; blink#ruby-lang@irc.freenode.net
2
+
3
+ gem_require 'ruby-openid', '~> 1.0.0' if defined? Gem
4
+ require 'rack/auth/abstract/handler'
5
+ require 'openid'
6
+
7
+ module Rack
8
+ module Auth
9
+ # Rack::Auth::OpenID provides a simple method for permitting openid
10
+ # based logins. It requires the ruby-openid lib from janrain to operate,
11
+ # as well as some method of session management of a Hash type.
12
+ #
13
+ # After a transaction, the response status object is stored in the
14
+ # environment at rack.auth.openid.status, which can be used in the
15
+ # followup block or in a wrapping application to accomplish
16
+ # additional data maniipulation.
17
+ #
18
+ # NOTE: Due to the amount of data that ruby-openid stores in the session,
19
+ # Rack::Session::Cookie may fault.
20
+ #
21
+ # A hash of data is stored in the session hash at the key of :openid.
22
+ # The fully canonicalized identity url is stored within at 'identity'.
23
+ # Extension data from 'openid.sreg.nickname' would be stored as
24
+ # { 'nickname' => value }.
25
+ #
26
+ # NOTE: To my knowledge there is no collision at this point from storage
27
+ # of this manner, if there is please let me know so I may adjust this app
28
+ # to cope.
29
+ # NOTE: This rack application is only compatible with the 1.x.x versions
30
+ # of the ruby-openid library. If rubygems is loaded at require time of
31
+ # this app, the specification will be made. If it is not then the 'openid'
32
+ # library will be required, and will fail if it is not compatible.
33
+ class OpenID < AbstractHandler
34
+ # Required for ruby-openid
35
+ OIDStore = ::OpenID::MemoryStore.new
36
+
37
+ # A Hash of options is taken as it's single initializing
38
+ # argument. String keys are taken to be openid protocol
39
+ # extension namespaces.
40
+ #
41
+ # For example: 'sreg' => { 'required' => # 'nickname' }
42
+ #
43
+ # Other keys are taken as options for Rack::Auth::OpenID, normally Symbols.
44
+ # Only :return is required. :trust is highly recommended to be set.
45
+ #
46
+ # * :return defines the url to return to after the client authenticates
47
+ # with the openid service provider. Should point to where this app is
48
+ # mounted. (ex: 'http://mysite.com/openid')
49
+ # * :trust defines the url identifying the site they are actually logging
50
+ # into. (ex: 'http://mysite.com/')
51
+ # * :session_key defines the key to the session hash in the env.
52
+ # (by default it uses 'rack.session')
53
+ def initialize(options={})
54
+ raise ArgumentError, 'No return url provided.' unless options[:return]
55
+ warn 'No trust url provided.' unless options[:trust]
56
+ options[:trust] ||= options[:return]
57
+
58
+ @options = {
59
+ :session_key => 'rack.session'
60
+ }.merge(options)
61
+ end
62
+
63
+ def call(env)
64
+ request = Rack::Request.new env
65
+ return no_session unless session = request.env[@options[:session_key]]
66
+ resp = if request.GET['openid.mode']
67
+ finish session, request.GET, env
68
+ elsif request.GET['openid_url']
69
+ check session, request.GET['openid_url'], env
70
+ else
71
+ bad_request
72
+ end
73
+ end
74
+
75
+ def check(session, oid_url, env)
76
+ consumer = ::OpenID::Consumer.new session, OIDStore
77
+ oid = consumer.begin oid_url
78
+ return auth_fail unless oid.status == ::OpenID::SUCCESS
79
+ @options.each do |ns,s|
80
+ next unless ns.is_a? String
81
+ s.each {|k,v| oid.add_extension_arg(ns, k, v) }
82
+ end
83
+ r_url = @options.fetch :return do |k| request.url end
84
+ t_url = @options.fetch :trust
85
+ env['rack.auth.openid.status'] = oid
86
+ return 303, {'Location'=>oid.redirect_url( t_url, r_url )}, []
87
+ end
88
+
89
+ def finish(session, params, env)
90
+ consumer = ::OpenID::Consumer.new session, OIDStore
91
+ oid = consumer.complete params
92
+ return bad_login unless oid.status == ::OpenID::SUCCESS
93
+ session[:openid] = {'identity' => oid.identity_url}
94
+ @options.each do |ns,s|
95
+ next unless ns.is_a? String
96
+ oid.extension_response(ns).each{|k,v| session[k]=v }
97
+ end
98
+ env['rack.auth.openid.status'] = oid
99
+ return 303, {'Location'=>@options[:trust]}, []
100
+ end
101
+
102
+ def no_session
103
+ @options.
104
+ fetch :no_session, [500,{'Content-Type'=>'text/plain'},'No session available.']
105
+ end
106
+ def auth_fail
107
+ @options.
108
+ fetch :auth_fail, [500, {'Content-Type'=>'text/plain'},'Foreign server failure.']
109
+ end
110
+ def bad_login
111
+ @options.
112
+ fetch :bad_login, [401, {'Content-Type'=>'text/plain'},'Identification has failed.']
113
+ end
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,56 @@
1
+ module Rack
2
+ # Rack::Builder implements a small DSL to iteratively construct Rack
3
+ # applications.
4
+ #
5
+ # Example:
6
+ #
7
+ # app = Rack::Builder.new {
8
+ # use Rack::CommonLogger
9
+ # use Rack::ShowExceptions
10
+ # map "/lobster" do
11
+ # use Rack::Lint
12
+ # run Rack::Lobster.new
13
+ # end
14
+ # }
15
+ #
16
+ # +use+ adds a middleware to the stack, +run+ dispatches to an application.
17
+ # You can use +map+ to construct a Rack::URLMap in a convenient way.
18
+
19
+ class Builder
20
+ def initialize(&block)
21
+ @ins = []
22
+ instance_eval(&block)
23
+ end
24
+
25
+ def use(middleware, *args, &block)
26
+ @ins << if block_given?
27
+ lambda { |app| middleware.new(app, *args, &block) }
28
+ else
29
+ lambda { |app| middleware.new(app, *args) }
30
+ end
31
+ end
32
+
33
+ def run(app)
34
+ @ins << app #lambda { |nothing| app }
35
+ end
36
+
37
+ def map(path, &block)
38
+ if @ins.last.kind_of? Hash
39
+ @ins.last[path] = Rack::Builder.new(&block).to_app
40
+ else
41
+ @ins << {}
42
+ map(path, &block)
43
+ end
44
+ end
45
+
46
+ def to_app
47
+ @ins[-1] = Rack::URLMap.new(@ins.last) if Hash === @ins.last
48
+ inner_app = @ins.last
49
+ @ins[0...-1].reverse.inject(inner_app) { |a, e| e.call(a) }
50
+ end
51
+
52
+ def call(env)
53
+ to_app.call(env)
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,36 @@
1
+ module Rack
2
+ # Rack::Cascade tries an request on several apps, and returns the
3
+ # first response that is not 404 (or in a list of configurable
4
+ # status codes).
5
+
6
+ class Cascade
7
+ attr_reader :apps
8
+
9
+ def initialize(apps, catch=404)
10
+ @apps = apps
11
+ @catch = [*catch]
12
+ end
13
+
14
+ def call(env)
15
+ status = headers = body = nil
16
+ raise ArgumentError, "empty cascade" if @apps.empty?
17
+ @apps.each { |app|
18
+ begin
19
+ status, headers, body = app.call(env)
20
+ break unless @catch.include?(status.to_i)
21
+ end
22
+ }
23
+ [status, headers, body]
24
+ end
25
+
26
+ def add app
27
+ @apps << app
28
+ end
29
+
30
+ def include? app
31
+ @apps.include? app
32
+ end
33
+
34
+ alias_method :<<, :add
35
+ end
36
+ end
@@ -0,0 +1,56 @@
1
+ module Rack
2
+ # Rack::CommonLogger forwards every request to an +app+ given, and
3
+ # logs a line in the Apache common log format to the +logger+, or
4
+ # rack.errors by default.
5
+
6
+ class CommonLogger
7
+ def initialize(app, logger=nil)
8
+ @app = app
9
+ @logger = logger
10
+ end
11
+
12
+ def call(env)
13
+ dup._call(env)
14
+ end
15
+
16
+ def _call(env)
17
+ @env = env
18
+ @logger ||= self
19
+ @time = Time.now
20
+ @status, @header, @body = @app.call(env)
21
+ [@status, @header, self]
22
+ end
23
+
24
+ # By default, log to rack.errors.
25
+ def <<(str)
26
+ @env["rack.errors"].write(str)
27
+ @env["rack.errors"].flush
28
+ end
29
+
30
+ def each
31
+ length = 0
32
+ @body.each { |part|
33
+ length += part.size
34
+ yield part
35
+ }
36
+
37
+ @now = Time.now
38
+
39
+ # Common Log Format: http://httpd.apache.org/docs/1.3/logs.html#common
40
+ # lilith.local - - [07/Aug/2006 23:58:02] "GET / HTTP/1.1" 500 -
41
+ # %{%s - %s [%s] "%s %s%s %s" %d %s\n} %
42
+ @logger << %{%s - %s [%s] "%s %s%s %s" %d %s %0.4f\n} %
43
+ [@env["REMOTE_ADDR"] || "-",
44
+ @env["REMOTE_USER"] || "-",
45
+ @now.strftime("%d/%b/%Y %H:%M:%S"),
46
+ @env["REQUEST_METHOD"],
47
+ @env["PATH_INFO"],
48
+ @env["QUERY_STRING"].empty? ? "" : "?"+@env["QUERY_STRING"],
49
+ @env["HTTP_VERSION"],
50
+ @status.to_s[0..3],
51
+ (length.zero? ? "-" : length.to_s),
52
+ @now - @time
53
+ ]
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,112 @@
1
+ require 'time'
2
+
3
+ module Rack
4
+ # Rack::File serves files below the +root+ given, according to the
5
+ # path info of the Rack request.
6
+ #
7
+ # Handlers can detect if bodies are a Rack::File, and use mechanisms
8
+ # like sendfile on the +path+.
9
+
10
+ class File
11
+ attr_accessor :root
12
+ attr_accessor :path
13
+
14
+ def initialize(root)
15
+ @root = root
16
+ end
17
+
18
+ def call(env)
19
+ dup._call(env)
20
+ end
21
+
22
+ F = ::File
23
+
24
+ def _call(env)
25
+ if env["PATH_INFO"].include? ".."
26
+ return [403, {"Content-Type" => "text/plain"}, ["Forbidden\n"]]
27
+ end
28
+
29
+ @path = F.join(@root, Utils.unescape(env["PATH_INFO"]))
30
+ ext = F.extname(@path)[1..-1]
31
+
32
+ if F.file?(@path) && F.readable?(@path)
33
+ [200, {
34
+ "Last-Modified" => F.mtime(@path).rfc822,
35
+ "Content-Type" => MIME_TYPES[ext] || "text/plain",
36
+ "Content-Length" => F.size(@path).to_s
37
+ }, self]
38
+ else
39
+ return [404, {"Content-Type" => "text/plain"},
40
+ ["File not found: #{env["PATH_INFO"]}\n"]]
41
+ end
42
+ end
43
+
44
+ def each
45
+ F.open(@path, "rb") { |file|
46
+ while part = file.read(8192)
47
+ yield part
48
+ end
49
+ }
50
+ end
51
+
52
+ # :stopdoc:
53
+ # From WEBrick.
54
+ MIME_TYPES = {
55
+ "ai" => "application/postscript",
56
+ "asc" => "text/plain",
57
+ "avi" => "video/x-msvideo",
58
+ "bin" => "application/octet-stream",
59
+ "bmp" => "image/bmp",
60
+ "class" => "application/octet-stream",
61
+ "cer" => "application/pkix-cert",
62
+ "crl" => "application/pkix-crl",
63
+ "crt" => "application/x-x509-ca-cert",
64
+ #"crl" => "application/x-pkcs7-crl",
65
+ "css" => "text/css",
66
+ "dms" => "application/octet-stream",
67
+ "doc" => "application/msword",
68
+ "dvi" => "application/x-dvi",
69
+ "eps" => "application/postscript",
70
+ "etx" => "text/x-setext",
71
+ "exe" => "application/octet-stream",
72
+ "gif" => "image/gif",
73
+ "htm" => "text/html",
74
+ "html" => "text/html",
75
+ "jpe" => "image/jpeg",
76
+ "jpeg" => "image/jpeg",
77
+ "jpg" => "image/jpeg",
78
+ "js" => "text/javascript",
79
+ "lha" => "application/octet-stream",
80
+ "lzh" => "application/octet-stream",
81
+ "mov" => "video/quicktime",
82
+ "mpe" => "video/mpeg",
83
+ "mpeg" => "video/mpeg",
84
+ "mpg" => "video/mpeg",
85
+ "pbm" => "image/x-portable-bitmap",
86
+ "pdf" => "application/pdf",
87
+ "pgm" => "image/x-portable-graymap",
88
+ "png" => "image/png",
89
+ "pnm" => "image/x-portable-anymap",
90
+ "ppm" => "image/x-portable-pixmap",
91
+ "ppt" => "application/vnd.ms-powerpoint",
92
+ "ps" => "application/postscript",
93
+ "qt" => "video/quicktime",
94
+ "ras" => "image/x-cmu-raster",
95
+ "rb" => "text/plain",
96
+ "rd" => "text/plain",
97
+ "rtf" => "application/rtf",
98
+ "sgm" => "text/sgml",
99
+ "sgml" => "text/sgml",
100
+ "tif" => "image/tiff",
101
+ "tiff" => "image/tiff",
102
+ "txt" => "text/plain",
103
+ "xbm" => "image/x-xbitmap",
104
+ "xls" => "application/vnd.ms-excel",
105
+ "xml" => "text/xml",
106
+ "xpm" => "image/x-xpixmap",
107
+ "xwd" => "image/x-xwindowdump",
108
+ "zip" => "application/zip",
109
+ }
110
+ # :startdoc:
111
+ end
112
+ end
@@ -0,0 +1,57 @@
1
+ module Rack
2
+ module Handler
3
+ class CGI
4
+ def self.run(app, options=nil)
5
+ serve app
6
+ end
7
+
8
+ def self.serve(app)
9
+ env = ENV.to_hash
10
+ env.delete "HTTP_CONTENT_LENGTH"
11
+
12
+ env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/"
13
+
14
+ env.update({"rack.version" => [0,1],
15
+ "rack.input" => STDIN,
16
+ "rack.errors" => STDERR,
17
+
18
+ "rack.multithread" => false,
19
+ "rack.multiprocess" => true,
20
+ "rack.run_once" => true,
21
+
22
+ "rack.url_scheme" => ["yes", "on", "1"].include?(ENV["HTTPS"]) ? "https" : "http"
23
+ })
24
+
25
+ env["QUERY_STRING"] ||= ""
26
+ env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"]
27
+ env["REQUEST_PATH"] ||= "/"
28
+
29
+ status, headers, body = app.call(env)
30
+ begin
31
+ send_headers status, headers
32
+ send_body body
33
+ ensure
34
+ body.close if body.respond_to? :close
35
+ end
36
+ end
37
+
38
+ def self.send_headers(status, headers)
39
+ STDOUT.print "Status: #{status}\r\n"
40
+ headers.each { |k, vs|
41
+ vs.each { |v|
42
+ STDOUT.print "#{k}: #{v}\r\n"
43
+ }
44
+ }
45
+ STDOUT.print "\r\n"
46
+ STDOUT.flush
47
+ end
48
+
49
+ def self.send_body(body)
50
+ body.each { |part|
51
+ STDOUT.print part
52
+ STDOUT.flush
53
+ }
54
+ end
55
+ end
56
+ end
57
+ end