class Netrc
Constants
- CYGWIN
- Entry
- VERSION
- WINDOWS
see stackoverflow.com/questions/4871309/what-is-the-correct-way-to-detect-if-ruby-is-running-on-windows
Attributes
new_item_prefix[RW]
Public Class Methods
check_permissions(path)
click to toggle source
# File lib/netrc.rb, line 68 def self.check_permissions(path) perm = File.stat(path).mode & 0777 if perm != 0600 && !(WINDOWS) && !(Netrc.config[:allow_permissive_netrc_file]) raise Error, "Permission bits for '#{path}' should be 0600, but are "+perm.to_s(8) end end
config()
click to toggle source
# File lib/netrc.rb, line 59 def self.config @config ||= {} end
configure() { |config| ... }
click to toggle source
# File lib/netrc.rb, line 63 def self.configure yield(self.config) if block_given? self.config end
default_path()
click to toggle source
# File lib/netrc.rb, line 10 def self.default_path File.join(ENV['NETRC'] || home_path, netrc_filename) end
home_path()
click to toggle source
# File lib/netrc.rb, line 14 def self.home_path home = Dir.respond_to?(:home) ? Dir.home : ENV['HOME'] if WINDOWS && !CYGWIN home ||= File.join(ENV['HOMEDRIVE'], ENV['HOMEPATH']) if ENV['HOMEDRIVE'] && ENV['HOMEPATH'] home ||= ENV['USERPROFILE'] # XXX: old stuff; most likely unnecessary home = home.tr("\\", "/") unless home.nil? end (home && File.readable?(home)) ? home : Dir.pwd rescue ArgumentError unless WINDOWS # Ruby 2.5.x through 2.7.1 (and probably other versions) raises an # ArgumentError when the 'HOME' env var is not set and the process is # not a subprocess of a login session. That is, it tries to navigate # into the password database using the username obtained from # getlogin(), whichs will return NULL in such a circumstance. It would # be better if it instead tried to do it via the UID obtained from # getuid(), which always succeeds. Nevertheless, we'll work around the # problem by doing that ourselves here. begin require 'etc' rescue LoadError warn "HOME is not set, and the 'etc' module not available; using pwd as home\n" return Dir.pwd end passwd_record = Etc.getpwuid(Process.uid); unless passwd_record warn "Record for uid #{Process.uid} not found in the password database; using pwd as home\n" return Dir.pwd end return passwd_record.dir end return Dir.pwd end
lex(lines)
click to toggle source
# File lib/netrc.rb, line 111 def self.lex(lines) tokens = TokenArray.new for line in lines content, comment = line.split(/(\s*#.*)/m) content.each_char do |char| case char when /\s/ if tokens.last && tokens.last[-1..-1] =~ /\s/ tokens.last << char else tokens << char end else if tokens.last && tokens.last[-1..-1] =~ /\S/ tokens.last << char else tokens << char end end end if comment tokens << comment end end tokens end
netrc_filename()
click to toggle source
# File lib/netrc.rb, line 55 def self.netrc_filename WINDOWS && !CYGWIN ? "_netrc" : ".netrc" end
new(path, data)
click to toggle source
# File lib/netrc.rb, line 192 def initialize(path, data) @new_item_prefix = '' @path = path @pre, @data = data if @data && @data.last && :default == @data.last[0] @default = @data.pop else @default = nil end end
parse(ts)
click to toggle source
Returns two values, a header and a list of items. Each item is a tuple, containing some or all of:
-
machine keyword (including trailing whitespace+comments)
-
machine name
-
login keyword (including surrounding whitespace+comments)
-
login
-
password keyword (including surrounding whitespace+comments)
-
password
-
trailing chars
This lets us change individual fields, then write out the file with all its original formatting.
# File lib/netrc.rb, line 155 def self.parse(ts) cur, item = [], [] unless ts.is_a?(TokenArray) ts = TokenArray.new(ts) end pre = ts.readto{|t| t == "machine" || t == "default"} while ts.length > 0 if ts[0] == 'default' cur << ts.take.to_sym cur << '' else cur << ts.take + ts.readto{|t| ! skip?(t)} cur << ts.take end if ts.include?('login') cur << ts.readto{|t| t == "login"} + ts.take + ts.readto{|t| ! skip?(t)} cur << ts.take end if ts.include?('password') cur << ts.readto{|t| t == "password"} + ts.take + ts.readto{|t| ! skip?(t)} cur << ts.take end cur << ts.readto{|t| t == "machine" || t == "default"} item << cur cur = [] end [pre, item] end
read(path=default_path)
click to toggle source
Reads path and parses it as a .netrc file. If path doesn't exist, returns an empty object. Decrypt paths ending in .gpg.
# File lib/netrc.rb, line 77 def self.read(path=default_path) check_permissions(path) data = if path =~ /\.gpg$/ decrypted = `gpg --batch --quiet --decrypt #{path}` if $?.success? decrypted else raise Error.new("Decrypting #{path} failed.") unless $?.success? end else File.read(path) end new(path, parse(lex(data.lines.to_a))) rescue Errno::ENOENT new(path, parse(lex([]))) end
skip?(s)
click to toggle source
# File lib/netrc.rb, line 138 def self.skip?(s) s =~ /^\s/ end
Public Instance Methods
[](k)
click to toggle source
# File lib/netrc.rb, line 206 def [](k) if item = @data.detect {|datum| datum[1] == k} Entry.new(item[3], item[5]) elsif @default Entry.new(@default[3], @default[5]) end end
[]=(k, info)
click to toggle source
# File lib/netrc.rb, line 214 def []=(k, info) if item = @data.detect {|datum| datum[1] == k} item[3], item[5] = info else @data << new_item(k, info[0], info[1]) end end
delete(key)
click to toggle source
# File lib/netrc.rb, line 226 def delete(key) datum = nil for value in @data if value[1] == key datum = value break end end @data.delete(datum) end
each(&block)
click to toggle source
# File lib/netrc.rb, line 237 def each(&block) @data.each(&block) end
length()
click to toggle source
# File lib/netrc.rb, line 222 def length @data.length end
new_item(m, l, p)
click to toggle source
# File lib/netrc.rb, line 241 def new_item(m, l, p) [new_item_prefix+"machine ", m, "\n login ", l, "\n password ", p, "\n"] end
save()
click to toggle source
# File lib/netrc.rb, line 245 def save if @path =~ /\.gpg$/ e = IO.popen("gpg -a --batch --default-recipient-self -e", "r+") do |gpg| gpg.puts(unparse) gpg.close_write gpg.read end raise Error.new("Encrypting #{@path} failed.") unless $?.success? File.open(@path, 'w', 0600) {|file| file.print(e)} else File.open(@path, 'w', 0600) {|file| file.print(unparse)} end end
unparse()
click to toggle source
# File lib/netrc.rb, line 259 def unparse @pre + @data.map do |datum| datum = datum.join unless datum[-1..-1] == "\n" datum << "\n" else datum end end.join end