Correct various edge cases in the new HTTP Host header validation parser.
Patch provided by Katya Todorova.

Fix IPv6/IPv4 parsing for host header:
    - chars other than : should not be allowed in IPv6 address after ]
    - ::: should not present in IPv6 address
    - IPv4 part of IPv6 address was not correctly parsed (1 symbol of IPv4 part was ignored)
    - tests added to cover IPv4/6 parsing 
    - parsed test class fixed not to throw NPE when an exception is expected but not thrown 


git-svn-id: https://svn.apache.org/repos/asf/tomcat/tc8.0.x/trunk@1830251 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/java/org/apache/tomcat/util/http/parser/HttpParser.java b/java/org/apache/tomcat/util/http/parser/HttpParser.java
index 62687fa..a945493 100644
--- a/java/org/apache/tomcat/util/http/parser/HttpParser.java
+++ b/java/org/apache/tomcat/util/http/parser/HttpParser.java
@@ -577,45 +577,50 @@
         int h16Size = 0;
         int pos = 1;
         boolean parsedDoubleColon = false;
-        boolean previousWasColon = false;
+        int precedingColonsCount = 0;
 
         do {
             c = reader.read();
-            if (h16Count == 0 && previousWasColon && c != ':') {
+            if (h16Count == 0 && precedingColonsCount == 1 && c != ':') {
                 // Can't start with a single :
                 throw new IllegalArgumentException();
             }
             if (HttpParser.isHex(c)) {
                 if (h16Size == 0) {
                     // Start of a new h16 block
-                    previousWasColon = false;
+                    precedingColonsCount = 0;
                     h16Count++;
-                    reader.mark(4);
                 }
                 h16Size++;
                 if (h16Size > 4) {
                     throw new IllegalArgumentException();
                 }
             } else if (c == ':') {
-                if (previousWasColon) {
-                    // End of ::
-                    if (parsedDoubleColon) {
-                        // Only allowed one :: sequence
-                        throw new IllegalArgumentException();
-                    }
-                    parsedDoubleColon = true;
-                    previousWasColon = false;
-                    // :: represents at least one h16 block
-                    h16Count++;
+                if (precedingColonsCount >=2 ) {
+                    // ::: is not allowed
+                    throw new IllegalArgumentException();
                 } else {
-                    previousWasColon = true;
+                    if(precedingColonsCount == 1) {
+                        // End of ::
+                        if (parsedDoubleColon ) {
+                            // Only allowed one :: sequence
+                            throw new IllegalArgumentException();
+                        }
+                        parsedDoubleColon = true;
+                        // :: represents at least one h16 block
+                        h16Count++;
+                    }
+                    precedingColonsCount++;
+                    // mark if the next symbol is hex before the actual read
+                    reader.mark(4);
                 }
                 h16Size = 0;
             } else if (c == ']') {
-                if (previousWasColon) {
+                if (precedingColonsCount == 1) {
                     // Can't end on a single ':'
                     throw new IllegalArgumentException();
                 }
+                pos++;
                 break;
             } else if (c == '.') {
                 if (h16Count == 7 || h16Count < 7 && parsedDoubleColon) {
@@ -641,9 +646,12 @@
 
         c = reader.read();
         if (c == ':') {
-            return pos + 1;
+            return pos;
         } else {
-            return -1;
+            if(c == -1) {
+                return -1;
+            }
+            throw new IllegalArgumentException();
         }
     }
 
diff --git a/res/maven/mvn-pub.xml b/res/maven/mvn-pub.xml
index 1bd7454..b8504a5 100644
--- a/res/maven/mvn-pub.xml
+++ b/res/maven/mvn-pub.xml
@@ -49,35 +49,18 @@
     </copy>
 
     <!--sign the jar, the source and the pom -->
-    <exec executable="${gpg.exec}" failonerror="true"
-          inputstring="${gpg.passphrase}">
-      <arg value="--batch"/>
-      <arg value="--passphrase-fd"/>
-      <arg value="0"/>
-      <arg value="-a"/>
-      <arg value="-b"/>
-      <arg value="${file}"/>
-    </exec>
-    <exec executable="${gpg.exec}" failonerror="true"
-          inputstring="${gpg.passphrase}">
-      <arg value="--batch"/>
-      <arg value="--passphrase-fd"/>
-      <arg value="0"/>
-      <arg value="-a"/>
-      <arg value="-b"/>
-      <arg value="${src}"/>
-    </exec>
-    <exec executable="${gpg.exec}" failonerror="true"
-          inputstring="${gpg.passphrase}">
-      <arg value="--batch"/>
-      <arg value="--passphrase-fd"/>
-      <arg value="0"/>
-      <arg value="-a"/>
-      <arg value="-b"/>
-      <arg value="-o"/>
-      <arg value="${pom}.asc"/>
-      <arg value="${pom}.tmp"/>
-    </exec>
+    <antcall target="-sign" >
+      <param name="file.in" value="@{file}" />
+      <param name="file.out" value="@{file}.asc" />
+    </antcall>
+    <antcall target="-sign" >
+      <param name="file.in" value="@{src}" />
+      <param name="file.out" value="@{src}.asc" />
+    </antcall>
+    <antcall target="-sign" >
+      <param name="file.in" value="@{pom}.tmp" />
+      <param name="file.out" value="@{pom}.asc" />
+    </antcall>
 
     <artifact:deploy file="${file}">
         <pom file="${pom}.tmp"/>
@@ -131,26 +114,14 @@
     </copy>
 
     <!--sign the file and pom -->
-    <exec executable="${gpg.exec}" failonerror="true"
-          inputstring="${gpg.passphrase}">
-      <arg value="--batch"/>
-      <arg value="--passphrase-fd"/>
-      <arg value="0"/>
-      <arg value="-a"/>
-      <arg value="-b"/>
-      <arg value="${file}"/>
-    </exec>
-    <exec executable="${gpg.exec}" failonerror="true"
-          inputstring="${gpg.passphrase}">
-      <arg value="--batch"/>
-      <arg value="--passphrase-fd"/>
-      <arg value="0"/>
-      <arg value="-a"/>
-      <arg value="-b"/>
-      <arg value="-o"/>
-      <arg value="${pom}.asc"/>
-      <arg value="${pom}.tmp"/>
-    </exec>
+    <antcall target="-sign" >
+      <param name="file.in" value="@{file}" />
+      <param name="file.out" value="@{file}.asc" />
+    </antcall>
+    <antcall target="-sign" >
+      <param name="file.in" value="@{pom}.tmp" />
+      <param name="file.out" value="@{pom}.asc" />
+    </antcall>
 
     <artifact:deploy file="${file}">
       <pom file="${pom}.tmp"/>
@@ -198,35 +169,18 @@
     </copy>
 
     <!--sign the zip, the tar.gz and the pom -->
-    <exec executable="${gpg.exec}" failonerror="true"
-          inputstring="${gpg.passphrase}">
-      <arg value="--batch"/>
-      <arg value="--passphrase-fd"/>
-      <arg value="0"/>
-      <arg value="-a"/>
-      <arg value="-b"/>
-      <arg value="${file}.zip"/>
-    </exec>
-    <exec executable="${gpg.exec}" failonerror="true"
-          inputstring="${gpg.passphrase}">
-      <arg value="--batch"/>
-      <arg value="--passphrase-fd"/>
-      <arg value="0"/>
-      <arg value="-a"/>
-      <arg value="-b"/>
-      <arg value="${file}.tar.gz"/>
-    </exec>
-    <exec executable="${gpg.exec}" failonerror="true"
-          inputstring="${gpg.passphrase}">
-      <arg value="--batch"/>
-      <arg value="--passphrase-fd"/>
-      <arg value="0"/>
-      <arg value="-a"/>
-      <arg value="-b"/>
-      <arg value="-o"/>
-      <arg value="${pom}.asc"/>
-      <arg value="${pom}.tmp"/>
-    </exec>
+    <antcall target="-sign" >
+      <param name="file.in" value="@{file}" />
+      <param name="file.out" value="@{file}.asc" />
+    </antcall>
+    <antcall target="-sign" >
+      <param name="file.in" value="@{file}.tar.gz" />
+      <param name="file.out" value="@{file}.tar.gz.asc" />
+    </antcall>
+    <antcall target="-sign" >
+      <param name="file.in" value="@{pom}.tmp" />
+      <param name="file.out" value="@{pom}.asc" />
+    </antcall>
 
     <artifact:deploy file="${pom}">
         <pom file="${pom}.tmp"/>
@@ -262,7 +216,7 @@
     </sequential>
   </macrodef>
 
-  <target name="generic-deploy" depends="init-maven,init-gpg,init-ldap">
+  <target name="generic-deploy" depends="init-maven,init-gpg-1,init-gpg-2,init-ldap">
     <!-- Standard jars in bin directory -->
     <!-- Skip bootstrap.jar - it is just a subset of catalina.jar -->
     <doMavenDeploy artifactId="tomcat-juli"
@@ -413,7 +367,11 @@
     </antcall>
   </target>
 
-  <target name="init-gpg">
+  <target name="init-gpg-1">
+    <available file="${gpg.exec}" property="gpg.exec.available"/>
+  </target>
+
+  <target name="init-gpg-2" if="${gpg.exec.available}">
     <input message="Enter GPG pass-phrase" addproperty="gpg.passphrase" >
       <handler type="secure"/>
     </input>
@@ -426,4 +384,19 @@
     </input>
   </target>
 
+  <target name="-sign" if="gpg.passphrase">
+    <fail unless="file" />
+    <exec executable="${gpg.exec}" failonerror="true"
+          inputstring="${gpg.passphrase}">
+      <arg value="--batch"/>
+      <arg value="--passphrase-fd"/>
+      <arg value="0"/>
+      <arg value="-a"/>
+      <arg value="-b"/>
+      <arg value="-o"/>
+      <arg value="${file.out}"/>
+      <arg value="${file.in}"/>
+    </exec>
+  </target>
+
 </project>
diff --git a/test/org/apache/tomcat/util/http/parser/TestHttpParserHost.java b/test/org/apache/tomcat/util/http/parser/TestHttpParserHost.java
index f49f4bb..a6f98ba 100644
--- a/test/org/apache/tomcat/util/http/parser/TestHttpParserHost.java
+++ b/test/org/apache/tomcat/util/http/parser/TestHttpParserHost.java
@@ -66,6 +66,7 @@
         result.add(new Object[] { TestType.IPv4, "0.0.0.256", Integer.valueOf(-1), IAE} );
         result.add(new Object[] { TestType.IPv4, "0.a.0.0", Integer.valueOf(-1), IAE} );
         result.add(new Object[] { TestType.IPv4, "0..0.0", Integer.valueOf(-1), IAE} );
+        result.add(new Object[] { TestType.IPv4, "0]", Integer.valueOf(-1), IAE} );
         // Domain Name - valid
         result.add(new Object[] { TestType.DOMAIN_NAME, "localhost", Integer.valueOf(-1), null} );
         result.add(new Object[] { TestType.DOMAIN_NAME, "localhost:8080", Integer.valueOf(9), null} );
@@ -121,6 +122,7 @@
         result.add(new Object[] { TestType.IPv6, "[0:0:0:0:0:0:127.0.0.1]", Integer.valueOf(-1), null} );
         result.add(new Object[] { TestType.IPv6, "[0:0:0:0:0:0:127.0.0.1]:8080",
                 Integer.valueOf(23), null} );
+        result.add(new Object[] { TestType.IPv6, "[::1.2.3.4]", Integer.valueOf(-1), null} );
         // IPv6 - invalid
         result.add(new Object[] { TestType.IPv6, "[1234:5678:90AB:CDEF:1234:127.0.0.1]",
                 Integer.valueOf(-1), IAE} );
@@ -136,6 +138,18 @@
         result.add(new Object[] { TestType.IPv6, "[0::0::127.0.0.1]", Integer.valueOf(-1), IAE} );
         result.add(new Object[] { TestType.IPv6, "[0:0:G:0:0:0:127.0.0.1]", Integer.valueOf(-1), IAE} );
         result.add(new Object[] { TestType.IPv6, "[00000:0:0:0:0:0:127.0.0.1]", Integer.valueOf(-1), IAE} );
+        result.add(new Object[] { TestType.IPv6, "[::1]'", Integer.valueOf(-1), IAE} );
+        result.add(new Object[] { TestType.IPv6, "[:2222:3333:4444:5555:6666:7777:8888]",
+                Integer.valueOf(-1), IAE} );
+        result.add(new Object[] { TestType.IPv6, "[1111:::3333:4444:5555:6666:7777:8888]",
+                Integer.valueOf(-1), IAE} );
+        result.add(new Object[] { TestType.IPv6, "::1]", Integer.valueOf(-1), IAE} );
+        result.add(new Object[] { TestType.IPv6, "[1111:2222:3333:4444:5555:6666:7777:8888:9999]",
+                Integer.valueOf(-1), IAE} );
+        result.add(new Object[] { TestType.IPv6, "[1111:2222:3333:4444:5555:6666:7777:1.2.3.4]",
+            Integer.valueOf(-1), IAE} );
+        result.add(new Object[] { TestType.IPv6, "[1111:2222:3333]",
+            Integer.valueOf(-1), IAE} );
         return result;
     }
 
@@ -165,6 +179,7 @@
         if (expectedException == null) {
             Assert.assertNull(input, exceptionClass);
         } else {
+            Assert.assertNotNull(exceptionClass);
             Assert.assertTrue(input, expectedException.isAssignableFrom(exceptionClass));
         }
     }
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 6cc9ac6..40f60d3 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -64,7 +64,7 @@
         when the Valve is configured on a Host or an Engine. (fschumacher)
       </fix>
     </changelog>
-  </subsection>  
+  </subsection>
   <subsection name="Jasper">
     <changelog>
       <fix>