rsence 2.0.0.0.pre
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 +295 -0
- data/LICENSE +622 -0
- data/README.rdoc +24 -0
- data/VERSION +1 -0
- data/bin/build_client.rb +254 -0
- data/bin/help +6 -0
- data/bin/launch.rb +120 -0
- data/bin/rdoc.sh +2 -0
- data/bin/restart +6 -0
- data/bin/rsence +120 -0
- data/bin/run +6 -0
- data/bin/run.rb +6 -0
- data/bin/save +6 -0
- data/bin/start +6 -0
- data/bin/status +6 -0
- data/bin/stop +6 -0
- data/conf/config.ru +5 -0
- data/conf/default_conf.yaml +337 -0
- data/conf/default_strings.yaml +77 -0
- data/conf/local_conf.yaml +14 -0
- data/conf/unicorn.conf +78 -0
- data/js/comm/comm/autosync/autosync.js +18 -0
- data/js/comm/comm/autosync/js.inc +0 -0
- data/js/comm/comm/comm.js +195 -0
- data/js/comm/comm/js.inc +0 -0
- data/js/comm/comm/queue/js.inc +0 -0
- data/js/comm/comm/queue/queue.js +183 -0
- data/js/comm/comm/session/js.inc +0 -0
- data/js/comm/comm/session/session.js +51 -0
- data/js/comm/comm/sessionwatcher/js.inc +0 -0
- data/js/comm/comm/sessionwatcher/sessionwatcher.js +43 -0
- data/js/comm/comm/transporter/js.inc +0 -0
- data/js/comm/comm/transporter/transporter.js +257 -0
- data/js/comm/comm/urlresponder/js.inc +0 -0
- data/js/comm/comm/urlresponder/urlresponder.js +148 -0
- data/js/comm/comm/values/js.inc +0 -0
- data/js/comm/comm/values/values.js +432 -0
- data/js/comm/jsloader/js.inc +0 -0
- data/js/comm/jsloader/jsloader.js +114 -0
- data/js/comm/reloadapp/js.inc +0 -0
- data/js/comm/reloadapp/reloadapp.js +150 -0
- data/js/comm/reloadapp/themes/default/reloadapp_warning-ie6.gif +0 -0
- data/js/comm/reloadapp/themes/default/reloadapp_warning.png +0 -0
- data/js/comm/sha/js.inc +0 -0
- data/js/comm/sha/sha.js +432 -0
- data/js/comm/values/value/js.inc +0 -0
- data/js/comm/values/value/value.js +182 -0
- data/js/comm/values/valuematrix/js.inc +0 -0
- data/js/comm/values/valuematrix/valuematrix.js +138 -0
- data/js/controls/button/button.js +57 -0
- data/js/controls/button/js.inc +0 -0
- data/js/controls/button/themes/bright/button.css +89 -0
- data/js/controls/button/themes/bright/button.html +7 -0
- data/js/controls/button/themes/bright/button_parts1-ie6.gif +0 -0
- data/js/controls/button/themes/bright/button_parts1.png +0 -0
- data/js/controls/button/themes/default/button.css +89 -0
- data/js/controls/button/themes/default/button.html +7 -0
- data/js/controls/button/themes/default/button_parts1-ie6.gif +0 -0
- data/js/controls/button/themes/default/button_parts1.png +0 -0
- data/js/controls/checkbox/checkbox.js +47 -0
- data/js/controls/checkbox/js.inc +0 -0
- data/js/controls/checkbox/themes/default/checkbox.css +69 -0
- data/js/controls/checkbox/themes/default/checkbox.html +5 -0
- data/js/controls/checkbox/themes/default/checkbox_parts1-ie6.gif +0 -0
- data/js/controls/checkbox/themes/default/checkbox_parts1.png +0 -0
- data/js/controls/datetime/calendar/calendar.js +197 -0
- data/js/controls/datetime/calendar/js.inc +0 -0
- data/js/controls/datetime/calendar/themes/default/calendar.css +108 -0
- data/js/controls/datetime/calendar/themes/default/calendar.html +9 -0
- data/js/controls/datetime/calendar/themes/default/calendar_arrows-ie6.gif +0 -0
- data/js/controls/datetime/calendar/themes/default/calendar_arrows.png +0 -0
- data/js/controls/datetime/datetimevalue/datetimevalue.js +246 -0
- data/js/controls/datetime/datetimevalue/js.inc +0 -0
- data/js/controls/datetime/timesheet/js.inc +0 -0
- data/js/controls/datetime/timesheet/themes/default/timesheet.css +30 -0
- data/js/controls/datetime/timesheet/themes/default/timesheet.html +2 -0
- data/js/controls/datetime/timesheet/timesheet.js +182 -0
- data/js/controls/datetime/timesheet_item/js.inc +0 -0
- data/js/controls/datetime/timesheet_item/themes/default/timesheet_item.css +42 -0
- data/js/controls/datetime/timesheet_item/themes/default/timesheet_item.html +8 -0
- data/js/controls/datetime/timesheet_item/timesheet_item.js +247 -0
- data/js/controls/datetime/timesheet_item_edit/js.inc +0 -0
- data/js/controls/datetime/timesheet_item_edit/timesheet_item_edit.js +274 -0
- data/js/controls/dialogs/alert_sheet/alert_sheet.js +62 -0
- data/js/controls/dialogs/alert_sheet/js.inc +0 -0
- data/js/controls/dialogs/confirm_sheet/confirm_sheet.js +36 -0
- data/js/controls/dialogs/confirm_sheet/js.inc +0 -0
- data/js/controls/dialogs/sheet/js.inc +0 -0
- data/js/controls/dialogs/sheet/sheet.js +83 -0
- data/js/controls/dialogs/sheet/themes/default/sheet.css +64 -0
- data/js/controls/dialogs/sheet/themes/default/sheet.html +14 -0
- data/js/controls/dialogs/sheet/themes/default/sheet_bg-ie6.gif +0 -0
- data/js/controls/dialogs/sheet/themes/default/sheet_bg.png +0 -0
- data/js/controls/dialogs/sheet/themes/default/sheet_dim-ie6.gif +0 -0
- data/js/controls/dialogs/sheet/themes/default/sheet_dim.png +0 -0
- data/js/controls/dialogs/sheet/themes/default/sheet_parts1-ie6.gif +0 -0
- data/js/controls/dialogs/sheet/themes/default/sheet_parts1.png +0 -0
- data/js/controls/dialogs/sheet/themes/default/sheet_parts2-ie6.gif +0 -0
- data/js/controls/dialogs/sheet/themes/default/sheet_parts2.png +0 -0
- data/js/controls/dialogs/sheet/themes/default/sheet_warning-ie6.gif +0 -0
- data/js/controls/dialogs/sheet/themes/default/sheet_warning.png +0 -0
- data/js/controls/imageview/imageview.js +108 -0
- data/js/controls/imageview/js.inc +0 -0
- data/js/controls/imageview/themes/default/blank.gif +0 -0
- data/js/controls/lists/checkboxlist/checkboxlist.js +170 -0
- data/js/controls/lists/checkboxlist/js.inc +0 -0
- data/js/controls/lists/listitems/js.inc +0 -0
- data/js/controls/lists/listitems/listitems.js +65 -0
- data/js/controls/lists/radiobuttonlist/js.inc +0 -0
- data/js/controls/lists/radiobuttonlist/radiobuttonlist.js +126 -0
- data/js/controls/passwordcontrol/js.inc +0 -0
- data/js/controls/passwordcontrol/passwordcontrol.js +22 -0
- data/js/controls/passwordcontrol/themes/default/passwordcontrol.css +0 -0
- data/js/controls/passwordcontrol/themes/default/passwordcontrol.html +18 -0
- data/js/controls/progress/progressbar/js.inc +0 -0
- data/js/controls/progress/progressbar/progressbar.js +36 -0
- data/js/controls/progress/progressbar/themes/default/progressbar.css +16 -0
- data/js/controls/progress/progressbar/themes/default/progressbar.html +2 -0
- data/js/controls/progress/progressindicator/js.inc +0 -0
- data/js/controls/progress/progressindicator/progressindicator.js +43 -0
- data/js/controls/radiobutton/js.inc +0 -0
- data/js/controls/radiobutton/radiobutton.js +41 -0
- data/js/controls/radiobutton/themes/default/radiobutton.css +69 -0
- data/js/controls/radiobutton/themes/default/radiobutton.html +5 -0
- data/js/controls/radiobutton/themes/default/radiobutton_parts1-ie6.gif +0 -0
- data/js/controls/radiobutton/themes/default/radiobutton_parts1.png +0 -0
- data/js/controls/sliders/slider/js.inc +0 -0
- data/js/controls/sliders/slider/slider.js +356 -0
- data/js/controls/sliders/slider/themes/default/hslider_tracks-ie6.gif +0 -0
- data/js/controls/sliders/slider/themes/default/hslider_tracks.png +0 -0
- data/js/controls/sliders/slider/themes/default/slider.css +108 -0
- data/js/controls/sliders/slider/themes/default/slider.html +5 -0
- data/js/controls/sliders/slider/themes/default/slider_thumbs-ie6.gif +0 -0
- data/js/controls/sliders/slider/themes/default/slider_thumbs.png +0 -0
- data/js/controls/sliders/vslider/js.inc +0 -0
- data/js/controls/sliders/vslider/themes/default/vslider.css +52 -0
- data/js/controls/sliders/vslider/themes/default/vslider.html +5 -0
- data/js/controls/sliders/vslider/themes/default/vslider_tracks-ie6.gif +0 -0
- data/js/controls/sliders/vslider/themes/default/vslider_tracks.png +0 -0
- data/js/controls/sliders/vslider/vslider.js +40 -0
- data/js/controls/stepper/js.inc +0 -0
- data/js/controls/stepper/stepper.js +212 -0
- data/js/controls/stepper/themes/default/stepper-ie6.gif +0 -0
- data/js/controls/stepper/themes/default/stepper.css +14 -0
- data/js/controls/stepper/themes/default/stepper.html +2 -0
- data/js/controls/stepper/themes/default/stepper.png +0 -0
- data/js/controls/stringview/js.inc +0 -0
- data/js/controls/stringview/stringview.js +49 -0
- data/js/controls/stringview/themes/default/stringview.css +8 -0
- data/js/controls/stringview/themes/default/stringview.html +1 -0
- data/js/controls/tab/js.inc +0 -0
- data/js/controls/tab/tab.js +276 -0
- data/js/controls/tab/themes/bright/tab.css +76 -0
- data/js/controls/tab/themes/bright/tab.html +6 -0
- data/js/controls/tab/themes/bright/tab_bg_color-ie6.gif +0 -0
- data/js/controls/tab/themes/bright/tab_bg_color.png +0 -0
- data/js/controls/tab/themes/bright/tab_border_pattern-ie6.gif +0 -0
- data/js/controls/tab/themes/bright/tab_border_pattern.png +0 -0
- data/js/controls/tab/themes/bright/tab_parts1-ie6.gif +0 -0
- data/js/controls/tab/themes/bright/tab_parts1.png +0 -0
- data/js/controls/tab/themes/default/tab.css +77 -0
- data/js/controls/tab/themes/default/tab.html +6 -0
- data/js/controls/tab/themes/default/tab_bg_color-ie6.gif +0 -0
- data/js/controls/tab/themes/default/tab_bg_color.png +0 -0
- data/js/controls/tab/themes/default/tab_border_pattern-ie6.gif +0 -0
- data/js/controls/tab/themes/default/tab_border_pattern.png +0 -0
- data/js/controls/tab/themes/default/tab_parts1-ie6.gif +0 -0
- data/js/controls/tab/themes/default/tab_parts1.png +0 -0
- data/js/controls/textarea/js.inc +0 -0
- data/js/controls/textarea/textarea.js +23 -0
- data/js/controls/textarea/themes/default/textarea.css +21 -0
- data/js/controls/textarea/themes/default/textarea.html +18 -0
- data/js/controls/textcontrol/js.inc +0 -0
- data/js/controls/textcontrol/textcontrol.js +372 -0
- data/js/controls/textcontrol/themes/default/textcontrol.css +107 -0
- data/js/controls/textcontrol/themes/default/textcontrol.html +18 -0
- data/js/controls/textcontrol/themes/default/textcontrol_parts1-ie6.gif +0 -0
- data/js/controls/textcontrol/themes/default/textcontrol_parts1.png +0 -0
- data/js/controls/textcontrol/themes/default/textcontrol_parts2-ie6.gif +0 -0
- data/js/controls/textcontrol/themes/default/textcontrol_parts2.png +0 -0
- data/js/controls/textcontrol/themes/default/textcontrol_parts3-ie6.gif +0 -0
- data/js/controls/textcontrol/themes/default/textcontrol_parts3.png +0 -0
- data/js/controls/uploader/js.inc +0 -0
- data/js/controls/uploader/themes/default/upload_progress.gif +0 -0
- data/js/controls/uploader/themes/default/uploader.css +108 -0
- data/js/controls/uploader/themes/default/uploader.html +27 -0
- data/js/controls/uploader/uploader.js +153 -0
- data/js/controls/validatorview/js.inc +0 -0
- data/js/controls/validatorview/themes/default/validator-ie6.gif +0 -0
- data/js/controls/validatorview/themes/default/validator.png +0 -0
- data/js/controls/validatorview/themes/default/validatorview.css +0 -0
- data/js/controls/validatorview/themes/default/validatorview.html +0 -0
- data/js/controls/validatorview/validatorview.js +55 -0
- data/js/controls/window/js.inc +0 -0
- data/js/controls/window/themes/default/window.css +219 -0
- data/js/controls/window/themes/default/window.html +17 -0
- data/js/controls/window/themes/default/window_bg_active-ie6.gif +0 -0
- data/js/controls/window/themes/default/window_bg_active.png +0 -0
- data/js/controls/window/themes/default/window_bg_inactive-ie6.gif +0 -0
- data/js/controls/window/themes/default/window_bg_inactive.png +0 -0
- data/js/controls/window/themes/default/window_buttons-ie6.gif +0 -0
- data/js/controls/window/themes/default/window_buttons.png +0 -0
- data/js/controls/window/themes/default/window_parts1-ie6.gif +0 -0
- data/js/controls/window/themes/default/window_parts1.png +0 -0
- data/js/controls/window/themes/default/window_parts2-ie6.gif +0 -0
- data/js/controls/window/themes/default/window_parts2.png +0 -0
- data/js/controls/window/window.js +284 -0
- data/js/core/class/class.js +317 -0
- data/js/core/class/js.inc +0 -0
- data/js/core/elem/elem.js +1376 -0
- data/js/core/elem/js.inc +0 -0
- data/js/core/event/event.js +1021 -0
- data/js/core/event/js.inc +0 -0
- data/js/core/iefix/ie_css_element.htc +5 -0
- data/js/core/iefix/ie_css_style.htc +5 -0
- data/js/core/iefix/iefix.js +359 -0
- data/js/core/iefix/js.inc +0 -0
- data/js/debugg/debugg.js +43 -0
- data/js/debugg/js.inc +0 -0
- data/js/foundation/application/application.js +209 -0
- data/js/foundation/application/js.inc +0 -0
- data/js/foundation/control/control.js +342 -0
- data/js/foundation/control/controldefaults/controldefaults.js +59 -0
- data/js/foundation/control/controldefaults/js.inc +0 -0
- data/js/foundation/control/dummyvalue/dummyvalue.js +50 -0
- data/js/foundation/control/dummyvalue/js.inc +0 -0
- data/js/foundation/control/dyncontrol/dyncontrol.js +494 -0
- data/js/foundation/control/dyncontrol/js.inc +0 -0
- data/js/foundation/control/dyncontrol/themes/default/dyncontrol.css +0 -0
- data/js/foundation/control/dyncontrol/themes/default/dyncontrol.html +0 -0
- data/js/foundation/control/eventresponder/eventresponder.js +713 -0
- data/js/foundation/control/eventresponder/js.inc +0 -0
- data/js/foundation/control/js.inc +0 -0
- data/js/foundation/control/valueresponder/js.inc +0 -0
- data/js/foundation/control/valueresponder/valueresponder.js +77 -0
- data/js/foundation/geom/point/js.inc +0 -0
- data/js/foundation/geom/point/point.js +202 -0
- data/js/foundation/geom/rect/js.inc +0 -0
- data/js/foundation/geom/rect/rect.js +610 -0
- data/js/foundation/json_renderer/js.inc +0 -0
- data/js/foundation/json_renderer/json_renderer.js +231 -0
- data/js/foundation/system/js.inc +0 -0
- data/js/foundation/system/system.js +369 -0
- data/js/foundation/thememanager/js.inc +0 -0
- data/js/foundation/thememanager/thememanager.js +387 -0
- data/js/foundation/view/js.inc +0 -0
- data/js/foundation/view/markupview/js.inc +0 -0
- data/js/foundation/view/markupview/markupview.js +113 -0
- data/js/foundation/view/morphanimation/js.inc +0 -0
- data/js/foundation/view/morphanimation/morphanimation.js +236 -0
- data/js/foundation/view/view.js +1804 -0
- data/js/foundation/view/viewdefaults/js.inc +0 -0
- data/js/foundation/view/viewdefaults/viewdefaults.js +25 -0
- data/js/views/centerview/centerview.js +45 -0
- data/js/views/centerview/js.inc +0 -0
- data/js/views/inlineview/inlineview.js +14 -0
- data/js/views/inlineview/js.inc +0 -0
- data/js/views/scrollview/js.inc +0 -0
- data/js/views/scrollview/scrollview.js +39 -0
- data/lib/conf/default.rb +220 -0
- data/lib/conf/wizard.rb +303 -0
- data/lib/daemon/daemon.rb +293 -0
- data/lib/http/broker.rb +102 -0
- data/lib/http/rackup.rb +88 -0
- data/lib/http/request.rb +69 -0
- data/lib/http/response.rb +63 -0
- data/lib/plugins/gui_plugin.rb +129 -0
- data/lib/plugins/guiparser.rb +114 -0
- data/lib/plugins/plugin.rb +652 -0
- data/lib/plugins/plugin_plugins.rb +47 -0
- data/lib/plugins/plugin_sqlite_db.rb +72 -0
- data/lib/plugins/plugin_util.rb +96 -0
- data/lib/plugins/pluginmanager.rb +517 -0
- data/lib/plugins/servlet.rb +69 -0
- data/lib/session/msg.rb +291 -0
- data/lib/session/sessionmanager.rb +491 -0
- data/lib/session/sessionstorage.rb +314 -0
- data/lib/transporter/transporter.rb +254 -0
- data/lib/util/gzstring.rb +5 -0
- data/lib/values/hvalue.rb +323 -0
- data/lib/values/valuemanager.rb +152 -0
- data/plugins/client_pkg/client_pkg.rb +186 -0
- data/plugins/client_pkg/info.yaml +25 -0
- data/plugins/client_pkg/lib/client_pkg_build.rb +569 -0
- data/plugins/client_pkg/lib/client_pkg_cache.rb +50 -0
- data/plugins/client_pkg/lib/client_pkg_serve.rb +210 -0
- data/plugins/client_pkg/log/build_log +0 -0
- data/plugins/index_html/img/loading.gif +0 -0
- data/plugins/index_html/img/riassence.gif +0 -0
- data/plugins/index_html/index_html.rb +150 -0
- data/plugins/index_html/tmpl/index.html +22 -0
- data/plugins/index_html/tmpl/startup_index.html +29 -0
- data/plugins/legacy/disabled +0 -0
- data/plugins/legacy/disabled- +0 -0
- data/plugins/legacy/info.yaml +22 -0
- data/plugins/legacy/legacy.rb +15 -0
- data/plugins/main/js/riassence_ns.js +87 -0
- data/plugins/main/main.rb +234 -0
- data/plugins/main/values.yaml +8 -0
- data/plugins/ticketservices/lib/common.rb +300 -0
- data/plugins/ticketservices/lib/favicon.rb +38 -0
- data/plugins/ticketservices/lib/file.rb +58 -0
- data/plugins/ticketservices/lib/img.rb +50 -0
- data/plugins/ticketservices/lib/objblob.rb +66 -0
- data/plugins/ticketservices/lib/rsrc.rb +34 -0
- data/plugins/ticketservices/lib/upload.rb +206 -0
- data/plugins/ticketservices/ticketservices.rb +268 -0
- data/var/db/.git_include +0 -0
- data/var/log/.git_include +0 -0
- data/var/run/.git_include +0 -0
- metadata +390 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
## Riassence Framework
|
|
2
|
+
# Copyright 2009 Riassence Inc.
|
|
3
|
+
# http://riassence.com/
|
|
4
|
+
#
|
|
5
|
+
# You should have received a copy of the GNU General Public License along
|
|
6
|
+
# with this software package. If not, contact licensing@riassence.com
|
|
7
|
+
##
|
|
8
|
+
|
|
9
|
+
## Register the ServletPlugin with a regular expression that
|
|
10
|
+
## should match its uri. Alternatively just a string, but
|
|
11
|
+
## that needs to be an exact match.
|
|
12
|
+
## servlet_plug = ServletPlugin.new
|
|
13
|
+
## servlet_plug.register_get( /\/about\/.*/ )
|
|
14
|
+
## servlet_plug.register_post( '/mailsender' )
|
|
15
|
+
## servlet_plug.register( /\/feedback\/.*/ )
|
|
16
|
+
class Servlet
|
|
17
|
+
|
|
18
|
+
include PluginUtil
|
|
19
|
+
|
|
20
|
+
# Initializes and registers the ServletPlugin.
|
|
21
|
+
def initialize( name = false )
|
|
22
|
+
@info = @@bundle_info
|
|
23
|
+
if name
|
|
24
|
+
@name = name
|
|
25
|
+
else
|
|
26
|
+
@name = @@bundle_name
|
|
27
|
+
end
|
|
28
|
+
@path = @@bundle_path
|
|
29
|
+
@plugins = @@plugin_manager
|
|
30
|
+
register
|
|
31
|
+
@inited = false
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Servlet ID
|
|
35
|
+
attr_reader :name, :path, :info, :inited
|
|
36
|
+
def register # :nodoc
|
|
37
|
+
@plugins.register_bundle( self, @name )
|
|
38
|
+
@inited = true
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
## Extendables
|
|
42
|
+
|
|
43
|
+
# Return true to match, false to not match. Returns false as default if
|
|
44
|
+
# not extended.
|
|
45
|
+
def match( uri, request_type=:get )
|
|
46
|
+
return false
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# If match, return score (lower is better). Returns 100 by defalt if not
|
|
50
|
+
# extended
|
|
51
|
+
def score
|
|
52
|
+
return 100
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Extend to do any GET request processing. Not doing anything by default.
|
|
56
|
+
def get( req, res, ses )
|
|
57
|
+
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Extend to do any POST request processing. Not doing anything by default.
|
|
61
|
+
def post( req, res, ses )
|
|
62
|
+
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
ServletPlugin = Servlet
|
|
68
|
+
|
|
69
|
+
|
data/lib/session/msg.rb
ADDED
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
## Riassence Framework
|
|
2
|
+
# Copyright 2006 Riassence Inc.
|
|
3
|
+
# http://riassence.com/
|
|
4
|
+
#
|
|
5
|
+
# You should have received a copy of the GNU General Public License along
|
|
6
|
+
# with this software package. If not, contact licensing@riassence.com
|
|
7
|
+
##
|
|
8
|
+
|
|
9
|
+
module RSence
|
|
10
|
+
require 'util/gzstring'
|
|
11
|
+
|
|
12
|
+
## Due to the single instance architecture of +Plugin+, instances of Message
|
|
13
|
+
## class are used for communication between sessions and +Plugin+ instance.
|
|
14
|
+
## The +Message+ instance contains session and request-response related
|
|
15
|
+
## mappings and utility methods.
|
|
16
|
+
##
|
|
17
|
+
## The Message object is initialized as 'msg' in SessionManager.
|
|
18
|
+
## It's passed around the system as the user/session -object namespace,
|
|
19
|
+
## much like 'self' is passed around in python methods.
|
|
20
|
+
##
|
|
21
|
+
## Using the msg object saves considerate amounts of CPU cycles and memory,
|
|
22
|
+
## because it allows single instances of any classes that handle user data.
|
|
23
|
+
##
|
|
24
|
+
## == HValue Initialization Example
|
|
25
|
+
## +HValue+ is closely related to +Message+ as instances of +HValue+ are
|
|
26
|
+
## used to send data between sessions and the server. This is a small
|
|
27
|
+
## code snippet about how to initialize several HValues as the session
|
|
28
|
+
## is initialized.
|
|
29
|
+
##
|
|
30
|
+
## def init_ses( msg )
|
|
31
|
+
## msg.session[:session_name] = {
|
|
32
|
+
## :hvalue1 => HValue.new( msg, @firstvalue ),
|
|
33
|
+
## :hvalue2 => HValue.new( msg, @secondvalue ),
|
|
34
|
+
## :hvalue3 => HValue.new( msg, @thirdvalue )
|
|
35
|
+
## }
|
|
36
|
+
## end
|
|
37
|
+
##
|
|
38
|
+
|
|
39
|
+
class Message
|
|
40
|
+
|
|
41
|
+
# Session data placeholder, assigned by SessionManager.
|
|
42
|
+
attr_accessor :session
|
|
43
|
+
|
|
44
|
+
# New session flag, check it in your code to decide
|
|
45
|
+
# what to do, when a new session is encountered.
|
|
46
|
+
# In plugins, this usually means that some Values
|
|
47
|
+
# need to be created and bound or possibly that a
|
|
48
|
+
# user_id mapping needs to be done.
|
|
49
|
+
attr_accessor :new_session
|
|
50
|
+
|
|
51
|
+
# Old session first xhr flag, check it in your code
|
|
52
|
+
# to decide what to do, when a restored session is
|
|
53
|
+
# encountered. The old Values are automatically present,
|
|
54
|
+
# so you should at least not re-create or re-bind them.
|
|
55
|
+
attr_accessor :restored_session
|
|
56
|
+
|
|
57
|
+
# Contains the source ses on the first request after this
|
|
58
|
+
# session was cloned from another session.
|
|
59
|
+
attr_accessor :cloned_source
|
|
60
|
+
|
|
61
|
+
# Contains the target sessions packed in an array on
|
|
62
|
+
# the first request after another session was cloned
|
|
63
|
+
# from this session.
|
|
64
|
+
attr_accessor :cloned_targets
|
|
65
|
+
|
|
66
|
+
# The session is not valid by default, it's set
|
|
67
|
+
# by SessionManager, if everything seems ok.
|
|
68
|
+
attr_accessor :ses_valid
|
|
69
|
+
|
|
70
|
+
# The http request object.
|
|
71
|
+
attr_accessor :request
|
|
72
|
+
|
|
73
|
+
# The http response object.
|
|
74
|
+
attr_accessor :response
|
|
75
|
+
|
|
76
|
+
# Response output.
|
|
77
|
+
attr_accessor :buffer
|
|
78
|
+
|
|
79
|
+
attr_accessor :value_buffer
|
|
80
|
+
|
|
81
|
+
# The request success flag.
|
|
82
|
+
attr_accessor :response_success
|
|
83
|
+
|
|
84
|
+
# Reference to Transporter
|
|
85
|
+
attr_accessor :transporter
|
|
86
|
+
|
|
87
|
+
# Reference to ValueManager
|
|
88
|
+
attr_accessor :valuemanager
|
|
89
|
+
|
|
90
|
+
# Reference to SessionManager
|
|
91
|
+
attr_accessor :sessions
|
|
92
|
+
|
|
93
|
+
# Reference to PluginManager
|
|
94
|
+
attr_accessor :plugins
|
|
95
|
+
|
|
96
|
+
# Message is initialized with a valid +Request+ and +Response+ objects.
|
|
97
|
+
def initialize( transporter, request, response, options )
|
|
98
|
+
|
|
99
|
+
@config = ::RSence.config
|
|
100
|
+
|
|
101
|
+
@request = request
|
|
102
|
+
@response_success = false
|
|
103
|
+
@response = response
|
|
104
|
+
@session = nil
|
|
105
|
+
@buffer = []
|
|
106
|
+
|
|
107
|
+
@options = options
|
|
108
|
+
|
|
109
|
+
# Value response output.
|
|
110
|
+
@value_buffer = []
|
|
111
|
+
|
|
112
|
+
# The session key placeholder.
|
|
113
|
+
@ses_key = false
|
|
114
|
+
@new_session = false
|
|
115
|
+
@restored_session = false
|
|
116
|
+
@cloned_source = false
|
|
117
|
+
@cloned_targets = false
|
|
118
|
+
@ses_valid = false
|
|
119
|
+
@error_js = ''
|
|
120
|
+
|
|
121
|
+
# global instances
|
|
122
|
+
@transporter = transporter
|
|
123
|
+
@valuemanager = @transporter.valuemanager
|
|
124
|
+
@sessions = @transporter.sessions
|
|
125
|
+
@plugins = @transporter.plugins
|
|
126
|
+
|
|
127
|
+
if options[:servlet]
|
|
128
|
+
@do_gzip = false
|
|
129
|
+
else
|
|
130
|
+
@response.content_type = 'text/javascript; charset=utf-8'
|
|
131
|
+
@response['cache-control'] = 'no-cache'
|
|
132
|
+
|
|
133
|
+
# gnu-zipped responses:
|
|
134
|
+
if @request.header['accept-encoding'] and @request.header['accept-encoding'].include?('gzip') and not @config[:no_gzip]
|
|
135
|
+
@response['content-encoding'] = 'gzip'
|
|
136
|
+
@do_gzip = true
|
|
137
|
+
else
|
|
138
|
+
@do_gzip = false
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
@response_sent = false
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# Returns true for Internet Explorer 6.0
|
|
146
|
+
def ie6;
|
|
147
|
+
(request.header.has_key?('user-agent') and request.header['user-agent'].include?('MSIE 6.0'))
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# Expire the session.
|
|
151
|
+
def expire_session
|
|
152
|
+
@sessions.expire_session( @ses_id )
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# Define the session key.
|
|
156
|
+
def ses_key=(ses_key)
|
|
157
|
+
@ses_key = ses_key
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# Getter for session key.
|
|
161
|
+
def ses_key
|
|
162
|
+
@ses_key
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# Returns the user id
|
|
166
|
+
def user_id
|
|
167
|
+
@session[:user_id]
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# Setter for the user id
|
|
171
|
+
def user_id=(user_id)
|
|
172
|
+
@session[:user_id] = user_id
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def ses_id
|
|
176
|
+
@session[:ses_id]
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def ses_id=(ses_id)
|
|
180
|
+
@session[:ses_id] = ses_id
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def error_msg( error_js )
|
|
184
|
+
@error_js = error_js
|
|
185
|
+
# response_done
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def buf_json(buffer)
|
|
189
|
+
buffer.to_json
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
# Called to flush buffer.
|
|
193
|
+
def response_done
|
|
194
|
+
return if @response_sent
|
|
195
|
+
if not @response_success
|
|
196
|
+
@response.status = 200
|
|
197
|
+
#@response.status = 503
|
|
198
|
+
|
|
199
|
+
buffer = [
|
|
200
|
+
"" # empty session key will stop the syncing
|
|
201
|
+
] + @error_js
|
|
202
|
+
else
|
|
203
|
+
## The response status should always be 200 (OK)
|
|
204
|
+
@response.status = 200
|
|
205
|
+
|
|
206
|
+
buffer = @value_buffer + @buffer
|
|
207
|
+
if @ses_key
|
|
208
|
+
buffer.unshift( @ses_key )
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
# flush the output
|
|
214
|
+
if @do_gzip
|
|
215
|
+
outp = GZString.new('')
|
|
216
|
+
gzwriter = Zlib::GzipWriter.new(outp,Zlib::BEST_SPEED)
|
|
217
|
+
gzwriter.write( buf_json(buffer) )
|
|
218
|
+
gzwriter.close
|
|
219
|
+
else
|
|
220
|
+
outp = buf_json(buffer)
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
@response['content-length'] = outp.size
|
|
224
|
+
@response.body = outp
|
|
225
|
+
|
|
226
|
+
@response_sent = true
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
# Sends data to the client, usually
|
|
230
|
+
# javascript, but is valid for any data.
|
|
231
|
+
def reply(data,dont_squeeze=false)
|
|
232
|
+
data.strip!
|
|
233
|
+
data = @plugins[:client_pkg].squeeze( data ) unless dont_squeeze
|
|
234
|
+
puts data if @config[:trace]
|
|
235
|
+
@buffer.push( data )
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
# For value manager; insert changed values BEFORE other js.
|
|
239
|
+
def reply_value(data)
|
|
240
|
+
puts data if @config[:trace]
|
|
241
|
+
@value_buffer.push( data )
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
# Sends data to the client's console.
|
|
245
|
+
def console(data)
|
|
246
|
+
reply( "console.log(#{data.to_json});" )
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
# Serves an image object +img_obj+ by returning its disposable URL. The
|
|
250
|
+
# second optional parameter +img_format+ defaults to 'PNG' and defines
|
|
251
|
+
# the format of served picture.
|
|
252
|
+
def serve_img( img_obj, img_format='PNG' )
|
|
253
|
+
call(:ticket,:serve_img, self, img_obj, img_format )
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
# Sends any binary to be served, returns a disposable uri. First parameter
|
|
257
|
+
# defines the file data, second optional defines content type and defaults
|
|
258
|
+
# to 'text/plain' and third, also optional defines the filename which
|
|
259
|
+
# defaults to 'untitled.txt'.
|
|
260
|
+
def serve_file( file_data, content_type='text/plain', filename='untitled.txt' )
|
|
261
|
+
call(:ticket,:serve_file, self, file_data, content_type, filename )
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
# Sends any binary to be served, returns a static uri.
|
|
265
|
+
#
|
|
266
|
+
# IMPORTANT: PLEASE call +release_rsrc+ manually, when you
|
|
267
|
+
# don't need the resource anymore! Otherwise TicketServe will
|
|
268
|
+
# keep on chugging more memory every time you serve something.
|
|
269
|
+
#
|
|
270
|
+
# HINT: Usually, it's a better idea to use serve_img or
|
|
271
|
+
# serve_file instead.
|
|
272
|
+
def serve_rsrc( rsrc_data, content_type='text/plain' )
|
|
273
|
+
call(:ticket,:serve_rsrc,self, rsrc_data, content_type )
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
# Removes the uri served, you HAVE TO call this manually when
|
|
277
|
+
# you are done serving something! Takes the uri as its only parameter.
|
|
278
|
+
def release_rsrc( uri )
|
|
279
|
+
run(:ticket,:del_rsrc, uri[3..-1] )
|
|
280
|
+
end
|
|
281
|
+
alias unserve_rsrc release_rsrc
|
|
282
|
+
|
|
283
|
+
# Calls registered plugin +plugin+ method +plugin_method+ with any +args+
|
|
284
|
+
def call( plugin_name, plug_method, *args )
|
|
285
|
+
@plugins.call( plugin_name, plug_method, *args)
|
|
286
|
+
end
|
|
287
|
+
alias run call
|
|
288
|
+
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
end
|
|
@@ -0,0 +1,491 @@
|
|
|
1
|
+
## Riassence Framework
|
|
2
|
+
# Copyright 2006 Riassence Inc.
|
|
3
|
+
# http://riassence.com/
|
|
4
|
+
#
|
|
5
|
+
# You should have received a copy of the GNU General Public License along
|
|
6
|
+
# with this software package. If not, contact licensing@riassence.com
|
|
7
|
+
##
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
require 'rubygems'
|
|
11
|
+
require 'json'
|
|
12
|
+
|
|
13
|
+
## Shared messaging-object:
|
|
14
|
+
require 'session/msg'
|
|
15
|
+
|
|
16
|
+
## Unique random number generator:
|
|
17
|
+
require 'randgen'
|
|
18
|
+
|
|
19
|
+
## SessionStorage is the superclass of SessionManager
|
|
20
|
+
require 'session/sessionstorage'
|
|
21
|
+
|
|
22
|
+
module RSence
|
|
23
|
+
|
|
24
|
+
require 'digest/sha1'
|
|
25
|
+
|
|
26
|
+
=begin
|
|
27
|
+
SessionManager does session creation, validation, expiration and storage duties.
|
|
28
|
+
It's quite transparent.
|
|
29
|
+
=end
|
|
30
|
+
class SessionManager < SessionStorage
|
|
31
|
+
|
|
32
|
+
include Digest
|
|
33
|
+
|
|
34
|
+
attr_reader :randgen
|
|
35
|
+
|
|
36
|
+
## Makes everything ready to run
|
|
37
|
+
def initialize( transporter )
|
|
38
|
+
|
|
39
|
+
super()
|
|
40
|
+
|
|
41
|
+
@transporter = transporter
|
|
42
|
+
|
|
43
|
+
@valuemanager = @transporter.valuemanager
|
|
44
|
+
|
|
45
|
+
@plugins = @transporter.plugins
|
|
46
|
+
|
|
47
|
+
## 'Unique' Random String generator for ses_key:s and cookie_key:s
|
|
48
|
+
@randgen = RandGen.new( @config[:key_length] )
|
|
49
|
+
|
|
50
|
+
# regex to match ipv4 addresses
|
|
51
|
+
@ipv4_reg = /^([1][0-9][0-9]|[2][0-5][0-9]|[1-9][0-9]|[1-9])\.([1][0-9][0-9]|[2][0-5][0-9]|[1-9][0-9]|[0-9])\.([1][0-9][0-9]|[2][0-5][0-9]|[1-9][0-9]|[0-9])\.([1][0-9][0-9]|[2][0-5][0-9]|[1-9][0-9]|[0-9])$/
|
|
52
|
+
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
### Creates a new session
|
|
56
|
+
def init_ses( msg, ses_seed )
|
|
57
|
+
|
|
58
|
+
## Assigns new timeout for the session
|
|
59
|
+
time_now = Time.now.to_i # seconds since epoch
|
|
60
|
+
timeout = time_now + @config[:timeout_secs]
|
|
61
|
+
|
|
62
|
+
## Creates a new session key
|
|
63
|
+
ses_key = @randgen.gen
|
|
64
|
+
|
|
65
|
+
## Creates a new cookie key
|
|
66
|
+
cookie_key = @randgen.gen_many(@config[:cookie_key_multiplier]).join('')
|
|
67
|
+
|
|
68
|
+
## Makes a new database row for the session, returns its id
|
|
69
|
+
ses_id = new_ses_id( cookie_key, ses_key, timeout )
|
|
70
|
+
|
|
71
|
+
ses_sha = SHA1.hexdigest(ses_key+ses_seed)
|
|
72
|
+
|
|
73
|
+
### Default session data structure,
|
|
74
|
+
### Please don't mess with it, unless you know exactly what you are doing.
|
|
75
|
+
ses_data = {
|
|
76
|
+
|
|
77
|
+
# the time, when the session will time out
|
|
78
|
+
:timeout => timeout,
|
|
79
|
+
|
|
80
|
+
# session id, used internally
|
|
81
|
+
:ses_id => ses_id,
|
|
82
|
+
|
|
83
|
+
# session key, used externally (client xhr)
|
|
84
|
+
:ses_key => ses_sha,
|
|
85
|
+
|
|
86
|
+
# session key, used externally (client cookies)
|
|
87
|
+
:cookie_key => cookie_key,
|
|
88
|
+
|
|
89
|
+
# user id, map to your own user management code
|
|
90
|
+
:user_id => 0,
|
|
91
|
+
|
|
92
|
+
# valuemanager data
|
|
93
|
+
:values => {
|
|
94
|
+
:sync => [], # value id's to sync to client
|
|
95
|
+
:check => [], # value id's to validate in server (from client)
|
|
96
|
+
:by_id => {} # values by id
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
# bind the session data to @sessions by its id
|
|
101
|
+
@sessions[ ses_id ] = ses_data
|
|
102
|
+
|
|
103
|
+
# map the key back to the id
|
|
104
|
+
@session_keys[ ses_sha ] = ses_id
|
|
105
|
+
|
|
106
|
+
# map the ses_id to cookie key
|
|
107
|
+
@session_cookie_keys[ cookie_key ] = ses_id
|
|
108
|
+
|
|
109
|
+
### Tell the client what the new key is
|
|
110
|
+
msg.ses_key = ses_key
|
|
111
|
+
|
|
112
|
+
### Set the session data and id to the message object
|
|
113
|
+
msg.session = ses_data
|
|
114
|
+
|
|
115
|
+
# Flag the session as new, so associated
|
|
116
|
+
# plugins know when to create new data
|
|
117
|
+
msg.new_session = true
|
|
118
|
+
|
|
119
|
+
# Returns the cookie key, so it can be sent in the response header
|
|
120
|
+
return cookie_key
|
|
121
|
+
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def refresh_ses( msg, ses_data, ses_id, ses_key, ses_seed )
|
|
125
|
+
# new time-out
|
|
126
|
+
ses_data[:timeout] = Time.now.to_i + @config[:timeout_secs]
|
|
127
|
+
|
|
128
|
+
# re-generates the ses_key for each xhr
|
|
129
|
+
if @config[:disposable_keys]
|
|
130
|
+
|
|
131
|
+
# disposes the old (current) ses_key:
|
|
132
|
+
@session_keys.delete( ses_key )
|
|
133
|
+
|
|
134
|
+
unless ses_seed
|
|
135
|
+
ses_seed = ses_key
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# gets a new ses_key:
|
|
139
|
+
ses_key = @randgen.gen
|
|
140
|
+
|
|
141
|
+
ses_sha = SHA1.hexdigest(ses_key+ses_seed)
|
|
142
|
+
|
|
143
|
+
# re-maps the session id to the new key
|
|
144
|
+
@session_keys[ses_sha] = ses_id
|
|
145
|
+
|
|
146
|
+
# changes the session key in the session data
|
|
147
|
+
ses_data[:ses_key] = ses_sha
|
|
148
|
+
|
|
149
|
+
# tell the client what its new session key is
|
|
150
|
+
msg.ses_key = ses_key
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
if @config[:clone_cookie_sessions] and @clone_targets.has_key? ses_id
|
|
154
|
+
targets = []
|
|
155
|
+
@clone_targets[ ses_id ].length.times do |n|
|
|
156
|
+
target_id = @clone_targets[ ses_id ].shift
|
|
157
|
+
# warn "target_id: #{target_id}"
|
|
158
|
+
target_ses = @sessions[ target_id ]
|
|
159
|
+
if @sessions.has_key?( target_id ) and @sessions[ target_id ].class == Hash
|
|
160
|
+
targets.push( target_ses )
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
@clone_targets.delete( ses_id ) if @clone_targets[ ses_id ].empty?
|
|
164
|
+
msg.cloned_targets = targets unless targets.empty?
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
### Bind the session data and id to the message object
|
|
168
|
+
msg.session = ses_data
|
|
169
|
+
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def clone_ses( msg, old_data, old_id, old_key, ses_seed )
|
|
173
|
+
ses_data = Marshal.restore( Marshal.dump( old_data ) )
|
|
174
|
+
old_data[:timeout] = Time.now.to_i + @config[:cloned_session_expires_in]
|
|
175
|
+
timeout = Time.now.to_i + @config[:timeout_secs]
|
|
176
|
+
cookie_key = @randgen.gen_many(@config[:cookie_key_multiplier]).join('')
|
|
177
|
+
ses_key = @randgen.gen
|
|
178
|
+
ses_sha = SHA1.hexdigest(ses_key+ses_seed)
|
|
179
|
+
ses_data[:timeout] = timeout
|
|
180
|
+
ses_data[:ses_key] = ses_key
|
|
181
|
+
ses_data[:cookie_key] = cookie_key
|
|
182
|
+
ses_id = new_ses_id( cookie_key, ses_key, timeout )
|
|
183
|
+
ses_data[:ses_id] = ses_id
|
|
184
|
+
@sessions[ ses_id ] = ses_data
|
|
185
|
+
@session_keys[ ses_sha ] = ses_id
|
|
186
|
+
@session_cookie_keys.delete( old_data[:cookie_key] )
|
|
187
|
+
@session_cookie_keys[ cookie_key ] = ses_id
|
|
188
|
+
msg.ses_key = ses_key
|
|
189
|
+
msg.session = ses_data
|
|
190
|
+
if @clone_targets.has_key? old_id
|
|
191
|
+
@clone_targets[ old_id ].push( ses_id )
|
|
192
|
+
else
|
|
193
|
+
@clone_targets[ old_id ] = [ ses_id ]
|
|
194
|
+
end
|
|
195
|
+
@clone_sources[ ses_id ] = old_id
|
|
196
|
+
msg.cloned_source = old_data
|
|
197
|
+
msg.new_session = false
|
|
198
|
+
msg.restored_session = true
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
### Returns the current session data, if the session is valid.
|
|
202
|
+
### Otherwise stops the client and returns false.
|
|
203
|
+
def check_ses( msg, ses_key, ses_seed=false )
|
|
204
|
+
|
|
205
|
+
# first, check if the session key exists (xhr)
|
|
206
|
+
if @session_keys.has_key?( ses_key )
|
|
207
|
+
|
|
208
|
+
# get the session's id based on its key
|
|
209
|
+
ses_id = @session_keys[ ses_key ]
|
|
210
|
+
|
|
211
|
+
# get the session's data based on its id
|
|
212
|
+
ses_data = @sessions[ ses_id ]
|
|
213
|
+
|
|
214
|
+
if @config[:clone_cookie_sessions] and ses_seed
|
|
215
|
+
clone_ses( msg, ses_data, ses_id, ses_key, ses_seed )
|
|
216
|
+
return [true, true]
|
|
217
|
+
else
|
|
218
|
+
refresh_ses( msg, ses_data, ses_id, ses_key, ses_seed )
|
|
219
|
+
return [true, false]
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
## The session was either faked or expired:
|
|
224
|
+
else
|
|
225
|
+
### Tells the client to stop connecting with its session key and reload instead to get a new one.
|
|
226
|
+
stop_client_with_message( msg,
|
|
227
|
+
@config[:messages][:invalid_session][:title],
|
|
228
|
+
@config[:messages][:invalid_session][:descr],
|
|
229
|
+
@config[:messages][:invalid_session][:uri]
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
## Return failure
|
|
233
|
+
return [false, false]
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
def js_str( str )
|
|
239
|
+
return str.to_json.gsub('<','<').gsub('>','>').gsub(/\[\[(.*?)\]\]/,'<\1>')
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
## Displays error message and stops the client
|
|
243
|
+
def stop_client_with_message( msg,
|
|
244
|
+
title = 'Unknown Issue',
|
|
245
|
+
descr = 'No issue description given.',
|
|
246
|
+
uri = ::RSence.config[:index_html][:respond_address] )
|
|
247
|
+
msg.error_msg( [
|
|
248
|
+
"jsLoader.load('default_theme');",
|
|
249
|
+
"jsLoader.load('controls');",
|
|
250
|
+
"jsLoader.load('servermessage');",
|
|
251
|
+
"ReloadApp.nu( #{js_str(title)}, #{js_str(descr)}, #{js_str(uri)} );"
|
|
252
|
+
] )
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
### Checks / Sets cookies
|
|
256
|
+
def check_cookie( msg, ses_seed )
|
|
257
|
+
|
|
258
|
+
# default to no cookie key found:
|
|
259
|
+
cookie_key = false
|
|
260
|
+
|
|
261
|
+
# gets the cookie array from the request object
|
|
262
|
+
cookie_raw = msg.request.cookies
|
|
263
|
+
|
|
264
|
+
# checks, if a cookie named 'ses_key' is found
|
|
265
|
+
if cookie_raw.has_key?('ses_key')
|
|
266
|
+
|
|
267
|
+
# gets just the data itself (discards comment, domain, exipiry etc)
|
|
268
|
+
cookie_key = cookie_raw['ses_key'].split(';')[0]
|
|
269
|
+
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
# if a cookie key is found (non-false), checks if it's valid
|
|
273
|
+
if cookie_key
|
|
274
|
+
|
|
275
|
+
# checks for validity by looking the key up in @session_cookie_keys
|
|
276
|
+
cookie_key_exist = @session_cookie_keys.has_key?( cookie_key )
|
|
277
|
+
|
|
278
|
+
# sets the cookie key to false, if it doesn't exist
|
|
279
|
+
cookie_key = false unless cookie_key_exist
|
|
280
|
+
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
# at this point, the cookie key seems valid:
|
|
284
|
+
if cookie_key and cookie_key_exist
|
|
285
|
+
|
|
286
|
+
# get the session identifier
|
|
287
|
+
ses_id = @session_cookie_keys[ cookie_key ]
|
|
288
|
+
|
|
289
|
+
# get the last session key from session data
|
|
290
|
+
ses_key = @sessions[ses_id][:ses_key]
|
|
291
|
+
|
|
292
|
+
# make additional checks on the session validity (expiry etc)
|
|
293
|
+
(ses_status, ses_cloned) = check_ses( msg, ses_key, ses_seed )
|
|
294
|
+
|
|
295
|
+
if ses_status and ses_cloned
|
|
296
|
+
ses_id = msg.ses_id
|
|
297
|
+
ses_key = msg.session[:ses_key]
|
|
298
|
+
cookie_key = msg.session[:cookie_key]
|
|
299
|
+
@valuemanager.resend_session_values( msg )
|
|
300
|
+
elsif ses_status
|
|
301
|
+
# delete the old cookie key:
|
|
302
|
+
@session_cookie_keys.delete( cookie_key )
|
|
303
|
+
|
|
304
|
+
# get a new cookie key
|
|
305
|
+
cookie_key = @randgen.gen_many(@config[:cookie_key_multiplier]).join('')
|
|
306
|
+
|
|
307
|
+
# map the new cookie key to the old session identifier
|
|
308
|
+
@session_cookie_keys[ cookie_key ] = ses_id
|
|
309
|
+
|
|
310
|
+
# binds the new cookie key to the old session data
|
|
311
|
+
@sessions[ses_id][:cookie_key] = cookie_key
|
|
312
|
+
|
|
313
|
+
# Sets the restored_session flag of msg to true
|
|
314
|
+
# It signals plugins to re-set data
|
|
315
|
+
msg.restored_session = true
|
|
316
|
+
|
|
317
|
+
# Sets the new_session flag of msg to false
|
|
318
|
+
# It signals plugins to not create new server-side values
|
|
319
|
+
msg.new_session = false
|
|
320
|
+
|
|
321
|
+
# tells ValueManager to re-send client-side HValue objects
|
|
322
|
+
# with data to the client
|
|
323
|
+
@valuemanager.resend_session_values( msg )
|
|
324
|
+
|
|
325
|
+
# if the session is not valid, make sure to mark the
|
|
326
|
+
# cookie key as invalid (false)
|
|
327
|
+
else
|
|
328
|
+
cookie_key = false
|
|
329
|
+
end
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
# if the cookie key failed validation in the
|
|
333
|
+
# tests above, create a new session instead
|
|
334
|
+
unless cookie_key
|
|
335
|
+
cookie_key = init_ses( msg, ses_seed )
|
|
336
|
+
ses_status = true
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
renew_cookie( msg, cookie_key )
|
|
340
|
+
|
|
341
|
+
## Return the session status. Actually,
|
|
342
|
+
## the value is always true, but future
|
|
343
|
+
## versions might not accept invalid
|
|
344
|
+
## cookies as new sessions.
|
|
345
|
+
return ses_status
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
def renew_cookie( msg, cookie_key )
|
|
349
|
+
# Uses a cookie comment to tell the user what the
|
|
350
|
+
# cookie is for, change it to anything valid in the
|
|
351
|
+
# configuration.
|
|
352
|
+
ses_cookie_comment = @config[:ses_cookie_comment]
|
|
353
|
+
|
|
354
|
+
## mod_rewrite changes the host header to x-forwarded-host:
|
|
355
|
+
if msg.request.header.has_key?('x-forwarded-host')
|
|
356
|
+
domain = msg.request.header['x-forwarded-host']
|
|
357
|
+
|
|
358
|
+
## direct access just uses host (at least mongrel
|
|
359
|
+
## does mod_rewrite header translation):
|
|
360
|
+
else
|
|
361
|
+
domain = msg.request.host
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
if domain == 'localhost'
|
|
365
|
+
# warn "Warning: Cookies won't be set for 'localhost'. Use '127.0.0.1' instead." if $DEBUG_MODE
|
|
366
|
+
return
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
server_port = msg.request.port
|
|
370
|
+
|
|
371
|
+
## if the host address is a real domain
|
|
372
|
+
## (not just hostname or 'localhost'),
|
|
373
|
+
## but not an ip-address, prepend it with
|
|
374
|
+
## a dot to accept wildcards (useful for
|
|
375
|
+
## dns-load-balanced server configurations)
|
|
376
|
+
if not @ipv4_reg.match(domain) and domain.include?('.')
|
|
377
|
+
ses_cookie_domain = ".#{domain}"
|
|
378
|
+
## Otherwise, use the domain as-is
|
|
379
|
+
else
|
|
380
|
+
ses_cookie_domain = domain
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
## uses the timeout to declare the max age
|
|
384
|
+
## of the cookie, allows the browser to delete
|
|
385
|
+
## it, when it expires.
|
|
386
|
+
ses_cookie_max_age = @config[:timeout_secs]
|
|
387
|
+
|
|
388
|
+
## Only match the handshaking address of rsence,
|
|
389
|
+
## prevents unneccessary cookie-juggling in xhr's
|
|
390
|
+
if @config[:trust_cookies]
|
|
391
|
+
ses_cookie_path = '/'
|
|
392
|
+
else
|
|
393
|
+
ses_cookie_path = ::RSence.config[:broker_urls][:hello]
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
## Formats the cookie to string
|
|
397
|
+
## (through array, to keep it readable in the source)
|
|
398
|
+
ses_cookie_arr = [
|
|
399
|
+
"ses_key=#{cookie_key}",
|
|
400
|
+
"Path=#{ses_cookie_path}",
|
|
401
|
+
"Port=#{server_port}",
|
|
402
|
+
"Max-Age=#{ses_cookie_max_age}",
|
|
403
|
+
"Comment=#{ses_cookie_comment}",
|
|
404
|
+
"Domain=#{ses_cookie_domain}"
|
|
405
|
+
]
|
|
406
|
+
|
|
407
|
+
### Sets the set-cookie header
|
|
408
|
+
msg.response['Set-Cookie'] = ses_cookie_arr.join('; ')
|
|
409
|
+
end
|
|
410
|
+
|
|
411
|
+
### Creates a message and checks the session
|
|
412
|
+
def init_msg( request, response, options = { :cookies => false, :servlet => false } )
|
|
413
|
+
|
|
414
|
+
cookies = options[:cookies]
|
|
415
|
+
|
|
416
|
+
if options.has_key?(:query)
|
|
417
|
+
query = options[:query]
|
|
418
|
+
else
|
|
419
|
+
query = request.query
|
|
420
|
+
end
|
|
421
|
+
|
|
422
|
+
## Perform old-session cleanup on all xhr:s
|
|
423
|
+
expire_sessions
|
|
424
|
+
|
|
425
|
+
## The 'ses_id' request query key is required.
|
|
426
|
+
## The client defaults to '0', which means the
|
|
427
|
+
## client needs to be initialized.
|
|
428
|
+
## The client's ses_id is the server's ses_key.
|
|
429
|
+
if not query.has_key?( 'ses_key' )
|
|
430
|
+
return Message.new( @transporter, request, response, options )
|
|
431
|
+
else
|
|
432
|
+
|
|
433
|
+
## get the ses_key from the request query:
|
|
434
|
+
ses_key = query[ 'ses_key' ]
|
|
435
|
+
# puts "ses key: #{ses_key}"
|
|
436
|
+
## The message object binds request, response
|
|
437
|
+
## and all user/session -related data to one
|
|
438
|
+
## object, which is passed around where
|
|
439
|
+
## request/response/user/session -related
|
|
440
|
+
## data is needed.
|
|
441
|
+
msg = Message.new( @transporter, request, response, options )
|
|
442
|
+
|
|
443
|
+
## The client tells that its ses_key is '0',
|
|
444
|
+
## until the server tells it otherwise.
|
|
445
|
+
(req_num, ses_seed) = ses_key.split(':.o.:')
|
|
446
|
+
|
|
447
|
+
if req_num == '0'
|
|
448
|
+
|
|
449
|
+
# If Broker encounters a '/hello' request, it
|
|
450
|
+
# sets cookies to true.
|
|
451
|
+
#
|
|
452
|
+
# It means that a session should have its cookies
|
|
453
|
+
# checked.
|
|
454
|
+
#
|
|
455
|
+
if cookies
|
|
456
|
+
ses_status = check_cookie( msg, ses_seed )
|
|
457
|
+
# Otherwise, a new session is created:
|
|
458
|
+
else
|
|
459
|
+
init_ses( msg, ses_seed )
|
|
460
|
+
ses_status = true
|
|
461
|
+
end
|
|
462
|
+
|
|
463
|
+
# for non-'0' ses_keys:
|
|
464
|
+
else
|
|
465
|
+
|
|
466
|
+
## Validate the session key
|
|
467
|
+
ses_status = check_ses( msg, ses_seed )[0]
|
|
468
|
+
|
|
469
|
+
## Renew the cookie even when the request is a "x" (not "hello")
|
|
470
|
+
if @config[:session_cookies] and ses_status
|
|
471
|
+
renew_cookie( msg, msg.session[:cookie_key] )
|
|
472
|
+
end
|
|
473
|
+
|
|
474
|
+
end # /ses_key
|
|
475
|
+
|
|
476
|
+
## msg.ses_valid is false by default, meaning
|
|
477
|
+
## it's not valid or hasn't been initialized.
|
|
478
|
+
msg.ses_valid = ses_status
|
|
479
|
+
|
|
480
|
+
return msg
|
|
481
|
+
|
|
482
|
+
end # /ses_key
|
|
483
|
+
|
|
484
|
+
end # /init_msg
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
end
|
|
488
|
+
|
|
489
|
+
|
|
490
|
+
end
|
|
491
|
+
|