sbsm 1.3.0 → 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
  # encoding: utf-8
3
- #
3
+ #--
4
4
  # State Based Session Management
5
5
  # Copyright (C) 2004 Hannes Wyss
6
6
  #
@@ -22,7 +22,7 @@
22
22
  # hwyss@ywesee.com
23
23
  #
24
24
  # Exception -- sbsm -- 22.10.2002 -- hwyss@ywesee.com
25
-
25
+ #++
26
26
  module SBSM
27
27
  class ProcessingError < RuntimeError
28
28
  end
data/lib/sbsm/index.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
  # encoding: utf-8
3
- #
3
+ #--
4
4
  # State Based Session Management
5
5
  # Copyright (C) 2004 Hannes Wyss
6
6
  #
@@ -22,6 +22,7 @@
22
22
  # hwyss@ywesee.com
23
23
  #
24
24
  # Index -- sbsm -- 04.03.2003 -- hwyss@ywesee.com
25
+ #++
25
26
 
26
27
  module SBSM
27
28
  class Index
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+ #--
4
+ # State Based Session Management
5
+ # Copyright (C) 2016 Niklaus Giger
6
+ #
7
+ # This library is free software; you can redistribute it and/or
8
+ # modify it under the terms of the GNU Lesser General Public
9
+ # License as published by the Free Software Foundation; either
10
+ # version 2.1 of the License, or (at your option) any later version.
11
+ #
12
+ # This library is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
+ # Lesser General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU Lesser General Public
18
+ # License along with this library; if not, write to the Free Software
19
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
+ #
21
+ # ywesee - intellectual capital connected, Winterthurerstrasse 52, CH-8006 Zürich, Switzerland
22
+ # ngiger@ywesee.com
23
+ #++
24
+
25
+ require 'chrono_logger'
26
+ require 'sbsm/version'
27
+ module SBSM
28
+ @@logger = ChronoLogger.new("/tmp/sbsm_#{VERSION}.log.%Y%m%d")
29
+ @@logger.level= :warn
30
+ def self.logger=(logger)
31
+ @@logger = logger
32
+ end
33
+ def self.logger
34
+ @@logger
35
+ end
36
+ # a simple logger, which makes it easy to compare the timing of the entries
37
+ # by the different process. Should probably later be replaced by a Rack based logger
38
+ def self.info(msg)
39
+ info = "#{File.basename(caller[0])} #{msg}"
40
+ @@logger.info(info) if @@logger
41
+ end
42
+ def self.debug(msg)
43
+ info = "#{File.basename(caller[0])} #{msg}"
44
+ @@logger.debug(info) if @@logger
45
+ end
46
+ end
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
  # encoding: utf-8
3
- #
3
+ #--
4
4
  # State Based Session Management
5
5
  # Copyright (C) 2004 Hannes Wyss
6
6
  #
@@ -22,7 +22,7 @@
22
22
  # hwyss@ywesee.com
23
23
  #
24
24
  # Lookandfeel -- sbsm -- hwyss@ywesee.com
25
-
25
+ #++
26
26
  require 'sbsm/time'
27
27
  require 'cgi'
28
28
 
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
  # encoding: utf-8
3
- #
3
+ #--
4
4
  # State Based Session Management
5
5
  # Copyright (C) 2004 Hannes Wyss
6
6
  #
@@ -22,7 +22,7 @@
22
22
  # hwyss@ywesee.com
23
23
  #
24
24
  # LookandfeelFactory -- sbsm -- hwyss@ywesee.com
25
-
25
+ #++
26
26
  require 'sbsm/lookandfeel'
27
27
 
28
28
  module SBSM
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
  # encoding: utf-8
3
- #
3
+ #--
4
4
  # State Based Session Management
5
5
  # Copyright (C) 2004 Hannes Wyss
6
6
  #
@@ -22,6 +22,7 @@
22
22
  # hwyss@ywesee.com
23
23
  #
24
24
  # LookandfeelWrapper -- sbsm -- hwyss@ywesee.com
25
+ #++
25
26
 
26
27
  require "sbsm/lookandfeel"
27
28
 
@@ -1,17 +1,18 @@
1
1
  #!/usr/bin/env ruby
2
2
  # encoding: utf-8
3
+ #--
3
4
  # Redirector -- sbsm -- 02.11.2006 -- hwyss@ywesee.com
4
-
5
+ #++
5
6
  module SBSM
6
7
  module Redirector
7
8
  def http_headers
8
- if(redirect?)
9
+ if(redirect?)
9
10
  @redirected = @state.redirected = true
10
11
  event, *args = @state.direct_event
11
12
  if(args.first.is_a? Hash)
