Skip to content

Commit 602ce10

Browse files
committed
Merge pull request #118 from longbai/avoid_dns_hijacking
dns hijacking
2 parents 7b5504a + 03e3334 commit 602ce10

File tree

15 files changed

+310
-84
lines changed

15 files changed

+310
-84
lines changed

library/src/androidTest/java/com/qiniu/android/FormUploadTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ public void complete(String k, ResponseInfo rinfo, JSONObject response) {
133133
e.printStackTrace();
134134
}
135135
Assert.assertEquals(expectKey, key);
136-
Assert.assertEquals(401, info.statusCode);
136+
Assert.assertEquals(ResponseInfo.InvalidToken, info.statusCode);
137137
Assert.assertNotNull(info.reqId);
138138
Assert.assertNull(resp);
139139
}

library/src/androidTest/java/com/qiniu/android/HttpTest.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public void complete(ResponseInfo rinfo, JSONObject response) {
4141
info = rinfo;
4242
signal.countDown();
4343
}
44-
}, null);
44+
}, null, false);
4545

4646
try {
4747
signal.await(60, TimeUnit.SECONDS); // wait for callback
@@ -61,7 +61,7 @@ public void complete(ResponseInfo rinfo, JSONObject response) {
6161
info = rinfo;
6262
signal.countDown();
6363
}
64-
}, null);
64+
}, null, false);
6565

6666
try {
6767
signal.await(60, TimeUnit.SECONDS); // wait for callback
@@ -82,7 +82,7 @@ public void complete(ResponseInfo rinfo, JSONObject response) {
8282
info = rinfo;
8383
signal.countDown();
8484
}
85-
}, null);
85+
}, null, false);
8686
}
8787
});
8888

@@ -106,7 +106,7 @@ public void complete(ResponseInfo rinfo, JSONObject response) {
106106
info = rinfo;
107107
signal.countDown();
108108
}
109-
}, null);
109+
}, null, false);
110110
}
111111
});
112112

@@ -129,7 +129,7 @@ public void complete(ResponseInfo rinfo, JSONObject response) {
129129
info = rinfo;
130130
signal.countDown();
131131
}
132-
}, null);
132+
}, null, false);
133133

134134
try {
135135
signal.await(60, TimeUnit.SECONDS); // wait for callback
@@ -150,7 +150,7 @@ public void complete(ResponseInfo rinfo, JSONObject response) {
150150
info = rinfo;
151151
signal.countDown();
152152
}
153-
}, null);
153+
}, null, false);
154154

155155
try {
156156
signal.await(60, TimeUnit.SECONDS); // wait for callback
@@ -171,7 +171,7 @@ public void complete(ResponseInfo rinfo, JSONObject response) {
171171
info = rinfo;
172172
signal.countDown();
173173
}
174-
}, null);
174+
}, null, false);
175175

