sbsm 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/COPYING +515 -0
  2. data/History.txt +5 -0
  3. data/Manifest.txt +49 -0
  4. data/README.txt +41 -0
  5. data/Rakefile +28 -0
  6. data/data/_flavored_uri.grammar +24 -0
  7. data/data/_uri.grammar +22 -0
  8. data/data/_zone_uri.grammar +24 -0
  9. data/data/flavored_uri.grammar +24 -0
  10. data/data/uri.grammar +22 -0
  11. data/data/zone_uri.grammar +24 -0
  12. data/install.rb +1098 -0
  13. data/lib/cgi/drbsession.rb +37 -0
  14. data/lib/sbsm/cgi.rb +79 -0
  15. data/lib/sbsm/drb.rb +19 -0
  16. data/lib/sbsm/drbserver.rb +162 -0
  17. data/lib/sbsm/exception.rb +28 -0
  18. data/lib/sbsm/flavored_uri_parser.rb +47 -0
  19. data/lib/sbsm/index.rb +66 -0
  20. data/lib/sbsm/lookandfeel.rb +176 -0
  21. data/lib/sbsm/lookandfeelfactory.rb +50 -0
  22. data/lib/sbsm/lookandfeelwrapper.rb +109 -0
  23. data/lib/sbsm/redefine_19_cookie.rb +4 -0
  24. data/lib/sbsm/redirector.rb +37 -0
  25. data/lib/sbsm/request.rb +162 -0
  26. data/lib/sbsm/session.rb +542 -0
  27. data/lib/sbsm/state.rb +301 -0
  28. data/lib/sbsm/time.rb +29 -0
  29. data/lib/sbsm/trans_handler.rb +119 -0
  30. data/lib/sbsm/turing.rb +25 -0
  31. data/lib/sbsm/uri_parser.rb +45 -0
  32. data/lib/sbsm/user.rb +47 -0
  33. data/lib/sbsm/validator.rb +256 -0
  34. data/lib/sbsm/viralstate.rb +47 -0
  35. data/lib/sbsm/zone_uri_parser.rb +48 -0
  36. data/test/data/dos_file.txt +2 -0
  37. data/test/data/lnf_file.txt +2 -0
  38. data/test/data/mac_file.txt +1 -0
  39. data/test/stub/cgi.rb +35 -0
  40. data/test/suite.rb +29 -0
  41. data/test/test_drbserver.rb +83 -0
  42. data/test/test_index.rb +90 -0
  43. data/test/test_lookandfeel.rb +230 -0
  44. data/test/test_session.rb +372 -0
  45. data/test/test_state.rb +176 -0
  46. data/test/test_trans_handler.rb +447 -0
  47. data/test/test_user.rb +44 -0
  48. data/test/test_validator.rb +126 -0
  49. data/usage-en.txt +112 -0
  50. metadata +142 -0
