B
Bob Showalter
Hi,
I'm a Perl-er learning ruby. I'm creating a ruby port of Perl's Net::Netrc
module for accessing ftp(1)'s .netrc file. I couldn't find an existing ruby
version anywhere.
My current code is below. I've essentially ported the Perl module's usage
semantics, although my internal implementation is quite different. I'd sure
appreciate any feedback, especially related to doing things the "ruby way",
with a view toward submitting this code to the appropriate archive site(s)
at some point.
Example usage:
require 'net/netrc'
n = Net::Netrc.locate('example.com')
if (n.nil?)
puts "No entry found"
else
puts "login = #{n.login}, password = #{n.password}"
end
Questions:
1. Should I use locate() instead of new()? locate() is how the Perl
module works.
2. Should I return nil if no entry is found, or should I return an
object with the accessors all nil?
3. Should I be returning a Net::Netrc object at all, or just a simple
Hash? Or should Net::Netrc sublcass Hash?
4. Is rasing a SecurityError appropriate? Should I create a specific
exception class instead?
------- BEGIN CODE --------
module Net
class Netrc
attr_accessor :machine, :login, assword, :account
# returns name of .netrc file
def Netrc.rcname
# TODO: cross platform? getpwuid() for home dir?
home = ENV['HOME']
home ||= ENV['HOMEDRIVE'] + (ENV['HOMEPATH'] || '') if
ENV['HOMEDRIVE']
File.join(home, '.netrc')
end
# opens .netrc file, returning File object if successful.
# returns nil if .netrc not found.
# raises SecurityError if .netrc is not owned by the current.
# user or if it is readable or writable by other than the
# current user.
def Netrc.open
name = rcname
return nil unless File.exist?(name)
# TODO: this stat code not applicable to Win32 (and others?)
s = File.stat(name)
raise SecurityError, "Not owner: #{name}" unless s.owned?
raise SecurityError, "Bad permissions: #{name}" if s.mode & 077 != 0
File.open(name, 'r')
end
# given a machine name, returns a Net::Netrc object containing
# the matching entry for that name, or the default entry. If
# no match is found an no default entry exists, nil is returned.
def Netrc.locate(mach)
f = open or return nil
entry = nil
key = nil
inmacdef = false
while line = f.gets
if inmacdef
inmacdef = false if line.strip.empty?
next
end
toks = line.scan(/"((?:\\.|[^"])*)"|((?:\\.|\S)+)/).flatten.compact
toks.each { |t| t.gsub!(/\\(.)/, '\1') }
while toks.length > 0
tok = toks.shift
if key
entry = new if key == 'machine' && tok == mach
entry.send "#{key}=", tok if entry
key = nil
end
case tok
when 'default'
return entry if entry
entry = new
when 'machine'
return entry if entry
key = 'machine'
when 'login', 'password', 'account'
key = tok
end
end
end
entry
end
end
end
------- END CODE --------
TIA for any feedback,
Bob
I'm a Perl-er learning ruby. I'm creating a ruby port of Perl's Net::Netrc
module for accessing ftp(1)'s .netrc file. I couldn't find an existing ruby
version anywhere.
My current code is below. I've essentially ported the Perl module's usage
semantics, although my internal implementation is quite different. I'd sure
appreciate any feedback, especially related to doing things the "ruby way",
with a view toward submitting this code to the appropriate archive site(s)
at some point.
Example usage:
require 'net/netrc'
n = Net::Netrc.locate('example.com')
if (n.nil?)
puts "No entry found"
else
puts "login = #{n.login}, password = #{n.password}"
end
Questions:
1. Should I use locate() instead of new()? locate() is how the Perl
module works.
2. Should I return nil if no entry is found, or should I return an
object with the accessors all nil?
3. Should I be returning a Net::Netrc object at all, or just a simple
Hash? Or should Net::Netrc sublcass Hash?
4. Is rasing a SecurityError appropriate? Should I create a specific
exception class instead?
------- BEGIN CODE --------
module Net
class Netrc
attr_accessor :machine, :login, assword, :account
# returns name of .netrc file
def Netrc.rcname
# TODO: cross platform? getpwuid() for home dir?
home = ENV['HOME']
home ||= ENV['HOMEDRIVE'] + (ENV['HOMEPATH'] || '') if
ENV['HOMEDRIVE']
File.join(home, '.netrc')
end
# opens .netrc file, returning File object if successful.
# returns nil if .netrc not found.
# raises SecurityError if .netrc is not owned by the current.
# user or if it is readable or writable by other than the
# current user.
def Netrc.open
name = rcname
return nil unless File.exist?(name)
# TODO: this stat code not applicable to Win32 (and others?)
s = File.stat(name)
raise SecurityError, "Not owner: #{name}" unless s.owned?
raise SecurityError, "Bad permissions: #{name}" if s.mode & 077 != 0
File.open(name, 'r')
end
# given a machine name, returns a Net::Netrc object containing
# the matching entry for that name, or the default entry. If
# no match is found an no default entry exists, nil is returned.
def Netrc.locate(mach)
f = open or return nil
entry = nil
key = nil
inmacdef = false
while line = f.gets
if inmacdef
inmacdef = false if line.strip.empty?
next
end
toks = line.scan(/"((?:\\.|[^"])*)"|((?:\\.|\S)+)/).flatten.compact
toks.each { |t| t.gsub!(/\\(.)/, '\1') }
while toks.length > 0
tok = toks.shift
if key
entry = new if key == 'machine' && tok == mach
entry.send "#{key}=", tok if entry
key = nil
end
case tok
when 'default'
return entry if entry
entry = new
when 'machine'
return entry if entry
key = 'machine'
when 'login', 'password', 'account'
key = tok
end
end
end
entry
end
end
end
------- END CODE --------
TIA for any feedback,
Bob