class OpenID::Store::Filesystem
Public Class Methods
new(directory)
click to toggle source
Create a Filesystem store instance, putting
all data in directory
.
# File lib/openid/store/filesystem.rb, line 15 def initialize(directory) @nonce_dir = File.join(directory, 'nonces') @association_dir = File.join(directory, 'associations') @temp_dir = File.join(directory, 'temp') self.ensure_dir(@nonce_dir) self.ensure_dir(@association_dir) self.ensure_dir(@temp_dir) end
Public Instance Methods
_get_association(filename)
click to toggle source
# File lib/openid/store/filesystem.rb, line 99 def _get_association(filename) begin assoc_file = File.open(filename, "r") rescue Errno::ENOENT return nil else begin assoc_s = assoc_file.read ensure assoc_file.close end begin association = Association.deserialize(assoc_s) rescue self.remove_if_present(filename) return nil end # clean up expired associations if association.expires_in == 0 self.remove_if_present(filename) return nil else return association end end end
cleanup()
click to toggle source
Remove expired entries from the database. This is potentially expensive, so only run when it is acceptable to take time.
# File lib/openid/store/filesystem.rb, line 170 def cleanup cleanup_associations cleanup_nonces end
cleanup_associations()
click to toggle source
# File lib/openid/store/filesystem.rb, line 175 def cleanup_associations association_filenames = Dir[File.join(@association_dir, "*")] count = 0 association_filenames.each do |af| begin f = File.open(af, 'r') rescue Errno::ENOENT next else begin assoc_s = f.read ensure f.close end begin association = OpenID::Association.deserialize(assoc_s) rescue StandardError self.remove_if_present(af) next else if association.expires_in == 0 self.remove_if_present(af) count += 1 end end end end return count end
cleanup_nonces()
click to toggle source
# File lib/openid/store/filesystem.rb, line 205 def cleanup_nonces nonces = Dir[File.join(@nonce_dir, "*")] now = Time.now.to_i count = 0 nonces.each do |filename| nonce = filename.split('/')[-1] timestamp = nonce.split('-', 2)[0].to_i(16) nonce_age = (timestamp - now).abs if nonce_age > Nonce.skew self.remove_if_present(filename) count += 1 end end return count end
get_association(server_url, handle=nil)
click to toggle source
Retrieve an association
# File lib/openid/store/filesystem.rb, line 79 def get_association(server_url, handle=nil) # the filename with empty handle is the prefix for the associations # for a given server url filename = get_association_filename(server_url, handle) if handle return _get_association(filename) end assoc_filenames = Dir.glob(filename.to_s + '*') assocs = assoc_filenames.collect do |f| _get_association(f) end assocs = assocs.find_all { |a| not a.nil? } assocs = assocs.sort_by { |a| a.issued } return nil if assocs.empty? return assocs[-1] end
get_association_filename(server_url, handle)
click to toggle source
Create a unique filename for a given server url and handle. The filename that is returned will contain the domain name from the server URL for ease of human inspection of the data dir.
# File lib/openid/store/filesystem.rb, line 28 def get_association_filename(server_url, handle) unless server_url.index('://') raise ArgumentError, "Bad server URL: #{server_url}" end proto, rest = server_url.split('://', 2) domain = filename_escape(rest.split('/',2)[0]) url_hash = safe64(server_url) if handle handle_hash = safe64(handle) else handle_hash = '' end filename = [proto,domain,url_hash,handle_hash].join('-') File.join(@association_dir, filename) end
remove_association(server_url, handle)
click to toggle source
Remove an association if it exists, otherwise do nothing.
# File lib/openid/store/filesystem.rb, line 129 def remove_association(server_url, handle) assoc = get_association(server_url, handle) if assoc.nil? return false else filename = get_association_filename(server_url, handle) return self.remove_if_present(filename) end end
store_association(server_url, association)
click to toggle source
Store an association in the assoc directory
# File lib/openid/store/filesystem.rb, line 46 def store_association(server_url, association) assoc_s = association.serialize filename = get_association_filename(server_url, association.handle) f, tmp = mktemp begin begin f.write(assoc_s) f.fsync ensure f.close end begin File.rename(tmp, filename) rescue Errno::EEXIST begin File.unlink(filename) rescue Errno::ENOENT # do nothing end File.rename(tmp, filename) end rescue self.remove_if_present(tmp) raise end end
use_nonce(server_url, timestamp, salt)
click to toggle source
Return whether the nonce is valid
# File lib/openid/store/filesystem.rb, line 141 def use_nonce(server_url, timestamp, salt) return false if (timestamp - Time.now.to_i).abs > Nonce.skew if server_url and !server_url.empty? proto, rest = server_url.split('://',2) else proto, rest = '','' end raise "Bad server URL" unless proto && rest domain = filename_escape(rest.split('/',2)[0]) url_hash = safe64(server_url) salt_hash = safe64(salt) nonce_fn = '%08x-%s-%s-%s-%s'%[timestamp, proto, domain, url_hash, salt_hash] filename = File.join(@nonce_dir, nonce_fn) begin fd = File.new(filename, File::CREAT | File::EXCL | File::WRONLY, 0200) fd.close return true rescue Errno::EEXIST return false end end
Protected Instance Methods
ensure_dir(dir_name)
click to toggle source
ensure that a path exists
# File lib/openid/store/filesystem.rb, line 260 def ensure_dir(dir_name) FileUtils::mkdir_p(dir_name) end
filename_escape(s)
click to toggle source
create a safe filename from a url
# File lib/openid/store/filesystem.rb, line 231 def filename_escape(s) s = '' if s.nil? filename_chunks = s.each_char.flat_map {|c| @@FILENAME_ALLOWED.include?(c) ? c : c.bytes.map {|b| "_%02X" % b } }.join end
mktemp()
click to toggle source
Create a temporary file and return the File object and filename.
# File lib/openid/store/filesystem.rb, line 225 def mktemp f = Tempfile.new('tmp', @temp_dir) [f, f.path] end
remove_if_present(filename)
click to toggle source
remove file if present in filesystem
# File lib/openid/store/filesystem.rb, line 250 def remove_if_present(filename) begin File.unlink(filename) rescue Errno::ENOENT return false end return true end
safe64(s)
click to toggle source
# File lib/openid/store/filesystem.rb, line 240 def safe64(s) s = OpenID::CryptUtil.sha1(s) s = OpenID::Util.to_base64(s) s.gsub!('+', '_') s.gsub!('/', '.') s.gsub!('=', '') return s end