strelka 0.0.1.pre129 → 0.0.1.pre148
Sign up to get free protection for your applications and to get access to all the features.
- data/IDEAS.rdoc +26 -32
- data/Manifest.txt +27 -12
- data/README.rdoc +29 -33
- data/Rakefile +2 -1
- data/bin/leash +2 -1
- data/contrib/hoetemplate/README.rdoc.erb +18 -0
- data/contrib/hoetemplate/data/{file_name → project}/apps/file_name_app +0 -0
- data/contrib/hoetemplate/data/{file_name → project}/templates/layout.tmpl.erb +0 -0
- data/contrib/hoetemplate/data/{file_name → project}/templates/top.tmpl.erb +0 -0
- data/examples/config.yml +3 -0
- data/examples/gen-config.rb +48 -0
- data/examples/sessions-demo.rb +43 -0
- data/lib/strelka/app/errors.rb +59 -17
- data/lib/strelka/app/filters.rb +3 -1
- data/lib/strelka/app/negotiation.rb +5 -3
- data/lib/strelka/app/parameters.rb +33 -31
- data/lib/strelka/app/plugins.rb +14 -8
- data/lib/strelka/app/restresources.rb +3 -1
- data/lib/strelka/app/routing.rb +9 -7
- data/lib/strelka/app/sessions.rb +175 -0
- data/lib/strelka/app/templating.rb +6 -3
- data/lib/strelka/app.rb +19 -11
- data/lib/strelka/behavior/plugin.rb +4 -2
- data/lib/strelka/constants.rb +9 -0
- data/lib/strelka/cookie.rb +357 -0
- data/lib/strelka/cookieset.rb +117 -0
- data/lib/strelka/httprequest/acceptparams.rb +12 -10
- data/lib/strelka/httprequest/negotiation.rb +4 -2
- data/lib/strelka/httprequest/session.rb +71 -0
- data/lib/strelka/httprequest.rb +19 -7
- data/lib/strelka/httpresponse/negotiation.rb +17 -15
- data/lib/strelka/httpresponse/session.rb +101 -0
- data/lib/strelka/httpresponse.rb +26 -4
- data/lib/strelka/logging.rb +3 -1
- data/lib/strelka/mixins.rb +174 -2
- data/lib/strelka/{app/paramvalidator.rb → paramvalidator.rb} +25 -22
- data/lib/strelka/{app/defaultrouter.rb → router/default.rb} +6 -4
- data/lib/strelka/{app/exclusiverouter.rb → router/exclusive.rb} +6 -4
- data/lib/strelka/{app/router.rb → router.rb} +9 -7
- data/lib/strelka/session/default.rb +209 -0
- data/lib/strelka/session.rb +178 -0
- data/lib/strelka.rb +6 -4
- data/spec/lib/constants.rb +3 -1
- data/spec/lib/helpers.rb +7 -0
- data/spec/strelka/app/errors_spec.rb +32 -52
- data/spec/strelka/app/filters_spec.rb +3 -1
- data/spec/strelka/app/negotiation_spec.rb +3 -1
- data/spec/strelka/app/parameters_spec.rb +5 -3
- data/spec/strelka/app/plugins_spec.rb +5 -3
- data/spec/strelka/app/restresources_spec.rb +3 -1
- data/spec/strelka/app/routing_spec.rb +6 -4
- data/spec/strelka/app/sessions_spec.rb +109 -0
- data/spec/strelka/app/templating_spec.rb +3 -1
- data/spec/strelka/app_spec.rb +11 -2
- data/spec/strelka/cookie_spec.rb +194 -0
- data/spec/strelka/cookieset_spec.rb +159 -0
- data/spec/strelka/exceptions_spec.rb +3 -1
- data/spec/strelka/httprequest/acceptparams_spec.rb +3 -1
- data/spec/strelka/httprequest/negotiation_spec.rb +3 -1
- data/spec/strelka/httprequest/session_spec.rb +43 -0
- data/spec/strelka/httprequest_spec.rb +28 -1
- data/spec/strelka/httpresponse/negotiation_spec.rb +3 -3
- data/spec/strelka/httpresponse_spec.rb +13 -0
- data/spec/strelka/logging_spec.rb +3 -1
- data/spec/strelka/mixins_spec.rb +125 -1
- data/spec/strelka/{app/paramvalidator_spec.rb → paramvalidator_spec.rb} +4 -4
- data/spec/strelka/{app/defaultrouter_spec.rb → router/default_spec.rb} +6 -4
- data/spec/strelka/{app/exclusiverouter_spec.rb → router/exclusive_spec.rb} +6 -4
- data/spec/strelka/{app/router_spec.rb → router_spec.rb} +9 -7
- data/spec/strelka/session/default_spec.rb +210 -0
- data/spec/strelka/session_spec.rb +101 -0
- data.tar.gz.sig +1 -1
- metadata +64 -47
- metadata.gz.sig +0 -0
- data/contrib/hoetemplate/.autotest.erb +0 -23
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# -*- ruby -*-
|
2
|
+
# vim: set nosta noet ts=4 sw=4:
|
3
|
+
# encoding: utf-8
|
2
4
|
|
3
5
|
require 'set'
|
4
6
|
require 'yaml'
|
@@ -10,7 +12,7 @@ require 'strelka/httpresponse' unless defined?( Strelka::HTTPResponse )
|
|
10
12
|
|
11
13
|
|
12
14
|
# The mixin that adds methods to Strelka::HTTPResponse for content-negotiation.
|
13
|
-
#
|
15
|
+
#
|
14
16
|
# response = request.response
|
15
17
|
# response.for( 'text/html' ) {...}
|
16
18
|
# response.for( :json ) {...}
|
@@ -187,7 +189,7 @@ module Strelka::HTTPResponse::Negotiation
|
|
187
189
|
# value of "ISO-8859-1" when received via HTTP. [RFC2616 3.7.1]
|
188
190
|
if charset == Encoding::ASCII_8BIT
|
189
191
|
return true unless self.content_type.start_with?( 'text/' )
|
190
|
-
charset = Encoding::ISO8859_1
|
192
|
+
charset = Encoding::ISO8859_1
|
191
193
|
end
|
192
194
|
|
193
195
|
answer = req.accepts_charset?( charset )
|
@@ -214,7 +216,7 @@ module Strelka::HTTPResponse::Negotiation
|
|
214
216
|
return true if self.languages.empty?
|
215
217
|
|
216
218
|
# If any of the languages present for the body are accepted, the
|
217
|
-
# request is acceptable. Or at least that's what I got out of
|
219
|
+
# request is acceptable. Or at least that's what I got out of
|
218
220
|
# reading RFC2616, Section 14.4.
|
219
221
|
answer = self.languages.any? {|lang| req.accepts_language?(lang) }
|
220
222
|
self.log.warn "Content-language %p NOT acceptable: %s" %
|
@@ -225,7 +227,7 @@ module Strelka::HTTPResponse::Negotiation
|
|
225
227
|
alias_method :has_acceptable_language?, :acceptable_language?
|
226
228
|
|
227
229
|
|
228
|
-
### Returns true if all of the receiver's #encodings were designated
|
230
|
+
### Returns true if all of the receiver's #encodings were designated
|
229
231
|
### as acceptable by the originating request, if there was no originating
|
230
232
|
### request, or if no #encodings have been set.
|
231
233
|
def acceptable_encoding?
|
@@ -255,7 +257,7 @@ module Strelka::HTTPResponse::Negotiation
|
|
255
257
|
### the desired mimetype, and should return the new value for the entity
|
256
258
|
### body if it successfully transformed the body, or a false value if
|
257
259
|
### the next alternative should be tried instead.
|
258
|
-
### If successful, the response's body will be set to the new value,
|
260
|
+
### If successful, the response's body will be set to the new value,
|
259
261
|
### its content_type set to the new mimetype, and its status changed
|
260
262
|
### to HTTP::OK.
|
261
263
|
def for( *mediatypes, &callback )
|
@@ -269,7 +271,7 @@ module Strelka::HTTPResponse::Negotiation
|
|
269
271
|
end
|
270
272
|
|
271
273
|
|
272
|
-
### Returns Strelka::HTTPRequest::MediaType objects for mediatypes that have
|
274
|
+
### Returns Strelka::HTTPRequest::MediaType objects for mediatypes that have
|
273
275
|
### a higher qvalue than the current response's entity body (if any).
|
274
276
|
def better_mediatypes
|
275
277
|
req = self.request or return []
|
@@ -294,11 +296,11 @@ module Strelka::HTTPResponse::Negotiation
|
|
294
296
|
end
|
295
297
|
|
296
298
|
|
297
|
-
### Iterate over the originating request's acceptable content types in
|
299
|
+
### Iterate over the originating request's acceptable content types in
|
298
300
|
### qvalue+listed order, looking for a content negotiation callback for
|
299
301
|
### each mediatype. If any are found, they are tried in declared order
|
300
302
|
### until one returns a true-ish value, which becomes the new entity
|
301
|
-
### body. If the body object is not a String,
|
303
|
+
### body. If the body object is not a String,
|
302
304
|
def transform_content_type
|
303
305
|
return if self.mediatype_callbacks.empty?
|
304
306
|
|
@@ -362,7 +364,7 @@ module Strelka::HTTPResponse::Negotiation
|
|
362
364
|
end
|
363
365
|
|
364
366
|
|
365
|
-
### Returns Strelka::HTTPRequest::Language objects for natural languages that have
|
367
|
+
### Returns Strelka::HTTPRequest::Language objects for natural languages that have
|
366
368
|
### a higher qvalue than the current response's entity body (if any).
|
367
369
|
def better_languages
|
368
370
|
req = self.request or return []
|
@@ -389,8 +391,8 @@ module Strelka::HTTPResponse::Negotiation
|
|
389
391
|
end
|
390
392
|
|
391
393
|
|
392
|
-
### If there are any languages that have a higher qvalue than the one/s in #languages,
|
393
|
-
### look for a negotiation callback that provides that language. If any are found, they
|
394
|
+
### If there are any languages that have a higher qvalue than the one/s in #languages,
|
395
|
+
### look for a negotiation callback that provides that language. If any are found, they
|
394
396
|
### are tried in declared order until one returns a true-ish value, which becomes the new
|
395
397
|
### entity body.
|
396
398
|
def transform_language
|
@@ -425,7 +427,7 @@ module Strelka::HTTPResponse::Negotiation
|
|
425
427
|
# :section: Charset negotiation callbacks
|
426
428
|
#
|
427
429
|
|
428
|
-
### Returns Strelka::HTTPRequest::Charset objects for accepted character sets that have
|
430
|
+
### Returns Strelka::HTTPRequest::Charset objects for accepted character sets that have
|
429
431
|
### a higher qvalue than the one used by the current response.
|
430
432
|
def better_charsets
|
431
433
|
req = self.request or return []
|
@@ -453,7 +455,7 @@ module Strelka::HTTPResponse::Negotiation
|
|
453
455
|
end
|
454
456
|
|
455
457
|
|
456
|
-
### Iterate over the originating request's acceptable charsets in
|
458
|
+
### Iterate over the originating request's acceptable charsets in
|
457
459
|
### qvalue+listed order, attempting to transcode the current entity body
|
458
460
|
### if it
|
459
461
|
def transform_charset
|
@@ -522,7 +524,7 @@ module Strelka::HTTPResponse::Negotiation
|
|
522
524
|
end
|
523
525
|
|
524
526
|
|
525
|
-
### Returns Strelka::HTTPRequest::Encoding objects for accepted encodings that have
|
527
|
+
### Returns Strelka::HTTPRequest::Encoding objects for accepted encodings that have
|
526
528
|
### a higher qvalue than the one used by the current response.
|
527
529
|
def better_encoding
|
528
530
|
req = self.request or return []
|
@@ -0,0 +1,101 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
# vim: set nosta noet ts=4 sw=4:
|
3
|
+
# encoding: utf-8
|
4
|
+
|
5
|
+
require 'strelka/constants'
|
6
|
+
require 'strelka/exceptions'
|
7
|
+
require 'strelka/httpresponse' unless defined?( Strelka::HTTPResponse )
|
8
|
+
|
9
|
+
|
10
|
+
# The mixin that adds methods to Strelka::HTTPResponse for session persistance.
|
11
|
+
# If you create a response via the Request#response method, the session will
|
12
|
+
# added to the response as well, and automatically saved after the handler and
|
13
|
+
# all plugins have run. Or you can do so manually:
|
14
|
+
#
|
15
|
+
# response = request.response
|
16
|
+
# response.save_session
|
17
|
+
#
|
18
|
+
# You can also clear the session with #destroy_session.
|
19
|
+
#
|
20
|
+
#
|
21
|
+
#
|
22
|
+
module Strelka::HTTPResponse::Session
|
23
|
+
include Strelka::Constants
|
24
|
+
|
25
|
+
|
26
|
+
### Initialize instance variables for session data in the response.
|
27
|
+
def initialize( * )
|
28
|
+
super
|
29
|
+
@session = nil
|
30
|
+
@session_namespace = nil
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
######
|
35
|
+
public
|
36
|
+
######
|
37
|
+
|
38
|
+
# The current session namespace
|
39
|
+
attr_reader :session_namespace
|
40
|
+
|
41
|
+
|
42
|
+
### The namespace that will be used when creating a session for this response
|
43
|
+
def session_namespace=( namespace )
|
44
|
+
self.log.debug "Setting session namespace to %p" % [ namespace ]
|
45
|
+
@session_namespace = namespace
|
46
|
+
|
47
|
+
# If the session has already been created, switch its current namespace
|
48
|
+
@session.namespace = namespace if @session
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
### Return the session associated with the response, creating it if necessary.
|
53
|
+
def session
|
54
|
+
unless @session
|
55
|
+
# Load the session from the associated request if there is one.
|
56
|
+
# If there isn't an associated request, this will just create a
|
57
|
+
# new blank session.
|
58
|
+
if self.request.session?
|
59
|
+
self.log.debug "Getting the request's session."
|
60
|
+
@session = request.session
|
61
|
+
else
|
62
|
+
self.log.debug "No session loaded in the request; creating it in the response."
|
63
|
+
sessionclass = Strelka::App::Sessions.session_class
|
64
|
+
@session = sessionclass.load_or_create( self.request )
|
65
|
+
@session.namespace = self.session_namespace
|
66
|
+
request.session = @session
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
return @session
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
### Set the request's session object.
|
75
|
+
def session=( new_session )
|
76
|
+
new_session.namespace = self.session_namespace
|
77
|
+
@session = new_session
|
78
|
+
request.session = new_session
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
### Returns +true+ if the response already has an associated session object.
|
83
|
+
def session?
|
84
|
+
return @session || self.request.session?
|
85
|
+
end
|
86
|
+
|
87
|
+
|
88
|
+
### Tell the associated session to save itself and set up the session ID in the
|
89
|
+
### response, if one exists.
|
90
|
+
def save_session
|
91
|
+
if self.session?
|
92
|
+
session = self.session
|
93
|
+
self.log.debug "Saving session: %p" % [ @session ]
|
94
|
+
session.save( self )
|
95
|
+
else
|
96
|
+
self.log.debug "No session to save."
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
end # module Strelka::HTTPResponse::Session
|
101
|
+
|
data/lib/strelka/httpresponse.rb
CHANGED
@@ -1,7 +1,10 @@
|
|
1
|
-
|
1
|
+
# -*- ruby -*-
|
2
|
+
# vim: set nosta noet ts=4 sw=4:
|
3
|
+
# encoding: utf-8
|
2
4
|
|
3
5
|
require 'mongrel2/httpresponse'
|
4
6
|
require 'strelka' unless defined?( Strelka )
|
7
|
+
require 'strelka/cookieset'
|
5
8
|
|
6
9
|
# An HTTP response class.
|
7
10
|
class Strelka::HTTPResponse < Mongrel2::HTTPResponse
|
@@ -16,9 +19,10 @@ class Strelka::HTTPResponse < Mongrel2::HTTPResponse
|
|
16
19
|
|
17
20
|
### Add some instance variables to new HTTPResponses.
|
18
21
|
def initialize( * ) # :notnew:
|
19
|
-
@charset
|
22
|
+
@charset = nil
|
20
23
|
@languages = []
|
21
24
|
@encodings = []
|
25
|
+
@cookies = nil
|
22
26
|
|
23
27
|
super
|
24
28
|
end
|
@@ -58,6 +62,7 @@ class Strelka::HTTPResponse < Mongrel2::HTTPResponse
|
|
58
62
|
self.add_content_type_charset( headers )
|
59
63
|
headers.content_encoding ||= self.encodings.join(', ') unless self.encodings.empty?
|
60
64
|
headers.content_language ||= self.languages.join(', ') unless self.languages.empty?
|
65
|
+
self.add_cookie_headers( headers )
|
61
66
|
|
62
67
|
return headers
|
63
68
|
end
|
@@ -73,6 +78,14 @@ class Strelka::HTTPResponse < Mongrel2::HTTPResponse
|
|
73
78
|
end
|
74
79
|
|
75
80
|
|
81
|
+
### Returns a Strelka::CookieSet that can be used to manipulate the cookies that are
|
82
|
+
### sent with the response, creating it if necessary.
|
83
|
+
def cookies
|
84
|
+
@cookies = Strelka::CookieSet.new unless @cookies
|
85
|
+
return @cookies
|
86
|
+
end
|
87
|
+
|
88
|
+
|
76
89
|
|
77
90
|
#########
|
78
91
|
protected
|
@@ -94,9 +107,9 @@ class Strelka::HTTPResponse < Mongrel2::HTTPResponse
|
|
94
107
|
### associated with the entity body, then the default external encoding (if it's set). If
|
95
108
|
### none of those are found, this method returns ISO-8859-1.
|
96
109
|
def find_header_charset
|
97
|
-
return ( self.charset ||
|
110
|
+
return ( self.charset ||
|
98
111
|
self.content_type_charset ||
|
99
|
-
self.entity_body_charset ||
|
112
|
+
self.entity_body_charset ||
|
100
113
|
Encoding.default_external ||
|
101
114
|
Encoding::ISO_8859_1 )
|
102
115
|
end
|
@@ -135,6 +148,15 @@ class Strelka::HTTPResponse < Mongrel2::HTTPResponse
|
|
135
148
|
return nil
|
136
149
|
end
|
137
150
|
|
151
|
+
|
152
|
+
### Add Set-Cookie members to +headers+ if the response has any cookies.
|
153
|
+
def add_cookie_headers( headers )
|
154
|
+
return unless @cookies
|
155
|
+
@cookies.each do |cookie|
|
156
|
+
headers.append( :set_cookie => cookie.to_s )
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
138
160
|
end # class Strelka::HTTPResponse
|
139
161
|
|
140
162
|
|
data/lib/strelka/logging.rb
CHANGED
data/lib/strelka/mixins.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# -*- ruby -*-
|
2
|
+
# vim: set nosta noet ts=4 sw=4:
|
3
|
+
# encoding: utf-8
|
2
4
|
|
3
5
|
require 'logger'
|
4
6
|
|
@@ -118,7 +120,7 @@ module Strelka
|
|
118
120
|
end
|
119
121
|
|
120
122
|
|
121
|
-
### Colorize the given +string+ with the specified +attributes+ and return it, handling
|
123
|
+
### Colorize the given +string+ with the specified +attributes+ and return it, handling
|
122
124
|
### line-endings, color reset, etc.
|
123
125
|
def colorize( *args )
|
124
126
|
string = ''
|
@@ -190,6 +192,176 @@ module Strelka
|
|
190
192
|
end # module AbstractClass
|
191
193
|
|
192
194
|
|
195
|
+
# A collection of various delegation code-generators that can be used to define
|
196
|
+
# delegation through other methods, to instance variables, etc.
|
197
|
+
module Delegation
|
198
|
+
|
199
|
+
###############
|
200
|
+
module_function
|
201
|
+
###############
|
202
|
+
|
203
|
+
### Define the given +delegated_methods+ as delegators to the like-named method
|
204
|
+
### of the return value of the +delegate_method+.
|
205
|
+
###
|
206
|
+
### class MyClass
|
207
|
+
### extend Strelka::Delegation
|
208
|
+
###
|
209
|
+
### # Delegate the #bound?, #err, and #result2error methods to the connection
|
210
|
+
### # object returned by the #connection method. This allows the connection
|
211
|
+
### # to still be loaded on demand/overridden/etc.
|
212
|
+
### def_method_delegators :connection, :bound?, :err, :result2error
|
213
|
+
###
|
214
|
+
### def connection
|
215
|
+
### @connection ||= self.connect
|
216
|
+
### end
|
217
|
+
### end
|
218
|
+
###
|
219
|
+
def def_method_delegators( delegate_method, *delegated_methods )
|
220
|
+
delegated_methods.each do |name|
|
221
|
+
body = make_method_delegator( delegate_method, name )
|
222
|
+
define_method( name, &body )
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
|
227
|
+
### Define the given +delegated_methods+ as delegators to the like-named method
|
228
|
+
### of the specified +ivar+. This is pretty much identical with how 'Forwardable'
|
229
|
+
### from the stdlib does delegation, but it's reimplemented here for consistency.
|
230
|
+
###
|
231
|
+
### class MyClass
|
232
|
+
### extend Strelka::Delegation
|
233
|
+
###
|
234
|
+
### # Delegate the #each method to the @collection ivar
|
235
|
+
### def_ivar_delegators :@collection, :each
|
236
|
+
###
|
237
|
+
### end
|
238
|
+
###
|
239
|
+
def def_ivar_delegators( ivar, *delegated_methods )
|
240
|
+
delegated_methods.each do |name|
|
241
|
+
body = make_ivar_delegator( ivar, name )
|
242
|
+
define_method( name, &body )
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
|
247
|
+
#######
|
248
|
+
private
|
249
|
+
#######
|
250
|
+
|
251
|
+
### Make the body of a delegator method that will delegate to the +name+ method
|
252
|
+
### of the object returned by the +delegate+ method.
|
253
|
+
def make_method_delegator( delegate, name )
|
254
|
+
error_frame = caller(5)[0]
|
255
|
+
file, line = error_frame.split( ':', 2 )
|
256
|
+
|
257
|
+
# Ruby can't parse obj.method=(*args), so we have to special-case setters...
|
258
|
+
if name.to_s =~ /(\w+)=$/
|
259
|
+
name = $1
|
260
|
+
code = <<-END_CODE
|
261
|
+
lambda {|*args| self.#{delegate}.#{name} = *args }
|
262
|
+
END_CODE
|
263
|
+
else
|
264
|
+
code = <<-END_CODE
|
265
|
+
lambda {|*args,&block| self.#{delegate}.#{name}(*args,&block) }
|
266
|
+
END_CODE
|
267
|
+
end
|
268
|
+
|
269
|
+
return eval( code, nil, file, line.to_i )
|
270
|
+
end
|
271
|
+
|
272
|
+
|
273
|
+
### Make the body of a delegator method that will delegate calls to the +name+
|
274
|
+
### method to the given +ivar+.
|
275
|
+
def make_ivar_delegator( ivar, name )
|
276
|
+
error_frame = caller(5)[0]
|
277
|
+
file, line = error_frame.split( ':', 2 )
|
278
|
+
|
279
|
+
# Ruby can't parse obj.method=(*args), so we have to special-case setters...
|
280
|
+
if name.to_s =~ /(\w+)=$/
|
281
|
+
name = $1
|
282
|
+
code = <<-END_CODE
|
283
|
+
lambda {|*args| #{ivar}.#{name} = *args }
|
284
|
+
END_CODE
|
285
|
+
else
|
286
|
+
code = <<-END_CODE
|
287
|
+
lambda {|*args,&block| #{ivar}.#{name}(*args,&block) }
|
288
|
+
END_CODE
|
289
|
+
end
|
290
|
+
|
291
|
+
return eval( code, nil, file, line.to_i )
|
292
|
+
end
|
293
|
+
|
294
|
+
end # module Delegation
|
295
|
+
|
296
|
+
|
297
|
+
# A collection of miscellaneous functions that are useful for manipulating
|
298
|
+
# complex data structures.
|
299
|
+
module DataUtilities
|
300
|
+
|
301
|
+
###############
|
302
|
+
module_function
|
303
|
+
###############
|
304
|
+
|
305
|
+
### Recursively copy the specified +obj+ and return the result.
|
306
|
+
def deep_copy( obj )
|
307
|
+
|
308
|
+
# Handle mocks during testing
|
309
|
+
return obj if obj.class.name == 'RSpec::Mocks::Mock'
|
310
|
+
|
311
|
+
return case obj
|
312
|
+
when NilClass, Numeric, TrueClass, FalseClass, Symbol
|
313
|
+
obj
|
314
|
+
|
315
|
+
when Array
|
316
|
+
obj.map {|o| deep_copy(o) }
|
317
|
+
|
318
|
+
when Hash
|
319
|
+
newhash = {}
|
320
|
+
obj.each do |k,v|
|
321
|
+
newhash[ deep_copy(k) ] = deep_copy( v )
|
322
|
+
end
|
323
|
+
newhash
|
324
|
+
|
325
|
+
else
|
326
|
+
obj.clone
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
end # module DataUtilities
|
331
|
+
|
332
|
+
|
333
|
+
# A collection of methods for declaring other methods.
|
334
|
+
module MethodUtilities
|
335
|
+
|
336
|
+
### Creates instance variables and corresponding methods that return their
|
337
|
+
### values for each of the specified +symbols+ in the singleton of the
|
338
|
+
### declaring object (e.g., class instance variables and methods if declared
|
339
|
+
### in a Class).
|
340
|
+
def singleton_attr_reader( *symbols )
|
341
|
+
symbols.each do |sym|
|
342
|
+
singleton_class.__send__( :attr_reader, sym )
|
343
|
+
end
|
344
|
+
end
|
345
|
+
|
346
|
+
### Creates methods that allow assignment to the attributes of the singleton
|
347
|
+
### of the declaring object that correspond to the specified +symbols+.
|
348
|
+
def singleton_attr_writer( *symbols )
|
349
|
+
symbols.each do |sym|
|
350
|
+
singleton_class.__send__( :attr_writer, sym )
|
351
|
+
end
|
352
|
+
end
|
353
|
+
|
354
|
+
### Creates readers and writers that allow assignment to the attributes of
|
355
|
+
### the singleton of the declaring object that correspond to the specified
|
356
|
+
### +symbols+.
|
357
|
+
def singleton_attr_accessor( *symbols )
|
358
|
+
symbols.each do |sym|
|
359
|
+
singleton_class.__send__( :attr_accessor, sym )
|
360
|
+
end
|
361
|
+
end
|
362
|
+
|
363
|
+
end # module MethodUtilities
|
364
|
+
|
193
365
|
end # module Strelka
|
194
366
|
|
195
367
|
# vim: set nosta noet ts=4 sw=4:
|
@@ -1,4 +1,7 @@
|
|
1
|
-
|
1
|
+
# -*- ruby -*-
|
2
|
+
# vim: set nosta noet ts=4 sw=4:
|
3
|
+
# encoding: utf-8
|
4
|
+
|
2
5
|
#encoding: utf-8
|
3
6
|
|
4
7
|
require 'uri'
|
@@ -12,7 +15,7 @@ require 'strelka/app' unless defined?( Strelka::App )
|
|
12
15
|
|
13
16
|
|
14
17
|
# A validator for user parameters.
|
15
|
-
#
|
18
|
+
#
|
16
19
|
# == Usage
|
17
20
|
#
|
18
21
|
# require 'strelka/app/formvalidator'
|
@@ -24,20 +27,20 @@ require 'strelka/app' unless defined?( Strelka::App )
|
|
24
27
|
# :filters => [:strip, :squeeze],
|
25
28
|
# :untaint_all_constraints => true,
|
26
29
|
# :descriptions => {
|
27
|
-
#
|
28
|
-
#
|
29
|
-
#
|
30
|
+
# :email => "Customer Email",
|
31
|
+
# :description => "Issue Description",
|
32
|
+
# :name => "Customer Name",
|
30
33
|
# },
|
31
|
-
# :constraints
|
32
|
-
#
|
33
|
-
#
|
34
|
-
#
|
34
|
+
# :constraints => {
|
35
|
+
# :email => :email,
|
36
|
+
# :name => /^[\x20-\x7f]+$/,
|
37
|
+
# :description => /^[\x20-\x7f]+$/,
|
35
38
|
# },
|
36
39
|
# }
|
37
40
|
#
|
38
41
|
# # Create a validator object and pass in a hash of request parameters and the
|
39
42
|
# # profile hash.
|
40
|
-
# validator = Strelka::
|
43
|
+
# validator = Strelka::ParamValidator.new
|
41
44
|
# validator.validate( req_params, profile )
|
42
45
|
#
|
43
46
|
# # Now if there weren't any errors, send the success page
|
@@ -51,7 +54,7 @@ require 'strelka/app' unless defined?( Strelka::App )
|
|
51
54
|
# return failure_template
|
52
55
|
# end
|
53
56
|
#
|
54
|
-
class Strelka::
|
57
|
+
class Strelka::ParamValidator < ::FormValidator
|
55
58
|
extend Forwardable
|
56
59
|
include Strelka::Loggable
|
57
60
|
|
@@ -64,7 +67,7 @@ class Strelka::App::ParamValidator < ::FormValidator
|
|
64
67
|
#
|
65
68
|
# RFC822 Email Address Regex
|
66
69
|
# --------------------------
|
67
|
-
#
|
70
|
+
#
|
68
71
|
# Originally written by Cal Henderson
|
69
72
|
# c.f. http://iamcal.com/publish/articles/php/parsing_email/
|
70
73
|
#
|
@@ -72,7 +75,7 @@ class Strelka::App::ParamValidator < ::FormValidator
|
|
72
75
|
#
|
73
76
|
# Licensed under a Creative Commons Attribution-ShareAlike 2.5 License
|
74
77
|
# http://creativecommons.org/licenses/by-sa/2.5/
|
75
|
-
#
|
78
|
+
#
|
76
79
|
RFC822_EMAIL_ADDRESS = begin
|
77
80
|
qtext = '[^\\x0d\\x22\\x5c\\x80-\\xff]'
|
78
81
|
dtext = '[^\\x0d\\x5b-\\x5d\\x80-\\xff]'
|
@@ -134,7 +137,7 @@ class Strelka::App::ParamValidator < ::FormValidator
|
|
134
137
|
### I N S T A N C E M E T H O D S
|
135
138
|
#################################################################
|
136
139
|
|
137
|
-
### Create a new Strelka::
|
140
|
+
### Create a new Strelka::ParamValidator object.
|
138
141
|
def initialize( profile, params=nil )
|
139
142
|
@form = {}
|
140
143
|
@raw_form = {}
|
@@ -215,7 +218,7 @@ class Strelka::App::ParamValidator < ::FormValidator
|
|
215
218
|
|
216
219
|
if additional_profile
|
217
220
|
self.log.debug "Merging additional profile %p" % [additional_profile]
|
218
|
-
profile = @profile.merge( additional_profile )
|
221
|
+
profile = @profile.merge( additional_profile )
|
219
222
|
end
|
220
223
|
|
221
224
|
super( params, profile )
|
@@ -270,8 +273,8 @@ class Strelka::App::ParamValidator < ::FormValidator
|
|
270
273
|
### Returns +true+ if the given +field+ is one that should be untainted.
|
271
274
|
def untaint?( field )
|
272
275
|
self.log.debug "Checking to see if %p should be untainted." % [field]
|
273
|
-
rval = ( @untaint_all ||
|
274
|
-
@untaint_fields.include?(field) ||
|
276
|
+
rval = ( @untaint_all ||
|
277
|
+
@untaint_fields.include?(field) ||
|
275
278
|
@untaint_fields.include?(field.to_sym) )
|
276
279
|
|
277
280
|
if rval
|
@@ -530,7 +533,7 @@ class Strelka::App::ParamValidator < ::FormValidator
|
|
530
533
|
when Proc, Method
|
531
534
|
apply_proc_constraint( key, constraint )
|
532
535
|
when Regexp
|
533
|
-
apply_regexp_constraint( key, constraint )
|
536
|
+
apply_regexp_constraint( key, constraint )
|
534
537
|
else
|
535
538
|
raise "unknown constraint type %p" % [constraint]
|
536
539
|
end
|
@@ -585,7 +588,7 @@ class Strelka::App::ParamValidator < ::FormValidator
|
|
585
588
|
end
|
586
589
|
|
587
590
|
|
588
|
-
### Apply a constraint that was specified as a Proc to the value for the given
|
591
|
+
### Apply a constraint that was specified as a Proc to the value for the given
|
589
592
|
### +key+
|
590
593
|
def apply_proc_constraint( key, constraint, *params )
|
591
594
|
value = nil
|
@@ -642,7 +645,7 @@ class Strelka::App::ParamValidator < ::FormValidator
|
|
642
645
|
key.untaint
|
643
646
|
|
644
647
|
# Have to test for nil because valid values might be false.
|
645
|
-
if !value.nil?
|
648
|
+
if !value.nil?
|
646
649
|
self.log.debug "Setting form value for %p to %p (constraint was %p)" %
|
647
650
|
[ key, value, constraint ]
|
648
651
|
if self.untaint?( key )
|
@@ -675,7 +678,7 @@ class Strelka::App::ParamValidator < ::FormValidator
|
|
675
678
|
|
676
679
|
### Formvalidator hack:
|
677
680
|
### The formvalidator filters method has a bug where he assumes an array
|
678
|
-
### when it is in fact a string for multiple values (ie anytime you have a
|
681
|
+
### when it is in fact a string for multiple values (ie anytime you have a
|
679
682
|
### text-area with newlines in it).
|
680
683
|
def filters
|
681
684
|
@filters_array = Array(@profile[:filters]) unless(@filters_array)
|
@@ -745,7 +748,7 @@ class Strelka::App::ParamValidator < ::FormValidator
|
|
745
748
|
end
|
746
749
|
end
|
747
750
|
|
748
|
-
end # class Strelka::
|
751
|
+
end # class Strelka::ParamValidator
|
749
752
|
|
750
753
|
|
751
754
|
|
@@ -1,11 +1,13 @@
|
|
1
|
-
|
1
|
+
# -*- ruby -*-
|
2
|
+
# vim: set nosta noet ts=4 sw=4:
|
3
|
+
# encoding: utf-8
|
2
4
|
|
3
5
|
require 'strelka' unless defined?( Strelka )
|
4
6
|
require 'strelka/app' unless defined?( Strelka::App )
|
5
|
-
require 'strelka/
|
7
|
+
require 'strelka/router'
|
6
8
|
|
7
9
|
# Simple (dumb?) request router for Strelka::App-based applications.
|
8
|
-
class Strelka::
|
10
|
+
class Strelka::Router::Default < Strelka::Router
|
9
11
|
include Strelka::Loggable
|
10
12
|
|
11
13
|
### Create a new router that will route requests according to the specified
|
@@ -101,4 +103,4 @@ class Strelka::App::DefaultRouter < Strelka::App::Router
|
|
101
103
|
|
102
104
|
end
|
103
105
|
|
104
|
-
end # class Strelka::
|
106
|
+
end # class Strelka::Router::Default
|
@@ -1,9 +1,11 @@
|
|
1
|
-
|
1
|
+
# -*- ruby -*-
|
2
|
+
# vim: set nosta noet ts=4 sw=4:
|
3
|
+
# encoding: utf-8
|
2
4
|
|
3
5
|
require 'strelka' unless defined?( Strelka )
|
4
6
|
require 'strela/app' unless defined?( Strelka::App )
|
5
7
|
|
6
|
-
require 'strelka/
|
8
|
+
require 'strelka/router/default'
|
7
9
|
|
8
10
|
# Alternative (stricter) router strategy for Strelka::App::Routing plugin.
|
9
11
|
#
|
@@ -21,7 +23,7 @@ require 'strelka/app/defaultrouter'
|
|
21
23
|
#
|
22
24
|
# end # class MyApp
|
23
25
|
#
|
24
|
-
class Strelka::
|
26
|
+
class Strelka::Router::Exclusive < Strelka::Router::Default
|
25
27
|
include Strelka::Loggable
|
26
28
|
|
27
29
|
######
|
@@ -37,4 +39,4 @@ class Strelka::App::ExclusiveRouter < Strelka::App::DefaultRouter
|
|
37
39
|
self.routes[ verb ][ re ] = route
|
38
40
|
end
|
39
41
|
|
40
|
-
end # class Strelka::
|
42
|
+
end # class Strelka::Router::Default
|