LEFT | RIGHT |
1 package org.adblockplus.android; | 1 package org.adblockplus.android; |
2 | 2 |
3 import java.io.File; | 3 import java.io.File; |
| 4 import java.io.FileNotFoundException; |
4 import java.io.IOException; | 5 import java.io.IOException; |
5 import java.lang.reflect.Method; | 6 import java.lang.reflect.Method; |
6 import java.net.InetAddress; | 7 import java.net.InetAddress; |
7 import java.net.ServerSocket; | 8 import java.net.ServerSocket; |
8 import java.util.List; | 9 import java.util.List; |
9 import java.util.Properties; | 10 import java.util.Properties; |
10 import java.util.concurrent.TimeoutException; | 11 import java.util.concurrent.TimeoutException; |
11 | 12 |
12 import sunlabs.brazil.server.Server; | 13 import sunlabs.brazil.server.Server; |
13 import sunlabs.brazil.util.Base64; | 14 import sunlabs.brazil.util.Base64; |
(...skipping 17 matching lines...) Expand all Loading... |
31 import android.preference.PreferenceManager; | 32 import android.preference.PreferenceManager; |
32 import android.util.Log; | 33 import android.util.Log; |
33 import android.widget.Toast; | 34 import android.widget.Toast; |
34 | 35 |
35 import com.stericson.RootTools.RootTools; | 36 import com.stericson.RootTools.RootTools; |
36 import com.stericson.RootTools.RootToolsException; | 37 import com.stericson.RootTools.RootToolsException; |
37 | 38 |
38 public class ProxyService extends Service implements OnSharedPreferenceChangeLis
tener | 39 public class ProxyService extends Service implements OnSharedPreferenceChangeLis
tener |
39 { | 40 { |
40 private static final String LOCALHOST = "127.0.0.1"; | 41 private static final String LOCALHOST = "127.0.0.1"; |
| 42 /** |
| 43 * Indicates that system supports native proxy configuration. |
| 44 */ |
| 45 public static boolean hasNativeProxy = Build.VERSION.SDK_INT >= 12; // Honeyco
mb 3.1 |
41 | 46 |
42 static | 47 static |
43 { | 48 { |
44 RootTools.debugMode = false; | 49 RootTools.debugMode = false; |
45 } | 50 } |
46 | 51 |
47 private static final String TAG = "ProxyService"; | 52 private static final String TAG = "ProxyService"; |
48 private static final boolean logRequests = true; | 53 private static final boolean logRequests = false; |
49 | 54 |
50 private final static int DEFAULT_TIMEOUT = 3000; | 55 private final static int DEFAULT_TIMEOUT = 3000; |
51 private final static int NO_TRAFFIC_TIMEOUT = 5 * 60 * 1000; // 5 minutes | 56 private final static int NO_TRAFFIC_TIMEOUT = 5 * 60 * 1000; // 5 minutes |
52 | 57 |
53 final static int ONGOING_NOTIFICATION_ID = R.string.app_name; | 58 final static int ONGOING_NOTIFICATION_ID = R.string.app_name; |
54 private final static int NOTRAFFIC_NOTIFICATION_ID = R.string.app_name + 3; | 59 private final static int NOTRAFFIC_NOTIFICATION_ID = R.string.app_name + 3; |
55 | 60 |
56 /** | 61 /** |
57 * Broadcasted when service starts or stops. | 62 * Broadcasted when service starts or stops. |
58 */ | 63 */ |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
103 port = getResources().getInteger(R.integer.def_port); | 108 port = getResources().getInteger(R.integer.def_port); |
104 } | 109 } |
105 | 110 |
106 // Try to read user proxy settings | 111 // Try to read user proxy settings |
107 String proxyHost = null; | 112 String proxyHost = null; |
108 String proxyPort = null; | 113 String proxyPort = null; |
109 String proxyExcl = null; | 114 String proxyExcl = null; |
110 String proxyUser = null; | 115 String proxyUser = null; |
111 String proxyPass = null; | 116 String proxyPass = null; |
112 | 117 |
113 if (Build.VERSION.SDK_INT >= 12) // Honeycomb 3.1 | 118 if (hasNativeProxy) |
114 { | 119 { |
115 // Read system settings | 120 // Read system settings |
116 proxyHost = System.getProperty("http.proxyHost"); | 121 proxyHost = System.getProperty("http.proxyHost"); |
117 proxyPort = System.getProperty("http.proxyPort"); | 122 proxyPort = System.getProperty("http.proxyPort"); |
118 proxyExcl = System.getProperty("http.nonProxyHosts"); | 123 proxyExcl = System.getProperty("http.nonProxyHosts"); |
119 | 124 |
120 Log.d(TAG, "PRX: " + proxyHost + ":" + proxyPort + "(" + proxyExcl + ")"); | 125 Log.d(TAG, "PRX: " + proxyHost + ":" + proxyPort + "(" + proxyExcl + ")"); |
121 String[] px = ProxySettings.getUserProxy(getApplicationContext()); // not
used but left for future reference | 126 String[] px = ProxySettings.getUserProxy(getApplicationContext()); // not
used but left for future reference |
122 if (px != null) | 127 if (px != null) |
123 Log.d(TAG, "PRX: " + px[0] + ":" + px[1] + "(" + px[2] + ")"); | 128 Log.d(TAG, "PRX: " + px[0] + ":" + px[1] + "(" + px[2] + ")"); |
124 } | 129 } |
125 else | 130 else |
126 { | 131 { |
127 // Read application settings | 132 // Read application settings |
128 proxyHost = prefs.getString(getString(R.string.pref_proxyhost), null); | 133 proxyHost = prefs.getString(getString(R.string.pref_proxyhost), null); |
129 proxyPort = prefs.getString(getString(R.string.pref_proxyport), null); | 134 proxyPort = prefs.getString(getString(R.string.pref_proxyport), null); |
130 proxyUser = prefs.getString(getString(R.string.pref_proxyuser), null); | 135 proxyUser = prefs.getString(getString(R.string.pref_proxyuser), null); |
131 proxyPass = prefs.getString(getString(R.string.pref_proxypass), null); | 136 proxyPass = prefs.getString(getString(R.string.pref_proxypass), null); |
132 } | 137 } |
133 | 138 |
134 // Check for root privileges and try to install transparent proxy | 139 // Check for root privileges and try to install transparent proxy |
135 if (RootTools.isAccessGiven()) | 140 if (RootTools.isAccessGiven()) |
136 { | 141 { |
137 try | 142 try |
138 { | 143 { |
139 iptables = getIptables(); | 144 initIptables(); |
140 if (iptables != null) | 145 |
141 { | 146 StringBuffer cmd = new StringBuffer(); |
142 StringBuffer cmd = new StringBuffer(); | 147 int uid = getPackageManager().getPackageInfo(getPackageName(), 0).applic
ationInfo.uid; |
143 int uid = getPackageManager().getPackageInfo(getPackageName(), 0).appl
icationInfo.uid; | 148 cmd.append(iptables); |
144 cmd.append(iptables); | 149 cmd.append(IPTABLES_RETURN.replace("{{UID}}", String.valueOf(uid))); |
145 cmd.append(IPTABLES_RETURN.replace("{{UID}}", String.valueOf(uid))); | 150 cmd.append(iptables); |
146 cmd.append(iptables); | 151 cmd.append(IPTABLES_ADD_HTTP.replace("{{PORT}}", String.valueOf(port))); |
147 cmd.append(IPTABLES_ADD_HTTP.replace("{{PORT}}", String.valueOf(port))
); | 152 String rules = cmd.toString(); |
148 String rules = cmd.toString(); | 153 RootTools.sendShell(rules, DEFAULT_TIMEOUT); |
149 RootTools.sendShell(rules, DEFAULT_TIMEOUT); | 154 transparent = true; |
150 transparent = true; | 155 } |
151 } | 156 catch (FileNotFoundException e) |
152 else | 157 { |
153 { | 158 // ignore - this is "normal" case |
154 Log.w(TAG, "Have root access, but no iptables found"); | |
155 } | |
156 } | 159 } |
157 catch (NameNotFoundException e) | 160 catch (NameNotFoundException e) |
158 { | 161 { |
159 Log.e(TAG, "Failed to initialize iptables", e); | 162 Log.e(TAG, "Failed to initialize iptables", e); |
160 } | 163 } |
161 catch (IOException e) | 164 catch (IOException e) |
162 { | 165 { |
163 Log.e(TAG, "Failed to initialize iptables", e); | 166 Log.e(TAG, "Failed to initialize iptables", e); |
164 } | 167 } |
165 catch (RootToolsException e) | 168 catch (RootToolsException e) |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
402 } | 405 } |
403 catch (ClassCastException e) | 406 catch (ClassCastException e) |
404 { | 407 { |
405 // ignore - default handler in use | 408 // ignore - default handler in use |
406 } | 409 } |
407 } | 410 } |
408 | 411 |
409 @Override | 412 @Override |
410 public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, Str
ing key) | 413 public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, Str
ing key) |
411 { | 414 { |
412 if (Build.VERSION.SDK_INT < 12) // Honeycomb 3.1 | 415 if (hasNativeProxy) |
413 { | 416 { |
414 String ketHost = getString(R.string.pref_proxyhost); | 417 String ketHost = getString(R.string.pref_proxyhost); |
415 String keyPort = getString(R.string.pref_proxyport); | 418 String keyPort = getString(R.string.pref_proxyport); |
416 String keyUser = getString(R.string.pref_proxyuser); | 419 String keyUser = getString(R.string.pref_proxyuser); |
417 String keyPass = getString(R.string.pref_proxypass); | 420 String keyPass = getString(R.string.pref_proxypass); |
418 if (key.equals(ketHost) || key.equals(keyPort) || key.equals(keyUser) || k
ey.equals(keyPass)) | 421 if (key.equals(ketHost) || key.equals(keyPort) || key.equals(keyUser) || k
ey.equals(keyPass)) |
419 { | 422 { |
420 String proxyHost = sharedPreferences.getString(ketHost, null); | 423 String proxyHost = sharedPreferences.getString(ketHost, null); |
421 String proxyPort = sharedPreferences.getString(keyPort, null); | 424 String proxyPort = sharedPreferences.getString(keyPort, null); |
422 String proxyUser = sharedPreferences.getString(keyUser, null); | 425 String proxyUser = sharedPreferences.getString(keyUser, null); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
465 return true; | 468 return true; |
466 } | 469 } |
467 catch (Exception e) | 470 catch (Exception e) |
468 { | 471 { |
469 Log.w(TAG, null, e); | 472 Log.w(TAG, null, e); |
470 } | 473 } |
471 return false; | 474 return false; |
472 } | 475 } |
473 | 476 |
474 /** | 477 /** |
475 * Returns path to iptables executable. | 478 * Initializes iptables executable. |
476 */ | 479 * |
477 public String getIptables() throws IOException, RootToolsException, TimeoutExc
eption | 480 * @throws FileNotFoundException If iptables initialization failed due to prov
ided reasons. |
| 481 */ |
| 482 private void initIptables() throws IOException, RootToolsException, TimeoutExc
eption, FileNotFoundException |
478 { | 483 { |
479 if (!RootTools.isAccessGiven()) | 484 if (!RootTools.isAccessGiven()) |
480 return null; | 485 throw new FileNotFoundException("No root access"); |
481 | 486 |
482 File ipt = getFileStreamPath("iptables"); | 487 File ipt = getFileStreamPath("iptables"); |
483 | 488 |
484 if (!ipt.exists()) | 489 if (!ipt.exists()) |
485 { | 490 { |
486 Log.e(TAG, "No iptables excutable found"); | 491 Log.e(TAG, "No iptables excutable found"); |
487 return null; | 492 throw new FileNotFoundException("No iptables executable"); |
488 } | 493 } |
489 | 494 |
490 String path = ipt.getAbsolutePath(); | 495 String path = ipt.getAbsolutePath(); |
491 | 496 |
492 RootTools.sendShell("chmod 700 " + path, DEFAULT_TIMEOUT); | 497 RootTools.sendShell("chmod 700 " + path, DEFAULT_TIMEOUT); |
493 | 498 |
494 boolean compatible = false; | 499 boolean compatible = false; |
495 boolean version = false; | 500 boolean version = false; |
496 | 501 |
497 String command = path + " --version\n" + path + " -L -t nat -n\n"; | 502 String command = path + " --version\n" + path + " -L -t nat -n\n"; |
498 | 503 |
499 List<String> result = RootTools.sendShell(command, DEFAULT_TIMEOUT); | 504 List<String> result = RootTools.sendShell(command, DEFAULT_TIMEOUT); |
500 for (String line : result) | 505 for (String line : result) |
501 { | 506 { |
502 if (line.contains("OUTPUT")) | 507 if (line.contains("OUTPUT")) |
503 compatible = true; | 508 compatible = true; |
504 if (line.contains("v1.4.")) | 509 if (line.contains("v1.4.")) |
505 version = true; | 510 version = true; |
506 } | 511 } |
507 | 512 |
508 if (!compatible || !version) | 513 if (!compatible || !version) |
509 { | 514 { |
510 Log.e(TAG, "Incompatible iptables excutable"); | 515 Log.e(TAG, "Incompatible iptables excutable"); |
511 return null; | 516 throw new FileNotFoundException("Incompatible iptables excutable"); |
512 } | 517 } |
513 | 518 |
514 return path; | 519 iptables = path; |
515 } | 520 } |
516 | 521 |
517 public List<String> getIptablesOutput() | 522 public List<String> getIptablesOutput() |
518 { | 523 { |
519 if (iptables == null) | 524 if (iptables == null) |
520 return null; | 525 return null; |
521 | 526 |
522 String command = iptables + " -L -t nat -n\n"; | 527 String command = iptables + " -L -t nat -n\n"; |
523 try | 528 try |
524 { | 529 { |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
676 public void close() | 681 public void close() |
677 { | 682 { |
678 try | 683 try |
679 { | 684 { |
680 listen.close(); | 685 listen.close(); |
681 this.interrupt(); | 686 this.interrupt(); |
682 this.join(); | 687 this.join(); |
683 } | 688 } |
684 catch (Exception e) | 689 catch (Exception e) |
685 { | 690 { |
| 691 // ignore - it always happens |
686 } | 692 } |
687 log(LOG_WARNING, null, "server stopped"); | 693 log(LOG_WARNING, null, "server stopped"); |
688 } | 694 } |
689 | 695 |
690 @Override | 696 @Override |
691 public void log(int level, Object obj, String message) | 697 public void log(int level, Object obj, String message) |
692 { | 698 { |
693 if (level <= logLevel) | 699 if (level <= logLevel) |
694 { | 700 { |
695 Log.println(7 - level, obj != null ? obj.toString() : TAG, message); | 701 Log.println(7 - level, obj != null ? obj.toString() : TAG, message); |
696 } | 702 } |
697 } | 703 } |
698 } | 704 } |
699 } | 705 } |
LEFT | RIGHT |