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 42
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 33
def self.config
  @config ||= {}
end
configure() { |config| ... } click to toggle source
# File lib/netrc.rb, line 37
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
  return Dir.pwd
end
lex(lines) click to toggle source
# File lib/netrc.rb, line 85
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 29
def self.netrc_filename
  WINDOWS && !CYGWIN ? "_netrc" : ".netrc"
end
new(path, data) click to toggle source
# File lib/netrc.rb, line 166
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 129
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 51
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 112
def self.skip?(s)
  s =~ /^\s/
end

Public Instance Methods

[](k) click to toggle source
# File lib/netrc.rb, line 180
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 188
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 200
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 211
def each(&block)
  @data.each(&block)
end
length() click to toggle source
# File lib/netrc.rb, line 196
def length
  @data.length
end
new_item(m, l, p) click to toggle source
# File lib/netrc.rb, line 215
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 219
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 233
def unparse
  @pre + @data.map do |datum|
    datum = datum.join
    unless datum[-1..-1] == "\n"
      datum << "\n"
    else
      datum
    end
  end.join
end