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 12require 'cgi/session' 13require 'pstore' 14 15class 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 99end 100 101if $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"}' 111end 112