Browse Source

Finalized adding of torrents via http, file or magnet; also multiple http links at once via ADD_MULTIPLE.

pull/11/head
Eric Kok 12 years ago
parent
commit
3593ead589
  1. 2
      android/src/com/xirvik/transdroid/preferences/PreferencesXirvikServer.java
  2. 2
      android/src/org/transdroid/preferences/ImportExport.java
  3. 2
      android/src/org/transdroid/search/barcode/GoogleWebSearchBarcodeResolver.java
  4. 2
      android/src/org/transdroid/service/UpdateService.java
  5. 4
      core/res/layout-w900dp/activity_rssfeeds.xml
  6. 2
      core/res/layout/activity_rssitems.xml
  7. 5
      core/res/layout/fragment_rssitems.xml
  8. 6
      core/res/layout/list_item_rssitem.xml
  9. 6
      core/res/menu/fragment_rssfeeds.xml
  10. 5
      core/res/values/strings.xml
  11. 6
      core/res/xml/pref_websearch.xml
  12. 2
      core/src/org/transdroid/core/app/search/GoogleWebSearchBarcodeResolver.java
  13. 50
      core/src/org/transdroid/core/app/settings/ApplicationSettings.java
  14. 2
      core/src/org/transdroid/core/app/settings/SettingsPersistence.java
  15. 8
      core/src/org/transdroid/core/app/settings/WebsearchSetting.java
  16. 140
      core/src/org/transdroid/core/gui/TorrentsActivity.java
  17. 2
      core/src/org/transdroid/core/gui/rss/RssfeedLoader.java
  18. 3
      core/src/org/transdroid/core/gui/rss/RssfeedView.java
  19. 77
      core/src/org/transdroid/core/gui/rss/RssfeedsActivity.java
  20. 7
      core/src/org/transdroid/core/gui/rss/RssfeedsFragment.java
  21. 5
      core/src/org/transdroid/core/gui/rss/RssitemView.java
  22. 4
      core/src/org/transdroid/core/gui/rss/RssitemsActivity.java
  23. 49
      core/src/org/transdroid/core/gui/rss/RssitemsFragment.java
  24. 1
      core/src/org/transdroid/core/gui/settings/WebsearchSettingsActivity.java
  25. 1
      core/src/org/transdroid/core/rssparser/Channel.java
  26. 6
      core/src/org/transdroid/core/rssparser/HttpHelper.java
  27. 3
      core/src/org/transdroid/core/rssparser/Item.java
  28. 112
      full/AndroidManifest.xml
  29. 10
      lib/src/org/transdroid/daemon/BitComet/BitCometAdapter.java
  30. 2
      lib/src/org/transdroid/daemon/Bitflu/BitfluAdapter.java
  31. 2
      lib/src/org/transdroid/daemon/BuffaloNas/BuffaloNasAdapter.java
  32. 2
      lib/src/org/transdroid/daemon/DLinkRouterBT/DLinkRouterBTAdapter.java
  33. 6
      lib/src/org/transdroid/daemon/Deluge/DelugeAdapter.java
  34. 6
      lib/src/org/transdroid/daemon/Ktorrent/KtorrentAdapter.java
  35. 2
      lib/src/org/transdroid/daemon/Qbittorrent/QbittorrentAdapter.java
  36. 2
      lib/src/org/transdroid/daemon/Synology/SynologyAdapter.java
  37. 4
      lib/src/org/transdroid/daemon/Tfb4rt/Tfb4rtAdapter.java
  38. 12
      lib/src/org/transdroid/daemon/Transmission/TransmissionAdapter.java
  39. 6
      lib/src/org/transdroid/daemon/Utorrent/UtorrentAdapter.java
  40. 273
      lib/src/org/transdroid/daemon/util/HttpHelper.java
  41. 103
      lite/AndroidManifest.xml

2
android/src/com/xirvik/transdroid/preferences/PreferencesXirvikServer.java