12
13
  args = args.first
13
14
  end
14
- {
15
+ {
15
16
  "Location" => lookandfeel._event_url(event, args || {}),
16
17
  }
17
18
  else
data/lib/sbsm/session.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
  # encoding: utf-8
3
- #
3
+ #--
4
4
  # State Based Session Management
5
5
  # Copyright (C) 2004 Hannes Wyss
6
6
  #
@@ -24,19 +24,21 @@
24
24
  # SBSM::Session -- sbsm -- 27.09.2012 -- yasaka@ywesee.com
25
25
  # SBSM::Session -- sbsm -- 17.01.2012 -- mhatakeyama@ywesee.com
26
26
  # SBSM::Session -- sbsm -- 22.10.2002 -- hwyss@ywesee.com
27
+ #++
27
28
 
28
29
  require 'cgi'
29
-
30
30
  require 'sbsm/cgi'
31
31
  require 'sbsm/drb'
32
32
  require 'sbsm/state'
33
33
  require 'sbsm/lookandfeelfactory'
34
34
  require 'delegate'
35
+ require 'sbsm/trans_handler'
35
36
 
36
37
  module SBSM
37
38
  class Session < SimpleDelegator
38
- attr_reader :user, :active_thread, :app, :key, :cookie_input,
39
+ attr_reader :user, :active_thread, :key, :cookie_input,
39
40
  :unsafe_input, :valid_input, :request_path, :cgi
41
+ attr_writer :trans_handler, :app, :validator
40
42
  include DRbUndumped
41
43
  PERSISTENT_COOKIE_NAME = "sbsm-persistent-cookie"
42
44
  DEFAULT_FLAVOR = 'sbsm'
@@ -90,6 +92,7 @@ module SBSM
90
92
  touch()
91
93
  reset_input()
92
94
  reset_cookie()
95
+ raise "Must pass key and app and validator to session" unless key && app # && validator
93
96
  @app = app
94
97
  @key = key
95
98
  @validator = validator
@@ -100,6 +103,7 @@ module SBSM
100
103
  @variables = {}
101
104
  @mutex = Mutex.new
102
105
  @cgi = CGI.initialize_without_offline_prompt('html4')
106
+ SBSM.debug "session initialized #{self} key #{key} app #{app.class} #{validator.class} with @cgi #{@cgi}"
103
107
  super(app)
104
108
  end
105
109
  def age(now=Time.now)
@@ -107,8 +111,7 @@ module SBSM
107
111
  end
108
112
  def cap_max_states
109
113
  if(@attended_states.size > self::class::CAP_MAX_THRESHOLD)
110
- #puts "too many states in session! Keeping only #{self::class::MAX_STATES}"
111
- #$stdout.flush
114
+ SBSM.info "too many states in session! Keeping only #{self::class::MAX_STATES}"
112
115
  sorted = @attended_states.values.sort
113
116
  sorted[0...(-self::class::MAX_STATES)].each { |state|
114
117
  state.__checkout
@@ -152,22 +155,31 @@ module SBSM
152
155
  @cookie_input[key]
153
156
  end
154
157
  def cookie_name
155
- self::class::PERSISTENT_COOKIE_NAME
158
+ # self::class::PERSISTENT_COOKIE_NAME
159
+ nil
156
160
  end
157
161
  def default_language
158
162
  self::class::DEFAULT_LANGUAGE
159
163
  end
160
164
  def direct_event
165
+ # used when
161
166
  @state.direct_event
162
167
  end
163
- def drb_process(request)
168
+ def drb_process(app, rack_request)
164
169
  start = Time.now
170
+ @request_path ||= rack_request.path
171
+ SBSM.debug("rack_request #{rack_request.class} #{@request_path} #{rack_request.request_method} #{@cgi}")
172
+ rack_request.params.each { |key, val| @cgi.params.store(key, val) }
173
+ @trans_handler.translate_uri(rack_request)
165
174
  html = @mutex.synchronize do
166
- process(request)
175
+ process(rack_request)
167
176
  to_html
168
177
  end
169
178
  (@@stats[@request_path] ||= []).push(Time.now - start)
170
179
  html
180
+ rescue => err
181
+ SBSM.info "Error in drb_process #{err.backtrace[0..5].join("\n")}"
182
+ raise err
171
183
  end
172
184
  def error(key)
173
185
  @state.error(key) if @state.respond_to?(:error)
@@ -200,40 +212,40 @@ module SBSM
200
212
  def import_cookies(request)
201
213
  reset_cookie()
202
214
  return if request.cookies.is_a?(DRb::DRbUnknown)
203
- if(cuki = request.cookies[self::class::PERSISTENT_COOKIE_NAME])
204
- cuki.each { |cuki_str|
205
- CGI.parse(CGI.unescape(cuki_str)).each { |key, val|
206
- key = key.intern
207
- valid = @validator.validate(key, val.compact.last)
208
- @cookie_input.store(key, valid)
209
- }
215
+ if(cuki_str = request.cookies[self::class::PERSISTENT_COOKIE_NAME])
216
+ CGI.parse(CGI.unescape(cuki_str)).each { |key, val|
217
+ key = key.intern
218
+ valid = @validator.validate(key, val.compact.last)
219
+ @cookie_input.store(key, valid)
210
220
  }
211
221
  end
212
222
  end
213
223
  @@hash_ptrn = /([^\[]+)((\[[^\]]+\])+)/
214
224
  @@index_ptrn = /[^\[\]]+/
215
- def import_user_input(request)
225
+ def import_user_input(rack_req)
216
226
  # attempting to read the cgi-params more than once results in a
217
227
  # DRbConnectionRefused Exception. Therefore, do it only once...
218
228
  return if(@user_input_imported)
219
- request.params.each { |key, value|
220
- #puts "importing #{key} -> #{value}"
229
+ hash = rack_req.env.merge rack_req.params
230
+ hash.each do |key, value|
231
+ next if /^rack\./.match(key)
221
232
  index = nil
222
233
  @unsafe_input.push([key.to_s.dup, value.to_s.dup])
223
234
  unless(key.nil? || key.empty?)
224
235
  if match = @@hash_ptrn.match(key)
225
236
  key = match[1]
226
237
  index = match[2]
227
- #puts key, index
238
+ #puts key, index
228
239
  end
229
240
  key = key.intern
230
241
  if(key == :confirm_pass)
231
- pass = request.params["pass"]
232
- #puts "pass:#{pass} - confirm:#{value}"
242
+ pass = rack_req.params["pass"]
243
+ # puts "pass:#{pass} - confirm:#{value}"
233
244
  @valid_input[key] = @valid_input[:set_pass] \
234
245
  = @validator.set_pass(pass, value)
235
246
  else
236
247
  valid = @validator.validate(key, value)
248
+ # puts "Checking #{key} -> #{value} valid #{valid.inspect} index #{index.inspect}"
237
249
  if(index)
238
250
  target = (@valid_input[key] ||= {})
239
251
  indices = []
@@ -247,13 +259,15 @@ module SBSM
247
259
  target.store(last, valid)
248
260
  else
249
261
  @valid_input[key] = valid
262
+ # puts "@valid_input #{key} -> #{value} valid #{valid.inspect} index #{index.inspect}"
250
263
  "dummy" # Some statement is necessary here to avoid Date data loading error on Ruby 1.9.3
251
264
  end
252
265
  end
253
266
  end
254
267
  #puts "imported #{key} -> #{value} => #{@valid_input[key].inspect}"
255
- }
268
+ end
256
269
  @user_input_imported = true
270
+ @valid_input
257
271
  #puts @unsafe_input.inspect
258
272
  #puts @valid_input.inspect
259
273
  #$stdout.flush
@@ -277,10 +291,14 @@ module SBSM
277
291
  end
278
292
  def login
279
293
  if(user = @app.login(self))
294
+ SBSM.debug "user is #{user} #{request_path.inspect}"
280
295
  @user = user
296
+ else
297
+ SBSM.debug "login no user #{request_path.inspect}"
281
298
  end
282
299
  end
283
300
  def logout
301
+ SBSM.debug "logout #{request_path.inspect} setting @state #{self::class::DEFAULT_STATE.new(self, @user)}"
284
302
  __checkout
285
303
  @user = @app.unknown_user()
286
304
  @active_state = @state = self::class::DEFAULT_STATE.new(self, @user)
@@ -316,9 +334,7 @@ module SBSM
316
334
  rescue DRb::DRbConnError
317
335
  raise
318
336
  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]
337
+ SBSM.info "NameError, StandardError: #@request_path"
322
338
  {'Content-Type' => 'text/plain'}
323
339
  end
324
340
  def http_protocol
@@ -345,15 +361,16 @@ module SBSM
345
361
  @persistent_user_input[key]
346
362
  end
347
363
  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())
364
+ def process(rack_request)
365
+ begin
366
+ @request_method =rack_request.request_method
367
+ @request = rack_request
368
+ @request_method ||= @request.request_method
369
+ @request_path = @request.path
370
+ @validator.reset_errors() if @validator && @validator.respond_to?(:reset_errors)
371
+ import_user_input(rack_request)
372
+ import_cookies(rack_request)
373
+ @state = active_state.trigger(event())
357
374
  #FIXME: is there a better way to distinguish returning states?
358
375
  # ... we could simply refuse to init if event == :sort, but that
359
376
  # would not solve the problem cleanly, I think.
@@ -361,38 +378,22 @@ module SBSM
361
378
  @state.request_path = @request_path
362
379
  @state.init
363
380
  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
381
+ unless @state.volatile?
382
+ SBSM.debug "Changing to #{@state.class}"
383
+ @active_state = @state
384
+ @attended_states.store(@state.object_id, @state)
385
+ end
386
+ @zone = @active_state.zone
387
+ @active_state.touch
388
+ cap_max_states
371
389
  rescue DRb::DRbConnError
372
390
  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
391
  ensure
380
392
  @user_input_imported = false
381
393
  end
382
394
  ''
383
395
  end
384
396
  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
397
  if @redirected
397
398
  @redirected = false
398
399
  else
@@ -443,10 +444,7 @@ module SBSM
443
444
  rescue DRb::DRbConnError
444
445
  raise
445
446
  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
447
+ SBSM.info "StandardError: #@request_path"
450
448
  [ err.class, err.message ].join("\n")
451
449
  end
452
450
  def user_agent
@@ -487,13 +485,9 @@ module SBSM
487
485
  end
488
486
  # CGI::SessionHandler compatibility
489
487
  def restore
490
- #puts "restore was called"
491
- #@unix_socket = DRb.start_service('drbunix:', self)
492
488
  hash = {
493
- #:proxy => DRbObject.new(self, @unix_socket.uri)
494
- :proxy => self,
489
+ :proxy => self,
495
490
  }
496
- hash.extend(DRbUndumped) # added for Ruby1.8 compliance
497
491
  hash
498
492
  end
499
493
  def update
data/lib/sbsm/state.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
  # encoding: utf-8
3
- #
3
+ #--
4
4
  # State Based Session Management
5
5
  # Copyright (C) 2004 Hannes Wyss
6
6
  #
@@ -23,6 +23,8 @@
23
23
  #
24
24
  # SBSM::State -- sbsm -- 15.05.2012 -- yasaka@ywesee.com
25
25
  # SBSM::State -- sbsm -- 22.10.2002 -- hwyss@ywesee.com
26
+ #++
27
+ require 'sbsm/logger'
26
28
 
27
29
  module SBSM
28
30
  class ProcessingError < RuntimeError
@@ -121,29 +123,19 @@ module SBSM
121
123
  @errors.store(key, error)
122
124
  end
123
125
  end
124
- if RUBY_VERSION >= '1.9'
125
- def extend(mod)
126
- if(mod.constants.include?(:VIRAL))
127
- @viral_modules.push(mod)
128
- end
129
- if(mod.constants.include?(:EVENT_MAP))
130
- @events.update(mod::EVENT_MAP)
131
- end
132
- super
126
+ def extend(mod)
127
+ if(mod.constants.include?(:VIRAL))
128
+ @viral_modules.push(mod)
133
129
  end
134
- else
135
- def extend(mod)
136
- if(mod.constants.include?('VIRAL'))
137
- @viral_modules.push(mod)
138
- end
139
- if(mod.constants.include?('EVENT_MAP'))
140
- @events.update(mod::EVENT_MAP)
141
- end
142
- super
130
+ if(mod.constants.include?(:EVENT_MAP))
131
+ @events.update(mod::EVENT_MAP)
143
132
  end
133
+ super
144
134
  end
145
135
  def http_headers
146
- @http_headers || view.http_headers
136
+ return @http_headers if @http_headers
137
+ name = view
138
+ name ? view.http_headers : {}
147
139
  end
148
140
  def info?
149
141
  !@infos.empty?
@@ -178,7 +170,8 @@ module SBSM
178
170
  @mtime = Time.now
179
171
  end
180
172
  def to_html(context)
181
- view.to_html(context)
173
+ name = view
174
+ name ? name.to_html(context) : ''
182
175
  end
183
176
  def trigger(event)
184
177
  if(@redirected)
@@ -197,6 +190,7 @@ module SBSM
197
190
  if(state.respond_to?(:previous=))
198
191
  state.previous = self
199
192
  end
193
+ # puts "state.rb #{__LINE__} state #{state.inspect}"
200
194
  state
201
195
  end
202
196
  def _trigger(event)
@@ -236,6 +230,7 @@ module SBSM
236
230
  end
237
231
  def view
238
232
  klass = @default_view
233
+ return nil unless @default_view
239
234
  if(klass.is_a?(Hash))
240
235
  klass = klass.fetch(@session.user.class) {
241
236
  klass[:default]