rubysl-cgi-session 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: be8113d5777dcd44f19953df53b5930ced231f2a
4
+ data.tar.gz: ae27543b310806b0b8eaca6657b8058d9d5d8b12
5
+ SHA512:
6
+ metadata.gz: 2a60a0678b8889e13337d81ceac3215d7bb85894c3ddf3725af681ae167f91865e830ba2de81a33888985151c089446f795597276dd2e70dc8ede4085cf1fadc
7
+ data.tar.gz: 630f5f071410e7a963567fa319fa561cccdb2b91726529468a900411061354ce661ba55804dbb09f83d40a9587332e68db049c49b31ecb505f2e61c55ff4e708
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ .rbx
@@ -0,0 +1,8 @@
1
+ language: ruby
2
+ before_install:
3
+ - gem update --system
4
+ - gem --version
5
+ - gem install rubysl-bundler
6
+ script: bundle exec mspec spec
7
+ rvm:
8
+ - rbx-nightly-18mode
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rubysl-cgi-session.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,25 @@
1
+ Copyright (c) 2013, Brian Shirai
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are met:
6
+
7
+ 1. Redistributions of source code must retain the above copyright notice, this
8
+ list of conditions and the following disclaimer.
9
+ 2. Redistributions in binary form must reproduce the above copyright notice,
10
+ this list of conditions and the following disclaimer in the documentation
11
+ and/or other materials provided with the distribution.
12
+ 3. Neither the name of the library nor the names of its contributors may be
13
+ used to endorse or promote products derived from this software without
14
+ specific prior written permission.
15
+
16
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19
+ DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY DIRECT,
20
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23
+ OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
25
+ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,29 @@
1
+ # RubySL::Cgi::Session
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'rubysl-cgi-session'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install rubysl-cgi-session
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1 @@
1
+ require "rubysl/cgi/session"
@@ -0,0 +1,111 @@
1
+ #
2
+ # cgi/session/pstore.rb - persistent storage of marshalled session data
3
+ #
4
+ # Documentation: William Webber (william@williamwebber.com)
5
+ #
6
+ # == Overview
7
+ #
8
+ # This file provides the CGI::Session::PStore class, which builds
9
+ # persistent of session data on top of the pstore library. See
10
+ # cgi/session.rb for more details on session storage managers.
11
+
12
+ require 'cgi/session'
13
+ require 'pstore'
14
+
15
+ class CGI
16
+ class Session
17
+ # PStore-based session storage class.
18
+ #
19
+ # This builds upon the top-level PStore class provided by the
20
+ # library file pstore.rb. Session data is marshalled and stored
21
+ # in a file. File locking and transaction services are provided.
22
+ class PStore
23
+ # Create a new CGI::Session::PStore instance
24
+ #
25
+ # This constructor is used internally by CGI::Session. The
26
+ # user does not generally need to call it directly.
27
+ #
28
+ # +session+ is the session for which this instance is being
29
+ # created. The session id must only contain alphanumeric
30
+ # characters; automatically generated session ids observe
31
+ # this requirement.
32
+ #
33
+ # +option+ is a hash of options for the initializer. The
34
+ # following options are recognised:
35
+ #
36
+ # tmpdir:: the directory to use for storing the PStore
37
+ # file. Defaults to Dir::tmpdir (generally "/tmp"
38
+ # on Unix systems).
39
+ # prefix:: the prefix to add to the session id when generating
40
+ # the filename for this session's PStore file.
41
+ # Defaults to the empty string.
42
+ #
43
+ # This session's PStore file will be created if it does
44
+ # not exist, or opened if it does.
45
+ def initialize(session, option={})
46
+ dir = option['tmpdir'] || Dir::tmpdir
47
+ prefix = option['prefix'] || ''
48
+ id = session.session_id
49
+ require 'digest/md5'
50
+ md5 = Digest::MD5.hexdigest(id)[0,16]
51
+ path = dir+"/"+prefix+md5
52
+ path.untaint
53
+ if File::exist?(path)
54
+ @hash = nil
55
+ else
56
+ unless session.new_session
57
+ raise CGI::Session::NoSession, "uninitialized session"
58
+ end
59
+ @hash = {}
60
+ end
61
+ @p = ::PStore.new(path)
62
+ @p.transaction do |p|
63
+ File.chmod(0600, p.path)
64
+ end
65
+ end
66
+
67
+ # Restore session state from the session's PStore file.
68
+ #
69
+ # Returns the session state as a hash.
70
+ def restore
71
+ unless @hash
72
+ @p.transaction do
73
+ @hash = @p['hash'] || {}
74
+ end
75
+ end
76
+ @hash
77
+ end
78
+
79
+ # Save session state to the session's PStore file.
80
+ def update
81
+ @p.transaction do
82
+ @p['hash'] = @hash
83
+ end
84
+ end
85
+
86
+ # Update and close the session's PStore file.
87
+ def close
88
+ update
89
+ end
90
+
91
+ # Close and delete the session's PStore file.
92
+ def delete
93
+ path = @p.path
94
+ File::unlink path
95
+ end
96
+
97
+ end
98
+ end
99
+ end
100
+
101
+ if $0 == __FILE__
102
+ # :enddoc:
103
+ STDIN.reopen("/dev/null")
104
+ cgi = CGI.new
105
+ session = CGI::Session.new(cgi, 'database_manager' => CGI::Session::PStore)
106
+ session['key'] = {'k' => 'v'}
107
+ puts session['key'].class
108
+ fail unless Hash === session['key']
109
+ puts session['key'].inspect
110
+ fail unless session['key'].inspect == '{"k"=>"v"}'
111
+ end
@@ -0,0 +1,2 @@
1
+ require "rubysl/cgi/session/session"
2
+ require "rubysl/cgi/session/version"
@@ -0,0 +1,500 @@
1
+ #
2
+ # cgi/session.rb - session support for cgi scripts
3
+ #
4
+ # Copyright (C) 2001 Yukihiro "Matz" Matsumoto
5
+ # Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
6
+ # Copyright (C) 2000 Information-technology Promotion Agency, Japan
7
+ #
8
+ # Author: Yukihiro "Matz" Matsumoto
9
+ #
10
+ # Documentation: William Webber (william@williamwebber.com)
11
+ #
12
+ # == Overview
13
+ #
14
+ # This file provides the +CGI::Session+ class, which provides session
15
+ # support for CGI scripts. A session is a sequence of HTTP requests
16
+ # and responses linked together and associated with a single client.
17
+ # Information associated with the session is stored
18
+ # on the server between requests. A session id is passed between client
19
+ # and server with every request and response, transparently
20
+ # to the user. This adds state information to the otherwise stateless
21
+ # HTTP request/response protocol.
22
+ #
23
+ # See the documentation to the +CGI::Session+ class for more details
24
+ # and examples of usage. See cgi.rb for the +CGI+ class itself.
25
+
26
+ require 'cgi'
27
+ require 'tmpdir'
28
+
29
+ class CGI
30
+
31
+ # Class representing an HTTP session. See documentation for the file
32
+ # cgi/session.rb for an introduction to HTTP sessions.
33
+ #
34
+ # == Lifecycle
35
+ #
36
+ # A CGI::Session instance is created from a CGI object. By default,
37
+ # this CGI::Session instance will start a new session if none currently
38
+ # exists, or continue the current session for this client if one does
39
+ # exist. The +new_session+ option can be used to either always or
40
+ # never create a new session. See #new() for more details.
41
+ #
42
+ # #delete() deletes a session from session storage. It
43
+ # does not however remove the session id from the client. If the client
44
+ # makes another request with the same id, the effect will be to start
45
+ # a new session with the old session's id.
46
+ #
47
+ # == Setting and retrieving session data.
48
+ #
49
+ # The Session class associates data with a session as key-value pairs.
50
+ # This data can be set and retrieved by indexing the Session instance
51
+ # using '[]', much the same as hashes (although other hash methods
52
+ # are not supported).
53
+ #
54
+ # When session processing has been completed for a request, the
55
+ # session should be closed using the close() method. This will
56
+ # store the session's state to persistent storage. If you want
57
+ # to store the session's state to persistent storage without
58
+ # finishing session processing for this request, call the update()
59
+ # method.
60
+ #
61
+ # == Storing session state
62
+ #
63
+ # The caller can specify what form of storage to use for the session's
64
+ # data with the +database_manager+ option to CGI::Session::new. The
65
+ # following storage classes are provided as part of the standard library:
66
+ #
67
+ # CGI::Session::FileStore:: stores data as plain text in a flat file. Only
68
+ # works with String data. This is the default
69
+ # storage type.
70
+ # CGI::Session::MemoryStore:: stores data in an in-memory hash. The data
71
+ # only persists for as long as the current ruby
72
+ # interpreter instance does.
73
+ # CGI::Session::PStore:: stores data in Marshalled format. Provided by
74
+ # cgi/session/pstore.rb. Supports data of any type,
75
+ # and provides file-locking and transaction support.
76
+ #
77
+ # Custom storage types can also be created by defining a class with
78
+ # the following methods:
79
+ #
80
+ # new(session, options)
81
+ # restore # returns hash of session data.
82
+ # update
83
+ # close
84
+ # delete
85
+ #
86
+ # Changing storage type mid-session does not work. Note in particular
87
+ # that by default the FileStore and PStore session data files have the
88
+ # same name. If your application switches from one to the other without
89
+ # making sure that filenames will be different
90
+ # and clients still have old sessions lying around in cookies, then
91
+ # things will break nastily!
92
+ #
93
+ # == Maintaining the session id.
94
+ #
95
+ # Most session state is maintained on the server. However, a session
96
+ # id must be passed backwards and forwards between client and server
97
+ # to maintain a reference to this session state.
98
+ #
99
+ # The simplest way to do this is via cookies. The CGI::Session class
100
+ # provides transparent support for session id communication via cookies
101
+ # if the client has cookies enabled.
102
+ #
103
+ # If the client has cookies disabled, the session id must be included
104
+ # as a parameter of all requests sent by the client to the server. The
105
+ # CGI::Session class in conjunction with the CGI class will transparently
106
+ # add the session id as a hidden input field to all forms generated
107
+ # using the CGI#form() HTML generation method. No built-in support is
108
+ # provided for other mechanisms, such as URL re-writing. The caller is
109
+ # responsible for extracting the session id from the session_id
110
+ # attribute and manually encoding it in URLs and adding it as a hidden
111
+ # input to HTML forms created by other mechanisms. Also, session expiry
112
+ # is not automatically handled.
113
+ #
114
+ # == Examples of use
115
+ #
116
+ # === Setting the user's name
117
+ #
118
+ # require 'cgi'
119
+ # require 'cgi/session'
120
+ # require 'cgi/session/pstore' # provides CGI::Session::PStore
121
+ #
122
+ # cgi = CGI.new("html4")
123
+ #
124
+ # session = CGI::Session.new(cgi,
125
+ # 'database_manager' => CGI::Session::PStore, # use PStore
126
+ # 'session_key' => '_rb_sess_id', # custom session key
127
+ # 'session_expires' => Time.now + 30 * 60, # 30 minute timeout
128
+ # 'prefix' => 'pstore_sid_') # PStore option
129
+ # if cgi.has_key?('user_name') and cgi['user_name'] != ''
130
+ # # coerce to String: cgi[] returns the
131
+ # # string-like CGI::QueryExtension::Value
132
+ # session['user_name'] = cgi['user_name'].to_s
133
+ # elsif !session['user_name']
134
+ # session['user_name'] = "guest"
135
+ # end
136
+ # session.close
137
+ #
138
+ # === Creating a new session safely
139
+ #
140
+ # require 'cgi'
141
+ # require 'cgi/session'
142
+ #
143
+ # cgi = CGI.new("html4")
144
+ #
145
+ # # We make sure to delete an old session if one exists,
146
+ # # not just to free resources, but to prevent the session
147
+ # # from being maliciously hijacked later on.
148
+ # begin
149
+ # session = CGI::Session.new(cgi, 'new_session' => false)
150
+ # session.delete
151
+ # rescue ArgumentError # if no old session
152
+ # end
153
+ # session = CGI::Session.new(cgi, 'new_session' => true)
154
+ # session.close
155
+ #
156
+ class Session
157
+
158
+ class NoSession < RuntimeError #:nodoc:
159
+ end
160
+
161
+ # The id of this session.
162
+ attr_reader :session_id, :new_session
163
+
164
+ def Session::callback(dbman) #:nodoc:
165
+ Proc.new{
166
+ dbman[0].close unless dbman.empty?
167
+ }
168
+ end
169
+
170
+ # Create a new session id.
171
+ #
172
+ # The session id is an MD5 hash based upon the time,
173
+ # a random number, and a constant string. This routine
174
+ # is used internally for automatically generated
175
+ # session ids.
176
+ def create_new_id
177
+ require 'securerandom'
178
+ begin
179
+ session_id = SecureRandom.hex(16)
180
+ rescue NotImplementedError
181
+ require 'digest/md5'
182
+ md5 = Digest::MD5::new
183
+ now = Time::now
184
+ md5.update(now.to_s)
185
+ md5.update(String(now.usec))
186
+ md5.update(String(rand(0)))
187
+ md5.update(String($$))
188
+ md5.update('foobar')
189
+ session_id = md5.hexdigest
190
+ end
191
+ session_id
192
+ end
193
+ private :create_new_id
194
+
195
+ # Create a new CGI::Session object for +request+.
196
+ #
197
+ # +request+ is an instance of the +CGI+ class (see cgi.rb).
198
+ # +option+ is a hash of options for initialising this
199
+ # CGI::Session instance. The following options are
200
+ # recognised:
201
+ #
202
+ # session_key:: the parameter name used for the session id.
203
+ # Defaults to '_session_id'.
204
+ # session_id:: the session id to use. If not provided, then
205
+ # it is retrieved from the +session_key+ parameter
206
+ # of the request, or automatically generated for
207
+ # a new session.
208
+ # new_session:: if true, force creation of a new session. If not set,
209
+ # a new session is only created if none currently
210
+ # exists. If false, a new session is never created,
211
+ # and if none currently exists and the +session_id+
212
+ # option is not set, an ArgumentError is raised.
213
+ # database_manager:: the name of the class providing storage facilities
214
+ # for session state persistence. Built-in support
215
+ # is provided for +FileStore+ (the default),
216
+ # +MemoryStore+, and +PStore+ (from
217
+ # cgi/session/pstore.rb). See the documentation for
218
+ # these classes for more details.
219
+ #
220
+ # The following options are also recognised, but only apply if the
221
+ # session id is stored in a cookie.
222
+ #
223
+ # session_expires:: the time the current session expires, as a
224
+ # +Time+ object. If not set, the session will terminate
225
+ # when the user's browser is closed.
226
+ # session_domain:: the hostname domain for which this session is valid.
227
+ # If not set, defaults to the hostname of the server.
228
+ # session_secure:: if +true+, this session will only work over HTTPS.
229
+ # session_path:: the path for which this session applies. Defaults
230
+ # to the directory of the CGI script.
231
+ #
232
+ # +option+ is also passed on to the session storage class initializer; see
233
+ # the documentation for each session storage class for the options
234
+ # they support.
235
+ #
236
+ # The retrieved or created session is automatically added to +request+
237
+ # as a cookie, and also to its +output_hidden+ table, which is used
238
+ # to add hidden input elements to forms.
239
+ #
240
+ # *WARNING* the +output_hidden+
241
+ # fields are surrounded by a <fieldset> tag in HTML 4 generation, which
242
+ # is _not_ invisible on many browsers; you may wish to disable the
243
+ # use of fieldsets with code similar to the following
244
+ # (see http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-list/37805)
245
+ #
246
+ # cgi = CGI.new("html4")
247
+ # class << cgi
248
+ # undef_method :fieldset
249
+ # end
250
+ #
251
+ def initialize(request, option={})
252
+ @new_session = false
253
+ session_key = option['session_key'] || '_session_id'
254
+ session_id = option['session_id']
255
+ unless session_id
256
+ if option['new_session']
257
+ session_id = create_new_id
258
+ @new_session = true
259
+ end
260
+ end
261
+ unless session_id
262
+ if request.key?(session_key)
263
+ session_id = request[session_key]
264
+ session_id = session_id.read if session_id.respond_to?(:read)
265
+ end
266
+ unless session_id
267
+ session_id, = request.cookies[session_key]
268
+ end
269
+ unless session_id
270
+ unless option.fetch('new_session', true)
271
+ raise ArgumentError, "session_key `%s' should be supplied"%session_key
272
+ end
273
+ session_id = create_new_id
274
+ @new_session = true
275
+ end
276
+ end
277
+ @session_id = session_id
278
+ dbman = option['database_manager'] || FileStore
279
+ begin
280
+ @dbman = dbman::new(self, option)
281
+ rescue NoSession
282
+ unless option.fetch('new_session', true)
283
+ raise ArgumentError, "invalid session_id `%s'"%session_id
284
+ end
285
+ session_id = @session_id = create_new_id unless session_id
286
+ @new_session = true
287
+ retry
288
+ end
289
+ request.instance_eval do
290
+ @output_hidden = {session_key => session_id} unless option['no_hidden']
291
+ @output_cookies = [
292
+ Cookie::new("name" => session_key,
293
+ "value" => session_id,
294
+ "expires" => option['session_expires'],
295
+ "domain" => option['session_domain'],
296
+ "secure" => option['session_secure'],
297
+ "path" => if option['session_path'] then
298
+ option['session_path']
299
+ elsif ENV["SCRIPT_NAME"] then
300
+ File::dirname(ENV["SCRIPT_NAME"])
301
+ else
302
+ ""
303
+ end)
304
+ ] unless option['no_cookies']
305
+ end
306
+ @dbprot = [@dbman]
307
+ ObjectSpace::define_finalizer(self, Session::callback(@dbprot))
308
+ end
309
+
310
+ # Retrieve the session data for key +key+.
311
+ def [](key)
312
+ @data ||= @dbman.restore
313
+ @data[key]
314
+ end
315
+
316
+ # Set the session date for key +key+.
317
+ def []=(key, val)
318
+ @write_lock ||= true
319
+ @data ||= @dbman.restore
320
+ @data[key] = val
321
+ end
322
+
323
+ # Store session data on the server. For some session storage types,
324
+ # this is a no-op.
325
+ def update
326
+ @dbman.update
327
+ end
328
+
329
+ # Store session data on the server and close the session storage.
330
+ # For some session storage types, this is a no-op.
331
+ def close
332
+ @dbman.close
333
+ @dbprot.clear
334
+ end
335
+
336
+ # Delete the session from storage. Also closes the storage.
337
+ #
338
+ # Note that the session's data is _not_ automatically deleted
339
+ # upon the session expiring.
340
+ def delete
341
+ @dbman.delete
342
+ @dbprot.clear
343
+ end
344
+
345
+ # File-based session storage class.
346
+ #
347
+ # Implements session storage as a flat file of 'key=value' values.
348
+ # This storage type only works directly with String values; the
349
+ # user is responsible for converting other types to Strings when
350
+ # storing and from Strings when retrieving.
351
+ class FileStore
352
+ # Create a new FileStore instance.
353
+ #
354
+ # This constructor is used internally by CGI::Session. The
355
+ # user does not generally need to call it directly.
356
+ #
357
+ # +session+ is the session for which this instance is being
358
+ # created. The session id must only contain alphanumeric
359
+ # characters; automatically generated session ids observe
360
+ # this requirement.
361
+ #
362
+ # +option+ is a hash of options for the initializer. The
363
+ # following options are recognised:
364
+ #
365
+ # tmpdir:: the directory to use for storing the FileStore
366
+ # file. Defaults to Dir::tmpdir (generally "/tmp"
367
+ # on Unix systems).
368
+ # prefix:: the prefix to add to the session id when generating
369
+ # the filename for this session's FileStore file.
370
+ # Defaults to the empty string.
371
+ # suffix:: the prefix to add to the session id when generating
372
+ # the filename for this session's FileStore file.
373
+ # Defaults to the empty string.
374
+ #
375
+ # This session's FileStore file will be created if it does
376
+ # not exist, or opened if it does.
377
+ def initialize(session, option={})
378
+ dir = option['tmpdir'] || Dir::tmpdir
379
+ prefix = option['prefix'] || ''
380
+ suffix = option['suffix'] || ''
381
+ id = session.session_id
382
+ require 'digest/md5'
383
+ md5 = Digest::MD5.hexdigest(id)[0,16]
384
+ @path = dir+"/"+prefix+md5+suffix
385
+ if File::exist? @path
386
+ @hash = nil
387
+ else
388
+ unless session.new_session
389
+ raise CGI::Session::NoSession, "uninitialized session"
390
+ end
391
+ @hash = {}
392
+ end
393
+ end
394
+
395
+ # Restore session state from the session's FileStore file.
396
+ #
397
+ # Returns the session state as a hash.
398
+ def restore
399
+ unless @hash
400
+ @hash = {}
401
+ begin
402
+ lockf = File.open(@path+".lock", "r")
403
+ lockf.flock File::LOCK_SH
404
+ f = File.open(@path, 'r')
405
+ for line in f
406
+ line.chomp!
407
+ k, v = line.split('=',2)
408
+ @hash[CGI::unescape(k)] = CGI::unescape(v)
409
+ end
410
+ ensure
411
+ f.close unless f.nil?
412
+ lockf.close if lockf
413
+ end
414
+ end
415
+ @hash
416
+ end
417
+
418
+ # Save session state to the session's FileStore file.
419
+ def update
420
+ return unless @hash
421
+ begin
422
+ lockf = File.open(@path+".lock", File::CREAT|File::RDWR, 0600)
423
+ lockf.flock File::LOCK_EX
424
+ f = File.open(@path+".new", File::CREAT|File::TRUNC|File::WRONLY, 0600)
425
+ for k,v in @hash
426
+ f.printf "%s=%s\n", CGI::escape(k), CGI::escape(String(v))
427
+ end
428
+ f.close
429
+ File.rename @path+".new", @path
430
+ ensure
431
+ f.close if f and !f.closed?
432
+ lockf.close if lockf
433
+ end
434
+ end
435
+
436
+ # Update and close the session's FileStore file.
437
+ def close
438
+ update
439
+ end
440
+
441
+ # Close and delete the session's FileStore file.
442
+ def delete
443
+ File::unlink @path+".lock" rescue nil
444
+ File::unlink @path+".new" rescue nil
445
+ File::unlink @path
446
+ rescue Errno::ENOENT
447
+ end
448
+ end
449
+
450
+ # In-memory session storage class.
451
+ #
452
+ # Implements session storage as a global in-memory hash. Session
453
+ # data will only persist for as long as the ruby interpreter
454
+ # instance does.
455
+ class MemoryStore
456
+ GLOBAL_HASH_TABLE = {} #:nodoc:
457
+
458
+ # Create a new MemoryStore instance.
459
+ #
460
+ # +session+ is the session this instance is associated with.
461
+ # +option+ is a list of initialisation options. None are
462
+ # currently recognised.
463
+ def initialize(session, option=nil)
464
+ @session_id = session.session_id
465
+ unless GLOBAL_HASH_TABLE.key?(@session_id)
466
+ unless session.new_session
467
+ raise CGI::Session::NoSession, "uninitialized session"
468
+ end
469
+ GLOBAL_HASH_TABLE[@session_id] = {}
470
+ end
471
+ end
472
+
473
+ # Restore session state.
474
+ #
475
+ # Returns session data as a hash.
476
+ def restore
477
+ GLOBAL_HASH_TABLE[@session_id]
478
+ end
479
+
480
+ # Update session state.
481
+ #
482
+ # A no-op.
483
+ def update
484
+ # don't need to update; hash is shared
485
+ end
486
+
487
+ # Close session storage.
488
+ #
489
+ # A no-op.
490
+ def close
491
+ # don't need to close
492
+ end
493
+
494
+ # Delete the session state.
495
+ def delete
496
+ GLOBAL_HASH_TABLE.delete(@session_id)
497
+ end
498
+ end
499
+ end
500
+ end
@@ -0,0 +1,7 @@
1
+ module RubySL
2
+ module CGI
3
+ module Session
4
+ VERSION = "1.0.0"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ require './lib/rubysl/cgi/session/version'
3
+
4
+ Gem::Specification.new do |spec|
5
+ spec.name = "rubysl-cgi-session"
6
+ spec.version = RubySL::CGI::Session::VERSION
7
+ spec.authors = ["Brian Shirai"]
8
+ spec.email = ["brixen@gmail.com"]
9
+ spec.description = %q{Ruby standard library cgi-session.}
10
+ spec.summary = %q{Ruby standard library cgi-session.}
11
+ spec.homepage = "https://github.com/rubysl/rubysl-cgi-session"
12
+ spec.license = "BSD"
13
+
14
+ spec.files = `git ls-files`.split($/)
15
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
16
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
17
+ spec.require_paths = ["lib"]
18
+
19
+ spec.add_development_dependency "bundler", "~> 1.3"
20
+ spec.add_development_dependency "rake", "~> 10.0"
21
+ spec.add_development_dependency "mspec", "~> 1.5"
22
+ spec.add_development_dependency "rubysl-prettyprint", "~> 1.0"
23
+ end
metadata ADDED
@@ -0,0 +1,112 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rubysl-cgi-session
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Brian Shirai
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-12-25 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: mspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '1.5'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '1.5'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubysl-prettyprint
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '1.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '1.0'
69
+ description: Ruby standard library cgi-session.
70
+ email:
71
+ - brixen@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - .gitignore
77
+ - .travis.yml
78
+ - Gemfile
79
+ - LICENSE
80
+ - README.md
81
+ - Rakefile
82
+ - lib/cgi/session.rb
83
+ - lib/cgi/session/pstore.rb
84
+ - lib/rubysl/cgi/session.rb
85
+ - lib/rubysl/cgi/session/session.rb
86
+ - lib/rubysl/cgi/session/version.rb
87
+ - rubysl-cgi-session.gemspec
88
+ homepage: https://github.com/rubysl/rubysl-cgi-session
89
+ licenses:
90
+ - BSD
91
+ metadata: {}
92
+ post_install_message:
93
+ rdoc_options: []
94
+ require_paths:
95
+ - lib
96
+ required_ruby_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - '>='
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
101
+ required_rubygems_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - '>='
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ requirements: []
107
+ rubyforge_project:
108
+ rubygems_version: 2.0.7
109
+ signing_key:
110
+ specification_version: 4
111
+ summary: Ruby standard library cgi-session.
112
+ test_files: []