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.
Files changed (43) hide show
  1. data/INSTALL.rdoc +61 -46
  2. data/README.rdoc +17 -1
  3. data/VERSION +1 -1
  4. data/conf/rsence_command_strings.yaml +16 -16
  5. data/js/comm/sessionwatcher/sessionwatcher.js +5 -4
  6. data/js/comm/transporter/transporter.js +62 -4
  7. data/js/comm/values/values.js +62 -0
  8. data/js/controls/button/themes/default/button.css +7 -7
  9. data/js/controls/imageview/imageview.js +15 -6
  10. data/js/controls/stringview/stringview.js +16 -2
  11. data/js/controls/textcontrol/textcontrol.js +56 -3
  12. data/js/core/elem/elem.js +38 -12
  13. data/js/datetime/timesheet/timesheet.js +141 -32
  14. data/js/datetime/timesheet_item/timesheet_item.js +82 -22
  15. data/js/foundation/application/application.js +10 -4
  16. data/js/foundation/control/control.js +5 -3
  17. data/js/foundation/control/dyncontrol/dyncontrol.js +17 -3
  18. data/js/foundation/control/eventresponder/eventresponder.js +31 -2
  19. data/js/foundation/eventmanager/eventmanager.js +202 -74
  20. data/js/foundation/json_renderer/json_renderer.js +5 -2
  21. data/js/foundation/system/system.js +13 -11
  22. data/js/foundation/view/morphanimation/morphanimation.js +9 -5
  23. data/js/foundation/view/view.js +22 -10
  24. data/js/lists/propertylist/propertylist.js +5 -0
  25. data/js/menus/minimenu/minimenu.js +3 -8
  26. data/lib/conf/default.rb +0 -3
  27. data/lib/http/broker.rb +6 -5
  28. data/lib/http/rackup.rb +3 -3
  29. data/lib/http/response.rb +28 -2
  30. data/lib/session/msg.rb +30 -18
  31. data/lib/transporter/transporter.rb +4 -0
  32. data/lib/values/hvalue.rb +4 -134
  33. data/lib/values/valuemanager.rb +36 -22
  34. data/plugins/client_pkg/lib/client_pkg_serve.rb +195 -152
  35. data/plugins/main/main.rb +8 -10
  36. data/plugins/ticket/lib/common.rb +4 -4
  37. data/plugins/ticket/lib/favicon.rb +1 -1
  38. data/plugins/ticket/lib/rsrc.rb +1 -1
  39. data/plugins/ticket/lib/upload.rb +2 -2
  40. data/plugins/ticket/ticket.rb +3 -3
  41. data/setup/welcome/gui/welcome.yaml +1 -1
  42. metadata +10 -11
  43. data/lib/util/ruby19_fixes.rb +0 -18
data/lib/conf/default.rb CHANGED
@@ -13,9 +13,6 @@ require 'yaml'
13
13
 
14
14
 
15
15
 
16
- require 'util/ruby19_fixes' if RUBY_VERSION.to_f >= 1.9
17
-
18
-
19
16
  module RSence
20
17
 
21
18
 
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, String)] Rack-style response status, header, body
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
- response.header['Content-Length'] = response.body.length.to_s unless response.header.has_key?('Content-Length')
47
- return [response.status, response.header, response.body]
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.length.to_s
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.length.to_s unless response.header.has_key?('Content-Length')
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['content-type'] = 'text/html; charset=UTF-8'
86
- response['content-length'] = err404.length.to_s
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.join
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.content_type = 'text/javascript; charset=utf-8'
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 = @value_buffer + @buffer
250
- if @ses_key
251
- buffer.unshift( @ses_key )
252
- end
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['content-length'] = outp.size
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
- puts data if @config[:trace]
285
- @value_buffer.push( data )
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 = msg.valuemanager.randgen.gen
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
- init_str = "COMM.Values.create(#{@value_id.to_json},#{@data.to_json});"
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 "HVM.s(#{@value_id.to_json},#{@data.to_json});"
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("HVM.del(#{@value_id.to_json});")
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
 
@@ -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
- new_id = @randgen.gen
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