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.
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,25 @@
1
+ #!/usr/bin/env ruby
2
+ # Turing -- SBSM -- 15.05.2009 -- hwyss@ywesee.com
3
+ # Use a Hash instead of a PStore to manage Captchas
4
+
5
+ require 'turing'
6
+ require 'thread'
7
+
8
+ module SBSM
9
+ class PStore < Hash
10
+ def initialize *args
11
+ super
12
+ @mutex = Mutex.new
13
+ end
14
+ def transaction &block
15
+ @mutex.synchronize &block
16
+ end
17
+ end
18
+ end
19
+ class Turing::Challenge
20
+ alias :__orig_initialize__ :initialize
21
+ def initialize *args
22
+ __orig_initialize__ *args
23
+ @store = SBSM::PStore.new
24
+ end
25
+ end
@@ -0,0 +1,45 @@
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:17 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",/^(�~~��~^^~3499569544)/),
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, :Variables],SyntaxTreeBuilder.new("Uri",["_", "language", "_", "event", "_", "variables"],[])),
17
+ p3 = Production.new(:Uri,[t2, t4, t2, t3, t2],SyntaxTreeBuilder.new("Uri",["_", "language", "_", "event"],[])),
18
+ p4 = Production.new(:Uri,[t2, t4, t2, t3],SyntaxTreeBuilder.new("Uri",["_", "language", "_", "event"],[nil])),
19
+ p5 = Production.new(:Uri,[t2, t4, t2],SyntaxTreeBuilder.new("Uri",["_", "language"],[])),
20
+ p6 = Production.new(:Uri,[t2, t4],SyntaxTreeBuilder.new("Uri",["_", "language"],[nil])),
21
+ p7 = Production.new(:Uri,[t2],SyntaxTreeBuilder.new("Uri",["_"],[])),
22
+ p8 = Production.new(:Variables,[:Plus404380716, t2],LiftingSyntaxTreeBuilder.new(["pair"],[])),
23
+ p9 = Production.new(:Variables,[:Plus404380716],LiftingSyntaxTreeBuilder.new(["pair"],[nil])),
24
+ p10 = Production.new(:Plus404380716,[:Plus404380716, :Pair],ArrayNodeBuilder.new([1],0,nil,nil,[],true)),
25
+ p11 = Production.new(:Plus404380716,[:Pair],ArrayNodeBuilder.new([0],nil,nil,nil,[],true)),
26
+ p12 = Production.new(:Pair,[t3, t2, t3, t2],SyntaxTreeBuilder.new("Pair",["key", "_", "value"],[])),
27
+ p13 = Production.new(:Pair,[t3, t2, t3],SyntaxTreeBuilder.new("Pair",["key", "_", "value"],[nil])),
28
+ p14 = Production.new(:Pair,[t3, t2, t2],SyntaxTreeBuilder.new("Pair",["key"],[])),
29
+ p15 = Production.new(:Pair,[t3],SyntaxTreeBuilder.new("Pair",["key"],[]))
30
+ ]
31
+ relations = [
32
+
33
+ ]
34
+ priorities = ProductionPriorities.new(relations)
35
+ action_table = [[9, 2], [2, 1], [13, 8, 24, 1], [17, 2, 20, 1], [21, 4, 16, 1], [25, 2, 12, 1], [41, 4, 8, 1], [49, 2, 41, 4, 32, 1], [4, 1], [40, 7], [53, 2, 56, 7], [36, 7], [28, 1], [57, 2, 61, 4], [52, 7], [65, 2, 48, 7], [44, 7]]
36
+ goto_hash = {0 => {1 => 1}, 6 => {2 => 8, 3 => 7, 4 => 9}, 7 => {4 => 11}}
37
+ @@parse_table404243016 = ParseTable.new(productions,tokens,priorities,action_table,goto_hash,2,[
38
+ :REDUCE,
39
+ :SHIFT,
40
+ :ACCEPT
41
+ ])
42
+ def SBSM._uri_parser
43
+ GeneralizedLrParser.new(@@parse_table404243016)
44
+ end
45
+ end
data/lib/sbsm/user.rb ADDED
@@ -0,0 +1,47 @@
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
+ # User -- sbsm -- 20.11.2002 -- hwyss@ywesee.com
24
+
25
+ module SBSM
26
+ class User
27
+ HOME = nil
28
+ NAVIGATION = []
29
+ SESSION_WEIGHT = 1
30
+ SESSION_WEIGHT_FACTOR = 60 * 15 # 15 Minutes
31
+ def home
32
+ self::class::HOME
33
+ end
34
+ def navigation
35
+ self::class::NAVIGATION.dup
36
+ end
37
+ def pass; end
38
+ def session_weight
39
+ self::class::SESSION_WEIGHT * SESSION_WEIGHT_FACTOR
40
+ end
41
+ end
42
+ class UnknownUser < User
43
+ end
44
+ class KnownUser < User
45
+ SESSION_WEIGHT = 2
46
+ end
47
+ end
@@ -0,0 +1,256 @@
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
+ # Validator -- sbsm -- 15.11.2002 -- hwyss@ywesee.com
24
+
25
+ require 'digest/md5'
26
+ require 'rmail'
27
+ require 'date'
28
+ require 'drb/drb'
29
+ require 'uri'
30
+ require 'stringio'
31
+ require 'hpricot'
32
+
33
+ module SBSM
34
+ class InvalidDataError < RuntimeError
35
+ attr_reader :key, :value
36
+ alias :data :value
37
+ def initialize(msg, key, value)
38
+ super(msg.to_s)
39
+ @key = key
40
+ @value = value
41
+ end
42
+ end
43
+ class Validator
44
+ BOOLEAN = []
45
+ DATES = []
46
+ ENUMS = {}
47
+ EVENTS = []
48
+ FILES = []
49
+ HTML = []
50
+ NUMERIC = []
51
+ PATTERNS = {}
52
+ STRINGS = []
53
+ URIS = []
54
+ ALLOWED_TAGS = %{a b br div font h1 h2 h3 i img li ol p pre span strong u ul}
55
+ def initialize
56
+ reset_errors()
57
+ @boolean = self::class::BOOLEAN.dup
58
+ @dates = self::class::DATES.dup
59
+ @enums = self::class::ENUMS.dup
60
+ @events = self::class::EVENTS.dup
61
+ @files = self::class::FILES.dup
62
+ @html = self::class::HTML.dup
63
+ @numeric = self::class::NUMERIC.dup
64
+ @patterns = self::class::PATTERNS.dup
65
+ @strings = self::class::STRINGS.dup
66
+ @uris = self::class::URIS.dup
67
+ end
68
+ def error?
69
+ !@errors.empty?
70
+ end
71
+ def reset_errors
72
+ @errors = {}
73
+ end
74
+ def set_pass(value1, value2)
75
+ valid1 = pass(value1.to_s)
76
+ valid2 = pass(value2.to_s)
77
+ if(value1.to_s.empty?)
78
+ SBSM::InvalidDataError.new(:e_empty_pass, :pass, '')
79
+ elsif(valid1 != valid2)
80
+ SBSM::InvalidDataError.new(:e_non_matching_pass, :pass, '')
81
+ else
82
+ valid1
83
+ end
84
+ end
85
+ def valid_values(key)
86
+ key = key.intern if key.is_a? String
87
+ @enums.fetch(key) {
88
+ if(@boolean.include?(key))
89
+ ['false', 'true']
90
+ end
91
+ }
92
+ end
93
+ def validate(key, value)
94
+ value = value.pop if value.is_a? Array
95
+ return nil if value.nil?
96
+ if value.is_a?(StringIO)
97
+ if(@files.include?(key))
98
+ return validate_file(key, value)
99
+ else
100
+ begin
101
+ value = value.read
102
+ rescue StandardError => e
103
+ p e
104
+ end
105
+ end
106
+ elsif(value.is_a? DRb::DRbObject)
107
+ value = value[0]
108
+ if(@files.include?(key))
109
+ return validate_file(key, value)
110
+ else
111
+ begin
112
+ value = value.read
113
+ rescue StandardError => e
114
+ #p e
115
+ end
116
+ end
117
+ end
118
+ perform_validation(key, value)
119
+ end
120
+ def perform_validation(key, value)
121
+ value = value.to_s.strip
122
+ begin
123
+ if(key==:event)
124
+ symbol = value.to_sym
125
+ symbol if @events.include?(symbol)
126
+ elsif(@boolean.include?(key))
127
+ validate_boolean(key, value)
128
+ elsif(@dates.include?(key))
129
+ validate_date(key, value)
130
+ elsif(@enums.has_key?(key))
131
+ value if @enums[key].include?(value)
132
+ elsif(@html.include?(key))
133
+ validate_html(value)
134
+ elsif(@patterns.include?(key))
135
+ validate_pattern(key, value)
136
+ elsif(@numeric.include?(key))
137
+ validate_numeric(key, value)
138
+ elsif(@uris.include?(key))
139
+ validate_uri(key, value)
140
+ elsif(@strings.include?(key))
141
+ validate_string(value)
142
+ elsif(@files.include?(key))
143
+ StringIO.new(value)
144
+ elsif(self.respond_to?(key, true))
145
+ self.send(key, value)
146
+ end
147
+ rescue InvalidDataError => e
148
+ @errors.store(e.key, e)
149
+ end
150
+ end
151
+ private
152
+ def email(value)
153
+ return if(value.empty?)
154
+ parsed = RMail::Address.parse(value).first
155
+ if(parsed.nil?)
156
+ raise InvalidDataError.new(:e_invalid_email_address, :email, value)
157
+ elsif(parsed.domain)
158
+ parsed.address
159
+ else
160
+ raise InvalidDataError.new(:e_domainless_email_address, :email, value)
161
+ end
162
+ end
163
+ def filename(value)
164
+ if(value == File.basename(value))
165
+ value
166
+ end
167
+ end
168
+ def flavor(value)
169
+ validate_string(value)
170
+ end
171
+ alias :default_flavor :flavor
172
+ def language(value)
173
+ validate_string(value)
174
+ end
175
+ def pass(value)
176
+ unless(value.empty?)
177
+ Digest::MD5::hexdigest(value)
178
+ end
179
+ end
180
+ alias :confirm_pass :pass
181
+ @@state_id_ptrn = /-?\d+/
182
+ def state_id(value)
183
+ if(match = @@state_id_ptrn.match(value))
184
+ match[0].to_i
185
+ else
186
+ nil
187
+ end
188
+ end
189
+ def validate_boolean(key, value)
190
+ case value.to_s.downcase
191
+ when 'true', '1', 'y', 'j'
192
+ true
193
+ when 'false', '0', 'n'
194
+ false
195
+ else
196
+ raise InvalidDataError.new(:e_invalid_boolean, key, value)
197
+ end
198
+ end
199
+ def validate_date(key, value)
200
+ return nil if (value.empty?)
201
+ begin
202
+ Date.parse(value.tr('.', '-'))
203
+ rescue ArgumentError
204
+ raise InvalidDataError.new(:e_invalid_date, key, value)
205
+ end
206
+ end
207
+ def validate_file(key, value)
208
+ return nil if value.original_filename.empty?
209
+ value
210
+ end
211
+ def validate_html(value)
212
+ _validate_html(value)
213
+ end
214
+ @@xml_ptrn = /<\?xml[^>]+>/
215
+ def _validate_html(value, valid=self.class.const_get(:ALLOWED_TAGS))
216
+ doc = Hpricot(value.gsub(@@xml_ptrn, ''), :fixup_tags => true)
217
+ (doc/"*").each { |element|
218
+ unless(element.is_a?(Hpricot::Text) \
219
+ || (element.respond_to?(:name) \
220
+ && valid.include?(element.name.downcase)))
221
+ element.swap _validate_html(element.inner_html.to_s)
222
+ end
223
+ }
224
+ valid = doc.to_html
225
+ valid.force_encoding 'UTF-8' if valid.respond_to?(:force_encoding)
226
+ valid
227
+ end
228
+ @@numeric_ptrn = /\d+(\.\d{1,2})?/
229
+ def validate_numeric(key, value)
230
+ return if(value.empty?)
231
+ if(match = @@numeric_ptrn.match(value))
232
+ match[0]
233
+ else
234
+ raise InvalidDataError.new("e_invalid_#{key}", key, value)
235
+ end
236
+ end
237
+ def validate_pattern(key, value)
238
+ pattern = @patterns[key]
239
+ if(match = pattern.match(value))
240
+ match[0]
241
+ end
242
+ end
243
+ def validate_string(value)
244
+ _validate_html(value, [])
245
+ end
246
+ def validate_uri(key, value)
247
+ uri = URI.parse(value)
248
+ if(uri.scheme.nil?)
249
+ uri = URI.parse('http://' << value)
250
+ end
251
+ uri
252
+ rescue
253
+ raise InvalidDataError.new(:e_invalid_uri, key, value)
254
+ end
255
+ end
256
+ end
@@ -0,0 +1,47 @@
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
+ # ViralState -- sbsm -- 16.04.2004 -- hwyss@ywesee.com
24
+
25
+ module SBSM
26
+ module ViralState
27
+ VIRAL = true
28
+ def infect(newstate)
29
+ @viral_modules.uniq.each { |mod|
30
+ newstate.extend(mod) unless newstate.is_a?(mod)
31
+ }
32
+ newstate
33
+ end
34
+ def trigger(event)
35
+ newstate = super
36
+ if(event==:logout)
37
+ @session.logout
38
+ else
39
+ infect(newstate)
40
+ end
41
+ newstate
42
+ rescue DRb::DRbError, RangeError
43
+ @session.logout
44
+ home
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,48 @@
1
+ # encoding: utf-8
2
+ require 'rockit/rockit'
3
+ module SBSM
4
+ # Parser for Uri
5
+ # created by Rockit version 0.3.8 on Wed Jul 19 18:24:42 CEST 2006
6
+ # Rockit is copyright (c) 2001 Robert Feldt, feldt@ce.chalmers.se
7
+ # and licensed under GPL
8
+ # but this parser is under LGPL
9
+ tokens = [
10
+ t1 = EofToken.new("EOF",/^(¤~~¤¤~^^~3493746103)/),
11
+ t2 = Token.new("SLASH",/^(\/)/),
12
+ t3 = Token.new("OTHER",/^([^\/]+)/),
13
+ t4 = Token.new("LANG",/^([a-z]{2})/)
14
+ ]
15
+ productions = [
16
+ p1 = Production.new("Uri'".intern,[:Uri],SyntaxTreeBuilder.new("Uri'",["uri"],[])),
17
+ p2 = Production.new(:Uri,[t2, t4, t2, t3, t2, t3, t2, :Variables],SyntaxTreeBuilder.new("Uri",["_", "language", "_", "zone", "_", "event", "_", "variables"],[])),
18
+ p3 = Production.new(:Uri,[t2, t4, t2, t3, t2, t3, t2],SyntaxTreeBuilder.new("Uri",["_", "language", "_", "zone", "_", "event"],[])),
19
+ p4 = Production.new(:Uri,[t2, t4, t2, t3, t2, t3],SyntaxTreeBuilder.new("Uri",["_", "language", "_", "zone", "_", "event"],[nil])),
20
+ p5 = Production.new(:Uri,[t2, t4, t2, t3, t2],SyntaxTreeBuilder.new("Uri",["_", "language", "_", "zone"],[])),
21
+ p6 = Production.new(:Uri,[t2, t4, t2, t3],SyntaxTreeBuilder.new("Uri",["_", "language", "_", "zone"],[nil])),
22
+ p7 = Production.new(:Uri,[t2, t4, t2],SyntaxTreeBuilder.new("Uri",["_", "language"],[])),
23
+ p8 = Production.new(:Uri,[t2, t4],SyntaxTreeBuilder.new("Uri",["_", "language"],[nil])),
24
+ p9 = Production.new(:Uri,[t2],SyntaxTreeBuilder.new("Uri",["_"],[])),
25
+ p10 = Production.new(:Variables,[:Plus403922760, t2],LiftingSyntaxTreeBuilder.new(["pair"],[])),
26
+ p11 = Production.new(:Variables,[:Plus403922760],LiftingSyntaxTreeBuilder.new(["pair"],[nil])),
27
+ p12 = Production.new(:Plus403922760,[:Plus403922760, :Pair],ArrayNodeBuilder.new([1],0,nil,nil,[],true)),
28
+ p13 = Production.new(:Plus403922760,[:Pair],ArrayNodeBuilder.new([0],nil,nil,nil,[],true)),
29
+ p14 = Production.new(:Pair,[t3, t2, t3, t2],SyntaxTreeBuilder.new("Pair",["key", "_", "value"],[])),
30
+ p15 = Production.new(:Pair,[t3, t2, t3],SyntaxTreeBuilder.new("Pair",["key", "_", "value"],[nil])),
31
+ p16 = Production.new(:Pair,[t3, t2, t2],SyntaxTreeBuilder.new("Pair",["key"],[])),
32
+ p17 = Production.new(:Pair,[t3],SyntaxTreeBuilder.new("Pair",["key"],[]))
33
+ ]
34
+ relations = [
35
+
36
+ ]
37
+ priorities = ProductionPriorities.new(relations)
38
+ 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], [49, 4, 8, 1], [53, 2, 49, 4, 40, 1], [4, 1], [48, 7], [61, 2, 64, 7], [36, 1], [44, 7], [65, 2, 69, 4], [60, 7], [73, 2, 56, 7], [52, 7]]
39
+ goto_hash = {0 => {1 => 1}, 8 => {2 => 10, 3 => 9, 4 => 11}, 9 => {4 => 14}}
40
+ @@parse_table403739556 = ParseTable.new(productions,tokens,priorities,action_table,goto_hash,2,[
41
+ :REDUCE,
42
+ :SHIFT,
43
+ :ACCEPT
44
+ ])
45
+ def SBSM._zone_uri_parser
46
+ GeneralizedLrParser.new(@@parse_table403739556)
47
+ end
48
+ end