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 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