1
0
mirror of https://github.com/TeamNewPipe/NewPipe synced 2024-11-17 15:24:55 +00:00

Merge pull request #136 from eighthave/tor-support-for-all-except-streaming

Tor support for all except streaming
This commit is contained in:
Christian Schabesberger 2016-01-03 17:40:02 +01:00
commit 0da1aef763
11 changed files with 250 additions and 15 deletions

View File

@ -35,4 +35,5 @@ dependencies {
compile 'com.android.support:recyclerview-v7:23.1.1' compile 'com.android.support:recyclerview-v7:23.1.1'
compile 'org.jsoup:jsoup:1.8.3' compile 'org.jsoup:jsoup:1.8.3'
compile 'org.mozilla:rhino:1.7.7' compile 'org.mozilla:rhino:1.7.7'
compile 'info.guardianproject.netcipher:netcipher:1.2'
} }

View File

@ -7,6 +7,7 @@
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application <application
android:name=".App"
android:allowBackup="true" android:allowBackup="true"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:logo="@mipmap/ic_launcher" android:logo="@mipmap/ic_launcher"

View File

@ -0,0 +1,46 @@
package org.schabi.newpipe;
import android.app.Application;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import info.guardianproject.netcipher.NetCipher;
import info.guardianproject.netcipher.proxy.OrbotHelper;
public class App extends Application {
private static boolean useTor;
@Override
public void onCreate() {
super.onCreate();
// if Orbot is installed, then default to using Tor, the user can still override
if (OrbotHelper.requestStartTor(this)) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
configureTor(prefs.getBoolean(getString(R.string.useTor), true));
}
}
/**
* Set the proxy settings based on whether Tor should be enabled or not.
*/
static void configureTor(boolean enabled) {
useTor = enabled;
if (useTor) {
NetCipher.useTor();
} else {
NetCipher.setProxy(null);
}
}
static void checkStartTor(Context context) {
if (useTor) {
OrbotHelper.requestStartTor(context);
}
}
static boolean isUsingTor() {
return useTor;
}
}

View File

@ -61,17 +61,17 @@ public class DownloadDialog extends DialogFragment {
String suffix = ""; String suffix = "";
String title = arguments.getString(TITLE); String title = arguments.getString(TITLE);
String url = ""; String url = "";
String downloadFolder = "Download"; String downloadFolder = Environment.DIRECTORY_DOWNLOADS;
switch(which) { switch(which) {
case 0: // Video case 0: // Video
suffix = arguments.getString(FILE_SUFFIX_VIDEO); suffix = arguments.getString(FILE_SUFFIX_VIDEO);
url = arguments.getString(VIDEO_URL); url = arguments.getString(VIDEO_URL);
downloadFolder = "Movies"; downloadFolder = Environment.DIRECTORY_MOVIES;
break; break;
case 1: case 1:
suffix = arguments.getString(FILE_SUFFIX_AUDIO); suffix = arguments.getString(FILE_SUFFIX_AUDIO);
url = arguments.getString(AUDIO_URL); url = arguments.getString(AUDIO_URL);
downloadFolder = "Music"; downloadFolder = Environment.DIRECTORY_MUSIC;
break; break;
default: default:
Log.d(TAG, "lolz"); Log.d(TAG, "lolz");
@ -87,15 +87,21 @@ public class DownloadDialog extends DialogFragment {
//TODO notify user "download directory should be changed" ? //TODO notify user "download directory should be changed" ?
} }
} }
DownloadManager dm = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); String saveFilePath = dir + "/" + title + suffix;
DownloadManager.Request request = new DownloadManager.Request( if (App.isUsingTor()) {
Uri.parse(url)); // if using Tor, do not use DownloadManager because the proxy cannot be set
request.setDestinationUri(Uri.fromFile(new File(dir + "/" + title + suffix))); Downloader.downloadFile(getContext(), url, saveFilePath);
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); } else {
try { DownloadManager dm = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
dm.enqueue(request); DownloadManager.Request request = new DownloadManager.Request(
} catch (Exception e) { Uri.parse(url));
e.printStackTrace(); request.setDestinationUri(Uri.fromFile(new File(saveFilePath)));
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
try {
dm.enqueue(request);
} catch (Exception e) {
e.printStackTrace();
}
} }
} }
}); });

View File

