Class: Pincerna::Ip

Inherits:
Base
  • Object
show all
Defined in:
lib/pincerna/ip.rb

Overview

Shows the IP addresses of all network interfaces.

Constant Summary collapse

MATCHER =

The expression to match.

/^(?<all>.*)$/i
ICON =

The icon to show for each feedback item.

Pincerna::Base::ROOT + "/images/network.png"
URL =

The URL of the webservice.

"http://api.externalip.net/ip"

Constants inherited from Base

Base::CACHE_ROOT, Base::FULL_NAME, Base::RELEVANT_MATCHES, Base::ROOT, Base::TYPES, Base::WORKFLOW_ROOT

Instance Attribute Summary

Attributes inherited from Base

#format, #format_content_type, #output

Instance Method Summary collapse

Methods inherited from Base

#add_feedback_item, execute!, #filter, #format_float, #initialize, #output_feedback, #round_float

Constructor Details

This class inherits a constructor from Pincerna::Base

Instance Method Details

#compare_ip_addresses(left, right) ⇒ Fixnum

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

Parameters:

  • left (String)

    The first IP to compare.

  • right (String)

    The second IP to compare.

Returns:

  • (Fixnum)

    The result of the comparison.



103
104
105
106
107
108
# 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) ⇒ Fixnum

Compares two IP classes, giving higher priority to IPv4.

Parameters:

  • left (String)

    The first IP to compare.

  • right (String)

    The second IP to compare.

Returns:

  • (Fixnum)

    The result of the comparison.



94
95
96
# File 'lib/pincerna/ip.rb', line 94

def compare_ip_classes(left, right)
  (left.index(":") ? 1 : 0) <=> (right.index(":") ? 1 : 0)
end

#get_interfaces_namesHash

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

Returns:

  • (Hash)

    The hash with interfaces' name.



113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# 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_addressesArray

Gets a list of local IP addresses.

Returns:

  • (Array)

    A list of IPs data.



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# 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_addressHash

Gets the public IP address for this machine.

Returns:

  • (Hash)

    The public IP address data.



85
86
87
# File 'lib/pincerna/ip.rb', line 85

def get_public_address
  {interface: nil, address: fetch_remote_resource(URL, {}, false)}
end

#perform_filtering(query) ⇒ Array

Shows the IP addresses of all network interfaces.

Parameters:

  • query (Array)

    A query to match against interfaces names.

Returns:

  • (Array)

    A list of items to process.



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# 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) ⇒ Array

Processes items to obtain feedback items.

Parameters:

  • results (Array)

    The items to process.

Returns:

  • (Array)

    The feedback items.



47
48
49
50
51
52
# 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