execute status code check on HEAD

Daniel Gultsch created

Change summary

src/main/java/eu/siacs/conversations/http/HttpDownloadConnection.java | 82 
1 file changed, 45 insertions(+), 37 deletions(-)

Detailed changes

src/main/java/eu/siacs/conversations/http/HttpDownloadConnection.java 🔗

@@ -318,6 +318,7 @@ public class HttpDownloadConnection implements Transferable {
             mostRecentCall = client.newCall(request);
             try {
                 final Response response = mostRecentCall.execute();
+                throwOnInvalidCode(response);
                 final String contentLength = response.header("Content-Length");
                 final String contentType = response.header("Content-Type");
                 final AbstractConnectionManager.Extension extension = AbstractConnectionManager.Extension.of(mUrl.encodedPath());
@@ -332,7 +333,11 @@ public class HttpDownloadConnection implements Transferable {
                 if (Strings.isNullOrEmpty(contentLength)) {
                     throw new IOException("no content-length found in HEAD response");
                 }
-                return Long.parseLong(contentLength, 10);
+                final long size = Long.parseLong(contentLength, 10);
+                if (size < 0) {
+                    throw new IOException("Server reported negative file size");
+                }
+                return size;
             } catch (IOException e) {
                 Log.d(Config.LOGTAG, "io exception during HEAD " + e.getMessage());
                 throw e;
@@ -395,45 +400,41 @@ public class HttpDownloadConnection implements Transferable {
             final Request request = requestBuilder.build();
             mostRecentCall = client.newCall(request);
             final Response response = mostRecentCall.execute();
-            final int code = response.code();
-            if (code >= 200 && code <= 299) {
-                final String contentRange = response.header("Content-Range");
-                final boolean serverResumed = tryResume && contentRange != null && contentRange.startsWith("bytes " + resumeSize + "-");
-                final InputStream inputStream = response.body().byteStream();
-                final OutputStream outputStream;
-                long transmitted = 0;
-                if (tryResume && serverResumed) {
-                    Log.d(Config.LOGTAG, "server resumed");
-                    transmitted = file.getSize();
-                    updateProgress(Math.round(((double) transmitted / expected) * 100));
-                    outputStream = AbstractConnectionManager.createOutputStream(file, true, false);
-                } else {
-                    final String contentLength = response.header("Content-Length");
-                    final long size = Strings.isNullOrEmpty(contentLength) ? 0 : Longs.tryParse(contentLength);
-                    if (expected != size) {
-                        Log.d(Config.LOGTAG, "content-length reported on GET (" + size + ") did not match Content-Length reported on HEAD (" + expected + ")");
-                    }
-                    file.getParentFile().mkdirs();
-                    if (!file.exists() && !file.createNewFile()) {
-                        throw new FileWriterException();
-                    }
-                    outputStream = AbstractConnectionManager.createOutputStream(file, false, false);
+            throwOnInvalidCode(response);
+            final String contentRange = response.header("Content-Range");
+            final boolean serverResumed = tryResume && contentRange != null && contentRange.startsWith("bytes " + resumeSize + "-");
+            final InputStream inputStream = response.body().byteStream();
+            final OutputStream outputStream;
+            long transmitted = 0;
+            if (tryResume && serverResumed) {
+                Log.d(Config.LOGTAG, "server resumed");
+                transmitted = file.getSize();
+                updateProgress(Math.round(((double) transmitted / expected) * 100));
+                outputStream = AbstractConnectionManager.createOutputStream(file, true, false);
+            } else {
+                final String contentLength = response.header("Content-Length");
+                final long size = Strings.isNullOrEmpty(contentLength) ? 0 : Longs.tryParse(contentLength);
+                if (expected != size) {
+                    Log.d(Config.LOGTAG, "content-length reported on GET (" + size + ") did not match Content-Length reported on HEAD (" + expected + ")");
                 }
-                int count;
-                final byte[] buffer = new byte[4096];
-                while ((count = inputStream.read(buffer)) != -1) {
-                    transmitted += count;
-                    try {
-                        outputStream.write(buffer, 0, count);
-                    } catch (IOException e) {
-                        throw new FileWriterException();
-                    }
-                    updateProgress(Math.round(((double) transmitted / expected) * 100));
+                file.getParentFile().mkdirs();
+                if (!file.exists() && !file.createNewFile()) {
+                    throw new FileWriterException();
                 }
-                outputStream.flush();
-            } else {
-                throw new IOException(String.format(Locale.ENGLISH, "HTTP Status code was %d", code));
+                outputStream = AbstractConnectionManager.createOutputStream(file, false, false);
+            }
+            int count;
+            final byte[] buffer = new byte[4096];
+            while ((count = inputStream.read(buffer)) != -1) {
+                transmitted += count;
+                try {
+                    outputStream.write(buffer, 0, count);
+                } catch (IOException e) {
+                    throw new FileWriterException();
+                }
+                updateProgress(Math.round(((double) transmitted / expected) * 100));
             }
+            outputStream.flush();
         }
 
         private void updateImageBounds() {
@@ -451,4 +452,11 @@ public class HttpDownloadConnection implements Transferable {
         }
 
     }
+
+    private static void throwOnInvalidCode(final Response response) throws IOException {
+        final int code = response.code();
+        if (code < 200 || code >= 300) {
+            throw new IOException(String.format(Locale.ENGLISH, "HTTP Status code was %d", code));
+        }
+    }
 }