@@ -0,0 +1,37 @@
1
+ #
2
+ # DRbSession - CGI::Session session database manager using DRb.
3
+ # Copyright (C) 2001 by Tietew. All Rights Reserved.
4
+ #
5
+ require 'drb/drb'
6
+
7
+ class CGI
8
+ class Session
9
+ class DRbSession
10
+ def initialize(session, option={})
11
+ unless uri = option['drbsession_uri']
12
+ raise ArgumentError, "drbsession_uri not specified"
13
+ end
14
+
15
+ unless DRb.thread
16
+ DRb.start_service
17
+ end
18
+
19
+ holder = DRbObject.new(nil, uri)
20
+ @obj = holder[session.session_id]
21
+ end
22
+
23
+ def restore
24
+ @obj.restore
25
+ end
26
+ def update
27
+ @obj.update
28
+ end
29
+ def close
30
+ @obj.close
31
+ end
32
+ def delete
33
+ @obj.delete
34
+ end
35
+ end
36
+ end
37
+ end
data/lib/sbsm/cgi.rb ADDED
@@ -0,0 +1,79 @@
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
+ # CGI redefinitions
24
+
25
+ require 'cgi'
26
+ require 'drb/drb'
27
+
28
+ class CGI
29
+ module TagMaker
30
+ def nOE_element_def(element, append = nil)
31
+ s = <<-END
32
+ "<#{element.upcase}" + attributes.collect{|name, value|
33
+ next unless value
34
+ " " + name.to_s +
35
+ if true == value
36
+ ""
37
+ else
38
+ '="' + CGI::escapeHTML(value) + '"'
39
+ end
40
+ }.to_s + ">"
41
+ END
42
+ s.sub!(/\Z/, " +") << append if append
43
+ s
44
+ end
45
+ end
46
+ class Session
47
+ attr_reader :output_cookies
48
+ end
49
+ def CGI::pretty(string, shift = " ")
50
+ lines = string.gsub(/(?!\A)<(?!\/(pre|textarea))(?:.)*?>/ni, "\n\\0").gsub(/<(?!(pre|textarea))(?:.)*?>(?!\n)/i, "\\0\n")
51
+ end_pos = 0
52
+ preformatted = []
53
+ while (end_pos = lines.index(/<\/pre\s*>/i, end_pos)) \
54
+ && (start_pos = lines.rindex(/<pre(\s+[^>]+)?>/i, end_pos))
55
+ start_pos += $~[0].length
56
+ preformatted.push(lines[ start_pos ... end_pos ])
57
+ lines[ start_pos ... end_pos ] = ''
58
+ end_pos = start_pos + 6
59
+ end
60
+ end_pos = 0
61
+ while end_pos = lines.index(/^<\/(\w+)/, end_pos)
62
+ element = $1.dup
63
+ start_pos = lines.rindex(/^\s*<#{element}/i, end_pos)
64
+ lines[start_pos ... end_pos] = "__" + lines[start_pos ... end_pos].gsub(/\n(?!\z)/, "\n" + shift) + "__"
65
+ end
66
+ pretty = lines.gsub(/^((?:#{Regexp::quote(shift)})*)__(?=<\/?\w)/, '\1')
67
+ pos = 0
68
+ preformatted.each { |pre|
69
+ if(pos = pretty.index(/<\/pre\s*>/i, pos))
70
+ pretty[pos,0] = pre
71
+ pos += pre.length + 6
72
+ end
73
+ }
74
+ pretty
75
+ end
76
+ def CGI::escapeHTML(string)
77
+ string.to_s.gsub(/&(?![^;]{2,6};)/, '&amp;').gsub(/\"/, '&quot;').gsub(/>/, '&gt;').gsub(/</, '&lt;')
78
+ end
79
+ end
data/lib/sbsm/drb.rb ADDED
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env ruby
2
+ # DRb::DRbObject -- fix bug in ruby -- 23.09.2005 -- hwyss@ywesee.com
3
+
4
+ require 'drb'
5
+
6
+ module DRb
7
+ class DRbObject
8
+ def respond_to?(msg_id)
9
+ case msg_id
10
+ when :_dump
11
+ true
12
+ when :marshal_dump
13
+ false
14
+ else
15
+ method_missing(:respond_to?, msg_id)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,162 @@
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
+ # DrbServer -- sbsm -- hwyss@ywesee.com
24
+
25
+ require 'delegate'
26
+ require 'sbsm/drb'
27
+ require 'sbsm/session'
28
+ require 'sbsm/user'
29
+ require 'thread'
30
+ require 'digest/md5'
31
+
32
+ module SBSM
33
+ class DRbServer < SimpleDelegator
34
+ include DRbUndumped
35
+ CLEANING_INTERVAL = 30
36
+ CAP_MAX_THRESHOLD = 120
37
+ ENABLE_ADMIN = false
38
+ MAX_SESSIONS = 100
39
+ RUN_CLEANER = true
40
+ SESSION = Session
41
+ UNKNOWN_USER = UnknownUser
42
+ VALIDATOR = nil
43
+ attr_reader :cleaner, :updater
44
+ def initialize(persistence_layer=nil)
45
+ @sessions = {}
46
+ @mutex = Mutex.new
47
+ @cleaner = run_cleaner if(self.class.const_get(:RUN_CLEANER))
48
+ @admin_threads = ThreadGroup.new
49
+ @async = ThreadGroup.new
50
+ @system = persistence_layer
51
+ super(persistence_layer)
52
+ end
53
+ def _admin(src, result, priority=0)
54
+ raise "admin interface disabled" unless(self::class::ENABLE_ADMIN)
55
+ t = Thread.new {
56
+ Thread.current.abort_on_exception = false
57
+ result << begin
58
+ response = begin
59
+ instance_eval(src)
60
+ rescue NameError => e
61
+ e
62
+ end
63
+ str = response.to_s
64
+ if(str.length > 200)
65
+ response.class
66
+ else
67
+ str
68
+ end
69
+ rescue StandardError => e
70
+ e.message
71
+ end.to_s
72
+ }
73
+ t[:source] = src
74
+ t.priority = priority
75
+ @admin_threads.add(t)
76
+ t
77
+ end
78
+ def async(&block)
79
+ @async.add(Thread.new(&block))
80
+ end
81
+ def cap_max_sessions(now = Time.now)
82
+ if(@sessions.size > self::class::CAP_MAX_THRESHOLD)
83
+ puts "too many sessions! Keeping only #{self::class::MAX_SESSIONS}"
84
+ sess = nil
85
+ sorted = @sessions.values.sort
86
+ sorted[0...(-self::class::MAX_SESSIONS)].each { |sess|
87
+ sess.__checkout
88
+ @sessions.delete(sess.key)
89
+ }
90
+ if(sess)
91
+ age = sess.age(now)
92
+ puts sprintf("deleted all sessions that had not been accessed for more than %im %is", age / 60, age % 60)
93
+ end
94
+ end
95
+ end
96
+ def clean
97
+ now = Time.now
98
+ @sessions.delete_if { |key, s|
99
+ begin
100
+ if s.respond_to?(:expired?)
101
+ if s.expired?(now)
102
+ s.__checkout
103
+ true
104
+ else
105
+ s.cap_max_states
106
+ false
107
+ end
108
+ else
109
+ true
110
+ end
111
+ rescue
112
+ true
113
+ end
114
+ }
115
+ #cap_max_sessions(now)
116
+ end
117
+ def clear
118
+ @sessions.each_value { |sess| sess.__checkout }
119
+ @sessions.clear
120
+ end
121
+ def delete_session(key)
122
+ if(sess = @sessions.delete(key))
123
+ sess.__checkout
124
+ end
125
+ end
126
+ def reset
127
+ @mutex.synchronize {
128
+ @sessions.clear
129
+ }
130
+ end
131
+ def run_cleaner
132
+ # puts "running cleaner thread"
133
+ Thread.new {
134
+ Thread.current.abort_on_exception = true
135
+ #Thread.current.priority = 1
136
+ loop {
137
+ sleep self::class::CLEANING_INTERVAL
138
+ @mutex.synchronize {
139
+ clean()
140
+ }
141
+ }
142
+ }
143
+ end
144
+ def unknown_user
145
+ self::class::UNKNOWN_USER.new
146
+ end
147
+ def [](key)
148
+ @mutex.synchronize {
149
+ unless((s = @sessions[key]) && !s.expired?)
150
+ args = [key, self]
151
+ if(klass = self::class::VALIDATOR)
152
+ args.push(klass.new)
153
+ end
154
+ s = @sessions[key] = self::class::SESSION.new(*args.compact)
155
+ end
156
+ s.reset()
157
+ s.touch()
158
+ s
159
+ }
160
+ end
161
+ end
162
+ end
@@ -0,0 +1,28 @@
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
+ # Exception -- sbsm -- 22.10.2002 -- hwyss@ywesee.com
24
+
25
+ module SBSM
26
+ class ProcessingError < RuntimeError
27
+ end
28
+ end
@@ -0,0 +1,47 @@
1
+ require 'rockit/rockit'
2
+ module SBSM
3
+ # Parser for Uri
4
+ # created by Rockit version 0.3.8 on Wed Jul 19 18:22:18 CEST 2006
5
+ # Rockit is copyright (c) 2001 Robert Feldt, feldt@ce.chalmers.se
6
+ # and licensed under GPL
7
+ # but this parser is under LGPL
8
+ tokens = [
9
+ t1 = EofToken.new("EOF",/^(�~~��~^^~2220240369)/),
10
+ t2 = Token.new("SLASH",/^(\/)/),
11
+ t3 = Token.new("OTHER",/^([^\/]+)/),
12
+ t4 = Token.new("LANG",/^([a-z]{2})/)
13
+ ]
14
+ productions = [
15
+ p1 = Production.new("Uri'".intern,[:Uri],SyntaxTreeBuilder.new("Uri'",["uri"],[])),
16
+ p2 = Production.new(:Uri,[t2, t4, t2, t3, t2, t3, t2, :Variables],SyntaxTreeBuilder.new("Uri",["_", "language", "_", "flavor", "_", "event", "_", "variables"],[])),
17
+ p3 = Production.new(:Uri,[t2, t4, t2, t3, t2, t3, t2],SyntaxTreeBuilder.new("Uri",["_", "language", "_", "flavor", "_", "event"],[])),
18
+ p4 = Production.new(:Uri,[t2, t4, t2, t3, t2, t3],SyntaxTreeBuilder.new("Uri",["_", "language", "_", "flavor", "_", "event"],[nil])),
19
+ p5 = Production.new(:Uri,[t2, t4, t2, t3, t2],SyntaxTreeBuilder.new("Uri",["_", "language", "_", "flavor"],[])),
20
+ p6 = Production.new(:Uri,[t2, t4, t2, t3],SyntaxTreeBuilder.new("Uri",["_", "language", "_", "flavor"],[nil])),
21
+ p7 = Production.new(:Uri,[t2, t4, t2],SyntaxTreeBuilder.new("Uri",["_", "language"],[])),
22
+ p8 = Production.new(:Uri,[t2, t4],SyntaxTreeBuilder.new("Uri",["_", "language"],[nil])),
23
+ p9 = Production.new(:Uri,[t2],SyntaxTreeBuilder.new("Uri",["_"],[])),
24
+ p10 = Production.new(:Variables,[:Plus404231304, t2],LiftingSyntaxTreeBuilder.new(["pair"],[])),
25
+ p11 = Production.new(:Variables,[:Plus404231304],LiftingSyntaxTreeBuilder.new(["pair"],[nil])),
26
+ p12 = Production.new(:Plus404231304,[:Plus404231304, :Pair],ArrayNodeBuilder.new([1],0,nil,nil,[],true)),
27
+ p13 = Production.new(:Plus404231304,[:Pair],ArrayNodeBuilder.new([0],nil,nil,nil,[],true)),
28
+ p14 = Production.new(:Pair,[t3, t2, t3, t2],SyntaxTreeBuilder.new("Pair",["key", "_", "value"],[])),
29
+ p15 = Production.new(:Pair,[t3, t2, t3],SyntaxTreeBuilder.new("Pair",["key", "_", "value"],[nil])),
30
+ p16 = Production.new(:Pair,[t3, t2, t2],SyntaxTreeBuilder.new("Pair",["key"],[])),
31
+ p17 = Production.new(:Pair,[t3],SyntaxTreeBuilder.new("Pair",["key"],[]))
32
+ ]
33
+ relations = [
34
+
35
+ ]
36
+ priorities = ProductionPriorities.new(relations)
37
+ action_table = [[9, 2], [2, 1], [13, 8, 32, 1], [17, 2, 28, 1], [21, 4, 24, 1], [25, 2, 20, 1], [29, 4, 16, 1], [33, 2, 12, 1], [45, 4, 8, 1], [4, 1], [48, 7], [53, 2, 64, 7], [61, 2, 45, 4, 40, 1], [65, 2, 69, 4], [44, 7], [36, 1], [60, 7], [73, 2, 56, 7], [52, 7]]
38
+ goto_hash = {0 => {1 => 1}, 12 => {4 => 14}, 8 => {2 => 9, 3 => 12, 4 => 10}}
39
+ @@parse_table404014956 = ParseTable.new(productions,tokens,priorities,action_table,goto_hash,2,[
40
+ :REDUCE,
41
+ :SHIFT,
42
+ :ACCEPT
43
+ ])
44
+ def SBSM._flavored_uri_parser
45
+ GeneralizedLrParser.new(@@parse_table404014956)
46
+ end
47
+ end
data/lib/sbsm/index.rb ADDED
@@ -0,0 +1,66 @@
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
+ # Index -- sbsm -- 04.03.2003 -- hwyss@ywesee.com
24
+
25
+ module SBSM
26
+ VERSION = '1.0.0'
27
+ class Index
28
+ def initialize
29
+ @values = []
30
+ @children = []
31
+ end
32
+ def delete(key, value)
33
+ if (key.size == 0)
34
+ @values.delete(value)
35
+ elsif (child = @children.at(key[0]))
36
+ child.delete(key[1..-1], value)
37
+ end
38
+ end
39
+ def fetch(key)
40
+ if(key.size == 1)
41
+ @values + @children[key[0]].to_a
42
+ elsif(key.size > 1 && @children.at(key[0]))
43
+ @children.at(key[0])[key[1..-1]]
44
+ else
45
+ []
46
+ end
47
+ end
48
+ def replace(oldkey, newkey, value)
49
+ delete(oldkey, value)
50
+ store(newkey, value)
51
+ end
52
+ def store(key, *values)
53
+ if(key.size == 0)
54
+ @values += values
55
+ else
56
+ @children[key[0]] ||= self.class.new
57
+ @children.at(key[0]).store(key[1..-1], *values)
58
+ end
59
+ end
60
+ def to_a
61
+ @values + @children.inject([]) { |inj, child| inj += child.to_a.compact }
62
+ end
63
+ alias :[] :fetch
64
+ alias :[]= :store
65
+ end
66
+ end