tor 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README CHANGED
@@ -10,10 +10,13 @@ Features
10
10
 
11
11
  * Supports checking whether Tor is installed in the user's current `PATH`,
12
12
  and if it is, returning the version number.
13
+ * Supports parsing Tor configuration files and looking up the values of
14
+ particular options.
13
15
  * Supports querying and controlling a locally-running Tor process using the
14
16
  [Tor Control Protocol (TC)][TC] over a socket connection.
15
17
  * Supports querying the [Tor DNS Exit List (DNSEL)][TorDNSEL] to determine
16
18
  whether a particular host is a Tor exit node or not.
19
+ * Compatible with Ruby 1.8.7+, Ruby 1.9.x, and JRuby 1.4/1.5.
17
20
 
18
21
  Examples
19
22
  --------
@@ -26,7 +29,22 @@ Examples
26
29
  Tor.available? #=> true
27
30
  Tor.version #=> "0.2.1.25"
28
31
 
29
- ### Obtaining information about a running Tor process
32
+ ### Parsing the Tor configuration file (1)
33
+
34
+ torrc = Tor::Config.load("/etc/tor/torrc")
35
+
36
+ ### Parsing the Tor configuration file (2)
37
+
38
+ Tor::Config.open("/etc/tor/torrc") do |torrc|
39
+ puts "Tor SOCKS port: #{torrc['SocksPort']}"
40
+ puts "Tor control port: #{torrc['ControlPort']}"
41
+ puts "Tor exit policy:"
42
+ torrc.each('ExitPolicy') do |key, value|
43
+ puts " #{value}"
44
+ end
45
+ end
46
+
47
+ ### Communicating with a running Tor process
30
48
 
31
49
  Tor::Controller.connect(:port => 9051) do |tor|
32
50
  puts "Tor version: #{tor.version}"
@@ -47,6 +65,7 @@ Dependencies
47
65
  ------------
48
66
 
