ramaze 0.0.6
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/Rakefile +360 -0
- data/bin/ramaze +152 -0
- data/doc/CHANGELOG +2021 -0
- data/doc/COPYING +56 -0
- data/doc/COPYING.ja +51 -0
- data/doc/README +275 -0
- data/doc/TODO +33 -0
- data/doc/allison/LICENSE +184 -0
- data/doc/allison/README +37 -0
- data/doc/allison/allison.css +300 -0
- data/doc/allison/allison.gif +0 -0
- data/doc/allison/allison.js +307 -0
- data/doc/allison/allison.rb +287 -0
- data/doc/allison/cache/BODY +588 -0
- data/doc/allison/cache/CLASS_INDEX +4 -0
- data/doc/allison/cache/CLASS_PAGE +1 -0
- data/doc/allison/cache/FILE_INDEX +4 -0
- data/doc/allison/cache/FILE_PAGE +1 -0
- data/doc/allison/cache/FONTS +1 -0
- data/doc/allison/cache/FR_INDEX_BODY +1 -0
- data/doc/allison/cache/IMGPATH +1 -0
- data/doc/allison/cache/INDEX +1 -0
- data/doc/allison/cache/JAVASCRIPT +307 -0
- data/doc/allison/cache/METHOD_INDEX +4 -0
- data/doc/allison/cache/METHOD_LIST +1 -0
- data/doc/allison/cache/SRC_PAGE +1 -0
- data/doc/allison/cache/STYLE +322 -0
- data/doc/allison/cache/URL +1 -0
- data/examples/blog/main.rb +16 -0
- data/examples/blog/public/screen.css +106 -0
- data/examples/blog/src/controller.rb +50 -0
- data/examples/blog/src/element.rb +53 -0
- data/examples/blog/src/model.rb +29 -0
- data/examples/blog/template/edit.xhtml +6 -0
- data/examples/blog/template/index.xhtml +24 -0
- data/examples/blog/template/new.xhtml +5 -0
- data/examples/blog/template/view.xhtml +15 -0
- data/examples/blog/test/tc_entry.rb +18 -0
- data/examples/caching.rb +23 -0
- data/examples/element.rb +40 -0
- data/examples/hello.rb +23 -0
- data/examples/simple.rb +60 -0
- data/examples/templates/template/external.haml +21 -0
- data/examples/templates/template/external.liquid +28 -0
- data/examples/templates/template/external.mab +27 -0
- data/examples/templates/template/external.rhtml +29 -0
- data/examples/templates/template/external.rmze +24 -0
- data/examples/templates/template_erubis.rb +50 -0
- data/examples/templates/template_haml.rb +48 -0
- data/examples/templates/template_liquid.rb +64 -0
- data/examples/templates/template_markaby.rb +52 -0
- data/examples/templates/template_ramaze.rb +49 -0
- data/examples/whywiki/main.rb +56 -0
- data/examples/whywiki/template/edit.xhtml +14 -0
- data/examples/whywiki/template/show.xhtml +17 -0
- data/lib/proto/conf/benchmark.yaml +35 -0
- data/lib/proto/conf/debug.yaml +34 -0
- data/lib/proto/conf/live.yaml +33 -0
- data/lib/proto/conf/silent.yaml +31 -0
- data/lib/proto/conf/stage.yaml +33 -0
- data/lib/proto/main.rb +18 -0
- data/lib/proto/public/404.jpg +0 -0
- data/lib/proto/public/css/coderay.css +105 -0
- data/lib/proto/public/css/ramaze_error.css +42 -0
- data/lib/proto/public/error.xhtml +74 -0
- data/lib/proto/public/favicon.ico +0 -0
- data/lib/proto/public/js/jquery.js +1923 -0
- data/lib/proto/public/ramaze.png +0 -0
- data/lib/proto/src/controller/main.rb +7 -0
- data/lib/proto/src/element/page.rb +16 -0
- data/lib/proto/src/model.rb +5 -0
- data/lib/proto/template/index.xhtml +6 -0
- data/lib/ramaze.rb +317 -0
- data/lib/ramaze/adapter/mongrel.rb +111 -0
- data/lib/ramaze/adapter/webrick.rb +161 -0
- data/lib/ramaze/cache.rb +11 -0
- data/lib/ramaze/cache/memcached.rb +52 -0
- data/lib/ramaze/cache/memory.rb +6 -0
- data/lib/ramaze/cache/yaml_store.rb +37 -0
- data/lib/ramaze/controller.rb +10 -0
- data/lib/ramaze/dispatcher.rb +315 -0
- data/lib/ramaze/error.rb +11 -0
- data/lib/ramaze/gestalt.rb +108 -0
- data/lib/ramaze/global.rb +120 -0
- data/lib/ramaze/helper.rb +32 -0
- data/lib/ramaze/helper/aspect.rb +189 -0
- data/lib/ramaze/helper/auth.rb +120 -0
- data/lib/ramaze/helper/cache.rb +52 -0
- data/lib/ramaze/helper/feed.rb +135 -0
- data/lib/ramaze/helper/form.rb +204 -0
- data/lib/ramaze/helper/link.rb +80 -0
- data/lib/ramaze/helper/redirect.rb +48 -0
- data/lib/ramaze/helper/stack.rb +67 -0
- data/lib/ramaze/http_status.rb +66 -0
- data/lib/ramaze/inform.rb +166 -0
- data/lib/ramaze/snippets.rb +5 -0
- data/lib/ramaze/snippets/hash/keys_to_sym.rb +19 -0
- data/lib/ramaze/snippets/kernel/aquire.rb +22 -0
- data/lib/ramaze/snippets/kernel/autoreload.rb +79 -0
- data/lib/ramaze/snippets/kernel/caller_lines.rb +58 -0
- data/lib/ramaze/snippets/kernel/constant.rb +24 -0
- data/lib/ramaze/snippets/kernel/rescue_require.rb +12 -0
- data/lib/ramaze/snippets/kernel/self_method.rb +41 -0
- data/lib/ramaze/snippets/kernel/silently.rb +13 -0
- data/lib/ramaze/snippets/object/traits.rb +60 -0
- data/lib/ramaze/snippets/openstruct/temp.rb +10 -0
- data/lib/ramaze/snippets/string/DIVIDE.rb +16 -0
- data/lib/ramaze/snippets/string/camel_case.rb +14 -0
- data/lib/ramaze/snippets/string/snake_case.rb +12 -0
- data/lib/ramaze/snippets/symbol/to_proc.rb +14 -0
- data/lib/ramaze/snippets/thread/deadQUESTIONMARK.rb +11 -0
- data/lib/ramaze/store/default.rb +48 -0
- data/lib/ramaze/template.rb +102 -0
- data/lib/ramaze/template/amrita2.rb +40 -0
- data/lib/ramaze/template/erubis.rb +58 -0
- data/lib/ramaze/template/haml.rb +65 -0
- data/lib/ramaze/template/haml/actionview_stub.rb +20 -0
- data/lib/ramaze/template/liquid.rb +74 -0
- data/lib/ramaze/template/markaby.rb +68 -0
- data/lib/ramaze/template/ramaze.rb +177 -0
- data/lib/ramaze/template/ramaze/element.rb +166 -0
- data/lib/ramaze/template/ramaze/morpher.rb +156 -0
- data/lib/ramaze/tool/create.rb +70 -0
- data/lib/ramaze/tool/tidy.rb +71 -0
- data/lib/ramaze/trinity.rb +38 -0
- data/lib/ramaze/trinity/request.rb +244 -0
- data/lib/ramaze/trinity/response.rb +41 -0
- data/lib/ramaze/trinity/session.rb +129 -0
- data/lib/ramaze/version.rb +14 -0
- data/spec/spec_all.rb +73 -0
- data/spec/spec_helper.rb +215 -0
- data/spec/tc_adapter_mongrel.rb +24 -0
- data/spec/tc_adapter_webrick.rb +22 -0
- data/spec/tc_cache.rb +79 -0
- data/spec/tc_controller.rb +39 -0
- data/spec/tc_element.rb +100 -0
- data/spec/tc_error.rb +23 -0
- data/spec/tc_gestalt.rb +90 -0
- data/spec/tc_global.rb +46 -0
- data/spec/tc_helper_aspect.rb +65 -0
- data/spec/tc_helper_auth.rb +61 -0
- data/spec/tc_helper_cache.rb +81 -0
- data/spec/tc_helper_feed.rb +129 -0
- data/spec/tc_helper_form.rb +146 -0
- data/spec/tc_helper_link.rb +58 -0
- data/spec/tc_helper_redirect.rb +51 -0
- data/spec/tc_helper_stack.rb +55 -0
- data/spec/tc_morpher.rb +90 -0
- data/spec/tc_params.rb +84 -0
- data/spec/tc_request.rb +111 -0
- data/spec/tc_session.rb +56 -0
- data/spec/tc_store.rb +25 -0
- data/spec/tc_template_amrita2.rb +34 -0
- data/spec/tc_template_erubis.rb +41 -0
- data/spec/tc_template_haml.rb +44 -0
- data/spec/tc_template_liquid.rb +98 -0
- data/spec/tc_template_markaby.rb +74 -0
- data/spec/tc_template_ramaze.rb +54 -0
- data/spec/tc_tidy.rb +14 -0
- data/spec/template/amrita2/data.html +6 -0
- data/spec/template/amrita2/index.html +1 -0
- data/spec/template/amrita2/sum.html +1 -0
- data/spec/template/erubis/sum.rhtml +1 -0
- data/spec/template/haml/index.haml +5 -0
- data/spec/template/haml/with_vars.haml +4 -0
- data/spec/template/liquid/index.liquid +1 -0
- data/spec/template/liquid/products.liquid +45 -0
- data/spec/template/markaby/external.mab +8 -0
- data/spec/template/markaby/sum.mab +1 -0
- data/spec/template/ramaze/file_only.rmze +1 -0
- data/spec/template/ramaze/index.rmze +1 -0
- data/spec/template/ramaze/nested.rmze +1 -0
- data/spec/template/ramaze/sum.rmze +1 -0
- metadata +317 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Copyright (c) 2006 Michael Fellinger m.fellinger@gmail.com
|
|
2
|
+
# All files in this distribution are subject to the terms of the Ruby license.
|
|
3
|
+
|
|
4
|
+
require 'ramaze/trinity/request'
|
|
5
|
+
require 'ramaze/trinity/response'
|
|
6
|
+
require 'ramaze/trinity/session'
|
|
7
|
+
|
|
8
|
+
module Ramaze
|
|
9
|
+
|
|
10
|
+
# The module to be included into the Controller it basically just provides
|
|
11
|
+
# #request, #response and #session, each accessing Thread.current to
|
|
12
|
+
# retrieve the demanded object
|
|
13
|
+
|
|
14
|
+
module Trinity
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
# same as
|
|
18
|
+
# Thread.current[:request]
|
|
19
|
+
|
|
20
|
+
def request
|
|
21
|
+
Thread.current[:request]
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# same as
|
|
25
|
+
# Thread.current[:response]
|
|
26
|
+
|
|
27
|
+
def response
|
|
28
|
+
Thread.current[:response]
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# same as
|
|
32
|
+
# Thread.current[:session]
|
|
33
|
+
|
|
34
|
+
def session
|
|
35
|
+
Thread.current[:session]
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
# Copyright (c) 2006 Michael Fellinger m.fellinger@gmail.com
|
|
2
|
+
# All files in this distribution are subject to the terms of the Ruby license.
|
|
3
|
+
|
|
4
|
+
require 'cgi'
|
|
5
|
+
require 'tmpdir'
|
|
6
|
+
require 'digest/md5'
|
|
7
|
+
|
|
8
|
+
module Ramaze
|
|
9
|
+
|
|
10
|
+
# This class is used for processing the information coming in from a request
|
|
11
|
+
# to the dispatcher, it takes the original request-object, processes it and
|
|
12
|
+
# is later available in the controller or as Thread.current[:request]
|
|
13
|
+
#
|
|
14
|
+
# Please note that the implementation is lacking performance and security
|
|
15
|
+
# in favor of simplicity. Hopefully I (or some CGI-guru) will come along
|
|
16
|
+
# and implement this properly, until then consider it unsafe, but functional.
|
|
17
|
+
#
|
|
18
|
+
# Most information you will need is in the #params, which is a compound of
|
|
19
|
+
# all the information available from POST, GET, DELETE and PUT.
|
|
20
|
+
|
|
21
|
+
class Request
|
|
22
|
+
attr_accessor :request, :post_query, :get_query, :puts_query, :get_query
|
|
23
|
+
|
|
24
|
+
class << self
|
|
25
|
+
|
|
26
|
+
# get the current request out of Thread.current[:request]
|
|
27
|
+
#
|
|
28
|
+
# You can call this from everywhere with Ramaze::Request.current
|
|
29
|
+
|
|
30
|
+
def current
|
|
31
|
+
Thread.current[:request]
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# create a new instance of Request, takes the original request-object
|
|
36
|
+
# and runs #parse_queries to extract/process the information inside
|
|
37
|
+
|
|
38
|
+
def initialize request = {}
|
|
39
|
+
@request = request
|
|
40
|
+
parse_queries
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# you can access the original @request via this method_missing,
|
|
44
|
+
# first it tries to match your method with any of the HTTP parameters
|
|
45
|
+
# then, in case that fails, it will relay to @request
|
|
46
|
+
|
|
47
|
+
def method_missing meth, *args, &block
|
|
48
|
+
if value = @request.params[meth.to_s.upcase] rescue false
|
|
49
|
+
value
|
|
50
|
+
else
|
|
51
|
+
@request.send(meth, *args, &block)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# containts all the parameters given, no matter wheter with
|
|
56
|
+
# POST, GET, PUT or DELETE
|
|
57
|
+
# answers with a hash that is generated from the respective
|
|
58
|
+
# _query instance-variables and cached subsequently in @params
|
|
59
|
+
|
|
60
|
+
def params
|
|
61
|
+
@params ||= [
|
|
62
|
+
@get_query, @post_query, @put_query, @delete_query
|
|
63
|
+
].inject({}) do |sum, hash|
|
|
64
|
+
sum.merge(hash || {})
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# this parses stuff like post-requests (very untested)
|
|
69
|
+
# and also ?foo=bar stuff (get-query)
|
|
70
|
+
# WEBrick uses body as a streaming-object, so we have to #read.
|
|
71
|
+
# Mongrel has a normal string as body, we just call to_s in case
|
|
72
|
+
# it's no POST
|
|
73
|
+
|
|
74
|
+
def parse_queries
|
|
75
|
+
case request_method
|
|
76
|
+
when 'GET' : process_get
|
|
77
|
+
when 'POST' : process_post
|
|
78
|
+
when 'PUT' : process_put
|
|
79
|
+
when 'DELETE' : process_delete
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# very naive implementation of POST-body parsing, this won't withstand
|
|
84
|
+
# any serious testing or multiple simultanous huge posts...
|
|
85
|
+
# However, it just extracts the information inside the @request.body
|
|
86
|
+
# and puts it into proper form
|
|
87
|
+
# you can access its contents via #post_query
|
|
88
|
+
|
|
89
|
+
def process_post
|
|
90
|
+
@post_query = {}
|
|
91
|
+
|
|
92
|
+
type, boundary = content_type.split(';')
|
|
93
|
+
|
|
94
|
+
if type.downcase == 'multipart/form-data' and not boundary.empty?
|
|
95
|
+
parse_multipart(body, boundary.split('=').last)
|
|
96
|
+
else
|
|
97
|
+
post_query = query_parse(body.respond_to?(:read) ? body.read : body)
|
|
98
|
+
post_query.each do |key, value|
|
|
99
|
+
@post_query[CGI.unescape(key)] = CGI.unescape(value)
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# processing incoming GET, stuffing the results into @get_query,
|
|
105
|
+
# you can access the information via #get_query
|
|
106
|
+
|
|
107
|
+
def process_get
|
|
108
|
+
@get_query = {}
|
|
109
|
+
|
|
110
|
+
get_query = query_parse(query_string) rescue {}
|
|
111
|
+
get_query.each do |key, value|
|
|
112
|
+
@get_query[CGI.unescape(key)] = CGI.unescape(value)
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# TODO
|
|
117
|
+
# - implement and test DELETE
|
|
118
|
+
|
|
119
|
+
def process_delete
|
|
120
|
+
@delete_query = {}
|
|
121
|
+
raise "Implement me"
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# again, rather naive, it just gives you the control over what to do
|
|
125
|
+
# with the #body but will parse the parameters from the URL
|
|
126
|
+
|
|
127
|
+
def process_put
|
|
128
|
+
@pust_query = {}
|
|
129
|
+
|
|
130
|
+
put_query = query_parse(query_string) rescue {}
|
|
131
|
+
put_query.each do |key, value|
|
|
132
|
+
@put_query[CGI.unescape(key)] = CGI.unescape(value)
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# process the parameters passed over the URL, they look like
|
|
137
|
+
#
|
|
138
|
+
# http://foo.bar/action?eins=one&zwei=two
|
|
139
|
+
#
|
|
140
|
+
# that would result in #params containing {'eins' => 'one', 'zwei' => 'two'}
|
|
141
|
+
|
|
142
|
+
def query_parse str
|
|
143
|
+
str = str.split('?').last.to_s rescue ''
|
|
144
|
+
hash = CGI.parse(str)
|
|
145
|
+
hash.each do |key, values|
|
|
146
|
+
key = CGI.unescape(key)
|
|
147
|
+
values = values.map{|v| CGI.unescape(v)}
|
|
148
|
+
hash[key] = values.size == 1 ? values.first : values
|
|
149
|
+
end
|
|
150
|
+
hash
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# parse multipart-requests, just pass it something that responds to .read
|
|
154
|
+
# and a boundary for the parts.
|
|
155
|
+
# again a naive implementation without any guarantee against DoS.
|
|
156
|
+
#
|
|
157
|
+
# TODO:
|
|
158
|
+
# - rewrite parsing of multipart
|
|
159
|
+
# - chunk through the body and pipe into tempfile
|
|
160
|
+
# - look at merb for example of correct parsing
|
|
161
|
+
|
|
162
|
+
def parse_multipart(body, boundary)
|
|
163
|
+
text = body.read
|
|
164
|
+
text.split("--" << boundary).each do |chunk|
|
|
165
|
+
header = chunk.split("\r\n\r\n").first
|
|
166
|
+
next if (!header or !body) || (header.strip.empty? or chunk.strip.empty?)
|
|
167
|
+
head = parse_multipart_head(header)
|
|
168
|
+
next if head.empty?
|
|
169
|
+
chunk = chunk[(header.size + 4)..-3]
|
|
170
|
+
hash = Digest::MD5.hexdigest([head['name'], chunk.size, head.hash].inspect)
|
|
171
|
+
filename = File.join(Dir.tmpdir, hash)
|
|
172
|
+
File.open(filename, "w+") do |file|
|
|
173
|
+
file.print(chunk)
|
|
174
|
+
end
|
|
175
|
+
@post_query[head['name']] = File.open(filename)
|
|
176
|
+
end
|
|
177
|
+
body.rewind
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
# parse the head of the one part of multipart
|
|
181
|
+
# you most likely won't have to use this on your own :)
|
|
182
|
+
|
|
183
|
+
def parse_multipart_head(string)
|
|
184
|
+
string.gsub("\r\n", ";").split(';').inject({}) do |sum, param|
|
|
185
|
+
key, value = param.strip.split('=')
|
|
186
|
+
sum[key] = value[1..-2] if key and value
|
|
187
|
+
sum
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
# like request.params[key]
|
|
192
|
+
|
|
193
|
+
def [](key)
|
|
194
|
+
params[key]
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
# like reuqest.params[key] = value
|
|
198
|
+
|
|
199
|
+
def []=(key, value)
|
|
200
|
+
params[key] = value
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
# request_method == 'GET'
|
|
204
|
+
def get?() request_method == 'GET' end
|
|
205
|
+
# request_method == 'POST'
|
|
206
|
+
def post?() request_method == 'POST' end
|
|
207
|
+
# request_method == 'PUT'
|
|
208
|
+
def put?() request_method == 'PUT' end
|
|
209
|
+
# request_method == 'DELETE'
|
|
210
|
+
def delete?() request_method == 'DELETE' end
|
|
211
|
+
|
|
212
|
+
# remote_addr == '127.0.0.1'
|
|
213
|
+
|
|
214
|
+
def local?
|
|
215
|
+
remote_addr == '127.0.0.1'
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
# Is the request coming from a local network?
|
|
219
|
+
|
|
220
|
+
def local_net?(ip = remote_addr)
|
|
221
|
+
bip = ip.split('.').map{ |x| x.to_i }.pack('C4').unpack('N')[0]
|
|
222
|
+
|
|
223
|
+
# 127.0.0.1/32 => 2130706433
|
|
224
|
+
# 192.168.0.0/16 => 49320
|
|
225
|
+
# 172.16.0.0/12 => 2753
|
|
226
|
+
# 10.0.0.0/8 => 10
|
|
227
|
+
|
|
228
|
+
{ 0 => 2130706433, 16 => 49320, 20 => 2753, 24 => 10}.each do |s,c|
|
|
229
|
+
return true if (bip >> s) == c
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
return false
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
# check the referer from which the browser came
|
|
236
|
+
# '/' if no referer given.
|
|
237
|
+
|
|
238
|
+
def referer
|
|
239
|
+
headers['HTTP_REFERER'] || '/'
|
|
240
|
+
rescue
|
|
241
|
+
params['HTTP_REFERER'] || '/'
|
|
242
|
+
end
|
|
243
|
+
end
|
|
244
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Copyright (c) 2006 Michael Fellinger m.fellinger@gmail.com
|
|
2
|
+
# All files in this distribution are subject to the terms of the Ruby license.
|
|
3
|
+
|
|
4
|
+
module Ramaze
|
|
5
|
+
# The Response given back to the adapter, this is the center of every request
|
|
6
|
+
# made.
|
|
7
|
+
#
|
|
8
|
+
# In case you do a custom response, just make sure you implement all three
|
|
9
|
+
# properties: #out, #code, #head
|
|
10
|
+
# where head has to #respond_to? #[]
|
|
11
|
+
#
|
|
12
|
+
# code is the status-code ( http://en.wikipedia.org/wiki/List_of_HTTP_status_codes )
|
|
13
|
+
# and out should be something very String-like
|
|
14
|
+
|
|
15
|
+
class ResponseStruct < Struct
|
|
16
|
+
|
|
17
|
+
# get the current response out of Thread.current[:response]
|
|
18
|
+
#
|
|
19
|
+
# You can call this from everywhere with Ramaze::Response.current
|
|
20
|
+
|
|
21
|
+
def current
|
|
22
|
+
Thread.current[:response]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# just #inspect for this class in the format of
|
|
26
|
+
# <Response#324543 @code => 200, @head => {'Content-Type'=>'text/html', @out.size => 234>
|
|
27
|
+
|
|
28
|
+
def inspect
|
|
29
|
+
"<Response##{object_id} @code => #{code}, @head => #{head.inspect}, @out.size => #{out.size}>"
|
|
30
|
+
end
|
|
31
|
+
alias pretty_inspect inspect
|
|
32
|
+
|
|
33
|
+
# same as #head['Content-Type']
|
|
34
|
+
|
|
35
|
+
def content_type
|
|
36
|
+
head['Content-Type']
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
Response = ResponseStruct.new(:out, :code, :head)
|
|
41
|
+
end
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# Copyright (c) 2006 Michael Fellinger m.fellinger@gmail.com
|
|
2
|
+
# All files in this distribution are subject to the terms of the Ruby license.
|
|
3
|
+
|
|
4
|
+
require 'digest/sha2'
|
|
5
|
+
|
|
6
|
+
module Ramaze
|
|
7
|
+
|
|
8
|
+
# Session is the object that stores all the session-information of the user.
|
|
9
|
+
# It is heavily based on cookies storing the key to the information stored
|
|
10
|
+
# on the server.
|
|
11
|
+
#
|
|
12
|
+
# It uses caching as set in Global.cache and tries to set a cookie in case
|
|
13
|
+
# there is none set yet.
|
|
14
|
+
|
|
15
|
+
class Session
|
|
16
|
+
SESSION_KEY = '_ramaze_session_id'
|
|
17
|
+
attr_accessor :session
|
|
18
|
+
|
|
19
|
+
class << self
|
|
20
|
+
|
|
21
|
+
# Get the current session out of Thread.current[:session]
|
|
22
|
+
#
|
|
23
|
+
# You can call this from everywhere with Ramaze::Session.current
|
|
24
|
+
|
|
25
|
+
def current
|
|
26
|
+
Thread.current[:session]
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# pass the request-object and it will extract the session-id (which is
|
|
31
|
+
# stored in the cookie with the key of SESSION_KEY
|
|
32
|
+
|
|
33
|
+
def initialize request
|
|
34
|
+
@session_id = parse(request)[SESSION_KEY]
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# current session_id, will generate a new one based on #hash if no session
|
|
38
|
+
# is currently active
|
|
39
|
+
|
|
40
|
+
def session_id
|
|
41
|
+
@session_id ||= hash
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# the current contents of session
|
|
45
|
+
|
|
46
|
+
def current
|
|
47
|
+
sessions[session_id] ||= {}
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# all the sessions currently stored, in case there are none yet it will
|
|
51
|
+
# set the constant Ramaze::SessionCache and from then on start populating
|
|
52
|
+
# it with the sessions. SessionCache is an instance of Global.cache as
|
|
53
|
+
# well.
|
|
54
|
+
|
|
55
|
+
def sessions
|
|
56
|
+
Thread.main[:session_cache] ||= Global.cache.new
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# this runs before #parse and will extract the information stored in the cookie
|
|
60
|
+
# of the client, in case there is none it will try to set one.
|
|
61
|
+
# Unfortunatly we have to go seperate paths here for mongrel and webrick,
|
|
62
|
+
# since they do not share the same API.
|
|
63
|
+
#
|
|
64
|
+
# ARGH, 3 different ways for webrick to hand us cookies!? (and counting)
|
|
65
|
+
|
|
66
|
+
def pre_parse request
|
|
67
|
+
if Global.adapter == :webrick
|
|
68
|
+
# input looks like this:
|
|
69
|
+
# "Set-Cookie: _ramaze__session_id=fa8cc88dafcb0973b48d4d65ef57e7d3\r\n"
|
|
70
|
+
cookie = request.raw_header.grep(/Set-Cookie/).first rescue ''
|
|
71
|
+
cookie = request.post_query.delete('Set-Cookie') if cookie.to_s.empty? and request.post?
|
|
72
|
+
cookie = request.header['cookie'] unless cookie
|
|
73
|
+
cookie.to_s.gsub(/Set-Cookie: (.*?)\r\n/, '\1')
|
|
74
|
+
else
|
|
75
|
+
cookie = (request.http_cookie rescue request.http_set_cookie rescue '') || ''
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# parse the cookie and extract all the variables stored in there.
|
|
80
|
+
|
|
81
|
+
def parse request
|
|
82
|
+
cookie = pre_parse(request)
|
|
83
|
+
|
|
84
|
+
return cookie if cookie.respond_to?(:to_hash)
|
|
85
|
+
|
|
86
|
+
cookie.split('; ').inject({}) do |s,v|
|
|
87
|
+
key, value = v.split('=')
|
|
88
|
+
s.merge key.strip => value
|
|
89
|
+
end
|
|
90
|
+
rescue => ex
|
|
91
|
+
Informer.error ex
|
|
92
|
+
{SESSION_KEY => hash}
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# tries to catch all methods and proxy them to the #current
|
|
96
|
+
# this makes it easier to do i.e. hash-manipulation directly
|
|
97
|
+
# on #session in the controller.
|
|
98
|
+
|
|
99
|
+
def method_missing meth, *args, &block
|
|
100
|
+
current.send(meth, *args, &block)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# show the contents of the session without key/value of the cookie
|
|
104
|
+
|
|
105
|
+
def inspect
|
|
106
|
+
tmp = current.clone
|
|
107
|
+
tmp.delete SESSION_KEY
|
|
108
|
+
tmp.inspect
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# show only the key/value of the cookie, useful for debugging.
|
|
112
|
+
|
|
113
|
+
def export
|
|
114
|
+
"#{SESSION_KEY}=#{session_id}"
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# generate an unique #hash for the current session
|
|
118
|
+
|
|
119
|
+
def hash
|
|
120
|
+
h = [
|
|
121
|
+
Time.now.to_f.to_s.reverse, rand,
|
|
122
|
+
Thread.current[:request].hash, rand,
|
|
123
|
+
Process.pid, rand,
|
|
124
|
+
object_id, rand
|
|
125
|
+
].join
|
|
126
|
+
Digest::SHA512.hexdigest(h)
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|