@ -230,7 +230,7 @@ public class PreferencesXirvikServer extends PreferenceActivity {
String url = "https://" + serverValue + ":443/browsers_addons/transdroid_autoconf.txt"; String url = "https://" + serverValue + ":443/browsers_addons/transdroid_autoconf.txt";
HttpResponse request = httpclient.execute(new HttpGet(url)); HttpResponse request = httpclient.execute(new HttpGet(url));
InputStream stream = request.getEntity().getContent(); InputStream stream = request.getEntity().getContent();
String folderVal = HttpHelper.ConvertStreamToString(stream).trim(); String folderVal = HttpHelper.convertStreamToString(stream).trim();
if (folderVal.startsWith("<?xml")) { if (folderVal.startsWith("<?xml")) {
folderVal = null; folderVal = null;
} }

2
android/src/org/transdroid/preferences/ImportExport.java

@ -33,7 +33,7 @@ public class ImportExport {
Editor editor = prefs.edit(); Editor editor = prefs.edit();
// Read the settings file // Read the settings file
String raw = HttpHelper.ConvertStreamToString(new FileInputStream(settingsFile)); String raw = HttpHelper.convertStreamToString(new FileInputStream(settingsFile));
JSONObject json = new JSONObject(raw); JSONObject json = new JSONObject(raw);
if (json.has("servers")) { if (json.has("servers")) {

2
android/src/org/transdroid/search/barcode/GoogleWebSearchBarcodeResolver.java

@ -53,7 +53,7 @@ public abstract class GoogleWebSearchBarcodeResolver extends AsyncTask<String,
HttpGet httpget = new HttpGet(callUrl); HttpGet httpget = new HttpGet(callUrl);
HttpResponse response = httpclient.execute(httpget); HttpResponse response = httpclient.execute(httpget);
InputStream instream = response.getEntity().getContent(); InputStream instream = response.getEntity().getContent();
String result = HttpHelper.ConvertStreamToString(instream); String result = HttpHelper.convertStreamToString(instream);
JSONArray results = new JSONObject(result).getJSONObject("responseData").getJSONArray("results"); JSONArray results = new JSONObject(result).getJSONObject("responseData").getJSONArray("results");
// We will combine and filter multiple results, if there are any // We will combine and filter multiple results, if there are any

2
android/src/org/transdroid/service/UpdateService.java

@ -134,7 +134,7 @@ public class UpdateService extends IntentService {
// Retrieve what is the latest released app version // Retrieve what is the latest released app version
HttpResponse request = httpclient.execute(new HttpGet(url)); HttpResponse request = httpclient.execute(new HttpGet(url));
InputStream stream = request.getEntity().getContent(); InputStream stream = request.getEntity().getContent();
String appVersion[] = HttpHelper.ConvertStreamToString(stream).split("\\|"); String appVersion[] = HttpHelper.convertStreamToString(stream).split("\\|");
stream.close(); stream.close();
return appVersion; return appVersion;

4
core/res/layout-w900dp/activity_rssfeeds.xml

@ -11,7 +11,7 @@
android:id="@+id/rssfeeds_list" android:id="@+id/rssfeeds_list"
android:layout_width="0dip" android:layout_width="0dip"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_weight="1" android:layout_weight="2"
class="org.transdroid.core.gui.rss.RssfeedsFragment_" class="org.transdroid.core.gui.rss.RssfeedsFragment_"
tools:layout="@layout/fragment_rssfeeds" /> tools:layout="@layout/fragment_rssfeeds" />
@ -19,7 +19,7 @@
android:id="@+id/rssitems_list" android:id="@+id/rssitems_list"
android:layout_width="0dip" android:layout_width="0dip"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_weight="1" android:layout_weight="3"
class="org.transdroid.core.gui.rss.RssitemsFragment_" class="org.transdroid.core.gui.rss.RssitemsFragment_"
tools:layout="@layout/fragment_rssitems" /> tools:layout="@layout/fragment_rssitems" />

2
core/res/layout/activity_rssitems.xml

@ -6,7 +6,7 @@
tools:context=".RssItemsActivity" > tools:context=".RssItemsActivity" >
<fragment <fragment
android:id="@+id/rssfitems_list" android:id="@+id/rssitems_list"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
class="org.transdroid.core.gui.rss.RssitemsFragment_" class="org.transdroid.core.gui.rss.RssitemsFragment_"

5
core/res/layout/fragment_rssitems.xml

@ -21,8 +21,7 @@
android:gravity="center" android:gravity="center"
android:maxWidth="400dip" android:maxWidth="400dip"
android:padding="@dimen/margin_default" android:padding="@dimen/margin_default"
android:text="@string/rss_empty" android:text="@string/rss_noselection"
android:textIsSelectable="false" android:textIsSelectable="false" />
android:visibility="gone" />
</FrameLayout> </FrameLayout>

6
core/res/layout/list_item_rssitem.xml

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<org.transdroid.core.gui.lists.RssitemStatusLayout xmlns:android="http://schemas.android.com/apk/res/android" <org.transdroid.core.gui.rss.RssitemStatusLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="?attr/selectable_background_transdroid" android:background="?attr/selectable_background_transdroid"
@ -14,7 +14,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:fontFamily="sans-serif-condensed" android:fontFamily="sans-serif-condensed"
android:textColor="?attr/text_bright" android:textColor="?attr/text_bright"
android:textIsSelectable="true" android:textIsSelectable="false"
android:textSize="@dimen/text_enlarged" /> android:textSize="@dimen/text_enlarged" />
<TextView <TextView
@ -26,4 +26,4 @@
android:textIsSelectable="false" android:textIsSelectable="false"
android:textSize="@dimen/text_small" /> android:textSize="@dimen/text_small" />
</org.transdroid.core.gui.lists.RssitemStatusLayout> </org.transdroid.core.gui.rss.RssitemStatusLayout>

6
core/res/menu/fragment_rssfeeds.xml

@ -1,5 +1,11 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android" > <menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/action_refresh"
android:icon="?attr/ic_action_refresh"
android:showAsAction="always"
android:title="@string/action_refresh"/>
<item <item
android:id="@+id/action_settings" android:id="@+id/action_settings"
android:title="@string/action_settings"/> android:title="@string/action_settings"/>

5
core/res/values/strings.xml

@ -121,7 +121,10 @@
<string name="rss_feeds">RSS feeds</string> <string name="rss_feeds">RSS feeds</string>
<string name="rss_nosettings">You have not defined any RSS feeds yet to monitor. Torrent-specific RSS feeds keep you up to date with new releases and you are notified of new items.</string> <string name="rss_nosettings">You have not defined any RSS feeds yet to monitor. Torrent-specific RSS feeds keep you up to date with new releases and you are notified of new items.</string>
<string name="rss_noselection">Select an RSS feed to view the new items</string>
<string name="rss_empty">The RSS feed is not available or it contains no items</string> <string name="rss_empty">The RSS feed is not available or it contains no items</string>
<string name="rss_notloaded">Sorry, please wait until the RSS feed is loaded</string>
<string name="rss_error">Sorry, this RSS feed could not be loaded at this time</string>
<plurals name="rss_itemsselected"> <plurals name="rss_itemsselected">
<item quantity="one">%1$d item selected</item> <item quantity="one">%1$d item selected</item>
<item quantity="other">%1$d items selected</item> <item quantity="other">%1$d items selected</item>
@ -140,6 +143,8 @@
<string name="pref_name_optional">Optional personal name</string> <string name="pref_name_optional">Optional personal name</string>
<string name="pref_searchurl">Direct search URL</string> <string name="pref_searchurl">Direct search URL</string>
<string name="pref_searchurl_info">%s will be replaced by the search query</string> <string name="pref_searchurl_info">%s will be replaced by the search query</string>
<string name="pref_cookies">Cookies</string>
<string name="pref_cookies_info">Optional; use the key1=value1;key2=value2 format</string>
<string name="pref_feedurl">Feed URL</string> <string name="pref_feedurl">Feed URL</string>
<string name="pref_reqauth">Requires authentication</string> <string name="pref_reqauth">Requires authentication</string>
<string name="pref_reqauth_info">Opens links in the webbrowser for user login</string> <string name="pref_reqauth_info">Opens links in the webbrowser for user login</string>

6
core/res/xml/pref_websearch.xml

@ -13,4 +13,10 @@
android:summary="@string/pref_searchurl_info" android:summary="@string/pref_searchurl_info"
android:inputType="textUri" /> android:inputType="textUri" />
<EditTextPreference
android:key="websearch_cookies"
android:title="@string/pref_cookies"
android:summary="@string/pref_cookies_info"
android:inputType="textUri" />
</PreferenceScreen> </PreferenceScreen>

2
core/src/org/transdroid/core/app/search/GoogleWebSearchBarcodeResolver.java

@ -44,7 +44,7 @@ public class GoogleWebSearchBarcodeResolver {
HttpGet httpget = new HttpGet(callUrl); HttpGet httpget = new HttpGet(callUrl);
HttpResponse response = httpclient.execute(httpget); HttpResponse response = httpclient.execute(httpget);
InputStream instream = response.getEntity().getContent(); InputStream instream = response.getEntity().getContent();
String result = HttpHelper.ConvertStreamToString(instream); String result = HttpHelper.convertStreamToString(instream);
JSONArray results = new JSONObject(result).getJSONObject("responseData").getJSONArray("results"); JSONArray results = new JSONObject(result).getJSONObject("responseData").getJSONArray("results");
// We will combine and filter multiple results, if there are any // We will combine and filter multiple results, if there are any

50
core/src/org/transdroid/core/app/settings/ApplicationSettings.java

@ -65,18 +65,28 @@ public class ApplicationSettings {
Daemon type = Daemon.fromCode(prefs.getString("server_type_" + order, null)); Daemon type = Daemon.fromCode(prefs.getString("server_type_" + order, null));
boolean ssl = prefs.getBoolean("server_sslenabled_" + order, false); boolean ssl = prefs.getBoolean("server_sslenabled_" + order, false);
String defaultPort = Integer.toString(Daemon.getDefaultPortNumber(type, ssl)); String defaultPort = Integer.toString(Daemon.getDefaultPortNumber(type, ssl));
return new ServerSetting(order, prefs.getString("server_name_" + order, null), type, prefs.getString( return new ServerSetting(order,
"server_address_" + order, null), prefs.getString("server_localaddress_" + order, null), prefs.getString("server_name_" + order, null), type,
prefs.getString("server_localnetwork_" + order, null), Integer.parseInt(prefs.getString("server_port_" prefs.getString("server_address_" + order, null),
+ order, defaultPort)), ssl, prefs.getBoolean("server_ssltrustall_" + order, false), prefs.getString("server_localaddress_" + order, null),
prefs.getString("server_ssltrustkey_" + order, null), prefs.getString("server_folder_" + order, null), prefs.getString("server_localnetwork_" + order, null),
prefs.getBoolean("server_useauth_" + order, true), prefs.getString("server_user_" + order, null), Integer.parseInt(prefs.getString("server_port_" + order, defaultPort)),
prefs.getString("server_pass_" + order, null), prefs.getString("server_extrapass_" + order, null), ssl,
OS.fromCode(prefs.getString("server_os_" + order, "type_linux")), prefs.getString("server_downloaddir_" prefs.getBoolean("server_ssltrustall_" + order, false),
+ order, null), prefs.getString("server_ftpurl_" + order, null), prefs.getString( prefs.getString("server_ssltrustkey_" + order, null),
"server_ftppass_" + order, null), Integer.parseInt(prefs.getString("server_timeout_" + order, prefs.getString("server_folder_" + order, null),
"8")), prefs.getBoolean("server_alarmfinished_" + order, true), prefs.getBoolean( prefs.getBoolean("server_useauth_" + order, true),
"server_alarmnew_" + order, false), false); prefs.getString("server_user_" + order, null),
prefs.getString("server_pass_" + order, null),
prefs.getString("server_extrapass_" + order, null),
OS.fromCode(prefs.getString("server_os_" + order, "type_linux")),
prefs.getString("server_downloaddir_" + order, null),
prefs.getString("server_ftpurl_" + order, null),
prefs.getString("server_ftppass_" + order, null),
Integer.parseInt(prefs.getString("server_timeout_" + order, "8")),
prefs.getBoolean("server_alarmfinished_" + order, true),
prefs.getBoolean("server_alarmnew_" + order, false),
false);
// @formatter:on // @formatter:on
} }
@ -219,8 +229,10 @@ public class ApplicationSettings {
*/ */
public WebsearchSetting getWebsearchSetting(int order) { public WebsearchSetting getWebsearchSetting(int order) {
// @formatter:off // @formatter:off
return new WebsearchSetting(order, prefs.getString("websearch_name_" + order, null), prefs.getString( return new WebsearchSetting(order,
"websearch_baseurl_" + order, null)); prefs.getString("websearch_name_" + order, null),
prefs.getString("websearch_baseurl_" + order, null),
prefs.getString("websearch_cookies_" + order, null));
// @formatter:on // @formatter:on
} }
@ -239,11 +251,13 @@ public class ApplicationSettings {
for (int i = order; i < max; i++) { for (int i = order; i < max; i++) {
edit.putString("websearch_name_" + i, prefs.getString("websearch_name_" + (i + 1), null)); edit.putString("websearch_name_" + i, prefs.getString("websearch_name_" + (i + 1), null));
edit.putString("websearch_baseurl_" + i, prefs.getString("websearch_baseurl_" + (i + 1), null)); edit.putString("websearch_baseurl_" + i, prefs.getString("websearch_baseurl_" + (i + 1), null));
edit.putString("websearch_cookies_" + i, prefs.getString("websearch_cookies_" + (i + 1), null));
} }
// Remove the last settings, of which we are now sure are no longer required // Remove the last settings, of which we are now sure are no longer required
edit.remove("websearch_name_" + max); edit.remove("websearch_name_" + max);
edit.remove("websearch_baseurl_" + max); edit.remove("websearch_baseurl_" + max);
edit.remove("websearch_cookies_" + max);
edit.commit(); edit.commit();
} }
@ -279,9 +293,11 @@ public class ApplicationSettings {
public RssfeedSetting getRssfeedSetting(int order) { public RssfeedSetting getRssfeedSetting(int order) {
// @formatter:off // @formatter:off
long lastViewed = prefs.getLong("rssfeed_lastviewed_" + order, -1); long lastViewed = prefs.getLong("rssfeed_lastviewed_" + order, -1);
return new RssfeedSetting(order, prefs.getString("rssfeed_name_" + order, null), prefs.getString("rssfeed_url_" return new RssfeedSetting(order,
+ order, null), prefs.getBoolean("rssfeed_reqauth_" + order, false), lastViewed == -1L ? null prefs.getString("rssfeed_name_" + order, null),
: new Date(lastViewed)); prefs.getString("rssfeed_url_" + order, null),
prefs.getBoolean("rssfeed_reqauth_" + order, false),
lastViewed == -1L ? null: new Date(lastViewed));
// @formatter:on // @formatter:on
} }

2
core/src/org/transdroid/core/app/settings/SettingsPersistence.java

@ -49,7 +49,7 @@ public class SettingsPersistence {
Editor editor = prefs.edit(); Editor editor = prefs.edit();
// Read the settings file // Read the settings file
String raw = HttpHelper.ConvertStreamToString(new FileInputStream(settingsFile)); String raw = HttpHelper.convertStreamToString(new FileInputStream(settingsFile));
JSONObject json = new JSONObject(raw); JSONObject json = new JSONObject(raw);
// Import servers // Import servers

8
core/src/org/transdroid/core/app/settings/WebsearchSetting.java

@ -17,11 +17,13 @@ public class WebsearchSetting implements SimpleListItem {
private final int order; private final int order;
private final String name; private final String name;
private final String baseUrl; private final String baseUrl;
private final String cookies;
public WebsearchSetting(int order, String name, String baseUrl) { public WebsearchSetting(int order, String name, String baseUrl, String cookies) {
this.order = order; this.order = order;
this.name = name; this.name = name;
this.baseUrl = baseUrl; this.baseUrl = baseUrl;
this.cookies = cookies;
} }
public int getOrder() { public int getOrder() {
@ -43,6 +45,10 @@ public class WebsearchSetting implements SimpleListItem {
return baseUrl; return baseUrl;
} }
public String getCookies() {
return cookies;
}
public String getKey() { public String getKey() {
return KEY_PREFIX + getOrder(); return KEY_PREFIX + getOrder();
} }

140
core/src/org/transdroid/core/gui/TorrentsActivity.java

@ -1,11 +1,14 @@
package org.transdroid.core.gui; package org.transdroid.core.gui;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.androidannotations.annotations.AfterViews; import org.androidannotations.annotations.AfterViews;
import org.androidannotations.annotations.Background; import org.androidannotations.annotations.Background;
@ -19,17 +22,33 @@ import org.androidannotations.annotations.OptionsMenu;
import org.androidannotations.annotations.SystemService; import org.androidannotations.annotations.SystemService;
import org.androidannotations.annotations.UiThread; import org.androidannotations.annotations.UiThread;
import org.androidannotations.annotations.ViewById; import org.androidannotations.annotations.ViewById;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.cookie.BasicClientCookie;
import org.transdroid.core.R; import org.transdroid.core.R;
import org.transdroid.core.app.settings.*; import org.transdroid.core.app.settings.ApplicationSettings;
import org.transdroid.core.app.settings.ServerSetting;
import org.transdroid.core.app.settings.SystemSettings_;
import org.transdroid.core.app.settings.WebsearchSetting;
import org.transdroid.core.gui.lists.LocalTorrent; import org.transdroid.core.gui.lists.LocalTorrent;
import org.transdroid.core.gui.lists.SimpleListItem; import org.transdroid.core.gui.lists.SimpleListItem;
import org.transdroid.core.gui.log.*; import org.transdroid.core.gui.log.Log;
import org.transdroid.core.gui.navigation.*; import org.transdroid.core.gui.log.Log_;
import org.transdroid.core.gui.rss.*; import org.transdroid.core.gui.navigation.FilterListAdapter;
import org.transdroid.core.gui.navigation.FilterListAdapter_;
import org.transdroid.core.gui.navigation.FilterListDropDownAdapter;
import org.transdroid.core.gui.navigation.FilterListDropDownAdapter_;
import org.transdroid.core.gui.navigation.Label;
import org.transdroid.core.gui.navigation.NavigationFilter;
import org.transdroid.core.gui.navigation.NavigationHelper;
import org.transdroid.core.gui.navigation.StatusType;
import org.transdroid.core.gui.rss.RssfeedsActivity_;
import org.transdroid.core.gui.search.BarcodeHelper; import org.transdroid.core.gui.search.BarcodeHelper;
import org.transdroid.core.gui.search.FilePickerHelper; import org.transdroid.core.gui.search.FilePickerHelper;
import org.transdroid.core.gui.search.UrlEntryDialog; import org.transdroid.core.gui.search.UrlEntryDialog;
import org.transdroid.core.gui.settings.*; import org.transdroid.core.gui.settings.MainSettingsActivity_;
import org.transdroid.daemon.Daemon; import org.transdroid.daemon.Daemon;
import org.transdroid.daemon.IDaemonAdapter; import org.transdroid.daemon.IDaemonAdapter;
import org.transdroid.daemon.Priority; import org.transdroid.daemon.Priority;
@ -62,6 +81,7 @@ import org.transdroid.daemon.task.SetTrackersTask;
import org.transdroid.daemon.task.StartTask; import org.transdroid.daemon.task.StartTask;
import org.transdroid.daemon.task.StopTask; import org.transdroid.daemon.task.StopTask;
import org.transdroid.daemon.util.DLog; import org.transdroid.daemon.util.DLog;
import org.transdroid.daemon.util.HttpHelper;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.app.SearchManager; import android.app.SearchManager;
@ -185,6 +205,7 @@ public class TorrentsActivity extends SherlockFragmentActivity implements OnNavi
// Handle any start up intents // Handle any start up intents
if (firstStart && getIntent() != null) { if (firstStart && getIntent() != null) {
currentConnection = lastUsed.createServerAdapter();
handleStartIntent(); handleStartIntent();
} }
@ -399,11 +420,32 @@ public class TorrentsActivity extends SherlockFragmentActivity implements OnNavi
// Adding a torrent from http or https URL // Adding a torrent from http or https URL
if (dataUri.getScheme().equals("http") || dataUri.getScheme().equals("https")) { if (dataUri.getScheme().equals("http") || dataUri.getScheme().equals("https")) {
String title = data.substring(data.lastIndexOf("/"));
if (intent.hasExtra("TORRENT_TITLE")) { // Check if the target URL is also defined as a web search in the user's settings
title = intent.getStringExtra("TORRENT_TITLE"); List<WebsearchSetting> websearches = applicationSettings.getWebsearchSettings();
WebsearchSetting match = null;
for (WebsearchSetting setting : websearches) {
Uri uri = Uri.parse(setting.getBaseUrl());
if (uri.getHost() != null && uri.getHost().equals(dataUri.getHost())) {
match = setting;
break;
}
}
// If the URL is also a web search and it defines cookies, use the cookies by downloading the targeted
// torrent file (while supplies the cookies to the HTTP request) instead of sending the URL directly to the
// torrent client
if (match != null && match.getCookies() != null) {
addTorrentFromWeb(data, match);
} else {
// Normally send the URL to the torrent client; the title we show is just the 'file name'
// TODO: Make a better effort in determining the title (check query string, clean special chars)
String title = data.substring(data.lastIndexOf("/") + 1);
if (intent.hasExtra("TORRENT_TITLE")) {
title = intent.getStringExtra("TORRENT_TITLE");
}
addTorrentByUrl(data, title);
} }
addTorrentByUrl(data, title);
return; return;
} }
@ -413,9 +455,9 @@ public class TorrentsActivity extends SherlockFragmentActivity implements OnNavi
return; return;
} }
// Adding a local .torrent file // Adding a local .torrent file; the title we show is just the file name
if (dataUri.getScheme().equals("file")) { if (dataUri.getScheme().equals("file")) {
String title = data.substring(data.lastIndexOf("/")); String title = data.substring(data.lastIndexOf("/") + 1);
addTorrentByFile(data, title); addTorrentByFile(data, title);
return; return;
} }
@ -638,13 +680,61 @@ public class TorrentsActivity extends SherlockFragmentActivity implements OnNavi
private void addTorrentFromDownloads(Uri contentUri) { private void addTorrentFromDownloads(Uri contentUri) {
InputStream input = null;
try { try {
// Open the content uri as input stream // Open the content uri as input stream and this via a local temporary file
input = getContentResolver().openInputStream(contentUri); addTorrentFromStream(getContentResolver().openInputStream(contentUri));
} catch (SecurityException e) {
// No longer access to this file
Log.e(this, "No access given to " + contentUri.toString() + ": " + e.toString());
Crouton.showText(this, R.string.error_torrentfile, NavigationHelper.CROUTON_ERROR_STYLE);
} catch (FileNotFoundException e) {
Log.e(this, contentUri.toString() + " does not exist: " + e.toString());
Crouton.showText(this, R.string.error_torrentfile, NavigationHelper.CROUTON_ERROR_STYLE);
}
}
@Background
protected void addTorrentFromWeb(String url, WebsearchSetting websearchSetting) {
try {
// Cookies are taken from the websearchSetting that we already matched against this target URL
DefaultHttpClient httpclient = HttpHelper.createStandardHttpClient(false, null, null, true, null, 10000,
null, -1);
Map<String, String> cookies = HttpHelper.parseCookiePairs(websearchSetting.getCookies());
String domain = Uri.parse(url).getHost();
for (Entry<String, String> pair : cookies.entrySet()) {
BasicClientCookie cookie = new BasicClientCookie(pair.getKey(), pair.getValue());
cookie.setPath("/");
cookie.setDomain(domain);
httpclient.getCookieStore().addCookie(cookie);
}
// Download the torrent at the specified URL (which will first be written to a temporary file)
// If we get an HTTP 401, 403 or 404 response, show an error to the user
HttpResponse response = httpclient.execute(new HttpGet(url));
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_UNAUTHORIZED
|| response.getStatusLine().getStatusCode() == HttpStatus.SC_FORBIDDEN
|| response.getStatusLine().getStatusCode() == HttpStatus.SC_NOT_FOUND) {
Log.e(this, "Can't retrieve web torrent " + url + ": Unexpected HTTP response status code "
+ response.getStatusLine().toString());
Crouton.showText(this, R.string.error_401, NavigationHelper.CROUTON_ERROR_STYLE);
return;
}
InputStream input = response.getEntity().getContent();
addTorrentFromStream(input);
} catch (Exception e) {
Log.e(this, "Can't retrieve web torrent " + url + ": " + e.toString());
Crouton.showText(this, R.string.error_torrentfile, NavigationHelper.CROUTON_ERROR_STYLE);
}
}
@Background
protected void addTorrentFromStream(InputStream input) {
File tempFile = new File("/not/yet/set");
try {
// Write a temporary file with the torrent contents // Write a temporary file with the torrent contents
File tempFile = File.createTempFile("transdroid_", ".torrent", getCacheDir()); tempFile = File.createTempFile("transdroid_", ".torrent", getCacheDir());
FileOutputStream output = new FileOutputStream(tempFile); FileOutputStream output = new FileOutputStream(tempFile);
try { try {
final byte[] buffer = new byte[1024]; final byte[] buffer = new byte[1024];
@ -657,17 +747,15 @@ public class TorrentsActivity extends SherlockFragmentActivity implements OnNavi
} finally { } finally {
output.close(); output.close();
} }
} catch (SecurityException e) { } catch (IOException e) {
// No longer access to this file Log.e(this, "Can't write input stream to " + tempFile.toString() + ": " + e.toString());
Crouton.showText(this, R.string.error_torrentfile, NavigationHelper.CROUTON_ERROR_STYLE);
} catch (IOException e1) {
// Can't write temporary file
Crouton.showText(this, R.string.error_torrentfile, NavigationHelper.CROUTON_ERROR_STYLE); Crouton.showText(this, R.string.error_torrentfile, NavigationHelper.CROUTON_ERROR_STYLE);
} finally { } finally {
try { try {
if (input != null) if (input != null)
input.close(); input.close();
} catch (IOException e) { } catch (IOException e) {
Log.e(this, "Error closing the input stream " + tempFile.toString() + ": " + e.toString());
Crouton.showText(this, R.string.error_torrentfile, NavigationHelper.CROUTON_ERROR_STYLE); Crouton.showText(this, R.string.error_torrentfile, NavigationHelper.CROUTON_ERROR_STYLE);
} }
} }
@ -725,7 +813,7 @@ public class TorrentsActivity extends SherlockFragmentActivity implements OnNavi
@Override @Override
public void removeTorrent(Torrent torrent, boolean withData) { public void removeTorrent(Torrent torrent, boolean withData) {
DaemonTaskResult result = RemoveTask.create(currentConnection, torrent, withData).execute(); DaemonTaskResult result = RemoveTask.create(currentConnection, torrent, withData).execute();
if (result instanceof DaemonTaskResult) { if (result instanceof DaemonTaskSuccessResult) {
onTaskSucceeded( onTaskSucceeded(
(DaemonTaskSuccessResult) result, (DaemonTaskSuccessResult) result,
getString(withData ? R.string.result_removed_with_data : R.string.result_removed, torrent.getName())); getString(withData ? R.string.result_removed_with_data : R.string.result_removed, torrent.getName()));
@ -799,16 +887,16 @@ public class TorrentsActivity extends SherlockFragmentActivity implements OnNavi
@UiThread @UiThread
protected void onTorrentsRetrieved(List<Torrent> torrents, List<org.transdroid.daemon.Label> labels) { protected void onTorrentsRetrieved(List<Torrent> torrents, List<org.transdroid.daemon.Label> labels) {
// Report the newly retrieved list of torrents to the torrents fragment // Report the newly retrieved list of torrents to the torrents fragment
fragmentTorrents.updateIsLoading(false); fragmentTorrents.updateIsLoading(false);
fragmentTorrents.updateTorrents(new ArrayList<Torrent>(torrents)); fragmentTorrents.updateTorrents(new ArrayList<Torrent>(torrents));
// Update the details fragment if the currently shown torrent is in the newly retrieved list // Update the details fragment if the currently shown torrent is in the newly retrieved list
if (fragmentDetails != null) { if (fragmentDetails != null) {
fragmentDetails.perhapsUpdateTorrent(torrents); fragmentDetails.perhapsUpdateTorrent(torrents);
} }
// Update local list of labels in the navigation // Update local list of labels in the navigation
List<Label> navigationLabels = Label.convertToNavigationLabels(labels, List<Label> navigationLabels = Label.convertToNavigationLabels(labels,
getResources().getString(R.string.labels_unlabeled)); getResources().getString(R.string.labels_unlabeled));
@ -819,10 +907,10 @@ public class TorrentsActivity extends SherlockFragmentActivity implements OnNavi
// Labels are shown in the action bar spinner // Labels are shown in the action bar spinner
navigationSpinnerAdapter.updateLabels(navigationLabels); navigationSpinnerAdapter.updateLabels(navigationLabels);
} }
// Update the server status (counts and speeds) in the action bar // Update the server status (counts and speeds) in the action bar
serverStatusView.update(torrents); serverStatusView.update(torrents);
} }
@UiThread @UiThread

2
core/src/org/transdroid/core/gui/rss/RssfeedLoader.java

@ -36,7 +36,7 @@ public class RssfeedLoader {
newCount++; newCount++;
item.setIsNew(true); item.setIsNew(true);
} else { } else {
item.setIsNew(true); item.setIsNew(false);
} }
} }
} }

3
core/src/org/transdroid/core/gui/rss/RssfeedView.java

@ -55,7 +55,8 @@ public class RssfeedView extends LinearLayout {
// Clear and then asynchronously load the RSS feed site' favicon // Clear and then asynchronously load the RSS feed site' favicon
// Uses the g.etfv.co service to resolve the favicon of any feed URL // Uses the g.etfv.co service to resolve the favicon of any feed URL
faviconImage.setImageDrawable(null); faviconImage.setImageDrawable(null);
navigationHelper.getImageCache().displayImage(String.format(GETFVO_URL, rssfeedLoader), faviconImage); navigationHelper.getImageCache().displayImage(String.format(GETFVO_URL, rssfeedLoader.getSetting().getUrl()),
faviconImage);
} }

77
core/src/org/transdroid/core/gui/rss/RssfeedsActivity.java

@ -1,11 +1,9 @@
package org.transdroid.core.gui.rss; package org.transdroid.core.gui.rss;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date;
import java.util.List; import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
import org.androidannotations.annotations.AfterViews; import org.androidannotations.annotations.AfterViews;
import org.androidannotations.annotations.Background; import org.androidannotations.annotations.Background;
import org.androidannotations.annotations.Bean; import org.androidannotations.annotations.Bean;
@ -16,10 +14,10 @@ import org.androidannotations.annotations.UiThread;
import org.transdroid.core.R; import org.transdroid.core.R;
import org.transdroid.core.app.settings.*; import org.transdroid.core.app.settings.*;
import org.transdroid.core.gui.*; import org.transdroid.core.gui.*;
import org.transdroid.core.gui.log.Log;
import org.transdroid.core.gui.navigation.NavigationHelper; import org.transdroid.core.gui.navigation.NavigationHelper;
import org.transdroid.core.rssparser.Channel; import org.transdroid.core.rssparser.Channel;
import org.transdroid.core.rssparser.RssParser; import org.transdroid.core.rssparser.RssParser;
import org.xml.sax.SAXException;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.content.Intent; import android.content.Intent;
@ -28,6 +26,8 @@ import android.os.Bundle;
import com.actionbarsherlock.app.SherlockFragmentActivity; import com.actionbarsherlock.app.SherlockFragmentActivity;
import de.keyboardsurfer.android.widget.crouton.Crouton;
@EActivity(resName = "activity_rssfeeds") @EActivity(resName = "activity_rssfeeds")
public class RssfeedsActivity extends SherlockFragmentActivity { public class RssfeedsActivity extends SherlockFragmentActivity {
@ -59,9 +59,22 @@ public class RssfeedsActivity extends SherlockFragmentActivity {
getSupportActionBar().setTitle(NavigationHelper.buildCondensedFontString(getString(R.string.rss_feeds))); getSupportActionBar().setTitle(NavigationHelper.buildCondensedFontString(getString(R.string.rss_feeds)));
} }
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@OptionsItem(android.R.id.home)
protected void navigateUp() {
TorrentsActivity_.intent(this).flags(Intent.FLAG_ACTIVITY_CLEAR_TOP).start();
}
@Override @Override
protected void onResume() { protected void onResume() {
super.onResume(); super.onResume();
refreshFeeds();
}
/**
* Reload the RSS feed settings and start loading all the feeds. To be called from contained fragments.
*/
public void refreshFeeds() {
loaders = new ArrayList<RssfeedLoader>(); loaders = new ArrayList<RssfeedLoader>();
// For each RSS feed setting the user created, start a loader that retrieved the RSS feed (via a background // For each RSS feed setting the user created, start a loader that retrieved the RSS feed (via a background
// thread) and, on success, determines the new items in the feed // thread) and, on success, determines the new items in the feed
@ -73,28 +86,21 @@ public class RssfeedsActivity extends SherlockFragmentActivity {
fragmentFeeds.update(loaders); fragmentFeeds.update(loaders);
} }
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@OptionsItem(android.R.id.home)
protected void navigateUp() {
TorrentsActivity_.intent(this).flags(Intent.FLAG_ACTIVITY_CLEAR_TOP).start();
}
/** /**
* Performs the loading of the RSS feed content and parsing of items, in a background thread. * Performs the loading of the RSS feed content and parsing of items, in a background thread.
* @param loader The RSS feed loader for which to retrieve the contents * @param loader The RSS feed loader for which to retrieve the contents
*/ */
@Background @Background
protected void loadRssfeed(RssfeedLoader loader) { protected void loadRssfeed(RssfeedLoader loader) {
RssParser parser = new RssParser(loader.getSetting().getUrl());
try { try {
// Load and parse the feed
RssParser parser = new RssParser(loader.getSetting().getUrl());
parser.parse(); parser.parse();
handleRssfeedResult(loader, parser.getChannel(), true); handleRssfeedResult(loader, parser.getChannel(), false);
} catch (ParserConfigurationException e) { } catch (Exception e) {
handleRssfeedResult(loader, null, true); // Catch any error that may occurred and register this failure
} catch (SAXException e) {
handleRssfeedResult(loader, null, true);
} catch (IOException e) {
handleRssfeedResult(loader, null, true); handleRssfeedResult(loader, null, true);
Log.i(this, "RSS feed " + loader.getSetting().getUrl() + " error: " + e.toString());
} }
} }
@ -113,15 +119,46 @@ public class RssfeedsActivity extends SherlockFragmentActivity {
} }
/** /**
* Opens an RSS feed in the dedicated fragment (if there was space in the UI) or a new {@link RssitemsActivity}. * Opens an RSS feed in the dedicated fragment (if there was space in the UI) or a new {@link RssitemsActivity}.
* Optionally this also registers in the user preferences that the feed was now viewed, so that in the future the
* new items can be properly marked.
* @param loader The RSS feed loader (with settings and the loaded content channel) to show * @param loader The RSS feed loader (with settings and the loaded content channel) to show
* @param markAsViewedNow True if the user settings should be updated to reflect this feed's last viewed date; false otherwise
*/ */
public void openRssfeed(RssfeedLoader loader) { public void openRssfeed(RssfeedLoader loader, boolean markAsViewedNow) {
// The RSS feed content was loaded and can now be shown in the dedicated fragment or a new activity
if (fragmentItems != null) { if (fragmentItems != null) {
fragmentItems.update(loader.getChannel());
// If desired, update the lastViewedDate of this feed in the user setting; this won't be loaded until the RSS
// feeds screen in opened again.
if (!loader.hasError() && loader.getChannel() != null && markAsViewedNow) {
applicationSettings.setRssfeedLastViewer(loader.getSetting().getOrder(), new Date());
}
fragmentItems.update(loader.getChannel(), loader.hasError());
} else { } else {
// Error message or not yet loaded? Show a toast message instead of opening the items activity
if (loader.hasError()) {
Crouton.showText(this, R.string.rss_error, NavigationHelper.CROUTON_INFO_STYLE);
return;
}
if (loader.getChannel() == null || loader.getChannel().getItems().size() == 0) {
Crouton.showText(this, R.string.rss_notloaded, NavigationHelper.CROUTON_INFO_STYLE);
return;
}
// If desired, update the lastViewedDate of this feed in the user setting; this won't be loaded until the RSS
// feeds screen in opened again
if (markAsViewedNow) {
applicationSettings.setRssfeedLastViewer(loader.getSetting().getOrder(), new Date());
}
RssitemsActivity_.intent(this).rssfeed(loader.getChannel()).start(); RssitemsActivity_.intent(this).rssfeed(loader.getChannel()).start();
} }
} }
} }

7
core/src/org/transdroid/core/gui/rss/RssfeedsFragment.java

@ -61,9 +61,14 @@ public class RssfeedsFragment extends SherlockFragment {
MainSettingsActivity_.intent(getActivity()).start(); MainSettingsActivity_.intent(getActivity()).start();
} }
@OptionsItem(resName = "action_refresh")
protected void refreshScreen() {
((RssfeedsActivity)getActivity()).refreshFeeds();
}
@ItemClick(resName = "rssfeeds_list") @ItemClick(resName = "rssfeeds_list")
protected void onFeedClicked(RssfeedLoader loader) { protected void onFeedClicked(RssfeedLoader loader) {
((RssfeedsActivity)getActivity()).openRssfeed(loader); ((RssfeedsActivity)getActivity()).openRssfeed(loader, true);
} }
/** /**

5
core/src/org/transdroid/core/gui/rss/RssitemView.java

@ -26,8 +26,9 @@ public class RssitemView extends RssitemStatusLayout {
public void bind(Item rssitem) { public void bind(Item rssitem) {
nameText.setText(rssitem.getTitle()); nameText.setText(rssitem.getTitle());
dateText.setText(DateUtils.getRelativeDateTimeString(getContext(), rssitem.getPubdate().getTime(), dateText.setText(rssitem.getPubdate() == null ? "" : DateUtils.getRelativeDateTimeString(getContext(), rssitem
DateUtils.SECOND_IN_MILLIS, DateUtils.WEEK_IN_MILLIS, DateUtils.FORMAT_ABBREV_MONTH)); .getPubdate().getTime(), DateUtils.SECOND_IN_MILLIS, DateUtils.WEEK_IN_MILLIS,
DateUtils.FORMAT_ABBREV_MONTH));
setIsNew(rssitem.isNew()); setIsNew(rssitem.isNew());
} }

4
core/src/org/transdroid/core/gui/rss/RssitemsActivity.java

@ -18,7 +18,7 @@ import android.os.Bundle;
import com.actionbarsherlock.app.SherlockFragmentActivity; import com.actionbarsherlock.app.SherlockFragmentActivity;
@EActivity(resName = "activity_rssfeeds") @EActivity(resName = "activity_rssitems")
public class RssitemsActivity extends SherlockFragmentActivity { public class RssitemsActivity extends SherlockFragmentActivity {
@Extra @Extra
@ -51,7 +51,7 @@ public class RssitemsActivity extends SherlockFragmentActivity {
getSupportActionBar().setTitle(NavigationHelper.buildCondensedFontString(rssfeed.getTitle())); getSupportActionBar().setTitle(NavigationHelper.buildCondensedFontString(rssfeed.getTitle()));
// Get the intent extras and show them to the already loaded fragment // Get the intent extras and show them to the already loaded fragment
fragmentItems.update(rssfeed); fragmentItems.update(rssfeed, false);
} }
@TargetApi(Build.VERSION_CODES.HONEYCOMB) @TargetApi(Build.VERSION_CODES.HONEYCOMB)

49
core/src/org/transdroid/core/gui/rss/RssitemsFragment.java

@ -15,6 +15,7 @@ import org.transdroid.core.rssparser.Channel;
import org.transdroid.core.rssparser.Item; import org.transdroid.core.rssparser.Item;
import android.content.Intent; import android.content.Intent;
import android.view.View;
import android.widget.TextView; import android.widget.TextView;
import com.actionbarsherlock.app.SherlockFragment; import com.actionbarsherlock.app.SherlockFragment;
@ -33,9 +34,11 @@ public class RssitemsFragment extends SherlockFragment {
@InstanceState @InstanceState
protected Channel rssfeed = null; protected Channel rssfeed = null;
@InstanceState
protected boolean hasError = false;
// Views // Views
@ViewById(resName = "rssfeeds_list") @ViewById(resName = "rssitems_list")
protected SherlockListView rssitemsList; protected SherlockListView rssitemsList;
@Bean @Bean
protected RssitemsAdapter rssitemsAdapter; protected RssitemsAdapter rssitemsAdapter;
@ -48,17 +51,34 @@ public class RssitemsFragment extends SherlockFragment {
// Set up the list adapter, which allows multi-select // Set up the list adapter, which allows multi-select
rssitemsList.setAdapter(rssitemsAdapter); rssitemsList.setAdapter(rssitemsAdapter);
rssitemsList.setMultiChoiceModeListener(onItemsSelected); rssitemsList.setMultiChoiceModeListener(onItemsSelected);
update(rssfeed); update(rssfeed, hasError);
} }
/** /**
* Update the shown RSS items in the list and the known last view date. This is automatically called when the * Update the shown RSS items in the list.
* fragment is instantiated by its build, but should be manually called if it was instantiated empty. * @param channel The loaded RSS content channel object
* @param rssfeed The RSS feed Channel object that was retrieved * @param hasError True if there were errors in loading the channel, in which case an error text is shown; false
* otherwise
*/ */
public void update(Channel rssfeed) { public void update(Channel channel, boolean hasError) {
rssitemsAdapter.update(rssfeed); rssitemsAdapter.update(channel);
rssitemsList.setVisibility(View.GONE);
emptyText.setVisibility(View.VISIBLE);
if (hasError) {
emptyText.setText(R.string.rss_error);
return;
}
if (channel == null) {
emptyText.setText(R.string.rss_noselection);
return;
}
if (channel.getItems().size() == 0) {
emptyText.setText(R.string.rss_empty);
return;
}
rssitemsList.setVisibility(View.VISIBLE);
emptyText.setVisibility(View.INVISIBLE);
} }
@ItemClick(resName = "rssitems_list") @ItemClick(resName = "rssitems_list")
@ -67,9 +87,9 @@ public class RssitemsFragment extends SherlockFragment {
} }
private MultiChoiceModeListenerCompat onItemsSelected = new MultiChoiceModeListenerCompat() { private MultiChoiceModeListenerCompat onItemsSelected = new MultiChoiceModeListenerCompat() {
SelectionManagerMode selectionManagerMode; SelectionManagerMode selectionManagerMode;
@Override @Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) { public boolean onCreateActionMode(ActionMode mode, Menu menu) {
// Show contextual action bar to add items in batch mode // Show contextual action bar to add items in batch mode
@ -90,8 +110,7 @@ public class RssitemsFragment extends SherlockFragment {
List<Item> checked = new ArrayList<Item>(); List<Item> checked = new ArrayList<Item>();
for (int i = 0; i < rssitemsList.getCheckedItemPositions().size(); i++) { for (int i = 0; i < rssitemsList.getCheckedItemPositions().size(); i++) {
if (rssitemsList.getCheckedItemPositions().valueAt(i)) if (rssitemsList.getCheckedItemPositions().valueAt(i))
checked.add(rssitemsAdapter.getItem( checked.add(rssitemsAdapter.getItem(rssitemsList.getCheckedItemPositions().keyAt(i)));
rssitemsList.getCheckedItemPositions().keyAt(i)));
} }
int itemId = item.getItemId(); int itemId = item.getItemId();
@ -102,8 +121,8 @@ public class RssitemsFragment extends SherlockFragment {
String[] urls = new String[checked.size()]; String[] urls = new String[checked.size()];
String[] titles = new String[checked.size()]; String[] titles = new String[checked.size()];
for (int i = 0; i < checked.size(); i++) { for (int i = 0; i < checked.size(); i++) {
urls[i] = checked.get(0).getTheLink(); urls[i] = checked.get(i).getTheLink();
titles[i] = checked.get(0).getTitle(); titles[i] = checked.get(i).getTitle();
} }
intent.putExtra("TORRENT_URLS", urls); intent.putExtra("TORRENT_URLS", urls);
intent.putExtra("TORRENT_TITLES", titles); intent.putExtra("TORRENT_TITLES", titles);

1
core/src/org/transdroid/core/gui/settings/WebsearchSettingsActivity.java

@ -30,6 +30,7 @@ public class WebsearchSettingsActivity extends KeyBoundPreferencesActivity {
init(R.xml.pref_websearch, ApplicationSettings_.getInstance_(this).getMaxWebsearch()); init(R.xml.pref_websearch, ApplicationSettings_.getInstance_(this).getMaxWebsearch());
initTextPreference("websearch_name"); initTextPreference("websearch_name");
initTextPreference("websearch_baseurl"); initTextPreference("websearch_baseurl");
initTextPreference("websearch_cookies");
} }

1
core/src/org/transdroid/core/rssparser/Channel.java

@ -137,6 +137,7 @@ public class Channel implements Parcelable {
}; };
private Channel(Parcel in) { private Channel(Parcel in) {
this();
id = in.readInt(); id = in.readInt();
title = in.readString(); title = in.readString();
link = in.readString(); link = in.readString();

6
core/src/org/transdroid/core/rssparser/HttpHelper.java

@ -110,7 +110,7 @@ public class HttpHelper {
* *
* Taken from http://senior.ceng.metu.edu.tr/2009/praeda/2009/01/11/a-simple-restful-client-at-android/ * Taken from http://senior.ceng.metu.edu.tr/2009/praeda/2009/01/11/a-simple-restful-client-at-android/
*/ */
public static String ConvertStreamToString(InputStream is, String encoding) throws UnsupportedEncodingException { public static String convertStreamToString(InputStream is, String encoding) throws UnsupportedEncodingException {
InputStreamReader isr; InputStreamReader isr;
if (encoding != null) { if (encoding != null) {
isr = new InputStreamReader(is, encoding); isr = new InputStreamReader(is, encoding);
@ -137,9 +137,9 @@ public class HttpHelper {
return sb.toString(); return sb.toString();
} }
public static String ConvertStreamToString(InputStream is) { public static String convertStreamToString(InputStream is) {
try { try {
return ConvertStreamToString(is, null); return convertStreamToString(is, null);
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
// Since this is going to use the default encoding, it is never going to crash on an UnsupportedEncodingException // Since this is going to use the default encoding, it is never going to crash on an UnsupportedEncodingException
e.printStackTrace(); e.printStackTrace();

3
core/src/org/transdroid/core/rssparser/Item.java

@ -117,8 +117,7 @@ public class Item implements Parcelable {
* @return A single link URI to be used * @return A single link URI to be used
*/ */
public Uri getTheLinkUri() { public Uri getTheLinkUri() {
// TODO Auto-generated method stub return Uri.parse(getTheLink());
return null;
} }
@Override @Override

112
full/AndroidManifest.xml

@ -44,20 +44,106 @@
<intent-filter> <intent-filter>
<action android:name="android.intent.action.SEARCH" /> <action android:name="android.intent.action.SEARCH" />
</intent-filter> </intent-filter>
<intent-filter>
<action android:name="org.transdroid.ADD_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:mimeType="application/x-bittorrent"
android:host="*"
android:scheme="http" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:pathPattern=".*\\.torrent"
android:host="*"
android:scheme="http" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:mimeType="application/x-bittorrent"
android:host="*"
android:scheme="https" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:pathPattern=".*\\.torrent"
android:host="*"
android:scheme="https" />
</intent-filter>
<intent-filter> <intent-filter>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="application/x-bittorrent" /> <category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http" android:mimeType="application/x-bittorrent" />
<data android:scheme="http" android:pathPattern=".*\\.torrent" /> <data
<data android:scheme="https" android:mimeType="application/x-bittorrent" /> android:mimeType="application/x-bittorrent"
<data android:scheme="https" android:pathPattern=".*\\.torrent" /> android:host="*"
<data android:scheme="file" android:mimeType="application/x-bittorrent" /> android:scheme="file" />
<data android:scheme="file" android:pathPattern=".*\\.torrent" /> </intent-filter>
<data android:scheme="content" android:mimeType="application/x-bittorrent" /> <intent-filter>
<data android:scheme="content" android:pathPattern=".*\\.torrent" /> <action android:name="android.intent.action.VIEW" />
<data android:scheme="magnet" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:pathPattern=".*\\.torrent"
android:host="*"
android:scheme="file" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:mimeType="application/x-bittorrent"
android:host="*"
android:scheme="content" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:pathPattern=".*\\.torrent"
android:host="*"
android:scheme="content" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="magnet" />
</intent-filter> </intent-filter>
<meta-data <meta-data
@ -115,7 +201,7 @@
android:name="org.transdroid.core.gui.rss.RssitemsActivity_" android:name="org.transdroid.core.gui.rss.RssitemsActivity_"
android:label="@string/rss_feeds" android:label="@string/rss_feeds"
android:theme="@style/TransdroidTheme" /> android:theme="@style/TransdroidTheme" />
<provider <provider
android:name="org.transdroid.core.gui.SearchHistoryProvider" android:name="org.transdroid.core.gui.SearchHistoryProvider"
android:authorities="org.transdroid.core.gui.SearchHistoryProvider" android:authorities="org.transdroid.core.gui.SearchHistoryProvider"

10
lib/src/org/transdroid/daemon/BitComet/BitCometAdapter.java

@ -253,7 +253,7 @@ public class BitCometAdapter implements IDaemonAdapter {
// Read HTTP response // Read HTTP response
java.io.InputStream instream = entity.getContent(); java.io.InputStream instream = entity.getContent();
String result = HttpHelper.ConvertStreamToString(instream); String result = HttpHelper.convertStreamToString(instream);
instream.close(); instream.close();
// Return raw result // Return raw result
@ -288,7 +288,7 @@ public class BitCometAdapter implements IDaemonAdapter {
// Read BitComet response // Read BitComet response
java.io.InputStream instream = entity.getContent(); java.io.InputStream instream = entity.getContent();
String result = HttpHelper.ConvertStreamToString(instream); String result = HttpHelper.convertStreamToString(instream);
instream.close(); instream.close();
int idx = result.indexOf("save_path' value='")+18; int idx = result.indexOf("save_path' value='")+18;
@ -307,7 +307,7 @@ public class BitCometAdapter implements IDaemonAdapter {
if (entity != null) { if (entity != null) {
// Check BitComet response // Check BitComet response
instream = entity.getContent(); instream = entity.getContent();
result = HttpHelper.ConvertStreamToString(instream); result = HttpHelper.convertStreamToString(instream);
instream.close(); instream.close();
if (result.indexOf("failed!") > 0) throw new Exception("Adding torrent file failed"); if (result.indexOf("failed!") > 0) throw new Exception("Adding torrent file failed");
} }
@ -340,7 +340,7 @@ public class BitCometAdapter implements IDaemonAdapter {
// Read BitComet response // Read BitComet response
java.io.InputStream instream = entity.getContent(); java.io.InputStream instream = entity.getContent();
String result = HttpHelper.ConvertStreamToString(instream); String result = HttpHelper.convertStreamToString(instream);
instream.close(); instream.close();
int idx = result.indexOf("save_path' value='")+18; int idx = result.indexOf("save_path' value='")+18;
@ -364,7 +364,7 @@ public class BitCometAdapter implements IDaemonAdapter {
if (entity != null) { if (entity != null) {
// Check BitComet response // Check BitComet response
instream = entity.getContent(); instream = entity.getContent();
result = HttpHelper.ConvertStreamToString(instream); result = HttpHelper.convertStreamToString(instream);
instream.close(); instream.close();
if (result.indexOf("failed!") > 0) { if (result.indexOf("failed!") > 0) {
throw new Exception("Adding URL failed"); throw new Exception("Adding URL failed");

2
lib/src/org/transdroid/daemon/Bitflu/BitfluAdapter.java

@ -155,7 +155,7 @@ public class BitfluAdapter implements IDaemonAdapter {
// Read JSON response // Read JSON response
InputStream instream = response.getEntity().getContent(); InputStream instream = response.getEntity().getContent();
String result = HttpHelper.ConvertStreamToString(instream); String result = HttpHelper.convertStreamToString(instream);
int httpstatus = response.getStatusLine().getStatusCode(); int httpstatus = response.getStatusLine().getStatusCode();
if(httpstatus != 200) { if(httpstatus != 200) {

2
lib/src/org/transdroid/daemon/BuffaloNas/BuffaloNasAdapter.java

@ -178,7 +178,7 @@ public class BuffaloNasAdapter implements IDaemonAdapter {
// Read JSON response // Read JSON response
java.io.InputStream instream = entity.getContent(); java.io.InputStream instream = entity.getContent();
String result = HttpHelper.ConvertStreamToString(instream); String result = HttpHelper.convertStreamToString(instream);
instream.close(); instream.close();
// Return raw result // Return raw result

2
lib/src/org/transdroid/daemon/DLinkRouterBT/DLinkRouterBTAdapter.java

@ -273,7 +273,7 @@ public class DLinkRouterBTAdapter implements IDaemonAdapter {
// Read JSON response // Read JSON response
java.io.InputStream instream = entity.getContent(); java.io.InputStream instream = entity.getContent();
String result = HttpHelper.ConvertStreamToString(instream); String result = HttpHelper.convertStreamToString(instream);
JSONObject json = new JSONObject(result); JSONObject json = new JSONObject(result);
instream.close(); instream.close();

6
lib/src/org/transdroid/daemon/Deluge/DelugeAdapter.java

@ -182,7 +182,7 @@ public class DelugeAdapter implements IDaemonAdapter {
// Read JSON response // Read JSON response
InputStream instream = response.getEntity().getContent(); InputStream instream = response.getEntity().getContent();
String result = HttpHelper.ConvertStreamToString(instream); String result = HttpHelper.convertStreamToString(instream);
// If the upload succeeded, add the torrent file on the server // If the upload succeeded, add the torrent file on the server
// For this we need the file name, which is now send as a JSON object like: // For this we need the file name, which is now send as a JSON object like:
@ -477,7 +477,7 @@ public class DelugeAdapter implements IDaemonAdapter {
// Still no session cookie? // Still no session cookie?
if (sessionCookie == null) { if (sessionCookie == null) {
// Set error message and cancel the action that was requested // Set error message and cancel the action that was requested
throw new DaemonException(ExceptionType.AuthenticationFailure, "Password error? Server time difference? No (valid) cookie in response and JSON was: " + HttpHelper.ConvertStreamToString(instream)); throw new DaemonException(ExceptionType.AuthenticationFailure, "Password error? Server time difference? No (valid) cookie in response and JSON was: " + HttpHelper.convertStreamToString(instream));
} }
} }
@ -509,7 +509,7 @@ public class DelugeAdapter implements IDaemonAdapter {
// Read JSON response // Read JSON response
InputStream instream = entity.getContent(); InputStream instream = entity.getContent();
String result = HttpHelper.ConvertStreamToString(instream); String result = HttpHelper.convertStreamToString(instream);
JSONObject json = new JSONObject(result); JSONObject json = new JSONObject(result);
instream.close(); instream.close();

6
lib/src/org/transdroid/daemon/Ktorrent/KtorrentAdapter.java

@ -293,7 +293,7 @@ public class KtorrentAdapter implements IDaemonAdapter {
HttpGet httpget = new HttpGet(buildWebUIUrl() + RPC_URL_CHALLENGE); HttpGet httpget = new HttpGet(buildWebUIUrl() + RPC_URL_CHALLENGE);
HttpResponse response = httpclient.execute(httpget); HttpResponse response = httpclient.execute(httpget);
InputStream instream = response.getEntity().getContent(); InputStream instream = response.getEntity().getContent();
String challengeString = HttpHelper.ConvertStreamToString(instream).replaceAll("\\<.*?>","").trim(); String challengeString = HttpHelper.convertStreamToString(instream).replaceAll("\\<.*?>","").trim();
instream.close(); instream.close();
// Challenge string should be something like TncpX3TB8uZ0h8eqztZ6 // Challenge string should be something like TncpX3TB8uZ0h8eqztZ6
if (challengeString == null || challengeString.length() != 20) { if (challengeString == null || challengeString.length() != 20) {
@ -358,7 +358,7 @@ public class KtorrentAdapter implements IDaemonAdapter {
// Read response (a successful action always returned '1') // Read response (a successful action always returned '1')
InputStream instream = response.getEntity().getContent(); InputStream instream = response.getEntity().getContent();
String result = HttpHelper.ConvertStreamToString(instream); String result = HttpHelper.convertStreamToString(instream);
instream.close(); instream.close();
if (result.contains(RPC_SUCCESS)) { if (result.contains(RPC_SUCCESS)) {
return true; return true;
@ -407,7 +407,7 @@ public class KtorrentAdapter implements IDaemonAdapter {
// Read response (a successful action always returned '1') // Read response (a successful action always returned '1')
InputStream instream = response.getEntity().getContent(); InputStream instream = response.getEntity().getContent();
String result = HttpHelper.ConvertStreamToString(instream); String result = HttpHelper.convertStreamToString(instream);
instream.close(); instream.close();
if (result.equals("")) { if (result.equals("")) {
return true; return true;

2
lib/src/org/transdroid/daemon/Qbittorrent/QbittorrentAdapter.java

@ -306,7 +306,7 @@ public class QbittorrentAdapter implements IDaemonAdapter {
// Read JSON response // Read JSON response
java.io.InputStream instream = entity.getContent(); java.io.InputStream instream = entity.getContent();
String result = HttpHelper.ConvertStreamToString(instream); String result = HttpHelper.convertStreamToString(instream);
instream.close(); instream.close();
//TLog.d(LOG_NAME, "Success: " + (result.length() > 300? result.substring(0, 300) + "... (" + result.length() + " chars)": result)); //TLog.d(LOG_NAME, "Success: " + (result.length() > 300? result.substring(0, 300) + "... (" + result.length() + " chars)": result));

2
lib/src/org/transdroid/daemon/Synology/SynologyAdapter.java

@ -427,7 +427,7 @@ public class SynologyAdapter implements IDaemonAdapter {
} }
// Read JSON response // Read JSON response
java.io.InputStream instream = entity.getContent(); java.io.InputStream instream = entity.getContent();
String result = HttpHelper.ConvertStreamToString(instream); String result = HttpHelper.convertStreamToString(instream);
JSONObject json; JSONObject json;
json = new JSONObject(result); json = new JSONObject(result);
instream.close(); instream.close();

4
lib/src/org/transdroid/daemon/Tfb4rt/Tfb4rtAdapter.java

@ -195,7 +195,7 @@ public class Tfb4rtAdapter implements IDaemonAdapter {
// Read response (a successful action always returned '1') // Read response (a successful action always returned '1')
InputStream instream = response.getEntity().getContent(); InputStream instream = response.getEntity().getContent();
String result = HttpHelper.ConvertStreamToString(instream); String result = HttpHelper.convertStreamToString(instream);
instream.close(); instream.close();
if (result.trim().equals("1")) { if (result.trim().equals("1")) {
return true; return true;
@ -232,7 +232,7 @@ public class Tfb4rtAdapter implements IDaemonAdapter {
// Read response (a successful action always returned '1') // Read response (a successful action always returned '1')
InputStream instream = response.getEntity().getContent(); InputStream instream = response.getEntity().getContent();
String result = HttpHelper.ConvertStreamToString(instream); String result = HttpHelper.convertStreamToString(instream);
instream.close(); instream.close();
if (result.equals("1")) { if (result.equals("1")) {
return true; return true;

12
lib/src/org/transdroid/daemon/Transmission/TransmissionAdapter.java

@ -396,17 +396,20 @@ public class TransmissionAdapter implements IDaemonAdapter {
} }
// Execute // Execute
DLog.d(LOG_NAME, "Execute " + data.getString("method") + " request to " + httppost.getURI().toString());
HttpResponse response = httpclient.execute(httppost); HttpResponse response = httpclient.execute(httppost);
// Authentication error? // Authentication error?
if (response.getStatusLine().getStatusCode() == 401) { if (response.getStatusLine().getStatusCode() == 401) {
throw new DaemonException(ExceptionType.AuthenticationFailure, "401 HTTP response (username or password incorrect)"); throw new DaemonException(ExceptionType.AuthenticationFailure,
"401 HTTP response (username or password incorrect)");
} }
// 409 error because of a session id? // 409 error because of a session id?
if (response.getStatusLine().getStatusCode() == 409) { if (response.getStatusLine().getStatusCode() == 409) {
// Retry post, but this time with the new session token that was encapsulated in the 409 response // Retry post, but this time with the new session token that was encapsulated in the 409 response
DLog.d(LOG_NAME, "Receive HTTP 409 with new session code; now try again for the actual request");
sessionToken = response.getFirstHeader(sessionHeader).getValue(); sessionToken = response.getFirstHeader(sessionHeader).getValue();
httppost.addHeader(sessionHeader, sessionToken); httppost.addHeader(sessionHeader, sessionToken);
response = httpclient.execute(httppost); response = httpclient.execute(httppost);
@ -418,12 +421,13 @@ public class TransmissionAdapter implements IDaemonAdapter {
// Read JSON response // Read JSON response
java.io.InputStream instream = entity.getContent(); java.io.InputStream instream = entity.getContent();
String result = HttpHelper.ConvertStreamToString(instream); String result = HttpHelper.convertStreamToString(instream);
DLog.d(LOG_NAME,
"Received content response starting with "
+ (result.length() > 100 ? result.substring(0, 100) + "..." : result));
JSONObject json = new JSONObject(result); JSONObject json = new JSONObject(result);
instream.close(); instream.close();
//TLog.d(LOG_NAME, "Success: " + (result.length() > 200? result.substring(0, 200) + "... (" + result.length() + " chars)": result));
// Return the JSON object // Return the JSON object
return json; return json;
} }

6
lib/src/org/transdroid/daemon/Utorrent/UtorrentAdapter.java

@ -302,7 +302,7 @@ public class UtorrentAdapter implements IDaemonAdapter {
// Read JSON response // Read JSON response
InputStream instream = response.getEntity().getContent(); InputStream instream = response.getEntity().getContent();
String result = HttpHelper.ConvertStreamToString(instream); String result = HttpHelper.convertStreamToString(instream);
if ((result.equals("") || result.trim().equals("invalid request"))) { if ((result.equals("") || result.trim().equals("invalid request"))) {
authtoken = null; authtoken = null;
throw new DaemonException(ExceptionType.AuthenticationFailure, "Response was '" + result.replace("\n", "") + "' instead of a proper JSON object (and we used auth token '" + authtoken + "')"); throw new DaemonException(ExceptionType.AuthenticationFailure, "Response was '" + result.replace("\n", "") + "' instead of a proper JSON object (and we used auth token '" + authtoken + "')");
@ -341,7 +341,7 @@ public class UtorrentAdapter implements IDaemonAdapter {
throw new DaemonException(ExceptionType.ConnectionError, "Not found (404); server doesn't exist or is inaccessible"); throw new DaemonException(ExceptionType.ConnectionError, "Not found (404); server doesn't exist or is inaccessible");
} }
InputStream instream = response.getEntity().getContent(); InputStream instream = response.getEntity().getContent();
String result = HttpHelper.ConvertStreamToString(instream); String result = HttpHelper.convertStreamToString(instream);
authtoken = result.replaceAll("\\<.*?>","").trim(); authtoken = result.replaceAll("\\<.*?>","").trim();
} }
@ -366,7 +366,7 @@ public class UtorrentAdapter implements IDaemonAdapter {
// Read JSON response // Read JSON response
InputStream instream = response.getEntity().getContent(); InputStream instream = response.getEntity().getContent();
String result = HttpHelper.ConvertStreamToString(instream); String result = HttpHelper.convertStreamToString(instream);
JSONObject json = new JSONObject(result); JSONObject json = new JSONObject(result);
instream.close(); instream.close();
return json; return json;

273
lib/src/org/transdroid/daemon/util/HttpHelper.java

@ -15,13 +15,16 @@
* along with Transdroid. If not, see <http://www.gnu.org/licenses/>. * along with Transdroid. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
package org.transdroid.daemon.util; package org.transdroid.daemon.util;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.GZIPInputStream; import java.util.zip.GZIPInputStream;
import org.apache.http.Header; import org.apache.http.Header;
@ -51,11 +54,11 @@ import org.transdroid.daemon.DaemonException;
import org.transdroid.daemon.DaemonException.ExceptionType; import org.transdroid.daemon.DaemonException.ExceptionType;
import org.transdroid.daemon.DaemonSettings; import org.transdroid.daemon.DaemonSettings;
import android.net.Uri;
/** /**
* Provides a set of general helper methods that can be used in web-based communication. * Provides a set of general helper methods that can be used in web-based communication.
*
* @author erickok * @author erickok
*
*/ */
public class HttpHelper { public class HttpHelper {
@ -64,43 +67,48 @@ public class HttpHelper {
public static final String SCHEME_HTTPS = "https"; public static final String SCHEME_HTTPS = "https";
public static final String SCHEME_MAGNET = "magnet"; public static final String SCHEME_MAGNET = "magnet";
public static final String SCHEME_FILE = "file"; public static final String SCHEME_FILE = "file";
/** /**
* The 'User-Agent' name to send to the server * The 'User-Agent' name to send to the server
*/ */
public static String userAgent = null; public static String userAgent = null;
/** /**
* Creates a standard Apache HttpClient that is thread safe, supports different * Creates a standard Apache HttpClient that is thread safe, supports different SSL auth methods and basic
* SSL auth methods and basic authentication * authentication
* @param settings The server settings to adhere * @param settings The server settings to adhere
* @return An HttpClient that should be stored locally and reused for every new request * @return An HttpClient that should be stored locally and reused for every new request
* @throws DaemonException Thrown when information (such as username/password) is missing * @throws DaemonException Thrown when information (such as username/password) is missing
*/ */
public static DefaultHttpClient createStandardHttpClient(DaemonSettings settings, boolean userBasicAuth) throws DaemonException { public static DefaultHttpClient createStandardHttpClient(DaemonSettings settings, boolean userBasicAuth)
return createStandardHttpClient(userBasicAuth && settings.shouldUseAuthentication(), settings.getUsername(), settings.getPassword(), settings.getSslTrustAll(), settings.getSslTrustKey(), settings.getTimeoutInMilliseconds(), settings.getAddress(), settings.getPort()); throws DaemonException {
return createStandardHttpClient(userBasicAuth && settings.shouldUseAuthentication(), settings.getUsername(),
settings.getPassword(), settings.getSslTrustAll(), settings.getSslTrustKey(),
settings.getTimeoutInMilliseconds(), settings.getAddress(), settings.getPort());
} }
/** /**
* Creates a standard Apache HttpClient that is thread safe, supports different * Creates a standard Apache HttpClient that is thread safe, supports different SSL auth methods and basic
* SSL auth methods and basic authentication * authentication
* @param sslTrustAll Whether to trust all SSL certificates * @param sslTrustAll Whether to trust all SSL certificates
* @param sslTrustkey A specific SSL key to accept exclusively * @param sslTrustkey A specific SSL key to accept exclusively
* @param timeout The connection timeout for all requests * @param timeout The connection timeout for all requests
* @param authAddress The authentication domain address * @param authAddress The authentication domain address
* @param authPort The authentication domain port number * @param authPort The authentication domain port number
* @return An HttpClient that should be stored locally and reused for every new request * @return An HttpClient that should be stored locally and reused for every new request
* @throws DaemonException Thrown when information (such as username/password) is missing * @throws DaemonException Thrown when information (such as username/password) is missing
*/ */
public static DefaultHttpClient createStandardHttpClient(boolean userBasicAuth, String username, String password, boolean sslTrustAll, String sslTrustkey, int timeout, String authAddress, int authPort) throws DaemonException { public static DefaultHttpClient createStandardHttpClient(boolean userBasicAuth, String username, String password,
boolean sslTrustAll, String sslTrustkey, int timeout, String authAddress, int authPort)
throws DaemonException {
// Register http and https sockets // Register http and https sockets
SchemeRegistry registry = new SchemeRegistry(); SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", new PlainSocketFactory(), 80)); registry.register(new Scheme("http", new PlainSocketFactory(), 80));
SocketFactory https_socket = sslTrustAll ? new FakeSocketFactory() SocketFactory https_socket = sslTrustAll ? new FakeSocketFactory()
: sslTrustkey != null ? new FakeSocketFactory(sslTrustkey) : SSLSocketFactory.getSocketFactory(); : sslTrustkey != null ? new FakeSocketFactory(sslTrustkey) : SSLSocketFactory.getSocketFactory();
registry.register(new Scheme("https", https_socket, 443)); registry.register(new Scheme("https", https_socket, 443));
// Standard parameters // Standard parameters
HttpParams httpparams = new BasicHttpParams(); HttpParams httpparams = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpparams, timeout); HttpConnectionParams.setConnectionTimeout(httpparams, timeout);
@ -108,124 +116,155 @@ public class HttpHelper {
if (userAgent != null) { if (userAgent != null) {
HttpProtocolParams.setUserAgent(httpparams, userAgent); HttpProtocolParams.setUserAgent(httpparams, userAgent);
} }
DefaultHttpClient httpclient = new DefaultHttpClient(new ThreadSafeClientConnManager(httpparams, registry), httpparams); DefaultHttpClient httpclient = new DefaultHttpClient(new ThreadSafeClientConnManager(httpparams, registry),
httpparams);
// Authentication credentials // Authentication credentials
if (userBasicAuth) { if (userBasicAuth) {
if (username == null || password == null) { if (username == null || password == null) {
throw new DaemonException(ExceptionType.AuthenticationFailure, "No username or password was provided while we hadauthentication enabled"); throw new DaemonException(ExceptionType.AuthenticationFailure,
"No username or password was provided while we hadauthentication enabled");
} }
httpclient.getCredentialsProvider().setCredentials( httpclient.getCredentialsProvider().setCredentials(
new AuthScope(authAddress, authPort, AuthScope.ANY_REALM), new AuthScope(authAddress, authPort, AuthScope.ANY_REALM),
new UsernamePasswordCredentials(username, password)); new UsernamePasswordCredentials(username, password));
} }
return httpclient; return httpclient;
} }
/** /**
* HTTP request interceptor to allow for GZip-encoded data transfer * HTTP request interceptor to allow for GZip-encoded data transfer
*/ */
public static HttpRequestInterceptor gzipRequestInterceptor = new HttpRequestInterceptor() { public static HttpRequestInterceptor gzipRequestInterceptor = new HttpRequestInterceptor() {
public void process(final HttpRequest request, final HttpContext context) throws HttpException, IOException { public void process(final HttpRequest request, final HttpContext context) throws HttpException, IOException {
if (!request.containsHeader("Accept-Encoding")) { if (!request.containsHeader("Accept-Encoding")) {
request.addHeader("Accept-Encoding", "gzip"); request.addHeader("Accept-Encoding", "gzip");
} }
} }
}; };
/** /**
* HTTP response interceptor that decodes GZipped data * HTTP response interceptor that decodes GZipped data
*/ */
public static HttpResponseInterceptor gzipResponseInterceptor = new HttpResponseInterceptor() { public static HttpResponseInterceptor gzipResponseInterceptor = new HttpResponseInterceptor() {
public void process(final HttpResponse response, final HttpContext context) throws HttpException, IOException { public void process(final HttpResponse response, final HttpContext context) throws HttpException, IOException {
HttpEntity entity = response.getEntity(); HttpEntity entity = response.getEntity();
Header ceheader = entity.getContentEncoding(); Header ceheader = entity.getContentEncoding();
if (ceheader != null) { if (ceheader != null) {
HeaderElement[] codecs = ceheader.getElements(); HeaderElement[] codecs = ceheader.getElements();
for (int i = 0; i < codecs.length; i++) { for (int i = 0; i < codecs.length; i++) {
if (codecs[i].getName().equalsIgnoreCase("gzip")) { if (codecs[i].getName().equalsIgnoreCase("gzip")) {
response.setEntity(new HttpHelper.GzipDecompressingEntity(response.getEntity())); response.setEntity(new HttpHelper.GzipDecompressingEntity(response.getEntity()));
return; return;
} }
} }
} }
} }
}; };
/** /**
* HTTP entity wrapper to decompress GZipped HTTP responses * HTTP entity wrapper to decompress GZipped HTTP responses
*/ */
private static class GzipDecompressingEntity extends HttpEntityWrapper { private static class GzipDecompressingEntity extends HttpEntityWrapper {
public GzipDecompressingEntity(final HttpEntity entity) { public GzipDecompressingEntity(final HttpEntity entity) {
super(entity); super(entity);
} }
@Override @Override
public InputStream getContent() throws IOException, IllegalStateException { public InputStream getContent() throws IOException, IllegalStateException {
// the wrapped entity's getContent() decides about repeatability // the wrapped entity's getContent() decides about repeatability
InputStream wrappedin = wrappedEntity.getContent(); InputStream wrappedin = wrappedEntity.getContent();
return new GZIPInputStream(wrappedin); return new GZIPInputStream(wrappedin);
} }
@Override @Override
public long getContentLength() { public long getContentLength() {
// length of ungzipped content is not known // length of ungzipped content is not known
return -1; return -1;
} }
}
/*
* To convert the InputStream to String we use the BufferedReader.readLine() method. We iterate until the
* BufferedReader return null which means there's no more data to read. Each line will appended to a StringBuilder
* and returned as String.
*
* Taken from http://senior.ceng.metu.edu.tr/2009/praeda/2009/01/11/a-simple-restful-client-at-android/
*/
public static String convertStreamToString(InputStream is, String encoding) throws UnsupportedEncodingException {
InputStreamReader isr;
if (encoding != null) {
isr = new InputStreamReader(is, encoding);
} else {
isr = new InputStreamReader(is);
}
BufferedReader reader = new BufferedReader(isr);
StringBuilder sb = new StringBuilder();
String line = null;
try {
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return sb.toString();
} }
/* public static String convertStreamToString(InputStream is) {
* To convert the InputStream to String we use the BufferedReader.readLine() try {
* method. We iterate until the BufferedReader return null which means return convertStreamToString(is, null);
* there's no more data to read. Each line will appended to a StringBuilder
* and returned as String.
*
* Taken from http://senior.ceng.metu.edu.tr/2009/praeda/2009/01/11/a-simple-restful-client-at-android/
*/
public static String ConvertStreamToString(InputStream is, String encoding) throws UnsupportedEncodingException {
InputStreamReader isr;
if (encoding != null) {
isr = new InputStreamReader(is, encoding);
} else {
isr = new InputStreamReader(is);
}
BufferedReader reader = new BufferedReader(isr);
StringBuilder sb = new StringBuilder();
String line = null;
try {
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return sb.toString();
}
public static String ConvertStreamToString(InputStream is) {
try {
return ConvertStreamToString(is, null);
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
// Since this is going to use the default encoding, it is never going to crash on an UnsupportedEncodingException // Since this is going to use the default encoding, it is never going to crash on an
// UnsupportedEncodingException
e.printStackTrace(); e.printStackTrace();
return null; return null;
} }
} }
/**
* Parses the individual parameters from a textual cookie representation-like string and returns them in an unsorted
* map. Inspired by Android's (API level 11+) getQueryParameterNames(Uri).
* @param raw A string of the form key1=value1;key2=value
* @return An unsorted, unmodifiable map of pairs of string keys and string values
*/
public static Map<String, String> parseCookiePairs(String raw) {
Map<String, String> pairs = new HashMap<String, String>();
int start = 0;
do {
int next = raw.indexOf(';', start);
int end = (next == -1) ? raw.length() : next;
int separator = raw.indexOf('=', start);
if (separator > end || separator == -1) {
separator = end;
}
String name = raw.substring(start, separator);
String value = raw.substring(separator + 1, end);
pairs.put(Uri.decode(name), Uri.decode(value));
start = end + 1;
} while (start < raw.length());
return Collections.unmodifiableMap(pairs);
}
} }

103
lite/AndroidManifest.xml

@ -23,12 +23,13 @@
<uses-feature <uses-feature
android:name="android.hardware.touchscreen" android:name="android.hardware.touchscreen"
android:required="false" /> android:required="false" />
<application <application
android:allowBackup="true" android:allowBackup="true"
android:icon="@drawable/ic_launcher" android:icon="@drawable/ic_launcher"
android:label="@string/system_name" android:label="@string/system_name"
android:theme="@style/Theme.Sherlock" > android:theme="@style/Theme.Sherlock"
android:hardwareAccelerated="true" >
<!-- Main activities --> <!-- Main activities -->
<activity <activity
@ -44,11 +45,104 @@
<intent-filter> <intent-filter>
<action android:name="android.intent.action.SEARCH" /> <action android:name="android.intent.action.SEARCH" />
</intent-filter> </intent-filter>
<intent-filter>
<action android:name="org.transdroid.ADD_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:mimeType="application/x-bittorrent"
android:scheme="http" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:pathPattern=".*\\.torrent"
android:scheme="http" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:mimeType="application/x-bittorrent"
android:scheme="https" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:pathPattern=".*\\.torrent"
android:scheme="https" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:mimeType="application/x-bittorrent"
android:scheme="file" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:pathPattern=".*\\.torrent"
android:scheme="file" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:mimeType="application/x-bittorrent"
android:scheme="content" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:pathPattern=".*\\.torrent"
android:scheme="content" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="magnet" />
</intent-filter>
</activity> </activity>
<activity <activity
android:name="org.transdroid.core.gui.DetailsActivity_" android:name="org.transdroid.core.gui.DetailsActivity_"
android:uiOptions="splitActionBarWhenNarrow" android:theme="@style/TransdroidTheme"
android:theme="@style/TransdroidTheme" > android:uiOptions="splitActionBarWhenNarrow" >
</activity> </activity>
<!-- Settings screens --> <!-- Settings screens -->
@ -59,7 +153,6 @@
<activity android:name="org.transdroid.core.gui.settings.NotificationSettingsActivity_" /> <activity android:name="org.transdroid.core.gui.settings.NotificationSettingsActivity_" />
<activity android:name="org.transdroid.core.gui.settings.SystemSettingsActivity_" /> <activity android:name="org.transdroid.core.gui.settings.SystemSettingsActivity_" />
<activity android:name="org.transdroid.core.gui.navigation.DialogHelper_" /> <activity android:name="org.transdroid.core.gui.navigation.DialogHelper_" />
</application> </application>
</manifest> </manifest>
Loading…
Cancel
Save