rsence 2.0.0.6.pre → 2.0.0.7.pre
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/INSTALL.rdoc +39 -25
- data/VERSION +1 -1
- data/conf/default_conf.yaml +0 -3
- data/lib/conf/default.rb +59 -60
- data/lib/daemon/daemon.rb +269 -280
- data/lib/http/broker.rb +47 -14
- data/lib/http/rackup.rb +4 -0
- data/lib/http/request.rb +47 -49
- data/lib/http/response.rb +47 -45
- data/lib/plugins/gui_plugin.rb +22 -21
- data/lib/plugins/guiparser.rb +95 -94
- data/lib/plugins/plugin.rb +300 -295
- data/lib/plugins/plugin_plugins.rb +64 -40
- data/lib/plugins/plugin_sqlite_db.rb +63 -63
- data/lib/plugins/plugin_util.rb +95 -104
- data/lib/plugins/pluginmanager.rb +373 -414
- data/lib/plugins/plugins.rb +11 -4
- data/lib/plugins/servlet.rb +10 -9
- data/lib/session/msg.rb +249 -248
- data/lib/session/sessionmanager.rb +364 -373
- data/lib/session/sessionstorage.rb +265 -272
- data/lib/transporter/transporter.rb +164 -169
- data/lib/util/gzstring.rb +2 -0
- data/lib/values/hvalue.rb +224 -224
- data/lib/values/valuemanager.rb +98 -98
- data/plugins/index_html/index_html.rb +1 -32
- metadata +4 -4
@@ -7,485 +7,476 @@
|
|
7
7
|
##
|
8
8
|
|
9
9
|
|
10
|
-
|
11
|
-
require 'json'
|
10
|
+
module RSence
|
12
11
|
|
13
|
-
|
14
|
-
require '
|
12
|
+
require 'rubygems'
|
13
|
+
require 'json'
|
15
14
|
|
16
|
-
##
|
17
|
-
require '
|
15
|
+
## Shared messaging-object:
|
16
|
+
require 'session/msg'
|
18
17
|
|
19
|
-
##
|
20
|
-
require '
|
18
|
+
## Unique random number generator:
|
19
|
+
require 'randgen'
|
21
20
|
|
22
|
-
|
21
|
+
## SessionStorage is the superclass of SessionManager
|
22
|
+
require 'session/sessionstorage'
|
23
23
|
|
24
|
-
require 'digest/sha1'
|
24
|
+
require 'digest/sha1'
|
25
25
|
|
26
|
-
|
27
|
-
SessionManager
|
28
|
-
It's quite transparent.
|
29
|
-
=end
|
30
|
-
class SessionManager < SessionStorage
|
26
|
+
# SessionManager does session creation, validation, expiration and storage duties.
|
27
|
+
class SessionManager < SessionStorage
|
31
28
|
|
32
|
-
|
29
|
+
include Digest
|
33
30
|
|
34
|
-
|
31
|
+
attr_reader :randgen
|
35
32
|
|
36
|
-
|
37
|
-
|
33
|
+
## Makes everything ready to run
|
34
|
+
def initialize( transporter )
|
38
35
|
|
39
|
-
|
36
|
+
super()
|
40
37
|
|
41
|
-
|
38
|
+
@transporter = transporter
|
42
39
|
|
43
|
-
|
40
|
+
@valuemanager = @transporter.valuemanager
|
44
41
|
|
45
|
-
|
42
|
+
@plugins = @transporter.plugins
|
46
43
|
|
47
|
-
|
48
|
-
|
44
|
+
## 'Unique' Random String generator for ses_key:s and cookie_key:s
|
45
|
+
@randgen = RandGen.new( @config[:key_length] )
|
49
46
|
|
50
|
-
|
51
|
-
|
47
|
+
# regex to match ipv4 addresses
|
48
|
+
@ipv4_reg = /^([1][0-9][0-9]|[2][0-5][0-9]|[1-9][0-9]|[1-9])\.([1][0-9][0-9]|[2][0-5][0-9]|[1-9][0-9]|[0-9])\.([1][0-9][0-9]|[2][0-5][0-9]|[1-9][0-9]|[0-9])\.([1][0-9][0-9]|[2][0-5][0-9]|[1-9][0-9]|[0-9])$/
|
52
49
|
|
53
|
-
|
50
|
+
end
|
54
51
|
|
55
|
-
|
56
|
-
|
52
|
+
### Creates a new session
|
53
|
+
def init_ses( msg, ses_seed )
|
57
54
|
|
58
|
-
|
59
|
-
|
60
|
-
|
55
|
+
## Assigns new timeout for the session
|
56
|
+
time_now = Time.now.to_i # seconds since epoch
|
57
|
+
timeout = time_now + @config[:timeout_secs]
|
61
58
|
|
62
|
-
|
63
|
-
|
59
|
+
## Creates a new session key
|
60
|
+
ses_key = @randgen.gen
|
64
61
|
|
65
|
-
|
66
|
-
|
62
|
+
## Creates a new cookie key
|
63
|
+
cookie_key = @randgen.gen_many(@config[:cookie_key_multiplier]).join('')
|
67
64
|
|
68
|
-
|
69
|
-
|
65
|
+
## Makes a new database row for the session, returns its id
|
66
|
+
ses_id = new_ses_id( cookie_key, ses_key, timeout )
|
70
67
|
|
71
|
-
|
68
|
+
ses_sha = SHA1.hexdigest(ses_key+ses_seed)
|
72
69
|
|
73
|
-
|
74
|
-
|
75
|
-
|
70
|
+
### Default session data structure,
|
71
|
+
### Please don't mess with it, unless you know exactly what you are doing.
|
72
|
+
ses_data = {
|
76
73
|
|
77
|
-
|
78
|
-
|
74
|
+
# the time, when the session will time out
|
75
|
+
:timeout => timeout,
|
79
76
|
|
80
|
-
|
81
|
-
|
77
|
+
# session id, used internally
|
78
|
+
:ses_id => ses_id,
|
82
79
|
|
83
|
-
|
84
|
-
|
80
|
+
# session key, used externally (client xhr)
|
81
|
+
:ses_key => ses_sha,
|
85
82
|
|
86
|
-
|
87
|
-
|
83
|
+
# session key, used externally (client cookies)
|
84
|
+
:cookie_key => cookie_key,
|
88
85
|
|
89
|
-
|
90
|
-
|
86
|
+
# user id, map to your own user management code
|
87
|
+
:user_id => 0,
|
91
88
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
89
|
+
# valuemanager data
|
90
|
+
:values => {
|
91
|
+
:sync => [], # value id's to sync to client
|
92
|
+
:check => [], # value id's to validate in server (from client)
|
93
|
+
:by_id => {} # values by id
|
94
|
+
}
|
97
95
|
}
|
98
|
-
}
|
99
96
|
|
100
|
-
|
101
|
-
|
97
|
+
# bind the session data to @sessions by its id
|
98
|
+
@sessions[ ses_id ] = ses_data
|
102
99
|
|
103
|
-
|
104
|
-
|
100
|
+
# map the key back to the id
|
101
|
+
@session_keys[ ses_sha ] = ses_id
|
105
102
|
|
106
|
-
|
107
|
-
|
103
|
+
# map the ses_id to cookie key
|
104
|
+
@session_cookie_keys[ cookie_key ] = ses_id
|
108
105
|
|
109
|
-
|
110
|
-
|
106
|
+
### Tell the client what the new key is
|
107
|
+
msg.ses_key = ses_key
|
111
108
|
|
112
|
-
|
113
|
-
|
109
|
+
### Set the session data and id to the message object
|
110
|
+
msg.session = ses_data
|
114
111
|
|
115
|
-
|
116
|
-
|
117
|
-
|
112
|
+
# Flag the session as new, so associated
|
113
|
+
# plugins know when to create new data
|
114
|
+
msg.new_session = true
|
118
115
|
|
119
|
-
|
120
|
-
|
116
|
+
# Returns the cookie key, so it can be sent in the response header
|
117
|
+
return cookie_key
|
121
118
|
|
122
|
-
|
119
|
+
end
|
123
120
|
|
124
|
-
|
125
|
-
|
126
|
-
|
121
|
+
def refresh_ses( msg, ses_data, ses_id, ses_key, ses_seed )
|
122
|
+
# new time-out
|
123
|
+
ses_data[:timeout] = Time.now.to_i + @config[:timeout_secs]
|
127
124
|
|
128
|
-
|
129
|
-
|
125
|
+
# re-generates the ses_key for each xhr
|
126
|
+
if @config[:disposable_keys]
|
130
127
|
|
131
|
-
|
132
|
-
|
128
|
+
# disposes the old (current) ses_key:
|
129
|
+
@session_keys.delete( ses_key )
|
133
130
|
|
134
|
-
|
135
|
-
|
136
|
-
|
131
|
+
unless ses_seed
|
132
|
+
ses_seed = ses_key
|
133
|
+
end
|
137
134
|
|
138
|
-
|
139
|
-
|
135
|
+
# gets a new ses_key:
|
136
|
+
ses_key = @randgen.gen
|
140
137
|
|
141
|
-
|
138
|
+
ses_sha = SHA1.hexdigest(ses_key+ses_seed)
|
142
139
|
|
143
|
-
|
144
|
-
|
140
|
+
# re-maps the session id to the new key
|
141
|
+
@session_keys[ses_sha] = ses_id
|
145
142
|
|
146
|
-
|
147
|
-
|
143
|
+
# changes the session key in the session data
|
144
|
+
ses_data[:ses_key] = ses_sha
|
148
145
|
|
149
|
-
|
150
|
-
|
151
|
-
|
146
|
+
# tell the client what its new session key is
|
147
|
+
msg.ses_key = ses_key
|
148
|
+
end
|
152
149
|
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
150
|
+
if @config[:clone_cookie_sessions] and @clone_targets.has_key? ses_id
|
151
|
+
targets = []
|
152
|
+
@clone_targets[ ses_id ].length.times do |n|
|
153
|
+
target_id = @clone_targets[ ses_id ].shift
|
154
|
+
# warn "target_id: #{target_id}"
|
155
|
+
target_ses = @sessions[ target_id ]
|
156
|
+
if @sessions.has_key?( target_id ) and @sessions[ target_id ].class == Hash
|
157
|
+
targets.push( target_ses )
|
158
|
+
end
|
161
159
|
end
|
160
|
+
@clone_targets.delete( ses_id ) if @clone_targets[ ses_id ].empty?
|
161
|
+
msg.cloned_targets = targets unless targets.empty?
|
162
162
|
end
|
163
|
-
@clone_targets.delete( ses_id ) if @clone_targets[ ses_id ].empty?
|
164
|
-
msg.cloned_targets = targets unless targets.empty?
|
165
|
-
end
|
166
163
|
|
167
|
-
|
168
|
-
|
164
|
+
### Bind the session data and id to the message object
|
165
|
+
msg.session = ses_data
|
169
166
|
|
170
|
-
|
167
|
+
end
|
171
168
|
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
169
|
+
def clone_ses( msg, old_data, old_id, old_key, ses_seed )
|
170
|
+
ses_data = Marshal.restore( Marshal.dump( old_data ) )
|
171
|
+
old_data[:timeout] = Time.now.to_i + @config[:cloned_session_expires_in]
|
172
|
+
timeout = Time.now.to_i + @config[:timeout_secs]
|
173
|
+
cookie_key = @randgen.gen_many(@config[:cookie_key_multiplier]).join('')
|
174
|
+
ses_key = @randgen.gen
|
175
|
+
ses_sha = SHA1.hexdigest(ses_key+ses_seed)
|
176
|
+
ses_data[:timeout] = timeout
|
177
|
+
ses_data[:ses_key] = ses_key
|
178
|
+
ses_data[:cookie_key] = cookie_key
|
179
|
+
ses_id = new_ses_id( cookie_key, ses_key, timeout )
|
180
|
+
ses_data[:ses_id] = ses_id
|
181
|
+
@sessions[ ses_id ] = ses_data
|
182
|
+
@session_keys[ ses_sha ] = ses_id
|
183
|
+
@session_cookie_keys.delete( old_data[:cookie_key] )
|
184
|
+
@session_cookie_keys[ cookie_key ] = ses_id
|
185
|
+
msg.ses_key = ses_key
|
186
|
+
msg.session = ses_data
|
187
|
+
if @clone_targets.has_key? old_id
|
188
|
+
@clone_targets[ old_id ].push( ses_id )
|
189
|
+
else
|
190
|
+
@clone_targets[ old_id ] = [ ses_id ]
|
191
|
+
end
|
192
|
+
@clone_sources[ ses_id ] = old_id
|
193
|
+
msg.cloned_source = old_data
|
194
|
+
msg.new_session = false
|
195
|
+
msg.restored_session = true
|
194
196
|
end
|
195
|
-
@clone_sources[ ses_id ] = old_id
|
196
|
-
msg.cloned_source = old_data
|
197
|
-
msg.new_session = false
|
198
|
-
msg.restored_session = true
|
199
|
-
end
|
200
197
|
|
201
|
-
|
202
|
-
|
203
|
-
|
198
|
+
### Returns the current session data, if the session is valid.
|
199
|
+
### Otherwise stops the client and returns false.
|
200
|
+
def check_ses( msg, ses_key, ses_seed=false )
|
204
201
|
|
205
|
-
|
206
|
-
|
202
|
+
# first, check if the session key exists (xhr)
|
203
|
+
if @session_keys.has_key?( ses_key )
|
207
204
|
|
208
|
-
|
209
|
-
|
205
|
+
# get the session's id based on its key
|
206
|
+
ses_id = @session_keys[ ses_key ]
|
210
207
|
|
211
|
-
|
212
|
-
|
208
|
+
# get the session's data based on its id
|
209
|
+
ses_data = @sessions[ ses_id ]
|
210
|
+
|
211
|
+
if @config[:clone_cookie_sessions] and ses_seed
|
212
|
+
clone_ses( msg, ses_data, ses_id, ses_key, ses_seed )
|
213
|
+
return [true, true]
|
214
|
+
else
|
215
|
+
refresh_ses( msg, ses_data, ses_id, ses_key, ses_seed )
|
216
|
+
return [true, false]
|
217
|
+
end
|
213
218
|
|
214
|
-
|
215
|
-
|
216
|
-
return [true, true]
|
219
|
+
|
220
|
+
## The session was either faked or expired:
|
217
221
|
else
|
218
|
-
|
219
|
-
|
222
|
+
### Tells the client to stop connecting with its session key and reload instead to get a new one.
|
223
|
+
stop_client_with_message( msg,
|
224
|
+
@config[:messages][:invalid_session][:title],
|
225
|
+
@config[:messages][:invalid_session][:descr],
|
226
|
+
@config[:messages][:invalid_session][:uri]
|
227
|
+
)
|
228
|
+
|
229
|
+
## Return failure
|
230
|
+
return [false, false]
|
220
231
|
end
|
221
|
-
|
222
232
|
|
223
|
-
## The session was either faked or expired:
|
224
|
-
else
|
225
|
-
### Tells the client to stop connecting with its session key and reload instead to get a new one.
|
226
|
-
stop_client_with_message( msg,
|
227
|
-
@config[:messages][:invalid_session][:title],
|
228
|
-
@config[:messages][:invalid_session][:descr],
|
229
|
-
@config[:messages][:invalid_session][:uri]
|
230
|
-
)
|
231
|
-
|
232
|
-
## Return failure
|
233
|
-
return [false, false]
|
234
233
|
end
|
235
|
-
|
236
|
-
end
|
237
234
|
|
238
|
-
|
239
|
-
|
240
|
-
|
235
|
+
def js_str( str )
|
236
|
+
return str.to_json.gsub('<','<').gsub('>','>').gsub(/\[\[(.*?)\]\]/,'<\1>')
|
237
|
+
end
|
241
238
|
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
239
|
+
## Displays error message and stops the client
|
240
|
+
def stop_client_with_message( msg,
|
241
|
+
title = 'Unknown Issue',
|
242
|
+
descr = 'No issue description given.',
|
243
|
+
uri = ::RSence.config[:index_html][:respond_address] )
|
244
|
+
msg.error_msg( [
|
245
|
+
"jsLoader.load('default_theme');",
|
246
|
+
"jsLoader.load('controls');",
|
247
|
+
"jsLoader.load('servermessage');",
|
248
|
+
"ReloadApp.nu( #{js_str(title)}, #{js_str(descr)}, #{js_str(uri)} );"
|
249
|
+
] )
|
250
|
+
end
|
254
251
|
|
255
|
-
|
256
|
-
|
252
|
+
### Checks / Sets cookies
|
253
|
+
def check_cookie( msg, ses_seed )
|
257
254
|
|
258
|
-
|
259
|
-
|
255
|
+
# default to no cookie key found:
|
256
|
+
cookie_key = false
|
260
257
|
|
261
|
-
|
262
|
-
|
258
|
+
# gets the cookie array from the request object
|
259
|
+
cookie_raw = msg.request.cookies
|
263
260
|
|
264
|
-
|
265
|
-
|
261
|
+
# checks, if a cookie named 'ses_key' is found
|
262
|
+
if cookie_raw.has_key?('ses_key')
|
266
263
|
|
267
|
-
|
268
|
-
|
264
|
+
# gets just the data itself (discards comment, domain, exipiry etc)
|
265
|
+
cookie_key = cookie_raw['ses_key'].split(';')[0]
|
269
266
|
|
270
|
-
|
267
|
+
end
|
271
268
|
|
272
|
-
|
273
|
-
|
269
|
+
# if a cookie key is found (non-false), checks if it's valid
|
270
|
+
if cookie_key
|
274
271
|
|
275
|
-
|
276
|
-
|
272
|
+
# checks for validity by looking the key up in @session_cookie_keys
|
273
|
+
cookie_key_exist = @session_cookie_keys.has_key?( cookie_key )
|
277
274
|
|
278
|
-
|
279
|
-
|
275
|
+
# sets the cookie key to false, if it doesn't exist
|
276
|
+
cookie_key = false unless cookie_key_exist
|
280
277
|
|
281
|
-
|
278
|
+
end
|
282
279
|
|
283
|
-
|
284
|
-
|
280
|
+
# at this point, the cookie key seems valid:
|
281
|
+
if cookie_key and cookie_key_exist
|
285
282
|
|
286
|
-
|
287
|
-
|
283
|
+
# get the session identifier
|
284
|
+
ses_id = @session_cookie_keys[ cookie_key ]
|
288
285
|
|
289
|
-
|
290
|
-
|
286
|
+
# get the last session key from session data
|
287
|
+
ses_key = @sessions[ses_id][:ses_key]
|
291
288
|
|
292
|
-
|
293
|
-
|
289
|
+
# make additional checks on the session validity (expiry etc)
|
290
|
+
(ses_status, ses_cloned) = check_ses( msg, ses_key, ses_seed )
|
294
291
|
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
292
|
+
if ses_status and ses_cloned
|
293
|
+
ses_id = msg.ses_id
|
294
|
+
ses_key = msg.session[:ses_key]
|
295
|
+
cookie_key = msg.session[:cookie_key]
|
296
|
+
@valuemanager.resend_session_values( msg )
|
297
|
+
elsif ses_status
|
298
|
+
# delete the old cookie key:
|
299
|
+
@session_cookie_keys.delete( cookie_key )
|
303
300
|
|
304
|
-
|
305
|
-
|
301
|
+
# get a new cookie key
|
302
|
+
cookie_key = @randgen.gen_many(@config[:cookie_key_multiplier]).join('')
|
306
303
|
|
307
|
-
|
308
|
-
|
304
|
+
# map the new cookie key to the old session identifier
|
305
|
+
@session_cookie_keys[ cookie_key ] = ses_id
|
309
306
|
|
310
|
-
|
311
|
-
|
307
|
+
# binds the new cookie key to the old session data
|
308
|
+
@sessions[ses_id][:cookie_key] = cookie_key
|
312
309
|
|
313
|
-
|
314
|
-
|
315
|
-
|
310
|
+
# Sets the restored_session flag of msg to true
|
311
|
+
# It signals plugins to re-set data
|
312
|
+
msg.restored_session = true
|
316
313
|
|
317
|
-
|
318
|
-
|
319
|
-
|
314
|
+
# Sets the new_session flag of msg to false
|
315
|
+
# It signals plugins to not create new server-side values
|
316
|
+
msg.new_session = false
|
320
317
|
|
321
|
-
|
322
|
-
|
323
|
-
|
318
|
+
# tells ValueManager to re-send client-side HValue objects
|
319
|
+
# with data to the client
|
320
|
+
@valuemanager.resend_session_values( msg )
|
324
321
|
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
322
|
+
# if the session is not valid, make sure to mark the
|
323
|
+
# cookie key as invalid (false)
|
324
|
+
else
|
325
|
+
cookie_key = false
|
326
|
+
end
|
329
327
|
end
|
330
|
-
end
|
331
328
|
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
329
|
+
# if the cookie key failed validation in the
|
330
|
+
# tests above, create a new session instead
|
331
|
+
unless cookie_key
|
332
|
+
cookie_key = init_ses( msg, ses_seed )
|
333
|
+
ses_status = true
|
334
|
+
end
|
338
335
|
|
339
|
-
|
336
|
+
renew_cookie( msg, cookie_key )
|
340
337
|
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
end
|
347
|
-
|
348
|
-
def renew_cookie( msg, cookie_key )
|
349
|
-
# Uses a cookie comment to tell the user what the
|
350
|
-
# cookie is for, change it to anything valid in the
|
351
|
-
# configuration.
|
352
|
-
ses_cookie_comment = @config[:ses_cookie_comment]
|
353
|
-
|
354
|
-
## mod_rewrite changes the host header to x-forwarded-host:
|
355
|
-
if msg.request.header.has_key?('x-forwarded-host')
|
356
|
-
domain = msg.request.header['x-forwarded-host']
|
357
|
-
|
358
|
-
## direct access just uses host (at least mongrel
|
359
|
-
## does mod_rewrite header translation):
|
360
|
-
else
|
361
|
-
domain = msg.request.host
|
338
|
+
## Return the session status. Actually,
|
339
|
+
## the value is always true, but future
|
340
|
+
## versions might not accept invalid
|
341
|
+
## cookies as new sessions.
|
342
|
+
return ses_status
|
362
343
|
end
|
344
|
+
|
345
|
+
def renew_cookie( msg, cookie_key )
|
346
|
+
# Uses a cookie comment to tell the user what the
|
347
|
+
# cookie is for, change it to anything valid in the
|
348
|
+
# configuration.
|
349
|
+
ses_cookie_comment = @config[:ses_cookie_comment]
|
350
|
+
|
351
|
+
## mod_rewrite changes the host header to x-forwarded-host:
|
352
|
+
if msg.request.header.has_key?('x-forwarded-host')
|
353
|
+
domain = msg.request.header['x-forwarded-host']
|
354
|
+
|
355
|
+
## direct access just uses host (at least mongrel
|
356
|
+
## does mod_rewrite header translation):
|
357
|
+
else
|
358
|
+
domain = msg.request.host
|
359
|
+
end
|
363
360
|
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
361
|
+
if domain == 'localhost'
|
362
|
+
warn "Warning: Cookies won't be set for 'localhost'. Use '127.0.0.1' instead." if RSence.args[:debug]
|
363
|
+
return
|
364
|
+
end
|
368
365
|
|
369
|
-
|
370
|
-
|
371
|
-
## if the host address is a real domain
|
372
|
-
## (not just hostname or 'localhost'),
|
373
|
-
## but not an ip-address, prepend it with
|
374
|
-
## a dot to accept wildcards (useful for
|
375
|
-
## dns-load-balanced server configurations)
|
376
|
-
if not @ipv4_reg.match(domain) and domain.include?('.')
|
377
|
-
ses_cookie_domain = ".#{domain}"
|
378
|
-
## Otherwise, use the domain as-is
|
379
|
-
else
|
380
|
-
ses_cookie_domain = domain
|
381
|
-
end
|
366
|
+
server_port = msg.request.port
|
382
367
|
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
end
|
368
|
+
## if the host address is a real domain
|
369
|
+
## (not just hostname or 'localhost'),
|
370
|
+
## but not an ip-address, prepend it with
|
371
|
+
## a dot to accept wildcards (useful for
|
372
|
+
## dns-load-balanced server configurations)
|
373
|
+
if not @ipv4_reg.match(domain) and domain.include?('.')
|
374
|
+
ses_cookie_domain = ".#{domain}"
|
375
|
+
## Otherwise, use the domain as-is
|
376
|
+
else
|
377
|
+
ses_cookie_domain = domain
|
378
|
+
end
|
395
379
|
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
"Path=#{ses_cookie_path}",
|
401
|
-
"Port=#{server_port}",
|
402
|
-
"Max-Age=#{ses_cookie_max_age}",
|
403
|
-
"Comment=#{ses_cookie_comment}",
|
404
|
-
"Domain=#{ses_cookie_domain}"
|
405
|
-
]
|
406
|
-
|
407
|
-
### Sets the set-cookie header
|
408
|
-
msg.response['Set-Cookie'] = ses_cookie_arr.join('; ')
|
409
|
-
end
|
410
|
-
|
411
|
-
### Creates a message and checks the session
|
412
|
-
def init_msg( request, response, options = { :cookies => false, :servlet => false } )
|
380
|
+
## uses the timeout to declare the max age
|
381
|
+
## of the cookie, allows the browser to delete
|
382
|
+
## it, when it expires.
|
383
|
+
ses_cookie_max_age = @config[:timeout_secs]
|
413
384
|
|
414
|
-
|
385
|
+
## Only match the handshaking address of rsence,
|
386
|
+
## prevents unneccessary cookie-juggling in xhr's
|
387
|
+
if @config[:trust_cookies]
|
388
|
+
ses_cookie_path = '/'
|
389
|
+
else
|
390
|
+
ses_cookie_path = ::RSence.config[:broker_urls][:hello]
|
391
|
+
end
|
415
392
|
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
393
|
+
## Formats the cookie to string
|
394
|
+
## (through array, to keep it readable in the source)
|
395
|
+
ses_cookie_arr = [
|
396
|
+
"ses_key=#{cookie_key}",
|
397
|
+
"Path=#{ses_cookie_path}",
|
398
|
+
"Port=#{server_port}",
|
399
|
+
"Max-Age=#{ses_cookie_max_age}",
|
400
|
+
"Comment=#{ses_cookie_comment}",
|
401
|
+
"Domain=#{ses_cookie_domain}"
|
402
|
+
]
|
403
|
+
|
404
|
+
### Sets the set-cookie header
|
405
|
+
msg.response['Set-Cookie'] = ses_cookie_arr.join('; ')
|
420
406
|
end
|
407
|
+
|
408
|
+
### Creates a message and checks the session
|
409
|
+
def init_msg( request, response, options = { :cookies => false, :servlet => false } )
|
410
|
+
|
411
|
+
cookies = options[:cookies]
|
421
412
|
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
##
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
413
|
+
if options.has_key?(:query)
|
414
|
+
query = options[:query]
|
415
|
+
else
|
416
|
+
query = request.query
|
417
|
+
end
|
418
|
+
|
419
|
+
## Perform old-session cleanup on all xhr:s
|
420
|
+
expire_sessions
|
421
|
+
|
422
|
+
## The 'ses_id' request query key is required.
|
423
|
+
## The client defaults to '0', which means the
|
424
|
+
## client needs to be initialized.
|
425
|
+
## The client's ses_id is the server's ses_key.
|
426
|
+
if not query.has_key?( 'ses_key' )
|
427
|
+
return Message.new( @transporter, request, response, options )
|
428
|
+
else
|
429
|
+
|
430
|
+
## get the ses_key from the request query:
|
431
|
+
ses_key = query[ 'ses_key' ]
|
432
|
+
# puts "ses key: #{ses_key}"
|
433
|
+
## The message object binds request, response
|
434
|
+
## and all user/session -related data to one
|
435
|
+
## object, which is passed around where
|
436
|
+
## request/response/user/session -related
|
437
|
+
## data is needed.
|
438
|
+
msg = Message.new( @transporter, request, response, options )
|
439
|
+
|
440
|
+
## The client tells that its ses_key is '0',
|
441
|
+
## until the server tells it otherwise.
|
442
|
+
(req_num, ses_seed) = ses_key.split(':.o.:')
|
443
|
+
|
444
|
+
if req_num == '0'
|
448
445
|
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
446
|
+
# If Broker encounters a '/hello' request, it
|
447
|
+
# sets cookies to true.
|
448
|
+
#
|
449
|
+
# It means that a session should have its cookies
|
450
|
+
# checked.
|
451
|
+
#
|
452
|
+
if cookies
|
453
|
+
ses_status = check_cookie( msg, ses_seed )
|
454
|
+
# Otherwise, a new session is created:
|
455
|
+
else
|
456
|
+
init_ses( msg, ses_seed )
|
457
|
+
ses_status = true
|
458
|
+
end
|
459
|
+
|
460
|
+
# for non-'0' ses_keys:
|
458
461
|
else
|
459
|
-
init_ses( msg, ses_seed )
|
460
|
-
ses_status = true
|
461
|
-
end
|
462
|
-
|
463
|
-
# for non-'0' ses_keys:
|
464
|
-
else
|
465
462
|
|
466
|
-
|
467
|
-
|
463
|
+
## Validate the session key
|
464
|
+
ses_status = check_ses( msg, ses_seed )[0]
|
468
465
|
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
466
|
+
## Renew the cookie even when the request is a "x" (not "hello")
|
467
|
+
if @config[:session_cookies] and ses_status
|
468
|
+
renew_cookie( msg, msg.session[:cookie_key] )
|
469
|
+
end
|
473
470
|
|
474
|
-
|
475
|
-
|
476
|
-
## msg.ses_valid is false by default, meaning
|
477
|
-
## it's not valid or hasn't been initialized.
|
478
|
-
msg.ses_valid = ses_status
|
471
|
+
end # /ses_key
|
479
472
|
|
480
|
-
|
473
|
+
## msg.ses_valid is false by default, meaning
|
474
|
+
## it's not valid or hasn't been initialized.
|
475
|
+
msg.ses_valid = ses_status
|
481
476
|
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
end
|
488
|
-
|
489
|
-
|
477
|
+
return msg
|
478
|
+
end # /ses_key
|
479
|
+
end # /init_msg
|
480
|
+
end
|
490
481
|
end
|
491
482
|
|