| 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 |