proxy_pac_rb 0.0.2 → 0.0.3
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/.rdebugrc +7 -0
- data/.rspec +3 -0
- data/.simplecov +8 -0
- data/.yardopts +5 -0
- data/README.md +12 -0
- data/files/sample2.pac +7 -0
- data/files/sample3.pac +7 -0
- data/lib/proxy_pac_rb.rb +8 -28
- data/lib/proxy_pac_rb/encoding.rb +33 -0
- data/lib/proxy_pac_rb/environment.rb +203 -0
- data/lib/proxy_pac_rb/exceptions.rb +3 -0
- data/lib/proxy_pac_rb/file.rb +11 -7
- data/lib/proxy_pac_rb/parser.rb +45 -0
- data/lib/proxy_pac_rb/proxy_pac_js.rb +194 -0
- data/lib/proxy_pac_rb/runtime.rb +61 -0
- data/lib/proxy_pac_rb/runtimes.rb +16 -7
- data/lib/proxy_pac_rb/runtimes/rubyracer.rb +74 -58
- data/lib/proxy_pac_rb/runtimes/rubyrhino.rb +68 -58
- data/lib/proxy_pac_rb/version.rb +1 -1
- data/proxy_pac_rb.gemspec +3 -0
- data/script/acceptance_test +4 -0
- data/script/bootstrap +5 -0
- data/script/ci +3 -0
- data/script/console +14 -0
- data/script/release +3 -0
- data/script/unit_test +3 -0
- data/spec/environment_spec.rb +193 -0
- data/spec/file_spec.rb +45 -0
- data/spec/parser_spec.rb +116 -0
- data/tmp/functions.js +61 -0
- data/tmp/functions.rb +11 -0
- data/tmp/script.rb +22 -0
- metadata +61 -14
- data/lib/proxy_pac_rb/functions.rb +0 -128
- data/spec/proxy_pac_rb/functions_spec.rb +0 -18
- data/spec/proxy_pac_rb_spec.rb +0 -112
data/.rdebugrc
ADDED
data/.rspec
ADDED
data/.simplecov
ADDED
data/.yardopts
ADDED
data/README.md
CHANGED
@@ -44,6 +44,8 @@ parsepac https://github.com/dg-vrnetze/proxy_pac_rb/raw/master/files/sample.pac
|
|
44
44
|
|
45
45
|
### Ruby
|
46
46
|
|
47
|
+
*Simple*
|
48
|
+
|
47
49
|
```ruby
|
48
50
|
require "rubygems"
|
49
51
|
require "pac"
|
@@ -61,6 +63,16 @@ pac = PAC.source <<-JS
|
|
61
63
|
}
|
62
64
|
JS
|
63
65
|
pac.find('http://localhost') # => "DIRECT"
|
66
|
+
|
67
|
+
*Use Client IP*
|
68
|
+
pac = PAC.load('https://github.com/dg-vrnetze/proxy_pac_rb/raw/master/files/sample2.pac')
|
69
|
+
pac.find('https://github.com', client_ip: '127.0.0.1') # => "PROXY localhost:8080"
|
70
|
+
pac.find('https://github.com', client_ip: '127.0.0.2') # => "DIRECT"
|
71
|
+
|
72
|
+
*Use Date Time*
|
73
|
+
pac = PAC.load('https://github.com/dg-vrnetze/proxy_pac_rb/raw/master/files/sample2.pac')
|
74
|
+
pac.find('https://github.com', time: '2014-01-02 08:00:00') # => "PROXY localhost:8080"
|
75
|
+
pac.find('https://github.com', time: '2014-01-02 19:00:00') # => "DIRECT"
|
64
76
|
```
|
65
77
|
|
66
78
|
## Available JavaScript Functions
|
data/files/sample2.pac
ADDED
data/files/sample3.pac
ADDED
data/lib/proxy_pac_rb.rb
CHANGED
@@ -1,38 +1,18 @@
|
|
1
|
-
require 'uri'
|
1
|
+
require 'addressable/uri'
|
2
2
|
require 'ipaddr'
|
3
3
|
require 'resolv'
|
4
4
|
require 'time'
|
5
|
+
require 'open-uri'
|
6
|
+
require 'active_support/core_ext/string/strip'
|
5
7
|
|
6
8
|
require 'proxy_pac_rb/version'
|
9
|
+
require 'proxy_pac_rb/encoding'
|
7
10
|
require 'proxy_pac_rb/exceptions'
|
8
|
-
require 'proxy_pac_rb/functions'
|
9
11
|
require 'proxy_pac_rb/file'
|
12
|
+
require 'proxy_pac_rb/environment'
|
13
|
+
require 'proxy_pac_rb/runtime'
|
10
14
|
require 'proxy_pac_rb/runtimes/rubyracer'
|
11
15
|
require 'proxy_pac_rb/runtimes/rubyrhino'
|
12
16
|
require 'proxy_pac_rb/runtimes'
|
13
|
-
|
14
|
-
|
15
|
-
class << self
|
16
|
-
attr_reader :runtime
|
17
|
-
|
18
|
-
def runtime=(runtime)
|
19
|
-
fail Exceptions::RuntimeUnavailable, "#{runtime.name} is unavailable on this system" unless runtime.available?
|
20
|
-
@runtime = runtime
|
21
|
-
end
|
22
|
-
|
23
|
-
def load(url, options = {})
|
24
|
-
require "open-uri"
|
25
|
-
File.new(open(url, { :proxy => false }.merge(options)).read)
|
26
|
-
end
|
27
|
-
|
28
|
-
def read(file)
|
29
|
-
File.new(::File.read(file))
|
30
|
-
end
|
31
|
-
|
32
|
-
def source(source)
|
33
|
-
File.new(source)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
self.runtime = Runtimes.autodetect
|
38
|
-
end
|
17
|
+
require 'proxy_pac_rb/parser'
|
18
|
+
require 'proxy_pac_rb/proxy_pac_js'
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module ProxyPacRb
|
2
|
+
# Encodes strings as UTF-8
|
3
|
+
module Encoding
|
4
|
+
if "".respond_to?(:encode)
|
5
|
+
if RUBY_ENGINE == 'jruby' || RUBY_ENGINE == 'rbx'
|
6
|
+
# workaround for jruby bug http://jira.codehaus.org/browse/JRUBY-6588
|
7
|
+
# workaround for rbx bug https://github.com/rubinius/rubinius/issues/1729
|
8
|
+
def encode(string)
|
9
|
+
if string.encoding.name == 'ASCII-8BIT'
|
10
|
+
data = string.dup
|
11
|
+
data.force_encoding('UTF-8')
|
12
|
+
|
13
|
+
unless data.valid_encoding?
|
14
|
+
fail ::Encoding::UndefinedConversionError, "Could not encode ASCII-8BIT data #{string.dump} as UTF-8"
|
15
|
+
end
|
16
|
+
else
|
17
|
+
data = string.encode('UTF-8')
|
18
|
+
end
|
19
|
+
data
|
20
|
+
end
|
21
|
+
else
|
22
|
+
def encode(string)
|
23
|
+
string.encode('UTF-8')
|
24
|
+
end
|
25
|
+
end
|
26
|
+
else
|
27
|
+
# Define no-op on 1.8
|
28
|
+
def encode(string)
|
29
|
+
string
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,203 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module ProxyPacRb
|
3
|
+
class Environment
|
4
|
+
|
5
|
+
private
|
6
|
+
|
7
|
+
attr_reader :days, :months, :my_ip_address, :time, :io, :javascript_function_templates
|
8
|
+
|
9
|
+
public
|
10
|
+
|
11
|
+
attr_reader :available_methods
|
12
|
+
|
13
|
+
def initialize(options = {})
|
14
|
+
@days = { "MON" => 1, "TUE" => 2, "WED" => 3, "THU" => 4, "FRI" => 5, "SAT" => 6, "SUN" => 0 }
|
15
|
+
@months = { "JAN" => 1, "FEB" => 2, "MAR" => 3, "APR" => 4, "MAY" => 5, "JUN" => 6, "JUL" => 7, "AUG" => 8, "SEP" => 9, "OCT" => 10, "NOV" => 11, "DEC" => 12 }
|
16
|
+
|
17
|
+
@my_ip_address = options.fetch(:my_ip_address, '127.0.0.1')
|
18
|
+
@time = options.fetch(:time, Time.now)
|
19
|
+
@io = options.fetch(:io, $stderr)
|
20
|
+
|
21
|
+
@javascript_function_templates = ProxyPacJs
|
22
|
+
|
23
|
+
@available_methods = [
|
24
|
+
:alert,
|
25
|
+
:isPlainHostName,
|
26
|
+
:dnsDomainIs,
|
27
|
+
:localHostOrDomainIs,
|
28
|
+
:isResolvable,
|
29
|
+
:isInNet,
|
30
|
+
:dnsResolve,
|
31
|
+
# :MyIpAddress ,
|
32
|
+
:dnsDomainLevels,
|
33
|
+
:shExpMatch,
|
34
|
+
# :weekdayRange,
|
35
|
+
# :dateRange,
|
36
|
+
# :timeRange,
|
37
|
+
]
|
38
|
+
end
|
39
|
+
|
40
|
+
def alert(msg)
|
41
|
+
io.puts msg
|
42
|
+
end
|
43
|
+
|
44
|
+
def isPlainHostName(host)
|
45
|
+
not host.include? "."
|
46
|
+
end
|
47
|
+
|
48
|
+
def dnsDomainIs(host, domain)
|
49
|
+
host.end_with? domain
|
50
|
+
end
|
51
|
+
|
52
|
+
def localHostOrDomainIs(host, hostdom)
|
53
|
+
host == hostdom or hostdom.include? host
|
54
|
+
end
|
55
|
+
|
56
|
+
def isResolvable(host)
|
57
|
+
!!resolve_host(host)
|
58
|
+
end
|
59
|
+
|
60
|
+
def isInNet(host, pattern, mask)
|
61
|
+
IPAddr.new(pattern).mask(mask).include? resolve_host(host)
|
62
|
+
end
|
63
|
+
|
64
|
+
def dnsResolve(host)
|
65
|
+
resolve_host(host)
|
66
|
+
end
|
67
|
+
|
68
|
+
def MyIpAddress
|
69
|
+
IPAddr.new(my_ip_address).to_s
|
70
|
+
end
|
71
|
+
|
72
|
+
def dnsDomainLevels(host)
|
73
|
+
host.scan(".").size
|
74
|
+
end
|
75
|
+
|
76
|
+
def shExpMatch(str, shexp)
|
77
|
+
::File.fnmatch(shexp, str)
|
78
|
+
end
|
79
|
+
|
80
|
+
def weekdayRange(wd1, wd2 = nil, gmt = nil)
|
81
|
+
fail Exceptions::InvalidArgument, "wd1 needs to be one of #{days.keys.collect {|k| "\"#{k}\""}.join(', ')}" unless days.key?(wd1)
|
82
|
+
fail Exceptions::InvalidArgument, "wd2 needs to be one of #{days.keys.collect {|k| "\"#{k}\""}.join(', ')}" if wd2 and !days.key?(wd2)
|
83
|
+
|
84
|
+
if gmt == "GMT"
|
85
|
+
local_time = time.utc
|
86
|
+
else
|
87
|
+
local_time = time
|
88
|
+
end
|
89
|
+
|
90
|
+
(days[wd1]..days[wd2 || wd1]).include? local_time.wday
|
91
|
+
end
|
92
|
+
|
93
|
+
def dateRange(*args)
|
94
|
+
fail Exceptions::InvalidArgument, "range needs to be one of #{months.keys.collect {|k| "\"#{k}\""}.join(', ')}" if args.any? { |a| !months.key?(a) }
|
95
|
+
|
96
|
+
if args.last == "GMT" and args.pop
|
97
|
+
local_time = time.utc
|
98
|
+
else
|
99
|
+
local_time = time
|
100
|
+
end
|
101
|
+
|
102
|
+
case args.size
|
103
|
+
when 1
|
104
|
+
check_date_part(local_time, args[0])
|
105
|
+
when 2
|
106
|
+
check_date_part(local_time, args[0]..args[1])
|
107
|
+
when 4
|
108
|
+
check_date_part(local_time, args[0]..args[2]) and
|
109
|
+
check_date_part(local_time, args[1]..args[3])
|
110
|
+
when 6
|
111
|
+
check_date_part(local_time, args[0]..args[3]) and
|
112
|
+
check_date_part(local_time, args[1]..args[4]) and
|
113
|
+
check_date_part(local_time, args[2]..args[5])
|
114
|
+
else
|
115
|
+
fail ArgumentError, "wrong number of arguments"
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def timeRange(*args)
|
120
|
+
fail Exceptions::InvalidArgument, "args need to be integer values" if args.any? { |a| !a.kind_of? Fixnum }
|
121
|
+
|
122
|
+
if args.last == "GMT" and args.pop
|
123
|
+
local_time = time.utc
|
124
|
+
else
|
125
|
+
local_time = time
|
126
|
+
end
|
127
|
+
|
128
|
+
case args.size
|
129
|
+
when 1
|
130
|
+
local_time.hour == args[0]
|
131
|
+
when 2
|
132
|
+
(args[0]..args[1]).include? local_time.hour
|
133
|
+
when 4
|
134
|
+
(args[0]..args[2]).include? local_time.hour and
|
135
|
+
(args[1]..args[3]).include? local_time.min
|
136
|
+
when 6
|
137
|
+
(args[0]..args[3]).include? local_time.hour and
|
138
|
+
(args[1]..args[4]).include? local_time.min and
|
139
|
+
(args[2]..args[5]).include? local_time.sec
|
140
|
+
else
|
141
|
+
fail ArgumentError, "wrong number of arguments"
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
private
|
146
|
+
|
147
|
+
def check_date_part(time, part, operation = :==)
|
148
|
+
case part
|
149
|
+
when String
|
150
|
+
time.month.send(operation, months[part])
|
151
|
+
when Integer
|
152
|
+
if part < 100
|
153
|
+
time.day.send(operation, part)
|
154
|
+
else
|
155
|
+
time.year.send(operation, part)
|
156
|
+
end
|
157
|
+
when Range
|
158
|
+
check_date_part(time, part.begin, :>=) and check_date_part(time, part.end, :<=)
|
159
|
+
else
|
160
|
+
fail ArgumentError, "wrong type"
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def resolve_host(host)
|
165
|
+
Resolv.each_address(host) do |address|
|
166
|
+
begin
|
167
|
+
return address if IPAddr.new(address).ipv4?
|
168
|
+
rescue ArgumentError
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
# We couldn't find an IPv4 address for the host
|
173
|
+
nil
|
174
|
+
rescue Resolv::ResolvError, NoMethodError
|
175
|
+
# Have to rescue NoMethodError because jruby has a bug with non existant hostnames
|
176
|
+
# See http://jira.codehaus.org/browse/JRUBY-6054
|
177
|
+
nil
|
178
|
+
end
|
179
|
+
|
180
|
+
public
|
181
|
+
|
182
|
+
def prepare(string)
|
183
|
+
if my_ip_address
|
184
|
+
string << "\n\n"
|
185
|
+
string << javascript_function_templates.my_ip_address_template(my_ip_address)
|
186
|
+
end
|
187
|
+
|
188
|
+
if time
|
189
|
+
string << javascript_function_templates.time_variables
|
190
|
+
string << "\n\n"
|
191
|
+
string << javascript_function_templates.week_day_range_template(time)
|
192
|
+
string << "\n\n"
|
193
|
+
string << javascript_function_templates.week_day_range_template(time)
|
194
|
+
string << "\n\n"
|
195
|
+
string << javascript_function_templates.date_range_template(time)
|
196
|
+
string << "\n\n"
|
197
|
+
string << javascript_function_templates.time_range_template(time)
|
198
|
+
end
|
199
|
+
|
200
|
+
string
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
data/lib/proxy_pac_rb/file.rb
CHANGED
@@ -1,17 +1,21 @@
|
|
1
1
|
module ProxyPacRb
|
2
2
|
class File
|
3
|
-
attr_reader :source, :context
|
4
3
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
4
|
+
private
|
5
|
+
|
6
|
+
attr_reader :javascript
|
7
|
+
|
8
|
+
public
|
9
|
+
|
10
|
+
def initialize(javascript)
|
11
|
+
@javascript = javascript
|
9
12
|
end
|
10
13
|
|
11
14
|
def find(url)
|
12
|
-
uri = URI.
|
15
|
+
uri = Addressable::URI.heuristic_parse(url)
|
13
16
|
fail ArgumentError, "url is missing host" unless uri.host
|
14
|
-
|
17
|
+
|
18
|
+
javascript.call("FindProxyForURL", url, uri.host)
|
15
19
|
end
|
16
20
|
end
|
17
21
|
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module ProxyPacRb
|
3
|
+
class Parser
|
4
|
+
|
5
|
+
private
|
6
|
+
|
7
|
+
attr_reader :runtime, :environment
|
8
|
+
|
9
|
+
public
|
10
|
+
|
11
|
+
def initialize(environment = Environment.new, runtime = Runtimes.autodetect)
|
12
|
+
fail Exceptions::RuntimeUnavailable, "#{runtime.name} is unavailable on this system" unless runtime.available?
|
13
|
+
|
14
|
+
@runtime = runtime
|
15
|
+
@environment = environment
|
16
|
+
end
|
17
|
+
|
18
|
+
def load(url, options = {})
|
19
|
+
create_file(open(url, { :proxy => false }.merge(options)).read)
|
20
|
+
end
|
21
|
+
|
22
|
+
def read(file)
|
23
|
+
create_file(::File.read(file))
|
24
|
+
end
|
25
|
+
|
26
|
+
def source(source)
|
27
|
+
create_file(source)
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def compile_javascript(source)
|
33
|
+
environment.prepare(source)
|
34
|
+
|
35
|
+
context = runtime.compile(source)
|
36
|
+
context.include environment
|
37
|
+
|
38
|
+
context
|
39
|
+
end
|
40
|
+
|
41
|
+
def create_file(source)
|
42
|
+
File.new(compile_javascript(source))
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|