make http condition follow redirects from http to https

Bugzilla Report 65105
diff --git a/WHATSNEW b/WHATSNEW
index be98daa..35f8ec8 100644
--- a/WHATSNEW
+++ b/WHATSNEW
@@ -27,6 +27,9 @@
    central repository didn't contain any source files.
    Bugzilla Report 65110
 
+ * The <http> condition didn't follow redirects from http to https.
+   Bugzilla Report 65105
+
 Other changes:
 --------------
 
diff --git a/src/main/org/apache/tools/ant/taskdefs/Get.java b/src/main/org/apache/tools/ant/taskdefs/Get.java
index e7d56d7..5ee3fb6 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Get.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Get.java
@@ -534,6 +534,18 @@
     }
 
     /**
+     * Does the response code represent a redirection?
+     *
+     * @since 1.10.10
+     */
+    public static boolean isMoved(final int responseCode) {
+        return responseCode == HttpURLConnection.HTTP_MOVED_PERM
+            || responseCode == HttpURLConnection.HTTP_MOVED_TEMP
+            || responseCode == HttpURLConnection.HTTP_SEE_OTHER
+            || responseCode == HTTP_MOVED_TEMP;
+    }
+
+    /**
      * Interface implemented for reporting
      * progress of downloading.
      */
@@ -815,13 +827,6 @@
             return connection;
         }
 
-        private boolean isMoved(final int responseCode) {
-            return responseCode == HttpURLConnection.HTTP_MOVED_PERM
-                    || responseCode == HttpURLConnection.HTTP_MOVED_TEMP
-                    || responseCode == HttpURLConnection.HTTP_SEE_OTHER
-                    || responseCode == HTTP_MOVED_TEMP;
-        }
-
         private boolean downloadFile() throws IOException {
             for (int i = 0; i < numberRetries; i++) {
                 // this three attempt trick is to get round quirks in different
diff --git a/src/main/org/apache/tools/ant/taskdefs/condition/Http.java b/src/main/org/apache/tools/ant/taskdefs/condition/Http.java
index 1219fab..a047dec 100644
--- a/src/main/org/apache/tools/ant/taskdefs/condition/Http.java
+++ b/src/main/org/apache/tools/ant/taskdefs/condition/Http.java
@@ -30,6 +30,7 @@
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.ProjectComponent;
+import org.apache.tools.ant.taskdefs.Get;
 
 /**
  * Condition to wait for a HTTP request to succeed. Its attribute(s) are:
@@ -42,6 +43,8 @@
 public class Http extends ProjectComponent implements Condition {
     private static final int ERROR_BEGINS = 400;
     private static final String DEFAULT_REQUEST_METHOD = "GET";
+    private static final String HTTP = "http";
+    private static final String HTTPS = "https";
 
     private String spec = null;
     private String requestMethod = DEFAULT_REQUEST_METHOD;
@@ -124,11 +127,7 @@
             try {
                 URLConnection conn = url.openConnection();
                 if (conn instanceof HttpURLConnection) {
-                    HttpURLConnection http = (HttpURLConnection) conn;
-                    http.setRequestMethod(requestMethod);
-                    http.setInstanceFollowRedirects(followRedirects);
-                    http.setReadTimeout(readTimeout);
-                    int code = http.getResponseCode();
+                    int code = request((HttpURLConnection) conn, url);
                     log("Result code for " + spec + " was " + code,
                         Project.MSG_VERBOSE);
                     return code > 0 && code < errorsBeginAt;
@@ -144,4 +143,39 @@
         }
         return true;
     }
+
+    private int request(final HttpURLConnection http, final URL url) throws IOException {
+        http.setRequestMethod(requestMethod);
+        http.setInstanceFollowRedirects(followRedirects);
+        http.setReadTimeout(readTimeout);
+        final int firstStatusCode = http.getResponseCode();
+        if (Get.isMoved(firstStatusCode)) {
+            final String newLocation = http.getHeaderField("Location");
+            final URL newURL = new URL(newLocation);
+            if (redirectionAllowed(url, newURL)) {
+                final URLConnection newConn = newURL.openConnection();
+                if (newConn instanceof HttpURLConnection) {
+                    log("Following redirect from " + url + " to " + newURL);
+                    return request((HttpURLConnection) newConn, newURL);
+                }
+            }
+        }
+        return firstStatusCode;
+    }
+
+    private boolean redirectionAllowed(final URL from, final URL to) {
+        if (from.equals(to)) {
+            // most simple case of an infinite redirect loop
+            return false;
+        }
+        if (!(from.getProtocol().equals(to.getProtocol())
+              || (HTTP.equals(from.getProtocol())
+                  && HTTPS.equals(to.getProtocol())))) {
+            log("Redirection detected from "
+                + from.getProtocol() + " to " + to.getProtocol()
+                + ". Protocol switch unsafe, not allowed.");
+            return false;
+        }
+        return true;
+    }
 }
diff --git a/src/tests/antunit/taskdefs/condition/http-test.xml b/src/tests/antunit/taskdefs/condition/http-test.xml
new file mode 100644
index 0000000..91ec866
--- /dev/null
+++ b/src/tests/antunit/taskdefs/condition/http-test.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<!--
+  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
+
+      https://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.
+-->
+
+<project name="http-test" default="antunit" xmlns:au="antlib:org.apache.ant.antunit">
+  <import file="../../antunit-base.xml" />
+
+  <property name="location" value="https://ant.apache.org/webtest/gettest" />
+  <property name="unsecurelocation" value="http://ant.apache.org/webtest/gettest/http-to-https.txt" />
+
+  <target name="testSeeOtherRedirect">
+    <sleep milliseconds="250"/>
+    <au:assertTrue>
+      <http url="${location}/other.txt"/>
+    </au:assertTrue>
+    <au:assertLogContains level="verbose"
+        text="Result code for ${location}/other.txt was 200" />
+  </target>
+
+  <target name="testPermanentRedirect">
+    <sleep milliseconds="250"/>
+    <au:assertTrue>
+      <http url="${location}/permanent.txt"/>
+    </au:assertTrue>
+    <au:assertLogContains level="verbose"
+        text="Result code for ${location}/permanent.txt was 200" />
+  </target>
+
+  <target name="testTemporaryRedirect">
+    <sleep milliseconds="250"/>
+    <au:assertTrue>
+      <http url="${location}/temp.txt"/>
+    </au:assertTrue>
+    <au:assertLogContains level="verbose"
+        text="Result code for ${location}/temp.txt was 200" />
+  </target>
+
+  <target name="testStatusCode307Redirect">
+    <sleep milliseconds="250"/>
+    <au:assertTrue>
+      <http url="${location}/307.txt"/>
+    </au:assertTrue>
+    <au:assertLogContains level="verbose"
+        text="Result code for ${location}/307.txt was 200" />
+  </target>
+
+  <target name="testHttpToHttpsRedirect" description="Tests that a resource that's redirected
+        from HTTP to HTTPS works without an error. See bugzilla-65105 for details">
+    <sleep milliseconds="250"/>
+    <au:assertTrue>
+      <http url="${unsecurelocation}"/>
+    </au:assertTrue>
+    <au:assertLogContains level="verbose"
+        text="Result code for ${unsecurelocation} was 200" />
+  </target>
+
+</project>