View | Details | Raw Unified | Return to bug 51497
Collapse All | Expand All

(-)java/org/apache/catalina/valves/AbstractAccessLogValve.java (-10 / +49 lines)
Lines 46-51 Link Here
46
import org.apache.juli.logging.LogFactory;
46
import org.apache.juli.logging.LogFactory;
47
import org.apache.tomcat.util.ExceptionUtils;
47
import org.apache.tomcat.util.ExceptionUtils;
48
import org.apache.tomcat.util.collections.SynchronizedStack;
48
import org.apache.tomcat.util.collections.SynchronizedStack;
49
import org.apache.tomcat.util.net.IPv6Utils;
49
50
50
51
51
/**
52
/**
Lines 148-153 Link Here
148
     */
149
     */
149
    protected boolean enabled = true;
150
    protected boolean enabled = true;
150
151
152
     /**
153
     * Use IPv6 canonical representation format as defined by RFC 5952.
154
     */
155
    protected boolean canonical = true;
156
151
    /**
157
    /**
152
     * The pattern used to format our access log lines.
158
     * The pattern used to format our access log lines.
153
     */
159
     */
Lines 484-489 Link Here
484
    }
490
    }
485
491
486
    /**
492
    /**
493
     * Are IPv6 addresses represented in canonical representation format?
494
     */
495
    public boolean isCanonical() {
496
        return canonical;
497
    }
498
499
    /**
500
     * Set the value if IPv6 addresses should be represented in canonical representation format.
501
     *
502
     * @param canonical true if canonical.
503
     */
504
    public void setCanonical(boolean canonical) {
505
        this.canonical = canonical;
506
    }
507
508
    /**
487
     * Return the format pattern.
509
     * Return the format pattern.
488
     */
510
     */
489
    public String getPattern() {
511
    public String getPattern() {
Lines 748-758 Link Here
748
    /**
770
    /**
749
     * write local IP address - %A
771
     * write local IP address - %A
750
     */
772
     */
751
    protected static class LocalAddrElement implements AccessLogElement {
773
    protected class LocalAddrElement implements AccessLogElement {
752
774
753
        private static final String LOCAL_ADDR_VALUE;
775
        private String localAddrValue;
754
776
755
        static {
777
        private void lazyInit() {
756
            String init;
778
            String init;
757
            try {
779
            try {
758
                init = InetAddress.getLocalHost().getHostAddress();
780
                init = InetAddress.getLocalHost().getHostAddress();
Lines 760-772 Link Here
760
                ExceptionUtils.handleThrowable(e);
782
                ExceptionUtils.handleThrowable(e);
761
                init = "127.0.0.1";
783
                init = "127.0.0.1";
762
            }
784
            }
763
            LOCAL_ADDR_VALUE = init;
785
            
786
            if (canonical) {
787
                localAddrValue = IPv6Utils.canonize(init);
788
            } else {
789
                localAddrValue = init;
790
            }
764
        }
791
        }
765
792
766
        @Override
793
        @Override
767
        public void addElement(CharArrayWriter buf, Date date, Request request,
794
        public void addElement(CharArrayWriter buf, Date date, Request request,
768
                Response response, long time) {
795
                Response response, long time) {
769
            buf.append(LOCAL_ADDR_VALUE);
796
            if (localAddrValue == null) {
797
               lazyInit();
798
            }
799
            buf.append(localAddrValue);
770
        }
800
        }
771
    }
801
    }
772
802
Lines 777-791 Link Here
777
        @Override
807
        @Override
778
        public void addElement(CharArrayWriter buf, Date date, Request request,
808
        public void addElement(CharArrayWriter buf, Date date, Request request,
779
                Response response, long time) {
809
                Response response, long time) {
810
            String value = null;
780
            if (requestAttributesEnabled) {
811
            if (requestAttributesEnabled) {
781
                Object addr = request.getAttribute(REMOTE_ADDR_ATTRIBUTE);
812
                Object addr = request.getAttribute(REMOTE_ADDR_ATTRIBUTE);
782
                if (addr == null) {
813
                if (addr == null) {
783
                    buf.append(request.getRemoteAddr());
814
                    value = request.getRemoteAddr();
784
                } else {
815
                } else {
785
                    buf.append(addr.toString());
816
                    value = addr.toString();
786
                }
817
                }
787
            } else {
818
            } else {
788
                buf.append(request.getRemoteAddr());
819
                value = request.getRemoteAddr();
789
            }
820
            }
790
        }
821
        }
791
    }
822
    }
