colouringcode-passenger 0.1 → 0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (170) hide show
  1. data/NEWS +129 -0
  2. data/Rakefile +2 -2
  3. data/bin/passenger-install-apache2-module +1 -0
  4. data/bin/passenger-install-nginx-module +4 -2
  5. data/ext/apache2/Hooks.cpp +4 -2
  6. data/ext/common/ApplicationPoolServer.h +1 -1
  7. data/ext/common/ApplicationPoolServerExecutable.cpp +1 -1
  8. data/ext/common/MessageChannel.h +48 -4
  9. data/ext/common/StandardApplicationPool.h +4 -2
  10. data/ext/common/Version.h +1 -1
  11. data/ext/nginx/Configuration.c +1 -1
  12. data/ext/nginx/HttpStatusExtractor.h +1 -0
  13. data/ext/nginx/ScgiRequestParser.h +1 -0
  14. data/ext/oxt/system_calls.cpp +11 -0
  15. data/ext/oxt/system_calls.hpp +2 -1
  16. data/ext/oxt/thread.hpp +97 -1
  17. data/ext/phusion_passenger/native_support.c +30 -1
  18. data/lib/phusion_passenger/constants.rb +1 -1
  19. data/lib/phusion_passenger/dependencies.rb +32 -0
  20. data/lib/phusion_passenger/message_channel.rb +45 -3
  21. data/lib/phusion_passenger/platform_info.rb +1 -1
  22. data/lib/phusion_passenger/rack/application_spawner.rb +10 -4
  23. data/lib/phusion_passenger/rack/request_handler.rb +2 -5
  24. data/lib/phusion_passenger/railz/application_spawner.rb +59 -7
  25. data/lib/phusion_passenger/utils.rb +70 -16
  26. data/{vendor/rack-1.0.0-git/lib/rack → lib/phusion_passenger/utils}/rewindable_input.rb +34 -9
  27. data/test/ApplicationPoolTest.cpp +1 -1
  28. data/test/MessageChannelTest.cpp +9 -1
  29. data/test/stub/message_channel.rb +1 -1
  30. data/test/stub/message_channel_2.rb +1 -1
  31. data/test/stub/message_channel_3.rb +2 -2
  32. metadata +43 -155
  33. data/doc/Architectural overview.html +0 -1
  34. data/doc/rdoc/classes/ConditionVariable.html +0 -194
  35. data/doc/rdoc/classes/Exception.html +0 -120
  36. data/doc/rdoc/classes/GC.html +0 -113
  37. data/doc/rdoc/classes/IO.html +0 -169
  38. data/doc/rdoc/classes/PhusionPassenger.html +0 -238
  39. data/doc/rdoc/classes/PhusionPassenger/AbstractInstaller.html +0 -153
  40. data/doc/rdoc/classes/PhusionPassenger/AbstractRequestHandler.html +0 -517
  41. data/doc/rdoc/classes/PhusionPassenger/AbstractServer.html +0 -719
  42. data/doc/rdoc/classes/PhusionPassenger/AbstractServer/ServerAlreadyStarted.html +0 -97
  43. data/doc/rdoc/classes/PhusionPassenger/AbstractServer/ServerError.html +0 -96
  44. data/doc/rdoc/classes/PhusionPassenger/AbstractServer/ServerNotStarted.html +0 -97
  45. data/doc/rdoc/classes/PhusionPassenger/AbstractServer/UnknownMessage.html +0 -96
  46. data/doc/rdoc/classes/PhusionPassenger/AbstractServerCollection.html +0 -598
  47. data/doc/rdoc/classes/PhusionPassenger/AdminTools.html +0 -140
  48. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ControlProcess.html +0 -317
  49. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ControlProcess/Instance.html +0 -138
  50. data/doc/rdoc/classes/PhusionPassenger/AppInitError.html +0 -154
  51. data/doc/rdoc/classes/PhusionPassenger/Application.html +0 -283
  52. data/doc/rdoc/classes/PhusionPassenger/ConsoleTextTemplate.html +0 -172
  53. data/doc/rdoc/classes/PhusionPassenger/FrameworkInitError.html +0 -145
  54. data/doc/rdoc/classes/PhusionPassenger/HTMLTemplate.html +0 -181
  55. data/doc/rdoc/classes/PhusionPassenger/InitializationError.html +0 -141
  56. data/doc/rdoc/classes/PhusionPassenger/InvalidPath.html +0 -92
  57. data/doc/rdoc/classes/PhusionPassenger/MessageChannel.html +0 -489
  58. data/doc/rdoc/classes/PhusionPassenger/NativeSupport.html +0 -350
  59. data/doc/rdoc/classes/PhusionPassenger/Rack.html +0 -91
  60. data/doc/rdoc/classes/PhusionPassenger/Rack/ApplicationSpawner.html +0 -188
  61. data/doc/rdoc/classes/PhusionPassenger/Rack/RequestHandler.html +0 -199
  62. data/doc/rdoc/classes/PhusionPassenger/Railz.html +0 -95
  63. data/doc/rdoc/classes/PhusionPassenger/Railz/ApplicationSpawner.html +0 -438
  64. data/doc/rdoc/classes/PhusionPassenger/Railz/ApplicationSpawner/Error.html +0 -98
  65. data/doc/rdoc/classes/PhusionPassenger/Railz/CGIFixed.html +0 -200
  66. data/doc/rdoc/classes/PhusionPassenger/Railz/FrameworkSpawner.html +0 -436
  67. data/doc/rdoc/classes/PhusionPassenger/Railz/FrameworkSpawner/Error.html +0 -98
  68. data/doc/rdoc/classes/PhusionPassenger/Railz/RequestHandler.html +0 -155
  69. data/doc/rdoc/classes/PhusionPassenger/SpawnManager.html +0 -402
  70. data/doc/rdoc/classes/PhusionPassenger/UnknownError.html +0 -125
  71. data/doc/rdoc/classes/PhusionPassenger/Utils.html +0 -803
  72. data/doc/rdoc/classes/PhusionPassenger/Utils/PseudoIO.html +0 -169
  73. data/doc/rdoc/classes/PhusionPassenger/VersionNotFound.html +0 -140
  74. data/doc/rdoc/classes/PhusionPassenger/WSGI.html +0 -89
  75. data/doc/rdoc/classes/PhusionPassenger/WSGI/ApplicationSpawner.html +0 -188
  76. data/doc/rdoc/classes/PlatformInfo.html +0 -866
  77. data/doc/rdoc/classes/RakeExtensions.html +0 -197
  78. data/doc/rdoc/classes/Signal.html +0 -131
  79. data/doc/rdoc/created.rid +0 -1
  80. data/doc/rdoc/files/DEVELOPERS_TXT.html +0 -255
  81. data/doc/rdoc/files/README.html +0 -175
  82. data/doc/rdoc/files/ext/phusion_passenger/native_support_c.html +0 -92
  83. data/doc/rdoc/files/lib/phusion_passenger/abstract_installer_rb.html +0 -129
  84. data/doc/rdoc/files/lib/phusion_passenger/abstract_request_handler_rb.html +0 -129
  85. data/doc/rdoc/files/lib/phusion_passenger/abstract_server_collection_rb.html +0 -126
  86. data/doc/rdoc/files/lib/phusion_passenger/abstract_server_rb.html +0 -128
  87. data/doc/rdoc/files/lib/phusion_passenger/admin_tools/control_process_rb.html +0 -130
  88. data/doc/rdoc/files/lib/phusion_passenger/admin_tools_rb.html +0 -122
  89. data/doc/rdoc/files/lib/phusion_passenger/application_rb.html +0 -127
  90. data/doc/rdoc/files/lib/phusion_passenger/console_text_template_rb.html +0 -126
  91. data/doc/rdoc/files/lib/phusion_passenger/constants_rb.html +0 -122
  92. data/doc/rdoc/files/lib/phusion_passenger/dependencies_rb.html +0 -134
  93. data/doc/rdoc/files/lib/phusion_passenger/events_rb.html +0 -122
  94. data/doc/rdoc/files/lib/phusion_passenger/exceptions_rb.html +0 -122
  95. data/doc/rdoc/files/lib/phusion_passenger/html_template_rb.html +0 -126
  96. data/doc/rdoc/files/lib/phusion_passenger/message_channel_rb.html +0 -120
  97. data/doc/rdoc/files/lib/phusion_passenger/packaging_rb.html +0 -122
  98. data/doc/rdoc/files/lib/phusion_passenger/platform_info_rb.html +0 -127
  99. data/doc/rdoc/files/lib/phusion_passenger/rack/application_spawner_rb.html +0 -133
  100. data/doc/rdoc/files/lib/phusion_passenger/rack/request_handler_rb.html +0 -125
  101. data/doc/rdoc/files/lib/phusion_passenger/railz/application_spawner_rb.html +0 -140
  102. data/doc/rdoc/files/lib/phusion_passenger/railz/cgi_fixed_rb.html +0 -126
  103. data/doc/rdoc/files/lib/phusion_passenger/railz/framework_spawner_rb.html +0 -145
  104. data/doc/rdoc/files/lib/phusion_passenger/railz/request_handler_rb.html +0 -125
  105. data/doc/rdoc/files/lib/phusion_passenger/simple_benchmarking_rb.html +0 -122
  106. data/doc/rdoc/files/lib/phusion_passenger/spawn_manager_rb.html +0 -159
  107. data/doc/rdoc/files/lib/phusion_passenger/utils_rb.html +0 -174
  108. data/doc/rdoc/files/lib/phusion_passenger/wsgi/application_spawner_rb.html +0 -129
  109. data/doc/rdoc/files/misc/rake/extensions_rb.html +0 -130
  110. data/doc/rdoc/fr_class_index.html +0 -91
  111. data/doc/rdoc/fr_file_index.html +0 -76
  112. data/doc/rdoc/fr_method_index.html +0 -205
  113. data/doc/rdoc/index.html +0 -26
  114. data/doc/rdoc/rdoc-style.css +0 -187
  115. data/vendor/README +0 -13
  116. data/vendor/README_FOR_PACKAGERS +0 -1
  117. data/vendor/rack-1.0.0-git/COPYING +0 -18
  118. data/vendor/rack-1.0.0-git/KNOWN-ISSUES +0 -18
  119. data/vendor/rack-1.0.0-git/README +0 -353
  120. data/vendor/rack-1.0.0-git/Rakefile +0 -164
  121. data/vendor/rack-1.0.0-git/lib/rack.rb +0 -90
  122. data/vendor/rack-1.0.0-git/lib/rack/adapter/camping.rb +0 -22
  123. data/vendor/rack-1.0.0-git/lib/rack/auth/abstract/handler.rb +0 -37
  124. data/vendor/rack-1.0.0-git/lib/rack/auth/abstract/request.rb +0 -37
  125. data/vendor/rack-1.0.0-git/lib/rack/auth/basic.rb +0 -58
  126. data/vendor/rack-1.0.0-git/lib/rack/auth/digest/md5.rb +0 -124
  127. data/vendor/rack-1.0.0-git/lib/rack/auth/digest/nonce.rb +0 -51
  128. data/vendor/rack-1.0.0-git/lib/rack/auth/digest/params.rb +0 -55
  129. data/vendor/rack-1.0.0-git/lib/rack/auth/digest/request.rb +0 -40
  130. data/vendor/rack-1.0.0-git/lib/rack/auth/openid.rb +0 -487
  131. data/vendor/rack-1.0.0-git/lib/rack/builder.rb +0 -63
  132. data/vendor/rack-1.0.0-git/lib/rack/cascade.rb +0 -41
  133. data/vendor/rack-1.0.0-git/lib/rack/chunked.rb +0 -49
  134. data/vendor/rack-1.0.0-git/lib/rack/commonlogger.rb +0 -52
  135. data/vendor/rack-1.0.0-git/lib/rack/conditionalget.rb +0 -47
  136. data/vendor/rack-1.0.0-git/lib/rack/content_length.rb +0 -29
  137. data/vendor/rack-1.0.0-git/lib/rack/content_type.rb +0 -23
  138. data/vendor/rack-1.0.0-git/lib/rack/deflater.rb +0 -96
  139. data/vendor/rack-1.0.0-git/lib/rack/directory.rb +0 -153
  140. data/vendor/rack-1.0.0-git/lib/rack/file.rb +0 -88
  141. data/vendor/rack-1.0.0-git/lib/rack/handler.rb +0 -69
  142. data/vendor/rack-1.0.0-git/lib/rack/handler/cgi.rb +0 -61
  143. data/vendor/rack-1.0.0-git/lib/rack/handler/evented_mongrel.rb +0 -8
  144. data/vendor/rack-1.0.0-git/lib/rack/handler/fastcgi.rb +0 -88
  145. data/vendor/rack-1.0.0-git/lib/rack/handler/lsws.rb +0 -55
  146. data/vendor/rack-1.0.0-git/lib/rack/handler/mongrel.rb +0 -84
  147. data/vendor/rack-1.0.0-git/lib/rack/handler/scgi.rb +0 -59
  148. data/vendor/rack-1.0.0-git/lib/rack/handler/swiftiplied_mongrel.rb +0 -8
  149. data/vendor/rack-1.0.0-git/lib/rack/handler/thin.rb +0 -18
  150. data/vendor/rack-1.0.0-git/lib/rack/handler/webrick.rb +0 -67
  151. data/vendor/rack-1.0.0-git/lib/rack/head.rb +0 -19
  152. data/vendor/rack-1.0.0-git/lib/rack/lint.rb +0 -537
  153. data/vendor/rack-1.0.0-git/lib/rack/lobster.rb +0 -65
  154. data/vendor/rack-1.0.0-git/lib/rack/lock.rb +0 -16
  155. data/vendor/rack-1.0.0-git/lib/rack/methodoverride.rb +0 -27
  156. data/vendor/rack-1.0.0-git/lib/rack/mime.rb +0 -204
  157. data/vendor/rack-1.0.0-git/lib/rack/mock.rb +0 -184
  158. data/vendor/rack-1.0.0-git/lib/rack/recursive.rb +0 -57
  159. data/vendor/rack-1.0.0-git/lib/rack/reloader.rb +0 -106
  160. data/vendor/rack-1.0.0-git/lib/rack/request.rb +0 -248
  161. data/vendor/rack-1.0.0-git/lib/rack/response.rb +0 -183
  162. data/vendor/rack-1.0.0-git/lib/rack/session/abstract/id.rb +0 -142
  163. data/vendor/rack-1.0.0-git/lib/rack/session/cookie.rb +0 -91
  164. data/vendor/rack-1.0.0-git/lib/rack/session/memcache.rb +0 -109
  165. data/vendor/rack-1.0.0-git/lib/rack/session/pool.rb +0 -100
  166. data/vendor/rack-1.0.0-git/lib/rack/showexceptions.rb +0 -349
  167. data/vendor/rack-1.0.0-git/lib/rack/showstatus.rb +0 -106
  168. data/vendor/rack-1.0.0-git/lib/rack/static.rb +0 -38
  169. data/vendor/rack-1.0.0-git/lib/rack/urlmap.rb +0 -55
  170. data/vendor/rack-1.0.0-git/lib/rack/utils.rb +0 -522
