diff --git a/lib/cgi/session.rb b/lib/cgi/session.rb index c0a9ae1..b69857b 100644 --- a/lib/cgi/session.rb +++ b/lib/cgi/session.rb @@ -206,19 +206,28 @@ def create_new_id # on Unix systems). # prefix:: the prefix to add to the session id when generating # the filename for this session's FileStore file. - # Defaults to "cgi_sid_". + # Defaults to the empty string. # suffix:: the prefix to add to the session id when generating # the filename for this session's FileStore file. # Defaults to the empty string. + # digest:: the digest algorithm to hash the session id when + # generating the filename for this session's FileStore + # file. Defaults to "SHA256". + # length:: the length of the session id part of the filestore, + # excluding +prefix+ and +suffix+ parts. Defaults to 16. def new_store_file(option={}) # :nodoc: dir = option['tmpdir'] || Dir::tmpdir prefix = option['prefix'] suffix = option['suffix'] - require 'digest' - sha256 = Digest::SHA256.hexdigest(session_id)[0,16] + algorithm = option['digest'] || 'SHA256' + if String === algorithm + require 'digest' + algorithm = Digest(algorithm) + end + digest = algorithm.hexdigest(session_id)[0, option['length'] || 16] path = dir+"/" path << prefix if prefix - path << sha256 + path << digest path << suffix if suffix if File::exist? path hash = nil @@ -410,6 +419,9 @@ class FileStore # suffix:: the prefix to add to the session id when generating # the filename for this session's FileStore file. # Defaults to the empty string. + # digest:: the digest algorithm to hash the session id when + # generating the filename for this session's FileStore + # file. Defaults to "MD5". # # This session's FileStore file will be created if it does # not exist, or opened if it does. diff --git a/test/cgi/test_cgi_session.rb b/test/cgi/test_cgi_session.rb index 32b907d..381c149 100644 --- a/test/cgi/test_cgi_session.rb +++ b/test/cgi/test_cgi_session.rb @@ -55,8 +55,8 @@ def test_cgi_session_filestore assert_equal(value1,session["key1"]) assert_equal(value2,session["key2"]) session.close - end + def test_cgi_session_pstore update_env( 'REQUEST_METHOD' => 'GET', @@ -92,6 +92,7 @@ def test_cgi_session_pstore assert_equal(value2,session["key2"]) session.close end if defined?(::PStore) + def test_cgi_session_specify_session_id update_env( 'REQUEST_METHOD' => 'GET', @@ -130,6 +131,7 @@ def test_cgi_session_specify_session_id assert_equal("foo",session.session_id) session.close end + def test_cgi_session_specify_session_key update_env( 'REQUEST_METHOD' => 'GET', @@ -166,4 +168,41 @@ def test_cgi_session_specify_session_key assert_equal(value2,session["key2"]) session.close end + + def test_cgi_session_filestore_path + session_id = "banana" + path_default = session_file_store_path("tmpdir"=>@session_dir, "session_id"=>session_id) + assert_session_filestore_path(path_default) + assert_equal path_default, session_file_store_path("tmpdir"=>@session_dir, "session_id"=>session_id) + path_sha512 = session_file_store_path("tmpdir"=>@session_dir, "session_id"=>session_id, "digest"=>"SHA512") + assert_session_filestore_path(path_default) + assert_not_equal path_sha512, path_default + path_long = session_file_store_path("tmpdir"=>@session_dir, "session_id"=>session_id, "length"=>32) + assert_equal path_default.length+16, path_long.length + assert_send [path_long, :start_with?, path_default] + + path = session_file_store_path("tmpdir"=>@session_dir, "session_id"=>session_id, "digest"=>Digest::SHA256) + assert_equal path_default, path + path = assert_session_filestore_path(session_file_store_path("tmpdir"=>@session_dir, "session_id"=>session_id, "digest"=>Digest::SHA512)) + assert_equal path_sha512, path + end + + private + + def assert_session_filestore_path(path, dir: @session_dir, prefix: "cgi_sid_", suffix: nil) + base = File.basename(path) + assert_equal dir, File.dirname(path) + assert_operator base, :start_with?, prefix if prefix + assert_operator base, :end_with?, suffix if suffix + path + end + + def session_file_store_path(options) + cgi = Object.new + session = CGI::Session.new(cgi, options) + session.delete + dbman = session.instance_variable_get(:@dbman) + assert_kind_of(CGI::Session::FileStore, dbman) + dbman.instance_variable_get(:@path) + end end