Lines 810-815 Link Here
810
            if (value == null || value.length() == 0) {
841
            if (value == null || value.length() == 0) {
811
                value = "-";
842
                value = "-";
812
            }
843
            }
844
845
            if (canonical) {
846
                value = IPv6Utils.canonize(value);
847
            }
813
            buf.append(value);
848
            buf.append(value);
814
        }
849
        }
815
    }
850
    }
Lines 1268-1278 Link Here
1268
    /**
1303
    /**
1269
     * write local server name - %v
1304
     * write local server name - %v
1270
     */
1305
     */
1271
    protected static class LocalServerNameElement implements AccessLogElement {
1306
    protected class LocalServerNameElement implements AccessLogElement {
1272
        @Override
1307
        @Override
1273
        public void addElement(CharArrayWriter buf, Date date, Request request,
1308
        public void addElement(CharArrayWriter buf, Date date, Request request,
1274
                Response response, long time) {
1309
                Response response, long time) {
1275
            buf.append(request.getServerName());
1310
            if (canonical) {
1311
                buf.append(IPv6Utils.canonize(request.getServerName()));
1312
            } else {
1313
                buf.append(request.getServerName());
1314
            }
1276
        }
1315
        }
1277
    }
1316
    }
1278
1317
(-)java/org/apache/tomcat/util/net/IPv6Utils.java (+252 lines)
Line 0 Link Here
1
/*
2
 *  Licensed to the Apache Software Foundation (ASF) under one or more
3
 *  contributor license agreements.  See the NOTICE file distributed with
4
 *  this work for additional information regarding copyright ownership.
5
 *  The ASF licenses this file to You under the Apache License, Version 2.0
6
 *  (the "License"); you may not use this file except in compliance with
7
 *  the License.  You may obtain a copy of the License at
8
 *
9
 *      http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 *  Unless required by applicable law or agreed to in writing, software
12
 *  distributed under the License is distributed on an "AS IS" BASIS,
13
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 *  See the License for the specific language governing permissions and
15
 *  limitations under the License.
16
 */
17
package org.apache.tomcat.util.net;
18
19
/**
20
 * <p>IPv6 utilities.
21
 * <p>For the moment, it only contains function to canonize IPv6 address into
22
 * RFC 5952 form.
23
 */
