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

(-)java/org/apache/catalina/valves/AccessLogValve.java (-10 / +55 lines)
Lines 54-59 Link Here
54
import org.apache.tomcat.util.ExceptionUtils;
54
import org.apache.tomcat.util.ExceptionUtils;
55
import org.apache.tomcat.util.buf.B2CConverter;
55
import org.apache.tomcat.util.buf.B2CConverter;
56
import org.apache.tomcat.util.collections.SynchronizedStack;
56
import org.apache.tomcat.util.collections.SynchronizedStack;
57
import org.apache.tomcat.util.net.IPv6Utils;
57
58
58
59
59
/**
60
/**
Lines 228-233 Link Here
228
229
229
230
230
    /**
231
    /**
232
     * Use IPv6 canonical representation format as defined by RFC 5952.
233
     */
234
    protected boolean canonical = true;
235
236
237
    /**
231
     * The PrintWriter to which we are currently logging, if any.
238
     * The PrintWriter to which we are currently logging, if any.
232
     */
239
     */
233
    protected PrintWriter writer = null;
240
    protected PrintWriter writer = null;
Lines 770-775 Link Here
770
777
771
778
772
    /**
779
    /**
780
     * Are IPv6 addresses represented in canonical representation format
781
     */
782
    public boolean isCanonical() {
783
        return canonical;
784
    }
785
786
787
    /**
788
     * Set the value if IPv6 addresses should be represented in canonical representation format?
789
     *
790
     * @param canonical true if canonical.
791
     */
792
    public void setCanonical(boolean canonical) {
793
        this.canonical = canonical;
794
    }
795
796
797
    /**
773
     * Return whether the attribute name to look for when
798
     * Return whether the attribute name to look for when
774
     * performing conditional logging. If null, every
799
     * performing conditional logging. If null, every
775
     * request is logged.
800
     * request is logged.
Lines 1290-1300 Link Here
1290
    /**
1315
    /**
1291
     * write local IP address - %A
1316
     * write local IP address - %A
1292
     */
1317
     */
1293
    protected static class LocalAddrElement implements AccessLogElement {
1318
    protected class LocalAddrElement implements AccessLogElement {
1294
1319
1295
        private static final String LOCAL_ADDR_VALUE;
1320
        private String localAddrValue;
1296
1321
1297
        static {
1322
        private void lazyInit() {
1298
            String init;
1323
            String init;
1299
            try {
1324
            try {
1300
                init = InetAddress.getLocalHost().getHostAddress();
1325
                init = InetAddress.getLocalHost().getHostAddress();
Lines 1302-1314 Link Here
1302
                ExceptionUtils.handleThrowable(e);
1327
                ExceptionUtils.handleThrowable(e);
1303
                init = "127.0.0.1";
1328
                init = "127.0.0.1";
1304
            }
1329
            }
1305
            LOCAL_ADDR_VALUE = init;
1330
            if (canonical) {
1331
                localAddrValue = IPv6Utils.canonize(init);
1332
            } else {
1333
                localAddrValue = init;
1334
            }
1306
        }
1335
        }
1307
1336
1308
        @Override
1337
        @Override
1309
        public void addElement(CharArrayWriter buf, Date date, Request request,
1338
        public void addElement(CharArrayWriter buf, Date date, Request request,
1310
                Response response, long time) {
1339
                Response response, long time) {
1311
            buf.append(LOCAL_ADDR_VALUE);
1340
            if (localAddrValue == null) {
1341
               lazyInit();
1342
            }
1343
            buf.append(localAddrValue);
1312
        }
1344
        }
1313
    }
1345
    }
1314
1346
Lines 1319-1334 Link Here
1319
        @Override
1351
        @Override
1320
        public void addElement(CharArrayWriter buf, Date date, Request request,
1352
        public void addElement(CharArrayWriter buf, Date date, Request request,
1321
                Response response, long time) {
1353
                Response response, long time) {
1354
            String value = null;
1322
            if (requestAttributesEnabled) {
1355
            if (requestAttributesEnabled) {
1323
                Object addr = request.getAttribute(REMOTE_ADDR_ATTRIBUTE);
1356
                Object addr = request.getAttribute(REMOTE_ADDR_ATTRIBUTE);
1324
                if (addr == null) {
1357
                if (addr == null) {
1325
                    buf.append(request.getRemoteAddr());
1358
                    value = request.getRemoteAddr();
1326
                } else {
1359
                } else {
1327
                    buf.append(addr.toString());
1360
                    value = addr.toString();
1328
                }
1361
                }
1329
            } else {
1362
            } else {
1330
                buf.append(request.getRemoteAddr());
1363
                value = request.getRemoteAddr();
1331
            }
1364
            }
1365
1366
            if (canonical) {
1367
                value = IPv6Utils.canonize(value);
1368
            }
1369
            buf.append(value);
1332
        }
1370
        }
1333
    }
1371
    }
1334
1372
Lines 1352-1357 Link Here
1352
            if (value == null || value.length() == 0) {
1390
            if (value == null || value.length() == 0) {
1353
                value = "-";
1391
                value = "-";
1354
            }
1392
            }
1393
            if (canonical) {
1394
                value = IPv6Utils.canonize(value);
1395
            }
1355
            buf.append(value);
1396
            buf.append(value);
1356
        }
1397
        }
1357
    }
1398
    }
Lines 1794-1804 Link Here
1794
    /**
1835
    /**
1795
     * write local server name - %v
1836
     * write local server name - %v
1796
     */
1837
     */
1797
    protected static class LocalServerNameElement implements AccessLogElement {
1838
    protected class LocalServerNameElement implements AccessLogElement {
1798
        @Override
1839
        @Override
1799
        public void addElement(CharArrayWriter buf, Date date, Request request,
1840
        public void addElement(CharArrayWriter buf, Date date, Request request,
1800
                Response response, long time) {
1841
                Response response, long time) {
1801
            buf.append(request.getServerName());
1842
            if (canonical) {
1843
                buf.append(IPv6Utils.canonize(request.getServerName()));
1844
            } else {
1845
                buf.append(request.getServerName());
1846
            }
1802
        }
1847
        }
1803
    }
1848
    }
1804
1849
(-)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 236-241 Link Here
236
        </p>
236
        </p>
237
      </attribute>
237
      </attribute>
238
238
239
      <attribute name="canonical" required="false">
240
        <p>Flag to determine if IPv6 addresses should be represented in canonical
241
           representation format as defined by RFC 5952. If set to <code>true</code>,
242
           then IPv6 addresses will be written in canonical format (e.g.
243
           <code>2001:db8::1:0:0:1</code>, <code>::1</code>), otherwise it will be
244
           represented in full form (e.g. <code>2001:db8:0:0:1:0:0:1</code>,
245
           <code>0:0:0:0:0:0:0:1</code>). Default value: <code>true</code>
246
        </p>
247
      </attribute>
248
239
      <attribute name="maxLogMessageBufferSize" required="false">
249
      <attribute name="maxLogMessageBufferSize" required="false">
240
        <p>Log message buffers are usually recycled and re-used. To prevent
250
        <p>Log message buffers are usually recycled and re-used. To prevent
241
           excessive memory usage, if a buffer grows beyond this size it will be
251
           excessive memory usage, if a buffer grows beyond this size it will be

Return to bug 51497