/*
 * ====================================================================
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 *
 */

package org.apache.http.conn.util;

import java.util.regex.Pattern;

import org.apache.http.annotation.Immutable;

/**
 * A collection of utilities relating to InetAddresses.
 *
 * @since 4.0
 */
@Immutable
public class InetAddressUtils {

    private InetAddressUtils() {
    }

    private static final String IPV4_BASIC_PATTERN_STRING = 
            "(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])";

    private static final Pattern IPV4_PATTERN =
        Pattern.compile("^" + IPV4_BASIC_PATTERN_STRING + "$");

    private static final Pattern IPV4_MAPPED_IPV6_PATTERN = // TODO does not allow for redundant leading zeros
            Pattern.compile("^::[fF]{4}:" + IPV4_BASIC_PATTERN_STRING + "$");

    private static final Pattern IPV6_STD_PATTERN =
        Pattern.compile(
                "^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$");

    private static final Pattern IPV6_HEX_COMPRESSED_PATTERN =
        Pattern.compile(
                "^((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)::((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)$");

    public static boolean isIPv4Address(final String input) {
        return IPV4_PATTERN.matcher(input).matches();
    }

    public static boolean isIPv4MappedIPv64Address(final String input) {
        return IPV4_MAPPED_IPV6_PATTERN.matcher(input).matches();
    }

    public static boolean isIPv6StdAddress(final String input) {
        return IPV6_STD_PATTERN.matcher(input).matches();
    }

    public static boolean isIPv6HexCompressedAddress(final String input) {
        return IPV6_HEX_COMPRESSED_PATTERN.matcher(input).matches();
    }

    public static boolean isIPv6Address(final String input) {
        return isIPv6StdAddress(input) || isIPv6HexCompressedAddress(input);
    }

}

@@ -1588,16 +1588,75 @@
 )%5C%5C.)%7B3%7D
+%22 + // initial 3 fields, 0-255 followed by .%0A             %22
 (%5B0-9%5D%7C%5B
@@ -1697,16 +1697,38 @@
 %5B0-5%5D)%22;
+ // final field, 0-255
 %0A%0A    pr
@@ -2120,18 +2120,16 @@
      %22%5E(
-?:
 %5B0-9a-fA
@@ -2271,18 +2271,16 @@
     %22%5E((
-?:
 %5B0-9A-Fa
@@ -2280,34 +2280,32 @@
 0-9A-Fa-f%5D%7B1,4%7D(
-?:
 :%5B0-9A-Fa-f%5D%7B1,4
@@ -2314,18 +2314,16 @@
 *)?)::((
-?:
 %5B0-9A-Fa
@@ -2335,10 +2335,8 @@
 ,4%7D(
-?:
 :%5B0-

Make repeat string in IPv4 expression more obvious Remove non-capturing groups for clarity