24
public class IPv6Utils {
25
26
    private static final int MAX_NUMBER_OF_GROUPS = 8;
27
    private static final int MAX_GROUP_LENGTH = 4;
28
29
    /**
30
     * <p>Convert IPv6 adress into RFC 5952 form.
31
     * E.g. 2001:db8:0:1:0:0:0:1 -> 2001:db8:0:1::1</p>
32
     *
33
     * <p>Method is null safe, and if IPv4 address or host name is passed to the
34
     * method it is returned wihout any processing.</p>
35
     *
36
     * <p>Method also supports IPv4 in IPv6 (e.g. 0:0:0:0:0:ffff:192.0.2.1 ->
37
     * ::ffff:192.0.2.1), and zone ID (e.g. fe80:0:0:0:f0f0:c0c0:1919:1234%4
38
     * -> fe80::f0f0:c0c0:1919:1234%4).</p>
39
     *
40
     * @param ipv6Address String representing valid IPv6 address.
41
     * @return String representing IPv6 in canonical form.
42
     * @throws IllegalArgumentException if IPv6 format is unacceptable.
43
     */
44
    public static String canonize(String ipv6Address)
45
            throws IllegalArgumentException {
46
47
        if (ipv6Address == null) {
48
            return null;
49
        }
50
51
        // Definitely not an IPv6, return untouched input.
52
        if (!mayBeIPv6Address(ipv6Address)) {
53
            return ipv6Address;
54
        }
55
56
        // Lenght without zone ID (%zone) or IPv4 address
57
        int ipv6AddressLength = ipv6Address.length();
58
        if (ipv6Address.contains(":") && ipv6Address.contains(".")) {
59
            // IPv4 in IPv6
60
            // e.g. 0:0:0:0:0:FFFF:127.0.0.1
61
            int lastColonPos = ipv6Address.lastIndexOf(":");
62
            int lastColonsPos = ipv6Address.lastIndexOf("::");
63
            if (lastColonsPos >= 0 && lastColonPos == lastColonsPos + 1) {
64
                /*
65
                 *  IPv6 part ends with two consecutive colons,
66
                 *  last colon is part of IPv6 format.
67
                 *  e.g. ::127.0.0.1
68
                 */
69
                ipv6AddressLength = lastColonPos + 1;
70
            } else {
71
                /*
72
                 *  IPv6 part ends with only one colon,
73
                 *  last colon is not part of IPv6 format.
74
                 *  e.g. ::FFFF:127.0.0.1
75
                 */
76
                ipv6AddressLength = lastColonPos;
77
            }
78
        } else if (ipv6Address.contains(":") && ipv6Address.contains("%")) {
79
            // Zone ID
80
            // e.g. fe80:0:0:0:f0f0:c0c0:1919:1234%4
81
            ipv6AddressLength = ipv6Address.lastIndexOf("%");
82
        }
83
84
        StringBuilder result = new StringBuilder();
85
        char [][] groups = new char[MAX_NUMBER_OF_GROUPS][MAX_GROUP_LENGTH];
86
        int groupCounter = 0;
87
        int charInGroupCounter = 0;
88
89
        // Index of the current zeroGroup, -1 means not found.
90
        int zeroGroupIndex = -1;
91
        int zeroGroupLength = 0;
92
93
        // maximum length zero group, if there is more then one, then first one
94
        int maxZeroGroupIndex = -1;
95
        int maxZeroGroupLength = 0;
96
97
        boolean isZero = true;
98
        boolean groupStart = true;
99
100
        /*
101
         *  Two consecutive colons, initial expansion.
102
         *  e.g. 2001:db8:0:0:1::1 -> 2001:db8:0:0:1:0:0:1
103
         */
104
105
        StringBuilder expanded = new StringBuilder(ipv6Address);
106
        int colonsPos = ipv6Address.indexOf("::");
107
        int length = ipv6AddressLength;
108
        int change = 0;
109
110
        if (colonsPos >= 0 && colonsPos < ipv6AddressLength - 2) {
111
            int colonCounter = 0;
112
            for (int i = 0; i < ipv6AddressLength; i++) {
113
                if (ipv6Address.charAt(i) == ':') {
114
                    colonCounter++;
115
                }
116
            }
117
118
            if (colonsPos == 0) {
119
                expanded.insert(0, "0");
120
                change = change + 1;
121
            }
122
123
            for (int i = 0; i < MAX_NUMBER_OF_GROUPS - colonCounter; i++) {
124
                expanded.insert(colonsPos + 1, "0:");
125
                change = change + 2;
126
            }
127
128
129
            if (colonsPos == ipv6AddressLength - 2) {
130
                expanded.setCharAt(colonsPos + change + 1, '0');
131
            } else {
132
                expanded.deleteCharAt(colonsPos + change + 1);
133
                change = change - 1;
134
            }
135
            length = length + change;
136
        }
137
138
139
        // Processing one char at the time
140
        for (int charCounter = 0; charCounter < length; charCounter++) {
141
            char c = expanded.charAt(charCounter);
142
            if (c >= 'A' && c <= 'F') {
143
                c = (char) (c + 32);
144
            }
145
            if (c != ':') {
146
                groups[groupCounter][charInGroupCounter] = c;
147
                if (!(groupStart && c == '0')) {
148
                    ++charInGroupCounter;
149
                    groupStart = false;
150
                }
151
                if (c != '0') {
152
                    isZero = false;
153
                }
154
            }
155
            if (c == ':' || charCounter == (length - 1)) {
156
                // We reached end of current group
157
                if (isZero) {
158
                    ++zeroGroupLength;
159
                    if (zeroGroupIndex == -1) {
160
                        zeroGroupIndex = groupCounter;
161
                    }
162
                }
163
164
                if (!isZero || charCounter == (length - 1)) {
165
                    // We reached end of zero group
166
                    if (zeroGroupLength > maxZeroGroupLength) {
167
                        maxZeroGroupLength = zeroGroupLength;
168
                        maxZeroGroupIndex = zeroGroupIndex;
169
                    }
170
                    zeroGroupLength = 0;
171
                    zeroGroupIndex = -1;
172
                }
173
                ++groupCounter;
174
                charInGroupCounter = 0;
175
                isZero = true;
176
                groupStart = true;
177
            }
178
        }
179
180
        int numberOfGroups = groupCounter;
181
182
        // Output results
183
        for (groupCounter = 0; groupCounter < numberOfGroups; groupCounter++) {
184
            if (maxZeroGroupLength <= 1 || groupCounter < maxZeroGroupIndex
185
                    || groupCounter >= maxZeroGroupIndex + maxZeroGroupLength) {
186
                for (int j = 0; j < MAX_GROUP_LENGTH; j++) {
187
                    if (groups[groupCounter][j] != 0) {
188
                        result.append(groups[groupCounter][j]);
189
                    }
190
                }
191
                if (groupCounter < (numberOfGroups - 1)
192
                        && (groupCounter != maxZeroGroupIndex - 1
193
                                || maxZeroGroupLength <= 1)) {
194
                    result.append(':');
195
                }
196
            } else if (groupCounter == maxZeroGroupIndex) {
197
                result.append("::");
198
            }
199
        }
200
201
        // Solve problem with three colons in IPv4 in IPv6 format
202
        // e.g. 0:0:0:0:0:0:127.0.0.1 -> :::127.0.0.1 -> ::127.0.0.1
203
        int resultLength = result.length();
204
        if (result.charAt(resultLength - 1) == ':' && ipv6AddressLength < ipv6Address.length()
205
                && ipv6Address.charAt(ipv6AddressLength) == ':') {
206
            result.delete(resultLength - 1, resultLength);
207
        }
208
209
        /*
210
         * Append IPv4 from IPv4-in-IPv6 format or Zone ID
211
         */
212
        for (int i = ipv6AddressLength; i < ipv6Address.length(); i++) {
213
            result.append(ipv6Address.charAt(i));
214
        }
215
216
        return result.toString();
217
    }
218
219
    /**
220
     * Heuristic check if string might be an IPv6 address.
221
     *
222
     * @param address Any string or null
223
     * @return true, if input string contains only hex digits and at least two colons, before '.' or '%' charachter
224
     */
225
    protected static boolean mayBeIPv6Address(String input) {
226
        if (input == null) {
227
            return false;
228
        }
229
230
        boolean result = false;
231
        int colonsCounter = 0;
232
        int length = input.length();
233
        for (int i = 0; i < length; i++) {
234
            char c = input.charAt(i);
235
            if (c == '.' || c == '%') {
236
                // IPv4 in IPv6 or Zone ID detected, end of checking.
237
                break;
238
            }
239
            if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f')
240
                    || (c >= 'A' && c <= 'F') || c == ':')) {
241
                return false;
242
            } else if (c == ':') {
243
                colonsCounter++;
244
            }
245
        }
