OLD | NEW |
1 /* | 1 /* |
2 * This file is part of Adblock Plus <http://adblockplus.org/>, | 2 * This file is part of Adblock Plus <http://adblockplus.org/>, |
3 * Copyright (C) 2006-2013 Eyeo GmbH | 3 * Copyright (C) 2006-2013 Eyeo GmbH |
4 * | 4 * |
5 * Adblock Plus is free software: you can redistribute it and/or modify | 5 * Adblock Plus is free software: you can redistribute it and/or modify |
6 * it under the terms of the GNU General Public License version 3 as | 6 * it under the terms of the GNU General Public License version 3 as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
8 * | 8 * |
9 * Adblock Plus is distributed in the hope that it will be useful, | 9 * Adblock Plus is distributed in the hope that it will be useful, |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 * GNU General Public License for more details. | 12 * GNU General Public License for more details. |
13 * | 13 * |
14 * You should have received a copy of the GNU General Public License | 14 * You should have received a copy of the GNU General Public License |
15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. | 15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. |
16 */ | 16 */ |
17 | 17 |
18 package org.adblockplus.brazil; | 18 package org.adblockplus.brazil; |
19 | 19 |
20 import java.io.EOFException; | 20 import java.io.EOFException; |
21 import java.io.FilterInputStream; | 21 import java.io.FilterInputStream; |
22 import java.io.FilterOutputStream; | 22 import java.io.FilterOutputStream; |
23 import java.io.IOException; | 23 import java.io.IOException; |
24 import java.io.InterruptedIOException; | 24 import java.io.InterruptedIOException; |
25 import java.io.OutputStream; | 25 import java.io.OutputStream; |
26 import java.net.ConnectException; | 26 import java.net.ConnectException; |
27 import java.net.MalformedURLException; | 27 import java.net.MalformedURLException; |
28 import java.net.URL; | 28 import java.net.URL; |
29 import java.net.UnknownHostException; | 29 import java.net.UnknownHostException; |
| 30 import java.nio.charset.Charset; |
30 import java.util.List; | 31 import java.util.List; |
| 32 import java.util.regex.Matcher; |
31 import java.util.regex.Pattern; | 33 import java.util.regex.Pattern; |
32 import java.util.zip.GZIPInputStream; | 34 import java.util.zip.GZIPInputStream; |
33 import java.util.zip.InflaterInputStream; | 35 import java.util.zip.InflaterInputStream; |
34 | 36 |
35 import org.adblockplus.ChunkedOutputStream; | 37 import org.adblockplus.ChunkedOutputStream; |
36 import org.adblockplus.android.AdblockPlus; | 38 import org.adblockplus.android.AdblockPlus; |
37 import org.apache.commons.lang.StringUtils; | 39 import org.apache.commons.lang.StringUtils; |
38 import org.literateprograms.BoyerMoore; | 40 import org.literateprograms.BoyerMoore; |
39 | 41 |
40 import sunlabs.brazil.server.Request; | 42 import sunlabs.brazil.server.Request; |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
268 // Use chunked encoding when injecting filters in page | 270 // Use chunked encoding when injecting filters in page |
269 if (out == null) | 271 if (out == null) |
270 { | 272 { |
271 request.responseHeaders.remove("Content-Length"); | 273 request.responseHeaders.remove("Content-Length"); |
272 request.responseHeaders.remove("Content-Encoding"); | 274 request.responseHeaders.remove("Content-Encoding"); |
273 out = new ChunkedOutputStream(request.out); | 275 out = new ChunkedOutputStream(request.out); |
274 request.responseHeaders.add("Transfer-Encoding", "chunked"); | 276 request.responseHeaders.add("Transfer-Encoding", "chunked"); |
275 size = Integer.MAX_VALUE; | 277 size = Integer.MAX_VALUE; |
276 } | 278 } |
277 | 279 |
| 280 String charsetName = "utf-8"; |
| 281 final String contentType = request.responseHeaders.get("Content-Type"); |
| 282 if (contentType != null) |
| 283 { |
| 284 final Matcher matcher = Pattern.compile("charset=([^;]*)").matcher(con
tentType); |
| 285 if (matcher.matches()) |
| 286 { |
| 287 try |
| 288 { |
| 289 final String extractedCharsetName = matcher.group(0); |
| 290 Charset.forName(extractedCharsetName); |
| 291 charsetName = extractedCharsetName; |
| 292 } |
| 293 catch (IllegalArgumentException e) |
| 294 { |
| 295 Log.e(prefix, "Unsupported site charset, falling back to " + chars
etName, e); |
| 296 } |
| 297 } |
| 298 } |
| 299 |
278 request.sendHeaders(-1, null, -1); | 300 request.sendHeaders(-1, null, -1); |
279 | 301 |
280 byte[] buf = new byte[Math.min(4096, size)]; | 302 byte[] buf = new byte[Math.min(4096, size)]; |
281 | 303 |
282 boolean sent = selectors == null; | 304 boolean sent = selectors == null; |
283 // TODO Do we need to set encoding here? | |
284 BoyerMoore matcher = new BoyerMoore("<html".getBytes()); | 305 BoyerMoore matcher = new BoyerMoore("<html".getBytes()); |
285 | 306 |
286 while (size > 0) | 307 while (size > 0) |
287 { | 308 { |
288 out.flush(); | 309 out.flush(); |
289 | 310 |
290 count = in.read(buf, 0, Math.min(buf.length, size)); | 311 count = in.read(buf, 0, Math.min(buf.length, size)); |
291 if (count < 0) | 312 if (count < 0) |
292 { | 313 { |
293 break; | 314 break; |
294 } | 315 } |
295 size -= count; | 316 size -= count; |
296 try | 317 try |
297 { | 318 { |
298 // Search for <html> tag | 319 // Search for <html> tag |
299 if (!sent && count > 0) | 320 if (!sent && count > 0) |
300 { | 321 { |
301 List<Integer> matches = matcher.match(buf, 0, count); | 322 List<Integer> matches = matcher.match(buf, 0, count); |
302 if (!matches.isEmpty()) | 323 if (!matches.isEmpty()) |
303 { | 324 { |
304 // Add filters right before match | 325 // Add filters right before match |
305 int m = matches.get(0); | 326 int m = matches.get(0); |
306 out.write(buf, 0, m); | 327 out.write(buf, 0, m); |
307 out.write("<style type=\"text/css\">\n".getBytes()); | 328 out.write("<style type=\"text/css\">\n".getBytes()); |
308 // TODO Do we need to set encoding here? | 329 out.write(StringUtils.join(selectors, ",\r\n").getBytes(charsetN
ame)); |
309 out.write(StringUtils.join(selectors, ",\r\n").getBytes()); | |
310 out.write("{ display: none !important }</style>\n".getBytes()); | 330 out.write("{ display: none !important }</style>\n".getBytes()); |
311 out.write(buf, m, count - m); | 331 out.write(buf, m, count - m); |
312 sent = true; | 332 sent = true; |
313 continue; | 333 continue; |
314 } | 334 } |
315 } | 335 } |
316 out.write(buf, 0, count); | 336 out.write(buf, 0, count); |
317 } | 337 } |
318 catch (IOException e) | 338 catch (IOException e) |
319 { | 339 { |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
364 request.sendError(500, msg); | 384 request.sendError(500, msg); |
365 Log.e(prefix, msg, e); | 385 Log.e(prefix, msg, e); |
366 } | 386 } |
367 finally | 387 finally |
368 { | 388 { |
369 target.close(); | 389 target.close(); |
370 } | 390 } |
371 return true; | 391 return true; |
372 } | 392 } |
373 } | 393 } |
OLD | NEW |