sbsm 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/COPYING +515 -0
- data/History.txt +5 -0
- data/Manifest.txt +49 -0
- data/README.txt +41 -0
- data/Rakefile +28 -0
- data/data/_flavored_uri.grammar +24 -0
- data/data/_uri.grammar +22 -0
- data/data/_zone_uri.grammar +24 -0
- data/data/flavored_uri.grammar +24 -0
- data/data/uri.grammar +22 -0
- data/data/zone_uri.grammar +24 -0
- data/install.rb +1098 -0
- data/lib/cgi/drbsession.rb +37 -0
- data/lib/sbsm/cgi.rb +79 -0
- data/lib/sbsm/drb.rb +19 -0
- data/lib/sbsm/drbserver.rb +162 -0
- data/lib/sbsm/exception.rb +28 -0
- data/lib/sbsm/flavored_uri_parser.rb +47 -0
- data/lib/sbsm/index.rb +66 -0
- data/lib/sbsm/lookandfeel.rb +176 -0
- data/lib/sbsm/lookandfeelfactory.rb +50 -0
- data/lib/sbsm/lookandfeelwrapper.rb +109 -0
- data/lib/sbsm/redefine_19_cookie.rb +4 -0
- data/lib/sbsm/redirector.rb +37 -0
- data/lib/sbsm/request.rb +162 -0
- data/lib/sbsm/session.rb +542 -0
- data/lib/sbsm/state.rb +301 -0
- data/lib/sbsm/time.rb +29 -0
- data/lib/sbsm/trans_handler.rb +119 -0
- data/lib/sbsm/turing.rb +25 -0
- data/lib/sbsm/uri_parser.rb +45 -0
- data/lib/sbsm/user.rb +47 -0
- data/lib/sbsm/validator.rb +256 -0
- data/lib/sbsm/viralstate.rb +47 -0
- data/lib/sbsm/zone_uri_parser.rb +48 -0
- data/test/data/dos_file.txt +2 -0
- data/test/data/lnf_file.txt +2 -0
- data/test/data/mac_file.txt +1 -0
- data/test/stub/cgi.rb +35 -0
- data/test/suite.rb +29 -0
- data/test/test_drbserver.rb +83 -0
- data/test/test_index.rb +90 -0
- data/test/test_lookandfeel.rb +230 -0
- data/test/test_session.rb +372 -0
- data/test/test_state.rb +176 -0
- data/test/test_trans_handler.rb +447 -0
- data/test/test_user.rb +44 -0
- data/test/test_validator.rb +126 -0
- data/usage-en.txt +112 -0
- metadata +142 -0
data/lib/sbsm/session.rb
ADDED
@@ -0,0 +1,542 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# State Based Session Management
|
4
|
+
# Copyright (C) 2004 Hannes Wyss
|
5
|
+
#
|
6
|
+
# This library is free software; you can redistribute it and/or
|
7
|
+
# modify it under the terms of the GNU Lesser General Public
|
8
|
+
# License as published by the Free Software Foundation; either
|
9
|
+
# version 2.1 of the License, or (at your option) any later version.
|
10
|
+
#
|
11
|
+
# This library is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
14
|
+
# Lesser General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU Lesser General Public
|
17
|
+
# License along with this library; if not, write to the Free Software
|
18
|
+
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
19
|
+
#
|
20
|
+
# ywesee - intellectual capital connected, Winterthurerstrasse 52, CH-8006 Z�rich, Switzerland
|
21
|
+
# hwyss@ywesee.com
|
22
|
+
#
|
23
|
+
# Session -- sbsm -- 22.10.2002 -- hwyss@ywesee.com
|
24
|
+
|
25
|
+
require 'sbsm/cgi'
|
26
|
+
require 'sbsm/drb'
|
27
|
+
require 'sbsm/state'
|
28
|
+
require 'sbsm/lookandfeelfactory'
|
29
|
+
require 'sbsm/redefine_19_cookie'
|
30
|
+
require 'delegate'
|
31
|
+
|
32
|
+
module SBSM
|
33
|
+
class Session < SimpleDelegator
|
34
|
+
attr_reader :user, :active_thread, :app, :key, :cookie_input,
|
35
|
+
:unsafe_input, :valid_input, :request_path
|
36
|
+
include DRbUndumped
|
37
|
+
PERSISTENT_COOKIE_NAME = "sbsm-persistent-cookie"
|
38
|
+
DEFAULT_FLAVOR = nil
|
39
|
+
DEFAULT_LANGUAGE = nil
|
40
|
+
DEFAULT_STATE = State
|
41
|
+
DEFAULT_ZONE = nil
|
42
|
+
DRB_LOAD_LIMIT = 255 * 102400
|
43
|
+
EXPIRES = 60 * 60
|
44
|
+
LF_FACTORY = nil
|
45
|
+
LOOKANDFEEL = Lookandfeel
|
46
|
+
CAP_MAX_THRESHOLD = 8
|
47
|
+
MAX_STATES = 4
|
48
|
+
SERVER_NAME = nil
|
49
|
+
ARGV.push('') # satisfy cgi-offline prompt
|
50
|
+
@@cgi = CGI.new('html4')
|
51
|
+
def Session.reset_stats
|
52
|
+
@@stats = {}
|
53
|
+
end
|
54
|
+
reset_stats
|
55
|
+
@@stats_ptrn = /./
|
56
|
+
def Session.show_stats ptrn=@@stats_ptrn
|
57
|
+
if ptrn.is_a?(String)
|
58
|
+
ptrn = /#{ptrn}/i
|
59
|
+
end
|
60
|
+
puts sprintf("%8s %8s %8s %6s %10s Request-Path",
|
61
|
+
"Min", "Max", "Avg", "Num", "Total")
|
62
|
+
grand_total = requests = all_max = all_min = 0
|
63
|
+
@@stats.collect do |path, times|
|
64
|
+
total = times.inject do |a, b| a + b end
|
65
|
+
grand_total += total
|
66
|
+
size = times.size
|
67
|
+
requests += size
|
68
|
+
max = times.max
|
69
|
+
all_max = max > all_max ? max : all_max
|
70
|
+
min = times.min
|
71
|
+
all_min = min < all_min ? min : all_min
|
72
|
+
[min, max, total / size, size, total, path]
|
73
|
+
end.sort.each do |data|
|
74
|
+
line = sprintf("%8.2f %8.2f %8.2f %6i %10.2f %s", *data)
|
75
|
+
if ptrn.match(line)
|
76
|
+
puts line
|
77
|
+
end
|
78
|
+
end
|
79
|
+
puts sprintf("%8s %8s %8s %6s %10s Request-Path",
|
80
|
+
"Min", "Max", "Avg", "Num", "Total")
|
81
|
+
puts sprintf("%8.2f %8.2f %8.2f %6i %10.2f",
|
82
|
+
all_min, all_max,
|
83
|
+
requests > 0 ? grand_total / requests : 0,
|
84
|
+
requests, grand_total)
|
85
|
+
''
|
86
|
+
end
|
87
|
+
def initialize(key, app, validator=nil)
|
88
|
+
touch()
|
89
|
+
reset_input()
|
90
|
+
reset_cookie()
|
91
|
+
@app = app
|
92
|
+
@key = key
|
93
|
+
@validator = validator
|
94
|
+
@attended_states = {}
|
95
|
+
@persistent_user_input = {}
|
96
|
+
logout()
|
97
|
+
@unknown_user_class = @user.class
|
98
|
+
@variables = {}
|
99
|
+
@mutex = Mutex.new
|
100
|
+
#ARGV.push('') # satisfy cgi-offline prompt
|
101
|
+
#@cgi = CGI.new('html4')
|
102
|
+
super(app)
|
103
|
+
end
|
104
|
+
def age(now=Time.now)
|
105
|
+
now - @mtime
|
106
|
+
end
|
107
|
+
def cap_max_states
|
108
|
+
if(@attended_states.size > self::class::CAP_MAX_THRESHOLD)
|
109
|
+
#puts "too many states in session! Keeping only #{self::class::MAX_STATES}"
|
110
|
+
#$stdout.flush
|
111
|
+
sorted = @attended_states.values.sort
|
112
|
+
sorted[0...(-self::class::MAX_STATES)].each { |state|
|
113
|
+
state.__checkout
|
114
|
+
@attended_states.delete(state.object_id)
|
115
|
+
}
|
116
|
+
@attended_states.size
|
117
|
+
end
|
118
|
+
end
|
119
|
+
def __checkout
|
120
|
+
@attended_states.each_value { |state| state.__checkout }
|
121
|
+
@attended_states.clear
|
122
|
+
flavor = @persistent_user_input[:flavor]
|
123
|
+
lang = @persistent_user_input[:language]
|
124
|
+
@persistent_user_input.clear
|
125
|
+
@persistent_user_input.store(:flavor, flavor)
|
126
|
+
@persistent_user_input.store(:language, lang)
|
127
|
+
@valid_input.clear
|
128
|
+
@unsafe_input.clear
|
129
|
+
@active_thread = nil
|
130
|
+
true
|
131
|
+
end
|
132
|
+
def cgi
|
133
|
+
@@cgi
|
134
|
+
end
|
135
|
+
@@msie_ptrn = /MSIE/
|
136
|
+
@@win_ptrn = /Win/i
|
137
|
+
def client_activex?
|
138
|
+
(ua = user_agent) && @@msie_ptrn.match(ua) && @@win_ptrn.match(ua)
|
139
|
+
end
|
140
|
+
@@nt5_ptrn = /Windows\s*NT\s*(\d+\.\d+)/i
|
141
|
+
def client_nt5?
|
142
|
+
(ua = user_agent) \
|
143
|
+
&& (match = @@nt5_ptrn.match(user_agent)) \
|
144
|
+
&& (match[1].to_f >= 5)
|
145
|
+
end
|
146
|
+
def cookie_set_or_get(key)
|
147
|
+
if(value = @valid_input[key])
|
148
|
+
set_cookie_input(key, value)
|
149
|
+
else
|
150
|
+
@cookie_input[key]
|
151
|
+
end
|
152
|
+
end
|
153
|
+
def get_cookie_input(key)
|
154
|
+
@cookie_input[key]
|
155
|
+
end
|
156
|
+
def cookie_name
|
157
|
+
self::class::PERSISTENT_COOKIE_NAME
|
158
|
+
end
|
159
|
+
def default_language
|
160
|
+
self::class::DEFAULT_LANGUAGE
|
161
|
+
end
|
162
|
+
def direct_event
|
163
|
+
@state.direct_event
|
164
|
+
end
|
165
|
+
def drb_process(request)
|
166
|
+
start = Time.now
|
167
|
+
html = @mutex.synchronize do
|
168
|
+
process(request)
|
169
|
+
to_html
|
170
|
+
end
|
171
|
+
(@@stats[@request_path] ||= []).push(Time.now - start)
|
172
|
+
html
|
173
|
+
end
|
174
|
+
def error(key)
|
175
|
+
@state.error(key) if @state.respond_to?(:error)
|
176
|
+
end
|
177
|
+
def errors
|
178
|
+
@state.errors.values if @state.respond_to?(:errors)
|
179
|
+
end
|
180
|
+
def error?
|
181
|
+
@state.error? if @state.respond_to?(:error?)
|
182
|
+
end
|
183
|
+
def event
|
184
|
+
@valid_input[:event]
|
185
|
+
end
|
186
|
+
def event_bound_user_input(key)
|
187
|
+
@event_user_input ||= {}
|
188
|
+
evt = state.direct_event
|
189
|
+
@event_user_input[evt] ||= {}
|
190
|
+
if(val = user_input(key))
|
191
|
+
@event_user_input[evt][key] = val
|
192
|
+
else
|
193
|
+
@event_user_input[evt][key]
|
194
|
+
end
|
195
|
+
end
|
196
|
+
def expired?(now=Time.now)
|
197
|
+
age(now) > EXPIRES
|
198
|
+
end
|
199
|
+
def force_login(user)
|
200
|
+
@user = user
|
201
|
+
end
|
202
|
+
def import_cookies(request)
|
203
|
+
reset_cookie()
|
204
|
+
if(cuki = request.cookies[self::class::PERSISTENT_COOKIE_NAME])
|
205
|
+
cuki.each { |cuki_str|
|
206
|
+
CGI.parse(CGI.unescape(cuki_str)).each { |key, val|
|
207
|
+
key = key.intern
|
208
|
+
valid = @validator.validate(key, val.compact.last)
|
209
|
+
@cookie_input.store(key, valid)
|
210
|
+
}
|
211
|
+
}
|
212
|
+
end
|
213
|
+
end
|
214
|
+
@@hash_ptrn = /([^\[]+)((\[[^\]]+\])+)/
|
215
|
+
@@index_ptrn = /[^\[\]]+/
|
216
|
+
def import_user_input(request)
|
217
|
+
# attempting to read the cgi-params more than once results in a
|
218
|
+
# DRbConnectionRefused Exception. Therefore, do it only once...
|
219
|
+
return if(@user_input_imported)
|
220
|
+
request.params.each { |key, value|
|
221
|
+
#puts "importing #{key} -> #{value}"
|
222
|
+
index = nil
|
223
|
+
@unsafe_input.push([key.to_s.dup, value.to_s.dup])
|
224
|
+
unless(key.nil? || key.empty?)
|
225
|
+
if match = @@hash_ptrn.match(key)
|
226
|
+
key = match[1]
|
227
|
+
index = match[2]
|
228
|
+
#puts key, index
|
229
|
+
end
|
230
|
+
key = key.intern
|
231
|
+
if(key == :confirm_pass)
|
232
|
+
pass = request.params["pass"]
|
233
|
+
#puts "pass:#{pass} - confirm:#{value}"
|
234
|
+
@valid_input[key] = @valid_input[:set_pass] \
|
235
|
+
= @validator.set_pass(pass, value)
|
236
|
+
else
|
237
|
+
valid = @validator.validate(key, value)
|
238
|
+
if(index)
|
239
|
+
target = (@valid_input[key] ||= {})
|
240
|
+
indices = []
|
241
|
+
index.scan(@@index_ptrn) { |idx|
|
242
|
+
indices.push idx
|
243
|
+
}
|
244
|
+
last = indices.pop
|
245
|
+
indices.each { |idx|
|
246
|
+
target = (target[idx] ||= {})
|
247
|
+
}
|
248
|
+
target.store(last, valid)
|
249
|
+
else
|
250
|
+
@valid_input[key] = valid
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
#puts "imported #{key} -> #{value} => #{@valid_input[key].inspect}"
|
255
|
+
}
|
256
|
+
@user_input_imported = true
|
257
|
+
#puts @unsafe_input.inspect
|
258
|
+
#puts @valid_input.inspect
|
259
|
+
#$stdout.flush
|
260
|
+
end
|
261
|
+
def infos
|
262
|
+
@state.infos if @state.respond_to?(:infos)
|
263
|
+
end
|
264
|
+
def info?
|
265
|
+
@state.info? if @state.respond_to?(:info?)
|
266
|
+
end
|
267
|
+
def is_crawler?
|
268
|
+
@is_crawler ||= if @request.respond_to?(:is_crawler?)
|
269
|
+
@request.is_crawler?
|
270
|
+
end
|
271
|
+
end
|
272
|
+
def language
|
273
|
+
cookie_set_or_get(:language) || default_language
|
274
|
+
end
|
275
|
+
def logged_in?
|
276
|
+
!@user.is_a?(@unknown_user_class)
|
277
|
+
end
|
278
|
+
def login
|
279
|
+
if(user = @app.login(self))
|
280
|
+
@user = user
|
281
|
+
end
|
282
|
+
end
|
283
|
+
def logout
|
284
|
+
__checkout
|
285
|
+
@user = @app.unknown_user()
|
286
|
+
@active_state = @state = self::class::DEFAULT_STATE.new(self, @user)
|
287
|
+
@state.init
|
288
|
+
@attended_states.store(@state.object_id, @state)
|
289
|
+
end
|
290
|
+
def lookandfeel
|
291
|
+
if(@lookandfeel.nil? \
|
292
|
+
|| (@lookandfeel.flavor != flavor) \
|
293
|
+
|| (@lookandfeel.language != persistent_user_input(:language)))
|
294
|
+
@lookandfeel = if self::class::LF_FACTORY
|
295
|
+
self::class::LF_FACTORY.create(self)
|
296
|
+
else
|
297
|
+
self::class::LOOKANDFEEL.new(self)
|
298
|
+
end
|
299
|
+
end
|
300
|
+
@lookandfeel
|
301
|
+
end
|
302
|
+
def flavor
|
303
|
+
@flavor ||= begin
|
304
|
+
user_input = persistent_user_input(:flavor)
|
305
|
+
user_input ||= @valid_input[:default_flavor]
|
306
|
+
lf_factory = self::class::LF_FACTORY
|
307
|
+
if(lf_factory && lf_factory.include?(user_input))
|
308
|
+
user_input
|
309
|
+
else
|
310
|
+
self::class::DEFAULT_FLAVOR
|
311
|
+
end
|
312
|
+
end
|
313
|
+
end
|
314
|
+
def http_headers
|
315
|
+
@state.http_headers
|
316
|
+
rescue DRb::DRbConnError
|
317
|
+
raise
|
318
|
+
rescue NameError, StandardError => err
|
319
|
+
puts "error in SBSM::Session#http_headers: #@request_path"
|
320
|
+
puts err.class, err.message
|
321
|
+
puts err.backtrace[0,5]
|
322
|
+
{'Content-Type' => 'text/plain'}
|
323
|
+
end
|
324
|
+
def http_protocol
|
325
|
+
@http_protocol ||= if(@request.respond_to?(:server_port) \
|
326
|
+
&& @request.server_port == 443)
|
327
|
+
'https'
|
328
|
+
else
|
329
|
+
'http'
|
330
|
+
end
|
331
|
+
end
|
332
|
+
def input_keys
|
333
|
+
@valid_input.keys
|
334
|
+
end
|
335
|
+
def navigation
|
336
|
+
@user.navigation
|
337
|
+
end
|
338
|
+
def passthru(*args)
|
339
|
+
@request.passthru(*args)
|
340
|
+
end
|
341
|
+
def persistent_user_input(key)
|
342
|
+
if(value = user_input(key))
|
343
|
+
@persistent_user_input.store(key, value)
|
344
|
+
else
|
345
|
+
@persistent_user_input[key]
|
346
|
+
end
|
347
|
+
end
|
348
|
+
def process(request)
|
349
|
+
begin
|
350
|
+
@request = request
|
351
|
+
@request_method = request.request_method
|
352
|
+
@request_path = @request.unparsed_uri
|
353
|
+
@validator.reset_errors() if @validator
|
354
|
+
import_user_input(request)
|
355
|
+
import_cookies(request)
|
356
|
+
@state = active_state.trigger(event())
|
357
|
+
#FIXME: is there a better way to distinguish returning states?
|
358
|
+
# ... we could simply refuse to init if event == :sort, but that
|
359
|
+
# would not solve the problem cleanly, I think.
|
360
|
+
unless(@state.request_path)
|
361
|
+
@state.request_path = @request_path
|
362
|
+
@state.init
|
363
|
+
end
|
364
|
+
unless @state.volatile?
|
365
|
+
@active_state = @state
|
366
|
+
@attended_states.store(@state.object_id, @state)
|
367
|
+
end
|
368
|
+
@zone = @active_state.zone
|
369
|
+
@active_state.touch
|
370
|
+
cap_max_states
|
371
|
+
rescue DRb::DRbConnError
|
372
|
+
raise
|
373
|
+
rescue StandardError => err
|
374
|
+
#@state = @state.previous
|
375
|
+
puts "error in SBSM::Session#process: #@request_path"
|
376
|
+
puts err.class, err.message
|
377
|
+
puts err.backtrace[0,5]
|
378
|
+
$stdout.flush
|
379
|
+
ensure
|
380
|
+
@user_input_imported = false
|
381
|
+
end
|
382
|
+
''
|
383
|
+
end
|
384
|
+
def reset
|
385
|
+
=begin
|
386
|
+
if(@active_thread \
|
387
|
+
&& @active_thread.alive? \
|
388
|
+
&& @active_thread != Thread.current)
|
389
|
+
begin
|
390
|
+
#@active_thread.exit
|
391
|
+
rescue StandardError
|
392
|
+
end
|
393
|
+
end
|
394
|
+
@active_thread = Thread.current
|
395
|
+
=end
|
396
|
+
if @redirected
|
397
|
+
@redirected = false
|
398
|
+
else
|
399
|
+
reset_input()
|
400
|
+
end
|
401
|
+
end
|
402
|
+
def reset_cookie
|
403
|
+
@cookie_input = {}
|
404
|
+
end
|
405
|
+
def reset_input
|
406
|
+
@valid_input = {}
|
407
|
+
@processing_errors = {}
|
408
|
+
@http_protocol = nil
|
409
|
+
@flavor = nil
|
410
|
+
@unsafe_input = []
|
411
|
+
end
|
412
|
+
def remote_addr
|
413
|
+
@remote_addr ||= if @request.respond_to?(:remote_addr)
|
414
|
+
@request.remote_addr
|
415
|
+
end
|
416
|
+
end
|
417
|
+
def remote_ip
|
418
|
+
@remote_ip ||= if(@request.respond_to?(:remote_host))
|
419
|
+
@request.remote_host
|
420
|
+
end
|
421
|
+
end
|
422
|
+
def set_cookie_input(key, val)
|
423
|
+
@cookie_input.store(key, val)
|
424
|
+
end
|
425
|
+
def server_name
|
426
|
+
@server_name ||= if @request.respond_to?(:server_name)
|
427
|
+
@request.server_name
|
428
|
+
else
|
429
|
+
self::class::SERVER_NAME
|
430
|
+
end
|
431
|
+
rescue DRb::DRbConnError
|
432
|
+
@server_name = self::class::SERVER_NAME
|
433
|
+
end
|
434
|
+
def state(event=nil)
|
435
|
+
@active_state
|
436
|
+
end
|
437
|
+
def touch
|
438
|
+
@mtime = Time.now
|
439
|
+
self
|
440
|
+
end
|
441
|
+
def to_html
|
442
|
+
@state.to_html(@@cgi)
|
443
|
+
rescue DRb::DRbConnError
|
444
|
+
raise
|
445
|
+
rescue StandardError => err
|
446
|
+
puts "error in SBSM::Session#to_html: #@request_path"
|
447
|
+
puts err.class, err.message
|
448
|
+
puts err.backtrace#[0,5]
|
449
|
+
$stdout.flush
|
450
|
+
[ err.class, err.message ].join("\n")
|
451
|
+
end
|
452
|
+
def user_agent
|
453
|
+
@user_agent ||= (@request.user_agent if @request.respond_to?(:user_agent))
|
454
|
+
end
|
455
|
+
@@input_ptrn = /([^\[]+)\[([^\]]+)\]/
|
456
|
+
def user_input(*keys)
|
457
|
+
if(keys.size == 1)
|
458
|
+
index = nil
|
459
|
+
key = keys.first.to_s
|
460
|
+
if match = @@input_ptrn.match(key)
|
461
|
+
key = match[1]
|
462
|
+
index = match[2]
|
463
|
+
end
|
464
|
+
key_sym = key.to_sym
|
465
|
+
valid = @valid_input[key_sym]
|
466
|
+
if(index && valid.respond_to?(:[]))
|
467
|
+
valid[index]
|
468
|
+
else
|
469
|
+
valid
|
470
|
+
end
|
471
|
+
else
|
472
|
+
keys.inject({}) { |inj, key|
|
473
|
+
inj.store(key, user_input(key))
|
474
|
+
inj
|
475
|
+
}
|
476
|
+
end
|
477
|
+
end
|
478
|
+
def valid_values(key)
|
479
|
+
vals = @validator.valid_values(key) unless @validator.nil?
|
480
|
+
vals || []
|
481
|
+
end
|
482
|
+
def warnings
|
483
|
+
@state.warnings if @state.respond_to?(:warnings)
|
484
|
+
end
|
485
|
+
def warning?
|
486
|
+
@state.warning? if @state.respond_to?(:warning?)
|
487
|
+
end
|
488
|
+
# CGI::SessionHandler compatibility
|
489
|
+
def restore
|
490
|
+
#puts "restore was called"
|
491
|
+
#@unix_socket = DRb.start_service('drbunix:', self)
|
492
|
+
hash = {
|
493
|
+
#:proxy => DRbObject.new(self, @unix_socket.uri)
|
494
|
+
:proxy => self,
|
495
|
+
}
|
496
|
+
hash.extend(DRbUndumped) # added for Ruby1.8 compliance
|
497
|
+
hash
|
498
|
+
end
|
499
|
+
def update
|
500
|
+
# nothing
|
501
|
+
end
|
502
|
+
def close
|
503
|
+
#@unix_socket.stop_service
|
504
|
+
# nothing
|
505
|
+
end
|
506
|
+
def delete
|
507
|
+
@app.delete_session @key
|
508
|
+
end
|
509
|
+
def zone
|
510
|
+
@valid_input[:zone] || @state.zone || self::class::DEFAULT_ZONE
|
511
|
+
end
|
512
|
+
def zones
|
513
|
+
@active_state.zones
|
514
|
+
end
|
515
|
+
def zone_navigation
|
516
|
+
@state.zone_navigation
|
517
|
+
end
|
518
|
+
def ==(other)
|
519
|
+
super
|
520
|
+
end
|
521
|
+
def <=>(other)
|
522
|
+
self.weighted_mtime <=> other.weighted_mtime
|
523
|
+
end
|
524
|
+
def [](key)
|
525
|
+
@variables[key]
|
526
|
+
end
|
527
|
+
def []=(key, val)
|
528
|
+
@variables[key] = val
|
529
|
+
end
|
530
|
+
private
|
531
|
+
def active_state
|
532
|
+
if(state_id = @valid_input[:state_id])
|
533
|
+
@attended_states[state_id]
|
534
|
+
end || @active_state
|
535
|
+
end
|
536
|
+
protected
|
537
|
+
attr_reader :mtime
|
538
|
+
def weighted_mtime
|
539
|
+
@mtime + @user.session_weight
|
540
|
+
end
|
541
|
+
end
|
542
|
+
end
|