@ -1,12 +1,30 @@
package org.schabi.newpipe; package org.schabi.newpipe;
import android.app.Notification;
import android.app.NotificationManager;
import android.content.Context;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import java.io.BufferedInputStream;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import javax.net.ssl.HttpsURLConnection;
import info.guardianproject.netcipher.NetCipher;
/** /**
* Created by Christian Schabesberger on 14.08.15. * Created by Christian Schabesberger on 14.08.15.
* *
@ -28,6 +46,7 @@ import java.net.UnknownHostException;
*/ */
public class Downloader { public class Downloader {
public static final String TAG = "Downloader";
private static final String USER_AGENT = "Mozilla/5.0"; private static final String USER_AGENT = "Mozilla/5.0";
@ -40,7 +59,7 @@ public class Downloader {
String ret = ""; String ret = "";
try { try {
URL url = new URL(siteUrl); URL url = new URL(siteUrl);
HttpURLConnection con = (HttpURLConnection) url.openConnection(); HttpsURLConnection con = NetCipher.getHttpsURLConnection(url);
con.setRequestProperty("Accept-Language", language); con.setRequestProperty("Accept-Language", language);
ret = dl(con); ret = dl(con);
} }
@ -84,7 +103,7 @@ public class Downloader {
try { try {
URL url = new URL(siteUrl); URL url = new URL(siteUrl);
HttpURLConnection con = (HttpURLConnection) url.openConnection(); HttpsURLConnection con = NetCipher.getHttpsURLConnection(url);
ret = dl(con); ret = dl(con);
} }
catch(Exception e) { catch(Exception e) {
@ -93,4 +112,92 @@ public class Downloader {
return ret; return ret;
} }
/**
* Downloads a file from a URL in the background using an {@link AsyncTask}.
*
* @param fileURL HTTP URL of the file to be downloaded
* @param saveFilePath path of the directory to save the file
* @throws IOException
*/
public static void downloadFile(final Context context, final String fileURL, final String saveFilePath) {
new AsyncTask<Void, Integer, Void>() {
private NotificationManager nm;
private NotificationCompat.Builder builder;
private int notifyId = 0x1234;
private int fileSize = 0xffffffff;
@Override
protected void onPreExecute() {
super.onPreExecute();
nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
Drawable icon = context.getResources().getDrawable(R.mipmap.ic_launcher);
builder = new NotificationCompat.Builder(context)
.setSmallIcon(android.R.drawable.stat_sys_download)
.setLargeIcon(((BitmapDrawable) icon).getBitmap())
.setContentTitle(saveFilePath.substring(saveFilePath.lastIndexOf('/') + 1))
.setContentText(saveFilePath)
.setProgress(fileSize, 0, false);
nm.notify(notifyId, builder.build());
}
@Override
protected Void doInBackground(Void... voids) {
HttpsURLConnection con = null;
try {
con = NetCipher.getHttpsURLConnection(fileURL);
int responseCode = con.getResponseCode();
// always check HTTP response code first
if (responseCode == HttpURLConnection.HTTP_OK) {
fileSize = con.getContentLength();
InputStream inputStream = new BufferedInputStream(con.getInputStream());
FileOutputStream outputStream = new FileOutputStream(saveFilePath);
int bufferSize = 8192;
int downloaded = 0;
int bytesRead = -1;
byte[] buffer = new byte[bufferSize];
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
downloaded += bytesRead;
if (downloaded % 50000 < bufferSize) {
publishProgress(downloaded);
}
}
outputStream.close();
inputStream.close();
publishProgress(bufferSize);
} else {
Log.i(TAG, "No file to download. Server replied HTTP code: " + responseCode);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (con != null) {
con.disconnect();
con = null;
}
}
return null;
}
@Override
protected void onProgressUpdate(Integer... progress) {
builder.setProgress(fileSize, progress[0], false);
nm.notify(notifyId, builder.build());
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
nm.cancel(notifyId);
}
}.execute();
}
} }

View File

@ -187,6 +187,18 @@ public class PlayVideoActivity extends AppCompatActivity {
videoView.pause(); videoView.pause();
} }
@Override
public void onResume() {
super.onResume();
App.checkStartTor(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
prefs = getPreferences(Context.MODE_PRIVATE);
}
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId(); int id = item.getItemId();

View File

@ -1,7 +1,12 @@
package org.schabi.newpipe; package org.schabi.newpipe;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.os.Bundle; import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity; import android.preference.PreferenceActivity;
import android.preference.PreferenceFragment; import android.preference.PreferenceFragment;
import android.support.annotation.LayoutRes; import android.support.annotation.LayoutRes;
@ -13,6 +18,8 @@ import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import info.guardianproject.netcipher.proxy.OrbotHelper;
/** /**
* Created by Christian Schabesberger on 31.08.15. * Created by Christian Schabesberger on 31.08.15.
* *
@ -35,6 +42,7 @@ import android.view.ViewGroup;
public class SettingsActivity extends PreferenceActivity { public class SettingsActivity extends PreferenceActivity {
private static final int REQUEST_INSTALL_ORBOT = 0x1234;
private AppCompatDelegate mDelegate = null; private AppCompatDelegate mDelegate = null;
@Override @Override
@ -52,13 +60,48 @@ public class SettingsActivity extends PreferenceActivity {
} }
public static class SettingsFragment extends PreferenceFragment { public static class SettingsFragment extends PreferenceFragment {
private CheckBoxPreference useTorCheckBox;
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.settings_screen); addPreferencesFromResource(R.xml.settings_screen);
// if Orbot is installed, then default to using Tor, the user can still override
useTorCheckBox = (CheckBoxPreference) findPreference(getString(R.string.useTor));
final Activity activity = getActivity();
final boolean useTor = OrbotHelper.isOrbotInstalled(activity);
useTorCheckBox.setDefaultValue(useTor);
useTorCheckBox.setChecked(useTor);
useTorCheckBox.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object o) {
boolean useTor = (Boolean) o;
if (useTor) {
if (OrbotHelper.isOrbotInstalled(activity)) {
App.configureTor(true);
} else {
Intent intent = OrbotHelper.getOrbotInstallIntent(activity);
activity.startActivityForResult(intent, REQUEST_INSTALL_ORBOT);
}
} else {
App.configureTor(false);
}
return true;
}
});
} }
} }
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// try to start tor regardless of resultCode since clicking back after
// installing the app does not necessarily return RESULT_OK
App.configureTor(requestCode == REQUEST_INSTALL_ORBOT
&& OrbotHelper.requestStartTor(this));
}
@Override @Override
protected void onPostCreate(Bundle savedInstanceState) { protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState); super.onPostCreate(savedInstanceState);

View File

@ -113,6 +113,12 @@ public class VideoItemDetailActivity extends AppCompatActivity {
.commit(); .commit();
} }
@Override
public void onResume() {
super.onResume();
App.checkStartTor(this);
}
@Override @Override
public void onSaveInstanceState(Bundle outState) { public void onSaveInstanceState(Bundle outState) {
outState.putString(VideoItemDetailFragment.VIDEO_URL, videoUrl); outState.putString(VideoItemDetailFragment.VIDEO_URL, videoUrl);

View File

@ -175,6 +175,12 @@ public class VideoItemListActivity extends AppCompatActivity
PreferenceManager.setDefaultValues(this, R.xml.settings_screen, false); PreferenceManager.setDefaultValues(this, R.xml.settings_screen, false);
} }
@Override
public void onResume() {
super.onResume();
App.checkStartTor(this);
}
/** /**
* Callback method from {@link VideoItemListFragment.Callbacks} * Callback method from {@link VideoItemListFragment.Callbacks}
* indicating that the item with the given ID was selected. * indicating that the item with the given ID was selected.

View File

@ -63,4 +63,6 @@
<string name="detailUploaderThumbnailViewDescription">Uploader thumbnail</string> <string name="detailUploaderThumbnailViewDescription">Uploader thumbnail</string>
<string name="detailThumbsDownImgViewDescription">Dislikes</string> <string name="detailThumbsDownImgViewDescription">Dislikes</string>
<string name="detailThumbsUpImgViewDescription">Likes</string> <string name="detailThumbsUpImgViewDescription">Likes</string>
<string name="useTor">Use Tor</string>
<string name="useTorSummary">Force download traffic through Tor for increased privacy (streaming videos not yet supported)</string>
</resources> </resources>

View File

@ -72,5 +72,10 @@
android:summary="@string/autoPlayThroughIntentSummary" android:summary="@string/autoPlayThroughIntentSummary"
android:defaultValue="false" /> android:defaultValue="false" />
<CheckBoxPreference
android:key="@string/useTor"
android:title="@string/useTor"
android:summary="@string/useTorSummary" />
</PreferenceCategory> </PreferenceCategory>
</PreferenceScreen> </PreferenceScreen>