rsence-pre 2.1.0.21 → 2.1.8.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.
- 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
|
|