pac 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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