ramaze 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|