49
67
  * [Ruby](http://ruby-lang.org/) (>= 1.8.7) or (>= 1.8.1 with [Backports][])
68
+ * [Tor](https://www.torproject.org/download.html.en) (>= 0.2.1)
50
69
 
51
70
  Installation
52
71
  ------------
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.1
1
+ 0.1.2
data/lib/tor.rb CHANGED
@@ -17,10 +17,33 @@ end
17
17
  ##
18
18
  # @see https://www.torproject.org/
19
19
  module Tor
20
+ autoload :Config, 'tor/config'
20
21
  autoload :Controller, 'tor/control'
21
22
  autoload :DNSEL, 'tor/dnsel'
22
23
  autoload :VERSION, 'tor/version'
23
24
 
25
+ ##
26
+ # Returns `true` if the Tor process is running locally, `false` otherwise.
27
+ #
28
+ # This works by attempting to establish a Tor Control Protocol (TC)
29
+ # connection to the standard control port 9051 on `localhost`. If Tor
30
+ # hasn't been configured with the `ControlPort 9051` option, this will
31
+ # return `false`.
32
+ #
33
+ # @example
34
+ # Tor.running? #=> false
35
+ #
36
+ # @return [Boolean]
37
+ # @since 0.1.2
38
+ def self.running?
39
+ begin
40
+ Tor::Controller.new.quit
41
+ true
42
+ rescue Errno::ECONNREFUSED
43
+ false
44
+ end
45
+ end
46
+
24
47
  ##
25
48
  # Returns `true` if Tor is available, `false` otherwise.
26
49
  #
@@ -0,0 +1,103 @@
1
+ module Tor
2
+ ##
3
+ # Tor configuration.
4
+ #
5
+ # @example Parsing a Tor configuration file (1)
6
+ # torrc = Tor::Config.load("/etc/tor/torrc")
7
+ #
8
+ # @example Parsing a Tor configuration file (2)
9
+ # Tor::Config.open("/etc/tor/torrc") do |torrc|
10
+ # puts "Tor SOCKS port: #{torrc['SocksPort']}"
11
+ # puts "Tor control port: #{torrc['ControlPort']}"
12
+ # puts "Tor exit policy:"
13
+ # torrc.each('ExitPolicy') do |key, value|
14
+ # puts " #{value}"
15
+ # end
16
+ # end
17
+ #
18
+ # @see https://www.torproject.org/tor-manual.html.en
19
+ # @since 0.1.2
20
+ class Config
21
+ CONFDIR = '/etc/tor' unless defined?(CONFDIR)
22
+
23
+ ##
24
+ # Opens a Tor configuration file.
25
+ #
26
+ # @param [String, #to_s] filename
27
+ # @param [Hash{Symbol => Object}] options
28
+ # @yield [config]
29
+ # @yieldparam [Config] config
30
+ # @return [Config]
31
+ def self.open(filename, options = {}, &block)
32
+ if block_given?
33
+ block.call(self.load(filename, options))
34
+ else
35
+ self.load(filename, options)
36
+ end
37
+ end
38
+
39
+ ##
40
+ # Loads the configuration options from a Tor configuration file.
41
+ #
42
+ # @param [String, #to_s] filename
43
+ # @param [Hash{Symbol => Object}] options
44
+ # @return [Config]
45
+ def self.load(filename, options = {})
46
+ self.new(options) do |config|
47
+ File.open(filename.to_s, 'rb') do |file|
48
+ file.each_line do |line|
49
+ case line = line.strip.chomp.strip
50
+ when '' then next # skip empty lines
51
+ when /^#/ then next # skip comments
52
+ else line = line.split('#').first.strip
53
+ end
54
+ # TODO: support for unquoting and unescaping values
55
+ config << line.split(/\s+/, 2)
56
+ end
57
+ end
58
+ end
59
+ end
60
+
61
+ ##
62
+ # @param [Hash{Symbol => Object}] options
63
+ # @yield [config]
64
+ # @yieldparam [Config] config
65
+ def initialize(options = {}, &block)
66
+ @lines, @options = [], options.dup
67
+ block.call(self) if block_given?
68
+ end
69
+
70
+ ##
71
+ # Appends a new configuration option.
72
+ #
73
+ # @param [Array(String, String)]
74
+ # @return [Config]
75
+ def <<(kv)
76
+ @lines << kv
77
+ self
78
+ end
79
+
80
+ ##
81
+ # Looks up the last value of a particular configuration option.
82
+ #
83
+ # @param [String, Regexp] key
84
+ # @return [String]
85
+ def [](key)
86
+ values = each(key).map(&:last)
87
+ values.empty? ? nil : values.last
88
+ end
89
+
90
+ ##
91
+ # Enumerates configuration options.
92
+ #
93
+ # @param [String, Regexp] key
94
+ # @yield [key, value]
95
+ # @yieldparam [String] key
96
+ # @yieldparam [String] value
97
+ # @return [Enumerator]
98
+ def each(key = nil, &block)
99
+ return enum_for(:each, key) unless block_given?
100
+ key ? @lines.find_all { |k, v| key === k }.each(&block) : @lines.each(&block)
101
+ end
102
+ end
103
+ end
@@ -82,9 +82,9 @@ module Tor
82
82
  # Returns `true` if the controller connection is active.
83
83
  #
84
84
  # @example
85
- # tor.connected? #=> true
85
+ # tor.connected? #=> true
86
86
  # tor.close
87
- # tor.connected? #=> false
87
+ # tor.connected? #=> false
88
88
  #
89
89
  # @return [Boolean]
90
90
  def connected?
@@ -119,19 +119,57 @@ module Tor
119
119
  #
120
120
  # @return [void]
121
121
  def quit
122
- send_command(:quit)
122
+ send_line('QUIT')
123
123
  reply = read_reply
124
124
  close
125
125
  reply
126
126
  end
127
127
 
128
+ ##
129
+ # Returns information about the authentication method required by the
130
+ # Tor process.
131
+ #
132
+ # This command may be used before authenticating.
133
+ #
134
+ # @example
135
+ # C: PROTOCOLINFO
136
+ # S: 250-PROTOCOLINFO 1
137
+ # S: 250-AUTH METHODS=NULL
138
+ # S: 250-VERSION Tor="0.2.1.25"
139
+ # S: 250 OK
140
+ #
141
+ # @example
142
+ # tor.authentication_method #=> nil
143
+ # tor.authentication_method #=> :hashedpassword
144
+ # tor.authentication_method #=> :cookie
145
+ #
146
+ # @return [Symbol]
147
+ # @since 0.1.2
148
+ def authentication_method
149
+ @authentication_method ||= begin
150
+ method = nil
151
+ send_line('PROTOCOLINFO')
152
+ loop do
153
+ # TODO: support for reading multiple authentication methods
154
+ case reply = read_reply
155
+ when /^250-AUTH METHODS=(\w*)/
156
+ method = $1.strip.downcase.to_sym
157
+ method = method.eql?(:null) ? nil : method
158
+ when /^250-/ then next
159
+ when '250 OK' then break
160
+ end
161
+ end
162
+ method
163
+ end
164
+ end
165
+
128
166
  ##
129
167
  # Returns `true` if the controller connection has been authenticated.
130
168
  #
131
169
  # @example
132
- # tor.authenticated? #=> false
170
+ # tor.authenticated? #=> false
133
171
  # tor.authenticate
134
- # tor.authenticated? #=> true
172
+ # tor.authenticated? #=> true
135
173
  #
136
174
  # @return [Boolean]
137
175
  def authenticated?
@@ -169,7 +207,7 @@ module Tor
169
207
  # S: 250 OK
170
208
  #
171
209
  # @example
172
- # tor.version #=> "0.2.1.25"
210
+ # tor.version #=> "0.2.1.25"
173
211
  #
174
212
  # @return [String]
175
213
  def version
@@ -188,7 +226,7 @@ module Tor
188
226
  # S: 250 OK
189
227
  #
190
228
  # @example
191
- # tor.config_file #=> #<Pathname:/opt/local/etc/tor/torrc>
229
+ # tor.config_file #=> #<Pathname:/opt/local/etc/tor/torrc>
192
230
  #
193
231
  # @return [Pathname]
194
232
  def config_file
@@ -2,7 +2,7 @@ module Tor
2
2
  module VERSION
3
3
  MAJOR = 0
4
4
  MINOR = 1
5
- TINY = 1
5
+ TINY = 2
6
6
  EXTRA = nil
7
7
 
8
8
  STRING = [MAJOR, MINOR, TINY, EXTRA].compact.join('.')
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 1
9
- version: 0.1.1
8
+ - 2
9
+ version: 0.1.2
10
10
  platform: ruby
11
11
  authors:
12
12
  - Arto Bendiken
@@ -59,6 +59,7 @@ files:
59
59
  - README
60
60
  - UNLICENSE
61
61
  - VERSION
62
+ - lib/tor/config.rb
62
63
  - lib/tor/control.rb
63
64
  - lib/tor/dnsel.rb
64
65
  - lib/tor/version.rb