1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
ruby--ruby/lib/cgi/session.rb
matz 87beea4496 * enum.c (enum_inject): new method.
* gc.c (rb_gc_call_finalizer_at_exit): clear klass member of
  terminating object.

* eval.c (rb_call): raise exception for terminated object.

* bignum.c (bigdivrem): t2 might be too big for signed long; do
  not use rb_int2big(), but rb_uint2big().

* error.c (rb_load_fail): new func to report LoadError.

* ruby.c (load_file): use rb_load_fail.

* eval.c (ruby_finalize): should enclosed by PUSH_TAG/POP_TAG.

* gc.c (rb_gc_mark): link 2 of NODE_IFUNC should not be explicitly
  marked.  it may contain non object pointer.

* re.c (reg_s_last_match): Regexp::last_match(nth) returns nth
  substring of the match  (alternative for $& and $<digit>).

* eval.c (rb_mod_define_method): wrong comparison for blocks.

* gc.c (id2ref): should handle Symbol too.

* gc.c (id2ref): should print original ptr value

* eval.c (rb_iterate): NODE_CFUNC does not protect its data
  (nd_tval), so create new node NODE_IFUNC for iteration C
  function.

* eval.c (rb_yield_0): use NODE_IFUNC.

* gc.c (rb_gc_mark): support NODE_IFUNC.

* gc.c (mem_error): prohibit recursive mem_error().
  (ruby-bugs-ja:PR#36)

* eval.c (rb_thread_fd_writable): should not switch context if
  rb_thread_critical is set.

* eval.c (rb_thread_wait_fd): ditto.

* eval.c (rb_thread_wait_for): ditto.

* eval.c (rb_thread_select): ditto.

* eval.c (rb_thread_join): join during critical section causes
  deadlock.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1090 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2001-01-09 07:26:21 +00:00

176 lines
3.3 KiB
Ruby

# Copyright (C) 2001 Yukihiro "Matz" Matsumoto
# Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
# Copyright (C) 2000 Information-technology Promotion Agency, Japan
require 'cgi'
require 'final'
class CGI
class Session
attr_reader :session_id
def Session::callback(dbman)
lambda{
dbman.close
}
end
def Session::create_new_id
require 'md5'
md5 = MD5::new
md5.update(String(Time::now))
md5.update(String(rand(0)))
md5.update(String($$))
md5.update('foobar')
md5.hexdigest[0,16]
end
private :create_new_id
def initialize(request, option={})
session_key = option['session_key'] || '_session_id'
id, = option['session_id']
unless id
if option['new_session']
id = Session::create_new_id
end
end
unless id
id, = request[session_key]
unless id
id, = request.cookies[session_key]
end
unless id
if option.key?('new_session') and not option['new_session']
raise ArgumentError, "session_key `%s' should be supplied"%session_key
end
id = Session::create_new_id
end
end
@session_id = id
dbman = option['database_manager'] || FileStore
@dbman = dbman::new(self, option)
request.instance_eval do
@output_hidden = {session_key => id}
@output_cookies = [
Cookie::new("name" => session_key,
"value" => id,
"path" => if option['session_path'] then
option['session_path']
elsif ENV["SCRIPT_NAME"] then
File::dirname(ENV["SCRIPT_NAME"])
else
""
end)
]
end
ObjectSpace::define_finalizer(self, Session::callback(@dbman))
end
def [](key)
unless @data
@data = @dbman.restore
end
@data[key]
end
def []=(key, val)
unless @write_lock
@write_lock = true
end
unless @data
@data = @dbman.restore
end
@data[key] = String(val)
end
def update
@dbman.update
end
def close
@dbman.close
end
def delete
@dbman.delete
end
class FileStore
def initialize(session, option={})
dir = option['tmpdir'] || ENV['TMP'] || '/tmp'
prefix = option['prefix'] || ''
path = dir+"/"+prefix+session.session_id
path.untaint
unless File::exist? path
@hash = {}
end
begin
@f = open(path, "r+")
rescue Errno::ENOENT
@f = open(path, "w+")
end
end
def restore
unless @hash
@hash = {}
@f.flock File::LOCK_EX
@f.rewind
for line in @f
line.chomp!
k, v = line.split('=',2)
@hash[CGI::unescape(k)] = CGI::unescape(v)
end
end
@hash
end
def update
@f.rewind
for k,v in @hash
@f.printf "%s=%s\n", CGI::escape(k), CGI::escape(v)
end
@f.truncate @f.tell
end
def close
return unless @f.closed?
update
@f.close
end
def delete
path = @f.path
return unless @f.closed?
@f.close
File::unlink path
end
end
class MemoryStore
GLOBAL_HASH_TABLE = {}
def initialize(session, option={})
@session_id = session.session_id
GLOBAL_HASH_TABLE[@session_id] = {}
end
def restore
GLOBAL_HASH_TABLE[@session_id]
end
def update
# don't need to update; hash is shared
end
def close
# don't need to close
end
def delete
GLOBAL_HASH_TABLE[@session_id] = nil
end
end
end
end