246
        if (colonsCounter >= 2) {
247
            result = true;
248
        }
249
        return result;
250
    }
251
252
}
(-)test/org/apache/tomcat/util/net/IPv6UtilsTest.java (+147 lines)
Line 0 Link Here
1
/*
2
 *  Licensed to the Apache Software Foundation (ASF) under one or more
3
 *  contributor license agreements.  See the NOTICE file distributed with
4
 *  this work for additional information regarding copyright ownership.
5
 *  The ASF licenses this file to You under the Apache License, Version 2.0
6
 *  (the "License"); you may not use this file except in compliance with
7
 *  the License.  You may obtain a copy of the License at
8
 *
9
 *      http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 *  Unless required by applicable law or agreed to in writing, software
12
 *  distributed under the License is distributed on an "AS IS" BASIS,
13
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 *  See the License for the specific language governing permissions and
15
 *  limitations under the License.
16
 */
17
18
package org.apache.tomcat.util.net;
19
20
import static org.junit.Assert.assertEquals;
21
import static org.junit.Assert.assertFalse;
22
import static org.junit.Assert.assertNull;
23
import static org.junit.Assert.assertTrue;
24
25
import org.junit.Test;
26
27
28
/**
29
 * Mostly examples from RFC 5952
30
 */
31
public class IPv6UtilsTest {
32
33
    @Test
34
    public void testMayBeIPv6Address() {
35
        assertFalse(IPv6Utils.mayBeIPv6Address(null));
36
37
        assertTrue(IPv6Utils.mayBeIPv6Address("::1"));
38
        assertTrue(IPv6Utils.mayBeIPv6Address("::"));
39
        assertTrue(IPv6Utils.mayBeIPv6Address("2001:db8:0:0:1:0:0:1"));
40
41
        assertFalse(IPv6Utils.mayBeIPv6Address(""));
42
        assertFalse(IPv6Utils.mayBeIPv6Address(":1"));
43
        assertFalse(IPv6Utils.mayBeIPv6Address("123.123.123.123"));
44
        assertFalse(IPv6Utils.mayBeIPv6Address("tomcat.eu.apache.org:443"));
45
    }
46
47
    @Test
48
    public void testCanonize() {
49
        assertNull(IPv6Utils.canonize(null));
50
        assertEquals("", IPv6Utils.canonize(""));
51
52
        // IPv4-safe
53
        assertEquals("123.123.123.123", IPv6Utils.canonize("123.123.123.123"));
54
        assertEquals("123.1.2.23", IPv6Utils.canonize("123.1.2.23"));
55
56
        // Introductory RFC 5952 examples
57
        assertEquals("2001:db8::1:0:0:1", IPv6Utils.canonize("2001:db8:0:0:1:0:0:1"));
58
        assertEquals("2001:db8::1:0:0:1", IPv6Utils.canonize("2001:0db8:0:0:1:0:0:1"));
59
        assertEquals("2001:db8::1:0:0:1", IPv6Utils.canonize("2001:db8::1:0:0:1"));
60
        assertEquals("2001:db8::1:0:0:1", IPv6Utils.canonize("2001:db8::0:1:0:0:1"));
61
        assertEquals("2001:db8::1:0:0:1", IPv6Utils.canonize("2001:0db8::1:0:0:1"));
62
        assertEquals("2001:db8::1:0:0:1", IPv6Utils.canonize("2001:db8:0:0:1::1"));
63
        assertEquals("2001:db8::1:0:0:1", IPv6Utils.canonize("2001:db8:0000:0:1::1"));
64
        assertEquals("2001:db8::1:0:0:1", IPv6Utils.canonize("2001:DB8:0:0:1::1"));
65
66
        // Strip leading zeros (2.1)
67
        assertEquals("2001:db8:aaaa:bbbb:cccc:dddd:eeee:1", IPv6Utils.canonize("2001:db8:aaaa:bbbb:cccc:dddd:eeee:0001"));
68
        assertEquals("2001:db8:aaaa:bbbb:cccc:dddd:eeee:1", IPv6Utils.canonize("2001:db8:aaaa:bbbb:cccc:dddd:eeee:001"));
69
        assertEquals("2001:db8:aaaa:bbbb:cccc:dddd:eeee:1", IPv6Utils.canonize("2001:db8:aaaa:bbbb:cccc:dddd:eeee:01"));
70
        assertEquals("2001:db8:aaaa:bbbb:cccc:dddd:eeee:1", IPv6Utils.canonize("2001:db8:aaaa:bbbb:cccc:dddd:eeee:1"));
71
72
        // Zero compression (2.2)
73
        assertEquals("2001:db8:aaaa:bbbb:cccc:dddd:0:1", IPv6Utils.canonize("2001:db8:aaaa:bbbb:cccc:dddd::1"));
74
        assertEquals("2001:db8:aaaa:bbbb:cccc:dddd:0:1", IPv6Utils.canonize("2001:db8:aaaa:bbbb:cccc:dddd:0:1"));
75
76
        assertEquals("2001:db8::1", IPv6Utils.canonize("2001:db8:0:0:0::1"));
77
        assertEquals("2001:db8::1", IPv6Utils.canonize("2001:db8:0:0::1"));
78
        assertEquals("2001:db8::1", IPv6Utils.canonize("2001:db8:0::1"));
79
        assertEquals("2001:db8::1", IPv6Utils.canonize("2001:db8::1"));
80
81
        assertEquals("2001:db8::aaaa:0:0:1", IPv6Utils.canonize("2001:db8::aaaa:0:0:1"));
82
        assertEquals("2001:db8::aaaa:0:0:1", IPv6Utils.canonize("2001:db8:0:0:aaaa::1"));
83
84
        // Uppercase or lowercase (2.3)
85
        assertEquals("2001:db8:aaaa:bbbb:cccc:dddd:eeee:aaaa", IPv6Utils.canonize("2001:db8:aaaa:bbbb:cccc:dddd:eeee:aaaa"));
86
        assertEquals("2001:db8:aaaa:bbbb:cccc:dddd:eeee:aaaa", IPv6Utils.canonize("2001:db8:aaaa:bbbb:cccc:dddd:eeee:AAAA"));
87
        assertEquals("2001:db8:aaaa:bbbb:cccc:dddd:eeee:aaaa", IPv6Utils.canonize("2001:db8:aaaa:bbbb:cccc:dddd:eeee:AaAa"));
88
89
        // Some more zero compression for localhost addresses
90
        assertEquals("::1", IPv6Utils.canonize("0:0:0:0:0:0:0:1"));
91
        assertEquals("::1", IPv6Utils.canonize("0000:0:0:0:0:0:0:0001"));
92
        assertEquals("::1", IPv6Utils.canonize("00:00:0:0:00:00:0:01"));
93
        assertEquals("::1", IPv6Utils.canonize("::0001"));
94
        assertEquals("::1", IPv6Utils.canonize("::1"));
95
96
        // IPv6 unspecified address
97
        assertEquals("::", IPv6Utils.canonize("0:0:0:0:0:0:0:0"));
98
        assertEquals("::", IPv6Utils.canonize("0000:0:0:0:0:0:0:0000"));
99
        assertEquals("::", IPv6Utils.canonize("00:00:0:0:00:00:0:00"));
100
        assertEquals("::", IPv6Utils.canonize("::0000"));
101
        assertEquals("::", IPv6Utils.canonize("::0"));
102
        assertEquals("::", IPv6Utils.canonize("::"));
103
104
        // Leading zeros (4.1)
105
        assertEquals("2001:db8::1", IPv6Utils.canonize("2001:0db8::0001"));
106
107
        // Shorten as much as possible (4.2.1)
108
        assertEquals("2001:db8::2:1", IPv6Utils.canonize("2001:db8:0:0:0:0:2:1"));
109
        assertEquals("2001:db8::", IPv6Utils.canonize("2001:db8:0:0:0:0:0:0"));
110
111
        // Handling One 16-Bit 0 Field (4.2.2)
112
        assertEquals("2001:db8:0:1:1:1:1:1", IPv6Utils.canonize("2001:db8:0:1:1:1:1:1"));
113
        assertEquals("2001:db8:0:1:1:1:1:1", IPv6Utils.canonize("2001:db8::1:1:1:1:1"));
114
115
        // Choice in Placement of "::" (4.2.3)
116
        assertEquals("2001:0:0:1::1", IPv6Utils.canonize("2001:0:0:1:0:0:0:1"));
117
        assertEquals("2001:db8::1:0:0:1", IPv6Utils.canonize("2001:db8:0:0:1:0:0:1"));
118
119
        // IPv4 inside IPv6
120
        assertEquals("::ffff:192.0.2.1", IPv6Utils.canonize("::ffff:192.0.2.1"));
121
        assertEquals("::ffff:192.0.2.1", IPv6Utils.canonize("0:0:0:0:0:ffff:192.0.2.1"));
122
        assertEquals("::192.0.2.1", IPv6Utils.canonize("::192.0.2.1"));
123
        assertEquals("::192.0.2.1", IPv6Utils.canonize("0:0:0:0:0:0:192.0.2.1"));
124
125
        // Zone ID
126
        assertEquals("fe80::f0f0:c0c0:1919:1234%4", IPv6Utils.canonize("fe80::f0f0:c0c0:1919:1234%4"));
127
        assertEquals("fe80::f0f0:c0c0:1919:1234%4", IPv6Utils.canonize("fe80:0:0:0:f0f0:c0c0:1919:1234%4"));
128
129
        assertEquals("::%4", IPv6Utils.canonize("::%4"));
130
        assertEquals("::%4", IPv6Utils.canonize("::0%4"));
131
        assertEquals("::%4", IPv6Utils.canonize("0:0::0%4"));
132
        assertEquals("::%4", IPv6Utils.canonize("0:0:0:0:0:0:0:0%4"));
133
134
        assertEquals("::1%4", IPv6Utils.canonize("::1%4"));
135
        assertEquals("::1%4", IPv6Utils.canonize("0:0::1%4"));
136
        assertEquals("::1%4", IPv6Utils.canonize("0:0:0:0:0:0:0:1%4"));
137
138
        assertEquals("::1%eth0", IPv6Utils.canonize("::1%eth0"));
139
        assertEquals("::1%eth0", IPv6Utils.canonize("0:0::1%eth0"));
140
        assertEquals("::1%eth0", IPv6Utils.canonize("0:0:0:0:0:0:0:1%eth0"));
141
142
        // Hostname safety
143
        assertEquals("www.apache.org", IPv6Utils.canonize("www.apache.org"));
144
        assertEquals("ipv6.google.com", IPv6Utils.canonize("ipv6.google.com"));
145
146
    }
147
}
(-)webapps/docs/config/valve.xml (+10 lines)
Lines 240-245 Link Here
240
        </p>
240
        </p>
241
      </attribute>
241
      </attribute>
242
242
243
      <attribute name="canonical" required="false">
244
        <p>Flag to determine if IPv6 addresses should be represented in canonical
245
           representation format as defined by RFC 5952. If set to <code>true</code>,
246
           then IPv6 addresses will be written in canonical format (e.g.
247
           <code>2001:db8::1:0:0:1</code>, <code>::1</code>), otherwise it will be
248
           represented in full form (e.g. <code>2001:db8:0:0:1:0:0:1</code>,
249
           <code>0:0:0:0:0:0:0:1</code>). Default value: <code>true</code>
250
        </p>
251
      </attribute>
252
243
      <attribute name="maxLogMessageBufferSize" required="false">
253
      <attribute name="maxLogMessageBufferSize" required="false">
244
        <p>Log message buffers are usually recycled and re-used. To prevent
254
        <p>Log message buffers are usually recycled and re-used. To prevent
245
           excessive memory usage, if a buffer grows beyond this size it will be
255
           excessive memory usage, if a buffer grows beyond this size it will be

Return to bug 51497