sbsm 1.0.0
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/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
|