class Pincerna::Ip

Shows the IP addresses of all network interfaces.

Constants

ICON

The icon to show for each feedback item.

MATCHER

The expression to match.

URL

The URL of the webservice.

Public Instance Methods

compare_ip_addresses(left, right) click to toggle source

Compares to IP addresses, giving higher priority to local address such as 127.0.0.1.

@param left [String] The first IP to compare. @param right [String] The second IP to compare. @return [Fixnum] The result of the comparison.

# File lib/pincerna/ip.rb, line 103
def compare_ip_addresses(left, right)
  higher_priority = ["::1", "127.0.0.1", "10.0.0.1"]
  cmp = (higher_priority.include?(left) ? 0 : 1) <=> (higher_priority.include?(right) ? 0 : 1)
  cmp = left <=> right if cmp == 0
  cmp
end
compare_ip_classes(left, right) click to toggle source

Compares two IP classes, giving higher priority to IPv4.

@param left [String] The first IP to compare. @param right [String] The second IP to compare. @return [Fixnum] The result of the comparison.

# File lib/pincerna/ip.rb, line 94
def compare_ip_classes(left, right)
  (left.index(":") ? 1 : 0) <=> (right.index(":") ? 1 : 0)
end
get_interfaces_names() click to toggle source

Gets a hash with pair of interfaces and their human names.

@return [Hash] The hash with interfaces' name.

# File lib/pincerna/ip.rb, line 113
def get_interfaces_names
  rv = {"lo0" => "Loopback"}

  names = execute_command("/usr/sbin/networksetup", "-listallhardwareports").split(/\n\n/)
  names.shift # Discard first whitespace
  
  names.each do |port|
    port = StringScanner.new(port)
    name = nil
    interface = nil
    
    if port.scan_until(/Hardware Port: /) then
      name = port.scan_until(/\n/).strip
      interface = port.scan_until(/\n/).strip if port.scan_until(/Device: /)
    end

    rv[interface] = name if name && interface
  end

  rv
end
get_local_addresses() click to toggle source

Gets a list of local IP addresses.

@return [Array] A list of IPs data.

# File lib/pincerna/ip.rb, line 57
def get_local_addresses
  rv = []
  names = get_interfaces_names

  # Split by interfaces
  interfaces = execute_command("/sbin/ifconfig").split(/(^\S+:\s+)/)
  interfaces.shift # Discard first whitespace

  # For each interface
  interfaces.each_slice(2) do |interface, configuration|
    # See if matches the query and then replace public name
    interface = interface.gsub(/\s*(.+):\s*/, "\\1")
    name = names[interface] ? "#{names[interface]} (#{interface})" : interface
    next if !@interface_filter.match(name)

    # Get addresses
    addresses = StringScanner.new(configuration)
    while addresses.scan_until(/inet(6?)\s/) do
      rv << {interface: name, address: addresses.scan(/\S+/)}
    end
  end

  rv
end
get_public_address() click to toggle source

Gets the public IP address for this machine.

@return [Hash] The public IP address data.

# File lib/pincerna/ip.rb, line 85
def get_public_address
  {interface: nil, address: fetch_remote_resource(URL, {}, false)}
end
perform_filtering(query) click to toggle source

Shows the IP addresses of all network interfaces.

@param query [Array] A query to match against interfaces names. @return [Array] A list of items to process.

# File lib/pincerna/ip.rb, line 23
def perform_filtering(query)    
  @interface_filter ||= query.empty? ? /.*/ : /#{query}/i

  # Get local addresses
  rv = get_local_addresses

  # Sort interfaces and address, IPv4 first then IPv6
  rv.sort! {|left, right|
    cmp = left[:interface] <=> right[:interface] # Interface name first
    cmp = compare_ip_classes(left[:address], right[:address]) if cmp == 0 # Now IPv4 first then IPv6
    cmp = compare_ip_addresses(left[:address], right[:address]) if cmp == 0 # Finally addresses
    cmp
  }

  # Add public address
  rv = rv.insert(0, get_public_address) if @interface_filter.match("public")

  rv
end
process_results(results) click to toggle source

Processes items to obtain feedback items.

@param results [Array] The items to process. @return [Array] The feedback items.

# File lib/pincerna/ip.rb, line 47
def process_results(results)
  results.map do |result|
    title = "#{result[:interface] ? result[:interface] : "Public"} IP: #{result[:address]}"
    {title: title, arg: result[:address], subtitle: "Action this item to copy the IP on the clipboard.", icon: ICON}
  end
end