176176
try {
177177
signal.await(60, TimeUnit.SECONDS); // wait for callback

library/src/androidTest/java/com/qiniu/android/PortTest.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
import android.test.suitebuilder.annotation.SmallTest;
66
import android.util.Log;
77

8-
import com.qiniu.android.http.CompletionHandler;
9-
import com.qiniu.android.http.HttpManager;
108
import com.qiniu.android.http.ResponseInfo;
119
import com.qiniu.android.storage.Configuration;
1210
import com.qiniu.android.storage.UpCompletionHandler;
@@ -15,8 +13,6 @@
1513

1614
import junit.framework.Assert;
1715

18-
import org.apache.http.Header;
19-
import org.apache.http.message.BasicHeader;
2016
import org.json.JSONObject;
2117

2218
import java.io.File;
@@ -96,7 +92,7 @@ public void complete(String k, ResponseInfo rinfo, JSONObject response) {
9692
check(expectKey);
9793
}
9894

99-
private void check( final String expectKey){
95+
private void check(final String expectKey) {
10096
try {
10197
signal.await(120, TimeUnit.SECONDS); // wait for callback
10298
} catch (InterruptedException e) {

library/src/androidTest/java/com/qiniu/android/TestFileRecorder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ public void complete(String k, ResponseInfo rinfo, JSONObject response) {
8080
});
8181

8282
try {
83-
signal.await(500, TimeUnit.SECONDS); // wait for callback
83+
signal.await(600, TimeUnit.SECONDS); // wait for callback
8484
} catch (InterruptedException e) {
8585
e.printStackTrace();
8686
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.qiniu.android;
2+
3+
import android.test.AndroidTestCase;
4+
5+
import com.qiniu.android.storage.UpToken;
6+
7+
import junit.framework.Assert;
8+
9+
/**
10+
* Created by bailong on 15/6/1.
11+
*/
12+
public class TokenTest extends AndroidTestCase {
13+
public void testRight() {
14+
UpToken t = UpToken.parse(TestConfig.token);
15+
Assert.assertNotNull(t);
16+
}
17+
}

library/src/main/java/com/qiniu/android/http/HttpManager.java

Lines changed: 25 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import com.loopj.android.http.AsyncHttpClient;
44
import com.loopj.android.http.AsyncHttpResponseHandler;
55
import com.qiniu.android.common.Constants;
6+
import com.qiniu.android.utils.Dns;
67

78
import org.apache.http.Header;
89
import org.apache.http.HttpEntity;
@@ -15,6 +16,8 @@
1516
import java.net.URISyntaxException;
1617
import java.util.Map;
1718
import java.util.Random;
19+
import java.util.concurrent.ExecutorService;
20+
import java.util.concurrent.ThreadPoolExecutor;
1821

1922
import static java.lang.String.format;
2023

@@ -41,9 +44,10 @@ public HttpManager(Proxy proxy, IReport reporter, String backUpIp,
4144
this.backUpIp = backUpIp;
4245
client = new AsyncHttpClient();
4346
client.setConnectTimeout(connectTimeout*1000);
44-
client.setResponseTimeout(responseTimeout*1000);
47+
client.setResponseTimeout(responseTimeout * 1000);
4548
client.setUserAgent(userAgent);
46-
client.setEnableRedirects(false);
49+
client.setEnableRedirects(true);
50+
client.setRedirectHandler(new UpRedirectHandler());
4751
AsyncHttpClient.blockRetryExceptionClass(CancellationHandler.CancellationException.class);
4852
if (proxy != null) {
4953
client.setProxy(proxy.hostAddress, proxy.port, proxy.user, proxy.password);
@@ -97,18 +101,18 @@ private static String getUserAgent() {
97101
* @param completionHandler 发送数据完成后续动作处理对象
98102
*/
99103
public void postData(String url, byte[] data, int offset, int size, Header[] headers,
100-
ProgressHandler progressHandler, final CompletionHandler completionHandler, CancellationHandler c) {
104+
ProgressHandler progressHandler, final CompletionHandler completionHandler, CancellationHandler c, boolean forceIp) {
101105
ByteArrayEntity entity = new ByteArrayEntity(data, offset, size, progressHandler, c);
102-
postEntity(url, entity, headers, progressHandler, completionHandler);
106+
postEntity(url, entity, headers, progressHandler, completionHandler, forceIp);
103107
}
104108

105109
public void postData(String url, byte[] data, Header[] headers, ProgressHandler progressHandler,
106-
CompletionHandler completionHandler, CancellationHandler c) {
107-
postData(url, data, 0, data.length, headers, progressHandler, completionHandler, c);
110+
CompletionHandler completionHandler, CancellationHandler c, boolean forceIp) {
111+
postData(url, data, 0, data.length, headers, progressHandler, completionHandler, c, forceIp);
108112
}
109113

110114
private void postEntity(String url, final HttpEntity entity, Header[] headers,
111-
ProgressHandler progressHandler, CompletionHandler completionHandler) {
115+
ProgressHandler progressHandler, CompletionHandler completionHandler, final boolean forceIp) {
112116
final CompletionHandler wrapper = wrap(completionHandler);
113117
final Header[] h = reporter.appendStatHeaders(headers);
114118

@@ -117,32 +121,35 @@ private void postEntity(String url, final HttpEntity entity, Header[] headers,
117121
}
118122

119123
final AsyncHttpResponseHandler originHandler = new ResponseHandler(url, wrapper, progressHandler);
120-
if(backUpIp == null){
124+
if(backUpIp == null || converter != null){
121125
client.post(null, url, h, entity, null, originHandler);
122126
return;
123127
}
124128
final String url2 = url;
125-
client.post(null, url, h, entity, null, new ResponseHandler(url, new CompletionHandler() {
129+
130+
ExecutorService t = client.getThreadPool();
131+
t.execute(new Runnable() {
126132
@Override
127-
public void complete(ResponseInfo info, JSONObject response) {
128-
if (info.statusCode != ResponseInfo.UnknownHost){
129-
wrapper.complete(info, response);
130-
return;
133+
public void run() {
134+
URI uri = URI.create(url2);
135+
String ip = Dns.getAddress(uri.getHost());
136+
if (ip == null || ip.equals("") || forceIp) {
137+
ip = backUpIp;
131138
}
139+
132140
Header[] h2 = new Header[h.length + 1];
133141
System.arraycopy(h, 0, h2, 0, h.length);
134142

135-
URI uri = URI.create(url2);
136143
String newUrl = null;
137144
try {
138-
newUrl = new URI(uri.getScheme(), null, backUpIp, uri.getPort(), uri.getPath(), uri.getQuery(), null).toString();
145+
newUrl = new URI(uri.getScheme(), null, ip, uri.getPort(), uri.getPath(), uri.getQuery(), null).toString();
139146
} catch (URISyntaxException e) {
140147
throw new AssertionError(e);
141148
}
142149
h2[h.length] = new BasicHeader("Host", uri.getHost());
143150
client.post(null, newUrl, h2, entity, null, originHandler);
144151
}
145-
}, progressHandler));
152+
});
146153
}
147154

148155
/**
@@ -154,7 +161,7 @@ public void complete(ResponseInfo info, JSONObject response) {
154161
* @param completionHandler 发送数据完成后续动作处理对象
155162
*/
156163
public void multipartPost(String url, PostArgs args, ProgressHandler progressHandler,
157-
final CompletionHandler completionHandler, CancellationHandler c) {
164+
final CompletionHandler completionHandler, CancellationHandler c, boolean forceIp) {
158165
MultipartBuilder mbuilder = new MultipartBuilder();
159166
for (Map.Entry<String, String> entry : args.params.entrySet()) {
160167
mbuilder.addPart(entry.getKey(), entry.getValue());
@@ -178,7 +185,7 @@ public void multipartPost(String url, PostArgs args, ProgressHandler progressHan
178185

179186
ByteArrayEntity entity = mbuilder.build(progressHandler, c);
180187
Header[] h = reporter.appendStatHeaders(new Header[0]);
181-
postEntity(url, entity, h, progressHandler, completionHandler);
188+
postEntity(url, entity, h, progressHandler, completionHandler, forceIp);
182189
}
183190

184191
private CompletionHandler wrap(final CompletionHandler completionHandler) {
@@ -194,40 +201,4 @@ public void complete(ResponseInfo info, JSONObject response) {
194201
}
195202
};
196203
}
197-
198-
/**
199-
* fixed key escape for async http client
200-
* Appends a quoted-string to a StringBuilder.
201-
* <p/>
202-
* <p>RFC 2388 is rather vague about how one should escape special characters
203-
* in form-data parameters, and as it turns out Firefox and Chrome actually
204-
* do rather different things, and both say in their comments that they're
205-
* not really sure what the right approach is. We go with Chrome's behavior
206-
* (which also experimentally seems to match what IE does), but if you
207-
* actually want to have a good chance of things working, please avoid
208-
* double-quotes, newlines, percent signs, and the like in your field names.
209-
*/
210-
private static String escapeMultipartString(String key) {
211-
StringBuilder target = new StringBuilder();
212-
213-
for (int i = 0, len = key.length(); i < len; i++) {
214-
char ch = key.charAt(i);
215-
switch (ch) {
216-
case '\n':
217-
target.append("%0A");
218-
break;
219-
case '\r':
220-
target.append("%0D");
221-
break;
222-
case '"':
223-
target.append("%22");
224-
break;
225-
default:
226-
target.append(ch);
227-
break;
228-
}
229-
}
230-
return target.toString();
231-
}
232-
233204
}

library/src/main/java/com/qiniu/android/http/Proxy.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
/**
44
* http 代理
55
*/
6-
public class Proxy {
6+
public final class Proxy {
77

88
public final String hostAddress;
99
public final int port;

library/src/main/java/com/qiniu/android/http/ResponseInfo.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
* 定义HTTP请求的日志信息和常规方法
88
*/
99
public final class ResponseInfo {
10+
public static final int InvalidToken = -5;
1011
public static final int InvalidArgument = -4;
1112
public static final int InvalidFile = -3;
1213
public static final int Cancelled = -2;
@@ -78,6 +79,10 @@ public static ResponseInfo invalidArgument(String message) {
7879
message);
7980
}
8081

82+
public static ResponseInfo invalidToken(String message) {
83+
return new ResponseInfo(InvalidToken, "", "", "", "", "", -1, 0,
84+
message);
85+
}
8186

8287
public static ResponseInfo fileError(Exception e) {
8388
return new ResponseInfo(InvalidFile, "", "", "", "", "", -1,
@@ -112,6 +117,9 @@ public boolean needRetry() {
112117
|| (statusCode == 200 && error != null));
113118
}
114119

120+
public boolean isQiniu() {
121+
return statusCode < 500 && statusCode >= 200 && reqId == null;
122+
}
115123

116124
public String toString() {
117125
return String.format(Locale.ENGLISH, "{ResponseInfo:%s,status:%d, reqId:%s, xlog:%s, xvia:%s, host:%s, ip:%s, port:%d, duration:%f s, error:%s}",

library/src/main/java/com/qiniu/android/http/StatReport.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
/**
77
* Report the client status to Server.
88
*/
9-
public class StatReport implements IReport{
9+
public final class StatReport implements IReport{
1010
private ResponseInfo previousErrorInfo = null;
1111
private ResponseInfo previousSpeedInfo = null;
1212

0 commit comments

Comments
 (0)