pac 1.0.0

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/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (C) 2011 by Samuel Kadolph
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
@@ -0,0 +1,93 @@
1
+ # pac
2
+
3
+ pac is a gem to parse [proxy auto-config](http://en.wikipedia.org/wiki/Proxy_auto-config) files.
4
+ pac uses a JavaScript runtime to evaulate a proxy auto-config file the same way a browser does to determine what proxy (if
5
+ any at all) should a program use to connect to a server. You must install on of the supported JavaScript runtimes:
6
+ therubyracer, therubyrhino, johnson or mustang.
7
+
8
+ Big thanks to [sstephenson](https://github.com/sstephenson)'s [execjs](https://github.com/sstephenson/execjs) for the
9
+ runtime wrapper code.
10
+
11
+ ## Installing
12
+
13
+ ### Recommended
14
+
15
+ ```
16
+ gem install pac
17
+ ```
18
+
19
+ ### Edge
20
+
21
+ ```
22
+ git clone https://github.com/samuelkadolph/ruby-pac
23
+ cd ruby-pac && rake install
24
+ ```
25
+
26
+ ## Requirements
27
+
28
+ After installing the `pac` gem you must install a JavaScript runtime. Compatible runtimes include:
29
+
30
+ * [therubyracer](https://rubygems.org/gems/therubyracer) Google V8 embedded within Ruby
31
+ * [therubyrhino](https://rubygems.org/gems/therubyrhino/) Mozilla Rhino embedded within JRuby
32
+ * [johnson](https://rubygems.org/gems/johnson/) Mozilla SpiderMonkey embedded within Ruby 1.8
33
+ * [mustang](https://rubygems.org/gems/mustang/) Mustang V8 embedded within Ruby
34
+
35
+ ## Usage
36
+
37
+ ### Command Line
38
+
39
+ ```
40
+ parsepac https://github.com/downloads/samuelkadolph/ruby-pac/sample.pac https://github.com # => "PROXY proxy:8080"
41
+ parsepac https://github.com/downloads/samuelkadolph/ruby-pac/sample.pac http://ruby-lang.com # => "PROXY proxy:8080; DIRECT"
42
+ parsepac https://github.com/downloads/samuelkadolph/ruby-pac/sample.pac http://samuel.kadolph.com # => "DIRECT"
43
+ ```
44
+
45
+ ### Ruby
46
+
47
+ ```ruby
48
+ require "rubygems"
49
+ require "pac"
50
+
51
+ pac = PAC.load("https://github.com/downloads/samuelkadolph/ruby-pac/sample.pac")
52
+ pac.find("https://github.com") # => "PROXY proxy:8080"
53
+ pac.find("http://ruby-lang.com") # => "PROXY proxy:8080; DIRECT"
54
+ pac.find("http://samuel.kadolph.com") # => "DIRECT"
55
+
56
+ pac = PAC.read("sample.pac")
57
+
58
+ pac = PAC.source <<-JS
59
+ function FindProxyForURL(url, host) {
60
+ return "DIRECT";
61
+ }
62
+ JS
63
+ pac.find("http://localhost") # => "DIRECT"
64
+ ```
65
+
66
+ ## Available JavaScript Functions
67
+
68
+ * isPlainHostName(host)
69
+ * dnsDomainIs(host, domain)
70
+ * localHostOrDomainIs(host, hostdom)
71
+ * isResolvable(host)
72
+ * isInNet(host, pattern, mask)
73
+ * dnsResolve(host)
74
+ * myIpAddress()
75
+ * dnsDomainLevels(host)
76
+ * shExpMatch(str, shexp)
77
+ * weekdayRange(wd1, wd2, gmt)
78
+ * dateRange(*args)
79
+ * timeRange(*args)
80
+
81
+ ## Developers
82
+
83
+ ### Contributing
84
+
85
+ If you want to contribute: fork, branch & pull request.
86
+
87
+ ### Running Tests
88
+
89
+ ```
90
+ bundle install
91
+ rake test
92
+ rake test:rubyracer
93
+ ```
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ if ARGV.size < 2
4
+ puts "usage: parsepac pac-url-or-file url-to-test"
5
+ exit 1
6
+ else
7
+ require "pac"
8
+ puts PAC.load(ARGV.shift).find(ARGV.shift)
9
+ exit 0
10
+ end
@@ -0,0 +1,40 @@
1
+ require "rubygems"
2
+
3
+ module PAC
4
+ require "pac/version"
5
+ require "pac/file"
6
+ require "pac/runtimes"
7
+
8
+ class Error < StandardError
9
+ end
10
+ class RuntimeError < Error
11
+ end
12
+ class ProgramError < Error
13
+ end
14
+ class RuntimeUnavailable < RuntimeError
15
+ end
16
+
17
+ class << self
18
+ attr_reader :runtime
19
+
20
+ def runtime=(runtime)
21
+ raise RuntimeUnavailable, "#{runtime.name} is unavailable on this system" unless runtime.available?
22
+ @runtime = runtime
23
+ end
24
+
25
+ def load(url, options = {})
26
+ require "open-uri"
27
+ File.new(open(url, { :proxy => false }.merge(options)).read)
28
+ end
29
+
30
+ def read(file)
31
+ File.new(::File.read(file))
32
+ end
33
+
34
+ def source(source)
35
+ File.new(source)
36
+ end
37
+ end
38
+
39
+ self.runtime = Runtimes.autodetect
40
+ end
@@ -0,0 +1,21 @@
1
+ require "uri"
2
+
3
+ module PAC
4
+ require "pac/functions"
5
+
6
+ class File
7
+ attr_reader :source, :context
8
+
9
+ def initialize(source)
10
+ @source = source.dup.freeze
11
+ @context = PAC.runtime.compile(@source)
12
+ @context.include Functions
13
+ end
14
+
15
+ def find(url)
16
+ uri = URI.parse(url)
17
+ raise ArgumentError, "url is missing host" unless uri.host
18
+ context.call("FindProxyForURL", url, uri.host)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,132 @@
1
+ require "ipaddr"
2
+ require "resolv"
3
+ require "time"
4
+
5
+ module PAC
6
+ module Functions
7
+ DAYS = { "MON" => 1, "TUE" => 2, "WED" => 3, "THU" => 4, "FRI" => 5, "SAT" => 6, "SUN" => 7 }
8
+ MONTHS = { "JAN" => 1, "FEB" => 2, "MAR" => 3, "APR" => 4, "MAY" => 5, "JUN" => 6,
9
+ "JUL" => 7, "AUG" => 8, "SEP" => 9, "OCT" => 10, "NOV" => 11, "DEC" => 12 }
10
+
11
+ class << self
12
+ def isPlainHostName(host)
13
+ not host.include? "."
14
+ end
15
+
16
+ def dnsDomainIs(host, domain)
17
+ host.end_with? domain
18
+ end
19
+
20
+ def localHostOrDomainIs(host, hostdom)
21
+ host == hostdom or hostdom.include? host
22
+ end
23
+
24
+ def isResolvable(host)
25
+ !!resolve_host(host)
26
+ end
27
+
28
+ def isInNet(host, pattern, mask)
29
+ IPAddr.new(pattern).mask(mask).include? resolve_host(host)
30
+ end
31
+
32
+ def dnsResolve(host)
33
+ resolve_host(host)
34
+ end
35
+
36
+ def myIpAddress()
37
+ resolve_host(Socket.gethostname)
38
+ end
39
+
40
+ def dnsDomainLevels(host)
41
+ host.scan(".").size
42
+ end
43
+
44
+ def shExpMatch(str, shexp)
45
+ ::File.fnmatch(shexp, str)
46
+ end
47
+
48
+ def weekdayRange(wd1, wd2 = nil, gmt = nil)
49
+ time = Time.now
50
+ time = time.utc if gmt == "GMT"
51
+
52
+ (DAYS[wd1]..DAYS[wd2 || wd1]).include? time.wday
53
+ end
54
+
55
+ def dateRange(*args)
56
+ time = Time.now
57
+ time = time.utc if args.last == "GMT" and args.pop
58
+
59
+ case args.size
60
+ when 1
61
+ check_date_part(time, args[0])
62
+ when 2
63
+ check_date_part(time, args[0]..args[1])
64
+ when 4
65
+ check_date_part(time, args[0]..args[2]) and
66
+ check_date_part(time, args[1]..args[3])
67
+ when 6
68
+ check_date_part(time, args[0]..args[3]) and
69
+ check_date_part(time, args[1]..args[4]) and
70
+ check_date_part(time, args[2]..args[5])
71
+ else
72
+ raise ArgumentError, "wrong number of arguments"
73
+ end
74
+ end
75
+
76
+ def timeRange(*args)
77
+ time = Time.now
78
+ time = time.utc if args.last == "GMT" and args.pop
79
+
80
+ case args.size
81
+ when 1
82
+ time.hour == args[0]
83
+ when 2
84
+ (args[0]..args[1]).include? time.hour
85
+ when 4
86
+ (args[0]..args[2]).include? time.hour and
87
+ (args[1]..args[3]).include? time.min
88
+ when 6
89
+ (args[0]..args[3]).include? time.hour and
90
+ (args[1]..args[4]).include? time.min and
91
+ (args[2]..args[5]).include? time.sec
92
+ else
93
+ raise ArgumentError, "wrong number of arguments"
94
+ end
95
+ end
96
+
97
+ private
98
+ def check_date_part(time, part, operation = :==)
99
+ case part
100
+ when String
101
+ time.month.send(operation, MONTHS[part])
102
+ when Integer
103
+ if part < 100
104
+ time.day.send(operation, part)
105
+ else
106
+ time.year.send(operation, part)
107
+ end
108
+ when Range
109
+ check_date_part(time, part.begin, :>=) and check_date_part(time, part.end, :<=)
110
+ else
111
+ raise ArgumentError, "wrong type"
112
+ end
113
+ end
114
+
115
+ def resolve_host(host)
116
+ Resolv.each_address(host) do |address|
117
+ begin
118
+ return address if IPAddr.new(address).ipv4?
119
+ rescue ArgumentError
120
+ end
121
+ end
122
+
123
+ # We couldn't find an IPv4 address for the host
124
+ nil
125
+ rescue Resolv::ResolvError, NoMethodError
126
+ # Have to rescue NoMethodError because jruby has a bug with non existant hostnames
127
+ # See http://jira.codehaus.org/browse/JRUBY-6054
128
+ nil
129
+ end
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,45 @@
1
+ module PAC
2
+ module Runtimes
3
+ require "pac/runtimes/rubyracer"
4
+ require "pac/runtimes/rubyrhino"
5
+ require "pac/runtimes/johnson"
6
+ require "pac/runtimes/mustang"
7
+
8
+ RubyRacer = RubyRacerRuntime.new
9
+ RubyRhino = RubyRhinoRuntime.new
10
+ Johnson = JohnsonRuntime.new
11
+ Mustang = MustangRuntime.new
12
+
13
+ class << self
14
+ def autodetect
15
+ from_environment || best_available || raise(RuntimeUnavailable, "Could not find a JavaScript runtime. See https://github.com/samuelkadolph/ruby-pac for a list of runtimes.")
16
+ end
17
+
18
+ def from_environment
19
+ if name = ENV["JS_RUNTIME"]
20
+ if runtime = const_get(name)
21
+ if runtime.available?
22
+ runtime if runtime.available?
23
+ else
24
+ raise RuntimeUnavailable, "#{runtime.name} runtime is not available on this system"
25
+ end
26
+ elsif !name.empty?
27
+ raise RuntimeUnavailable, "#{name} runtime is not defined"
28
+ end
29
+ end
30
+ end
31
+
32
+ def best_available
33
+ runtimes.find(&:available?)
34
+ end
35
+
36
+ def runtimes
37
+ @runtimes ||= [RubyRacer, RubyRhino, Johnson, Mustang]
38
+ end
39
+ end
40
+ end
41
+
42
+ def self.runtimes
43
+ Runtimes.runtimes
44
+ end
45
+ end
@@ -0,0 +1,86 @@
1
+ module PAC
2
+ module Runtimes
3
+ class JohnsonRuntime
4
+ class Context
5
+ def initialize(source = "")
6
+ @runtime = ::Johnson::Runtime.new
7
+ @runtime.evaluate(source)
8
+ end
9
+
10
+ def include(mod)
11
+ (mod.methods - Module.methods).each do |name|
12
+ @runtime[name] = mod.method(name)
13
+ end
14
+ end
15
+
16
+ def call(properties, *args)
17
+ unbox @runtime.evaluate(properties).call(*args)
18
+ rescue Johnson::Error => e
19
+ if syntax_error?(e)
20
+ raise RuntimeError, e.message
21
+ else
22
+ raise ProgramError, e.message
23
+ end
24
+ end
25
+
26
+ def unbox(value)
27
+ case
28
+ when function?(value)
29
+ nil
30
+ when string?(value)
31
+ value.respond_to?(:force_encoding) ? value.force_encoding("UTF-8") : value
32
+ when array?(value)
33
+ value.map { |v| unbox(v) }
34
+ when object?(value)
35
+ value.inject({}) do |vs, (k, v)|
36
+ vs[k] = unbox(v) unless function?(v)
37
+ vs
38
+ end
39
+ else
40
+ value
41
+ end
42
+ end
43
+
44
+ private
45
+ def syntax_error?(error)
46
+ error.message =~ /^syntax error at /
47
+ end
48
+
49
+ def function?(value)
50
+ value.respond_to?(:function?) && value.function?
51
+ end
52
+
53
+ def string?(value)
54
+ value.is_a?(String)
55
+ end
56
+
57
+ def array?(value)
58
+ array_test.call(value)
59
+ end
60
+
61
+ def object?(value)
62
+ value.respond_to?(:inject)
63
+ end
64
+
65
+ def array_test
66
+ @array_test ||= @runtime.evaluate("(function(a) { return a instanceof [].constructor})")
67
+ end
68
+ end
69
+
70
+ def name
71
+ "Johnson (SpiderMonkey)"
72
+ end
73
+
74
+ def compile(source)
75
+ Context.new(source)
76
+ end
77
+
78
+ def available?
79
+ require "johnson"
80
+ true
81
+ rescue LoadError
82
+ false
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,60 @@
1
+ module PAC
2
+ module Runtimes
3
+ class MustangRuntime
4
+ class Context
5
+ def initialize(source = "")
6
+ source = source.encode("UTF-8") if source.respond_to?(:encode)
7
+
8
+ @v8_context = ::Mustang::Context.new
9
+ @v8_context.eval(source)
10
+ end
11
+
12
+ def include(mod)
13
+ (mod.methods - Module.methods).each do |name|
14
+ @v8_context[name] = mod.method(name)
15
+ end
16
+ end
17
+
18
+ def call(properties, *args)
19
+ unbox @v8_context.eval(properties).call(*args)
20
+ rescue NoMethodError => e
21
+ raise ProgramError, e.message
22
+ end
23
+
24
+ def unbox(value)
25
+ case value
26
+ when ::Mustang::V8::Array
27
+ value.map { |v| unbox(v) }
28
+ when ::Mustang::V8::Boolean
29
+ value.to_bool
30
+ when ::Mustang::V8::NullClass, ::Mustang::V8::UndefinedClass
31
+ nil
32
+ when ::Mustang::V8::Function
33
+ nil
34
+ when ::Mustang::V8::SyntaxError
35
+ raise RuntimeError, value.message
36
+ when ::Mustang::V8::Error
37
+ raise ProgramError, value.message
38
+ else
39
+ value.respond_to?(:delegate) ? value.delegate : value
40
+ end
41
+ end
42
+ end
43
+
44
+ def name
45
+ "Mustang (V8)"
46
+ end
47
+
48
+ def compile(source)
49
+ Context.new(source)
50
+ end
51
+
52
+ def available?
53
+ require "mustang"
54
+ true
55
+ rescue LoadError
56
+ false
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,87 @@
1
+ module PAC
2
+ module Runtimes
3
+ class RubyRacerRuntime
4
+ class Context
5
+ def initialize(source = "")
6
+ source = source.encode("UTF-8") if source.respond_to?(:encode)
7
+
8
+ lock do
9
+ @v8_context = V8::Context.new
10
+ @v8_context.eval(source)
11
+ end
12
+ end
13
+
14
+ def include(mod)
15
+ (mod.methods - Module.methods).each do |name|
16
+ @v8_context[name] = mod.method(name)
17
+ end
18
+ end
19
+
20
+ def call(properties, *args)
21
+ lock do
22
+ begin
23
+ unbox @v8_context.eval(properties).call(*args)
24
+ rescue ::V8::JSError => e
25
+ if e.value["name"] == "SyntaxError"
26
+ raise RuntimeError, e.message
27
+ else
28
+ raise ProgramError, e.message
29
+ end
30
+ end
31
+ end
32
+ end
33
+
34
+ def unbox(value)
35
+ case value
36
+ when ::V8::Function
37
+ nil
38
+ when ::V8::Array
39
+ value.map { |v| unbox(v) }
40
+ when ::V8::Object
41
+ value.inject({}) do |vs, (k, v)|
42
+ vs[k] = unbox(v) unless v.is_a?(::V8::Function)
43
+ vs
44
+ end
45
+ when String
46
+ value.respond_to?(:force_encoding) ? value.force_encoding("UTF-8") : value
47
+ else
48
+ value
49
+ end
50
+ end
51
+
52
+ private
53
+ def lock
54
+ result, exception = nil, nil
55
+ V8::C::Locker() do
56
+ begin
57
+ result = yield
58
+ rescue Exception => e
59
+ exception = e
60
+ end
61
+ end
62
+
63
+ if exception
64
+ raise exception
65
+ else
66
+ result
67
+ end
68
+ end
69
+ end
70
+
71
+ def name
72
+ "therubyracer (V8)"
73
+ end
74
+
75
+ def compile(source)
76
+ Context.new(source)
77
+ end
78
+
79
+ def available?
80
+ require "v8"
81
+ true
82
+ rescue LoadError
83
+ false
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,77 @@
1
+ module PAC
2
+ module Runtimes
3
+ class RubyRhinoRuntime
4
+ class Context
5
+ def initialize(source = "")
6
+ source = source.encode("UTF-8") if source.respond_to?(:encode)
7
+
8
+ @rhino_context = Rhino::Context.new
9
+ fix_memory_limit! @rhino_context
10
+ @rhino_context.eval(source)
11
+ end
12
+
13
+ def include(mod)
14
+ (mod.methods - Module.methods).each do |name|
15
+ @rhino_context[name] = mod.method(name)
16
+ end
17
+ end
18
+
19
+ def call(properties, *args)
20
+ unbox @rhino_context.eval(properties).call(*args)
21
+ rescue ::Rhino::JavascriptError => e
22
+ if e.message == "syntax error"
23
+ raise RuntimeError, e.message
24
+ else
25
+ raise ProgramError, e.message
26
+ end
27
+ end
28
+
29
+ def unbox(value)
30
+ case value = ::Rhino::To.ruby(value)
31
+ when ::Rhino::NativeFunction
32
+ nil
33
+ when ::Rhino::NativeObject
34
+ value.inject({}) do |vs, (k, v)|
35
+ case v
36
+ when ::Rhino::NativeFunction, ::Rhino::J::Function
37
+ nil
38
+ else
39
+ vs[k] = unbox(v)
40
+ end
41
+ vs
42
+ end
43
+ when Array
44
+ value.map { |v| unbox(v) }
45
+ else
46
+ value
47
+ end
48
+ end
49
+
50
+ private
51
+ # Disables bytecode compiling which limits you to 64K scripts
52
+ def fix_memory_limit!(context)
53
+ if context.respond_to?(:optimization_level=)
54
+ context.optimization_level = -1
55
+ else
56
+ context.instance_eval { @native.setOptimizationLevel(-1) }
57
+ end
58
+ end
59
+ end
60
+
61
+ def name
62
+ "therubyrhino (Rhino)"
63
+ end
64
+
65
+ def compile(source)
66
+ Context.new(source)
67
+ end
68
+
69
+ def available?
70
+ require "rhino"
71
+ true
72
+ rescue LoadError
73
+ false
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,4 @@
1
+ require "rubygems"
2
+ require "pac"
3
+ require "minitest/autorun"
4
+ require "minitest/spec"
@@ -0,0 +1,3 @@
1
+ module PAC
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,13 @@
1
+ require "pac/test_helper"
2
+
3
+ describe PAC::Functions do
4
+ describe "isResolvable()" do
5
+ it "should return true for localhost" do
6
+ PAC::Functions.isResolvable("localhost").must_equal true
7
+ end
8
+
9
+ it "should return false for awidhaowuhuiuhiuug" do
10
+ PAC::Functions.isResolvable("awidhaowuhuiuhiuug").must_equal false
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,39 @@
1
+ require "pac/test_helper"
2
+
3
+ describe PAC do
4
+ describe "read" do
5
+ before do
6
+ @path = File.expand_path("../files/sample.pac", __FILE__)
7
+ end
8
+
9
+ it "should load a file from a path" do
10
+ pac = PAC.read(@path)
11
+ pac.wont_be_nil
12
+ end
13
+
14
+ it "should return DIRECT for a url" do
15
+ pac = PAC.read(@path)
16
+ pac.find("http://localhost").must_equal "DIRECT"
17
+ end
18
+ end
19
+
20
+ describe "source" do
21
+ before do
22
+ @source = <<-JS
23
+ function FindProxyForURL(url, host) {
24
+ return "DIRECT";
25
+ }
26
+ JS
27
+ end
28
+
29
+ it "should load source" do
30
+ pac = PAC.source(@source)
31
+ pac.wont_be_nil
32
+ end
33
+
34
+ it "should return DIRECT for a url" do
35
+ pac = PAC.source(@source)
36
+ pac.find("http://localhost").must_equal "DIRECT"
37
+ end
38
+ end
39
+ end
metadata ADDED
@@ -0,0 +1,93 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pac
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Samuel Kadolph
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-09-10 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake
16
+ requirement: &70297018438300 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 0.9.2
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *70297018438300
25
+ - !ruby/object:Gem::Dependency
26
+ name: minitest
27
+ requirement: &70297018437400 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: 2.3.1
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *70297018437400
36
+ description: ! 'pac uses a JavaScript runtime to evaulate a proxy auto-config file
37
+ the same way a browser does to determine what proxy (if
38
+
39
+ any at all) should a program use to connect to a server. You must install on of
40
+ the supported JavaScript runtimes:
41
+
42
+ therubyracer, therubyrhino, johnson or mustang.
43
+
44
+ '
45
+ email:
46
+ - samuel@kadolph.com
47
+ executables:
48
+ - parsepac
49
+ extensions: []
50
+ extra_rdoc_files: []
51
+ files:
52
+ - bin/parsepac
53
+ - lib/pac/file.rb
54
+ - lib/pac/functions.rb
55
+ - lib/pac/runtimes/johnson.rb
56
+ - lib/pac/runtimes/mustang.rb
57
+ - lib/pac/runtimes/rubyracer.rb
58
+ - lib/pac/runtimes/rubyrhino.rb
59
+ - lib/pac/runtimes.rb
60
+ - lib/pac/test_helper.rb
61
+ - lib/pac/version.rb
62
+ - lib/pac.rb
63
+ - LICENSE
64
+ - README.md
65
+ - test/pac/functions_test.rb
66
+ - test/pac_test.rb
67
+ homepage: https://github.com/samuelkadolph/ruby-pac
68
+ licenses: []
69
+ post_install_message:
70
+ rdoc_options: []
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ! '>='
77
+ - !ruby/object:Gem::Version
78
+ version: 1.8.7
79
+ required_rubygems_version: !ruby/object:Gem::Requirement
80
+ none: false
81
+ requirements:
82
+ - - ! '>='
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ requirements: []
86
+ rubyforge_project:
87
+ rubygems_version: 1.8.10
88
+ signing_key:
89
+ specification_version: 3
90
+ summary: pac is a gem to parse proxy auto-config files.
91
+ test_files:
92
+ - test/pac/functions_test.rb
93
+ - test/pac_test.rb