rsence-pre 2.1.0.21 → 2.1.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/INSTALL.rdoc +61 -46
- data/README.rdoc +17 -1
- data/VERSION +1 -1
- data/conf/rsence_command_strings.yaml +16 -16
- data/js/comm/sessionwatcher/sessionwatcher.js +5 -4
- data/js/comm/transporter/transporter.js +62 -4
- data/js/comm/values/values.js +62 -0
- data/js/controls/button/themes/default/button.css +7 -7
- data/js/controls/imageview/imageview.js +15 -6
- data/js/controls/stringview/stringview.js +16 -2
- data/js/controls/textcontrol/textcontrol.js +56 -3
- data/js/core/elem/elem.js +38 -12
- data/js/datetime/timesheet/timesheet.js +141 -32
- data/js/datetime/timesheet_item/timesheet_item.js +82 -22
- data/js/foundation/application/application.js +10 -4
- data/js/foundation/control/control.js +5 -3
- data/js/foundation/control/dyncontrol/dyncontrol.js +17 -3
- data/js/foundation/control/eventresponder/eventresponder.js +31 -2
- data/js/foundation/eventmanager/eventmanager.js +202 -74
- data/js/foundation/json_renderer/json_renderer.js +5 -2
- data/js/foundation/system/system.js +13 -11
- data/js/foundation/view/morphanimation/morphanimation.js +9 -5
- data/js/foundation/view/view.js +22 -10
- data/js/lists/propertylist/propertylist.js +5 -0
- data/js/menus/minimenu/minimenu.js +3 -8
- data/lib/conf/default.rb +0 -3
- data/lib/http/broker.rb +6 -5
- data/lib/http/rackup.rb +3 -3
- data/lib/http/response.rb +28 -2
- data/lib/session/msg.rb +30 -18
- data/lib/transporter/transporter.rb +4 -0
- data/lib/values/hvalue.rb +4 -134
- data/lib/values/valuemanager.rb +36 -22
- data/plugins/client_pkg/lib/client_pkg_serve.rb +195 -152
- data/plugins/main/main.rb +8 -10
- data/plugins/ticket/lib/common.rb +4 -4
- data/plugins/ticket/lib/favicon.rb +1 -1
- data/plugins/ticket/lib/rsrc.rb +1 -1
- data/plugins/ticket/lib/upload.rb +2 -2
- data/plugins/ticket/ticket.rb +3 -3
- data/setup/welcome/gui/welcome.yaml +1 -1
- metadata +10 -11
- data/lib/util/ruby19_fixes.rb +0 -18
data/lib/conf/default.rb
CHANGED
data/lib/http/broker.rb
CHANGED
@@ -24,7 +24,7 @@ class Broker
|
|
24
24
|
|
25
25
|
# This method is called from Rack.
|
26
26
|
# @param [Hash] env is the Rack environment.
|
27
|
-
# @return [Array(Number, Hash,
|
27
|
+
# @return [Array(Number, Hash, Array)] Rack-style response status, header, body
|
28
28
|
def call( env )
|
29
29
|
sleep @@ping_sim if @@ping_sim
|
30
30
|
unless @@transporter.online?
|
@@ -35,7 +35,7 @@ class Broker
|
|
35
35
|
'Refresh' => "2; #{env['REQUEST_URI']}",
|
36
36
|
'Content-Length' => '4'
|
37
37
|
}
|
38
|
-
return [ 503, headers, 'BUSY' ]
|
38
|
+
return [ 503, headers, ['BUSY'] ]
|
39
39
|
end
|
40
40
|
request = Request.new(env)
|
41
41
|
response = Response.new
|
@@ -43,8 +43,9 @@ class Broker
|
|
43
43
|
dispatcher = dispatcher_class.new( request, response )
|
44
44
|
dispatcher.send( request_method )
|
45
45
|
content_type = dispatcher.content_type
|
46
|
-
|
47
|
-
|
46
|
+
response_body = response.body
|
47
|
+
response.header['Content-Length'] = response.body_bytes unless response.header.has_key?('Content-Length')
|
48
|
+
return [response.status, response.header, response_body]
|
48
49
|
end
|
49
50
|
|
50
51
|
# Returns a dynamically created "REST Dispatcher" kind of class that has
|
@@ -121,7 +122,7 @@ class Broker
|
|
121
122
|
@response.status = 404
|
122
123
|
err404 = '<html><head><title>404 - Page Not Found</title></head><body>404 - Page Not Found</body></html>'
|
123
124
|
@response['Content-Type'] = 'text/html; charset=UTF-8'
|
124
|
-
@response['Content-Length'] = err404.
|
125
|
+
@response['Content-Length'] = err404.bytesize.to_s
|
125
126
|
@response.body = err404
|
126
127
|
end
|
127
128
|
|
data/lib/http/rackup.rb
CHANGED
@@ -74,7 +74,7 @@ module Broker
|
|
74
74
|
else
|
75
75
|
puts "unsupported method: #{request_method.inspect}"
|
76
76
|
end
|
77
|
-
response.header['Content-Length'] = response.body.
|
77
|
+
response.header['Content-Length'] = response.body.bytesize.to_s unless response.header.has_key?('Content-Length')
|
78
78
|
return [response.status, response.header, response.body]
|
79
79
|
end
|
80
80
|
|
@@ -82,8 +82,8 @@ module Broker
|
|
82
82
|
puts "/404: #{request.fullpath.inspect}" if $DEBUG_MODE
|
83
83
|
response.status = 404
|
84
84
|
err404 = '<html><head><title>404 - Page Not Found</title></head><body>404 - Page Not Found</body></html>'
|
85
|
-
response['
|
86
|
-
response['
|
85
|
+
response['Content-Type'] = 'text/html; charset=UTF-8'
|
86
|
+
response['Content-Length'] = err404.bytesize.to_s
|
87
87
|
response.body = err404
|
88
88
|
end
|
89
89
|
|
data/lib/http/response.rb
CHANGED
@@ -17,6 +17,21 @@ module RSence
|
|
17
17
|
# Adds the + method "operator" to an extended Array.
|
18
18
|
# Used for pushing http body data.
|
19
19
|
class ResponseBody < Array
|
20
|
+
|
21
|
+
def push( body_data )
|
22
|
+
super( sanitize_body_data( body_data ) )
|
23
|
+
end
|
24
|
+
def sanitize_body_data( body_data )
|
25
|
+
if body_data.class == String or body_data.class == GZString
|
26
|
+
return body_data
|
27
|
+
elsif body_data.respond_to?(:to_s)
|
28
|
+
warn "WARNING: RSence::Response::ResponseBody -> body_data is not a string. It's a #{body_data.class}, with the following contents: #{body_data.inspect}" if RSence.args[:verbose]
|
29
|
+
return body_data.to_s
|
30
|
+
else
|
31
|
+
warn "Invalid response data: #{body_data.inspect[0..100]}"
|
32
|
+
return ''
|
33
|
+
end
|
34
|
+
end
|
20
35
|
def +(body_data)
|
21
36
|
self.push(body_data)
|
22
37
|
end
|
@@ -33,10 +48,21 @@ module RSence
|
|
33
48
|
end
|
34
49
|
def body=(body_data)
|
35
50
|
@body = ResponseBody.new(1)
|
36
|
-
@body[0] = body_data
|
51
|
+
@body[0] = @body.sanitize_body_data( body_data )
|
37
52
|
end
|
38
53
|
def body
|
39
|
-
@body
|
54
|
+
@body
|
55
|
+
end
|
56
|
+
def body_bytes
|
57
|
+
bytes = 0
|
58
|
+
@body.each do |part|
|
59
|
+
if part.respond_to?(:to_s)
|
60
|
+
bytes += part.to_s.bytesize
|
61
|
+
else
|
62
|
+
warn "body data part does not respond to to_s: #{part.inspect[0..100]}"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
return bytes.to_s
|
40
66
|
end
|
41
67
|
def content_type=(new_content_type)
|
42
68
|
@header['Content-Type'] = new_content_type
|
data/lib/session/msg.rb
CHANGED
@@ -111,7 +111,11 @@ module RSence
|
|
111
111
|
@options = options
|
112
112
|
|
113
113
|
# Value response output.
|
114
|
-
@value_buffer =
|
114
|
+
@value_buffer = {
|
115
|
+
:new => [],
|
116
|
+
:set => [],
|
117
|
+
:del => []
|
118
|
+
}
|
115
119
|
|
116
120
|
# The session key placeholder.
|
117
121
|
@ses_key = false
|
@@ -131,7 +135,7 @@ module RSence
|
|
131
135
|
if options[:servlet]
|
132
136
|
@do_gzip = false
|
133
137
|
else
|
134
|
-
@response
|
138
|
+
@response['Content-Type'] = 'text/javascript; charset=utf-8'
|
135
139
|
@response['Cache-Control'] = 'no-cache'
|
136
140
|
|
137
141
|
# gnu-zipped responses:
|
@@ -238,21 +242,22 @@ module RSence
|
|
238
242
|
if not @response_success
|
239
243
|
@response.status = 200
|
240
244
|
#@response.status = 503
|
241
|
-
|
245
|
+
|
242
246
|
buffer = [
|
243
|
-
"" # empty session key will stop the syncing
|
247
|
+
"", # empty session key will stop the syncing
|
248
|
+
{}, # no session values
|
244
249
|
] + @error_js
|
245
250
|
else
|
246
251
|
## The response status should always be 200 (OK)
|
247
252
|
@response.status = 200
|
248
|
-
|
249
|
-
buffer =
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
253
|
+
|
254
|
+
buffer = [
|
255
|
+
@ses_key,
|
256
|
+
@value_buffer,
|
257
|
+
] + @buffer
|
258
|
+
|
254
259
|
end
|
255
|
-
|
260
|
+
|
256
261
|
# flush the output
|
257
262
|
if @do_gzip
|
258
263
|
outp = GZString.new('')
|
@@ -262,13 +267,13 @@ module RSence
|
|
262
267
|
else
|
263
268
|
outp = buf_json(buffer)
|
264
269
|
end
|
265
|
-
|
266
|
-
@response['
|
270
|
+
|
271
|
+
@response['Content-Length'] = outp.bytesize.to_s
|
267
272
|
@response.body = outp
|
268
|
-
|
273
|
+
|
269
274
|
@response_sent = true
|
270
275
|
end
|
271
|
-
|
276
|
+
|
272
277
|
# Sends data to the client, usually javascript, but is valid for any data that responds to #to_json
|
273
278
|
# @param [String<js>, #to_json] data Javascript source or object that responds to #to_json
|
274
279
|
# @param [Boolean] dont_squeeze When true, doesn't `squeeze` the contents (jsmin + jscompress)
|
@@ -280,9 +285,16 @@ module RSence
|
|
280
285
|
end
|
281
286
|
|
282
287
|
# @private For value manager; insert changed values BEFORE other js.
|
283
|
-
def reply_value(data)
|
284
|
-
|
285
|
-
|
288
|
+
def reply_value( operation_type, value_id, data=nil )
|
289
|
+
if operation_type == :set
|
290
|
+
@value_buffer[:set].push( [ value_id, data ] )
|
291
|
+
elsif operation_type == :new
|
292
|
+
@value_buffer[:new].push( [ value_id, data ] )
|
293
|
+
elsif operation_type == :del
|
294
|
+
@value_buffer[:del].push( value_id )
|
295
|
+
else
|
296
|
+
throw "Invalid reply_value operation: operation_type: #{operation_type.inspect}, value_id: #{value_id.inspect}, data: #{data.inspect}"
|
297
|
+
end
|
286
298
|
end
|
287
299
|
|
288
300
|
# Sends data to the client's javascript console.
|
@@ -229,6 +229,10 @@ module RSence
|
|
229
229
|
end
|
230
230
|
|
231
231
|
elsif msg.refresh_page?( @plugins.incr ) and @config[:client_autoreload]
|
232
|
+
while msg.refresh_page?( @plugins.incr )
|
233
|
+
msg.session[:plugin_incr] == @plugins.incr
|
234
|
+
sleep 0.5
|
235
|
+
end
|
232
236
|
# Forces the client to reload, if plugins are incremented
|
233
237
|
msg.reply("window.location.reload( true );")
|
234
238
|
end
|
data/lib/values/hvalue.rb
CHANGED
@@ -84,7 +84,7 @@ module RSence
|
|
84
84
|
if RSence.args[:debug] and meta[:name] and not msg.valuemanager.id_exists?( msg, meta[:name] )
|
85
85
|
@value_id = meta[:name]
|
86
86
|
else
|
87
|
-
@value_id
|
87
|
+
@value_id = msg.valuemanager.ses_unique_id( msg )
|
88
88
|
end
|
89
89
|
|
90
90
|
@meta = meta
|
@@ -245,12 +245,11 @@ module RSence
|
|
245
245
|
def to_client( msg )
|
246
246
|
if @is_new_to_client
|
247
247
|
## Initialize a new client value
|
248
|
-
|
249
|
-
msg.reply_value( init_str )
|
248
|
+
msg.reply_value( :new, @value_id, @data )
|
250
249
|
@is_new_to_client = false
|
251
250
|
else
|
252
251
|
## Sets the client value
|
253
|
-
msg.reply_value
|
252
|
+
msg.reply_value( :set, @value_id, @data )
|
254
253
|
end
|
255
254
|
end
|
256
255
|
|
@@ -267,142 +266,13 @@ module RSence
|
|
267
266
|
session_values.delete( @value_id )
|
268
267
|
|
269
268
|
if msg and not @is_new_to_client
|
270
|
-
msg.reply_value(
|
269
|
+
msg.reply_value( :del, @value_id )
|
271
270
|
end
|
272
271
|
end
|
273
272
|
alias die die!
|
274
273
|
|
275
274
|
end
|
276
275
|
|
277
|
-
|
278
|
-
=begin
|
279
|
-
class UploadValue < HValue
|
280
|
-
|
281
|
-
@state_responders = {
|
282
|
-
:ready => [], # id == 0
|
283
|
-
:started => [], # id == 1
|
284
|
-
:process => [], # id == 2 ; also uses bind
|
285
|
-
3 => [], # id == 3
|
286
|
-
4 => [], # id == 4
|
287
|
-
:error => [] # id < 0
|
288
|
-
}
|
289
|
-
|
290
|
-
@upload_state = 0
|
291
|
-
@upload_key = ''
|
292
|
-
@uploads = []
|
293
|
-
|
294
|
-
# the data should contain both state and key in the value
|
295
|
-
def from_client( msg, data )
|
296
|
-
|
297
|
-
## change the valid state, because the value was set by the client!
|
298
|
-
@is_valid = data.include?(':::')
|
299
|
-
|
300
|
-
# the state and key are separated by the ':::' delimiter string
|
301
|
-
if @is_valid
|
302
|
-
|
303
|
-
# split state and key using the delimiter
|
304
|
-
(upload_state, upload_key) = data.split(':::')
|
305
|
-
|
306
|
-
# the state is a number
|
307
|
-
upload_state = upload_state.to_i
|
308
|
-
|
309
|
-
@upload_state = upload_state
|
310
|
-
@upload_key = upload_key
|
311
|
-
|
312
|
-
# negative states are errors
|
313
|
-
if upload_state < 0
|
314
|
-
# "upload error: #{upload_state}"
|
315
|
-
# (parse the error)
|
316
|
-
unless @state_responders[:error].empty?
|
317
|
-
@state_responders[:error].each do |plugin_name,method_name|
|
318
|
-
msg.run( plugin_name,method_name,msg,self,upload_state )
|
319
|
-
end
|
320
|
-
end
|
321
|
-
|
322
|
-
# the default state, 0 means the UI is ready to send an
|
323
|
-
# upload and ticketserve is ready to receive it
|
324
|
-
elsif upload_state == 0
|
325
|
-
# "upload state: ready to upload."
|
326
|
-
# (do nothing)
|
327
|
-
|
328
|
-
unless @state_responders[:ready].empty?
|
329
|
-
@state_responders[:ready].each do |plugin_name,method_name|
|
330
|
-
msg.run( plugin_name,method_name,msg,self,upload_state )
|
331
|
-
end
|
332
|
-
end
|
333
|
-
|
334
|
-
# this state means the upload's transfer is started and progressing
|
335
|
-
elsif upload_state == 1
|
336
|
-
# "upload state: upload started."
|
337
|
-
# (show progress bar)
|
338
|
-
|
339
|
-
unless @state_responders[:started].empty?
|
340
|
-
@state_responders[:started].each do |plugin_name,method_name|
|
341
|
-
msg.run( plugin_name,method_name,msg,self,upload_state )
|
342
|
-
end
|
343
|
-
end
|
344
|
-
|
345
|
-
# this state means the upload's transfer is complete,
|
346
|
-
# but the uploaded data hasn't been handled yet.
|
347
|
-
elsif upload_state == 2
|
348
|
-
# "upload state: waiting to process."
|
349
|
-
|
350
|
-
uploads = msg.plugins[:ticketservices].get_uploads(upload_key,true)
|
351
|
-
if uploads.size == 1
|
352
|
-
uploaded_data = uploads[0]
|
353
|
-
|
354
|
-
# only process changes, if different from the one already stored.
|
355
|
-
if uploaded_data != @data
|
356
|
-
|
357
|
-
@data = uploaded_data
|
358
|
-
|
359
|
-
## add the id to the values to be checked
|
360
|
-
check_ids = msg.session[:values][:check]
|
361
|
-
unless check_ids.include?( @value_id )
|
362
|
-
check_ids.push( @value_id )
|
363
|
-
end
|
364
|
-
|
365
|
-
end
|
366
|
-
msg.plugins[:ticketservices].del_uploads(upload_key,msg.ses_id)
|
367
|
-
else
|
368
|
-
# "upload, amount of uploads: #{uploads.size}"
|
369
|
-
end
|
370
|
-
|
371
|
-
#
|
372
|
-
hvalue.set(msg,"3:::#{upload_key}")
|
373
|
-
|
374
|
-
msg.console( "upload state: set to ack" )
|
375
|
-
|
376
|
-
elsif upload_state == 3
|
377
|
-
# "upload state: waiting for user ack."
|
378
|
-
# (do nothing)
|
379
|
-
|
380
|
-
msg.console( "upload state: waiting user ack" )
|
381
|
-
|
382
|
-
|
383
|
-
elsif upload_state == 4
|
384
|
-
# "upload state: user wants to upload again."
|
385
|
-
# (set a new upload key, )
|
386
|
-
|
387
|
-
msg.console( "upload state: ack, getting new key" )
|
388
|
-
|
389
|
-
|
390
|
-
setup_upload( msg, hvalue )
|
391
|
-
|
392
|
-
|
393
|
-
else
|
394
|
-
# "upload unknown state: #{upload_state.inspect}"
|
395
|
-
end
|
396
|
-
end
|
397
|
-
return true
|
398
|
-
end
|
399
|
-
def setup_upload(msg,hvalue,size_bytes=500*1024,accept_mime=/image\/(.*?)/,allow_multi=false)
|
400
|
-
upload_key = msg.plugins[:ticketservices].upload_key(msg,hvalue.val_id,size_bytes,accept_mime,allow_multi)
|
401
|
-
hvalue.set( msg, upload_key )
|
402
|
-
end
|
403
|
-
end
|
404
|
-
=end
|
405
|
-
|
406
276
|
end
|
407
277
|
|
408
278
|
|
data/lib/values/valuemanager.rb
CHANGED
@@ -35,6 +35,40 @@ module RSence
|
|
35
35
|
|
36
36
|
end
|
37
37
|
|
38
|
+
|
39
|
+
# @private Returns a session-unique random string
|
40
|
+
def ses_unique_id( msg )
|
41
|
+
new_id = randgen.gen while id_exists?( msg, new_id )
|
42
|
+
return new_id
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
# @private Regenerate a value id
|
47
|
+
def reshuffle_id( msg, ses_values, val_obj, old_id )
|
48
|
+
|
49
|
+
new_id = ses_unique_id( msg )
|
50
|
+
|
51
|
+
# replace the old id in the hvalue itself
|
52
|
+
val_obj.val_id = new_id
|
53
|
+
|
54
|
+
# re-associate the value with the new id
|
55
|
+
ses_values[:by_id][new_id] = val_obj
|
56
|
+
ses_values[:by_id].delete(old_id)
|
57
|
+
|
58
|
+
# replace the id in the unvalidated values (:check) array
|
59
|
+
if ses_values[:check].include?(old_id)
|
60
|
+
old_idx = ses_values[:check].index(old_id)
|
61
|
+
ses_values[:check][old_idx] = new_id
|
62
|
+
end
|
63
|
+
|
64
|
+
# replace the id in the unsynchronized values (:sync) array
|
65
|
+
if ses_values[:sync].include?(old_id)
|
66
|
+
old_idx = ses_values[:sync].index(old_id)
|
67
|
+
ses_values[:sync][old_idx] = new_id
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
|
38
72
|
# @private Re-constructs all stored values and sends them to the client.
|
39
73
|
# Used for restoring and cloning session values.
|
40
74
|
def resend_session_values( msg )
|
@@ -56,28 +90,7 @@ module RSence
|
|
56
90
|
|
57
91
|
# make a new id
|
58
92
|
unless RSence.args[:debug] and val_obj.meta[:name]
|
59
|
-
|
60
|
-
new_id = @randgen.gen while id_exists?( msg, new_id )
|
61
|
-
|
62
|
-
# replace the old id in the hvalue itself
|
63
|
-
val_obj.val_id = new_id
|
64
|
-
|
65
|
-
# re-associate the value with the new id
|
66
|
-
ses_values[:by_id][new_id] = val_obj
|
67
|
-
ses_values[:by_id].delete(old_id)
|
68
|
-
|
69
|
-
# replace the id in the unvalidated values (:check) array
|
70
|
-
if ses_values[:check].include?(old_id)
|
71
|
-
old_idx = ses_values[:check].index(old_id)
|
72
|
-
ses_values[:check][old_idx] = new_id
|
73
|
-
end
|
74
|
-
|
75
|
-
# replace the id in the unsynchronized values (:sync) array
|
76
|
-
if ses_values[:sync].include?(old_id)
|
77
|
-
old_idx = ses_values[:sync].index(old_id)
|
78
|
-
ses_values[:sync][old_idx] = new_id
|
79
|
-
end
|
80
|
-
|
93
|
+
reshuffle_id( msg, ses_values, val_obj, old_id )
|
81
94
|
end
|
82
95
|
|
83
96
|
# tell the hvalue to send its client-side initialization
|
@@ -96,6 +109,7 @@ module RSence
|
|
96
109
|
|
97
110
|
# @private Verifies new_id is unique.
|
98
111
|
def id_exists?( msg, new_id )
|
112
|
+
return true unless new_id.class == String
|
99
113
|
return msg.session[:values][:by_id].has_key?(new_id)
|
100
114
|
end
|
101
115
|
|