Переглянути джерело

Handle IPv6 address brackets correctly in bypass list. Fix #998.

FelisCatus 8 роки тому
батько
коміт
bf3df2b707

+ 33 - 17
omega-pac/src/conditions.coffee

@@ -306,6 +306,7 @@ module.exports = exports =
           ip: null
           scheme: null
           url: null
+          normalizedPattern: ''
         server = condition.pattern
         if server == '<local>'
           cache.host = server
@@ -313,6 +314,7 @@ module.exports = exports =
         parts = server.split '://'
         if parts.length > 1
           cache.scheme = parts[0]
+          cache.normalizedPattern = cache.scheme + '://'
           server = parts[1]
 
         parts = server.split '/'
@@ -322,36 +324,43 @@ module.exports = exports =
           if addr and not isNaN(prefixLen)
             cache.ip =
               conditionType: 'IpCondition'
-              ip: parts[0]
+              ip: @normalizeIp addr
               prefixLength: prefixLen
+            cache.normalizedPattern += cache.ip.ip + '/' + cache.ip.prefixLength
             return cache
-        if server.charCodeAt(server.length - 1) != ']'.charCodeAt(0)
+        # The server can be an IP address with or without brackets.
+        serverIp = @parseIp(server)
+        if not serverIp?
           pos = server.lastIndexOf(':')
           if pos >= 0
             matchPort = server.substring(pos + 1)
             server = server.substring(0, pos)
-        serverIp = @parseIp server
-        serverRegex = null
+          serverIp = @parseIp server
         if serverIp?
-          if serverIp.regularExpressionString?
-            regexStr = serverIp.regularExpressionString(true)
-            serverRegex = '\\[' + regexStr + '\\]'
+          server = @normalizeIp serverIp
+          if serverIp.v4
+            cache.normalizedPattern += server
           else
-            server = @normalizeIp serverIp
-        else if server.charCodeAt(0) == '.'.charCodeAt(0)
-          server = '*' + server
+            cache.normalizedPattern += '[' + server + ']'
+        else
+          if server.charCodeAt(0) == '.'.charCodeAt(0)
+            server = '*' + server
+          cache.normalizedPattern = server
+
         if matchPort
-          if not serverRegex?
-            serverRegex = shExp2RegExp(server)
-            serverRegex = serverRegex.substring(1, serverRegex.length - 1)
+          cache.port = matchPort
+          cache.normalizedPattern += ':' + cache.port
+          # In URL, IPv6 server addresses need to be bracketed.
+          if serverIp? and not serverIp.v4
+            server = '[' + server + ']'
+          serverRegex = shExp2RegExp(server)
+          serverRegex = serverRegex.substring(1, serverRegex.length - 1)
           scheme = cache.scheme ? '[^:]+'
           cache.url = @safeRegex('^' + scheme + ':\\/\\/' + serverRegex +
             ':' + matchPort + '\\/')
         else if server != '*'
-          if serverRegex
-            serverRegex = '^' + serverRegex + '$'
-          else
-            serverRegex = shExp2RegExp server, trimAsterisk: true
+          # In host, IPv6 server addresses are never bracketed.
+          serverRegex = shExp2RegExp server, trimAsterisk: true
           cache.host = @safeRegex(serverRegex)
         return cache
       match: (condition, request, cache) ->
@@ -374,6 +383,13 @@ module.exports = exports =
             return false if not cache.host.test(request.host)
         return false if cache.url? and !cache.url.test(request.url)
         return true
+      str: (condition) ->
+        analyze = @_handler(condition).analyze
+        cache = analyze.call(exports, condition)
+        if cache.normalizedPattern
+          return cache.normalizedPattern
+        else
+          return condition.pattern
       compile: (condition, cache) ->
         cache = cache.analyzed
         if cache.url?

+ 1 - 1
omega-pac/src/profiles.coffee

@@ -246,7 +246,7 @@ module.exports = exports =
           }
           {
             conditionType: 'BypassCondition'
-            pattern: '::1'
+            pattern: '[::1]'
           }
           {
             conditionType: 'BypassCondition'

+ 33 - 0
omega-pac/test/conditions.coffee

@@ -183,6 +183,13 @@ describe 'Conditions', ->
       result = Conditions.analyze(cond)
       testCond(cond, 'http://[::1]:8080/', 'match')
       testCond(cond, 'http://[1::1]:8080/', not 'match')
+    it 'should correctly support IPv6 canonicalization 2', ->
+      cond =
+        conditionType: 'BypassCondition'
+        pattern: '[::1]'
+      result = Conditions.analyze(cond)
+      testCond(cond, 'http://[::1]:8080/', 'match')
+      testCond(cond, 'http://[1::1]:8080/', not 'match')
 
     it 'should parse IPv4 CIDR notation', ->
       cond =
@@ -559,6 +566,32 @@ describe 'Conditions', ->
       result.should.equal('HostWildcard: ' + condition.pattern)
       cond = Conditions.fromStr(result)
       cond.should.eql(condition)
+    it 'should encode & decode BypassCondition correctly', ->
+      condition =
+        conditionType: 'BypassCondition'
+        pattern: '127.0.0.1/16'
+      result = Conditions.str(condition)
+      result.should.equal('Bypass: 127.0.0.1/16')
+      cond = Conditions.fromStr(result)
+      cond.should.eql(condition)
+    it 'should add brackets for IPv6 hosts in BypassCondition', ->
+      condition =
+        conditionType: 'BypassCondition'
+        pattern: '::1'
+      result = Conditions.str(condition)
+      result.should.equal('Bypass: [::1]')
+      cond = Conditions.fromStr(result)
+      cond.conditionType.should.equal('BypassCondition')
+      cond.pattern.should.equal('[::1]')
+    it 'should add brackets for IPv6 hosts with scheme in BypassCondition', ->
+      condition =
+        conditionType: 'BypassCondition'
+        pattern: 'http://::1'
+      result = Conditions.str(condition)
+      result.should.equal('Bypass: http://[::1]')
+      cond = Conditions.fromStr(result)
+      cond.conditionType.should.equal('BypassCondition')
+      cond.pattern.should.equal('http://[::1]')
     it 'should encode & decode IpCondition correctly', ->
       condition =
         conditionType: 'IpCondition'

+ 6 - 2
omega-target-chromium-extension/src/options.coffee

@@ -74,6 +74,10 @@ class ChromeOptions extends OmegaTarget.Options
       chrome.browserAction.setBadgeText(text: '')
     return
 
+  _formatBypassItem: (condition) ->
+    str = OmegaPac.Conditions.str(condition)
+    i = str.indexOf(' ')
+    return str.substr(i + 1)
   _fixedProfileConfig: (profile) ->
     config = {}
     config['mode'] = 'fixed_servers'
@@ -101,8 +105,8 @@ class ChromeOptions extends OmegaTarget.Options
 
     if config['mode'] != 'direct'
       rules['bypassList'] = bypassList = []
-      for rule in profile.bypassList
-        bypassList.push(rule.pattern)
+      for condition in profile.bypassList
+        bypassList.push(@_formatBypassItem(condition))
       config['rules'] = rules
     return config