proxy_pac_rb 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/.rdebugrc ADDED
@@ -0,0 +1,7 @@
1
+ set listsize 30
2
+ set history save on
3
+ set history size 99999
4
+ set history filename ~/.rdebug_history
5
+ set autolist
6
+ set autoeval
7
+ set autoreload
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format Fuubar
2
+ --order rand
3
+ --color
data/.simplecov ADDED
@@ -0,0 +1,8 @@
1
+ SimpleCov.start do
2
+ add_filter "/features/"
3
+ add_filter "/spec/"
4
+ add_filter "/tmp"
5
+ add_filter "/vendor"
6
+
7
+ add_group "lib", "lib"
8
+ end
data/.yardopts ADDED
@@ -0,0 +1,5 @@
1
+ -o doc/yard
2
+ --verbose
3
+ -
4
+ LICENSE.md
5
+ README.md
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
@@ -0,0 +1,7 @@
1
+ function FindProxyForURL(url, host) {
2
+ if ( MyIpAddress() == '127.0.0.2' ) {
3
+ return "DIRECT";
4
+ } else {
5
+ return "PROXY localhost:8080";
6
+ }
7
+ }
data/files/sample3.pac ADDED
@@ -0,0 +1,7 @@
1
+ function FindProxyForURL(url, host) {
2
+ if ( timeRange(8, 18) ) {
3
+ return "PROXY localhost:8080";
4
+ } else {
5
+ return "DIRECT";
6
+ }
7
+ }
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
- module ProxyPacRb
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
@@ -6,5 +6,8 @@ module ProxyPacRb
6
6
 
7
7
  #raise on java script runtime error
8
8
  class RuntimeUnavailable < StandardError; end
9
+
10
+ #raise on invalid argument
11
+ class InvalidArgument < StandardError; end
9
12
  end
10
13
  end
@@ -1,17 +1,21 @@
1
1
  module ProxyPacRb
2
2
  class File
3
- attr_reader :source, :context
4
3
 
5
- def initialize(source)
6
- @source = source.dup.freeze
7
- @context = ProxyPacRb.runtime.compile(@source)
8
- @context.include Functions
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.parse(url)
15
+ uri = Addressable::URI.heuristic_parse(url)
13
16
  fail ArgumentError, "url is missing host" unless uri.host
14
- context.call("FindProxyForURL", url, uri.host)
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