@@ -1,51 +0,0 @@
1
- require 'digest/md5'
2
-
3
- module Rack
4
- module Auth
5
- module Digest
6
- # Rack::Auth::Digest::Nonce is the default nonce generator for the
7
- # Rack::Auth::Digest::MD5 authentication handler.
8
- #
9
- # +private_key+ needs to set to a constant string.
10
- #
11
- # +time_limit+ can be optionally set to an integer (number of seconds),
12
- # to limit the validity of the generated nonces.
13
-
14
- class Nonce
15
-
16
- class << self
17
- attr_accessor :private_key, :time_limit
18
- end
19
-
20
- def self.parse(string)
21
- new(*string.unpack("m*").first.split(' ', 2))
22
- end
23
-
24
- def initialize(timestamp = Time.now, given_digest = nil)
25
- @timestamp, @given_digest = timestamp.to_i, given_digest
26
- end
27
-
28
- def to_s
29
- [([ @timestamp, digest ] * ' ')].pack("m*").strip
30
- end
31
-
32
- def digest
33
- ::Digest::MD5.hexdigest([ @timestamp, self.class.private_key ] * ':')
34
- end
35
-
36
- def valid?
37
- digest == @given_digest
38
- end
39
-
40
- def stale?
41
- !self.class.time_limit.nil? && (@timestamp - Time.now.to_i) < self.class.time_limit
42
- end
43
-
44
- def fresh?
45
- !stale?
46
- end
47
-
48
- end
49
- end
50
- end
51
- end
@@ -1,55 +0,0 @@
1
- module Rack
2
- module Auth
3
- module Digest
4
- class Params < Hash
5
-
6
- def self.parse(str)
7
- split_header_value(str).inject(new) do |header, param|
8
- k, v = param.split('=', 2)
9
- header[k] = dequote(v)
10
- header
11
- end
12
- end
13
-
14
- def self.dequote(str) # From WEBrick::HTTPUtils
15
- ret = (/\A"(.*)"\Z/ =~ str) ? $1 : str.dup
16
- ret.gsub!(/\\(.)/, "\\1")
17
- ret
18
- end
19
-
20
- def self.split_header_value(str)
21
- str.scan( /(\w+\=(?:"[^\"]+"|[^,]+))/n ).collect{ |v| v[0] }
22
- end
23
-
24
- def initialize
25
- super
26
-
27
- yield self if block_given?
28
- end
29
-
30
- def [](k)
31
- super k.to_s
32
- end
33
-
34
- def []=(k, v)
35
- super k.to_s, v.to_s
36
- end
37
-
38
- UNQUOTED = ['qop', 'nc', 'stale']
39
-
40
- def to_s
41
- inject([]) do |parts, (k, v)|
42
- parts << "#{k}=" + (UNQUOTED.include?(k) ? v.to_s : quote(v))
43
- parts
44
- end.join(', ')
45
- end
46
-
47
- def quote(str) # From WEBrick::HTTPUtils
48
- '"' << str.gsub(/[\\\"]/o, "\\\1") << '"'
49
- end
50
-
51
- end
52
- end
53
- end
54
- end
55
-
@@ -1,40 +0,0 @@
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['rack.methodoverride.original_method'] || @env['REQUEST_METHOD']
12
- end
13
-
14
- def digest?
15
- :digest == scheme
16
- end
17
-
18
- def correct_uri?
19
- (@env['SCRIPT_NAME'].to_s + @env['PATH_INFO'].to_s) == 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
@@ -1,487 +0,0 @@
1
- # AUTHOR: Scytrin dai Kinthra <scytrin@gmail.com>; blink#ruby-lang@irc.freenode.net
2
-
3
- gem 'ruby-openid', '~> 2' if defined? Gem
4
- require 'rack/request'
5
- require 'rack/utils'
6
- require 'rack/auth/abstract/handler'
7
-
8
- require 'uri'
9
- require 'openid'
10
- require 'openid/extension'
11
- require 'openid/store/memory'
12
-
13
- module Rack
14
- class Request
15
- def openid_request
16
- @env['rack.auth.openid.request']
17
- end
18
-
19
- def openid_response
20
- @env['rack.auth.openid.response']
21
- end
22
- end
23
-
24
- module Auth
25
-
26
- # Rack::Auth::OpenID provides a simple method for setting up an OpenID
27
- # Consumer. It requires the ruby-openid library from janrain to operate,
28
- # as well as a rack method of session management.
29
- #
30
- # The ruby-openid home page is at http://openidenabled.com/ruby-openid/.
31
- #
32
- # The OpenID specifications can be found at
33
- # http://openid.net/specs/openid-authentication-1_1.html
34
- # and
35
- # http://openid.net/specs/openid-authentication-2_0.html. Documentation
36
- # for published OpenID extensions and related topics can be found at
37
- # http://openid.net/developers/specs/.
38
- #
39
- # It is recommended to read through the OpenID spec, as well as
40
- # ruby-openid's documentation, to understand what exactly goes on. However
41
- # a setup as simple as the presented examples is enough to provide
42
- # Consumer functionality.
43
- #
44
- # This library strongly intends to utilize the OpenID 2.0 features of the
45
- # ruby-openid library, which provides OpenID 1.0 compatiblity.
46
- #
47
- # NOTE: Due to the amount of data that this library stores in the
48
- # session, Rack::Session::Cookie may fault.
49
- #
50
- # == Examples
51
- #
52
- # simple_oid = OpenID.new('http://mysite.com/')
53
- #
54
- # return_oid = OpenID.new('http://mysite.com/', {
55
- # :return_to => 'http://mysite.com/openid'
56
- # })
57
- #
58
- # complex_oid = OpenID.new('http://mysite.com/',
59
- # :immediate => true,
60
- # :extensions => {
61
- # ::OpenID::SReg => [['email'],['nickname']]
62
- # }
63
- # )
64
- #
65
- # = Advanced
66
- #
67
- # Most of the functionality of this library is encapsulated such that
68
- # expansion and overriding functions isn't difficult nor tricky.
69
- # Alternately, to avoid opening up singleton objects or subclassing, a
70
- # wrapper rack middleware can be composed to act upon Auth::OpenID's
71
- # responses. See #check and #finish for locations of pertinent data.
72
- #
73
- # == Responses
74
- #
75
- # To change the responses that Auth::OpenID returns, override the methods
76
- # #redirect, #bad_request, #unauthorized, #access_denied, and
77
- # #foreign_server_failure.
78
- #
79
- # Additionally #confirm_post_params is used when the URI would exceed
80
- # length limits on a GET request when doing the initial verification
81
- # request.
82
- #
83
- # == Processing
84
- #
85
- # To change methods of processing completed transactions, override the
86
- # methods #success, #setup_needed, #cancel, and #failure. Please ensure
87
- # the returned object is a rack compatible response.
88
- #
89
- # The first argument is an OpenID::Response, the second is a
90
- # Rack::Request of the current request, the last is the hash used in
91
- # ruby-openid handling, which can be found manually at
92
- # env['rack.session'][:openid].
93
- #
94
- # This is useful if you wanted to expand the processing done, such as
95
- # setting up user accounts.
96
- #
97
- # oid_app = Rack::Auth::OpenID.new realm, :return_to => return_to
98
- # def oid_app.success oid, request, session
99
- # user = Models::User[oid.identity_url]
100
- # user ||= Models::User.create_from_openid oid
101
- # request['rack.session'][:user] = user.id
102
- # redirect MyApp.site_home
103
- # end
104
- #
105
- # site_map['/openid'] = oid_app
106
- # map = Rack::URLMap.new site_map
107
- # ...
108
-
109
- class OpenID
110
- # Raised if an incompatible session is being used.
111
- class NoSession < RuntimeError; end
112
- # Raised if an extension not matching specifications is provided.
113
- class BadExtension < RuntimeError; end
114
- # Possible statuses returned from consumer responses. See definitions
115
- # in the ruby-openid library.
116
- ValidStatus = [
117
- ::OpenID::Consumer::SUCCESS,
118
- ::OpenID::Consumer::FAILURE,
119
- ::OpenID::Consumer::CANCEL,
120
- ::OpenID::Consumer::SETUP_NEEDED
121
- ]
122
-
123
- # The first argument is the realm, identifying the site they are trusting
124
- # with their identity. This is required, also treated as the trust_root
125
- # in OpenID 1.x exchanges.
126
- #
127
- # The lits of acceptable options include :return_to, :session_key,
128
- # :openid_param, :store, :immediate, :extensions.
129
- #
130
- # <tt>:return_to</tt> defines the url to return to after the client
131
- # authenticates with the openid service provider. This url should point
132
- # to where Rack::Auth::OpenID is mounted. If unprovided, the url of
133
- # the current request is used.
134
- #
135
- # <tt>:session_key</tt> defines the key to the session hash in the env.
136
- # The default is 'rack.session'.
137
- #
138
- # <tt>:openid_param</tt> defines at what key in the request parameters to
139
- # find the identifier to resolve. As per the 2.0 spec, the default is
140
- # 'openid_identifier'.
141
- #
142
- # <tt>:store</tt> defined what OpenID Store to use for persistant
143
- # information. By default a Store::Memory is used.
144
- #
145
- # <tt>:immediate</tt> as true will make initial requests to be of an
146
- # immediate type. This is false by default. See OpenID specification
147
- # documentation.
148
- #
149
- # <tt>:extensions</tt> should be a hash of openid extension
150
- # implementations. The key should be the extension module, the value
151
- # should be an array of arguments for extension::Request.new().
152
- # The hash is iterated over and passed to #add_extension for processing.
153
- # Please see #add_extension for further documentation.
154
-
155
- def initialize(realm, options={})
156
- realm = URI(realm)
157
- raise ArgumentError, "Invalid realm: #{realm}" \
158
- unless realm.absolute? \
159
- and realm.fragment.nil? \
160
- and realm.scheme =~ /^https?$/ \
161
- and realm.host =~ /^(\*\.)?#{URI::REGEXP::PATTERN::URIC_NO_SLASH}+/
162
- realm.path = '/' if realm.path.empty?
163
- @realm = realm.to_s
164
-
165
- if ruri = options[:return_to]
166
- ruri = URI(ruri)
167
- raise ArgumentError, "Invalid return_to: #{ruri}" \
168
- unless ruri.absolute? \
169
- and ruri.scheme =~ /^https?$/ \
170
- and ruri.fragment.nil?
171
- raise ArgumentError, "return_to #{ruri} not within realm #{realm}" \
172
- unless self.within_realm?(ruri)
173
- @return_to = ruri.to_s
174
- end
175
-
176
- @session_key = options[:session_key] || 'rack.session'
177
- @openid_param = options[:openid_param] || 'openid_identifier'
178
- @store = options[:store] || ::OpenID::Store::Memory.new
179
- @immediate = !!options[:immediate]
180
-
181
- @extensions = {}
182
- if extensions = options[:extensions]
183
- extensions.each do |ext, args|
184
- add_extension(ext, *args)
185
- end
186
- end
187
-
188
- # Undocumented, semi-experimental
189
- @anonymous = !!options[:anonymous]
190
- end
191
-
192
- attr_reader :realm, :return_to, :session_key, :openid_param, :store,
193
- :immediate, :extensions
194
-
195
- # Sets up and uses session data at <tt>:openid</tt> within the session.
196
- # Errors in this setup will raise a NoSession exception.
197
- #
198
- # If the parameter 'openid.mode' is set, which implies a followup from
199
- # the openid server, processing is passed to #finish and the result is
200
- # returned. However, if there is no appropriate openid information in the
201
- # session, a 400 error is returned.
202
- #
203
- # If the parameter specified by <tt>options[:openid_param]</tt> is
204
- # present, processing is passed to #check and the result is returned.
205
- #
206
- # If neither of these conditions are met, #bad_request is called.
207
-
208
- def call(env)
209
- env['rack.auth.openid'] = self
210
- env_session = env[@session_key]
211
- unless env_session and env_session.is_a?(Hash)
212
- raise NoSession, 'No compatible session.'
213
- end
214
- # let us work in our own namespace...
215
- session = (env_session[:openid] ||= {})
216
- unless session and session.is_a?(Hash)
217
- raise NoSession, 'Incompatible openid session.'
218
- end
219
-
220
- request = Rack::Request.new(env)
221
- consumer = ::OpenID::Consumer.new(session, @store)
222
-
223
- if mode = request.GET['openid.mode']
224
- finish(consumer, session, request)
225
- elsif request.GET[@openid_param]
226
- check(consumer, session, request)
227
- else
228
- bad_request
229
- end
230
- end
231
-
232
- # As the first part of OpenID consumer action, #check retrieves the data
233
- # required for completion.
234
- #
235
- # If all parameters fit within the max length of a URI, a 303 redirect
236
- # will be returned. Otherwise #confirm_post_params will be called.
237
- #
238
- # Any messages from OpenID's request are logged to env['rack.errors']
239
- #
240
- # <tt>env['rack.auth.openid.request']</tt> is the openid checkid request
241
- # instance.
242
- #
243
- # <tt>session[:openid_param]</tt> is set to the openid identifier
244
- # provided by the user.
245
- #
246
- # <tt>session[:return_to]</tt> is set to the return_to uri given to the
247
- # identity provider.
248
-
249
- def check(consumer, session, req)
250
- oid = consumer.begin(req.GET[@openid_param], @anonymous)
251
- req.env['rack.auth.openid.request'] = oid
252
- req.env['rack.errors'].puts(oid.message)
253
- p oid if $DEBUG
254
-
255
- ## Extension support
256
- extensions.each do |ext,args|
257
- oid.add_extension(ext::Request.new(*args))
258
- end
259
-
260
- session[:openid_param] = req.GET[openid_param]
261
- return_to_uri = return_to ? return_to : req.url
262
- session[:return_to] = return_to_uri
263
- immediate = session.key?(:setup_needed) ? false : immediate
264
-
265
- if oid.send_redirect?(realm, return_to_uri, immediate)
266
- redirect(oid.redirect_url(realm, return_to_uri, immediate))
267
- else
268
- confirm_post_params(oid, realm, return_to_uri, immediate)
269
- end
270
- rescue ::OpenID::DiscoveryFailure => e
271
- # thrown from inside OpenID::Consumer#begin by yadis stuff
272
- req.env['rack.errors'].puts( [e.message, *e.backtrace]*"\n" )
273
- return foreign_server_failure
274
- end
275
-
276
- # This is the final portion of authentication.
277
- # If successful, a redirect to the realm is be returned.
278
- # Data gathered from extensions are stored in session[:openid] with the
279
- # extension's namespace uri as the key.
280
- #
281
- # Any messages from OpenID's response are logged to env['rack.errors']
282
- #
283
- # <tt>env['rack.auth.openid.response']</tt> will contain the openid
284
- # response.
285
-
286
- def finish(consumer, session, req)
287
- oid = consumer.complete(req.GET, req.url)
288
- req.env['rack.auth.openid.response'] = oid
289
- req.env['rack.errors'].puts(oid.message)
290
- p oid if $DEBUG
291
-
292
- if ValidStatus.include?(oid.status)
293
- __send__(oid.status, oid, req, session)
294
- else
295
- invalid_status(oid, req, session)
296
- end
297
- end
298
-
299
- # The first argument should be the main extension module.
300
- # The extension module should contain the constants:
301
- # * class Request, should have OpenID::Extension as an ancestor
302
- # * class Response, should have OpenID::Extension as an ancestor
303
- # * string NS_URI, which defining the namespace of the extension
304
- #
305
- # All trailing arguments will be passed to extension::Request.new in
306
- # #check.
307
- # The openid response will be passed to
308
- # extension::Response#from_success_response, oid#get_extension_args will
309
- # be called on the result to attain the gathered data.
310
- #
311
- # This method returns the key at which the response data will be found in
312
- # the session, which is the namespace uri by default.
313
-
314
- def add_extension(ext, *args)
315
- raise BadExtension unless valid_extension?(ext)
316
- extensions[ext] = args
317
- return ext::NS_URI
318
- end
319
-
320
- # Checks the validitity, in the context of usage, of a submitted
321
- # extension.
322
-
323
- def valid_extension?(ext)
324
- if not %w[NS_URI Request Response].all?{|c| ext.const_defined?(c) }
325
- raise ArgumentError, 'Extension is missing constants.'
326
- elsif not ext::Response.respond_to?(:from_success_response)
327
- raise ArgumentError, 'Response is missing required method.'
328
- end
329
- return true
330
- rescue
331
- return false
332
- end
333
-
334
- # Checks the provided uri to ensure it'd be considered within the realm.
335
- # is currently not compatible with wildcard realms.
336
-
337
- def within_realm? uri
338
- uri = URI.parse(uri.to_s)
339
- realm = URI.parse(self.realm)
340
- return false unless uri.absolute?
341
- return false unless uri.path[0, realm.path.size] == realm.path
342
- return false unless uri.host == realm.host or realm.host[/^\*\./]
343
- # for wildcard support, is awkward with URI limitations
344
- realm_match = Regexp.escape(realm.host).
345
- sub(/^\*\./,"^#{URI::REGEXP::PATTERN::URIC_NO_SLASH}+.")+'$'
346
- return false unless uri.host.match(realm_match)
347
- return true
348
- end
349
-
350
- alias_method :include?, :within_realm?
351
-
352
- protected
353
-
354
- # Returns an html form page for posting to an Identity Provider if the
355
- # GET request would exceed the upper URI length limit.
356
-
357
- def confirm_post_params(oid, realm, return_to, immediate)
358
- response = Rack::Response.new '<html>'+
359
- '<head><title>Confirm...</title></head>'+
360
- '<body>'+oid.form_markup(realm, return_to, immediate)+'</body>'+
361
- '</html>'
362
- response.finish
363
- end
364
-
365
- # Returns a 303 redirect with the destination of that provided by the
366
- # argument.
367
-
368
- def redirect(uri)
369
- [ 303, {'Content-Type'=>'text/plain', 'Content-Length'=>'0',
370
- 'Location' => uri},
371
- [] ]
372
- end
373
-
374
- # Returns an empty 400 response.
375
-
376
- def bad_request
377
- [ 400, {'Content-Type'=>'text/plain', 'Content-Length'=>'0'},
378
- [''] ]
379
- end
380
-
381
- # Returns a basic unauthorized 401 response.
382
-
383
- def unauthorized
384
- [ 401, {'Content-Type' => 'text/plain', 'Content-Length' => '13'},
385
- ['Unauthorized.'] ]
386
- end
387
-
388
- # Returns a basic access denied 403 response.
389
-
390
- def access_denied
391
- [ 403, {'Content-Type' => 'text/plain', 'Content-Length' => '14'},
392
- ['Access denied.'] ]
393
- end
394
-
395
- # Returns a 503 response to be used if communication with the remote
396
- # OpenID server fails.
397
-
398
- def foreign_server_failure
399
- [ 503, {'Content-Type'=>'text/plain', 'Content-Length' => '23'},
400
- ['Foreign server failure.'] ]
401
- end
402
-
403
- private
404
-
405
- # Called to complete processing on a successful transaction.
406
- # Within the openid session, :openid_identity and :openid_identifier are
407
- # set to the user friendly and the standard representation of the
408
- # validated identity. All other data in the openid session is cleared.
409
-
410
- def success(oid, request, session)
411
- session.clear
412
- session[:openid_identity] = oid.display_identifier
413
- session[:openid_identifier] = oid.identity_url
414
- extensions.keys.each do |ext|
415
- label = ext.name[/[^:]+$/].downcase
416
- response = ext::Response.from_success_response(oid)
417
- session[label] = response.data
418
- end
419
- redirect(realm)
420
- end
421
-
422
- # Called if the Identity Provider indicates further setup by the user is
423
- # required.
424
- # The identifier is retrived from the openid session at :openid_param.
425
- # And :setup_needed is set to true to prevent looping.
426
-
427
- def setup_needed(oid, request, session)
428
- identifier = session[:openid_param]
429
- session[:setup_needed] = true
430
- redirect(req.script_name + '?' + openid_param + '=' + identifier)
431
- end
432
-
433
- # Called if the user indicates they wish to cancel identification.
434
- # Data within openid session is cleared.
435
-
436
- def cancel(oid, request, session)
437
- session.clear
438
- access_denied
439
- end
440
-
441
- # Called if the Identity Provider indicates the user is unable to confirm
442
- # their identity. Data within the openid session is left alone, in case
443
- # of swarm auth attacks.
444
-
445
- def failure(oid, request, session)
446
- unauthorized
447
- end
448
-
449
- # To be called if there is no method for handling the OpenID response
450
- # status.
451
-
452
- def invalid_status(oid, request, session)
453
- msg = 'Invalid status returned by the OpenID authorization reponse.'
454
- [ 500,
455
- {'Content-Type'=>'text/plain','Content-Length'=>msg.length.to_s},
456
- [msg] ]
457
- end
458
- end
459
-
460
- # A class developed out of the request to use OpenID as an authentication
461
- # middleware. The request will be sent to the OpenID instance unless the
462
- # block evaluates to true. For example in rackup, you can use it as such:
463
- #
464
- # use Rack::Session::Pool
465
- # use Rack::Auth::OpenIDAuth, realm, openid_options do |env|
466
- # env['rack.session'][:authkey] == a_string
467
- # end
468
- # run RackApp
469
- #
470
- # Or simply:
471
- #
472
- # app = Rack::Auth::OpenIDAuth.new app, realm, openid_options, &auth
473
-
474
- class OpenIDAuth < Rack::Auth::AbstractHandler
475
- attr_reader :oid
476
- def initialize(app, realm, options={}, &auth)
477
- @oid = OpenID.new(realm, options)
478
- super(app, &auth)
479
- end
480
-
481
- def call(env)
482
- to = @authenticator.call(env) ? @app : @oid
483
- to.call(env)
484
- end
485
- end
486
- end
487
- end