nitro 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/AUTHORS +8 -0
- data/ChangeLog +1546 -0
- data/LICENCE +32 -0
- data/README +278 -0
- data/RELEASES +7 -0
- data/Rakefile +79 -0
- data/bin/cluster.rb +219 -0
- data/doc/architecture.txt +28 -0
- data/doc/bugs.txt +7 -0
- data/doc/css.txt +20 -0
- data/doc/ideas.txt +120 -0
- data/doc/pg.txt +47 -0
- data/doc/svn.txt +82 -0
- data/doc/todo.txt +30 -0
- data/etc/new-project.rb +18 -0
- data/examples/simple/README +15 -0
- data/examples/simple/app.rb +31 -0
- data/examples/simple/conf/apache.conf +100 -0
- data/examples/simple/conf/config.rb +89 -0
- data/examples/simple/conf/debug-config.rb +53 -0
- data/examples/simple/conf/live-config.rb +48 -0
- data/examples/simple/conf/overrides.rb +9 -0
- data/examples/simple/conf/requires.rb +51 -0
- data/examples/simple/ctl +32 -0
- data/examples/simple/env.rb +33 -0
- data/examples/simple/install.rb +12 -0
- data/examples/simple/lib/articles/entities.rb +35 -0
- data/examples/simple/lib/articles/lc-en.rb +36 -0
- data/examples/simple/lib/articles/methods.rb +55 -0
- data/examples/simple/lib/articles/part.rb +58 -0
- data/examples/simple/logs/access_log +2 -0
- data/examples/simple/logs/apache.log +3 -0
- data/examples/simple/logs/app.log +1 -0
- data/examples/simple/logs/events.log +1 -0
- data/examples/simple/root/add-article.sx +15 -0
- data/examples/simple/root/article-form.ss +20 -0
- data/examples/simple/root/comments-form.ss +16 -0
- data/examples/simple/root/comments.si +30 -0
- data/examples/simple/root/index.sx +44 -0
- data/examples/simple/root/shader/shader.xsl +100 -0
- data/examples/simple/root/shader/style.css +9 -0
- data/examples/simple/root/view-article.sx +30 -0
- data/examples/tiny/app.rb +30 -0
- data/examples/tiny/conf/apache.conf +100 -0
- data/examples/tiny/conf/config.rb +67 -0
- data/examples/tiny/conf/requires.rb +40 -0
- data/examples/tiny/ctl +31 -0
- data/examples/tiny/logs/access_log +9 -0
- data/examples/tiny/logs/apache.log +9 -0
- data/examples/tiny/root/index.sx +35 -0
- data/lib/n/app/cluster.rb +219 -0
- data/lib/n/app/cookie.rb +86 -0
- data/lib/n/app/filters/autologin.rb +50 -0
- data/lib/n/app/fragment.rb +67 -0
- data/lib/n/app/handlers.rb +120 -0
- data/lib/n/app/handlers/code-handler.rb +184 -0
- data/lib/n/app/handlers/page-handler.rb +612 -0
- data/lib/n/app/request-part.rb +59 -0
- data/lib/n/app/request.rb +653 -0
- data/lib/n/app/script.rb +398 -0
- data/lib/n/app/server.rb +53 -0
- data/lib/n/app/session.rb +224 -0
- data/lib/n/app/user.rb +47 -0
- data/lib/n/app/webrick-servlet.rb +213 -0
- data/lib/n/app/webrick.rb +70 -0
- data/lib/n/application.rb +187 -0
- data/lib/n/config.rb +31 -0
- data/lib/n/db.rb +217 -0
- data/lib/n/db/README +232 -0
- data/lib/n/db/connection.rb +369 -0
- data/lib/n/db/make-release.sh +26 -0
- data/lib/n/db/managed.rb +235 -0
- data/lib/n/db/mixins.rb +282 -0
- data/lib/n/db/mysql.rb +342 -0
- data/lib/n/db/psql.rb +378 -0
- data/lib/n/db/tools.rb +110 -0
- data/lib/n/db/utils.rb +99 -0
- data/lib/n/events.rb +118 -0
- data/lib/n/l10n.rb +22 -0
- data/lib/n/logger.rb +33 -0
- data/lib/n/macros.rb +53 -0
- data/lib/n/mixins.rb +46 -0
- data/lib/n/parts.rb +154 -0
- data/lib/n/properties.rb +194 -0
- data/lib/n/server.rb +61 -0
- data/lib/n/server/PLAYBACK.txt +8 -0
- data/lib/n/server/RESEARCH.txt +13 -0
- data/lib/n/server/filter.rb +77 -0
- data/lib/n/shaders.rb +167 -0
- data/lib/n/sitemap.rb +188 -0
- data/lib/n/std.rb +69 -0
- data/lib/n/sync/clc.rb +108 -0
- data/lib/n/sync/handler.rb +221 -0
- data/lib/n/sync/server.rb +170 -0
- data/lib/n/tools/README +11 -0
- data/lib/n/ui/date-select.rb +74 -0
- data/lib/n/ui/pager.rb +187 -0
- data/lib/n/ui/popup.rb +45 -0
- data/lib/n/ui/select.rb +41 -0
- data/lib/n/ui/tabs.rb +34 -0
- data/lib/n/utils/array.rb +92 -0
- data/lib/n/utils/cache.rb +144 -0
- data/lib/n/utils/gfx.rb +108 -0
- data/lib/n/utils/hash.rb +148 -0
- data/lib/n/utils/html.rb +147 -0
- data/lib/n/utils/http.rb +98 -0
- data/lib/n/utils/mail.rb +28 -0
- data/lib/n/utils/number.rb +31 -0
- data/lib/n/utils/pool.rb +66 -0
- data/lib/n/utils/string.rb +297 -0
- data/lib/n/utils/template.rb +38 -0
- data/lib/n/utils/time.rb +91 -0
- data/lib/n/utils/uri.rb +193 -0
- data/lib/xsl/base.xsl +205 -0
- data/lib/xsl/ce.xsl +30 -0
- data/lib/xsl/localization.xsl +23 -0
- data/lib/xsl/xforms.xsl +26 -0
- data/test/run.rb +95 -0
- metadata +187 -0
@@ -0,0 +1,224 @@
|
|
1
|
+
# = Session
|
2
|
+
#
|
3
|
+
#--
|
4
|
+
# code:
|
5
|
+
# George Moschovitis <gm@navel.gr>
|
6
|
+
#
|
7
|
+
# (c) 2002-2003 Navel, all rights reserved.
|
8
|
+
# $Id: session.rb 84 2004-10-19 13:57:01Z gmosx $
|
9
|
+
#++
|
10
|
+
|
11
|
+
require "md5"
|
12
|
+
|
13
|
+
require "n/utils/hash"
|
14
|
+
require "n/app/user"
|
15
|
+
|
16
|
+
module N; module App
|
17
|
+
|
18
|
+
# = SessionManager
|
19
|
+
#
|
20
|
+
# This object manages Session Objects. Several utility methods
|
21
|
+
# are also provided.
|
22
|
+
#
|
23
|
+
# === WARNING:
|
24
|
+
#
|
25
|
+
# This object is typically called in a distributed configuration.
|
26
|
+
# Avoid writting methods that accept or return big objects!
|
27
|
+
#
|
28
|
+
# SOS: This object lives in the Cluster!
|
29
|
+
#
|
30
|
+
class SessionManager < N::SafeHash
|
31
|
+
# the collection of online users.
|
32
|
+
attr_reader :online
|
33
|
+
|
34
|
+
def initialize
|
35
|
+
super
|
36
|
+
@online = N::SafeHash.new
|
37
|
+
end
|
38
|
+
|
39
|
+
# Return the number of anonymous sessions.
|
40
|
+
#
|
41
|
+
def anonymous_count
|
42
|
+
return self.size - @online.size
|
43
|
+
end
|
44
|
+
|
45
|
+
# Login a named user.
|
46
|
+
# The caller may pass user.to_html instead of the user name.
|
47
|
+
# this method is distributed keep a lightweight
|
48
|
+
# signature. By using @online.keys i get access to the
|
49
|
+
# oids and in this way to the full objects.
|
50
|
+
#
|
51
|
+
def login(user_oid, user_name)
|
52
|
+
@online[user_oid] = user_name
|
53
|
+
end
|
54
|
+
|
55
|
+
# Logout a named user.
|
56
|
+
#
|
57
|
+
def logout(user_oid)
|
58
|
+
@online.delete(user_oid)
|
59
|
+
end
|
60
|
+
|
61
|
+
# Returns the session for the given user.
|
62
|
+
#
|
63
|
+
def session_for_user(user)
|
64
|
+
return values().find { |s| user.oid == s.user.oid }
|
65
|
+
end
|
66
|
+
|
67
|
+
# Returns the session for the given user.
|
68
|
+
#
|
69
|
+
def session_for_name(name)
|
70
|
+
return values().find { |s| name == s.user.name }
|
71
|
+
end
|
72
|
+
|
73
|
+
# garbage collect stale sessions
|
74
|
+
#
|
75
|
+
# === TODO:
|
76
|
+
#
|
77
|
+
# - add unit testing.
|
78
|
+
#
|
79
|
+
def self.garbage_collect!
|
80
|
+
# gmosx: the only way to get it to ruby with
|
81
|
+
# druby, aaarghhh!! Rethink this though! perhaps some
|
82
|
+
# fixes i made allow for recoding this.
|
83
|
+
for key in $sessions.keys()
|
84
|
+
begin
|
85
|
+
session = $sessions[key]
|
86
|
+
if session.stale?
|
87
|
+
$log.debug "Session finalized: logging out idle user '#{session.user}'" if $DBG
|
88
|
+
session.logout()
|
89
|
+
$sessions.delete(key)
|
90
|
+
end
|
91
|
+
rescue Exception, StandardError => e
|
92
|
+
$log.error "Session gc errror #$!"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# = Session
|
99
|
+
#
|
100
|
+
# This object encapsulates a WebApplication session.
|
101
|
+
#
|
102
|
+
# === Design:
|
103
|
+
#
|
104
|
+
# The session should be persistable to survive server shutdowns.
|
105
|
+
#
|
106
|
+
# === Usage
|
107
|
+
#
|
108
|
+
# State is a neccessary evil but try to avoid using session
|
109
|
+
# variables as much as possible. Session state is typically
|
110
|
+
# distributed to many servers so avoid storing complete objects
|
111
|
+
# in session variables, only store oids and integer/strings.
|
112
|
+
#
|
113
|
+
class Session < Hash
|
114
|
+
COOKIE_NAME = "nsid"
|
115
|
+
|
116
|
+
attr_reader :session_id
|
117
|
+
|
118
|
+
# keep the user to allow for session lookup based on user.
|
119
|
+
# also do NOT keep the full user as an object in the session hash
|
120
|
+
# to optimize druby usage!
|
121
|
+
#
|
122
|
+
attr_accessor :user
|
123
|
+
|
124
|
+
# the last touch time
|
125
|
+
attr_accessor :touch_time
|
126
|
+
|
127
|
+
#
|
128
|
+
#
|
129
|
+
def initialize(sid, request = nil)
|
130
|
+
super()
|
131
|
+
@session_id = sid
|
132
|
+
@touch_time = Time.now
|
133
|
+
@user = N::AnonymousUser.instance()
|
134
|
+
end
|
135
|
+
|
136
|
+
# Login a user
|
137
|
+
#
|
138
|
+
# Returns false for banned users.
|
139
|
+
#
|
140
|
+
def login(request, user)
|
141
|
+
return false if user.banned?
|
142
|
+
@user = user
|
143
|
+
@user.login(request)
|
144
|
+
$sessions.login(@user.oid, @user.name)
|
145
|
+
$log.info "User '#{user}' logged in!"
|
146
|
+
return true
|
147
|
+
end
|
148
|
+
|
149
|
+
# Logout a user
|
150
|
+
#
|
151
|
+
def logout()
|
152
|
+
self.clear()
|
153
|
+
@user.logout()
|
154
|
+
$sessions.logout(@user.oid)
|
155
|
+
$log.info "User '#{user}' logged out!"
|
156
|
+
@user = N::AnonymousUser.instance
|
157
|
+
end
|
158
|
+
|
159
|
+
#
|
160
|
+
#
|
161
|
+
def touch
|
162
|
+
@touch_time = Time.now
|
163
|
+
end
|
164
|
+
|
165
|
+
#
|
166
|
+
#
|
167
|
+
def stale?
|
168
|
+
timeout = @user.anonymous? ? $srv_anon_session_timeout : $srv_session_timeout
|
169
|
+
return (Time.now - @touch_time > timeout)
|
170
|
+
end
|
171
|
+
|
172
|
+
# call this method to synchronize the session with other servers
|
173
|
+
# in the cluster.
|
174
|
+
#
|
175
|
+
def synchronize!
|
176
|
+
# gmosx: TODO, add a check if the session is allready
|
177
|
+
# synchronized.
|
178
|
+
$sessions[@session_id] = self
|
179
|
+
end
|
180
|
+
|
181
|
+
# Refresh session entities.
|
182
|
+
#
|
183
|
+
# Call this when you manually change entities stored in the
|
184
|
+
# session. A typical scenario is when you change an online user.
|
185
|
+
#
|
186
|
+
# === Warning: the current version only refreshes the "USER" entity.
|
187
|
+
#
|
188
|
+
def refresh!
|
189
|
+
@user = $db.get(@user.oid, @user.class) if @user
|
190
|
+
end
|
191
|
+
|
192
|
+
# Calculates a unique id.
|
193
|
+
#
|
194
|
+
# The session id must be unique, a monotonically increasing function
|
195
|
+
# like time is appropriate. Random may produce equal ids? add a prefix
|
196
|
+
# (SALT) to stop hackers from creating session_ids.
|
197
|
+
#
|
198
|
+
# TODO:
|
199
|
+
# make the prefix configurable
|
200
|
+
#
|
201
|
+
def self.calculate_id
|
202
|
+
time = Time.now
|
203
|
+
# FIXME: make this more random?
|
204
|
+
id = Digest::MD5.md5("SALT#{time.to_i} #{time.tv_usec}").to_s
|
205
|
+
return id
|
206
|
+
end
|
207
|
+
|
208
|
+
# Initialize sessions garbage collection.
|
209
|
+
#
|
210
|
+
# === Warning: this is not used yet!
|
211
|
+
#
|
212
|
+
def self.initialize_gc(session_manager, interval)
|
213
|
+
# gmosx, FIXME: store this in a variable.
|
214
|
+
Thread.new {
|
215
|
+
loop do
|
216
|
+
sleep(interval)
|
217
|
+
garbage_collect(session_manager.sessions)
|
218
|
+
end
|
219
|
+
}
|
220
|
+
end
|
221
|
+
|
222
|
+
end
|
223
|
+
|
224
|
+
end; end # module
|
data/lib/n/app/user.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# = User
|
2
|
+
#
|
3
|
+
# A user of the Web Application. This is a base object, typically
|
4
|
+
# extended by the users part.
|
5
|
+
#
|
6
|
+
#--
|
7
|
+
# code:
|
8
|
+
# George Moschovitis <gm@navel.gr>
|
9
|
+
#
|
10
|
+
# (c) 2002-2003 Navel, all rights reserved.
|
11
|
+
# $Id: user.rb 86 2004-10-19 13:58:40Z gmosx $
|
12
|
+
#++
|
13
|
+
|
14
|
+
require "singleton"
|
15
|
+
|
16
|
+
module N
|
17
|
+
|
18
|
+
# = Anonymous User
|
19
|
+
#
|
20
|
+
# Implemented as singleton.
|
21
|
+
#
|
22
|
+
class AnonymousUser
|
23
|
+
include Singleton
|
24
|
+
|
25
|
+
attr_accessor :name
|
26
|
+
attr_accessor :locale
|
27
|
+
attr_accessor :shader
|
28
|
+
|
29
|
+
def initialize
|
30
|
+
super
|
31
|
+
@name = "anonymous"
|
32
|
+
@locale = "en"
|
33
|
+
@shader = $default_shader
|
34
|
+
end
|
35
|
+
|
36
|
+
def anonymous?
|
37
|
+
true
|
38
|
+
end
|
39
|
+
|
40
|
+
def login
|
41
|
+
end
|
42
|
+
|
43
|
+
def logout
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end # module
|
@@ -0,0 +1,213 @@
|
|
1
|
+
# = Webrick Servlet.
|
2
|
+
#
|
3
|
+
# code:
|
4
|
+
# George Moschovitis <gm@navel.gr>
|
5
|
+
#
|
6
|
+
# (c) 2004 Navel, all rights reserved.
|
7
|
+
# $Id: webrick-servlet.rb 87 2004-10-19 17:27:45Z gmosx $
|
8
|
+
|
9
|
+
require "drb"
|
10
|
+
require "singleton"
|
11
|
+
require "webrick"
|
12
|
+
|
13
|
+
require "n/logger"
|
14
|
+
require "n/utils/cache"
|
15
|
+
require "n/app/request"
|
16
|
+
require "n/app/request"
|
17
|
+
require "n/app/handlers"
|
18
|
+
require "n/app/session"
|
19
|
+
|
20
|
+
# Override WEBrick to suit our needs.
|
21
|
+
|
22
|
+
module WEBrick
|
23
|
+
class HTTPRequest
|
24
|
+
alias_method :old_parse_uri, :parse_uri
|
25
|
+
def parse_uri(str, scheme="http")
|
26
|
+
old_parse_uri(__rewrite(str.dup), scheme)
|
27
|
+
end
|
28
|
+
|
29
|
+
# gmosx, FIXME: temp hack!
|
30
|
+
#
|
31
|
+
def __rewrite(uri)
|
32
|
+
# FIXME: scan for first ONLY.
|
33
|
+
realm = uri.scan(/^\/(.*?)\//)
|
34
|
+
realm = realm[0][0] unless realm.empty?
|
35
|
+
|
36
|
+
if rules = $rewrites[realm]
|
37
|
+
for rule in rules
|
38
|
+
return uri if uri.gsub!(rule[0], rule[1])
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
return uri
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class HTTPResponse
|
47
|
+
attr_writer :header
|
48
|
+
attr_writer :cookies
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
module N; module App
|
53
|
+
|
54
|
+
# = WebrickServlet
|
55
|
+
#
|
56
|
+
class WebrickServlet < WEBrick::HTTPServlet::AbstractServlet
|
57
|
+
include WEBrick
|
58
|
+
|
59
|
+
def do_GET(wreq, wres)
|
60
|
+
request = create_request(wreq)
|
61
|
+
request.session = create_session(request)
|
62
|
+
|
63
|
+
extension = N::StringUtils.extension_from_path(request.path)
|
64
|
+
handler = $srv_extension_map[extension][1]
|
65
|
+
|
66
|
+
begin
|
67
|
+
fragment, script = handler.process(request)
|
68
|
+
|
69
|
+
if fragment
|
70
|
+
request.out["Content-Type"] = "text/html" unless request.out["Content-Type"]
|
71
|
+
request.out_buffer = fragment.body
|
72
|
+
end
|
73
|
+
|
74
|
+
unless request.expires?
|
75
|
+
request.expires!(Time.now())
|
76
|
+
end
|
77
|
+
|
78
|
+
rescue Exception, StandardError => e
|
79
|
+
$log.error "error while handling the request #{request.uri}"
|
80
|
+
$log.error pp_exception(e)
|
81
|
+
|
82
|
+
if $error_page_url
|
83
|
+
# internal redirect to error page.
|
84
|
+
# gmosx: reset handler for .rx pages.
|
85
|
+
handler = $srv_extension_map["sx"][1]
|
86
|
+
request.path = $error_page_url
|
87
|
+
retry
|
88
|
+
else
|
89
|
+
# no custom error page defined. Presen a simple yet
|
90
|
+
# useful error screen.
|
91
|
+
request.out["Content-Type"] = "text/html"
|
92
|
+
body = %{
|
93
|
+
<h1>ERROR</h1>
|
94
|
+
<p>Click <a href="#{request.referer}">here</a> to return
|
95
|
+
to the previous page.</p>
|
96
|
+
}
|
97
|
+
if request.error_log
|
98
|
+
body << %{
|
99
|
+
<h3>Request error log</h3>
|
100
|
+
<pre>#{request.error_log.join("\n")}</pre>
|
101
|
+
}
|
102
|
+
end
|
103
|
+
body << %{
|
104
|
+
<h3>Exception</h3>
|
105
|
+
<pre>#{pp_exception(e)}</pre>
|
106
|
+
}
|
107
|
+
request.out_buffer = body
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# gmosx: optimize me, do something more clever!!!
|
112
|
+
request.session.synchronize!
|
113
|
+
|
114
|
+
wres.status = request.status
|
115
|
+
wres.header = request.out
|
116
|
+
wres.cookies = request.out_cookies.values()
|
117
|
+
wres.body = request.out_buffer
|
118
|
+
end
|
119
|
+
|
120
|
+
def do_POST(wreq, wres)
|
121
|
+
do_GET(wreq, wres)
|
122
|
+
end
|
123
|
+
|
124
|
+
#-------------------------------------------------------------------------------
|
125
|
+
|
126
|
+
private
|
127
|
+
|
128
|
+
# Convert a webrick request to an engine request
|
129
|
+
# FIXME: this is UNOPTIMIZED code!
|
130
|
+
#
|
131
|
+
def create_request(wreq)
|
132
|
+
# FIXME: use a resource pool!
|
133
|
+
request = N::App::Request.new
|
134
|
+
|
135
|
+
request.uri = wreq.unparsed_uri
|
136
|
+
request.translated_uri = wreq.path_info
|
137
|
+
request.path = wreq.path
|
138
|
+
# request.path_info = wreq.path_info
|
139
|
+
request.query_string = wreq.query_string
|
140
|
+
request.method = wreq.request_method
|
141
|
+
# request.remote_addr = wreq["REMOTE_ADDR"]
|
142
|
+
# gmosx: we use an apache proxy for the moment.
|
143
|
+
request.remote_addr = wreq["X-FORWARDED-FOR"]
|
144
|
+
|
145
|
+
# gmosx: remove this ??
|
146
|
+
request.in = {}
|
147
|
+
wreq.header.each { |k, v|
|
148
|
+
# gmosx: upcase to make compatible with n2 codebase.
|
149
|
+
request.in[k.upcase] = v[0]
|
150
|
+
}
|
151
|
+
|
152
|
+
request.parts = {}
|
153
|
+
request.parameters = {}
|
154
|
+
|
155
|
+
wreq.query.each { |k, v|
|
156
|
+
if v.filename
|
157
|
+
request.parts[k] = N::App::RequestPart.new(v.filename, v)
|
158
|
+
else
|
159
|
+
request.parameters[k] = v
|
160
|
+
end
|
161
|
+
}
|
162
|
+
|
163
|
+
request.in_cookies = {}
|
164
|
+
wreq.cookies.each { |c|
|
165
|
+
request.in_cookies[c.name] = c
|
166
|
+
}
|
167
|
+
|
168
|
+
# gmosx: is this STILL needed??
|
169
|
+
#
|
170
|
+
# INVESTIGATE, FIXME: this is a hack!
|
171
|
+
# apache prepends $srv_url and fucks up msie.
|
172
|
+
# FIXME: add unit test for this!
|
173
|
+
|
174
|
+
if ref = request.in["REFERER"]
|
175
|
+
split_re = Regexp.new($srv_url) unless split_re
|
176
|
+
xref = ref.split(split_re).last
|
177
|
+
if N::StringUtils.valid?(xref)
|
178
|
+
request.in["REFERER"] = xref
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
return request
|
183
|
+
end
|
184
|
+
|
185
|
+
# Create session
|
186
|
+
#
|
187
|
+
def create_session(request)
|
188
|
+
session = nil
|
189
|
+
session_id = nil
|
190
|
+
|
191
|
+
# gmosx: i have to fix the get_cookie method to return a
|
192
|
+
# full cookie object.
|
193
|
+
|
194
|
+
if session_id = request.get_cookie(N::App::Session::COOKIE_NAME)
|
195
|
+
session = $sessions[session_id]
|
196
|
+
$log.debug "Stale session cookie: #{session_id}" unless session
|
197
|
+
# FIXME: remove cookie if stale!
|
198
|
+
else
|
199
|
+
session_id = N::App::Session.calculate_id()
|
200
|
+
cookie = N::App::Cookie.new(N::App::Session::COOKIE_NAME, session_id)
|
201
|
+
request.out_cookies[N::App::Session::COOKIE_NAME] = cookie
|
202
|
+
end
|
203
|
+
|
204
|
+
# session not found and must be created
|
205
|
+
unless session
|
206
|
+
session = N::App::Session.new(session_id)
|
207
|
+
end
|
208
|
+
|
209
|
+
return session
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
end; end # module
|