1 | #
|
---|
2 | # cgi/session/pstore.rb - persistent storage of marshalled session data
|
---|
3 | #
|
---|
4 | # Documentation: William Webber ([email protected])
|
---|
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 initialiser. 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
|
---|