Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

public class ParcelFileDescriptorUtil {

private static final int BUFFER_SIZE = 1024;

private ParcelFileDescriptorUtil() { }

public static ParcelFileDescriptor pipeFrom(InputStream inputStream, IThreadListener listener)
Expand Down Expand Up @@ -61,7 +63,7 @@ static class TransferThread extends Thread {

@Override
public void run() {
byte[] buf = new byte[1024];
byte[] buf = new byte[BUFFER_SIZE];
int len;

try {
Expand Down
59 changes: 44 additions & 15 deletions lib/src/main/java/com/nextcloud/android/sso/api/NextcloudAPI.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import com.nextcloud.android.sso.exceptions.SSOException;
import com.nextcloud.android.sso.model.SingleSignOnAccount;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
Expand All @@ -37,8 +38,8 @@

public class NextcloudAPI implements AutoCloseable {

private static final int PEEK_LIMIT = 64;
private static final String TAG = NextcloudAPI.class.getCanonicalName();

private static final EmptyResponse EMPTY_RESPONSE = new EmptyResponse();

private final NetworkRequest networkRequest;
Expand Down Expand Up @@ -127,27 +128,55 @@ public <T> T convertStreamToTargetEntity(InputStream inputStream, Type targetEnt
ensureTypeNotVoid(targetEntity);

final T result;
try (InputStream os = inputStream;
Reader targetReader = new InputStreamReader(os)) {
if (targetEntity == EmptyResponse.class) {

try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
reader.mark(PEEK_LIMIT);
boolean empty = isReaderContainsEmptyResponse(reader);
reader.reset();

if (targetEntity == EmptyResponse.class || empty) {
//noinspection unchecked
result = (T) EMPTY_RESPONSE;
} else {
result = gson.fromJson(targetReader, targetEntity);
if (result == null) {
if (targetEntity == Object.class) {
//noinspection unchecked
return (T) EMPTY_RESPONSE;
} else {
throw new IllegalStateException("Could not instantiate \"" +
targetEntity + "\", because response was null.");
}
return (T) EMPTY_RESPONSE;
}

result = gson.fromJson(reader, targetEntity);

if (result == null) {
if (targetEntity == Object.class) {
//noinspection unchecked
return (T) EMPTY_RESPONSE;
} else {
throw new IllegalStateException("Could not instantiate \"" +
targetEntity + "\", because response was null.");
}
}
}

return result;
}

public boolean isReaderContainsEmptyResponse(Reader reader) throws IOException {
reader.mark(PEEK_LIMIT);
try {
int c;
int count = 0;
while ((c = reader.read()) != -1 && count < PEEK_LIMIT) {
if (c != '\u0000' && !Character.isWhitespace(c)) {
// Found meaningful character
return false;
}
count++;
}
return true;
} finally {
try {
reader.reset();
} catch (Exception e) {
// Ignored
}
}
}

/**
* The InputStreams needs to be closed after reading from it
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@
*/
package com.nextcloud.android.sso.api;

import static junit.framework.TestCase.assertTrue;
import static junit.framework.TestCase.fail;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
Expand All @@ -34,6 +35,8 @@
import org.mockito.junit.MockitoRule;

import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
Expand Down Expand Up @@ -75,6 +78,8 @@ public void setUp() throws Exception {
lenient().when(nextcloudApiMock.getGson()).thenReturn(new GsonBuilder().create());
lenient().when(nextcloudApiMock.performRequestObservableV2(any(), any())).thenReturn(Observable.empty());
lenient().when(nextcloudApiMock.performNetworkRequestV2(any())).thenReturn(new com.nextcloud.android.sso.api.Response(null, null));
lenient().when(nextcloudApiMock.isReaderContainsEmptyResponse(any()))
.thenCallRealMethod();
mApi = new NextcloudRetrofitApiBuilder(nextcloudApiMock, mApiEndpoint).create(API.class);
}

Expand Down Expand Up @@ -538,4 +543,31 @@ public void testEnqueue() throws InterruptedException {
assertTrue(successful);
}

@Test
public void testValidJson() throws IOException {
String json = "{\"name\": \"value\", \"type\": \"value_2\"}";
Reader reader = new StringReader(json);
assertFalse(nextcloudApiMock.isReaderContainsEmptyResponse(reader));
}

@Test
public void testValidXml() throws IOException {
String xml = "<note><to>User</to><from>User2</from></note>";
Reader reader = new StringReader(xml);
assertFalse(nextcloudApiMock.isReaderContainsEmptyResponse(reader));
}

@Test
public void testOnlyNulls() throws IOException {
String nulls = "\u0000\u0000\u0000\u0000\u0000 \n\t"; // nulls + whitespace
Reader reader = new StringReader(nulls);
assertTrue(nextcloudApiMock.isReaderContainsEmptyResponse(reader));
}

@Test
public void testWhitespaceOnly() throws IOException {
String whitespace = " \n\t ";
Reader reader = new StringReader(whitespace);
assertTrue(nextcloudApiMock.isReaderContainsEmptyResponse(reader));
}
}